예제 #1
0
void process_data (PacketProtoDecoder *enc)
{
    int was_error = 0;
    
    do {
        uint8_t *data = enc->buf + enc->buf_start;
        int left = enc->buf_used;
        
        // check if header was received
        if (left < sizeof(struct packetproto_header)) {
            break;
        }
        struct packetproto_header header;
        memcpy(&header, data, sizeof(header));
        data += sizeof(struct packetproto_header);
        left -= sizeof(struct packetproto_header);
        int data_len = ltoh16(header.len);
        
        // check data length
        if (data_len > enc->output_mtu) {
            BLog(BLOG_NOTICE, "error: packet too large");
            was_error = 1;
            break;
        }
        
        // check if whole packet was received
        if (left < data_len) {
            break;
        }
        
        // update buffer
        enc->buf_start += sizeof(struct packetproto_header) + data_len;
        enc->buf_used -= sizeof(struct packetproto_header) + data_len;
        
        // submit packet
        PacketPassInterface_Sender_Send(enc->output, data, data_len);
        return;
    } while (0);
    
    if (was_error) {
        // reset buffer
        enc->buf_start = 0;
        enc->buf_used = 0;
    } else {
        // if we reached the end of the buffer, wrap around to allow more data to be received
        if (enc->buf_start + enc->buf_used == enc->buf_size) {
            memmove(enc->buf, enc->buf + enc->buf_start, enc->buf_used);
            enc->buf_start = 0;
        }
    }
    
    // receive data
    StreamRecvInterface_Receiver_Recv(enc->input, enc->buf + (enc->buf_start + enc->buf_used), enc->buf_size - (enc->buf_start + enc->buf_used));
    
    // if we had error, report it
    if (was_error) {
        enc->handler_error(enc->user);
        return;
    }
}
예제 #2
0
int main ()
{
    int ret = 1;
    
    BLog_InitStdout();
    
    // init network
    if (!BNetwork_GlobalInit()) {
        fprintf(stderr, "BNetwork_GlobalInit failed\n");
        goto fail1;
    }
    
    // init reactor (event loop)
    if (!BReactor_Init(&reactor)) {
        fprintf(stderr, "BReactor_Init failed\n");
        goto fail1;
    }
    
    // init signal handling
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGINT);
    sigaddset(&set, SIGTERM);
    if (!BUnixSignal_Init(&usignal, &reactor, set, signal_handler, NULL)) {
        fprintf(stderr, "BUnixSignal_Init failed\n");
        goto fail2;
    }
    
    // init BConnection object backed by the stdin fd
    if (!BConnection_Init(&pipe_con, BCONNECTION_SOURCE_PIPE(0), &reactor, NULL, connection_handler)) {
        fprintf(stderr, "BConnection_Init failed\n");
        goto fail3;
    }
    
    // init connection receive interface
    BConnection_RecvAsync_Init(&pipe_con);
    source_if = BConnection_RecvAsync_GetIf(&pipe_con);
    
    // init receive done callback
    StreamRecvInterface_Receiver_Init(source_if, input_handler_done, NULL);
    
    // receive first chunk
    StreamRecvInterface_Receiver_Recv(source_if, buf, BUF_SIZE);
    
    // run event loop
    ret = BReactor_Exec(&reactor);
    
    BConnection_RecvAsync_Free(&pipe_con);
    BConnection_Free(&pipe_con);
fail3:
    BUnixSignal_Free(&usignal, 0);
fail2:
    BReactor_Free(&reactor);
