/* command: DCC CHAT */ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) { DCC_REC *dcc; IPADDR own_ip; char *str, host[MAX_IP_LEN]; int port, handle; g_return_if_fail(data != NULL); if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = dcc_find_item(DCC_TYPE_CHAT, data, NULL); if (dcc != NULL) { /* found from dcc list - so we're the connecting side.. */ dcc_chat_connect(dcc); return; } /* send dcc chat request */ if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (net_getsockname(server->handle, &own_ip, NULL) == -1) cmd_return_error(CMDERR_ERRNO); port = settings_get_int("dcc_port"); handle = net_listen(&own_ip, &port); if (handle == -1) cmd_return_error(CMDERR_ERRNO); dcc = dcc_create(DCC_TYPE_CHAT, handle, data, "chat", server, NULL); dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* send the request */ dcc_make_address(&own_ip, host); str = g_strdup_printf("PRIVMSG %s :\001DCC CHAT CHAT %s %d\001", data, host, port); irc_send_cmd(server, str); g_free(str); }
/* CTCP: DCC CHAT */ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr, const char *target, CHAT_DCC_REC *chat) { CHAT_DCC_REC *dcc; char **params; int paramcount; int passive, autoallow = FALSE; /* CHAT <unused> <address> <port> */ /* CHAT <unused> <address> 0 <id> (DCC CHAT passive protocol) */ params = g_strsplit(data, " ", -1); paramcount = g_strv_length(params); if (paramcount < 3) { g_strfreev(params); return; } passive = paramcount == 4 && g_strcmp0(params[2], "0") == 0; if (nick == NULL) nick = ""; dcc = DCC_CHAT(dcc_find_request(DCC_CHAT_TYPE, nick, NULL)); if (dcc != NULL) { if (dcc_is_listening(dcc)) { /* we requested dcc chat, they requested dcc chat from us .. allow it. */ dcc_destroy(DCC(dcc)); autoallow = TRUE; } else if (!dcc_is_passive(dcc)) { /* we already have one dcc chat request from this nick, remove it. */ dcc_destroy(DCC(dcc)); } else if (passive) { if (dcc->pasv_id != atoi(params[3])) { /* IDs don't match! */ dcc_destroy(DCC(dcc)); } else { /* IDs are ok! Update address and port and connect! */ dcc->target = g_strdup(target); dcc->port = atoi(params[2]); dcc_str2ip(params[1], &dcc->addr); net_ip2host(&dcc->addr, dcc->addrstr); dcc_chat_connect(dcc); g_strfreev(params); return; } } } dcc = dcc_chat_create(server, chat, nick, params[0]); if (dcc == NULL) { g_strfreev(params); g_warn_if_reached(); return; } dcc->target = g_strdup(target); dcc->port = atoi(params[2]); if (passive) dcc->pasv_id = atoi(params[3]); dcc_str2ip(params[1], &dcc->addr); net_ip2host(&dcc->addr, dcc->addrstr); signal_emit("dcc request", 2, dcc, addr); if (autoallow || DCC_CHAT_AUTOACCEPT(dcc, server, nick, addr)) { if (passive) { /* Passive DCC... let's set up a listening socket and send reply back */ dcc_chat_passive(dcc); } else { dcc_chat_connect(dcc); } } g_strfreev(params); }
/* SYNTAX: DCC CHAT [-passive] [<nick>] */ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) { void *free_arg; CHAT_DCC_REC *dcc; IPADDR own_ip; GIOChannel *handle; GHashTable *optlist; int p_id; char *nick, host[MAX_IP_LEN]; int port; g_return_if_fail(data != NULL); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, "dcc chat", &optlist, &nick)) return; if (*nick == '\0') { dcc = DCC_CHAT(dcc_find_request_latest(DCC_CHAT_TYPE)); if (dcc != NULL) { if (!dcc_is_passive(dcc)) dcc_chat_connect(dcc); else dcc_chat_passive(dcc); } cmd_params_free(free_arg); return; } dcc = dcc_chat_find_id(nick); if (dcc != NULL && dcc_is_waiting_user(dcc)) { if (!dcc_is_passive(dcc)) { /* found from dcc chat requests, we're the connecting side */ dcc_chat_connect(dcc); } else { /* We are accepting a passive DCC CHAT. */ dcc_chat_passive(dcc); } cmd_params_free(free_arg); return; } if (dcc != NULL && dcc_is_listening(dcc) && dcc->server == server) { /* sending request again even while old request is still waiting, remove it. */ dcc_destroy(DCC(dcc)); } if (!IS_IRC_SERVER(server) || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); dcc = dcc_chat_create(server, NULL, nick, "chat"); if (dcc == NULL) { cmd_params_free(free_arg); g_warn_if_reached(); return; } if (g_hash_table_lookup(optlist, "passive") == NULL) { /* Standard DCC CHAT... let's listen for incoming connections */ handle = dcc_listen(net_sendbuffer_handle(server->handle), &own_ip, &port); if (handle == NULL) cmd_param_error(CMDERR_ERRNO); dcc->handle = handle; dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* send the chat request */ signal_emit("dcc request send", 1, dcc); dcc_ip2str(&own_ip, host); irc_send_cmdv(server, "PRIVMSG %s :\001DCC CHAT CHAT %s %d\001", nick, host, port); } else { /* Passive protocol... we want the other side to listen */ /* send the chat request */ dcc->port = 0; signal_emit("dcc request send", 1, dcc); /* generate a random id */ p_id = rand() % 64; dcc->pasv_id = p_id; /* 16843009 is the long format of 1.1.1.1, we use a fake IP since the other side shouldn't care of it: they will send the address for us to connect to in the reply */ irc_send_cmdv(server, "PRIVMSG %s :\001DCC CHAT CHAT 16843009 0 %d\001", nick, p_id); } cmd_params_free(free_arg); }