commit 0448e1cc8aaaa5b4d71277b9738cfa5b33268212 Author: Zack Weinberg zackw@panix.com Date: Thu Mar 29 17:45:25 2012 -0700
Split up steg_t into per-connection and per-listener state objects.
This will facilitate the removal of the global variables in embed and http so that they work in multi-listener mode, and the addition of configurable parameters to steg modules (such as the location of the trace files). --- src/protocol/chop.cc | 26 +++++----- src/steg.cc | 13 +++-- src/steg.h | 126 +++++++++++++++++++++++++++++++----------------- src/steg/embed.cc | 122 ++++++++++++++++++++++++++++++++++------------- src/steg/http.cc | 83 ++++++++++++++++++++++++--------- src/steg/nosteg.cc | 50 +++++++++++++++---- src/steg/nosteg_rr.cc | 62 ++++++++++++++++++------ 7 files changed, 339 insertions(+), 143 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc index cf64e6c..06346b7 100644 --- a/src/protocol/chop.cc +++ b/src/protocol/chop.cc @@ -371,7 +371,7 @@ struct chop_config_t : config_t { struct evutil_addrinfo *up_address; vector<struct evutil_addrinfo *> down_addresses; - vector<const char *> steg_targets; + vector<steg_config_t *> steg_targets; chop_circuit_table circuits;
CONFIG_DECLARE_METHODS(chop); @@ -392,7 +392,9 @@ chop_config_t::~chop_config_t() i != down_addresses.end(); i++) evutil_freeaddrinfo(*i);
- // The strings in steg_targets are not on the heap. + for (vector<steg_config_t *>::iterator i = steg_targets.begin(); + i != steg_targets.end(); i++) + delete *i;
for (chop_circuit_table::iterator i = circuits.begin(); i != circuits.end(); i++) @@ -454,7 +456,7 @@ chop_config_t::init(int n_options, const char *const *options) log_warn("chop: steganographer '%s' not supported", options[i]); goto usage; } - steg_targets.push_back(options[i]); + steg_targets.push_back(steg_new(options[i], this)); } return true;
@@ -744,7 +746,7 @@ chop_circuit_t::send_targeted(chop_conn_t *conn) avail = SECTION_LEN; avail += MIN_BLOCK_SIZE;
- size_t room = conn->steg->transmit_room(conn); + size_t room = conn->steg->transmit_room(); if (room < MIN_BLOCK_SIZE) { log_warn(conn, "send() called without enough transmit room " "(have %lu, need %lu)", (unsigned long)room, @@ -752,7 +754,7 @@ chop_circuit_t::send_targeted(chop_conn_t *conn) return -1; } log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room, - conn->steg->name()); + conn->steg->cfg()->name());
if (room < avail) avail = room; @@ -868,7 +870,7 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize) if (conn->steg) { // Find the connections whose transmit rooms are closest to the // desired transmission length from both directions. - size_t room = conn->steg->transmit_room(conn); + size_t room = conn->steg->transmit_room();
if (room <= MIN_BLOCK_SIZE) room = 0; @@ -877,7 +879,7 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize) room = MAX_BLOCK_SIZE;
log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room, - conn->steg->name()); + conn->steg->cfg()->name());
if (room >= desired) { if (room < minabove) { @@ -1029,7 +1031,7 @@ chop_config_t::conn_create(size_t index) { chop_conn_t *conn = new chop_conn_t; conn->config = this; - conn->steg = steg_new(steg_targets.at(index), mode != LSN_SIMPLE_SERVER); + conn->steg = steg_targets.at(index)->steg_create(conn); if (!conn->steg) { free(conn); return 0; @@ -1082,7 +1084,7 @@ chop_conn_t::send(struct evbuffer *block) } }
- if (steg->transmit(block, this)) { + if (steg->transmit(block)) { log_warn(this, "failed to transmit block"); return -1; } @@ -1154,7 +1156,7 @@ chop_conn_t::recv_handshake() int chop_conn_t::recv() { - if (steg->receive(this, recv_pending)) + if (steg->receive(recv_pending)) return -1;
if (!upstream) { @@ -1320,7 +1322,7 @@ chop_conn_t::send() } else { log_debug(this, "must send (no upstream)");
- size_t room = steg->transmit_room(this); + size_t room = steg->transmit_room(); if (room < MIN_BLOCK_SIZE) { log_warn(this, "send() called without enough transmit room " "(have %lu, need %lu)", (unsigned long)room, @@ -1351,7 +1353,7 @@ chop_conn_t::send() return; }
- if (steg->transmit(chaff, this)) + if (steg->transmit(chaff)) conn_do_flush(this);
evbuffer_free(chaff); diff --git a/src/steg.cc b/src/steg.cc index 8db5498..12ea291 100644 --- a/src/steg.cc +++ b/src/steg.cc @@ -18,16 +18,17 @@ steg_is_supported(const char *name) }
/* Instantiate a steg module by name. */ -steg_t * -steg_new(const char *name, bool is_clientside) +steg_config_t * +steg_new(const char *name, config_t *cfg) { const steg_module *const *s; for (s = supported_stegs; *s; s++) if (!strcmp(name, (**s).name)) - return (**s).new_(is_clientside); - return NULL; + return (**s).new_(cfg); + return 0; }
-/* Define this here rather than in the class definition so that the - vtable will be emitted in only one place. */ +/* Define these here rather than in the class definition so that the + vtables will be emitted in only one place. */ +steg_config_t::~steg_config_t() {} steg_t::~steg_t() {} diff --git a/src/steg.h b/src/steg.h index dab44e5..a044afb 100644 --- a/src/steg.h +++ b/src/steg.h @@ -5,42 +5,73 @@ #ifndef STEG_H #define STEG_H
-/** A steganography instance must define a private subclass of this - type, that implements all of the methods below, plus a descendant - constructor. The subclass must have exactly the same name that - you use for the module name in STEG_DEFINE_MODULE, and should be - declared inside an anonymous namespace. Use STEG_DECLARE_METHODS - in the declaration. */ -struct steg_t +/** A 'steg_config_t' is analogous to a 'config_t' (see protocol.h); + it defines cross-connection state for a steganography module. + (A 'config_t' may be associated with several 'steg_config_t's.) + + A steganography module must define a private subclass of this + type, that implements all the methods below, plus a descendant + constructor. The subclass must have the name MODULE_steg_config_t, + where MODULE is the module name you use in STEG_DEFINE_MODULE. + It should be declared inside an anonymous namespace. + Use STEG_CONFIG_DECLARE_METHODS in the declaration. */ + +struct steg_t; + +struct steg_config_t { - bool is_clientside : 1; + struct config_t *cfg;
- steg_t(bool is_clientside) : is_clientside(is_clientside) {} - virtual ~steg_t(); + steg_config_t(config_t *c) : cfg(c) {} + virtual ~steg_config_t();
/** Report the name of this steg module. You do not have to define this method in your subclass, STEG_DEFINE_MODULE does it for you. */ virtual const char *name() = 0;
+ /** Create an extended 'steg_t' object (see below) from this + configuration, associated with connection CONN. */ + virtual steg_t *steg_create(conn_t *conn) = 0; +}; + +/** A 'steg_t' object handles the actual steganography for one + connection, and is responsible for tracking per-connection + state for the cover protocol, if any. + + Again, a steganography module must define a private subclass of + this type, that implements all of the methods below, plus a + descendant constructor. The subclass must have the name + MODULE_steg_t, where MODULE is the module name you use in + STEG_DEFINE_MODULE. It should be declared inside an anonymous + namespace. Use STEG_DECLARE_METHODS in the declaration. */ +struct steg_t +{ + steg_t() {} + virtual ~steg_t(); + + /** Return the steg_config_t from which this steg_t was created. */ + virtual steg_config_t *cfg() = 0; + /** Report the maximum number of bytes that could be transmitted on - connection CONN at this time. You must be prepared to handle a + your connection at this time. You must be prepared to handle a subsequent request to transmit any _smaller_ number of bytes on this connection. */ - virtual size_t transmit_room(conn_t *conn) = 0; + virtual size_t transmit_room() = 0;
/** Consume all of the data in SOURCE, disguise it, and write it to - the outbound buffer for CONN. Return 0 on success, -1 on failure. */ - virtual int transmit(struct evbuffer *source, conn_t *conn) = 0; - - /** The data in CONN's inbound buffer should have been disguised by - the peer instance to STATE. Unmask it and write it to DEST. - Return 0 on success, -1 on failure. If more data needs to come - over the wire before anything can be unmasked, that is *not* a - failure condition; return 0, but do not consume any data or - write anything to DEST. It is *preferable*, but not currently - *required*, for this method to not consume any data or write - anything to DEST in a failure situation. */ - virtual int receive(conn_t *conn, struct evbuffer *dest) = 0; + the outbound buffer for your connection. Return 0 on success, -1 + on failure. */ + virtual int transmit(struct evbuffer *source) = 0; + + /** Unmask as much of the data in your connection's inbound buffer + as possible, and write it to DEST. Return 0 on success, -1 on + failure. If more data needs to come over the wire before + anything can be unmasked, that is *not* a failure condition; + return 0, but do not consume any data or write anything to DEST. + It is *preferable*, but not currently *required*, for this + method to not consume any data or write anything to DEST in a + failure situation. */ + virtual int receive(struct evbuffer *dest) = 0; };
/** STEG_DEFINE_MODULE defines an object with this type, plus the @@ -52,38 +83,43 @@ struct steg_module /** Name of the steganography module. Must be a valid C identifier. */ const char *name;
- /** Create an appropriate steg_t subclass for this module. - More arguments may be added later. */ - steg_t *(*new_)(bool is_clientside); + /** Create an appropriate steg_config_t subclass for this module. */ + steg_config_t *(*new_)(config_t *cfg); };
extern const steg_module *const supported_stegs[];
int steg_is_supported(const char *name); -steg_t *steg_new(const char *name, bool is_clientside); +steg_config_t *steg_new(const char *name, config_t *cfg);
/* Macros for use in defining steg modules. */
-#define STEG_DEFINE_MODULE(mod) \ - /* new_ dispatchers */ \ - static steg_t *mod##_new(bool is_clientside) \ - { return new mod(is_clientside); } \ - \ - /* canned methods */ \ - const char *mod::name() { return #mod; } \ - \ - /* module object */ \ - extern const steg_module s_mod_##mod = { \ - #mod, mod##_new \ +#define STEG_DEFINE_MODULE(mod) \ + /* new_ dispatchers */ \ + static steg_config_t *mod##_new(config_t *cfg) \ + { return new mod##_steg_config_t(cfg); } \ + \ + /* canned methods */ \ + const char *mod##_steg_config_t::name() { return #mod; } \ + \ + /* module object */ \ + extern const steg_module s_mod_##mod = { \ + #mod, mod##_new \ } /* deliberate absence of semicolon */
-#define STEG_DECLARE_METHODS(mod) \ - mod(bool is_clientside); \ - virtual ~mod(); \ +#define STEG_CONFIG_DECLARE_METHODS(mod) \ + mod##_steg_config_t(config_t *cfg); \ + virtual ~mod##_steg_config_t(); \ virtual const char *name(); \ - virtual size_t transmit_room(conn_t *conn); \ - virtual int transmit(struct evbuffer *source, conn_t *conn); \ - virtual int receive(conn_t *conn, struct evbuffer *dest) \ + virtual steg_t *steg_create(conn_t *conn) \ + /* deliberate absence of semicolon */ + +#define STEG_DECLARE_METHODS(mod) \ + virtual ~mod##_steg_t(); \ + virtual steg_config_t *cfg(); \ + virtual size_t transmit_room(); \ + virtual int transmit(struct evbuffer *source); \ + virtual int receive(struct evbuffer *dest) \ /* deliberate absence of semicolon */
#endif diff --git a/src/steg/embed.cc b/src/steg/embed.cc index e2f12a0..6559bf7 100644 --- a/src/steg/embed.cc +++ b/src/steg/embed.cc @@ -1,5 +1,6 @@ #include "util.h" #include "connections.h" +#include "protocol.h" #include "steg.h" #include "rng.h"
@@ -9,19 +10,30 @@ #include <unistd.h> #include <time.h>
-typedef struct trace_t { - int num_pkt; // number of packets in trace - short *pkt_sizes; // packet sizes (positive = client->server) - int *pkt_times; // packet inter-arrival times -} trace_t; - namespace { - struct embed : steg_t { + struct trace_t { + int num_pkt; // number of packets in trace + short *pkt_sizes; // packet sizes (positive = client->server) + int *pkt_times; // packet inter-arrival times + }; + + struct embed_steg_config_t : steg_config_t { + bool is_clientside; + + STEG_CONFIG_DECLARE_METHODS(embed); + }; + + struct embed_steg_t : steg_t { + embed_steg_config_t *config; + conn_t *conn; + int cur_idx; // current trace index trace_t *cur; // current trace int cur_pkt; // current packet in the trace struct timeval last_pkt; // time at which last packet was sent/received
+ embed_steg_t(embed_steg_config_t *cf, conn_t *cn); + STEG_DECLARE_METHODS(embed);
bool advance_packet(); @@ -32,13 +44,15 @@ namespace { }; }
+STEG_DEFINE_MODULE(embed); + static int embed_init = 0; // whether traces are initialized static int embed_num_traces; // number of traces static trace_t *embed_traces; // global array of all traces
-STEG_DEFINE_MODULE(embed); - -int millis_since(struct timeval *last) { +static int +millis_since(struct timeval *last) +{ struct timeval cur; int diff = 0; gettimeofday(&cur, NULL); @@ -48,13 +62,31 @@ int millis_since(struct timeval *last) { return diff; }
-void init_embed_traces() { +embed_steg_config_t::embed_steg_config_t(config_t *cfg) + : steg_config_t(cfg), + is_clientside(cfg->mode != LSN_SIMPLE_SERVER) +{ +} + +embed_steg_config_t::~embed_steg_config_t() +{ +} + +steg_t * +embed_steg_config_t::steg_create(conn_t *conn) +{ + return new embed_steg_t(this, conn); +} + +static void +init_embed_traces() +{ // read in traces to use for connections FILE *trace_file = fopen("traces/embed.txt", "r"); if (fscanf(trace_file, "%d", &embed_num_traces) < 1) { log_abort("couldn't read number of traces to use -- exiting"); exit(1); - } + } embed_traces = (trace_t *)xmalloc(sizeof(trace_t) * embed_num_traces); for (int i = 0; i < embed_num_traces; i++) { int num_pkt; @@ -67,10 +99,10 @@ void init_embed_traces() { embed_traces[i].pkt_times = (int *)xmalloc(sizeof(int) * num_pkt); for (int j = 0; j < embed_traces[i].num_pkt; j++) { if (fscanf(trace_file, "%hd %d", - &embed_traces[i].pkt_sizes[j], - &embed_traces[i].pkt_times[j]) < 1) { - log_abort("couldn't read numbers of packet size and times to use -- exiting"); - exit(1); + &embed_traces[i].pkt_sizes[j], + &embed_traces[i].pkt_times[j]) < 1) { + log_abort("couldn't read numbers of packet size and times to use -- exiting"); + exit(1); } } } @@ -79,39 +111,51 @@ void init_embed_traces() { embed_init = 1; }
-int get_random_trace() { +static int +get_random_trace() +{ return rng_int(embed_num_traces); }
-bool embed::advance_packet() { +bool +embed_steg_t::advance_packet() +{ cur_pkt++; return cur_pkt == cur->num_pkt; }
-short embed::get_pkt_size() { +short +embed_steg_t::get_pkt_size() +{ return abs(cur->pkt_sizes[cur_pkt]); }
-bool embed::is_outgoing() { - return (cur->pkt_sizes[cur_pkt] < 0) ^ is_clientside; +bool +embed_steg_t::is_outgoing() +{ + return (cur->pkt_sizes[cur_pkt] < 0) ^ config->is_clientside; }
-int embed::get_pkt_time() { +int +embed_steg_t::get_pkt_time() +{ return cur->pkt_times[cur_pkt]; }
-bool embed::is_finished() { +bool +embed_steg_t::is_finished() +{ if (cur_idx == -1) return true; return cur_pkt >= cur->num_pkt; }
-embed::embed(bool is_clientside) - : steg_t(is_clientside) +embed_steg_t::embed_steg_t(embed_steg_config_t *cf, conn_t *cn) + : config(cf), conn(cn) { if (!embed_init) init_embed_traces();
cur_idx = -1; - if (is_clientside) { + if (config->is_clientside) { cur_idx = get_random_trace(); cur = &embed_traces[cur_idx]; cur_pkt = 0; @@ -119,11 +163,19 @@ embed::embed(bool is_clientside) gettimeofday(&last_pkt, NULL); }
-embed::~embed() +embed_steg_t::~embed_steg_t() +{ +} + +steg_config_t * +embed_steg_t::cfg() { + return config; }
-size_t embed::transmit_room(conn_t * /* conn */) { +size_t +embed_steg_t::transmit_room() +{ if (is_finished() || !is_outgoing()) return 0;
int time_diff = millis_since(&last_pkt); @@ -135,7 +187,9 @@ size_t embed::transmit_room(conn_t * /* conn */) { return room; }
-int embed::transmit(struct evbuffer *source, conn_t *conn) { +int +embed_steg_t::transmit(struct evbuffer *source) +{ struct evbuffer *dest = conn->outbound(); short src_len = evbuffer_get_length(source); short pkt_size = get_pkt_size(); @@ -177,13 +231,15 @@ int embed::transmit(struct evbuffer *source, conn_t *conn) { return 0; }
-int embed::receive(conn_t *conn, struct evbuffer *dest) { +int +embed_steg_t::receive(struct evbuffer *dest) +{ struct evbuffer *source = conn->inbound(); short src_len = evbuffer_get_length(source); short pkt_size = 0;
log_debug("receiving buffer of length %d", src_len); - + // if we are receiving the first packet of the trace, read the index if (cur_idx == -1) { if (evbuffer_remove(source, &cur_idx, 4) != 4) return -1; @@ -206,7 +262,7 @@ int embed::receive(conn_t *conn, struct evbuffer *dest) { if (evbuffer_remove(source, &data_len, 2) != 2) return -1; if (data_len > 0) { if (evbuffer_remove_buffer(source, dest, data_len) != data_len) { - return -1; +return -1; } } pkt_size += data_len + 2; @@ -221,7 +277,7 @@ int embed::receive(conn_t *conn, struct evbuffer *dest) { pkt_size = 0;
log_debug("received packet %d of trace %d", - cur_pkt, cur_idx); + cur_pkt, cur_idx);
// advance packet; if done with trace, sender should close connection if (advance_packet()) { diff --git a/src/steg/http.cc b/src/steg/http.cc index 5a78ffe..05ab940 100644 --- a/src/steg/http.cc +++ b/src/steg/http.cc @@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util.h" #include "connections.h" +#include "protocol.h" #include "steg.h" #include "payloads.h" #include "cookies.h" @@ -60,20 +61,48 @@ static int has_peer_name = 0; static char peername[512];
namespace { -struct http : steg_t -{ - bool have_transmitted : 1; - bool have_received : 1; - int type; + struct http_steg_config_t : steg_config_t + { + bool is_clientside : 1; + + STEG_CONFIG_DECLARE_METHODS(http); + }; + + struct http_steg_t : steg_t + { + http_steg_config_t *config; + conn_t *conn; + + bool have_transmitted : 1; + bool have_received : 1; + int type;
- STEG_DECLARE_METHODS(http); -}; + http_steg_t(http_steg_config_t *cf, conn_t *cn); + STEG_DECLARE_METHODS(http); + }; }
STEG_DEFINE_MODULE(http);
-int http_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn); -int http_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn); +http_steg_config_t::http_steg_config_t(config_t *cfg) + : steg_config_t(cfg), + is_clientside(cfg->mode != LSN_SIMPLE_SERVER) +{ +} + +http_steg_config_t::~http_steg_config_t() +{ +} + +steg_t * +http_steg_config_t::steg_create(conn_t *conn) +{ + return new http_steg_t(this, conn); +} + + +int http_client_uri_transmit (http_steg_t *s, struct evbuffer *source, conn_t *conn); +int http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source, conn_t *conn);
void evbuffer_dump(struct evbuffer *buf, FILE *out); void buf_dump(unsigned char* buf, int len, FILE *out); @@ -128,11 +157,11 @@ buf_dump(unsigned char* buf, int len, FILE *out) }
-http::http(bool is_clientside) - : steg_t(is_clientside), +http_steg_t::http_steg_t(http_steg_config_t *cf, conn_t *cn) + : config(cf), conn(cn), have_transmitted(false), have_received(false) { - if (is_clientside) + if (config->is_clientside) load_payloads("traces/client.out"); else { load_payloads("traces/server.out"); @@ -144,12 +173,18 @@ http::http(bool is_clientside) } }
-http::~http() +http_steg_t::~http_steg_t() { }
+steg_config_t * +http_steg_t::cfg() +{ + return config; +} + size_t -http::transmit_room(conn_t *) +http_steg_t::transmit_room() { unsigned int mjc;
@@ -158,7 +193,7 @@ http::transmit_room(conn_t *) return 0;
- if (is_clientside) { + if (config->is_clientside) { return (MIN_COOKIE_SIZE + rand() % (MAX_COOKIE_SIZE - MIN_COOKIE_SIZE)) / 4; } else { @@ -251,7 +286,9 @@ lookup_peer_name_from_ip(char* p_ip, char* p_name) {
int -http_client_cookie_transmit (http *s, struct evbuffer *source, conn_t *conn) { +http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source, + conn_t *conn) +{
/* On the client side, we have to embed the data in a GET query somehow; the only plausible places to put it are the URL and cookies. This @@ -455,7 +492,9 @@ int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen) {
int -http_client_uri_transmit (http *s, struct evbuffer *source, conn_t *conn) { +http_client_uri_transmit (http_steg_t *s, + struct evbuffer *source, conn_t *conn) +{
struct evbuffer *dest = conn->outbound(); @@ -558,7 +597,7 @@ http_client_uri_transmit (http *s, struct evbuffer *source, conn_t *conn) {
int -http::transmit(struct evbuffer *source, conn_t *conn) +http_steg_t::transmit(struct evbuffer *source) { // struct evbuffer *dest = conn_get_outbound(conn);
@@ -566,7 +605,7 @@ http::transmit(struct evbuffer *source, conn_t *conn)
- if (is_clientside) { + if (config->is_clientside) { /* On the client side, we have to embed the data in a GET query somehow; the only plausible places to put it are the URL and cookies. */
@@ -609,7 +648,7 @@ http::transmit(struct evbuffer *source, conn_t *conn)
int -http_server_receive(http *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) { +http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
char* data; int type; @@ -710,14 +749,14 @@ http_server_receive(http *s, conn_t *conn, struct evbuffer *dest, struct evbuffe
int -http::receive(conn_t *conn, struct evbuffer *dest) +http_steg_t::receive(struct evbuffer *dest) { struct evbuffer *source = conn->inbound(); // unsigned int type; int rval = RECV_BAD;
- if (is_clientside) { + if (config->is_clientside) { switch(type) {
case HTTP_CONTENT_SWF: diff --git a/src/steg/nosteg.cc b/src/steg/nosteg.cc index 02d2e10..df80c89 100644 --- a/src/steg/nosteg.cc +++ b/src/steg/nosteg.cc @@ -39,31 +39,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <event2/buffer.h>
namespace { -struct nosteg : steg_t -{ - STEG_DECLARE_METHODS(nosteg); -}; + struct nosteg_steg_config_t : steg_config_t + { + STEG_CONFIG_DECLARE_METHODS(nosteg); + }; + + struct nosteg_steg_t : steg_t + { + nosteg_steg_config_t *config; + conn_t *conn; + + nosteg_steg_t(nosteg_steg_config_t *cf, conn_t *cn); + STEG_DECLARE_METHODS(nosteg); + }; }
STEG_DEFINE_MODULE(nosteg);
-nosteg::nosteg(bool is_clientside) - : steg_t(is_clientside) +nosteg_steg_config_t::nosteg_steg_config_t(config_t *cfg) + : steg_config_t(cfg) +{ +} + +nosteg_steg_config_t::~nosteg_steg_config_t() +{ +} + +steg_t * +nosteg_steg_config_t::steg_create(conn_t *conn) +{ + return new nosteg_steg_t(this, conn); +} + +nosteg_steg_t::nosteg_steg_t(nosteg_steg_config_t *cf, conn_t *cn) + : config(cf), conn(cn) +{ +} + +nosteg_steg_t::~nosteg_steg_t() { }
-nosteg::~nosteg() +steg_config_t * +nosteg_steg_t::cfg() { + return config; }
size_t -nosteg::transmit_room(conn_t *) +nosteg_steg_t::transmit_room() { return SIZE_MAX; }
int -nosteg::transmit(struct evbuffer *source, conn_t *conn) +nosteg_steg_t::transmit(struct evbuffer *source) { struct evbuffer *dest = conn->outbound();
@@ -79,7 +109,7 @@ nosteg::transmit(struct evbuffer *source, conn_t *conn) }
int -nosteg::receive(conn_t *conn, struct evbuffer *dest) +nosteg_steg_t::receive(struct evbuffer *dest) { struct evbuffer *source = conn->inbound();
diff --git a/src/steg/nosteg_rr.cc b/src/steg/nosteg_rr.cc index 70e376e..8b316bb 100644 --- a/src/steg/nosteg_rr.cc +++ b/src/steg/nosteg_rr.cc @@ -39,35 +39,67 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <event2/buffer.h>
namespace { -struct nosteg_rr : steg_t -{ - bool can_transmit : 1; - bool did_transmit : 1; - STEG_DECLARE_METHODS(nosteg_rr); -}; + struct nosteg_rr_steg_config_t : steg_config_t + { + STEG_CONFIG_DECLARE_METHODS(nosteg_rr); + }; + + struct nosteg_rr_steg_t : steg_t + { + nosteg_rr_steg_config_t *config; + conn_t *conn; + + bool can_transmit : 1; + bool did_transmit : 1; + + nosteg_rr_steg_t(nosteg_rr_steg_config_t *cf, conn_t *cn); + STEG_DECLARE_METHODS(nosteg_rr); + }; }
STEG_DEFINE_MODULE(nosteg_rr);
-nosteg_rr::nosteg_rr(bool is_clientside) - : steg_t(is_clientside), - can_transmit(is_clientside), +nosteg_rr_steg_config_t::nosteg_rr_steg_config_t(config_t *cfg) + : steg_config_t(cfg) +{ +} + +nosteg_rr_steg_config_t::~nosteg_rr_steg_config_t() +{ +} + +steg_t * +nosteg_rr_steg_config_t::steg_create(conn_t *conn) +{ + return new nosteg_rr_steg_t(this, conn); +} + +nosteg_rr_steg_t::nosteg_rr_steg_t(nosteg_rr_steg_config_t *cf, + conn_t *cn) + : config(cf), conn(cn), + can_transmit(cf->cfg->mode != LSN_SIMPLE_SERVER), did_transmit(false) { }
-nosteg_rr::~nosteg_rr() +nosteg_rr_steg_t::~nosteg_rr_steg_t() +{ +} + +steg_config_t * +nosteg_rr_steg_t::cfg() { + return config; }
size_t -nosteg_rr::transmit_room(conn_t *) +nosteg_rr_steg_t::transmit_room() { return can_transmit ? SIZE_MAX : 0; }
int -nosteg_rr::transmit(struct evbuffer *source, conn_t *conn) +nosteg_rr_steg_t::transmit(struct evbuffer *source) { log_assert(can_transmit);
@@ -89,12 +121,12 @@ nosteg_rr::transmit(struct evbuffer *source, conn_t *conn) }
int -nosteg_rr::receive(conn_t *conn, struct evbuffer *dest) +nosteg_rr_steg_t::receive(struct evbuffer *dest) { struct evbuffer *source = conn->inbound();
log_debug(conn, "%s-side receiving %lu bytes", - is_clientside ? "client" : "server", + config->cfg->mode == LSN_SIMPLE_SERVER ? "server" : "client", (unsigned long)evbuffer_get_length(source));
if (evbuffer_add_buffer(dest, source)) { @@ -102,7 +134,7 @@ nosteg_rr::receive(conn_t *conn, struct evbuffer *dest) return -1; }
- if (is_clientside) { + if (config->cfg->mode != LSN_SIMPLE_SERVER) { conn->expect_close(); } else if (!did_transmit) { can_transmit = true;
tor-commits@lists.torproject.org