SOCKS: finishing touches

Making sure that I handle all corner cases appropriately.
This commit is contained in:
Přemysl Eric Janouch 2015-07-22 00:34:27 +02:00
parent 7d9b05eb9a
commit c34bb483ca
1 changed files with 48 additions and 32 deletions

View File

@ -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,11 +802,9 @@ 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);
} }
static void static void
@ -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);