Beispiel #1
0
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");
		}	
	}
}
Beispiel #2
0
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");
		}	
	}
}