SOCKS: finishing touches
Making sure that I handle all corner cases appropriately.
This commit is contained in:
parent
7d9b05eb9a
commit
c34bb483ca
78
common.c
78
common.c
|
@ -383,23 +383,20 @@ struct socks_connector
|
||||||
|
|
||||||
// Negotiation:
|
// Negotiation:
|
||||||
|
|
||||||
|
struct poller_timer timeout; ///< Timeout timer
|
||||||
|
|
||||||
int socket_fd; ///< Current socket file descriptor
|
int socket_fd; ///< Current socket file descriptor
|
||||||
struct poller_fd socket_event; ///< Socket can be read from/written to
|
struct poller_fd socket_event; ///< Socket can be read from/written to
|
||||||
struct str read_buffer; ///< Read buffer
|
struct str read_buffer; ///< Read buffer
|
||||||
struct str write_buffer; ///< Write buffer
|
struct str write_buffer; ///< Write buffer
|
||||||
|
|
||||||
struct poller_timer timeout; ///< Timeout timer
|
bool done; ///< Tunnel succesfully established
|
||||||
|
|
||||||
bool done; ///< We're connected
|
|
||||||
uint8_t bound_address_len; ///< Length of domain name
|
uint8_t bound_address_len; ///< Length of domain name
|
||||||
struct socks_addr bound_address; ///< Bound address at the server
|
size_t data_needed; ///< How much data "on_data" needs
|
||||||
uint16_t bound_port; ///< Bound port at the server
|
|
||||||
|
|
||||||
/// Process incoming data if there's enough of it available
|
/// Process incoming data if there's enough of it available
|
||||||
bool (*on_data) (struct socks_connector *, struct msg_unpacker *);
|
bool (*on_data) (struct socks_connector *, struct msg_unpacker *);
|
||||||
|
|
||||||
size_t data_needed; ///< How much data the callback needs
|
|
||||||
|
|
||||||
// Configuration:
|
// Configuration:
|
||||||
|
|
||||||
const char *hostname; ///< SOCKS server hostname
|
const char *hostname; ///< SOCKS server hostname
|
||||||
|
@ -413,6 +410,11 @@ struct socks_connector
|
||||||
|
|
||||||
void *user_data; ///< User data for callbacks
|
void *user_data; ///< User data for callbacks
|
||||||
|
|
||||||
|
// Additional results:
|
||||||
|
|
||||||
|
struct socks_addr bound_address; ///< Bound address at the server
|
||||||
|
uint16_t bound_port; ///< Bound port at the server
|
||||||
|
|
||||||
// You may destroy the connector object in these two main callbacks:
|
// You may destroy the connector object in these two main callbacks:
|
||||||
|
|
||||||
/// Connection has been successfully established
|
/// Connection has been successfully established
|
||||||
|
@ -429,6 +431,8 @@ struct socks_connector
|
||||||
void (*on_error) (void *user_data, const char *error);
|
void (*on_error) (void *user_data, const char *error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// I've tried to make the actual protocol handlers as simple as possible
|
||||||
|
|
||||||
#define SOCKS_FAIL(...) \
|
#define SOCKS_FAIL(...) \
|
||||||
BLOCK_START \
|
BLOCK_START \
|
||||||
char *error = xstrdup_printf (__VA_ARGS__); \
|
char *error = xstrdup_printf (__VA_ARGS__); \
|
||||||
|
@ -712,18 +716,38 @@ socks_5_auth_start (struct socks_connector *self)
|
||||||
|
|
||||||
static void socks_connector_start (struct socks_connector *self);
|
static void socks_connector_start (struct socks_connector *self);
|
||||||
|
|
||||||
|
static void
|
||||||
|
socks_connector_destroy_connector (struct socks_connector *self)
|
||||||
|
{
|
||||||
|
if (self->connector)
|
||||||
|
{
|
||||||
|
connector_free (self->connector);
|
||||||
|
free (self->connector);
|
||||||
|
self->connector = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
socks_connector_cancel_events (struct socks_connector *self)
|
||||||
|
{
|
||||||
|
// Before calling the final callbacks, we should cancel events that
|
||||||
|
// could potentially fire; caller should destroy us immediately, though
|
||||||
|
poller_fd_reset (&self->socket_event);
|
||||||
|
poller_timer_reset (&self->timeout);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
socks_connector_fail (struct socks_connector *self)
|
socks_connector_fail (struct socks_connector *self)
|
||||||
{
|
{
|
||||||
poller_fd_reset (&self->socket_event);
|
socks_connector_cancel_events (self);
|
||||||
self->on_failure (self->user_data);
|
self->on_failure (self->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
socks_connector_step_iterators (struct socks_connector *self)
|
socks_connector_step_iterators (struct socks_connector *self)
|
||||||
{
|
{
|
||||||
// At the lowest level we iterate over all addresses for the SOCKS server;
|
// At the lowest level we iterate over all addresses for the SOCKS server
|
||||||
// this is done automatically by the connector
|
// and just try to connect; this is done automatically by the connector
|
||||||
|
|
||||||
// Then we iterate over available protocols
|
// Then we iterate over available protocols
|
||||||
if (++self->protocol_iter != SOCKS_MAX)
|
if (++self->protocol_iter != SOCKS_MAX)
|
||||||
|
@ -747,13 +771,7 @@ socks_connector_step (struct socks_connector *self)
|
||||||
self->socket_fd = -1;
|
self->socket_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->connector)
|
socks_connector_destroy_connector (self);
|
||||||
{
|
|
||||||
connector_free (self->connector);
|
|
||||||
free (self->connector);
|
|
||||||
self->connector = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socks_connector_step_iterators (self))
|
if (socks_connector_step_iterators (self))
|
||||||
socks_connector_start (self);
|
socks_connector_start (self);
|
||||||
else
|
else
|
||||||
|
@ -766,6 +784,7 @@ socks_connector_on_timeout (struct socks_connector *self)
|
||||||
if (self->on_error)
|
if (self->on_error)
|
||||||
self->on_error (self->user_data, "timeout");
|
self->on_error (self->user_data, "timeout");
|
||||||
|
|
||||||
|
socks_connector_destroy_connector (self);
|
||||||
socks_connector_fail (self);
|
socks_connector_fail (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -783,10 +802,8 @@ socks_connector_on_connected (void *user_data, int socket_fd)
|
||||||
str_reset (&self->read_buffer);
|
str_reset (&self->read_buffer);
|
||||||
str_reset (&self->write_buffer);
|
str_reset (&self->write_buffer);
|
||||||
|
|
||||||
if ((self->protocol_iter == SOCKS_5 && socks_5_auth_start (self))
|
if (!(self->protocol_iter == SOCKS_5 && socks_5_auth_start (self))
|
||||||
|| (self->protocol_iter == SOCKS_4A && socks_4a_start (self)))
|
&& !(self->protocol_iter == SOCKS_4A && socks_4a_start (self)))
|
||||||
return;
|
|
||||||
|
|
||||||
socks_connector_fail (self);
|
socks_connector_fail (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -838,9 +855,13 @@ socks_connector_start (struct socks_connector *self)
|
||||||
hard_assert (connector_add_target (connector,
|
hard_assert (connector_add_target (connector,
|
||||||
self->hostname, self->service, NULL));
|
self->hostname, self->service, NULL));
|
||||||
|
|
||||||
connector_step (connector);
|
|
||||||
poller_timer_set (&self->timeout, 60 * 1000);
|
poller_timer_set (&self->timeout, 60 * 1000);
|
||||||
|
connector_step (connector);
|
||||||
self->done = false;
|
self->done = false;
|
||||||
|
|
||||||
|
self->bound_port = 0;
|
||||||
|
socks_addr_free (&self->bound_address);
|
||||||
|
memset (&self->bound_address, 0, sizeof self->bound_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -923,8 +944,9 @@ socks_connector_on_ready
|
||||||
}
|
}
|
||||||
else if (self->done)
|
else if (self->done)
|
||||||
{
|
{
|
||||||
|
socks_connector_cancel_events (self);
|
||||||
|
|
||||||
int fd = self->socket_fd;
|
int fd = self->socket_fd;
|
||||||
poller_fd_reset (&self->socket_event);
|
|
||||||
self->socket_fd = -1;
|
self->socket_fd = -1;
|
||||||
set_blocking (fd, true);
|
set_blocking (fd, true);
|
||||||
self->on_connected (self->user_data, fd);
|
self->on_connected (self->user_data, fd);
|
||||||
|
@ -956,14 +978,8 @@ socks_connector_init (struct socks_connector *self, struct poller *poller)
|
||||||
static void
|
static void
|
||||||
socks_connector_free (struct socks_connector *self)
|
socks_connector_free (struct socks_connector *self)
|
||||||
{
|
{
|
||||||
if (self->connector)
|
socks_connector_destroy_connector (self);
|
||||||
{
|
socks_connector_cancel_events (self);
|
||||||
connector_free (self->connector);
|
|
||||||
free (self->connector);
|
|
||||||
}
|
|
||||||
|
|
||||||
poller_fd_reset (&self->socket_event);
|
|
||||||
poller_timer_reset (&self->timeout);
|
|
||||||
|
|
||||||
if (self->socket_fd != -1)
|
if (self->socket_fd != -1)
|
||||||
xclose (self->socket_fd);
|
xclose (self->socket_fd);
|
||||||
|
|
Loading…
Reference in New Issue