fail1:
    BLog_Free();
    DebugObjectGlobal_Finish();
    return ret;
}
예제 #3
0
static void input_handler_done (void *user, int data_len)
{
    // receive next chunk
    StreamRecvInterface_Receiver_Recv(source_if, buf, BUF_SIZE);
    
    // print this chunk
    buf[data_len] = '\0';
    printf("Received: '%s'\n", buf);
}
static PRInt32 method_read (PRFileDesc *fd, void *buf, PRInt32 amount)
{
    struct BSSLConnection_backend *b = (struct BSSLConnection_backend *)fd->secret;
    ASSERT(amount > 0)
    
    if (b->threadwork_state != THREADWORK_STATE_NONE) {
        BMutex_Lock(&b->recv_buf_mutex);
    }
    
    // if we are receiving into buffer or buffer has no data left, refuse recv
    if (b->recv_busy || b->recv_pos == b->recv_len) {
        if (b->threadwork_state != THREADWORK_STATE_NONE) {
            b->threadwork_want_recv = 1;
            BMutex_Unlock(&b->recv_buf_mutex);
        } else {
            // start receiving if not already
            if (!b->recv_busy) {
                // set recv busy
                b->recv_busy = 1;
                
                // receive into buffer
                StreamRecvInterface_Receiver_Recv(b->recv_if, b->recv_buf, BSSLCONNECTION_BUF_SIZE);
            }
        }
        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
        return -1;
    }
    
    // limit amount to available data
    if (amount > b->recv_len - b->recv_pos) {
        amount = b->recv_len - b->recv_pos;
    }
    
    // copy data
    memcpy(buf, b->recv_buf + b->recv_pos, amount);
    
    // update buffer
    b->recv_pos += amount;
    
    if (b->threadwork_state != THREADWORK_STATE_NONE) {
        BMutex_Unlock(&b->recv_buf_mutex);
    }
    
    return amount;
}
예제 #5
0
static void input_handler_done (SingleStreamReceiver *o, int data_len)
{
    DebugObject_Access(&o->d_obj);
    ASSERT(data_len > 0)
    ASSERT(data_len <= o->packet_len - o->pos)
    
    // update position
    o->pos += data_len;
    
    // if everything was received, notify user
    if (o->pos == o->packet_len) {
        DEBUGERROR(&o->d_err, o->handler(o->user));
        return;
    }
    
    // receive more
    StreamRecvInterface_Receiver_Recv(o->input, o->packet + o->pos, o->packet_len - o->pos);
}
예제 #6
0
int PacketProtoDecoder_Init (PacketProtoDecoder *enc, StreamRecvInterface *input, PacketPassInterface *output, BPendingGroup *pg, void *user, PacketProtoDecoder_handler_error handler_error)
{
    // init arguments
    enc->input = input;
    enc->output = output;
    enc->user = user;
    enc->handler_error = handler_error;
    
    // init input
    StreamRecvInterface_Receiver_Init(enc->input, (StreamRecvInterface_handler_done)input_handler_done, enc);
    
    // init output
    PacketPassInterface_Sender_Init(enc->output, (PacketPassInterface_handler_done)output_handler_done, enc);
    
    // set output MTU, limit by maximum payload size
    enc->output_mtu = bmin_int(PacketPassInterface_GetMTU(enc->output), PACKETPROTO_MAXPAYLOAD);
    
    // init buffer state
    enc->buf_size = PACKETPROTO_ENCLEN(enc->output_mtu);
    enc->buf_start = 0;
    enc->buf_used = 0;
    
    // allocate buffer
    if (!(enc->buf = (uint8_t *)malloc(enc->buf_size))) {
        goto fail0;
    }
    
    // start receiving
    StreamRecvInterface_Receiver_Recv(enc->input, enc->buf, enc->buf_size);
    
    DebugObject_Init(&enc->d_obj);
    
    return 1;
    
fail0:
    return 0;
}
예제 #7
0
void SingleStreamReceiver_Init (SingleStreamReceiver *o, uint8_t *packet, int packet_len, StreamRecvInterface *input, BPendingGroup *pg, void *user, SingleStreamReceiver_handler handler)
{
    ASSERT(packet_len > 0)
    ASSERT(handler)
    
    // init arguments
    o->packet = packet;
    o->packet_len = packet_len;
    o->input = input;
    o->user = user;
    o->handler = handler;
    
    // set position zero
    o->pos = 0;
    
    // init output
    StreamRecvInterface_Receiver_Init(o->input, (StreamRecvInterface_handler_done)input_handler_done, o);
    
    // start receiving
    StreamRecvInterface_Receiver_Recv(o->input, o->packet + o->pos, o->packet_len - o->pos);
    
    DebugError_Init(&o->d_err, pg);
    DebugObject_Init(&o->d_obj);
}
예제 #8
0
void do_receive (BSocksClient *o)
{
    ASSERT(o->control.recv_len < o->control.recv_total)
    
    StreamRecvInterface_Receiver_Recv(o->control.recv_if, o->control.recv_dest + o->control.recv_len, o->control.recv_total - o->control.recv_len);
}