static void direct_relay_relaywritecb(struct bufferevent *to, void *_client) { redsocks_client *client = _client; autoproxy_client * aclient = (void*)(client + 1) + client->instance->relay_ss->payload_len; struct bufferevent * from = client->client; redsocks_touch_client(client); if (EVBUFFER_LENGTH(from->input) == 0 && (client->client_evshut & EV_READ)) { redsocks_shutdown(client, to, SHUT_WR); return; } else if (aclient->state == AUTOPROXY_CONNECTED ) { /* Not send or receive data. */ if (!aclient->data_sent && !aclient->data_recv) { /* Ensure we have data to send */ if (EVBUFFER_LENGTH(from->input)) { /* copy data from input to output of relay */ aclient->data_sent = copy_evbuffer (to, from, 0); redsocks_log_error(client, LOG_DEBUG, "not sent, not got %d", EVBUFFER_LENGTH(from->input)); } } /* * Relay reaceived data before writing to relay. */ else if (!aclient->data_sent && aclient->data_recv) { redsocks_log_error(client, LOG_DEBUG, "not sent, got"); aclient->data_sent = copy_evbuffer(to, from, 0); } /* aclient->state = AUTOPROXY_CONFIRMED; */ /* We have writen data to relay, but got nothing until we are requested to * write to it again. */ else if (aclient->data_sent && !aclient->data_recv) { /* No response from relay and no CONNECTION RESET, Send more data. */ redsocks_log_error(client, LOG_DEBUG, "sent, not got in:%d out:%d high:%d sent:%d", evbuffer_get_length(from->input), evbuffer_get_length(to->output), to->wm_write.high, aclient->data_sent ); /* Write more data util input buffer is full */ if (EVBUFFER_LENGTH(from->input)- aclient->data_sent > 0) /* we have more data waiting to be sent */ { aclient->data_sent += copy_evbuffer(to, from, aclient->data_sent); } else if (EVBUFFER_LENGTH(to->output) < aclient->data_sent /* data is sent out, more or less */ && EVBUFFER_LENGTH(from->input) == from->wm_read.high /* do not confirm unless read buffer is full */ && EVBUFFER_LENGTH(from->input) == aclient->data_sent /* all data in read buffer is sent */ ) { evbuffer_drain(from->input, aclient->data_sent); aclient->data_sent = 0; aclient->state = AUTOPROXY_CONFIRMED; on_connection_confirmed(client); } } /* We sent data to and got data from relay. */ else if (aclient->data_sent && aclient->data_recv) { /* No CONNECTION RESET error occur after sending data, good. */ aclient->state = AUTOPROXY_CONFIRMED; on_connection_confirmed(client); redsocks_log_error(client, LOG_DEBUG, "sent, got %d ", aclient->data_recv); if (evbuffer_get_length(from->input)) { evbuffer_drain(from->input, aclient->data_sent); aclient->data_sent = 0; } } } if (aclient->state == AUTOPROXY_CONFIRMED) { if (EVBUFFER_LENGTH(to->output) < to->wm_write.high) { if (bufferevent_write_buffer(to, from->input) == -1) redsocks_log_errno(client, LOG_ERR, "bufferevent_write_buffer"); if (bufferevent_enable(from, EV_READ) == -1) redsocks_log_errno(client, LOG_ERR, "bufferevent_enable"); } } }
static void direct_relay_relaywritecb(struct bufferevent *to, void *_client) { redsocks_client *client = _client; socks5_client *socks5 = (void*)(client + 1); struct bufferevent * from = client->client; redsocks_touch_client(client); if (EVBUFFER_LENGTH(from->input) == 0 && (client->client_evshut & EV_READ)) { redsocks_shutdown(client, to, SHUT_WR); return; } else if (client->state == socks5_direct ) { /* Not send or receive data. */ if (!socks5->data_sent && !socks5->got_data) { /* Ensure we have data to send */ if (EVBUFFER_LENGTH(from->input)) { /* copy data from input to output of relay */ socks5->data_sent = copy_evbuffer (to, from); redsocks_log_error(client, LOG_DEBUG, "not sent, not got %d", EVBUFFER_LENGTH(from->input)); } } /* * Relay reaceived data before writing to relay. */ else if (!socks5->data_sent && socks5->got_data) { redsocks_log_error(client, LOG_DEBUG, "not sent, got"); socks5->data_sent = copy_evbuffer(to, from); } /* client->state = socks5_direct_confirmed; */ /* We have writen data to relay, but got nothing until we are requested to * write to it again. */ else if (socks5->data_sent && !socks5->got_data) { /* No response from relay and no CONNECTION RESET, Send more data. */ redsocks_log_error(client, LOG_DEBUG, "sent, not got in:%d out:%d high:%d sent:%d", evbuffer_get_length(from->input), evbuffer_get_length(to->output), to->wm_write.high, socks5->data_sent ); /* TODO: Write more data? */ if (EVBUFFER_LENGTH(to->output) < socks5->data_sent /* data is sent out, more or less */ && EVBUFFER_LENGTH(from->input) == from->wm_read.high /* read buffer is full */ && EVBUFFER_LENGTH(from->input) == socks5->data_sent /* all data in read buffer is sent */ ) { evbuffer_drain(from->input, socks5->data_sent); socks5->data_sent = 0; client->state = socks5_direct_confirmed; } } /* We sent data to and got data from relay. */ else if (socks5->data_sent && socks5->got_data) { /* No CONNECTION RESET error occur after sending data, good. */ client->state = socks5_direct_confirmed; redsocks_log_error(client, LOG_DEBUG, "sent, got %d ", socks5->got_data); if (evbuffer_get_length(from->input)) { evbuffer_drain(from->input, socks5->data_sent); socks5->data_sent = 0; } } } if (client->state == socks5_direct_confirmed) { if (EVBUFFER_LENGTH(to->output) < to->wm_write.high) { if (bufferevent_write_buffer(to, from->input) == -1) redsocks_log_errno(client, LOG_ERR, "bufferevent_write_buffer"); if (bufferevent_enable(from, EV_READ) == -1) redsocks_log_errno(client, LOG_ERR, "bufferevent_enable"); } } }