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: scriptnet.c,v 1.13 2008-10-17 15:57:43 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025 #include "egg_script_internal.h"
00026
00027 typedef struct script_net_info {
00028 struct script_net_info *prev, *next;
00029 int idx;
00030 script_callback_t *on_connect, *on_eof, *on_newclient;
00031 script_callback_t *on_read, *on_written;
00032 script_callback_t *on_delete;
00033 } script_net_info_t;
00034
00035
00036 static script_net_info_t *script_net_info_head = NULL;
00037
00038 static void script_net_info_add(script_net_info_t *info);
00039 static void script_net_info_remove(script_net_info_t *info);
00040
00041
00042 static int script_net_takeover(int idx);
00043 static int script_net_listen(script_var_t *retval, int port);
00044 static int script_net_open(const char *host, int port, int timeout);
00045 static int script_net_close(int idx);
00046 static int script_net_write(int idx, const char *text, int len);
00047 static int script_net_linemode(int nargs, int idx, int onoff);
00048 static int script_net_handler(int idx, const char *event, script_callback_t *handler);
00049 static int script_net_info(script_var_t *retval, int idx, char *what);
00050 static int script_net_throttle(int idx, int speedin, int speedout);
00051 static int script_net_throttle_set(void *client_data, int idx, int speed);
00052
00053
00054 static int on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00055 static int on_eof(void *client_data, int idx, int err, const char *errmsg);
00056 static int on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port);
00057 static int on_read(void *client_data, int idx, char *data, int len);
00058 static int on_written(void *client_data, int idx, int len, int remaining);
00059 static int on_delete(event_owner_t *owner, void *client_data);
00060
00061 static sockbuf_handler_t sock_handler = {
00062 "script",
00063 on_connect, on_eof, on_newclient,
00064 on_read, on_written
00065 };
00066
00067 event_owner_t socket_owner = {
00068 "script", NULL,
00069 NULL, NULL,
00070 on_delete
00071 };
00072
00073 void script_event_cleanup(egg_module_t *module) {
00074 script_net_info_t *i, *next;
00075
00076 for (i = script_net_info_head; i; i = next) {
00077 next = i->next;
00078 if (i->on_connect && i->on_connect->owner && i->on_connect->owner->module == module) {
00079 if (i->on_connect->owner->on_delete) i->on_connect->owner->on_delete(i->on_connect->owner, i->on_connect);
00080 i->on_connect = NULL;
00081 }
00082 if (i->on_eof && i->on_eof->owner && i->on_eof->owner->module == module) {
00083 if (i->on_eof->owner->on_delete) i->on_eof->owner->on_delete(i->on_eof->owner, i->on_eof);
00084 i->on_eof = NULL;
00085 }
00086 if (i->on_newclient && i->on_newclient->owner && i->on_newclient->owner->module == module) {
00087 if (i->on_newclient->owner->on_delete) i->on_newclient->owner->on_delete(i->on_newclient->owner, i->on_newclient);
00088 i->on_newclient = NULL;
00089 }
00090 if (i->on_read && i->on_read->owner && i->on_read->owner->module == module) {
00091 if (i->on_read->owner->on_delete) i->on_read->owner->on_delete(i->on_read->owner, i->on_read);
00092 i->on_read = NULL;
00093 }
00094 if (i->on_written && i->on_written->owner && i->on_written->owner->module == module) {
00095 if (i->on_written->owner->on_delete) i->on_written->owner->on_delete(i->on_written->owner, i->on_written);
00096 i->on_written = NULL;
00097 }
00098 if (i->on_delete && i->on_delete->owner && i->on_delete->owner->module == module) {
00099 if (i->on_delete->owner->on_delete) i->on_delete->owner->on_delete(i->on_delete->owner, i->on_delete);
00100 i->on_delete = NULL;
00101 }
00102 if (!i->on_connect && !i->on_eof && !i->on_newclient && !i->on_read && !i->on_written && !i->on_delete) sockbuf_delete(i->idx);
00103 }
00104 }
00105
00106
00107 static int script_net_takeover(int idx)
00108 {
00109 script_net_info_t *info;
00110
00111 info = calloc(1, sizeof(*info));
00112 info->idx = idx;
00113 script_net_info_add(info);
00114 sockbuf_set_handler(info->idx, &sock_handler, info, &socket_owner);
00115 return(0);
00116 }
00117
00118
00119 static script_net_info_t *script_net_info_lookup(int idx)
00120 {
00121 script_net_info_t *info;
00122
00123 for (info = script_net_info_head; info; info = info->next) {
00124 if (info->idx == idx) break;
00125 }
00126 return(info);
00127 }
00128
00129 static void script_net_info_add(script_net_info_t *info)
00130 {
00131 info->next = script_net_info_head;
00132 info->prev = NULL;
00133 if (script_net_info_head) script_net_info_head->prev = info;
00134 script_net_info_head = info;
00135 }
00136
00137 static void script_net_info_remove(script_net_info_t *info)
00138 {
00139 if (info->prev) info->prev->next = info->next;
00140 else script_net_info_head = info->next;
00141
00142 if (info->next) info->next->prev = info->prev;
00143 }
00144
00145
00146 static int script_net_listen(script_var_t *retval, int port)
00147 {
00148 int idx, real_port;
00149
00150 retval->type = SCRIPT_ARRAY | SCRIPT_FREE | SCRIPT_VAR;
00151 retval->len = 0;
00152
00153 idx = egg_listen(port, &real_port);
00154 script_net_takeover(idx);
00155 script_list_append(retval, script_int(idx));
00156 script_list_append(retval, script_int(real_port));
00157 return(0);
00158 }
00159
00160 static int script_net_open(const char *host, int port, int timeout)
00161 {
00162 int idx;
00163
00164 idx = egg_connect(host, port, timeout);
00165 script_net_takeover(idx);
00166 return(idx);
00167 }
00168
00169 static int script_net_close(int idx)
00170 {
00171 return sockbuf_delete(idx);
00172 }
00173
00174 static int script_net_write(int idx, const char *text, int len)
00175 {
00176 if (len <= 0) len = strlen(text);
00177
00178 return sockbuf_write(idx, text, len);
00179 }
00180
00181 static int script_net_linemode(int nargs, int idx, int onoff)
00182 {
00183 if (nargs == 1) return linemode_check(idx);
00184 if (onoff) return linemode_on(idx);
00185 else return linemode_off(idx);
00186 }
00187
00188 static int script_net_handler(int idx, const char *event, script_callback_t *callback)
00189 {
00190 script_net_info_t *info;
00191 script_callback_t **replace = NULL;
00192 const char *newsyntax;
00193
00194
00195 info = script_net_info_lookup(idx);
00196 if (!info) {
00197
00198 script_net_takeover(idx);
00199 info = script_net_info_lookup(idx);
00200 if (!info) return(-1);
00201 }
00202
00203 if (!strcasecmp(event, "connect")) {
00204 replace = &info->on_connect;
00205 newsyntax = "isi";
00206 }
00207 else if (!strcasecmp(event, "eof")) {
00208 replace = &info->on_eof;
00209 newsyntax = "iis";
00210 }
00211 else if (!strcasecmp(event, "newclient")) {
00212 replace = &info->on_newclient;
00213 newsyntax = "iisi";
00214 }
00215 else if (!strcasecmp(event, "read")) {
00216 replace = &info->on_read;
00217 newsyntax = "ibi";
00218 }
00219 else if (!strcasecmp(event, "written")) {
00220 replace = &info->on_written;
00221 newsyntax = "iii";
00222 }
00223 else if (!strcasecmp(event, "delete")) {
00224 replace = &info->on_delete;
00225 newsyntax = "i";
00226 }
00227 else {
00228
00229 return(-2);
00230 }
00231
00232 if (*replace && (*replace)->owner && (*replace)->owner->on_delete) (*replace)->owner->on_delete((*replace)->owner, *replace);
00233 if (callback) callback->syntax = strdup(newsyntax);
00234 *replace = callback;
00235 return(0);
00236 }
00237
00238 static int script_net_info(script_var_t *retval, int idx, char *what)
00239 {
00240 sockbuf_stats_t *stats = NULL;
00241
00242 sockbuf_get_stats(idx, &stats);
00243 retval->type = SCRIPT_INTEGER;
00244 if (!stats) return(0);
00245
00246 if (!strcasecmp(what, "all")) {
00247 retval->type = SCRIPT_ARRAY | SCRIPT_FREE | SCRIPT_VAR;
00248 retval->len = 0;
00249 script_list_append(retval, script_int(stats->connected_at.sec));
00250 script_list_append(retval, script_int(stats->last_input_at.sec));
00251 script_list_append(retval, script_int(stats->last_output_at.sec));
00252 script_list_append(retval, script_int(stats->raw_bytes_in));
00253 script_list_append(retval, script_int(stats->raw_bytes_out));
00254 script_list_append(retval, script_int(stats->raw_bytes_left));
00255 script_list_append(retval, script_int(stats->bytes_in));
00256 script_list_append(retval, script_int(stats->bytes_out));
00257 script_list_append(retval, script_int(stats->total_in_cps));
00258 script_list_append(retval, script_int(stats->snapshot_in_cps));
00259 script_list_append(retval, script_int(stats->total_out_cps));
00260 script_list_append(retval, script_int(stats->snapshot_out_cps));
00261 }
00262 else if (!strcasecmp(what, "raw_bytes_left")) retval->value = (void *)(int)stats->raw_bytes_left;
00263 else if (!strcasecmp(what, "raw_bytes_in")) retval->value = (void *)(int)stats->raw_bytes_in;
00264 else if (!strcasecmp(what, "raw_bytes_out")) retval->value = (void *)(int)stats->raw_bytes_out;
00265 return(0);
00266 }
00267
00268 static int script_net_throttle(int idx, int speedin, int speedout)
00269 {
00270 throttle_on(idx);
00271 if (speedin) throttle_set(idx, 0, speedin);
00272 if (speedout) throttle_set(idx, 1, speedout);
00273 return(0);
00274 }
00275
00276 static int script_net_throttle_set(void *client_data, int idx, int speed)
00277 {
00278 return throttle_set(idx, (int) client_data, speed);
00279 }
00280
00281
00282 static int on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
00283 {
00284 script_net_info_t *info = client_data;
00285
00286 if (info->on_connect) info->on_connect->callback(info->on_connect, idx, peer_ip, peer_port);
00287 return(0);
00288 }
00289
00290 static int on_eof(void *client_data, int idx, int err, const char *errmsg)
00291 {
00292 script_net_info_t *info = client_data;
00293
00294 if (info->on_eof) info->on_eof->callback(info->on_eof, idx, err, errmsg);
00295 sockbuf_delete(idx);
00296 return(0);
00297 }
00298
00299 static int on_newclient(void *client_data, int idx, int newidx, const char *peer_ip, int peer_port)
00300 {
00301 script_net_info_t *info = client_data;
00302
00303 if (info->on_newclient) info->on_newclient->callback(info->on_newclient, idx, newidx, peer_ip, peer_port);
00304 return(0);
00305 }
00306
00307 static int on_read(void *client_data, int idx, char *data, int len)
00308 {
00309 script_net_info_t *info = client_data;
00310 byte_array_t bytes;
00311
00312 if (info->on_read) {
00313 bytes.bytes = data;
00314 bytes.len = len;
00315 bytes.do_free = 0;
00316 info->on_read->callback(info->on_read, idx, &bytes, len);
00317 }
00318 return(0);
00319 }
00320
00321 static int on_written(void *client_data, int idx, int len, int remaining)
00322 {
00323 script_net_info_t *info = client_data;
00324
00325 if (info->on_written) info->on_written->callback(info->on_written, idx, len, remaining);
00326 return(0);
00327 }
00328
00329 static int on_delete(event_owner_t *owner, void *client_data)
00330 {
00331 script_net_info_t *info = client_data;
00332
00333 if (info->on_connect && info->on_connect->owner && info->on_connect->owner->on_delete) info->on_connect->owner->on_delete(info->on_connect->owner, info->on_connect);
00334 if (info->on_eof && info->on_eof->owner && info->on_eof->owner->on_delete) info->on_eof->owner->on_delete(info->on_eof->owner, info->on_eof);
00335 if (info->on_newclient && info->on_newclient->owner && info->on_newclient->owner->on_delete) info->on_newclient->owner->on_delete(info->on_newclient->owner, info->on_newclient);
00336 if (info->on_read && info->on_read->owner && info->on_read->owner->on_delete) info->on_read->owner->on_delete(info->on_read->owner, info->on_read);
00337 if (info->on_written && info->on_written->owner && info->on_written->owner->on_delete) info->on_written->owner->on_delete(info->on_written->owner, info->on_written);
00338
00339 if (info->on_delete) {
00340 info->on_delete->callback(info->on_delete, info->idx);
00341 if (info->on_delete && info->on_delete->owner && info->on_delete->owner->on_delete) info->on_delete->owner->on_delete(info->on_delete->owner, info->on_delete);
00342 }
00343 script_net_info_remove(info);
00344 free(info);
00345 return(0);
00346 }
00347
00348 script_command_t script_net_cmds[] = {
00349 {"net", "takeover", script_net_takeover, NULL, 1, "i", "idx", SCRIPT_INTEGER, 0},
00350 {"net", "listen", script_net_listen, NULL, 1, "i", "port", 0, SCRIPT_PASS_RETVAL},
00351 {"net", "open", script_net_open, NULL, 2, "sii", "host port ?timeout?", SCRIPT_INTEGER, SCRIPT_VAR_ARGS},
00352 {"net", "close", script_net_close, NULL, 1, "i", "idx", SCRIPT_INTEGER, 0},
00353 {"net", "write", script_net_write, NULL, 2, "isi", "idx text ?len?", SCRIPT_INTEGER, SCRIPT_VAR_ARGS},
00354 {"net", "handler", script_net_handler, NULL, 2, "isc", "idx event callback", SCRIPT_INTEGER, SCRIPT_VAR_ARGS},
00355 {"net", "linemode", script_net_linemode, NULL, 1, "ii", "idx ?on-off?", SCRIPT_INTEGER, SCRIPT_PASS_COUNT | SCRIPT_VAR_ARGS},
00356 {"net", "info", script_net_info, NULL, 2, "is", "idx what", 0, SCRIPT_PASS_RETVAL},
00357 {"net", "throttle", script_net_throttle, NULL, 3, "iii", "idx speed-in speed-out", SCRIPT_INTEGER, 0},
00358 {"net", "throttle_in", script_net_throttle_set, (void *)0, 2, "ii", "idx speed", SCRIPT_INTEGER, SCRIPT_PASS_CDATA},
00359 {"net", "throttle_out", script_net_throttle_set, (void *)1, 2, "ii", "idx speed", SCRIPT_INTEGER, SCRIPT_PASS_CDATA},
00360 {"net", "throttle_off", throttle_off, NULL, 1, "i", "idx", SCRIPT_INTEGER, 0},
00361 {0}
00362 };