/* input function: DCC SERVER received some data.. */ static void dcc_server_input(SERVER_DCC_REC *dcc) { char tmpbuf[512], *str; int recvlen, ret; g_return_if_fail(IS_DCC_SERVER(dcc)); do { recvlen = net_receive(dcc->handle, tmpbuf, sizeof(tmpbuf)); ret = line_split(tmpbuf, recvlen, &str, &dcc->readbuf); if (ret == -1) { /* connection lost */ dcc_close(DCC(dcc)); break; } if (ret > 0) { dcc->transfd += ret; signal_emit("dcc server message", 2, dcc, str); } if (dcc->connection_established) { /* We set handle to NULL first because the new (chat/get) is using the same */ /* handle and we don't want dcc_close to disconnect it.*/ dcc->handle = NULL; dcc_close(DCC(dcc)); break; } } while (ret > 0); }
/* input function: DCC SERVER - someone tried to connect to our socket */ static void dcc_server_listen(SERVER_DCC_REC *dcc) { SERVER_DCC_REC *newdcc; IPADDR ip; GIOChannel *handle; int port; g_return_if_fail(IS_DCC_SERVER(dcc)); /* accept connection */ handle = net_accept(dcc->handle, &ip, &port); if (handle == NULL) return; /* Create a new DCC SERVER to handle this connection */ newdcc = dcc_server_clone(dcc); newdcc->starttime = time(NULL); newdcc->handle = handle; newdcc->sendbuf = net_sendbuffer_create(handle, 0); memcpy(&newdcc->addr, &ip, sizeof(IPADDR)); net_ip2host(&newdcc->addr, newdcc->addrstr); newdcc->port = port; newdcc->tagread = g_input_add(handle, G_INPUT_READ, (GInputFunction) dcc_server_input, newdcc); signal_emit("dcc connected", 1, newdcc); }
static void sig_dcc_destroyed(SERVER_DCC_REC *dcc) { if (!IS_DCC_SERVER(dcc)) return; if (dcc->sendbuf != NULL) net_sendbuffer_destroy(dcc->sendbuf, FALSE); }
static void dcc_server_started(SERVER_DCC_REC *dcc) { if (!IS_DCC_SERVER(dcc)) { return; } printformat(dcc->server, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SERVER_STARTED, dcc->port); }
static void dcc_closed(SERVER_DCC_REC *dcc) { /* We don't want to print a msg if its just starting a chat/get */ /* and getting rid of the leftover SERVER_DCC_REC */ if (!IS_DCC_SERVER(dcc) || dcc->connection_established) { return; } printformat(dcc->server, NULL, MSGLEVEL_DCC, IRCTXT_DCC_SERVER_CLOSED, dcc->port); }
static void sig_dcc_list_print(SERVER_DCC_REC *dcc) { /* We don't want to print a msg if its just starting a chat/get */ /* and getting rid of the leftover SERVER_DCC_REC */ if (!IS_DCC_SERVER(dcc) || dcc->connection_established) { return; } /* SERVER: Port(59) - Send(on) - Chat(on) - Fserve(on) */ printformat(NULL, NULL, MSGLEVEL_DCC, IRCTXT_DCC_LIST_LINE_SERVER, "SERVER", dcc->port, dcc->accept_send ? "on" : "off", dcc->accept_chat ? "on" : "off", dcc->accept_fserve ? "on" : "off"); }
static SERVER_DCC_REC *dcc_server_clone(SERVER_DCC_REC *dcc) { SERVER_DCC_REC *newdcc; g_return_val_if_fail(IS_DCC_SERVER(dcc), NULL); newdcc = g_new0(SERVER_DCC_REC, 1); newdcc->orig_type = newdcc->type = DCC_SERVER_TYPE; newdcc->accept_send = dcc->accept_send; newdcc->accept_chat = dcc->accept_chat; newdcc->accept_fserve = dcc->accept_fserve; dcc_init_server_rec(newdcc, dcc->server, dcc->mynick, dcc->servertag); return newdcc; }
static void dcc_server_update_flags(SERVER_DCC_REC *dcc, const char *flags) { g_return_if_fail(dcc != NULL); g_return_if_fail(IS_DCC_SERVER(dcc)); if (*flags == '+' || *flags == '-') { const char *ptr = flags + 1; unsigned int value = (*flags == '+') ? 1 : 0; while (*ptr) { if (*ptr == 's' || *ptr == 'S') { dcc->accept_send = value; } else if (*ptr == 'c' || *ptr == 'C') { dcc->accept_chat = value; } else if (*ptr == 'f' || *ptr == 'F') { dcc->accept_fserve = value; } ptr++; } } }
SERVER_DCC_REC *dcc_server_find_port(const char *port_str) { GSList *tmp; unsigned int port = 0; g_return_val_if_fail(port_str != NULL, NULL); port = atoi(port_str); for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { SERVER_DCC_REC *dcc = tmp->data; if (IS_DCC_SERVER(dcc) && dcc->port == port) return dcc; } return NULL; }
/* Initialize DCC record */ static void dcc_init_server_rec(SERVER_DCC_REC *dcc, IRC_SERVER_REC *server, const char *mynick, const char *servertag) { g_return_if_fail(dcc != NULL); g_return_if_fail(IS_DCC_SERVER(dcc)); MODULE_DATA_INIT(dcc); dcc->created = time(NULL); dcc->chat = NULL; dcc->arg = NULL; dcc->nick = NULL; dcc->tagconn = dcc->tagread = dcc->tagwrite = -1; dcc->server = server; dcc->mynick = g_strdup(mynick); dcc->servertag = g_strdup(servertag); dcc_conns = g_slist_append(dcc_conns, dcc); signal_emit("dcc created", 1, dcc); }
static int dcc_timeout_func(void) { GSList *tmp, *next; time_t now; now = time(NULL)-settings_get_time("dcc_timeout")/1000; for (tmp = dcc_conns; tmp != NULL; tmp = next) { DCC_REC *dcc = tmp->data; next = tmp->next; if (dcc->tagread == -1 && now > dcc->created && !IS_DCC_SERVER(dcc)) { /* Timed out - don't send DCC REJECT CTCP so CTCP flooders won't affect us and it really doesn't matter that much anyway if the other side doen't get it.. We don't want dcc servers to time out. */ dcc_close(dcc); } } return 1; }
/* DCC CLOSE SERVER <port> */ static void cmd_dcc_close(char *data, SERVER_REC *server) { GSList *tmp, *next; char *port_str; void *free_arg; int found, port; g_return_if_fail(data != NULL); if (g_strncasecmp(data, "SERVER ", 7) != 0 || !cmd_get_params(data, &free_arg, 2, NULL, &port_str)) { return; } if (*port_str == '\0') { cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); } port = atoi(port_str); found = FALSE; for (tmp = dcc_conns; tmp != NULL; tmp = next) { SERVER_DCC_REC *dcc = tmp->data; next = tmp->next; if (IS_DCC_SERVER(dcc) && dcc->port == port) { found = TRUE; dcc_close(DCC(dcc)); } } if (found) { signal_stop(); } cmd_params_free(free_arg); }
/* DCC SERVER: text received */ static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg) { g_return_if_fail(IS_DCC_SERVER(dcc)); g_return_if_fail(msg != NULL); /* Check for CHAT protocol */ if (g_strncasecmp(msg, "100 ", 4) == 0) { msg += 4; /* Check if this server is accepting chat requests.*/ if (dcc->accept_chat) { /* Connect and start DCC Chat */ char *str; CHAT_DCC_REC *dccchat = dcc_chat_create(dcc->server, NULL, msg, "chat"); dccchat->starttime = time(NULL); dccchat->handle = dcc->handle; dccchat->sendbuf = net_sendbuffer_create(dccchat->handle, 0); memcpy(&dccchat->addr, &dcc->addr, sizeof(IPADDR)); net_ip2host(&dccchat->addr, dccchat->addrstr); dccchat->port = dcc->port; dccchat->tagread = g_input_add(dccchat->handle, G_INPUT_READ, (GInputFunction) dcc_chat_input, dccchat); dcc->connection_established = 1; signal_emit("dcc connected", 1, dccchat); str = g_strdup_printf("101 %s\n", (dccchat->server) ? dccchat->server->nick : "??"); net_sendbuffer_send(dccchat->sendbuf, str, strlen(str)); g_free(str); } } /* Check for FSERVE protocol */ if (g_strncasecmp(msg, "110 ", 4) == 0) { msg += 4; /* Check if this server is accepting fserve requests.*/ if (dcc->accept_fserve) { /* TODO - Connect and start DCC Fserve */ } } /* Check for SEND protocol */ if (g_strncasecmp(msg, "120 ", 4) == 0) { msg += 4; /* Check if this server is accepting send requests.*/ if (dcc->accept_send) { /* Connect and start DCC Send */ GET_DCC_REC *dccget; char **params, *fname, *nick; int paramcount, len, quoted = FALSE; uoff_t size; /* 120 clientnickname filesize filename */ params = g_strsplit(msg, " ", -1); paramcount = strarray_length(params); if (paramcount < 3) { g_strfreev(params); signal_stop(); return; } nick = params[0]; size = str_to_uofft(params[1]); fname = g_strjoinv(" ", ¶ms[2]); len = strlen(fname); if (len > 1 && *fname == '"' && fname[len-1] == '"') { /* "file name" - MIRC sends filenames with spaces like this */ fname[len-1] = '\0'; g_memmove(fname, fname+1, len); quoted = TRUE; } dccget = dcc_get_create(dcc->server, NULL, nick, fname); dccget->handle = dcc->handle; dccget->target = g_strdup(dcc->server ? dcc->server->nick : "??"); memcpy(&dccget->addr, &dcc->addr, sizeof(dcc->addr)); if (dccget->addr.family == AF_INET) { net_ip2host(&dccget->addr, dccget->addrstr); } else { /* with IPv6, show it to us as it was sent */ memcpy(dccget->addrstr, dcc->addrstr, sizeof(dccget->addrstr)); } dccget->port = dcc->port; dccget->size = size; dccget->file_quoted = quoted; dccget->from_dccserver = 1; dcc->connection_established = 1; signal_emit("dcc request", 2, dccget, dccget->addrstr); g_strfreev(params); g_free(fname); } } signal_stop(); }