void bot_send_cmd(BOT_REC *bot, char *data) { g_return_if_fail(bot != NULL); g_return_if_fail(data != NULL); net_transmit(bot->handle, data, strlen(data)); net_transmit(bot->handle, "\n", 1); }
static gboolean sig_server_event(gchar *line, SERVER_REC *server, gchar *nick, gchar *address) { GSList *tmp, *list; gchar *event, *args; g_return_val_if_fail(line != NULL, FALSE); /* get command.. */ event = g_strconcat("event ", line, NULL); args = strchr(event+6, ' '); if (args != NULL) *args++ = '\0'; else args = ""; while (*args == ' ') args++; list = server_redirect_getqueue(server, event, args); if (list != NULL) { /* we want to send this to one client (or proxy itself) only */ REDIRECT_REC *rec; gint handle; rec = list->data; if (g_strncasecmp(rec->name, "proxy ", 6) != 0) { /* proxy only */ g_free(event); return TRUE; } if (sscanf(rec->name+6, "%d", &handle) == 1) { /* send it to specific client only */ server_redirect_remove_next(server, event, list); net_transmit(handle, next_line->str, next_line->len); g_free(event); return FALSE; } } if (g_strcasecmp(event, "event ping") == 0) { /* We want to answer ourself to PINGs.. */ g_free(event); return TRUE; } /* send the data to clients.. */ for (tmp = proxy_data->clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->server == server) net_transmit(rec->handle, next_line->str, next_line->len); } g_free(event); return TRUE; }
/* Send `data' to dcc chat. */ void dcc_chat_send(DCC_REC *dcc, const char *data) { g_return_if_fail(dcc != NULL); g_return_if_fail(data != NULL); /* FIXME: we need output queue! */ net_transmit(dcc->handle, data, strlen(data)); net_transmit(dcc->handle, "\n", 1); }
/* input function: DCC GET is free to send data */ static void sig_dccget_send(GET_DCC_REC *dcc) { guint32 recd; int ret; if (dcc->count_pos != 0) { ret = net_transmit(dcc->handle, dcc->count_buf+dcc->count_pos, 4-dcc->count_pos); if (dcc->count_pos <= 0) dcc->count_pos = ret; else if (ret > 0) dcc->count_pos += ret; if (dcc->count_pos == 4) dcc->count_pos = 0; } if (dcc->count_pos == 0) { g_source_remove(dcc->tagwrite); dcc->tagwrite = -1; } memcpy(&recd, dcc->count_buf, 4); if (recd != (guint32) htonl(dcc->transfd)) dcc_get_send_received(dcc); }
static void ssl_input(struct ssl_proxy *proxy) { int rcvd, sent; rcvd = proxy_recv_ssl(proxy, proxy->outbuf_plain, sizeof(proxy->outbuf_plain)); if (rcvd <= 0) return; sent = net_transmit(proxy->fd_plain, proxy->outbuf_plain, (size_t)rcvd); if (sent == rcvd) return; if (sent < 0) { /* disconnected */ ssl_proxy_destroy(proxy); return; } /* everything wasn't sent - don't read anything until we've sent it all */ proxy->outbuf_pos_plain = 0; proxy->send_left_plain = rcvd - sent; io_remove(proxy->io_ssl); proxy->io_ssl = io_add(proxy->fd_ssl, IO_WRITE, ssl_output, proxy); }
/* Send data, if all of it couldn't be sent immediately, it will be resent automatically after a while. Returns -1 if some unrecoverable error occured. */ int net_sendbuffer_send(NET_SENDBUF_REC *rec, const void *data, int size) { int ret; g_return_val_if_fail(rec != NULL, -1); g_return_val_if_fail(data != NULL, -1); if (size <= 0) return 0; if (rec->buffer == NULL) { /* nothing in buffer - transmit immediately */ ret = net_transmit(rec->handle, data, size); if (ret < 0) return -1; size -= ret; data = ((const char *) data) + ret; } if (size <= 0) return 0; /* everything couldn't be sent. */ if (rec->send_tag == -1) { rec->send_tag = g_input_add(rec->handle, G_INPUT_WRITE, (GInputFunction) sig_sendbuffer, rec); } return buffer_add(rec, data, size) ? 0 : -1; }
/* input function: DCC SEND - we're ready to send more data */ static void dcc_send_data(DCC_REC *dcc) { int ret; g_return_if_fail(dcc != NULL); if (!dcc->fastsend && !dcc->gotalldata) { /* haven't received everything we've send there yet.. */ return; } ret = read(dcc->fhandle, dcc->databuf, dcc->databufsize); if (ret <= 0) { /* end of file .. or some error .. */ if (dcc->fastsend) { /* no need to call this function anymore.. in fact it just eats all the cpu.. */ dcc->waitforend = TRUE; g_source_remove(dcc->tagwrite); dcc->tagwrite = -1; } else { signal_emit("dcc closed", 1, dcc); dcc_destroy(dcc); } return; } ret = net_transmit(dcc->handle, dcc->databuf, ret); if (ret > 0) dcc->transfd += ret; dcc->gotalldata = FALSE; lseek(dcc->fhandle, dcc->transfd, SEEK_SET); signal_emit("dcc transfer update", 1, dcc); }
void proxy_outdata(CLIENT_REC *client, const char *data, ...) { va_list args; char *str; g_return_if_fail(client != NULL); g_return_if_fail(data != NULL); va_start(args, data); str = g_strdup_vprintf(data, args); net_transmit(client->handle, str, strlen(str)); g_free(str); va_end(args); }
/* Transmit all data from buffer - return TRUE if the whole buffer was sent */ static int buffer_send(NET_SENDBUF_REC *rec) { int ret; ret = net_transmit(rec->handle, rec->buffer, rec->bufpos); if (ret < 0 || rec->bufpos == ret) { /* error/all sent - don't try to send it anymore */ g_free_and_null(rec->buffer); return TRUE; } if (ret > 0) { rec->bufpos -= ret; g_memmove(rec->buffer, rec->buffer+ret, rec->bufpos); } return FALSE; }
void dcc_get_send_received(DCC_REC *dcc) { guint32 recd; recd = (guint32) htonl(dcc->transfd); memcpy(dcc->count_buf, &recd, 4); dcc->count_pos = net_transmit(dcc->handle, dcc->count_buf+dcc->count_pos, 4-dcc->count_pos); if (dcc->count_pos == 4) dcc->count_pos = 0; /* count_pos might be -1 here. if this happens, the count_buf should be re-sent.. also, if it's 1, 2 or 3, the last 1-3 bytes should be sent later. these happen probably never, but I just want to do it right.. :) */ if (dcc->tagwrite != -1) { dcc->tagwrite = g_input_add(dcc->handle, G_INPUT_WRITE, (GInputFunction) sig_dccget_send, dcc); } }
static void ssl_output(struct ssl_proxy *proxy) { int sent; sent = net_transmit(proxy->fd_plain, proxy->outbuf_plain + proxy->outbuf_pos_plain, proxy->send_left_plain); if (sent < 0) { /* disconnected */ ssl_proxy_destroy(proxy); return; } proxy->send_left_plain -= sent; proxy->outbuf_pos_plain += sent; if (proxy->send_left_plain > 0) return; /* everything is sent, start reading again */ io_remove(proxy->io_ssl); proxy->io_ssl = io_add(proxy->fd_ssl, IO_READ, ssl_input, proxy); }
/* input function: DCC SEND - we're ready to send more data */ static void dcc_send_data(SEND_DCC_REC *dcc) { char buffer[512]; int ret; ret = read(dcc->fhandle, buffer, sizeof(buffer)); if (ret <= 0) { /* no need to call this function anymore.. in fact it just eats all the cpu.. */ dcc->waitforend = TRUE; g_source_remove(dcc->tagwrite); dcc->tagwrite = -1; return; } ret = net_transmit(dcc->handle, buffer, ret); if (ret > 0) dcc->transfd += ret; dcc->gotalldata = FALSE; lseek(dcc->fhandle, dcc->transfd, SEEK_SET); signal_emit("dcc transfer update", 1, dcc); }
void proxy_outdata_all(IRC_SERVER_REC *server, const char *data, ...) { va_list args; GSList *tmp; char *str; int len; g_return_if_fail(server != NULL); g_return_if_fail(data != NULL); va_start(args, data); str = g_strdup_vprintf(data, args); len = strlen(str); for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { CLIENT_REC *rec = tmp->data; if (rec->connected && rec->server == server) net_transmit(rec->handle, str, len); } g_free(str); va_end(args); }
/* callback: net_connect() finished for DCC GET */ void sig_dccget_connected(GET_DCC_REC *dcc) { struct stat statbuf; char *fname, *tempfname, *str; int ret, ret_errno, temphandle, old_umask; if (!dcc->from_dccserver) { if (net_geterror(dcc->handle) != 0) { /* error connecting */ signal_emit("dcc error connect", 1, dcc); dcc_destroy(DCC(dcc)); return; } g_source_remove(dcc->tagconn); dcc->tagconn = -1; } g_free_not_null(dcc->file); dcc->file = dcc_get_download_path(dcc->arg); /* if some plugin wants to change the file name/path here.. */ signal_emit("dcc get receive", 1, dcc); if (stat(dcc->file, &statbuf) == 0 && dcc->get_type == DCC_GET_RENAME) { /* file exists, rename.. */ fname = dcc_get_rename_file(dcc->file); g_free(dcc->file); dcc->file = fname; } if (dcc->get_type != DCC_GET_RESUME) { int dcc_file_create_mode = octal2dec(settings_get_int("dcc_file_create_mode")); /* we want to overwrite the file, remove it here. if it gets created after this, we'll fail. */ unlink(dcc->file); /* just to make sure we won't run into race conditions if download_path is in some global temp directory */ tempfname = g_strconcat(dcc->file, ".XXXXXX", NULL); old_umask = umask(0077); temphandle = mkstemp(tempfname); umask(old_umask); if (temphandle == -1) ret = -1; else ret = fchmod(temphandle, dcc_file_create_mode); close(temphandle); if (ret != -1) { ret = link(tempfname, dcc->file); if (ret == -1 && /* Linux */ (errno == EPERM || /* FUSE */ errno == ENOSYS || /* BSD */ errno == EOPNOTSUPP)) { /* hard links aren't supported - some people want to download stuff to FAT/NTFS/etc partitions, so fallback to rename() */ ret = rename(tempfname, dcc->file); } } /* if ret = 0, we're the file owner now */ dcc->fhandle = ret == -1 ? -1 : open(dcc->file, O_WRONLY | O_TRUNC); /* close/remove the temp file */ ret_errno = errno; unlink(tempfname); g_free(tempfname); if (dcc->fhandle == -1) { signal_emit("dcc error file create", 3, dcc, dcc->file, g_strerror(ret_errno)); dcc_destroy(DCC(dcc)); return; } } dcc->starttime = time(NULL); if (dcc->size == 0) { dcc_close(DCC(dcc)); return; } dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) sig_dccget_receive, dcc); signal_emit("dcc connected", 1, dcc); if (dcc->from_dccserver) { str = g_strdup_printf("121 %s %d\n", dcc->server ? dcc->server->nick : "??", 0); net_transmit(dcc->handle, str, strlen(str)); } }
static void sig_listen_client(CLIENT_REC *client, gint handle) { char tmpbuf[1024], *str, *cmd, *args, *p; int ret, recvlen; g_return_if_fail(client != NULL); for (;;) { recvlen = net_receive(handle, tmpbuf, sizeof(tmpbuf)); ret = line_split(tmpbuf, recvlen, &str, &client->buffer); if (ret == -1) { /* connection lost */ remove_client(proxy_data, client); break; } if (ret == 0) break; if (client->server == NULL) continue; cmd = g_strdup(str); args = strchr(cmd, ' '); if (args != NULL) *args++ = '\0'; else args = ""; if (*args == ':') args++; g_strup(cmd); if (!client->connected) { if (proxy_data->password != NULL && strcmp(cmd, "PASS") == 0) { if (strcmp(proxy_data->password, args) != 0) { /* wrong password! */ remove_client(proxy_data, client); break; } client->pass_sent = TRUE; } else if (strcmp(cmd, "NICK") == 0) client->nick = g_strdup(args); else if (strcmp(cmd, "USER") == 0) { if (client->nick == NULL || (proxy_data->password != NULL && !client->pass_sent)) { /* stupid client didn't send us NICK/PASS or, kill it */ remove_client(proxy_data, client); break; } client->connected = TRUE; plugin_proxy_dump_data(client); } } else if (strcmp(cmd, "QUIT") == 0) { remove_client(proxy_data, client); break; } else if (strcmp(cmd, "PING") == 0) { net_transmit(handle, "PONG proxy :nick\n", 17); } else { net_transmit(net_sendbuffer_handle(client->server->handle), str, strlen(str)); net_transmit(net_sendbuffer_handle(client->server->handle), "\n", 1); if (strcmp(cmd, "WHO") == 0) { grab_who(client, args); } else if (strcmp(cmd, "WHOIS") == 0) { /* convert dots to spaces */ for (p = args; *p != '\0'; p++) if (*p == ',') *p = ' '; proxy_redirect_event(client, args, 2, "event 318", -1, "event 402", -1, "event 401", 1, "event 311", 1, "event 301", 1, "event 312", 1, "event 313", 1, "event 317", 1, "event 319", 1, NULL); } else if (strcmp(cmd, "ISON") == 0) { proxy_redirect_event(client, NULL, 1, "event 303", -1, NULL); } else if (strcmp(cmd, "USERHOST") == 0) { proxy_redirect_event(client, args, 1, "event 302", -1, "event 401", 1, NULL); } else if (strcmp(cmd, "MODE") == 0) { /* convert dots to spaces */ gchar *slist, *str, mode; gint argc; p = strchr(args, ' '); if (p != NULL) *p++ = '\0'; mode = p == NULL ? '\0' : *p; slist = g_strdup(args); argc = 1; for (p = slist; *p != '\0'; p++) { if (*p == ',') { *p = ' '; argc++; } } /* get channel mode / bans / exception / invite list */ str = g_strdup_printf("%s %s", args, slist); switch (mode) { case '\0': while (argc-- > 0) proxy_redirect_event(client, str, 3, "event 403", 1, "event 443", 1, "event 324", 1, NULL); break; case 'b': while (argc-- > 0) proxy_redirect_event(client, str, 2, "event 403", 1, "event 368", 1, "event 367", 1, NULL); break; case 'e': while (argc-- > 0) proxy_redirect_event(client, str, 4, "event 403", 1, "event 482", 1, "event 472", -1, "event 349", 1, "event 348", 1, NULL); break; case 'I': while (argc-- > 0) proxy_redirect_event(client, str, 4, "event 403", 1, "event 482", 1, "event 472", -1, "event 347", 1, "event 346", 1, NULL); break; } g_free(str); g_free(slist); } } g_free(cmd); } }