00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: net.c,v 1.7 2006-09-12 01:50:50 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #define EGGNET_LEVEL (SOCKBUF_LEVEL_INTERNAL+1)
00027
00028 typedef struct connect_info {
00029 int dns_id;
00030 int timer_id;
00031 int idx;
00032 int port;
00033 } connect_info_t;
00034
00035 static int connect_host_resolved(void *client_data, const char *host, char **ips);
00036 static int egg_connect_timeout(void *client_data);
00037 static int egg_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00038 static int egg_on_eof(void *client_data, int idx, int err, const char *errmsg);
00039 static int egg_on_delete(void *client_data, int idx);
00040 static connect_info_t *attach(int idx, const char *host, int port, int timeout);
00041 static int detach(void *client_data, int idx);
00042
00043 static sockbuf_filter_t net_connect_filter = {
00044 "connect", EGGNET_LEVEL,
00045 egg_on_connect, egg_on_eof, NULL,
00046 NULL, NULL, NULL,
00047 NULL, egg_on_delete
00048 };
00049
00050 static char *default_proxy_name = NULL;
00051 static int default_timeout = 30;
00052
00053 int egg_net_init(void)
00054 {
00055 if (egg_dns_init() != 0)
00056 return (-1);
00057 return sockbuf_init();
00058 }
00059
00060 int egg_net_shutdown(void)
00061 {
00062 if (egg_dns_shutdown() != 0)
00063 ;
00064 return sockbuf_shutdown();
00065 }
00066
00067
00068 int egg_iprintf(int idx, const char *format, ...)
00069 {
00070 char *ptr, buf[1024];
00071 int len;
00072 va_list args;
00073
00074 va_start(args, format);
00075 ptr = egg_mvsprintf(buf, sizeof(buf), &len, format, args);
00076 va_end(args);
00077 sockbuf_write(idx, ptr, len);
00078 if (ptr != buf) free(ptr);
00079 return(len);
00080 }
00081
00082
00083 int egg_server(const char *vip, int port, int *real_port)
00084 {
00085 int idx, sock, ntries;
00086
00087 ntries = 0;
00088 do {
00089 sock = socket_create(NULL, 0, vip, port+ntries, SOCKET_SERVER|SOCKET_TCP|SOCKET_NONBLOCK);
00090 ntries++;
00091 } while (sock < 0 && ntries < 20 && port);
00092
00093 if (sock < 0) return(sock);
00094
00095 if (real_port) socket_get_name(sock, NULL, real_port);
00096
00097 idx = sockbuf_new();
00098 sockbuf_set_sock(idx, sock, SOCKBUF_SERVER);
00099
00100 return(idx);
00101 }
00102
00103
00104
00105
00106 int egg_client(int idx, const char *host, int port, const char *vip, int vport, int timeout)
00107 {
00108 connect_info_t *connect_info;
00109
00110
00111 if (idx < 0) idx = sockbuf_new();
00112
00113
00114 connect_info = attach(idx, host, port, timeout);
00115 connect_info->dns_id = egg_dns_lookup(host, -1, connect_host_resolved, connect_info, NULL);
00116 return(idx);
00117 }
00118
00119
00120
00121 int egg_listen(int port, int *real_port)
00122 {
00123 int idx;
00124
00125
00126 idx = egg_server(NULL, port, real_port);
00127 return(idx);
00128 }
00129
00130
00131
00132 int egg_reconnect(int idx, const char *host, int port, int timeout)
00133 {
00134 egg_proxy_t *proxy;
00135
00136 if (!default_proxy_name) return egg_client(idx, host, port, NULL, 0, timeout);
00137
00138
00139
00140 proxy = egg_proxy_lookup(default_proxy_name);
00141 if (!proxy) {
00142 putlog(LOG_MISC, "*", "Proxy '%s' selected but not loaded!", default_proxy_name);
00143 putlog(LOG_MISC, "*", "Trying to connect without proxy.");
00144 return egg_client(idx, host, port, NULL, 0, timeout);
00145 }
00146
00147
00148
00149
00150 if (timeout > 0) attach(idx, host, port, timeout);
00151 proxy->reconnect(idx, host, port);
00152 return(0);
00153 }
00154
00155 int egg_connect(const char *host, int port, int timeout)
00156 {
00157 int idx;
00158
00159 idx = sockbuf_new();
00160 egg_reconnect(idx, host, port, timeout);
00161 return(idx);
00162 }
00163
00164
00165
00166 static int connect_host_resolved(void *client_data, const char *host, char **ips)
00167 {
00168 connect_info_t *connect_info = client_data;
00169 int sock, idx;
00170
00171 connect_info->dns_id = -1;
00172
00173 if (!ips || !ips[0]) {
00174 idx = connect_info->idx;
00175 detach(client_data, idx);
00176 sockbuf_on_eof(idx, EGGNET_LEVEL, -1, "Could not resolve host");
00177 return(0);
00178 }
00179
00180 sock = socket_create(ips[0], connect_info->port, NULL, 0, SOCKET_CLIENT|SOCKET_TCP|SOCKET_NONBLOCK);
00181 if (sock < 0) {
00182 idx = connect_info->idx;
00183 detach(client_data, idx);
00184 sockbuf_on_eof(idx, EGGNET_LEVEL, -1, "Could not create socket");
00185 return(0);
00186 }
00187
00188
00189
00190
00191 sockbuf_set_sock(connect_info->idx, sock, SOCKBUF_CLIENT|SOCKBUF_CONNECTING);
00192 return(0);
00193 }
00194
00195
00196 static int egg_connect_timeout(void *client_data)
00197 {
00198 connect_info_t *connect_info = client_data;
00199 int idx, dns_id;
00200
00201 idx = connect_info->idx;
00202 dns_id = connect_info->dns_id;
00203 connect_info->timer_id = -1;
00204 if (dns_id != -1) {
00205
00206
00207 egg_dns_cancel(dns_id, 1);
00208 }
00209 else {
00210 detach(client_data, idx);
00211 sockbuf_on_eof(idx, EGGNET_LEVEL, -1, "Connect timed out");
00212 }
00213 return(0);
00214 }
00215
00216
00217 static int egg_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
00218 {
00219 detach(client_data, idx);
00220 sockbuf_on_connect(idx, EGGNET_LEVEL, peer_ip, peer_port);
00221 return(0);
00222 }
00223
00224 static int egg_on_eof(void *client_data, int idx, int err, const char *errmsg)
00225 {
00226 detach(client_data, idx);
00227 return sockbuf_on_eof(idx, EGGNET_LEVEL, err, errmsg);
00228 }
00229
00230 static int egg_on_delete(void *client_data, int idx)
00231 {
00232 connect_info_t *connect_info = client_data;
00233
00234 if (connect_info->dns_id != -1) egg_dns_cancel(connect_info->dns_id, 0);
00235 if (connect_info->timer_id != -1) timer_destroy(connect_info->timer_id);
00236 free(connect_info);
00237 return(0);
00238 }
00239
00240 static connect_info_t *attach(int idx, const char *host, int port, int timeout)
00241 {
00242 connect_info_t *connect_info = calloc(1, sizeof(*connect_info));
00243
00244 connect_info->port = port;
00245 connect_info->idx = idx;
00246 connect_info->dns_id = -1;
00247 connect_info->timer_id = -1;
00248 sockbuf_attach_filter(connect_info->idx, &net_connect_filter, connect_info);
00249 if (timeout == 0) timeout = default_timeout;
00250 if (timeout > 0) {
00251 char buf[128];
00252 egg_timeval_t howlong;
00253
00254 snprintf(buf, sizeof(buf), "idx %d to %s/%d", idx, host, port);
00255 howlong.sec = timeout;
00256 howlong.usec = 0;
00257 connect_info->timer_id = timer_create_complex(&howlong, buf, egg_connect_timeout, connect_info, 0, NULL);
00258 }
00259 return(connect_info);
00260 }
00261
00262 static int detach(void *client_data, int idx)
00263 {
00264 connect_info_t *connect_info = client_data;
00265
00266 if (connect_info->timer_id != -1) timer_destroy(connect_info->timer_id);
00267 sockbuf_detach_filter(idx, &net_connect_filter, NULL);
00268 free(connect_info);
00269 return(0);
00270 }
00271
00272
00273
00274
00275
00276
00277 static egg_proxy_t **proxies = NULL;
00278 static int nproxies = 0;
00279
00280 int egg_proxy_add(egg_proxy_t *proxy)
00281 {
00282 proxies = realloc(proxies, (nproxies+1) * sizeof(*proxies));
00283 proxies[nproxies++] = proxy;
00284 return(0);
00285 }
00286
00287 int egg_proxy_del(egg_proxy_t *proxy)
00288 {
00289 int i;
00290
00291 for (i = 0; i < nproxies; i++) {
00292 if (proxies[i] == proxy) break;
00293 }
00294 if (i == nproxies) return(-1);
00295 memmove(proxies+i, proxies+i+1, (nproxies-i-1) * sizeof(*proxies));
00296 nproxies--;
00297 return(0);
00298 }
00299
00300 egg_proxy_t *egg_proxy_lookup(const char *name)
00301 {
00302 int i;
00303
00304 for (i = 0; i < nproxies; i++) {
00305 if (proxies[i]->name && !strcasecmp(proxies[i]->name, name)) return(proxies[i]);
00306 }
00307 return(NULL);
00308 }
00309
00310 int egg_proxy_set_default(const char *name)
00311 {
00312 str_redup(&default_proxy_name, name);
00313 return(0);
00314 }
00315
00316 const char *egg_proxy_get_default()
00317 {
00318 return(default_proxy_name);
00319 }