Esempio n. 1
0
void *tcp_server(void *arg) {
    sock_t *s = (sock_t *) arg;
    int i,fd,try_to_read,received;
    struct tcp_client *clients,*client;
    struct pollfd *pfds = NULL;
    volatile nfds_t nfds;
    setnonblocking(s->socket);

    nfds = 1;
    pfds = mallocz_or_die(nfds * sizeof(struct pollfd));
    pfds->fd = s->socket;
    pfds->events = POLLIN;
    clients = NULL;
    RELAY_ATOMIC_AND( RECEIVED_STATS.active_connections, 0);
    int rc;
    for (;;) {
        rc = poll(pfds,nfds,CONFIG.polling_interval_ms);
        if (rc == -1) {
            if (rc == EINTR)
                continue;
            WARN_ERRNO("poll");
            goto out;
        }
        for (i = 0; i < nfds; i++) {
            if (!pfds[i].revents)
                continue;
            if (pfds[i].fd == s->socket) {
                fd = accept(s->socket, NULL, NULL);
                if (fd == -1) {
                    WARN_ERRNO("accept");
                    goto out;
                }
                setnonblocking(fd);
                RELAY_ATOMIC_INCREMENT( RECEIVED_STATS.active_connections, 1 );
                pfds = realloc_or_die(pfds, (nfds + 1) * sizeof(*pfds));
                clients = realloc_or_die(clients,(nfds + 1) * sizeof(*clients));

                clients[nfds].pos = 0;
                clients[nfds].buf = mallocz_or_die(ASYNC_BUFFER_SIZE);
//                WARN("[%d] CREATE %p fd: %d",i,clients[nfds].buf,fd);
                pfds[nfds].fd  = fd;
                pfds[nfds].events = POLLIN;
                pfds[nfds].revents = 0;
                nfds++;
            } else {
                client = &clients[i];
                try_to_read = ASYNC_BUFFER_SIZE - client->pos; // try to read as much as possible
                if (try_to_read <= 0) {
                    WARN("disconnecting, try to read: %d, pos: %d", try_to_read, client->pos);
                    goto disconnect;
                }
                received = recv(pfds[i].fd, client->buf + client->pos, try_to_read,0);
                if (received <= 0) {
                    if (received == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
                        continue;

                disconnect:
                    shutdown(pfds[i].fd,SHUT_RDWR);
                    close(pfds[i].fd);
//                    WARN("[%d] DESTROY %p %d %d fd: %d vs %d",i,client->buf,client->x,i,pfds[i].fd,client->fd);
                    free(client->buf);

                    // shft left
                    memcpy(pfds + i,pfds + i + 1, (nfds - i - 1) * sizeof(struct pollfd));
                    memcpy(clients + i,clients + i + 1, (nfds - i - 1) * sizeof(struct tcp_client));

                    nfds--;
                    pfds = realloc_or_die(pfds, nfds * sizeof(struct pollfd));
                    clients = realloc_or_die(clients, nfds * sizeof(struct tcp_client));
                    RELAY_ATOMIC_DECREMENT( RECEIVED_STATS.active_connections, 1 );
                    continue;
                }
                client->pos += received;

            try_to_consume_one_more:

                if (client->pos < EXPECTED_HEADER_SIZE)
                    continue;

                if (EXPECTED(client) > MAX_CHUNK_SIZE) {
                    WARN("received frame (%d) > MAX_CHUNK_SIZE(%d)",EXPECTED(client),MAX_CHUNK_SIZE);
                    goto disconnect;
                }
                if (client->pos >= EXPECTED(client) + EXPECTED_HEADER_SIZE) {
                    buf_to_blob_enqueue(client->buf,EXPECTED(client));

                    client->pos -= EXPECTED(client) + EXPECTED_HEADER_SIZE;
                    if (client->pos < 0) {
                        WARN("BAD PACKET wrong 'next' position(< 0) pos: %d expected packet size:%d header_size: %d",
                             client->pos, EXPECTED(client),EXPECTED_HEADER_SIZE);
                        goto disconnect;
                    }
                    if (client->pos > 0) {
                        // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                                                                     ^ pos(12)
                        // after we remove the first packet + header it becomes:
                        // [ h ] [ h ] [ h ] [ h ] [ D ] [ D ] [ D ] [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                           ^ pos (5)
                        // and then we copy from header + data, to position 0, 5 bytes
                        //
                        // [ h ] [ h ] [ h ] [ h ] [ D ]
                        //                           ^ pos (5)
                        memmove(client->buf,
                                client->buf + EXPECTED_HEADER_SIZE + EXPECTED(client),
                                client->pos);
                        if (client->pos >= EXPECTED_HEADER_SIZE)
                            goto try_to_consume_one_more;
                    }
                }
            }
        }
    }
out:
    for (i = 0; i < nfds; i++) {
        if (pfds[i].fd != s->socket)
            free(clients[i].buf);
        shutdown(pfds[i].fd, SHUT_RDWR);
        close(pfds[i].fd);
    }
    free(pfds);
    free(clients);
    set_aborted();
    pthread_exit(NULL);
}
Esempio n. 2
0
void unset_abort_bits(uint32_t v) {
    v= ~v;
    RELAY_ATOMIC_AND(ABORT, v);
}