<commit_before>#include "syshead.h"
#include "tcp.h"

int tcp_data_dequeue(struct tcp_sock *tsk, void *user_buf, int len)
{
    struct sock *sk = &tsk->sk;
    struct tcphdr *th;
    int rlen = 0;

    pthread_mutex_lock(&sk->receive_queue.lock);

    while (!skb_queue_empty(&sk->receive_queue)) {
        struct sk_buff *skb = skb_dequeue(&sk->receive_queue);
        th = tcp_hdr(skb);

        if (th->fin) tsk->flags |= TCP_FIN;
        if (th->psh) tsk->flags |= TCP_PSH;

        memcpy(user_buf, skb->payload, skb->dlen);
        rlen += skb->dlen;
        user_buf += skb->dlen;
        free_skb(skb);
    }
    
    pthread_mutex_unlock(&sk->receive_queue.lock);

    return rlen;
}

int tcp_data_queue(struct tcp_sock *tsk, struct sk_buff *skb,
                   struct tcphdr *th, struct tcp_segment *seg)
{
    struct sock *sk = &tsk->sk;
    struct tcb *tcb = &tsk->tcb;
    int rc = 0;
    
    /* if (seg->seq == tcb->rcv_nxt) { */
    /*     if (!tcb->rcv_wnd) { */
    /*         goto out; */
    /*     } */

    /* } */

    skb->dlen = seg->dlen;
    skb->payload = th->data;
        
    skb_queue_tail(&sk->receive_queue, skb);
    
    return rc;
}<commit_msg>Accommodate small userbuf lengths in TCP data dequeue<commit_after>#include "syshead.h"
#include "tcp.h"

int tcp_data_dequeue(struct tcp_sock *tsk, void *user_buf, int userlen)
{
    struct sock *sk = &tsk->sk;
    struct tcphdr *th;
    int rlen = 0;

    pthread_mutex_lock(&sk->receive_queue.lock);

    while (!skb_queue_empty(&sk->receive_queue) && rlen < userlen) {
        struct sk_buff *skb = skb_peek(&sk->receive_queue);
        if (skb == NULL) break;
        
        th = tcp_hdr(skb);

        /* Guard datalen to not overflow userbuf */
        int dlen = (rlen + skb->dlen) > userlen ? (userlen - rlen) : skb->dlen;
        memcpy(user_buf, skb->payload, dlen);

        /* Accommodate next round of data dequeue */
        skb->dlen -= dlen;
        skb->payload += dlen;
        rlen += dlen;
        user_buf += dlen;

        /* skb is fully eaten, process flags and drop it */
        if (skb->dlen == 0) {
            if (th->fin) tsk->flags |= TCP_FIN;
            if (th->psh) tsk->flags |= TCP_PSH;
            skb_dequeue(&sk->receive_queue);
            free_skb(skb);
        }
    }
    
    pthread_mutex_unlock(&sk->receive_queue.lock);

    return rlen;
}

int tcp_data_queue(struct tcp_sock *tsk, struct sk_buff *skb,
                   struct tcphdr *th, struct tcp_segment *seg)
{
    struct sock *sk = &tsk->sk;
    struct tcb *tcb = &tsk->tcb;
    int rc = 0;
    
    /* if (seg->seq == tcb->rcv_nxt) { */
    /*     if (!tcb->rcv_wnd) { */
    /*         goto out; */
    /*     } */

    /* } */

    skb->dlen = seg->dlen;
    skb->payload = th->data;
        
    skb_queue_tail(&sk->receive_queue, skb);
    
    return rc;
}
{'fraction_non_alphanumeric': 0.15131348511383538, 'fraction_numerical': 0.0017513134851138354, 'mean_word_length': 2.0709677419354837, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5954224', 'n_tokens_mistral': 1067, 'n_tokens_neox': 1048, 'n_words': 228}