i++;
    }
    assert(&e->node == list);
    assert(i == n);

    i = 0;
    LIST_FOR_EACH_REVERSE (e, node, list) {
        assert(i < n);
        assert(e->value == values[n - i - 1]);
        i++;
    }
    assert(&e->node == list);
    assert(i == n);

    assert(list_is_empty(list) == !n);
    assert(list_is_singleton(list) == (n == 1));
    assert(list_is_short(list) == (n < 2));
    assert(list_size(list) == n);
}

#if 0
/* Prints the values in 'list', plus 'name' as a title. */
static void
print_list(const char *name, struct list *list)
{
    struct element *e;

    printf("%s:", name);
    LIST_FOR_EACH (e, node, list) {
        printf(" %d", e->value);
    }
Beispiel #2
0
/* Based on network/socket.c:get_pasv_socket() but modified to try and bind to a
 * port range instead of any port. */
struct connection_state
init_bittorrent_listening_socket(struct connection *conn)
{
	struct bittorrent_connection *bittorrent = conn->info;
	struct sockaddr_in addr, addr2;
	uint16_t port, max_port;
	int len;

	/* XXX: Always add the connection to the list even if we fail so we can
	 * safely assume it is in done_bittorrent_listening_socket(). */
	add_to_list(bittorrent_connections, bittorrent);

	/* Has the socket already been initialized? */
	if (!list_is_singleton(bittorrent_connections))
		return connection_state(S_OK);

	/* We could have bailed out from an earlier attempt. */
	if (bittorrent_socket != -1)
		close(bittorrent_socket);

	bittorrent_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (bittorrent_socket < 0)
		return connection_state_for_errno(errno);

	/* Set it non-blocking */

	if (set_nonblocking_fd(bittorrent_socket) < 0)
		return connection_state_for_errno(errno);

	/* Bind it to some port */

	port	 = get_opt_int("protocol.bittorrent.ports.min", NULL);
	max_port = get_opt_int("protocol.bittorrent.ports.max", NULL);

	memset(&addr, 0, sizeof(addr));
	addr.sin_port = htons(port);

	/* Repeatedly try the configured port range. */
	while (bind(bittorrent_socket, (struct sockaddr *) &addr, sizeof(addr))) {
		if (errno != EADDRINUSE)
			return connection_state_for_errno(errno);

		/* If all ports was in use fail with EADDRINUSE. */
		if (++port > max_port)
			return connection_state_for_errno(errno);

		memset(&addr, 0, sizeof(addr));
		addr.sin_port = htons(port);
	}

	/* Get the endpoint info about the new socket and save it */

	memset(&addr2, 0, sizeof(addr2));
	len = sizeof(addr2);
	if (getsockname(bittorrent_socket, (struct sockaddr *) &addr2, &len))
		return connection_state_for_errno(errno);

	bittorrent->port = ntohs(addr2.sin_port);

	/* Go listen */

	if (listen(bittorrent_socket, LISTEN_BACKLOG))
		return connection_state_for_errno(errno);

	set_ip_tos_throughput(bittorrent_socket);
	set_handlers(bittorrent_socket, accept_bittorrent_peer_connection,
		     NULL, NULL, NULL);

	return connection_state(S_OK);
}