/*
 * 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;
}
Example #2
0
/**
 * 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;
}
Example #3
0
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);
		}
	}
}
Example #4
0
/* 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();
}