static void dcc_chat_passive(CHAT_DCC_REC *dcc) { IPADDR own_ip; int port; GIOChannel *handle; char host[MAX_IP_LEN]; g_return_if_fail(IS_DCC_CHAT(dcc)); if (dcc->addrstr[0] == '\0' || dcc->starttime != 0 || dcc->handle != NULL) { /* already sent a chat request / already chatting */ return; } handle = dcc_listen(net_sendbuffer_handle(dcc->server->handle), &own_ip, &port); if (handle == NULL) cmd_return_error(CMDERR_ERRNO); dcc->handle = handle; dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* Let's send the reply to the other client! */ dcc_ip2str(&own_ip, host); irc_send_cmdv(dcc->server, "PRIVMSG %s :\001DCC CHAT CHAT %s %d %d\001", dcc->nick, host, port, dcc->pasv_id); }
int dcc_start_send(const char *nick, const char *fname, int timeout) { dcc_listen_t *listen; dcc_send_t *send; int idx, size, fd; char *quote, *slash; fd = open(fname, O_RDONLY); if (!fd) return(-2); /* File could not be opened. */ size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); listen = dcc_listen(timeout); if (!listen) { close(fd); return(-1); } /* Create an empty sockbuf that will eventually be used for the * dcc chat (when they connect to us). */ idx = sockbuf_new(); send = calloc(1, sizeof(*send)); sockbuf_attach_filter(idx, &dcc_send_filter, send); listen->client = idx; send->next = dcc_send_head; dcc_send_head = send; send->serv = listen->serv; send->port = listen->port; send->fd = fd; send->idx = idx; send->size = size; send->bytes_sent = 0; send->bytes_left = size; timer_get_now_sec(&send->request_time); send->fname = strdup(fname); send->nick = strdup(nick); slash = strrchr(fname, '/'); if (slash) fname = slash+1; if (strchr(fname, ' ')) quote = "\""; else quote = ""; printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC SEND %s%s%s %u %d %d%c", nick, 1, quote, fname, quote, current_server.mylongip, listen->port, size, 1); return(idx); }
/* Starts a chat with the specified nick. * If timeout is 0, the default timeout is used. * If timeout is -1, there is no timeout. * We don't make sure the nick is valid, so if it's not, you won't know until * the chat times out. */ int dcc_start_chat(const char *nick, int timeout) { dcc_listen_t *listen; int idx; /* Create a listening idx to accept the chat connection. */ listen = dcc_listen(timeout); if (!listen) return(-1); /* Create an empty sockbuf that will eventually be used for the * dcc chat (when they connect to us). */ idx = sockbuf_new(); sockbuf_attach_filter(idx, &dcc_chat_filter, (void *)listen->serv); listen->client = idx; printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC CHAT chat %u %d%c", nick, 1, current_server.mylongip, listen->port, 1); return(idx); }
void dcc_get_passive(GET_DCC_REC *dcc) { GIOChannel *handle; IPADDR own_ip; int port; char host[MAX_IP_LEN]; handle = dcc_listen(net_sendbuffer_handle(dcc->server->handle), &own_ip, &port); if (handle == NULL) cmd_return_error(CMDERR_ERRNO); dcc->handle = handle; dcc->tagconn = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_get_listen, dcc); /* Let's send the reply to the other client! */ dcc_ip2str(&own_ip, host); irc_send_cmdv(dcc->server, "PRIVMSG %s :\001DCC SEND %s %s %d %"PRIuUOFF_T" %d\001", dcc->nick, dcc->arg, host, port, dcc->size, dcc->pasv_id); }
/* 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); }
static int dcc_send_one_file(int queue, const char *target, const char *fname, IRC_SERVER_REC *server, CHAT_DCC_REC *chat) { struct stat st; char *str; char host[MAX_IP_LEN]; int hfile, port; SEND_DCC_REC *dcc; IPADDR own_ip; GIOChannel *handle; if (dcc_find_request(DCC_SEND_TYPE, target, fname)) { signal_emit("dcc error send exists", 2, target, fname); return FALSE; } str = dcc_send_get_file(fname); hfile = open(str, O_RDONLY); g_free(str); if (hfile == -1) { signal_emit("dcc error file open", 3, target, fname, GINT_TO_POINTER(errno)); return FALSE; } if (fstat(hfile, &st) < 0) { g_warning("fstat() failed: %s", strerror(errno)); close(hfile); return FALSE; } /* start listening */ handle = dcc_listen(chat != NULL ? chat->handle : net_sendbuffer_handle(server->handle), &own_ip, &port); if (handle == NULL) { close(hfile); g_warning("dcc_listen() failed: %s", strerror(errno)); return FALSE; } fname = g_basename(fname); /* Replace all the spaces with underscore so that lesser intellgent clients can communicate.. */ if (!settings_get_bool("dcc_send_replace_space_with_underscore")) str = NULL; else { str = g_strdup(fname); g_strdelimit(str, " ", '_'); fname = str; } dcc = dcc_send_create(server, chat, target, fname); g_free(str); dcc->handle = handle; dcc->port = port; dcc->size = st.st_size; dcc->fhandle = hfile; dcc->queue = queue; dcc->file_quoted = strchr(fname, ' ') != NULL; dcc->tagconn = g_input_add(handle, G_INPUT_READ, (GInputFunction) dcc_send_connected, dcc); /* send DCC request */ signal_emit("dcc request send", 1, dcc); dcc_ip2str(&own_ip, host); str = g_strdup_printf(dcc->file_quoted ? "DCC SEND \"%s\" %s %d %"PRIuUOFF_T : "DCC SEND %s %s %d %"PRIuUOFF_T, dcc->arg, host, port, dcc->size); dcc_ctcp_message(server, target, chat, FALSE, str); g_free(str); return TRUE; }