I am writing a socks4 proxy in C and everything works well, like I tested the data forwarding with a simple echo server as the remote peer.
But now I am not sure how to handle the data if the other protocols are used as they have different package sizes.
How do I know if the transmission is complete or how do I have to handle that everything is transmitted properly to the remote peer and vice versa to the client?
Here is my thread connection handler function:
// Contains the client socket and remote peer socket after successful connect:
typedef struct socks_connection {
    int client_sock;
    int target_sock;
} socks_connection;
void *socks_connection_thread(void *sockets) {
    printf("Thread started\n");
    socks_connection conn = *(socks_connection*) sockets;
    uint8_t buf[512];
    int rbytes;
    int wbytes;
    for(;;) {
        rbytes = recv(conn.client_sock, buf, sizeof(buf), 0);
        printf("read: %d\n", rbytes);
        if(rbytes < 0) {
            perror("read");
        }
        wbytes = send(conn.target_sock, buf, rbytes, 0);
        printf("send: %d\n", wbytes);
        if(rbytes < 0) {
            perror("send");
        }
        rbytes = recv(conn.target_sock, buf, sizeof(buf), 0);
        if(rbytes < 0) {
            perror("read");
        }
        printf("read: %d\n", rbytes);
        wbytes = send(conn.client_sock, buf, rbytes, 0);
        printf("send: %d\n", wbytes);
        if(rbytes < 0) {
            perror("send");
        }
    }
}
EDIT: I am trying to use poll() instead of select() and I want to know if it is normal for poll to use less code and additional work like i.e. FD_SET, FD_ISSET etc.
#define MAX_SOCKETS 2
#define DEFAULT_TIMEOUT (3 * 60 * 1000)
#define CLIENT_POLL 0
#define REMOTE_POLL 1
void *socks_connection_thread(void *pipefd) {
    pthread_detach(pthread_self());
    socks_connection *conn = pipefd;
    int rc = 0;
    int timeout = DEFAULT_TIMEOUT;
    struct pollfd pfds[MAX_SOCKETS];
    nfds_t nfds = MAX_SOCKETS;
    uint8_t client_buf[1024];
    size_t client_buf_size = 0;
    uint8_t target_buf[1024];
    size_t target_buf_size = 0;
    
    ssize_t num_bytes;
    memset(&pfds, 0, sizeof(pfds));
    
    int opt = 1;
    ioctl(conn->client_sock, FIONBIO, &opt);
    ioctl(conn->target_sock, FIONBIO, &opt);
    pfds[CLIENT_POLL].fd = conn->client_sock;
    pfds[CLIENT_POLL].events = POLLIN;
    pfds[REMOTE_POLL].fd = conn->target_sock;
    pfds[REMOTE_POLL].events = POLLIN;
    for(;;) {
        if(socksshutdown) break;
        /* waiting for some events */
        rc = poll(pfds, MAX_SOCKETS, timeout);
        if(rc < 0) {
            fprintf(stderr, "poll() failed: %s\n", strerror(errno));
            break;
        }
        if(rc == 0) {
            fprintf(stderr, "poll() timed out. End Connection\n");
            break;
        }
        /* there is something to read form the client side */
        if(pfds[CLIENT_POLL].revents & POLLIN)
        {
            num_bytes = readFromSocket(conn->client_sock, client_buf, sizeof(client_buf));
            if(num_bytes < 0) break; // client connection lost
            if(num_bytes > 0) {
                printf("read from client: %s (%ld)\n", client_buf, num_bytes);
                client_buf_size += num_bytes;
            }
            num_bytes = sendToSocket(conn->target_sock, client_buf, num_bytes);
            if(num_bytes < 0) break;
            if(num_bytes > 0) {
                printf("forward to remote peer: %s (%ld)\n", client_buf, num_bytes);
            }
            pfds[CLIENT_POLL].revents = 0;
        }
        /* there is something to read from the remote side */
        else if(pfds[REMOTE_POLL].revents & POLLIN)
        {
            //printf("Got data from remote.\n");
            num_bytes = readFromSocket(conn->target_sock, target_buf, sizeof(target_buf));
            if (num_bytes < 0) break; // remote connection lost
            if (num_bytes > 0) {
                printf("read from client: %s (%ld)\n", target_buf, num_bytes);
                target_buf_size += num_bytes;
            }
            num_bytes = sendToSocket(conn->client_sock, target_buf, target_buf_size);
                if (num_bytes < 0) break;
                if (num_bytes > 0) {
                    printf("forward to client: %s (%ld)\n", target_buf, num_bytes);
                    // remove the sent bytes...
                } 
            pfds[REMOTE_POLL].revents = 0;
        } else {
            // unexpected event result appeared so close the connection
            break;
        }
    }
    // all done
    close(conn->client_sock);
    close(conn->target_sock);
    printf("Thread terminating\n");
}
 
    