bud_client_error_t bud_client_throttle(bud_client_t* client, bud_client_side_t* side, ringbuffer* buf) { int err; bud_client_side_t* opposite; if (!ringbuffer_is_full(buf)) return bud_client_ok(side); opposite = side == &client->frontend ? &client->backend : &client->frontend; if (opposite->reading != kBudProgressRunning) goto done; DBG(opposite, "throttle, buffer full: %ld", ringbuffer_size(buf)); err = uv_read_stop((uv_stream_t*) &opposite->tcp); if (err != 0) { NOTICE(opposite, "uv_read_stop failed: %d - \"%s\"", err, uv_strerror(err)); return bud_client_error(bud_error_num(kBudErrClientReadStop, err), side); } opposite->reading = kBudProgressNone; done: return bud_client_error(bud_error(kBudErrClientThrottle), side); }
/* Read some data from the upstream secure socket via OpenSSL, * and buffer anything we get for writing to the backend */ static void client_read(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; proxystate *ps = (proxystate *)w->data; if (ps->want_shutdown) { ev_io_stop(loop, &ps->ev_r_up); return; } char * buf = ringbuffer_write_ptr(&ps->ring_down); t = SSL_read(ps->ssl, buf, RING_DATA_LEN); if (t > 0) { ringbuffer_write_append(&ps->ring_down, t); if (ringbuffer_is_full(&ps->ring_down)) ev_io_stop(loop, &ps->ev_r_up); safe_enable_io(ps, &ps->ev_w_down); } else { int err = SSL_get_error(ps->ssl, t); if (err == SSL_ERROR_WANT_WRITE) { start_handshake(ps, err); } else if (err == SSL_ERROR_WANT_READ) { } /* incomplete SSL data */ else handle_fatal_ssl_error(ps, err); } }
/* Read some data from the backend when libev says data is available-- * write it into the upstream buffer and make sure the write event is * enabled for the upstream socket */ static void back_read(struct ev_loop *loop, ev_io *w, int revents) { (void) revents; int t; proxystate *ps = (proxystate *)w->data; if (ps->want_shutdown) { ev_io_stop(loop, &ps->ev_r_down); return; } int fd = w->fd; char * buf = ringbuffer_write_ptr(&ps->ring_up); t = recv(fd, buf, RING_DATA_LEN, 0); if (t > 0) { ringbuffer_write_append(&ps->ring_up, t); if (ringbuffer_is_full(&ps->ring_up)) ev_io_stop(loop, &ps->ev_r_down); safe_enable_io(ps, &ps->ev_w_up); } else if (t == 0) { LOG("{backend} Connection closed\n"); shutdown_proxy(ps, SHUTDOWN_DOWN); } else { assert(t == -1); handle_socket_errno(ps); } }
void * producer_proc(void *arg) { struct ringbuffer *ring_buf = (struct ringbuffer *)arg; char i; i = 0; while(1) { printf("******************************************\n"); printf("put datas to ring buffer.\n"); if (ringbuffer_is_full(ring_buf)) { printf("buffer is full !\n"); sleep(1); continue; } ringbuffer_put(ring_buf, &i, sizeof(i)); i++; printf("ring buffer length: %u\n", ringbuffer_len(ring_buf)); printf("******************************************\n"); sleep(1); } }
/* After OpenSSL is done with a handshake, re-wire standard read/write handlers * for data transmission */ static void end_handshake(proxystate *ps) { ev_io_stop(loop, &ps->ev_r_handshake); ev_io_stop(loop, &ps->ev_w_handshake); /* if incoming buffer is not full */ if (!ringbuffer_is_full(&ps->ring_down)) safe_enable_io(ps, &ps->ev_r_up); /* if outgoing buffer is not empty */ if (!ringbuffer_is_empty(&ps->ring_up)) // not safe.. we want to resume stream even during half-closed ev_io_start(loop, &ps->ev_w_up); }
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { struct fm_state *fm2 = ctx; if (do_exit) { return;} if (!ctx) { return;} if(ringbuffer_is_full((ringbuffer*)fm2->buf)) { fprintf(stderr, "Dropping %u bytes of rtl_sdr input due to full buffer!\n", len); return; } ringbuffer_write((ringbuffer*)fm2->buf, buf); // pthread_mutex_lock(&data_write); // memcpy(fm2->buf, buf, len); // fm2->buf_len = len; // pthread_mutex_unlock(&data_ready); /* single threaded uses 25% less CPU? */ /* full_demod(fm2); */ }
void bud_client_send_cb(uv_write_t* req, int status) { bud_client_t* client; bud_client_error_t cerr; bud_client_side_t* side; bud_client_side_t* opposite; /* Closing, ignore */ if (status == UV_ECANCELED) return; client = req->data; if (req == &client->frontend.write_req) { side = &client->frontend; opposite = &client->backend; } else { side = &client->backend; opposite = &client->frontend; } if (status != 0) { side->write = kBudProgressDone; bud_client_close( client, bud_client_error(bud_error_num(kBudErrClientWriteCb, status), side)); return; } /* Consume written data */ DBG(side, "write_cb => %d", side->write_size); ringbuffer_read_skip(&side->output, side->write_size); /* Skip data in xforward parser */ if (side == &client->backend) bud_client_xforward_skip(client, side->write_size); side->write = kBudProgressNone; side->write_size = 0; if (opposite->reading == kBudProgressNone) { if ((client->retry == kBudProgressRunning || client->connect == kBudProgressRunning) && opposite == &client->backend) { /* Set reading mark on backend to resume it after reconnecting */ opposite->reading = kBudProgressRunning; } else if (opposite->close != kBudProgressDone && side->close != kBudProgressDone && side->shutdown != kBudProgressDone && !ringbuffer_is_full(&side->output)) { DBG_LN(opposite, "read_start"); cerr = bud_client_read_start(client, opposite); if (!bud_is_ok(cerr.err)) return bud_client_close(client, cerr); opposite->reading = kBudProgressRunning; } } /* Cycle again */ cerr = bud_client_cycle(client); if (!bud_is_ok(cerr.err)) return bud_client_close(client, cerr); if (side->close == kBudProgressRunning || side->shutdown == kBudProgressRunning) { if (!ringbuffer_is_empty(&side->output)) return; /* No new data, destroy or shutdown */ if (side->shutdown == kBudProgressRunning) { cerr = bud_client_shutdown(client, side); if (!bud_is_ok(cerr.err)) bud_client_close(client, cerr); return; } bud_client_close(client, bud_client_ok(side)); } }