/* * Create a new struct Client structure and set it to initial state. * * from == NULL, create local client (a client connected to a socket). * * from != NULL, create remote client (behind a socket associated with * the client defined by 'from'). * ('from' is a local client!!). */ struct Client* make_client(struct Client *from, int status) { struct Client* cptr = 0; struct Connection* con = 0; assert(!from || cli_verify(from)); cptr = alloc_client(); assert(0 != cptr); assert(!cli_magic(cptr)); assert(0 == from || 0 != cli_connect(from)); if (!from) { /* local client, allocate a struct Connection */ con = alloc_connection(); assert(0 != con); assert(!con_magic(con)); con_magic(con) = CONNECTION_MAGIC; con_fd(con) = -1; /* initialize struct Connection */ con_freeflag(con) = 0; con_nextnick(con) = CurrentTime - NICK_DELAY; con_nexttarget(con) = CurrentTime - (TARGET_DELAY * (STARTTARGETS - 1)); con_handler(con) = UNREGISTERED_HANDLER; con_client(con) = cptr; cli_local(cptr) = 1; /* Set certain fields of the struct Client */ cli_since(cptr) = cli_lasttime(cptr) = cli_firsttime(cptr) = CurrentTime; cli_lastnick(cptr) = TStime(); } else con = cli_connect(from); /* use 'from's connection */ assert(0 != con); assert(con_verify(con)); cli_magic(cptr) = CLIENT_MAGIC; cli_connect(cptr) = con; /* set the connection and other fields */ cli_status(cptr) = status; cli_hnext(cptr) = cptr; strcpy(cli_username(cptr), "unknown"); return cptr; }
/** * Creates a proxy_connection if a client wants to connect * * @access public * @param fd_set *master * @param connection_context *ctx * @param int hListen * @return int newsocket */ int create_proxy_connection(fd_set *master, connection_context *ctx, int hListen) { struct sockaddr_in remoteaddr; proxy_connection *conn; int addrlen; int newfd; addrlen= sizeof (remoteaddr); if (-1 == (newfd= accept(hListen, (struct sockaddr *)&remoteaddr, &addrlen))) { ERR("Could not accept new connection"); return -1; } alloc_connection(&conn); conn->hClient= newfd; add_connection(ctx, conn); /* Add socket to fdset */ FD_SET (newfd, master); _dump_context (ctx); LOG("New client connected"); return newfd; }
void do_with_listen(struct worker_context *ctx, netresult_t result) { if ( NET_OP_NOTIFY == result._op_type ) { WARNING("listen fd[%d] error.", g_listen_fd); return ; } int err; int sock; int avg_conn; struct sockaddr_in addr; socklen_t addrlen; struct connection *conn; while (1) { avg_conn = atomic_read(&g_active_conn_num) / atomic_read(&g_worker_num); if ( ctx->_active_conn_num >= avg_conn + WORKER_CONN_NUM_DELTA ) { DEBUG("drop accept ignore unbalance, avg conn num[%d], worker[%d] active conn num[%d].", avg_conn, ctx->_wid, ctx->_active_conn_num); break; } addrlen = sizeof(addr); sock = accept(g_listen_fd, (struct sockaddr *)&addr, &addrlen); if ( sock < 0 ) { err = errno; if ( EINTR == err ) { continue; } else if ( EAGAIN == err ) { return ; } else if ( EMFILE == err || ENFILE == err ) { atomic_add(1, &g_conn_nofile_err_num); } else if ( ENOBUFS == err || ENOMEM == err ) { atomic_add(1, &g_conn_nomem_err_num); } else if ( ECONNABORTED == err ) { atomic_add(1, &g_conn_aborted_err_num); } else { atomic_add(1, &g_conn_other_err_num); } WARNING("accept ret error[%s] on fd[%d].", strerror_t(err), g_listen_fd); return ; } else if ( atomic_read(&g_active_conn_num) > g_conf._max_active_conn_num ) { atomic_add(1, &g_conn_denied_by_limit_num); SAFE_CLOSE(sock); WARNING("deny connection, too many active connections[> %d].", g_conf._max_active_conn_num); } else { atomic_add(1, &g_active_conn_num); conn = alloc_connection(ctx); if ( NULL != conn ) { conn->_client._fd = sock; if ( NULL == inet_ntop(AF_INET, &addr.sin_addr, conn->_client._ip_str, sizeof(conn->_client._ip_str)) ) { WARNING("inet_ntop error[%s], addr[%X].", strerror_t(errno), *(int *)&addr.sin_addr); conn->_client._ip_str[0] = '\0'; } if ( epex_attach(ctx->_epoll, sock, conn, g_conf._client_connection_timeout) ) { if ( epex_read_any(ctx->_epoll, sock, conn->_client._header, MAX_HTTP_HEADER_LEN, NULL, g_conf._client_read_timeout) ) { DEBUG("worker[%d] accept connection[%d][%p] ok.", ctx->_wid, sock, conn); ++ctx->_active_conn_num; continue; } else { WARNING("failed to submit read request."); epex_detach(ctx->_epoll, sock, NULL); free_connection(ctx, conn); SAFE_CLOSE(sock); } } else { WARNING("failed to attach sock[%d] to epoll.", sock); free_connection(ctx, conn); SAFE_CLOSE(sock); } } else { WARNING("failed to alloc connection."); } atomic_add(-1, &g_active_conn_num); } } }
/* process_packet: * Callback which processes a packet captured by libpcap. */ void process_packet(u_char *user, const struct pcap_pkthdr *hdr, const u_char *pkt) { struct tcphdr tcp; int off, len, delta; connection *C, c; struct sockaddr_storage src, dst; struct sockaddr *s, *d; uint8_t proto; s = (struct sockaddr *)&src; d = (struct sockaddr *)&dst; if (handle_link_layer(&datalink_info, pkt, hdr->caplen, &proto, &off)) return; if (layer3_find_tcp(pkt, proto, &off, s, d, &tcp)) return; len = hdr->caplen - off; /* XXX fragmented packets and other nasties. */ /* try to find the connection slot associated with this. */ C = find_connection(s, d); /* no connection at all, so we need to allocate one. */ if (!C) { log_msg(LOG_INFO, "new connection: %s", connection_string(s,d)); C = alloc_connection(); *C = connection_new(s, d); /* This might or might not be an entirely new connection (SYN flag * set). Either way we need a sequence number to start at. */ (*C)->isn = ntohl(tcp.th_seq); } /* Now we need to process this segment. */ c = *C; delta = 0;/*tcp.syn ? 1 : 0;*/ /* NB (STD0007): * SEG.LEN = the number of octets occupied by the data in the * segment (counting SYN and FIN) */ #if 0 if (tcp.syn) /* getting a new isn. */ c->isn = htonl(tcp.seq); #endif if (tcp.th_flags & TH_RST) { /* Looks like this connection is bogus, and so might be a * connection going the other way. */ log_msg(LOG_INFO, "connection reset: %s", connection_string(s, d)); connection_delete(c); *C = NULL; if ((C = find_connection(d, s))) { connection_delete(*C); *C = NULL; } return; } if (len > 0) { /* We have some data in the packet. If this data occurred after * the first data we collected for this connection, then save it * so that we can look for images. Otherwise, discard it. */ unsigned int offset; offset = ntohl(tcp.th_seq); /* Modulo 2**32 arithmetic; offset = seq - isn + delta. */ if (offset < (c->isn + delta)) offset = 0xffffffff - (c->isn + delta - offset); else offset -= c->isn + delta; if (offset > c->len + WRAPLEN) { /* Out-of-order packet. */ log_msg(LOG_INFO, "out of order packet: %s", connection_string(s, d)); } else { connection_push(c, pkt + off, offset, len); extract_media(c); } } if (tcp.th_flags & TH_FIN) { /* Connection closing; mark it as closed, but let sweep_connections * free it if appropriate. */ log_msg(LOG_INFO, "connection closing: %s, %d bytes transferred", connection_string(s, d), c->len); c->fin = 1; } /* sweep out old connections */ sweep_connections(); }