Files
shadowsocks-android/jni/obfsproxy/protocol.c
T

205 lines
5.1 KiB
C

/* Copyright 2011 Nick Mathewson, George Kadianakis
See LICENSE for other credits and copying information
*/
/**
* \file protocol.c
* \headerfile protocol.h
* \brief Pluggable transports-related functions.
*
* \details Acts as an intermediary between generic obfsproxy code,
* and pluggable transports code. Provides wrappers for
* transport-specific configuration, and callbacks.
*
* Note that in obfsproxy code, 'protocol' is a synonym to 'pluggable
* transport'.
**/
#include "util.h"
#include "network.h"
#include "protocol.h"
#include "protocols/dummy.h"
#include "protocols/obfs2.h"
/**
All supported protocols should be put in this array.
It's used by main.c.
*/
const protocol_vtable *const supported_protocols[] =
{
&dummy_vtable,
&obfs2_vtable
};
const size_t n_supported_protocols =
sizeof(supported_protocols)/sizeof(supported_protocols[0]);
/**
This function dispatches (by name) creation of a |config_t|
to the appropriate protocol-specific initalization function.
*/
config_t *
config_create(int n_options, const char *const *options)
{
size_t i;
for (i = 0; i < n_supported_protocols; i++)
if (!strcmp(*options, supported_protocols[i]->name))
/* Remove the first element of 'options' (which is always the
protocol name) from the list passed to the init method. */
return supported_protocols[i]->config_create(n_options - 1, options + 1);
return NULL;
}
/**
Return the transport name for 'cfg'.
*/
const char *
get_transport_name_from_config(config_t *cfg)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->name);
return cfg->vtable->name;
}
/**
Create a config_t for a managed proxy listener.
*/
config_t *
config_create_managed(int is_server, const char *protocol,
const char *bindaddr, const char *orport)
{
size_t i;
for (i = 0; i < n_supported_protocols; i++)
if (!strcmp(protocol, supported_protocols[i]->name)) {
/* Remove the first element of 'options' (which is always the
protocol name) from the list passed to the init method. */
return supported_protocols[i]->config_create_managed(is_server,
protocol,
bindaddr, orport);
}
return NULL;
}
/**
This function destroys the protocol-specific part of a listener object.
*/
void
config_free(config_t *cfg)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->config_free);
cfg->vtable->config_free(cfg);
}
struct evutil_addrinfo *
config_get_listen_addrs(config_t *cfg, size_t n)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->config_get_listen_addrs);
return cfg->vtable->config_get_listen_addrs(cfg, n);
}
struct evutil_addrinfo *
config_get_target_addr(config_t *cfg)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->config_get_target_addr);
return cfg->vtable->config_get_target_addr(cfg);
}
/**
This function is called once per connection and creates a protocol
object to be used during the session.
Return a 'protocol_t' if successful, NULL otherwise.
*/
conn_t *
proto_conn_create(config_t *cfg)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->conn_create);
return cfg->vtable->conn_create(cfg);
}
/**
This function does the protocol handshake.
Not all protocols have a handshake.
*/
int
proto_handshake(conn_t *conn, void *buf) {
obfs_assert(conn);
obfs_assert(conn->cfg);
obfs_assert(conn->cfg->vtable);
obfs_assert(conn->cfg->vtable->handshake);
return conn->cfg->vtable->handshake(conn, buf);
}
/**
This function is responsible for sending protocol data.
*/
int
proto_send(conn_t *conn, void *source, void *dest) {
obfs_assert(conn);
obfs_assert(conn->cfg);
obfs_assert(conn->cfg->vtable);
obfs_assert(conn->cfg->vtable->send);
return conn->cfg->vtable->send(conn, source, dest);
}
/**
This function is responsible for receiving protocol data.
*/
enum recv_ret
proto_recv(conn_t *conn, void *source, void *dest) {
obfs_assert(conn);
obfs_assert(conn->cfg);
obfs_assert(conn->cfg->vtable);
obfs_assert(conn->cfg->vtable->recv);
return conn->cfg->vtable->recv(conn, source, dest);
}
/**
This function destroys 'conn'.
It's called everytime we close a connection.
*/
void
proto_conn_free(conn_t *conn) {
obfs_assert(conn);
obfs_assert(conn->cfg);
obfs_assert(conn->cfg->vtable);
obfs_assert(conn->cfg->vtable->conn_free);
conn->cfg->vtable->conn_free(conn);
}
/**
This protocol is called everytime a circuit has to be created.
Return a circuit_t on success or a NULL on fail.
*/
circuit_t *
proto_circuit_create(config_t *cfg)
{
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->circuit_create);
return cfg->vtable->circuit_create(cfg);
}
/**
This function destroys 'circuit', using the vtable off 'cfg'.
*/
void
proto_circuit_free(circuit_t *circuit, config_t *cfg) {
obfs_assert(cfg);
obfs_assert(cfg->vtable);
obfs_assert(cfg->vtable->circuit_free);
cfg->vtable->circuit_free(circuit);
}