#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include "server.h"
Go to the source code of this file.
Data Structures | |
struct | dcc_listen |
struct | dcc_send |
Defines | |
#define | DCC_FILTER_LEVEL (SOCKBUF_LEVEL_TEXT_BUFFER + 100) |
Typedefs | |
typedef struct dcc_listen | dcc_listen_t |
typedef struct dcc_send | dcc_send_t |
Functions | |
static int | dcc_listen_newclient (void *client_data, int idx, int newidx, const char *peer_ip, int peer_port) |
static int | dcc_listen_delete (event_owner_t *owner, void *client_data) |
static int | dcc_listen_timeout (void *client_data) |
static int | dcc_chat_connect (void *client_data, int idx, const char *peer_ip, int peer_port) |
static int | dcc_chat_eof (void *client_data, int idx, int err, const char *errmsg) |
static int | dcc_chat_delete (void *client_data, int idx) |
static int | dcc_send_connect (void *client_data, int idx, const char *peer_ip, int peer_port) |
static int | dcc_send_read (void *client_data, int idx, char *data, int len) |
static int | dcc_send_written (void *client_data, int idx, int len, int remaining) |
static int | dcc_send_eof (void *client_data, int idx, int err, const char *errmsg) |
static int | dcc_send_delete (void *client_data, int idx) |
static int | dcc_send_done (dcc_send_t *send) |
static int | dcc_recv_timeout (void *client_data) |
static int | dcc_recv_connect (void *client_data, int idx, const char *peer_ip, int peer_port) |
static int | dcc_recv_read (void *client_data, int idx, char *data, int len) |
static int | dcc_recv_eof (void *client_data, int idx, int err, const char *errmsg) |
static int | dcc_recv_delete (void *client_data, int idx) |
static void | update_snapshot (dcc_send_t *send, int len) |
static int | dcc_dns_callback (void *client_data, const char *host, char **ips) |
int | dcc_dns_set (const char *host) |
static dcc_listen_t * | dcc_listen (int timeout) |
int | dcc_start_chat (const char *nick, int timeout) |
int | dcc_start_send (const char *nick, const char *fname, int timeout) |
static int | dcc_send_bytes (dcc_send_t *send) |
int | dcc_send_info (int idx, int field, void *valueptr) |
int | dcc_accept_send (char *nick, char *localfname, char *fname, int size, int resume, char *ip, int port, int timeout) |
static void | got_chat (char *nick, char *uhost, user_t *u, char *text) |
static void | got_resume (char *nick, char *uhost, user_t *u, char *text) |
static void | got_accept (char *nick, char *uhost, user_t *u, char *text) |
static void | got_send (char *nick, char *uhost, user_t *u, char *text) |
static int | got_dcc (char *nick, char *uhost, user_t *u, char *dest, char *cmd, char *text) |
Variables | |
static const char | rcsid [] = "$Id: dcc.c,v 1.27 2007-09-13 22:20:57 sven Exp $" |
static dcc_send_t * | dcc_send_head = NULL |
static dcc_send_t * | dcc_recv_head = NULL |
event_owner_t | server_dcclistener_owner |
static sockbuf_handler_t | dcc_listen_handler |
static sockbuf_filter_t | dcc_chat_filter |
static sockbuf_filter_t | dcc_send_filter |
static sockbuf_filter_t | dcc_recv_filter |
bind_list_t | ctcp_dcc_binds [] |
#define DCC_FILTER_LEVEL (SOCKBUF_LEVEL_TEXT_BUFFER + 100) |
Definition at line 93 of file dcc.c.
Referenced by dcc_chat_connect(), dcc_chat_eof(), dcc_recv_connect(), dcc_recv_eof(), dcc_recv_read(), dcc_send_bytes(), dcc_send_connect(), dcc_send_done(), dcc_send_eof(), and dcc_send_written().
typedef struct dcc_listen dcc_listen_t |
typedef struct dcc_send dcc_send_t |
int dcc_accept_send | ( | char * | nick, | |
char * | localfname, | |||
char * | fname, | |||
int | size, | |||
int | resume, | |||
char * | ip, | |||
int | port, | |||
int | timeout | |||
) |
Definition at line 506 of file dcc.c.
References dcc_send::bytes_left, dcc_send::bytes_sent, dcc_send::connect_time, dcc_recv_timeout(), egg_connect(), dcc_send::fd, dcc_send::fname, dcc_send::idx, dcc_send::ip, LOG_MISC, dcc_send::next, dcc_send::nick, dcc_send::port, printserv, putlog(), dcc_send::request_time, egg_timeval::sec, server_config, SERVER_NORMAL, server_owner, dcc_send::size, sockbuf_attach_filter(), sockbuf_new(), timer_create_complex(), timer_get_now_sec(), dcc_send::timer_id, and egg_timeval::usec.
00507 { 00508 dcc_send_t *send; 00509 char *quote; 00510 egg_timeval_t howlong; 00511 00512 send = calloc(1, sizeof(*send)); 00513 send->next = dcc_recv_head; 00514 dcc_recv_head = send; 00515 00516 /* See if they want the default timeout. */ 00517 if (!timeout) timeout = server_config.dcc_timeout; 00518 if (timeout > 0) { 00519 char buf[128]; 00520 00521 snprintf(buf, sizeof(buf), "dcc recv %s/%d", ip, port); 00522 howlong.sec = timeout; 00523 howlong.usec = 0; 00524 send->timer_id = timer_create_complex(&howlong, buf, dcc_recv_timeout, send, 0, &server_owner); 00525 } 00526 else send->connect_time = -1; 00527 00528 send->port = port; 00529 send->fname = strdup(localfname); 00530 send->nick = strdup(nick); 00531 send->ip = strdup(ip); 00532 send->size = size; 00533 send->bytes_sent = 0; 00534 send->bytes_left = size; 00535 timer_get_now_sec(&send->request_time); 00536 00537 if (resume < 0) { 00538 send->fd = open(localfname, O_RDWR | O_CREAT, 0640); 00539 resume = lseek(send->fd, 0, SEEK_END); 00540 close(send->fd); 00541 if (resume < 0) resume = 0; 00542 } 00543 00544 if (resume >= size) resume = 0; 00545 00546 if (resume) { 00547 putlog(LOG_MISC, "*", "sending resume request"); 00548 send->idx = sockbuf_new(); 00549 send->fd = open(localfname, O_RDWR | O_CREAT, 0640); 00550 if (resume < 0) resume = lseek(send->fd, 0, SEEK_END); 00551 else resume = lseek(send->fd, resume, SEEK_SET); 00552 if (strchr(fname, ' ')) quote = "\""; 00553 else quote = ""; 00554 printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC RESUME %s%s%s %d %d%c", nick, 1, quote, fname, quote, port, resume, 1); 00555 } 00556 else { 00557 send->idx = egg_connect(ip, port, -1); 00558 send->fd = open(localfname, O_RDWR | O_CREAT | O_TRUNC, 0640); 00559 } 00560 00561 sockbuf_attach_filter(send->idx, &dcc_recv_filter, send); 00562 00563 return(send->idx); 00564 }
static int dcc_chat_connect | ( | void * | client_data, | |
int | idx, | |||
const char * | peer_ip, | |||
int | peer_port | |||
) | [static] |
Definition at line 237 of file dcc.c.
References DCC_FILTER_LEVEL, NULL, sockbuf_detach_filter(), and sockbuf_on_connect().
00238 { 00239 sockbuf_detach_filter(idx, &dcc_chat_filter, NULL); 00240 return sockbuf_on_connect(idx, DCC_FILTER_LEVEL, peer_ip, peer_port); 00241 }
static int dcc_chat_delete | ( | void * | client_data, | |
int | idx | |||
) | [static] |
Definition at line 249 of file dcc.c.
References dcc_send::serv, and sockbuf_delete().
00250 { 00251 int serv = (int) client_data; 00252 sockbuf_delete(serv); 00253 return(0); 00254 }
static int dcc_chat_eof | ( | void * | client_data, | |
int | idx, | |||
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 243 of file dcc.c.
References DCC_FILTER_LEVEL, NULL, sockbuf_detach_filter(), and sockbuf_on_eof().
00244 { 00245 sockbuf_detach_filter(idx, &dcc_chat_filter, NULL); 00246 return sockbuf_on_eof(idx, DCC_FILTER_LEVEL, err, errmsg); 00247 }
static int dcc_dns_callback | ( | void * | client_data, | |
const char * | host, | |||
char ** | ips | |||
) | [static] |
Definition at line 116 of file dcc.c.
References current_server, socket_ip_to_uint(), and str_redup().
Referenced by dcc_dns_set().
00117 { 00118 if (ips && ips[0]) str_redup(¤t_server.myip, ips[0]); 00119 else str_redup(¤t_server.myip, "127.0.0.1"); 00120 socket_ip_to_uint(current_server.myip, ¤t_server.mylongip); 00121 return(0); 00122 }
int dcc_dns_set | ( | const char * | host | ) |
Definition at line 124 of file dcc.c.
References dcc_dns_callback(), egg_dns_lookup(), NULL, and server_owner.
00125 { 00126 egg_dns_lookup(host, 0, dcc_dns_callback, NULL, &server_owner); 00127 return(0); 00128 }
static dcc_listen_t* dcc_listen | ( | int | timeout | ) | [static] |
Definition at line 130 of file dcc.c.
References dcc_listen_timeout(), egg_listen(), dcc_send::idx, NULL, dcc_listen::port, dcc_send::port, egg_timeval::sec, dcc_listen::serv, server_config, server_owner, sockbuf_set_handler(), timer_create_complex(), dcc_listen::timer_id, and egg_timeval::usec.
Referenced by dcc_start_chat(), and dcc_start_send().
00131 { 00132 dcc_listen_t *listen; 00133 int idx, port; 00134 egg_timeval_t howlong; 00135 00136 idx = egg_listen(0, &port); 00137 if (idx < 0) return(NULL); 00138 00139 listen = calloc(1, sizeof(*listen)); 00140 listen->serv = idx; 00141 listen->port = port; 00142 00143 sockbuf_set_handler(idx, &dcc_listen_handler, listen, &server_dcclistener_owner); 00144 00145 /* See if they want the default timeout. */ 00146 if (!timeout) timeout = server_config.dcc_timeout; 00147 00148 if (timeout > 0) { 00149 char buf[128]; 00150 00151 snprintf(buf, sizeof(buf), "dcc listen port %d", port); 00152 howlong.sec = timeout; 00153 howlong.usec = 0; 00154 listen->timer_id = timer_create_complex(&howlong, buf, dcc_listen_timeout, listen, 0, &server_owner); 00155 } 00156 00157 return(listen); 00158 }
static int dcc_listen_delete | ( | event_owner_t * | owner, | |
void * | client_data | |||
) | [static] |
Definition at line 203 of file dcc.c.
References dcc_listen::client, sockbuf_isvalid(), SOCKBUF_LEVEL_INTERNAL, sockbuf_on_eof(), dcc_listen::timeout, timer_destroy(), and dcc_listen::timer_id.
00204 { 00205 dcc_listen_t *listen = client_data; 00206 00207 /* If the timer is still going, kill it. */ 00208 if (listen->timer_id != -1) { 00209 timer_destroy(listen->timer_id); 00210 listen->timer_id = -1; 00211 } 00212 00213 /* If we're still waiting for the connection to come in, then send 00214 * an error to the associated client sock. */ 00215 if (sockbuf_isvalid(listen->client)) { 00216 if (listen->timeout) { 00217 sockbuf_on_eof(listen->client, SOCKBUF_LEVEL_INTERNAL, -1, "DCC timed out"); 00218 } 00219 else { 00220 sockbuf_on_eof(listen->client, SOCKBUF_LEVEL_INTERNAL, -2, "DCC listening socket unexpectedly closed"); 00221 } 00222 } 00223 free(listen); 00224 return(0); 00225 }
static int dcc_listen_newclient | ( | void * | client_data, | |
int | idx, | |||
int | newidx, | |||
const char * | peer_ip, | |||
int | peer_port | |||
) | [static] |
Definition at line 184 of file dcc.c.
References dcc_listen::client, SOCKBUF_CLIENT, SOCKBUF_CONNECTING, sockbuf_delete(), sockbuf_get_sock(), and sockbuf_set_sock().
00185 { 00186 int sock; 00187 dcc_listen_t *chat = client_data; 00188 00189 sock = sockbuf_get_sock(newidx); 00190 sockbuf_set_sock(newidx, -1, 0); 00191 sockbuf_delete(newidx); 00192 00193 /* Give the waiting sockbuf the new socket and mark it as a client 00194 * so that it fires the on_connect event. */ 00195 sockbuf_set_sock(chat->client, sock, SOCKBUF_CONNECTING|SOCKBUF_CLIENT); 00196 00197 /* Delete the listening idx since it's not needed. */ 00198 chat->client = -1; 00199 sockbuf_delete(idx); 00200 return(0); 00201 }
static int dcc_listen_timeout | ( | void * | client_data | ) | [static] |
Definition at line 227 of file dcc.c.
References dcc_listen::serv, sockbuf_delete(), dcc_listen::timeout, and dcc_listen::timer_id.
Referenced by dcc_listen().
00228 { 00229 dcc_listen_t *listen = client_data; 00230 00231 listen->timeout = 1; 00232 listen->timer_id = -1; 00233 sockbuf_delete(listen->serv); 00234 return(0); 00235 }
static int dcc_recv_connect | ( | void * | client_data, | |
int | idx, | |||
const char * | peer_ip, | |||
int | peer_port | |||
) | [static] |
Definition at line 575 of file dcc.c.
References dcc_send::connect_time, DCC_FILTER_LEVEL, sockbuf_on_connect(), timer_destroy(), timer_get_now_sec(), and dcc_send::timer_id.
00576 { 00577 dcc_send_t *send = client_data; 00578 00579 /* send->connect_time holds our connect timer if there was one */ 00580 if (send->timer_id >= 0) timer_destroy(send->timer_id); 00581 timer_get_now_sec(&send->connect_time); 00582 sockbuf_on_connect(idx, DCC_FILTER_LEVEL, peer_ip, peer_port); 00583 return(0); 00584 }
static int dcc_recv_delete | ( | void * | client_data, | |
int | idx | |||
) | [static] |
Definition at line 607 of file dcc.c.
References dcc_send::fd, dcc_send::fname, dcc_send::ip, dcc_send::next, dcc_send::nick, NULL, timer_destroy(), and dcc_send::timer_id.
00608 { 00609 dcc_send_t *send = client_data; 00610 dcc_send_t *prev, *ptr; 00611 00612 if (send->timer_id != -1) timer_destroy(send->timer_id); 00613 00614 if (send->fd != -1) close(send->fd); 00615 if (send->fname) free(send->fname); 00616 if (send->nick) free(send->nick); 00617 if (send->ip) free(send->ip); 00618 prev = NULL; 00619 for (ptr = dcc_recv_head; ptr; ptr = ptr->next) { 00620 if (ptr == send) break; 00621 prev = ptr; 00622 } 00623 if (prev) prev->next = send->next; 00624 else dcc_recv_head = send->next; 00625 free(send); 00626 return(0); 00627 }
static int dcc_recv_eof | ( | void * | client_data, | |
int | idx, | |||
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 600 of file dcc.c.
References DCC_FILTER_LEVEL, sockbuf_delete(), and sockbuf_on_eof().
00601 { 00602 sockbuf_on_eof(idx, DCC_FILTER_LEVEL, err, errmsg); 00603 sockbuf_delete(idx); 00604 return(0); 00605 }
static int dcc_recv_read | ( | void * | client_data, | |
int | idx, | |||
char * | data, | |||
int | len | |||
) | [static] |
Definition at line 586 of file dcc.c.
References dcc_send::bytes_left, dcc_send::bytes_sent, DCC_FILTER_LEVEL, dcc_send::fd, sockbuf_on_read(), sockbuf_on_write(), and update_snapshot().
00587 { 00588 dcc_send_t *send = client_data; 00589 int nlen; /* len in network byte order */ 00590 00591 send->bytes_sent += len; 00592 send->bytes_left -= len; 00593 update_snapshot(send, len); 00594 write(send->fd, data, len); 00595 nlen = htonl(send->bytes_sent); 00596 sockbuf_on_write(idx, DCC_FILTER_LEVEL, (char *)&nlen, 4); 00597 return sockbuf_on_read(idx, DCC_FILTER_LEVEL, data, len); 00598 }
static int dcc_recv_timeout | ( | void * | client_data | ) | [static] |
Definition at line 566 of file dcc.c.
References dcc_send::idx, SOCKBUF_LEVEL_INTERNAL, sockbuf_on_eof(), and dcc_send::timer_id.
Referenced by dcc_accept_send().
00567 { 00568 dcc_send_t *send = client_data; 00569 00570 send->timer_id = -1; 00571 sockbuf_on_eof(send->idx, SOCKBUF_LEVEL_INTERNAL, -1, "DCC timed out"); 00572 return(0); 00573 }
static int dcc_send_bytes | ( | dcc_send_t * | send | ) | [static] |
Definition at line 311 of file dcc.c.
References dcc_send::bytes_left, dcc_send::bytes_sent, DCC_FILTER_LEVEL, dcc_send::fd, dcc_send::idx, sockbuf_isvalid(), sockbuf_on_written(), sockbuf_write(), and update_snapshot().
Referenced by dcc_send_connect(), and dcc_send_written().
00312 { 00313 int n, out, total; 00314 char buf[4096]; 00315 00316 total = 0; 00317 for (;;) { 00318 /* Read in a chunk from the file. If we get eof or error, 00319 * return -1. */ 00320 n = read(send->fd, buf, sizeof(buf)); 00321 if (n <= 0) return(-1); 00322 00323 /* Now write the chunk to the sockbuf. If we get an error 00324 * return -2, and if it starts blocking return 0. Otherwise 00325 * we loop to send another chunk. */ 00326 out = sockbuf_write(send->idx, buf, n); 00327 if (out < 0) return(-2); 00328 send->bytes_sent += out; 00329 send->bytes_left -= out; 00330 update_snapshot(send, out); 00331 total += out; 00332 if (out < n) { 00333 sockbuf_on_written(send->idx, DCC_FILTER_LEVEL, total, n - out); 00334 if (sockbuf_isvalid(send->idx)) return(0); 00335 else return(-2); 00336 } 00337 } 00338 }
static int dcc_send_connect | ( | void * | client_data, | |
int | idx, | |||
const char * | peer_ip, | |||
int | peer_port | |||
) | [static] |
Definition at line 340 of file dcc.c.
References dcc_send::connect_time, DCC_FILTER_LEVEL, dcc_send_bytes(), dcc_send_done(), dcc_send::ip, dcc_send::serv, sockbuf_isvalid(), sockbuf_on_connect(), and timer_get_now_sec().
00341 { 00342 dcc_send_t *send = client_data; 00343 int n; 00344 00345 timer_get_now_sec(&send->connect_time); 00346 send->serv = -1; 00347 send->ip = strdup(peer_ip); 00348 sockbuf_on_connect(idx, DCC_FILTER_LEVEL, peer_ip, peer_port); 00349 if (sockbuf_isvalid(idx)) { 00350 n = dcc_send_bytes(send); 00351 if (n == -1) dcc_send_done(send); 00352 } 00353 return(0); 00354 }
static int dcc_send_delete | ( | void * | client_data, | |
int | idx | |||
) | [static] |
Definition at line 403 of file dcc.c.
References dcc_send::fd, dcc_send::fname, dcc_send::ip, dcc_send::next, dcc_send::nick, NULL, dcc_send::serv, sockbuf_delete(), and sockbuf_isvalid().
00404 { 00405 dcc_send_t *send = client_data; 00406 dcc_send_t *prev, *ptr; 00407 00408 if (sockbuf_isvalid(send->serv)) { 00409 sockbuf_delete(send->serv); 00410 } 00411 if (send->fd != -1) close(send->fd); 00412 if (send->fname) free(send->fname); 00413 if (send->nick) free(send->nick); 00414 if (send->ip) free(send->ip); 00415 prev = NULL; 00416 for (ptr = dcc_send_head; ptr; ptr = ptr->next) { 00417 if (ptr == send) break; 00418 prev = ptr; 00419 } 00420 if (prev) prev->next = send->next; 00421 else dcc_send_head = send->next; 00422 free(send); 00423 return(0); 00424 }
static int dcc_send_done | ( | dcc_send_t * | send | ) | [static] |
Definition at line 426 of file dcc.c.
References DCC_FILTER_LEVEL, dcc_send::fd, dcc_send::idx, sockbuf_delete(), sockbuf_isvalid(), and sockbuf_on_eof().
Referenced by dcc_send_connect(), and dcc_send_written().
00427 { 00428 int idx; 00429 00430 idx = send->idx; 00431 close(send->fd); 00432 send->fd = -1; 00433 sockbuf_on_eof(idx, DCC_FILTER_LEVEL, 0, "Success"); 00434 00435 /* If their handler didn't close the idx, do it here. */ 00436 if (sockbuf_isvalid(idx)) sockbuf_delete(idx); 00437 return(0); 00438 }
static int dcc_send_eof | ( | void * | client_data, | |
int | idx, | |||
int | err, | |||
const char * | errmsg | |||
) | [static] |
Definition at line 396 of file dcc.c.
References DCC_FILTER_LEVEL, sockbuf_delete(), and sockbuf_on_eof().
00397 { 00398 sockbuf_on_eof(idx, DCC_FILTER_LEVEL, err, errmsg); 00399 sockbuf_delete(idx); 00400 return(0); 00401 }
int dcc_send_info | ( | int | idx, | |
int | field, | |||
void * | valueptr | |||
) |
Definition at line 440 of file dcc.c.
References dcc_send::acks, dcc_send::bytes_acked, dcc_send::bytes_left, dcc_send::bytes_sent, dcc_send::connect_time, DCC_SEND_ACKS, DCC_SEND_BYTES_ACKED, DCC_SEND_CONNECT_TIME, DCC_SEND_CPS_SNAPSHOT, DCC_SEND_CPS_TOTAL, DCC_SEND_LEFT, DCC_SEND_REQUEST_TIME, DCC_SEND_SENT, now, dcc_send::request_time, dcc_send::snapshot_bytes, dcc_send::snapshot_counter, sockbuf_get_filter_data(), timer_get_now_sec(), and update_snapshot().
00441 { 00442 dcc_send_t *send; 00443 int i, n; 00444 long now; 00445 00446 if (!valueptr) 00447 return(-1); 00448 00449 if (sockbuf_get_filter_data(idx, &dcc_send_filter, &send) < 0) 00450 if (sockbuf_get_filter_data(idx, &dcc_recv_filter, &send) < 0) 00451 return(-1); 00452 00453 timer_get_now_sec(&now); 00454 switch (field) { 00455 case DCC_SEND_SENT: 00456 *(int *)valueptr = send->bytes_sent; 00457 break; 00458 case DCC_SEND_LEFT: 00459 *(int *)valueptr = send->bytes_left; 00460 break; 00461 case DCC_SEND_CPS_TOTAL: 00462 if (!send->connect_time) 00463 n = 0; 00464 else if (send->connect_time >= now) 00465 n = send->bytes_sent; 00466 else 00467 n = (int) ((float) send->bytes_sent / ((float) now - (float) send->connect_time)); 00468 *(int *)valueptr = n; 00469 break; 00470 case DCC_SEND_CPS_SNAPSHOT: 00471 update_snapshot(send, 0); 00472 /* When we calculate the total, we do not include 00473 * the current second (snapshot_counter) because more 00474 * data might be sent this second and our report won't 00475 * be accurate. */ 00476 n = 0; 00477 for (i = 0; i < 5; i++) { 00478 if (i != send->snapshot_counter) 00479 n += send->snapshot_bytes[i]; 00480 } 00481 if (now - send->connect_time >= 5) 00482 n = (int) ((float) n / 4.0); 00483 else if (now - send->connect_time > 1) 00484 n = (int) ((float) n / (float) (now - send->connect_time - 1)); 00485 else n = 0; 00486 *(int *)valueptr = n; 00487 break; 00488 case DCC_SEND_ACKS: 00489 *(int *)valueptr = send->acks; 00490 break; 00491 case DCC_SEND_BYTES_ACKED: 00492 *(int *)valueptr = send->bytes_acked; 00493 break; 00494 case DCC_SEND_REQUEST_TIME: 00495 *(int *)valueptr = send->request_time; 00496 break; 00497 case DCC_SEND_CONNECT_TIME: 00498 *(int *)valueptr = send->connect_time; 00499 break; 00500 default: 00501 return(-1); 00502 } 00503 return(0); 00504 }
static int dcc_send_read | ( | void * | client_data, | |
int | idx, | |||
char * | data, | |||
int | len | |||
) | [static] |
Definition at line 356 of file dcc.c.
References dcc_send::acks, and dcc_send::bytes_acked.
00357 { 00358 dcc_send_t *send = client_data; 00359 int ack; 00360 00361 memcpy(&ack, data, sizeof(int)); 00362 ack = ntohl(ack); 00363 send->acks++; 00364 send->bytes_acked = ack; 00365 00366 return(0); 00367 }
static int dcc_send_written | ( | void * | client_data, | |
int | idx, | |||
int | len, | |||
int | remaining | |||
) | [static] |
Definition at line 369 of file dcc.c.
References dcc_send::bytes_acked, dcc_send::bytes_left, dcc_send::bytes_sent, DCC_FILTER_LEVEL, dcc_send_bytes(), dcc_send_done(), sockbuf_isvalid(), sockbuf_on_written(), and update_snapshot().
00370 { 00371 dcc_send_t *send = client_data; 00372 int n; 00373 00374 /* Update stats on the send. */ 00375 send->bytes_sent += len; 00376 send->bytes_left -= len; 00377 update_snapshot(send, len); 00378 00379 /* Pass the event up to whoever's listening. */ 00380 00381 sockbuf_on_written(idx, DCC_FILTER_LEVEL, len, remaining); 00382 00383 if (!sockbuf_isvalid(idx)) 00384 return(0); 00385 00386 /* Send as much data as we can until we block. dcc_send_bytes() 00387 * returns -1 when the file has eof(). */ 00388 n = dcc_send_bytes(send); 00389 if (n == -1 && send->bytes_left <= 0 && send->bytes_acked >= send->bytes_sent) { 00390 dcc_send_done(send); 00391 } 00392 00393 return(0); 00394 }
int dcc_start_chat | ( | const char * | nick, | |
int | timeout | |||
) |
Definition at line 165 of file dcc.c.
References dcc_listen::client, current_server, dcc_listen(), dcc_send::idx, dcc_listen::port, printserv, dcc_listen::serv, SERVER_NORMAL, sockbuf_attach_filter(), and sockbuf_new().
00166 { 00167 dcc_listen_t *listen; 00168 int idx; 00169 00170 /* Create a listening idx to accept the chat connection. */ 00171 listen = dcc_listen(timeout); 00172 if (!listen) return(-1); 00173 00174 /* Create an empty sockbuf that will eventually be used for the 00175 * dcc chat (when they connect to us). */ 00176 idx = sockbuf_new(); 00177 sockbuf_attach_filter(idx, &dcc_chat_filter, (void *)listen->serv); 00178 listen->client = idx; 00179 00180 printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC CHAT chat %u %d%c", nick, 1, current_server.mylongip, listen->port, 1); 00181 return(idx); 00182 }
int dcc_start_send | ( | const char * | nick, | |
const char * | fname, | |||
int | timeout | |||
) |
Definition at line 256 of file dcc.c.
References dcc_send::bytes_left, dcc_send::bytes_sent, dcc_listen::client, current_server, dcc_listen(), dcc_send::fd, dcc_send::fname, dcc_send::idx, dcc_send::next, dcc_send::nick, dcc_listen::port, dcc_send::port, printserv, dcc_send::request_time, dcc_listen::serv, dcc_send::serv, SERVER_NORMAL, dcc_send::size, sockbuf_attach_filter(), sockbuf_new(), and timer_get_now_sec().
00257 { 00258 dcc_listen_t *listen; 00259 dcc_send_t *send; 00260 int idx, size, fd; 00261 char *quote, *slash; 00262 00263 fd = open(fname, O_RDONLY); 00264 if (!fd) 00265 return(-2); /* File could not be opened. */ 00266 00267 size = lseek(fd, 0, SEEK_END); 00268 lseek(fd, 0, SEEK_SET); 00269 00270 listen = dcc_listen(timeout); 00271 if (!listen) { 00272 close(fd); 00273 return(-1); 00274 } 00275 00276 /* Create an empty sockbuf that will eventually be used for the 00277 * dcc chat (when they connect to us). */ 00278 idx = sockbuf_new(); 00279 send = calloc(1, sizeof(*send)); 00280 sockbuf_attach_filter(idx, &dcc_send_filter, send); 00281 00282 listen->client = idx; 00283 send->next = dcc_send_head; 00284 dcc_send_head = send; 00285 send->serv = listen->serv; 00286 send->port = listen->port; 00287 send->fd = fd; 00288 send->idx = idx; 00289 send->size = size; 00290 send->bytes_sent = 0; 00291 send->bytes_left = size; 00292 timer_get_now_sec(&send->request_time); 00293 send->fname = strdup(fname); 00294 send->nick = strdup(nick); 00295 00296 slash = strrchr(fname, '/'); 00297 if (slash) 00298 fname = slash+1; 00299 00300 if (strchr(fname, ' ')) 00301 quote = "\""; 00302 else 00303 quote = ""; 00304 00305 printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC SEND %s%s%s %u %d %d%c", nick, 1, quote, fname, quote, 00306 current_server.mylongip, listen->port, size, 1); 00307 00308 return(idx); 00309 }
static void got_accept | ( | char * | nick, | |
char * | uhost, | |||
user_t * | u, | |||
char * | text | |||
) | [static] |
Definition at line 700 of file dcc.c.
References dcc_send::bytes_left, egg_reconnect(), dcc_send::fd, dcc_send::fname, dcc_send::idx, dcc_send::ip, dcc_send::next, dcc_send::nick, dcc_send::port, and dcc_send::resumed_at.
Referenced by got_dcc().
00701 { 00702 int port, pos, n; 00703 dcc_send_t *send; 00704 char *fname, *space; 00705 00706 fname = text; 00707 space = strrchr(text, ' '); 00708 if (space && space != text) pos = atoi(space+1); 00709 else return; 00710 *space = 0; 00711 space--; 00712 space = strrchr(text, ' '); 00713 if (space && space != text) port = atoi(space+1); 00714 else return; 00715 *space = 0; 00716 00717 for (send = dcc_recv_head; send; send = send->next) { 00718 if (send->port == port && !strcasecmp(send->nick, nick)) { 00719 n = lseek(send->fd, pos, SEEK_SET); 00720 send->bytes_left -= n; 00721 send->resumed_at = n; 00722 egg_reconnect(send->idx, send->ip, port, -1); 00723 break; 00724 } 00725 } 00726 }
static void got_chat | ( | char * | nick, | |
char * | uhost, | |||
user_t * | u, | |||
char * | text | |||
) | [static] |
Definition at line 650 of file dcc.c.
References bind_check(), BT_dcc_chat, user_setting_t::flags, dcc_send::ip, NULL, dcc_send::port, and user::settings.
00651 { 00652 char type[256], ip[256], port[32]; 00653 int nport; 00654 00655 type[0] = ip[0] = port[0] = 0; 00656 sscanf(text, "%255[^ ] %255[^ ] %31[^ ]", type, ip, port); 00657 type[255] = ip[255] = port[31] = 0; 00658 00659 /* Check if the ip is 'new-style' (dotted decimal or ipv6). If not, 00660 * it's the old-style long ip. */ 00661 if (!strchr(ip, '.') && !strchr(ip, ':')) { 00662 unsigned long longip; 00663 longip = strtoul(ip, NULL, 10); 00664 snprintf(ip, sizeof(ip), "%lu.%lu.%lu.%lu", (longip >> 24) & 255, (longip >> 16) & 255, (longip >> 8) & 255, (longip) & 255); 00665 } 00666 00667 nport = atoi(port); 00668 00669 bind_check(BT_dcc_chat, u ? &u->settings[0].flags : NULL, nick, nick, uhost, u, type, ip, nport); 00670 }
static int got_dcc | ( | char * | nick, | |
char * | uhost, | |||
user_t * | u, | |||
char * | dest, | |||
char * | cmd, | |||
char * | text | |||
) | [static] |
Definition at line 765 of file dcc.c.
References got_accept(), got_chat(), got_resume(), and got_send().
00766 { 00767 if (!strncasecmp(text, "chat ", 5)) { 00768 got_chat(nick, uhost, u, text+5); 00769 } 00770 else if (!strncasecmp(text, "send ", 5)) { 00771 got_send(nick, uhost, u, text+5); 00772 } 00773 else if (!strncasecmp(text, "resume ", 7)) { 00774 got_resume(nick, uhost, u, text+7); 00775 } 00776 else if (!strncasecmp(text, "accept ", 7)) { 00777 got_accept(nick, uhost, u, text+7); 00778 } 00779 return(0); 00780 }
static void got_resume | ( | char * | nick, | |
char * | uhost, | |||
user_t * | u, | |||
char * | text | |||
) | [static] |
Definition at line 672 of file dcc.c.
References dcc_send::bytes_left, dcc_send::fd, dcc_send::fname, dcc_send::next, dcc_send::nick, dcc_send::port, printserv, dcc_send::resumed_at, and SERVER_NORMAL.
Referenced by got_dcc().
00673 { 00674 int port, pos, n; 00675 dcc_send_t *send; 00676 char *fname, *space; 00677 00678 fname = text; 00679 space = strrchr(text, ' '); 00680 if (space && space != text) pos = atoi(space+1); 00681 else return; 00682 *space = 0; 00683 space--; 00684 space = strrchr(text, ' '); 00685 if (space && space != text) port = atoi(space+1); 00686 else return; 00687 *space = 0; 00688 00689 for (send = dcc_send_head; send; send = send->next) { 00690 if (send->port == port && !strcasecmp(send->nick, nick)) { 00691 n = lseek(send->fd, pos, SEEK_SET); 00692 send->bytes_left -= n; 00693 send->resumed_at = n; 00694 printserv(SERVER_NORMAL, "PRIVMSG %s :%cDCC ACCEPT %s %d %d%c", nick, 1, fname, port, n, 1); 00695 break; 00696 } 00697 } 00698 }
static void got_send | ( | char * | nick, | |
char * | uhost, | |||
user_t * | u, | |||
char * | text | |||
) | [static] |
Definition at line 728 of file dcc.c.
References bind_check(), BT_dcc_recv, user_setting_t::flags, dcc_send::fname, dcc_send::ip, NULL, dcc_send::port, user::settings, and dcc_send::size.
Referenced by got_dcc().
00729 { 00730 char *space, *fname, ip[256]; 00731 int port, size, n; 00732 00733 fname = text; 00734 space = strrchr(text, ' '); 00735 if (!space || space == text) return; 00736 size = atoi(space+1); 00737 *space-- = 0; 00738 space = strrchr(text, ' '); 00739 if (!space || space == text) return; 00740 port = atoi(space+1); 00741 *space-- = 0; 00742 space = strchr(text, ' '); 00743 if (!space || space == text) return; 00744 strlcpy(ip, space + 1, sizeof ip); 00745 *space = 0; 00746 00747 if (*fname == '"') { 00748 fname++; 00749 n = strlen(fname); 00750 if (n && fname[n-1] == '"') fname[n-1] = 0; 00751 else return; 00752 } 00753 /* Check if the ip is new-style (dotted decimal or ipv6). If not, 00754 * it's the old-style long ip. */ 00755 if (!strchr(ip, '.') && !strchr(ip, ':')) { 00756 unsigned int longip; 00757 longip = (unsigned int) atol(ip); 00758 sprintf(ip, "%d.%d.%d.%d", (longip >> 24) & 255, (longip >> 16) & 255, (longip >> 8) & 255, (longip) & 255); 00759 } 00760 00761 bind_check(BT_dcc_recv, u ? &u->settings[0].flags : NULL, nick, nick, uhost, u, fname, ip, port, size); 00762 }
static void update_snapshot | ( | dcc_send_t * | send, | |
int | len | |||
) | [static] |
Definition at line 629 of file dcc.c.
References dcc_send::last_snapshot, NULL, dcc_send::snapshot_bytes, dcc_send::snapshot_counter, and timer_get_now_sec().
Referenced by dcc_recv_read(), dcc_send_bytes(), dcc_send_info(), and dcc_send_written().
00630 { 00631 int diff; 00632 int i; 00633 00634 /* Get time diff. */ 00635 diff = timer_get_now_sec(NULL) - send->last_snapshot; 00636 timer_get_now_sec(&send->last_snapshot); 00637 if (diff > 5) diff = 5; 00638 00639 /* Reset counter for seconds that were skipped. */ 00640 for (i = 0; i < diff; i++) { 00641 send->snapshot_counter++; 00642 if (send->snapshot_counter >= 5) send->snapshot_counter = 0; 00643 send->snapshot_bytes[send->snapshot_counter] = 0; 00644 } 00645 00646 /* Add the bytes to the current second. */ 00647 send->snapshot_bytes[send->snapshot_counter] += len; 00648 }
sockbuf_filter_t dcc_chat_filter [static] |
Initial value:
{ "DCC chat", DCC_FILTER_LEVEL, dcc_chat_connect, dcc_chat_eof, NULL, NULL, NULL, NULL, NULL, dcc_chat_delete }
sockbuf_handler_t dcc_listen_handler [static] |
Initial value:
{ "DCC listen", NULL, NULL, dcc_listen_newclient, NULL, NULL }
sockbuf_filter_t dcc_recv_filter [static] |
Initial value:
{ "DCC get", DCC_FILTER_LEVEL, dcc_recv_connect, dcc_recv_eof, NULL, dcc_recv_read, NULL, NULL, NULL, dcc_recv_delete }
dcc_send_t* dcc_recv_head = NULL [static] |
sockbuf_filter_t dcc_send_filter [static] |
Initial value:
{ "DCC send", DCC_FILTER_LEVEL, dcc_send_connect, dcc_send_eof, NULL, dcc_send_read, NULL, dcc_send_written, NULL, dcc_send_delete }
dcc_send_t* dcc_send_head = NULL [static] |
const char rcsid[] = "$Id: dcc.c,v 1.27 2007-09-13 22:20:57 sven Exp $" [static] |