tor-commits
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 1 participants
- 215042 discussions
[obfsproxy/master] Add a whole bunch more logging and test framework tracking. Properly distinguish BEV_EVENT_EOF from BEV_EVENT_ERROR in error_cb (flush_error_cb and pending_socks_cb are still sloppy).
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit dfdc4fb57b2633359d41a993d78bc3ae8f7b92fc
Author: Zack Weinberg <zackw(a)panix.com>
Date: Wed Jul 27 17:06:41 2011 -0700
Add a whole bunch more logging and test framework tracking. Properly distinguish BEV_EVENT_EOF from BEV_EVENT_ERROR in error_cb (flush_error_cb and pending_socks_cb are still sloppy).
---
src/main.c | 1 +
src/network.c | 91 +++++++++++++++++++------
src/network.h | 2 +
src/test/tester.py.in | 183 ++++++++++++++++++++++++++++--------------------
src/util.c | 41 +++++++++++
src/util.h | 4 +
6 files changed, 226 insertions(+), 96 deletions(-)
diff --git a/src/main.c b/src/main.c
index f6280c2..1459af3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -91,6 +91,7 @@ handle_signal_cb(evutil_socket_t fd, short what, void *arg)
void
finish_shutdown(void)
{
+ log_debug("Finishing shutdown.");
event_base_loopexit(the_event_base, NULL);
}
diff --git a/src/network.c b/src/network.c
index f05c5b8..7831a4e 100644
--- a/src/network.c
+++ b/src/network.c
@@ -92,6 +92,8 @@ static void pending_socks_cb(struct bufferevent *bev, short what, void *arg);
void
start_shutdown(int barbaric)
{
+ log_debug("Beginning %s shutdown.", barbaric ? "barbaric" : "normal");
+
if (!shutting_down)
shutting_down=1;
@@ -115,6 +117,7 @@ close_all_connections(void)
{
if (!connections)
return;
+ log_debug("Closing all connections.");
SMARTLIST_FOREACH(connections, conn_t *, conn,
{ conn_free(conn); });
smartlist_free(connections);
@@ -143,6 +146,8 @@ create_listener(struct event_base *base, protocol_params_t *params)
default: obfs_abort();
}
+ lsn->address = printable_address(params->listen_addr->ai_addr,
+ params->listen_addr->ai_addrlen);
lsn->proto_params = params;
lsn->listener =
evconnlistener_new_bind(base, callback, lsn, flags, -1,
@@ -156,6 +161,9 @@ create_listener(struct event_base *base, protocol_params_t *params)
return 0;
}
+ log_debug("Now listening on %s in mode %d, protocol %s.",
+ lsn->address, params->mode, params->vtable->name);
+
/* If we don't have a listener list, create one now. */
if (!listeners)
listeners = smartlist_create();
@@ -170,6 +178,8 @@ create_listener(struct event_base *base, protocol_params_t *params)
static void
listener_free(listener_t *lsn)
{
+ if (lsn->address)
+ free(lsn->address);
if (lsn->listener)
evconnlistener_free(lsn->listener);
if (lsn->proto_params)
@@ -206,7 +216,9 @@ simple_client_listener_cb(struct evconnlistener *evcl,
struct event_base *base;
conn_t *conn = xzalloc(sizeof(conn_t));
- log_debug("%s: connection attempt.", __func__);
+ conn->peername = printable_address(sourceaddr, socklen);
+ log_debug("%s: connection to %s from %s", __func__,
+ lsn->address, conn->peername);
conn->mode = lsn->proto_params->mode;
obfs_assert(conn->mode == LSN_SIMPLE_CLIENT);
@@ -280,7 +292,9 @@ socks_client_listener_cb(struct evconnlistener *evcl,
struct event_base *base;
conn_t *conn = xzalloc(sizeof(conn_t));
- log_debug("%s: connection attempt.", __func__);
+ conn->peername = printable_address(sourceaddr, socklen);
+ log_debug("%s: connection to %s from %s", __func__,
+ lsn->address, conn->peername);
conn->mode = lsn->proto_params->mode;
obfs_assert(conn->mode == LSN_SOCKS_CLIENT);
@@ -336,7 +350,9 @@ simple_server_listener_cb(struct evconnlistener *evcl,
struct event_base *base;
conn_t *conn = xzalloc(sizeof(conn_t));
- log_debug("%s: connection attempt.", __func__);
+ conn->peername = printable_address(sourceaddr, socklen);
+ log_debug("%s: connection to %s from %s", __func__,
+ lsn->address, conn->peername);
conn->mode = lsn->proto_params->mode;
obfs_assert(conn->mode == LSN_SIMPLE_SERVER);
@@ -403,6 +419,8 @@ simple_server_listener_cb(struct evconnlistener *evcl,
static void
conn_free(conn_t *conn)
{
+ if (conn->peername)
+ free(conn->peername);
if (conn->proto)
proto_destroy(conn->proto);
if (conn->socks_state)
@@ -423,10 +441,11 @@ static void
close_conn(conn_t *conn)
{
obfs_assert(connections);
+ log_debug("Closing connection from %s; %d remaining",
+ conn->peername, smartlist_len(connections) - 1);
+
smartlist_remove(connections, conn);
conn_free(conn);
- log_debug("Connection destroyed. "
- "We currently have %d connections!", smartlist_len(connections));
/* If this was the last connection AND we are shutting down,
finish shutdown. */
@@ -447,6 +466,7 @@ static void
close_conn_on_flush(struct bufferevent *bev, void *arg)
{
conn_t *conn = arg;
+ log_debug("%s for %s", __func__, conn->peername);
if (evbuffer_get_length(bufferevent_get_output(bev)) == 0)
close_conn(conn);
@@ -460,6 +480,7 @@ socks_read_cb(struct bufferevent *bev, void *arg)
{
conn_t *conn = arg;
enum socks_ret socks_ret;
+ log_debug("%s for %s", __func__, conn->peername);
/* socks only makes sense on the upstream side */
obfs_assert(bev == conn->upstream);
@@ -534,9 +555,9 @@ static void
upstream_read_cb(struct bufferevent *bev, void *arg)
{
conn_t *conn = arg;
+ log_debug("%s for %s", __func__, conn->peername);
obfs_assert(bev == conn->upstream);
- log_debug("Got data on upstream side");
if (proto_send(conn->proto,
bufferevent_get_input(conn->upstream),
bufferevent_get_output(conn->downstream)) < 0)
@@ -553,9 +574,9 @@ downstream_read_cb(struct bufferevent *bev, void *arg)
{
conn_t *conn = arg;
enum recv_ret r;
+ log_debug("%s for %s", __func__, conn->peername);
obfs_assert(bev == conn->downstream);
- log_debug("Got data on downstream side");
r = proto_recv(conn->proto,
bufferevent_get_input(conn->downstream),
bufferevent_get_output(conn->upstream));
@@ -576,12 +597,12 @@ static void
error_or_eof(conn_t *conn, struct bufferevent *bev_err)
{
struct bufferevent *bev_flush;
+ log_debug("%s for %s", __func__, conn->peername);
if (bev_err == conn->upstream) bev_flush = conn->downstream;
else if (bev_err == conn->downstream) bev_flush = conn->upstream;
else obfs_abort();
- log_debug("error_or_eof");
if (conn->flushing || !conn->is_open ||
evbuffer_get_length(bufferevent_get_output(bev_flush)) == 0) {
close_conn(conn);
@@ -607,17 +628,35 @@ error_or_eof(conn_t *conn, struct bufferevent *bev_err)
static void
error_cb(struct bufferevent *bev, short what, void *arg)
{
+ conn_t *conn = arg;
+ int errcode = EVUTIL_SOCKET_ERROR();
+ log_debug("%s for %s: what=%x err=%d", __func__, conn->peername,
+ what, errcode);
+
/* It should be impossible to get here with BEV_EVENT_CONNECTED. */
obfs_assert(what & (BEV_EVENT_EOF|BEV_EVENT_ERROR|BEV_EVENT_TIMEOUT));
obfs_assert(!(what & BEV_EVENT_CONNECTED));
- /* If we get EAGAIN or EINPROGRESS here, something has gone horribly
- wrong. */
- obfs_assert(EVUTIL_SOCKET_ERROR() != EAGAIN &&
- EVUTIL_SOCKET_ERROR() != EINPROGRESS);
-
- log_warn("Got error: %s",
- evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
+ if (what & BEV_EVENT_ERROR) {
+ /* If we get EAGAIN, EINTR, or EINPROGRESS here, something has
+ gone horribly wrong. */
+ obfs_assert(errcode != EAGAIN && errcode != EINTR &&
+ errcode != EINPROGRESS);
+
+ log_warn("Error on %s side of connection from %s: %s",
+ bev == conn->upstream ? "upstream" : "downstream",
+ conn->peername,
+ evutil_socket_error_to_string(errcode));
+ } else if (what & BEV_EVENT_EOF) {
+ log_info("EOF on %s side of connection from %s",
+ bev == conn->upstream ? "upstream" : "downstream",
+ conn->peername);
+ } else {
+ obfs_assert(what & BEV_EVENT_TIMEOUT);
+ log_info("Timeout on %s side of connection from %s",
+ bev == conn->upstream ? "upstream" : "downstream",
+ conn->peername);
+ }
error_or_eof(arg, bev);
}
@@ -629,6 +668,9 @@ static void
flush_error_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = arg;
+ int errcode = EVUTIL_SOCKET_ERROR();
+ log_debug("%s for %s: what=%x err=%d", __func__, conn->peername,
+ what, errcode);
/* It should be impossible to get here with BEV_EVENT_CONNECTED. */
obfs_assert(what & (BEV_EVENT_EOF|BEV_EVENT_ERROR|BEV_EVENT_TIMEOUT));
@@ -636,8 +678,10 @@ flush_error_cb(struct bufferevent *bev, short what, void *arg)
obfs_assert(conn->flushing);
- log_warn("Error during flush: %s",
- evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
+ log_warn("Error during flush of %s side of connection from %s: %s",
+ bev == conn->upstream ? "upstream" : "downstream",
+ conn->peername,
+ evutil_socket_error_to_string(errcode));
close_conn(conn);
return;
}
@@ -653,6 +697,8 @@ pending_conn_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = arg;
struct bufferevent *other;
+ log_debug("%s for %s", __func__, conn->peername);
+
if (bev == conn->upstream) other = conn->downstream;
else if (bev == conn->downstream) other = conn->upstream;
else obfs_abort();
@@ -663,13 +709,15 @@ pending_conn_cb(struct bufferevent *bev, short what, void *arg)
obfs_assert(!conn->flushing);
conn->is_open = 1;
- log_debug("Connection successful");
- bufferevent_enable(other, EV_READ|EV_WRITE);
+ log_debug("Successful %s connection for %s",
+ bev == conn->upstream ? "upstream" : "downstream",
+ conn->peername);
/* XXX Dirty access to bufferevent guts. There appears to be no
official API to retrieve the callback functions and/or change
just one callback while leaving the others intact. */
bufferevent_setcb(bev, bev->readcb, bev->writecb, error_cb, conn);
+ bufferevent_enable(other, EV_READ|EV_WRITE);
return;
}
@@ -686,13 +734,16 @@ static void
pending_socks_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = arg;
+ log_debug("%s for %s", __func__, conn->peername);
obfs_assert(bev == conn->downstream);
obfs_assert(conn->socks_state);
/* If we got an error while in the ST_HAVE_ADDR state, chances are
that we failed connecting to the host requested by the CONNECT
call. This means that we should send a negative SOCKS reply back
- to the client and terminate the connection. */
+ to the client and terminate the connection.
+ XXX properly distinguish BEV_EVENT_EOF from BEV_EVENT_ERROR;
+ errno isn't meaningful in that case... */
if ((what & (BEV_EVENT_EOF|BEV_EVENT_ERROR|BEV_EVENT_TIMEOUT))) {
int err = EVUTIL_SOCKET_ERROR();
log_warn("Connection error: %s",
diff --git a/src/network.h b/src/network.h
index c5ef69e..4ae96fc 100644
--- a/src/network.h
+++ b/src/network.h
@@ -14,11 +14,13 @@ void start_shutdown(int barbaric);
#ifdef NETWORK_PRIVATE
typedef struct listener_t {
+ char *address;
protocol_params_t *proto_params;
struct evconnlistener *listener;
} listener_t;
typedef struct conn_t {
+ char *peername;
protocol_t *proto;
socks_state_t *socks_state;
struct bufferevent *upstream;
diff --git a/src/test/tester.py.in b/src/test/tester.py.in
index 104026c..d9040fe 100644
--- a/src/test/tester.py.in
+++ b/src/test/tester.py.in
@@ -7,16 +7,86 @@
# You need to be able to make connections to arbitrary high-numbered
# TCP ports on the loopback interface.
+import difflib
import errno
import multiprocessing
import Queue
+import re
import signal
import socket
import struct
import subprocess
import time
+import traceback
import unittest
+# Helper: generate unified-format diffs between two named strings.
+# Pythonic escaped-string syntax is used for unprintable characters.
+
+def diff(label, expected, received):
+ if expected == received:
+ return ""
+ else:
+ return (label + "\n"
+ + "\n".join(s.encode("string_escape")
+ for s in
+ difflib.unified_diff(expected.split("\n"),
+ received.split("\n"),
+ "expected", "received",
+ lineterm=""))
+ + "\n")
+
+# Helper: Run obfsproxy instances and confirm that they have
+# completed without any errors.
+
+class Obfsproxy(subprocess.Popen):
+ def __init__(self, *args, **kwargs):
+ argv = ["./obfsproxy", "--log-min-severity=debug"]
+ if len(args) == 1 and (isinstance(args[0], list) or
+ isinstance(args[0], tuple)):
+ argv.extend(args[0])
+ else:
+ argv.extend(args)
+
+ subprocess.Popen.__init__(self, argv,
+ stdin=open("/dev/null", "r"),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ **kwargs)
+
+ severe_error_re = re.compile(r"\[(?:warn|err(?:or)?)\]")
+
+ def check_completion(self, label):
+ if self.poll() is None:
+ self.send_signal(signal.SIGINT)
+
+ (out, err) = self.communicate()
+
+ report = ""
+ def indent(s):
+ return "| " + "\n| ".join(s.strip().split("\n"))
+
+ # exit status should be zero
+ if self.returncode > 0:
+ report += label + " exit code: %d\n" % self.returncode
+ elif self.returncode < 0:
+ report += label + " killed: signal %d\n" % -self.returncode
+
+ # there should be nothing on stdout
+ if out != "":
+ report += label + " stdout:\n%s\n" % indent(out)
+
+ # there will be debugging messages on stderr, but there should be
+ # no [warn], [err], or [error] messages.
+ if self.severe_error_re.search(err):
+ report += label + " stderr:\n%s\n" % indent(err)
+
+ return report
+
+ def stop(self):
+ if self.poll() is None:
+ self.terminate()
+
# Helper: Repeatedly try to connect to the specified server socket
# until either it succeeds or one full second has elapsed. (Surely
# there is a better way to do this?)
@@ -89,32 +159,14 @@ EXIT_PORT = 5001
class DirectTest(object):
def setUp(self):
self.output_reader = ReadWorker(("127.0.0.1", EXIT_PORT))
- self.obfs = subprocess.Popen(
- self.obfs_args,
- stdin=open("/dev/null", "r"),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
-
+ self.obfs = Obfsproxy(self.obfs_args)
self.input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
self.input_chan.settimeout(1.0)
def tearDown(self):
- if self.obfs.returncode is None:
- self.obfs.terminate()
+ self.obfs.stop()
self.output_reader.stop()
-
- def checkSubprocesses(self):
- if self.obfs.poll() is None:
- self.obfs.send_signal(signal.SIGINT)
-
- (out, err) = self.obfs.communicate()
-
- if (out != "" or err != "" or self.obfs.returncode != 0):
- self.fail("obfsproxy process failure:\n"
- "\treturn code: %d\n"
- "\tstdout: %s\n"
- "\tstderr: %s\n"
- % (self.obfs.returncode, out, err))
+ self.input_chan.close()
def test_direct_transfer(self):
# Open a server and a simple client (in the same process) and
@@ -127,8 +179,11 @@ class DirectTest(object):
except Queue.Empty:
output = ""
- self.checkSubprocesses()
- self.assertEqual(output, TEST_FILE)
+ report = self.obfs.check_completion("obfsproxy")
+ report += diff("errors in transfer:", TEST_FILE, output)
+
+ if report != "":
+ self.fail("\n" + report)
# Same as above, but we use a socks client instead of a simple client,
# and the server's a separate process.
@@ -136,47 +191,14 @@ class DirectTest(object):
class SocksTest(object):
def setUp(self):
self.output_reader = ReadWorker(("127.0.0.1", EXIT_PORT))
- self.obfs_server = subprocess.Popen(
- self.server_args,
- stdin=open("/dev/null", "r"),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- self.obfs_client = subprocess.Popen(
- self.client_args,
- stdin=open("/dev/null", "r"),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
+ self.obfs_server = Obfsproxy(self.server_args)
+ self.obfs_client = Obfsproxy(self.client_args)
def tearDown(self):
- if self.obfs_server.returncode is None:
- self.obfs_server.terminate()
- if self.obfs_client.returncode is None:
- self.obfs_client.terminate()
+ self.obfs_server.stop()
+ self.obfs_client.stop()
self.output_reader.stop()
- def checkSubprocesses(self):
- if self.obfs_server.poll() is None:
- self.obfs_server.send_signal(signal.SIGINT)
- if self.obfs_client.poll() is None:
- self.obfs_client.send_signal(signal.SIGINT)
-
- (sout, serr) = self.obfs_server.communicate()
- (cout, cerr) = self.obfs_client.communicate()
-
- if (sout != "" or serr != "" or cout != "" or cerr != ""
- or self.obfs_server.returncode != 0
- or self.obfs_client.returncode != 0):
- self.fail("obfsproxy process failures:\n"
- "\tclient return code: %d\n"
- "\tserver return code: %d\n"
- "\tclient stdout: %s\n"
- "\tclient stderr: %s\n"
- "\tserver stdout: %s\n"
- "\tserver stderr: %s\n"
- % (self.obfs_client.returncode,
- self.obfs_server.returncode,
- cout, cerr, sout, serr))
-
# 'sequence' is a sequence of SOCKS[45] protocol messages
# which we will send or receive. Sends alternate with
# receives. Each entry may be a string, which is sent or
@@ -187,7 +209,7 @@ class SocksTest(object):
# the SOCKS sequence without the server having dropped the
# connection, we transmit the test file and expect to get it
# back from the far end.
- def socksTest(self, sequence):
+ def socksTestInner(self, sequence):
sending = True
good = True
input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
@@ -230,10 +252,25 @@ class SocksTest(object):
output = ""
input_chan.close()
- self.checkSubprocesses()
+ if good: return output
+ else: return None
- if good:
- self.assertEqual(output, TEST_FILE)
+ def socksTest(self, sequence):
+ try:
+ output = self.socksTestInner(sequence)
+ report = ""
+ except Exception:
+ output = None
+ report = traceback.format_exc()
+
+ report += self.obfs_server.check_completion("obfsproxy server")
+ report += self.obfs_client.check_completion("obfsproxy client")
+
+ if output is not None:
+ report += diff("errors in transfer:", TEST_FILE, output)
+
+ if report != "":
+ self.fail("\n" + report)
def test_illformed(self):
@@ -295,8 +332,7 @@ class SocksTest(object):
#
class DirectObfs2(DirectTest, unittest.TestCase):
- obfs_args = ("./obfsproxy", "--log-min-severity=warn",
- "obfs2",
+ obfs_args = ("obfs2",
"--dest=127.0.0.1:%d" % EXIT_PORT,
"server", "127.0.0.1:%d" % SERVER_PORT,
"+", "obfs2",
@@ -304,8 +340,7 @@ class DirectObfs2(DirectTest, unittest.TestCase):
"client", "127.0.0.1:%d" % ENTRY_PORT)
class DirectDummy(DirectTest, unittest.TestCase):
- obfs_args = ("./obfsproxy", "--log-min-severity=warn",
- "dummy", "server",
+ obfs_args = ("dummy", "server",
"127.0.0.1:%d" % SERVER_PORT,
"127.0.0.1:%d" % EXIT_PORT,
"+", "dummy", "client",
@@ -313,21 +348,17 @@ class DirectDummy(DirectTest, unittest.TestCase):
"127.0.0.1:%d" % SERVER_PORT)
class SocksObfs2(SocksTest, unittest.TestCase):
- server_args = ("./obfsproxy", "--log-min-severity=warn",
- "obfs2",
+ server_args = ("obfs2",
"--dest=127.0.0.1:%d" % EXIT_PORT,
"server", "127.0.0.1:%d" % SERVER_PORT)
- client_args = ("./obfsproxy", "--log-min-severity=warn",
- "obfs2",
+ client_args = ("obfs2",
"socks", "127.0.0.1:%d" % ENTRY_PORT)
class SocksDummy(SocksTest, unittest.TestCase):
- server_args = ("./obfsproxy", "--log-min-severity=warn",
- "dummy", "server",
+ server_args = ("dummy", "server",
"127.0.0.1:%d" % SERVER_PORT,
"127.0.0.1:%d" % EXIT_PORT)
- client_args = ("./obfsproxy", "--log-min-severity=warn",
- "dummy", "socks",
+ client_args = ("dummy", "socks",
"127.0.0.1:%d" % ENTRY_PORT)
TEST_FILE = """\
diff --git a/src/util.c b/src/util.c
index e44b131..46d4b42 100644
--- a/src/util.c
+++ b/src/util.c
@@ -10,6 +10,10 @@
#include <unistd.h>
#include <event2/dns.h>
+#include <arpa/inet.h>
+#ifdef AF_LOCAL
+#include <sys/un.h>
+#endif
/** Any size_t larger than this amount is likely to be an underflow. */
#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
@@ -195,6 +199,43 @@ resolve_address_port(const char *address, int nodns, int passive,
return ai;
}
+char *
+printable_address(struct sockaddr *addr, socklen_t addrlen)
+{
+ char abuf[INET6_ADDRSTRLEN];
+ char apbuf[INET6_ADDRSTRLEN + 8]; /* []:65535 is 8 characters */
+
+ switch (addr->sa_family) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (struct sockaddr_in*)addr;
+ if (!inet_ntop(AF_INET, &sin->sin_addr, abuf, INET6_ADDRSTRLEN))
+ break;
+ obfs_snprintf(apbuf, sizeof apbuf, "%s:%d", abuf, ntohs(sin->sin_port));
+ return xstrdup(apbuf);
+ }
+
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
+ if (!inet_ntop(AF_INET, &sin6->sin6_addr, abuf, INET6_ADDRSTRLEN))
+ break;
+ obfs_snprintf(apbuf, sizeof apbuf, "[%s]:%d", abuf,
+ ntohs(sin6->sin6_port));
+ return xstrdup(apbuf);
+ }
+
+#ifdef AF_LOCAL
+ case AF_LOCAL:
+ return xstrdup(((struct sockaddr_un*)addr)->sun_path);
+#endif
+ default:
+ break;
+ }
+
+ obfs_snprintf(apbuf, sizeof apbuf,
+ "<addr family %d>", addr->sa_family);
+ return xstrdup(apbuf);
+}
+
static struct evdns_base *the_evdns_base = NULL;
struct evdns_base *
diff --git a/src/util.h b/src/util.h
index 4fc1a33..5108b62 100644
--- a/src/util.h
+++ b/src/util.h
@@ -93,6 +93,10 @@ struct evutil_addrinfo *resolve_address_port(const char *address,
int nodns, int passive,
const char *default_port);
+/** Produce a printable name for this sockaddr. The result is in
+ malloced memory. */
+char *printable_address(struct sockaddr *addr, socklen_t addrlen);
+
struct evdns_base *get_evdns_base(void);
int init_evdns_base(struct event_base *base);
1
0
[obfsproxy/master] Add a stub integration test runner in Python, which will eventually subsume the existing integration test fragments.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 3a3d2e47428d92e1953bddf02dec0840cedb9992
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 25 17:11:27 2011 -0700
Add a stub integration test runner in Python, which will eventually subsume the existing integration test fragments.
---
Makefile.am | 10 ++++++++++
configure.ac | 8 ++++++++
src/test/tester.py.in | 18 ++++++++++++++++++
3 files changed, 36 insertions(+), 0 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index fe47256..5a815ff 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -51,3 +51,13 @@ noinst_HEADERS = \
EXTRA_DIST = doc/protocol-spec.txt
TESTS = unittests
+
+if HAVE_PYTHON
+TESTS += tester.py
+noinst_PROGRAMS += tester.py
+tester_py_SOURCES = src/test/tester.py.in
+
+tester.py: src/test/tester.py.in Makefile
+ $(SED) -e 's,[@]PYTHON[@],$(PYTHON),' < $< > $@
+ chmod +x $@
+endif
diff --git a/configure.ac b/configure.ac
index 08d21c3..ceeec89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -13,6 +13,14 @@ m4_pushdef([AC_INCLUDES_DEFAULT], [$1])
AC_PROG_CC
AC_PROG_RANLIB
+AC_PROG_SED
+
+AM_PATH_PYTHON([2.6],, [:])
+AM_CONDITIONAL([HAVE_PYTHON], [test "$PYTHON" != ":"])
+if test "$PYTHON" == ":"; then
+ AC_MSG_WARN([Python interpreter not found; integration tests disabled.])
+fi
+
PKG_PROG_PKG_CONFIG
### Libraries ###
diff --git a/src/test/tester.py.in b/src/test/tester.py.in
new file mode 100644
index 0000000..d330e69
--- /dev/null
+++ b/src/test/tester.py.in
@@ -0,0 +1,18 @@
+#! @PYTHON@
+
+# Integration tests for obfsproxy.
+#
+# The obfsproxy binary is assumed to exist in the current working
+# directory, and you need to have Python 2.6 or better (but not 3).
+# You need to be able to make connections to arbitrary high-numbered
+# TCP ports on the loopback interface (there is, however, an effort to
+# figure out which ones are already in use) and all IPv4 addresses in
+# 127.0.0/24 are assumed to be bound to the loopback interface.
+
+import socket
+import struct
+import subprocess
+import sys
+
+print "All tests successful."
+sys.exit(0)
1
0
09 Sep '11
commit 4d13c443f016d9a68e4af851454c69d312e57954
Author: Zack Weinberg <zackw(a)panix.com>
Date: Tue Jul 26 15:46:36 2011 -0700
Diagnostic logs belong on stderr, not stdout
---
src/test/unittest_dummy.c | 2 +-
src/test/unittest_obfs2.c | 2 +-
src/util.c | 6 +++---
src/util.h | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/test/unittest_dummy.c b/src/test/unittest_dummy.c
index aaeafa9..6470528 100644
--- a/src/test/unittest_dummy.c
+++ b/src/test/unittest_dummy.c
@@ -58,7 +58,7 @@ test_dummy_option_parsing(void *unused)
proto_params_free(c->result);
/* Unsuspend logging */
- log_set_method(LOG_METHOD_STDOUT, NULL);
+ log_set_method(LOG_METHOD_STDERR, NULL);
}
/* All the tests below use this test environment: */
diff --git a/src/test/unittest_obfs2.c b/src/test/unittest_obfs2.c
index 6767769..c6d793c 100644
--- a/src/test/unittest_obfs2.c
+++ b/src/test/unittest_obfs2.c
@@ -71,7 +71,7 @@ test_obfs2_option_parsing(void *unused)
proto_params_free(c->result);
/* Unsuspend logging */
- log_set_method(LOG_METHOD_STDOUT, NULL);
+ log_set_method(LOG_METHOD_STDERR, NULL);
}
/* All the tests below use this test environment: */
diff --git a/src/util.c b/src/util.c
index 167e867..e44b131 100644
--- a/src/util.c
+++ b/src/util.c
@@ -298,7 +298,7 @@ ascii_strlower(char *s)
#define LOG_SEV_DEBUG 1
/* logging method */
-static int logging_method=LOG_METHOD_STDOUT;
+static int logging_method=LOG_METHOD_STDERR;
/* minimum logging severity */
static int logging_min_sev=LOG_SEV_INFO;
/* logfile fd */
@@ -473,8 +473,8 @@ logv(int severity, const char *format, va_list ap)
buf[n]='\n';
buf[n+1]='\0';
- if (logging_method == LOG_METHOD_STDOUT)
- fprintf(stdout, "%s", buf);
+ if (logging_method == LOG_METHOD_STDERR)
+ fprintf(stderr, "%s", buf);
else if (logging_method == LOG_METHOD_FILE) {
if (!logging_logfile)
abort();
diff --git a/src/util.h b/src/util.h
index ede23e4..4fc1a33 100644
--- a/src/util.h
+++ b/src/util.h
@@ -120,8 +120,8 @@ int obfs_snprintf(char *str, size_t size,
/** Log destinations */
-/** Spit log messages on stdout. */
-#define LOG_METHOD_STDOUT 1
+/** Spit log messages on stderr. */
+#define LOG_METHOD_STDERR 1
/** Place log messages in a file. */
#define LOG_METHOD_FILE 2
/** We don't want no logs. */
1
0
[obfsproxy/master] Tweak the socks tests so they actually test what they're supposed to. No need to repeat the bad-socks-dialogue tests for every obfuscation protocol.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 686b25171e1d82240e00ba5088ff41d98a085c9b
Author: Zack Weinberg <zackw(a)panix.com>
Date: Thu Jul 28 14:06:05 2011 -0700
Tweak the socks tests so they actually test what they're supposed to. No need to repeat the bad-socks-dialogue tests for every obfuscation protocol.
---
src/test/tester.py.in | 90 ++++++++++++++++++++++++++++++-------------------
1 files changed, 55 insertions(+), 35 deletions(-)
diff --git a/src/test/tester.py.in b/src/test/tester.py.in
index d9040fe..916c1a0 100644
--- a/src/test/tester.py.in
+++ b/src/test/tester.py.in
@@ -56,7 +56,7 @@ class Obfsproxy(subprocess.Popen):
severe_error_re = re.compile(r"\[(?:warn|err(?:or)?)\]")
- def check_completion(self, label):
+ def check_completion(self, label, force_stderr):
if self.poll() is None:
self.send_signal(signal.SIGINT)
@@ -78,7 +78,7 @@ class Obfsproxy(subprocess.Popen):
# there will be debugging messages on stderr, but there should be
# no [warn], [err], or [error] messages.
- if self.severe_error_re.search(err):
+ if force_stderr or self.severe_error_re.search(err):
report += label + " stderr:\n%s\n" % indent(err)
return report
@@ -115,6 +115,8 @@ class ReadWorker(object):
listener.bind(address)
listener.listen(1)
(conn, remote) = listener.accept()
+ listener.close()
+ conn.settimeout(1.0)
data = ""
try:
while True:
@@ -124,7 +126,6 @@ class ReadWorker(object):
except Exception, e:
data += "|RECV ERROR: " + e
conn.close()
- listener.close()
oq.put(data)
def __init__(self, address):
@@ -179,8 +180,9 @@ class DirectTest(object):
except Queue.Empty:
output = ""
- report = self.obfs.check_completion("obfsproxy")
- report += diff("errors in transfer:", TEST_FILE, output)
+ report = diff("errors in transfer:", TEST_FILE, output)
+
+ report += self.obfs.check_completion("obfsproxy", report!="")
if report != "":
self.fail("\n" + report)
@@ -209,12 +211,9 @@ class SocksTest(object):
# the SOCKS sequence without the server having dropped the
# connection, we transmit the test file and expect to get it
# back from the far end.
- def socksTestInner(self, sequence):
+ def socksTestInner(self, sequence, input_chan):
sending = True
good = True
- input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
- input_chan.settimeout(1.0)
-
for msg in sequence:
if msg is False:
input_chan.shutdown(socket.SHUT_WR)
@@ -243,6 +242,7 @@ class SocksTest(object):
except socket.error, e:
if e.errno != errno.ECONNRESET: raise
self.assertEqual(got, exp)
+ sending = not sending
if good:
input_chan.sendall(TEST_FILE)
input_chan.shutdown(socket.SHUT_WR)
@@ -251,27 +251,57 @@ class SocksTest(object):
except Queue.Empty:
output = ""
- input_chan.close()
if good: return output
else: return None
def socksTest(self, sequence):
+ input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
+ input_chan.settimeout(1.0)
+
try:
- output = self.socksTestInner(sequence)
+ output = self.socksTestInner(sequence, input_chan)
report = ""
except Exception:
output = None
report = traceback.format_exc()
- report += self.obfs_server.check_completion("obfsproxy server")
- report += self.obfs_client.check_completion("obfsproxy client")
+ input_chan.close()
if output is not None:
report += diff("errors in transfer:", TEST_FILE, output)
+ fs = report != ""
+
+ report += self.obfs_server.check_completion("obfsproxy server", fs)
+ report += self.obfs_client.check_completion("obfsproxy client", fs)
+
if report != "":
self.fail("\n" + report)
+class GoodSocksTest(SocksTest):
+ # Test methods for good SOCKS dialogues; these should be repeated for each
+ # protocol.
+
+ def test_socks4_connect(self):
+ # SOCKS4 connection request - should succeed
+ self.socksTest([ ( (4, 1, SERVER_PORT, 127, 0, 0, 1, 0), "!BBH5B" ),
+ ( (0, 90, SERVER_PORT, 127, 0, 0, 1), "!BBH4B" ) ])
+
+ def test_socks5_connect(self):
+ self.socksTest([ "\x05\x01\x00", "\x05\x00",
+ ( (5, 1, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
+ ( (5, 0, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ) ])
+
+#
+# Concrete test classes that are not protocol-specific.
+#
+
+class SocksBad(SocksTest, unittest.TestCase):
+ server_args = ("dummy", "server",
+ "127.0.0.1:%d" % SERVER_PORT,
+ "127.0.0.1:%d" % EXIT_PORT)
+ client_args = ("dummy", "socks",
+ "127.0.0.1:%d" % ENTRY_PORT)
def test_illformed(self):
# ill-formed socks message - server should drop connection
@@ -284,11 +314,6 @@ class SocksTest(object):
self.socksTest([ ( (4, 2, SERVER_PORT, 127, 0, 0, 1, 0), "!BBH5B" ),
False ])
- def test_socks4_connect(self):
- # SOCKS4 connection request - should succeed
- self.socksTest([ ( (4, 1, SERVER_PORT, 127, 0, 0, 1, 0), "!BBH5B" ),
- ( (0, 90, SERVER_PORT, 127, 0, 0, 1), "!BBH4B" ) ])
-
def test_socks5_bad_handshake_1(self):
self.socksTest([ "\x05", False ])
@@ -296,36 +321,31 @@ class SocksTest(object):
self.socksTest([ "\x05\x00", False ])
def test_socks5_bad_handshake_3(self):
- self.socksTest([ "\x05\x01\x01", "\x05\xFF", False ])
+ self.socksTest([ "\x05\x01\x01", False ]) # should get "\x05\xFF"
def test_socks5_bad_handshake_4(self):
- self.socksTest([ "\x05\x01\x080", "\x05\xFF", False ])
+ self.socksTest([ "\x05\x01\x080", False ]) # should get "\x05\xFF"
def test_socks5_bad_handshake_5(self):
- self.socksTest([ "\x05\x02\x01\x02", "\x05\xFF", False ])
+ self.socksTest([ "\x05\x02\x01\x02", False ]) # should get "\x05\xFF"
- def test_socks5_bad_request_1(self):
- self.socksTest([ "\x05\x01\x00", "\x05\x00", "\x05\x00",
- "\x05\x07\x00", False ])
+ def test_socks5_good_handshake_1(self):
+ self.socksTest([ "\x05\x01\x00", "\x05\x00", False ])
- def test_socks5_bad_request_2(self):
- self.socksTest([ "\x05\x02\x00\x01", "\x05\x00", "\x05\x00",
- "\x05\x07\x00", False ])
+ def test_socks5_good_handshake_2(self):
+ self.socksTest([ "\x05\x02\x00\x01", "\x05\x00", False ])
def test_socks5_unsupported_method_1(self):
self.socksTest([ "\x05\x01\x00", "\x05\x00",
( (5, 2, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
- "\x05\x07\x00", False ])
+ "\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", False ])
def test_socks5_unsupported_method_2(self):
self.socksTest([ "\x05\x01\x00", "\x05\x00",
( (5, 3, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
- "\x05\x07\x00", False ])
+ "\x05\x07\x00\x01\x00\x00\x00\x00\x00\x00", False ])
+
- def test_socks5_connect(self):
- self.socksTest([ "\x05\x01\x00", "\x05\x00",
- ( (5, 1, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
- ( (5, 0, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ) ])
#
# Concrete test classes specialize the above base classes for each protocol.
@@ -347,14 +367,14 @@ class DirectDummy(DirectTest, unittest.TestCase):
"127.0.0.1:%d" % ENTRY_PORT,
"127.0.0.1:%d" % SERVER_PORT)
-class SocksObfs2(SocksTest, unittest.TestCase):
+class SocksObfs2(GoodSocksTest, unittest.TestCase):
server_args = ("obfs2",
"--dest=127.0.0.1:%d" % EXIT_PORT,
"server", "127.0.0.1:%d" % SERVER_PORT)
client_args = ("obfs2",
"socks", "127.0.0.1:%d" % ENTRY_PORT)
-class SocksDummy(SocksTest, unittest.TestCase):
+class SocksDummy(GoodSocksTest, unittest.TestCase):
server_args = ("dummy", "server",
"127.0.0.1:%d" % SERVER_PORT,
"127.0.0.1:%d" % EXIT_PORT)
1
0
[obfsproxy/master] Flesh tester.py.in out to subsume the existing non-automated integration tests. Note: all tests presently fail due to bugs introduced somewhere on this branch.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit a99ca9dd19d3fc8e290b04ad3af9251a43caa4d1
Author: Zack Weinberg <zackw(a)panix.com>
Date: Tue Jul 26 15:44:08 2011 -0700
Flesh tester.py.in out to subsume the existing non-automated integration tests. Note: all tests presently fail due to bugs introduced somewhere on this branch.
---
src/test/integration_test/alpha | 38 ----
src/test/integration_test/int_test.sh | 76 -------
src/test/test_socks_unsupported.py | 18 --
src/test/tester.py.in | 354 ++++++++++++++++++++++++++++++++-
4 files changed, 348 insertions(+), 138 deletions(-)
diff --git a/src/test/integration_test/alpha b/src/test/integration_test/alpha
deleted file mode 100644
index b6d68d6..0000000
--- a/src/test/integration_test/alpha
+++ /dev/null
@@ -1,38 +0,0 @@
-THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
-THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
-THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
-THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
-
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-"Can entropy ever be reversed?"
-"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
-
- In obfuscatory age geeky warfare did I wage
- For hiding bits from nasty censors' sight
- I was hacker to my set in that dim dark age of net
- And I hacked from noon till three or four at night
-
- Then a rival from Helsinki said my protocol was dinky
- So I flamed him with a condescending laugh,
- Saying his designs for stego might as well be made of lego
- And that my bikeshed was prettier by half.
-
- But Claude Shannon saw my shame. From his noiseless channel came
- A message sent with not a wasted byte
- "There are nine and sixty ways to disguise communiques
- And RATHER MORE THAN ONE OF THEM IS RIGHT"
-
- (apologies to Rudyard Kipling.)
diff --git a/src/test/integration_test/int_test.sh b/src/test/integration_test/int_test.sh
deleted file mode 100644
index 9aa37ac..0000000
--- a/src/test/integration_test/int_test.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/bash
-
-# replace this with your path to obfsproxy.
-OBFSPROXY="../../../obfsproxy"
-# replace this with your path to ncat.
-NCAT=ncat
-
-ENTRY_PORT=4999
-SERVER_PORT=5000
-NCAT_PORT=5001
-
-DIR=inttemp_temp
-FILE1=$DIR/test1
-FILE2=$DIR/test2
-
-mkdir -p $DIR ; :>$FILE1
-
-# TEST 1
-# We open a server and a client and transfer a file. Then we check if the output of the
-# server is the same as the file we sent.
-
-$NCAT -k -l -o $FILE1 -p $NCAT_PORT > /dev/null &
-ncat1_pid=$!
-
-
-$OBFSPROXY --log-min-severity=warn obfs2 --dest=127.0.0.1:$NCAT_PORT server 127.0.0.1:$SERVER_PORT \
- + obfs2 --dest=127.0.0.1:$SERVER_PORT client 127.0.0.1:$ENTRY_PORT &
-obfsproxy_pid=$!
-sleep 1
-
-
-$NCAT localhost $ENTRY_PORT < alpha &
-ncat2_pid=$!
-sleep 2
-
-if cmp -s alpha $FILE1
-then echo "GREAT SUCCESS 1!" ; rm $FILE1
-else echo "GREAT FAIL 1!"
-fi
-
-kill -9 $ncat1_pid
-kill -9 $obfsproxy_pid
-kill -9 $ncat2_pid
-
-sleep 2
-
-# TEST 2
-# We open an obfsproxy SOCKS server on the dummy protocol and an ncat listening.
-# Then we configure another ncat to use SOCKS4 and transfer a file to the other ncat.
-# Finally, we check if the file was sent correctly.
-
-:>$FILE2
-
-$NCAT -k -l -o $FILE2 -p $NCAT_PORT > /dev/null &
-ncat1_pid=$!
-
-$OBFSPROXY --log-min-severity=warn dummy socks 127.0.0.1:$SERVER_PORT &
-obfsproxy_pid=$!
-sleep 1
-
-$NCAT --proxy-type socks4 --proxy 127.0.0.1:$SERVER_PORT \
- 127.0.0.1 $NCAT_PORT < alpha &
-ncat2_pid=$!
-sleep 2
-
-if cmp -s alpha $FILE2
-then echo "GREAT SUCCESS 2!" ; rm $FILE2
-else echo "GREAT FAIL 2!"
-fi
-
-kill -9 $ncat1_pid
-kill -9 $obfsproxy_pid
-kill -9 $ncat2_pid
-
-rmdir $DIR
-
diff --git a/src/test/test_socks_unsupported.py b/src/test/test_socks_unsupported.py
deleted file mode 100644
index d1afd02..0000000
--- a/src/test/test_socks_unsupported.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import socket,struct
-
-negot = struct.pack('BBB', 5, 1, 0)
-request = struct.pack('BBBBBBB', 5, 2, 0, 1, 1, 1, 1)
-
-PORT = 4500
-
-s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-s.connect(("127.0.0.1",PORT))
-s.send(negot)
-s.recv(1024)
-s.send(request)
-data = s.recv(1024)
-if (struct.unpack('BBBBih', data)[1] == 7):
- print "Works."
-else:
- print "Fail!"
-
diff --git a/src/test/tester.py.in b/src/test/tester.py.in
index d330e69..b0602ed 100644
--- a/src/test/tester.py.in
+++ b/src/test/tester.py.in
@@ -5,14 +5,356 @@
# The obfsproxy binary is assumed to exist in the current working
# directory, and you need to have Python 2.6 or better (but not 3).
# You need to be able to make connections to arbitrary high-numbered
-# TCP ports on the loopback interface (there is, however, an effort to
-# figure out which ones are already in use) and all IPv4 addresses in
-# 127.0.0/24 are assumed to be bound to the loopback interface.
+# TCP ports on the loopback interface.
+import errno
+import multiprocessing
+import Queue
+import signal
import socket
import struct
import subprocess
-import sys
+import time
+import unittest
-print "All tests successful."
-sys.exit(0)
+# Helper: Repeatedly try to connect to the specified server socket
+# until either it succeeds or one full second has elapsed. (Surely
+# there is a better way to do this?)
+
+def connect_with_retry(addr):
+ retry = 0
+ while True:
+ try:
+ return socket.create_connection(addr)
+ except socket.error, e:
+ if e.errno != errno.ECONNREFUSED: raise
+ if retry == 20: raise
+ retry += 1
+ time.sleep(0.05)
+
+# Helper: In a separate process (to avoid deadlock), listen on a
+# specified socket. The first time something connects to that socket,
+# read all available data, stick it in a string, and post the string
+# to the output queue. Then close both sockets and exit.
+
+class ReadWorker(object):
+ @staticmethod
+ def work(address, oq):
+ listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ listener.bind(address)
+ listener.listen(1)
+ (conn, remote) = listener.accept()
+ data = ""
+ try:
+ while True:
+ chunk = conn.recv(4096)
+ if chunk == "": break
+ data += chunk
+ except Exception, e:
+ data += "|RECV ERROR: " + e
+ conn.close()
+ listener.close()
+ oq.put(data)
+
+ def __init__(self, address):
+ self.oq = multiprocessing.Queue()
+ self.worker = multiprocessing.Process(target=self.work,
+ args=(address, self.oq))
+ self.worker.start()
+
+ def get(self):
+ rv = self.oq.get(timeout=1)
+ self.worker.join()
+ return rv
+
+ def stop(self):
+ if self.worker.is_alive(): self.worker.terminate()
+
+# Right now this is a direct translation of the former int_test.sh
+# (except that I have fleshed out the SOCKS test a bit).
+# It will be made more general and parametric Real Soon.
+
+ENTRY_PORT = 4999
+SERVER_PORT = 5000
+EXIT_PORT = 5001
+
+#
+# Test base classes. They do _not_ inherit from unittest.TestCase
+# so that they are not scanned directly for test functions (some of
+# them do provide test functions, but not in a usable state without
+# further code from subclasses).
+#
+
+class DirectTest(object):
+ def setUp(self):
+ self.output_reader = ReadWorker(("127.0.0.1", EXIT_PORT))
+ self.obfs = subprocess.Popen(
+ self.obfs_args,
+ stdin=open("/dev/null", "r"),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ self.input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
+ self.input_chan.settimeout(1.0)
+
+ def tearDown(self):
+ if self.obfs.returncode is None:
+ self.obfs.terminate()
+ self.output_reader.stop()
+
+ def checkSubprocesses(self):
+ if self.obfs.poll() is None:
+ self.obfs.send_signal(signal.SIGINT)
+
+ (out, err) = self.obfs.communicate()
+
+ if (out != "" or err != "" or self.obfs.returncode != 0):
+ self.fail("obfsproxy process failure:\n"
+ "\treturn code: %d\n"
+ "\tstdout: %s\n"
+ "\tstderr: %s\n"
+ % (self.obfs.returncode, out, err))
+
+ def test_direct_transfer(self):
+ # Open a server and a simple client (in the same process) and
+ # transfer a file. Then check whether the output is the same
+ # as the input.
+ self.input_chan.sendall(TEST_FILE)
+ self.input_chan.shutdown(socket.SHUT_WR)
+ try:
+ output = self.output_reader.get()
+ except Queue.Empty:
+ output = ""
+
+ self.checkSubprocesses()
+ self.assertEqual(output, TEST_FILE)
+
+# Same as above, but we use a socks client instead of a simple client,
+# and the server's a separate process.
+
+class SocksTest(object):
+ def setUp(self):
+ self.output_reader = ReadWorker(("127.0.0.1", EXIT_PORT))
+ self.obfs_server = subprocess.Popen(
+ self.server_args,
+ stdin=open("/dev/null", "r"),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ self.obfs_client = subprocess.Popen(
+ self.client_args,
+ stdin=open("/dev/null", "r"),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+
+ self.input_chan = connect_with_retry(("127.0.0.1", ENTRY_PORT))
+ self.input_chan.settimeout(1.0)
+
+ def tearDown(self):
+ if self.obfs_server.returncode is None:
+ self.obfs_server.terminate()
+ if self.obfs_client.returncode is None:
+ self.obfs_client.terminate()
+ self.output_reader.stop()
+
+ def checkSubprocesses(self):
+ if self.obfs_server.poll() is None:
+ self.obfs_server.send_signal(signal.SIGINT)
+ if self.obfs_client.poll() is None:
+ self.obfs_client.send_signal(signal.SIGINT)
+
+ (sout, serr) = self.obfs_server.communicate()
+ (cout, cerr) = self.obfs_client.communicate()
+
+ if (sout != "" or serr != "" or cout != "" or cerr != ""
+ or self.obfs_server.returncode != 0
+ or self.obfs_client.returncode != 0):
+ self.fail("obfsproxy process failures:\n"
+ "\tclient return code: %d\n"
+ "\tserver return code: %d\n"
+ "\tclient stdout: %s\n"
+ "\tclient stderr: %s\n"
+ "\tserver stdout: %s\n"
+ "\tserver stderr: %s\n"
+ % (self.obfs_client.returncode,
+ self.obfs_server.returncode,
+ cout, cerr, sout, serr))
+
+ # 'sequence' is a sequence of SOCKS[45] protocol messages
+ # which we will send or receive. Sends alternate with
+ # receives. Each entry may be a string, which is sent or
+ # received verbatim; a pair of a sequence of data items and a
+ # struct pack code, which is packed and then sent or received;
+ # or the constant False, which means the server is expected to
+ # drop the connection at that point. If we come to the end of
+ # the SOCKS sequence without the server having dropped the
+ # connection, we transmit the test file and expect to get it
+ # back from the far end.
+ def socksTest(self, sequence):
+ sending = True
+ good = True
+ for msg in sequence:
+ if msg is False:
+ self.input_chan.shutdown(socket.SHUT_WR)
+ # Expect either a clean closedown or a connection reset
+ # at this point.
+ got = ""
+ try:
+ got = self.input_chan.recv(4096)
+ except socket.error, e:
+ if e.errno != errno.ECONNRESET: raise
+ self.assertEqual(got, "")
+ good = False
+ break
+ elif isinstance(msg, str):
+ exp = msg
+ elif isinstance(msg, tuple):
+ exp = struct.pack(msg[1], *msg[0])
+ else:
+ raise TypeError("incomprehensible msg: " + repr(msg))
+ if sending:
+ self.input_chan.sendall(exp)
+ else:
+ got = ""
+ try:
+ got = self.input_chan.recv(4096)
+ except socket.error, e:
+ if e.errno != errno.ECONNRESET: raise
+ self.assertEqual(got, exp)
+ if good:
+ self.input_chan.sendall(TEST_FILE)
+ self.input_chan.shutdown(socket.SHUT_WR)
+ try:
+ output = self.output_reader.get()
+ except Queue.Empty:
+ output = ""
+ self.assertEqual(output, TEST_FILE)
+
+ self.input_chan.close()
+ self.checkSubprocesses()
+
+ def test_illformed(self):
+ # ill-formed socks message - server should drop connection
+ self.socksTest([ "GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n"
+ "Connection: close\r\n\r\n",
+ False ])
+
+ def test_socks4_unsupported_methods(self):
+ # SOCKS4 bind request - should fail, presently just drops connection
+ self.socksTest([ ( (4, 2, SERVER_PORT, 127, 0, 0, 1, 0), "!BBH5B" ),
+ False ])
+
+ def test_socks4_connect(self):
+ # SOCKS4 connection request - should succeed
+ self.socksTest([ ( (4, 1, SERVER_PORT, 127, 0, 0, 1, 0), "!BBH5B" ),
+ ( (0, 90, SERVER_PORT, 127, 0, 0, 1), "!BBH4B" ) ])
+
+ def test_socks5_bad_handshakes(self):
+ self.socksTest([ "\x05", False ])
+ self.socksTest([ "\x05\x00", False ])
+ self.socksTest([ "\x05\x01\x01", "\x05\xFF", False ])
+ self.socksTest([ "\x05\x01\x080", "\x05\xFF", False ])
+ self.socksTest([ "\x05\x02\x01\x02", "\x05\xFF", False ])
+
+ def test_socks5_bad_requests(self):
+ self.socksTest([ "\x05\x01\x00", "\x05\x00", "\x05\x00",
+ "\x05\x07\x00", False ])
+ self.socksTest([ "\x05\x02\x00\x01", "\x05\x00", "\x05\x00",
+ "\x05\x07\x00", False ])
+
+ def test_socks5_unsupported_methods(self):
+ self.socksTest([ "\x05\x01\x00", "\x05\x00",
+ ( (5, 2, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
+ "\x05\x07\x00", False ])
+ self.socksTest([ "\x05\x01\x00", "\x05\x00",
+ ( (5, 3, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
+ "\x05\x07\x00", False ])
+
+ def test_socks5_connect(self):
+ self.socksTest([ "\x05\x01\x00", "\x05\x00",
+ ( (5, 1, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ),
+ ( (5, 0, 0, 1, 127, 0, 0, 1, SERVER_PORT), "!8BH" ) ])
+
+#
+# Concrete test classes specialize the above base classes for each protocol.
+#
+
+class DirectObfs2(DirectTest, unittest.TestCase):
+ obfs_args = ("./obfsproxy", "--log-min-severity=warn",
+ "obfs2",
+ "--dest=127.0.0.1:%d" % EXIT_PORT,
+ "server", "127.0.0.1:%d" % SERVER_PORT,
+ "+", "obfs2",
+ "--dest=127.0.0.1:%d" % SERVER_PORT,
+ "client", "127.0.0.1:%d" % ENTRY_PORT)
+
+class DirectDummy(DirectTest, unittest.TestCase):
+ obfs_args = ("./obfsproxy", "--log-min-severity=warn",
+ "dummy", "server",
+ "127.0.0.1:%d" % SERVER_PORT,
+ "127.0.0.1:%d" % EXIT_PORT,
+ "+", "dummy", "client",
+ "127.0.0.1:%d" % ENTRY_PORT,
+ "127.0.0.1:%d" % SERVER_PORT)
+
+class SocksObfs2(SocksTest, unittest.TestCase):
+ server_args = ("./obfsproxy", "--log-min-severity=warn",
+ "obfs2",
+ "--dest=127.0.0.1:%d" % EXIT_PORT,
+ "server", "127.0.0.1:%d" % SERVER_PORT)
+ client_args = ("./obfsproxy", "--log-min-severity=warn",
+ "obfs2",
+ "socks", "127.0.0.1:%d" % ENTRY_PORT)
+
+class SocksDummy(SocksTest, unittest.TestCase):
+ server_args = ("./obfsproxy", "--log-min-severity=warn",
+ "dummy", "server",
+ "127.0.0.1:%d" % SERVER_PORT,
+ "127.0.0.1:%d" % EXIT_PORT)
+ client_args = ("./obfsproxy", "--log-min-severity=warn",
+ "dummy", "socks",
+ "127.0.0.1:%d" % ENTRY_PORT)
+
+TEST_FILE = """\
+THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
+THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
+THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
+THIS IS A TEST FILE. IT'S USED BY THE INTEGRATION TESTS.
+
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+"Can entropy ever be reversed?"
+"THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER."
+
+ In obfuscatory age geeky warfare did I wage
+ For hiding bits from nasty censors' sight
+ I was hacker to my set in that dim dark age of net
+ And I hacked from noon till three or four at night
+
+ Then a rival from Helsinki said my protocol was dinky
+ So I flamed him with a condescending laugh,
+ Saying his designs for stego might as well be made of lego
+ And that my bikeshed was prettier by half.
+
+ But Claude Shannon saw my shame. From his noiseless channel came
+ A message sent with not a wasted byte
+ "There are nine and sixty ways to disguise communiques
+ And RATHER MORE THAN ONE OF THEM IS RIGHT"
+
+ (apologies to Rudyard Kipling.)
+"""
+
+if __name__ == '__main__':
+ unittest.main()
1
0
[obfsproxy/master] Hoist (nearly-)ubiquitous includes and forward declarations to util.h.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 7184b10a0b08fd0cb7c5148be23898d38138f04e
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 25 16:26:55 2011 -0700
Hoist (nearly-)ubiquitous includes and forward declarations to util.h.
---
src/container.h | 2 --
src/crypt.c | 3 ---
src/crypt.h | 2 --
src/main.c | 2 --
src/network.c | 7 -------
src/network.h | 37 ++++---------------------------------
src/protocol.c | 4 ----
src/protocol.h | 33 ++++++++++++++-------------------
src/protocols/dummy.c | 2 --
src/protocols/dummy.h | 3 +--
src/protocols/obfs2.c | 2 --
src/protocols/obfs2.h | 3 +--
src/sha256.c | 1 -
src/sha256.h | 2 --
src/socks.c | 6 ------
src/socks.h | 4 ----
src/test/tinytest.c | 4 ----
src/util.c | 8 --------
src/util.h | 44 +++++++++++++++++++++++++++++++++++++++++---
19 files changed, 61 insertions(+), 108 deletions(-)
diff --git a/src/container.h b/src/container.h
index e1c1a07..129e4f9 100644
--- a/src/container.h
+++ b/src/container.h
@@ -6,8 +6,6 @@
#ifndef CONTAINER_H
#define CONTAINER_H
-#include <stdlib.h>
-#include <string.h>
#include <time.h>
/** A resizeable list of pointers, with associated helpful functionality.
diff --git a/src/crypt.c b/src/crypt.c
index 9019fc9..62d99fe 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -8,9 +8,6 @@
#include "crypt.h"
#include <fcntl.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <openssl/opensslv.h>
diff --git a/src/crypt.h b/src/crypt.h
index beccda6..51bbc57 100644
--- a/src/crypt.h
+++ b/src/crypt.h
@@ -5,8 +5,6 @@
#ifndef CRYPT_H
#define CRYPT_H
-#include <stddef.h> /* for size_t */
-
#define SHA256_LENGTH 32
/* Stream cipher state */
diff --git a/src/main.c b/src/main.c
index cc69805..f6280c2 100644
--- a/src/main.c
+++ b/src/main.c
@@ -11,8 +11,6 @@
#include <errno.h>
#include <signal.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <event2/event.h>
#include <event2/dns.h>
diff --git a/src/network.c b/src/network.c
index c4cf0c7..f7a94d3 100644
--- a/src/network.c
+++ b/src/network.c
@@ -13,18 +13,11 @@
#include "protocol.h"
#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/bufferevent_struct.h>
#include <event2/listener.h>
-#include <event2/util.h>
-
-#ifdef _WIN32
-#include <ws2tcpip.h> /* socklen_t */
-#endif
/* Terminology used in this file:
diff --git a/src/network.h b/src/network.h
index b6aa410..c5ef69e 100644
--- a/src/network.h
+++ b/src/network.h
@@ -5,51 +5,22 @@
#ifndef NETWORK_H
#define NETWORK_H
-struct event_base;
-struct protocol_params_t;
-
-#define LSN_SIMPLE_CLIENT 1
-#define LSN_SIMPLE_SERVER 2
-#define LSN_SOCKS_CLIENT 3
-
-enum recv_ret {
- /* Everything went fine. */
- RECV_GOOD=0,
- /* Something went bad. */
- RECV_BAD,
- /* ...need...more...data... */
- RECV_INCOMPLETE,
-
- /* Originally needed by the obfs2 protocol but it might get other
- users in the future.
- It means:
- "We have pending data that we have to send. You should do that by
- calling proto_send() immediately." */
- RECV_SEND_PENDING
-};
-
/* returns 1 on success, 0 on failure */
-int create_listener(struct event_base *base, struct protocol_params_t *params);
+int create_listener(struct event_base *base, protocol_params_t *params);
void free_all_listeners(void);
void start_shutdown(int barbaric);
#ifdef NETWORK_PRIVATE
-struct bufferevent;
-struct evconnlistener;
-struct socks_state_t;
-struct protocol_t;
-struct protocol_params_t;
-
typedef struct listener_t {
+ protocol_params_t *proto_params;
struct evconnlistener *listener;
- struct protocol_params_t *proto_params;
} listener_t;
typedef struct conn_t {
- struct protocol_t *proto;
- struct socks_state_t *socks_state;
+ protocol_t *proto;
+ socks_state_t *socks_state;
struct bufferevent *upstream;
struct bufferevent *downstream;
unsigned int mode : 30;
diff --git a/src/protocol.c b/src/protocol.c
index a010d16..2966e06 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -8,10 +8,6 @@
#include "protocols/obfs2.h"
#include "protocols/dummy.h"
-#include <stdlib.h>
-#include <string.h>
-
-
/**
All supported protocols should be put in this array.
It's used by main.c.
diff --git a/src/protocol.h b/src/protocol.h
index c023720..246ad1c 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -5,11 +5,6 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
-#include "network.h" /* for recv_ret */
-#include <event2/util.h> /* for evutil_addrinfo */
-
-struct evbuffer;
-
/**
This struct defines the protocol-specific state for all connections
opened from a particular listener. Each protocol may extend this
@@ -17,12 +12,12 @@ struct evbuffer;
member of a larger structure (standard fake-inheritance-in-C
technique).
*/
-typedef struct protocol_params_t {
- const struct protocol_vtable *vtable;
+struct protocol_params_t {
+ const protocol_vtable *vtable;
struct evutil_addrinfo *target_addr;
struct evutil_addrinfo *listen_addr;
int mode;
-} protocol_params_t;
+};
/**
This struct defines the protocol-specific state for a particular
@@ -30,9 +25,9 @@ typedef struct protocol_params_t {
additional private data by embedding it as the first member of a
larger structure.
*/
-typedef struct protocol_t {
- const struct protocol_vtable *vtable;
-} protocol_t;
+struct protocol_t {
+ const protocol_vtable *vtable;
+};
/**
This struct defines a protocol and its methods; note that not all
@@ -42,7 +37,7 @@ typedef struct protocol_t {
principal interface between each individual protocol and generic
code. At present there is a static list of these objects in protocol.c.
*/
-typedef struct protocol_vtable
+struct protocol_vtable
{
/** The short name of this protocol. */
const char *name;
@@ -78,19 +73,19 @@ typedef struct protocol_vtable
struct evbuffer *source,
struct evbuffer *dest);
-} protocol_vtable;
+};
/**
Use this macro to define protocol_vtable objects; it ensures all
the methods are in the correct order and enforces a consistent
naming convention on protocol implementations.
*/
-#define DEFINE_PROTOCOL_VTABLE(name) \
- const struct protocol_vtable name##_vtable = { \
- #name, \
- name##_init, name##_fini, \
- name##_create, name##_destroy, \
- name##_handshake, name##_send, name##_recv \
+#define DEFINE_PROTOCOL_VTABLE(name) \
+ const protocol_vtable name##_vtable = { \
+ #name, \
+ name##_init, name##_fini, \
+ name##_create, name##_destroy, \
+ name##_handshake, name##_send, name##_recv \
}
protocol_params_t *proto_params_init(int n_options,
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index e6c4ca5..8ecce8f 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -7,8 +7,6 @@
#define PROTOCOL_DUMMY_PRIVATE
#include "dummy.h"
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
/* type-safe downcast wrappers */
diff --git a/src/protocols/dummy.h b/src/protocols/dummy.h
index 944fe1b..308c4f0 100644
--- a/src/protocols/dummy.h
+++ b/src/protocols/dummy.h
@@ -4,8 +4,7 @@
#ifndef PROTOCOL_DUMMY_H
#define PROTOCOL_DUMMY_H
-struct protocol_vtable;
-extern const struct protocol_vtable dummy_vtable;
+extern const protocol_vtable dummy_vtable;
#ifdef PROTOCOL_DUMMY_PRIVATE
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index 166c54a..6a6a975 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -7,8 +7,6 @@
#define PROTOCOL_OBFS2_PRIVATE
#include "obfs2.h"
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
/* type-safe downcast wrappers */
diff --git a/src/protocols/obfs2.h b/src/protocols/obfs2.h
index 107d15a..ce28217 100644
--- a/src/protocols/obfs2.h
+++ b/src/protocols/obfs2.h
@@ -5,8 +5,7 @@
#ifndef PROTOCOL_OBFS2_H
#define PROTOCOL_OBFS2_H
-struct protocol_vtable;
-extern const struct protocol_vtable obfs2_vtable;
+extern const protocol_vtable obfs2_vtable;
#ifdef PROTOCOL_OBFS2_PRIVATE
diff --git a/src/sha256.c b/src/sha256.c
index 7d273ae..fccbde6 100644
--- a/src/sha256.c
+++ b/src/sha256.c
@@ -7,7 +7,6 @@
#include "util.h"
#include "sha256.h"
-#include <string.h>
#include <arpa/inet.h> /* for htonl/ntohl */
#define STMT_BEGIN do {
diff --git a/src/sha256.h b/src/sha256.h
index b6a75be..6afdbfe 100644
--- a/src/sha256.h
+++ b/src/sha256.h
@@ -2,8 +2,6 @@
#ifndef SHA256_H
#define SHA256_H
-#include <stdint.h>
-
typedef struct sha256_state {
uint64_t length;
uint32_t state[8], curlen;
diff --git a/src/socks.c b/src/socks.c
index f1eada4..9941005 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -8,15 +8,9 @@
#include "socks.h"
#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
-#ifdef _WIN32
-#include <ws2tcpip.h> /* sockaddr_in6 */
-#endif
-
/**
General SOCKS5 idea:
diff --git a/src/socks.h b/src/socks.h
index db10cb5..a06a11e 100644
--- a/src/socks.h
+++ b/src/socks.h
@@ -5,10 +5,6 @@
#ifndef SOCKS_H
#define SOCKS_H
-typedef struct socks_state_t socks_state_t;
-struct evbuffer;
-struct sockaddr;
-
enum socks_status_t {
/* Waiting for initial socks4 or socks5 message */
ST_WAITING,
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
index 5151bcb..32e7b76 100644
--- a/src/test/tinytest.c
+++ b/src/test/tinytest.c
@@ -23,13 +23,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "tinytest.h"
#include "tinytest_macros.h"
#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
diff --git a/src/util.c b/src/util.c
index 8e63944..167e867 100644
--- a/src/util.c
+++ b/src/util.c
@@ -6,18 +6,10 @@
#include <errno.h>
#include <fcntl.h>
-#include <limits.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <event2/dns.h>
-#include <event2/util.h>
-
-#ifdef _WIN32
-#include <ws2tcpip.h> /* addrinfo */
-#endif
/** Any size_t larger than this amount is likely to be an underflow. */
#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
diff --git a/src/util.h b/src/util.h
index cb98fbd..ede23e4 100644
--- a/src/util.h
+++ b/src/util.h
@@ -6,14 +6,25 @@
#define UTIL_H
#include "config.h"
+
+#include <limits.h>
#include <stdarg.h> /* va_list */
#include <stddef.h> /* size_t, ptrdiff_t, offsetof, NULL */
#include <stdint.h> /* intN_t, uintN_t */
+#include <stdlib.h>
+#include <string.h>
+
#include <event2/util.h> /* evutil_addrinfo */
+#ifdef _WIN32
+#include <ws2tcpip.h> /* addrinfo (event2/util.h should do this,
+ but it doesn't) */
+#endif
-struct sockaddr;
-struct event_base;
+struct bufferevent;
+struct evconnlistener;
+struct evbuffer;
struct evdns_base;
+struct event_base;
/***** Type annotations. *****/
@@ -49,7 +60,34 @@ char *xstrndup(const char *s, size_t maxsize) ATTR_MALLOC;
unsigned int ui64_log2(uint64_t u64);
-/***** Network functions. *****/
+/***** Network types and functions. *****/
+
+typedef struct protocol_t protocol_t;
+typedef struct protocol_params_t protocol_params_t;
+typedef struct protocol_vtable protocol_vtable;
+typedef struct socks_state_t socks_state_t;
+
+enum recv_ret {
+ /* Everything went fine. */
+ RECV_GOOD=0,
+ /* Something went bad. */
+ RECV_BAD,
+ /* ...need...more...data... */
+ RECV_INCOMPLETE,
+
+ /* Originally needed by the obfs2 protocol but it might get other
+ users in the future.
+ It means:
+ "We have pending data that we have to send. You should do that by
+ calling proto_send() immediately." */
+ RECV_SEND_PENDING
+};
+
+enum listen_mode {
+ LSN_SIMPLE_CLIENT = 1,
+ LSN_SIMPLE_SERVER,
+ LSN_SOCKS_CLIENT
+};
struct evutil_addrinfo *resolve_address_port(const char *address,
int nodns, int passive,
1
0
[obfsproxy/master] In preparation for importing Tor container.c, switch from bare __attribute__ to ATTR_* macros.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 94d44dd806b58dde92fdb82dd0c5ae12d649ef80
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 18 14:15:50 2011 -0700
In preparation for importing Tor container.c, switch from bare __attribute__ to ATTR_* macros.
---
src/main.c | 17 +++++++----------
src/protocols/dummy.c | 7 +++----
src/util.c | 2 +-
src/util.h | 21 +++++++++++++--------
4 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/src/main.c b/src/main.c
index 21c4feb..c48f81a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,27 +2,24 @@
See LICENSE for other credits and copying information
*/
-#include <stdlib.h>
+#include "util.h"
+#include "network.h"
+#include "protocol.h"
+
#include <errno.h>
+#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <signal.h>
#include <event2/event.h>
-#include "network.h"
-#include "util.h"
-#include "protocol.h"
-
-#ifndef __GNUC__
-#define __attribute__(x)
-#endif
/* The character that seperates multiple listeners in the cli */
#define SEPARATOR "+"
/* Totally arbitrary. */
#define MAXPROTOCOLS 20
-static void usage(void) __attribute__((noreturn));
+static void usage(void) ATTR_NORETURN;
static int handle_obfsproxy_args(const char **argv);
static struct event_base *the_event_base=NULL;
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index d82818d..61cdf2b 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -116,14 +116,13 @@ dummy_destroy(struct protocol_t *proto)
The dummy protocol just puts the data of 'source' in 'dest'.
*/
static int
-dummy_handshake(struct protocol_t *proto __attribute__((unused)),
- struct evbuffer *buf __attribute__((unused)))
+dummy_handshake(struct protocol_t *proto, struct evbuffer *buf)
{
return 0;
}
static int
-dummy_send(struct protocol_t *proto __attribute__((unused)),
+dummy_send(struct protocol_t *proto,
struct evbuffer *source, struct evbuffer *dest)
{
return evbuffer_add_buffer(dest,source);
@@ -135,7 +134,7 @@ dummy_send(struct protocol_t *proto __attribute__((unused)),
The dummy protocol just puts the data of 'source' into 'dest'.
*/
static enum recv_ret
-dummy_recv(struct protocol_t *proto __attribute__((unused)),
+dummy_recv(struct protocol_t *proto,
struct evbuffer *source, struct evbuffer *dest)
{
if (evbuffer_add_buffer(dest,source)<0)
diff --git a/src/util.c b/src/util.c
index 6a0e4a0..ce25375 100644
--- a/src/util.c
+++ b/src/util.c
@@ -25,7 +25,7 @@
/**************************** Memory Allocation ******************************/
-static void __attribute__((noreturn))
+static void ATTR_NORETURN
die_oom(void)
{
log_warn("Memory allocation failed: %s",strerror(errno));
diff --git a/src/util.h b/src/util.h
index d909b53..0693930 100644
--- a/src/util.h
+++ b/src/util.h
@@ -11,6 +11,11 @@
#ifndef __GNUC__
#define __attribute__(x) /* nothing */
#endif
+#define ATTR_MALLOC __attribute__((malloc))
+#define ATTR_NORETURN __attribute__((noreturn))
+#define ATTR_PRINTF_1 __attribute__((format(printf, 1, 2)))
+#define ATTR_PRINTF_3 __attribute__((format(printf, 3, 4)))
+#define ATTR_PURE __attribute__((pure))
struct sockaddr;
struct event_base;
@@ -23,11 +28,11 @@ struct evdns_base;
allocate-memory-or-crash functions "xwhatever". Also, at this time
I do not see a need for a free() wrapper. */
-void *xmalloc(size_t size) __attribute__((malloc)); /* does not clear memory */
-void *xzalloc(size_t size) __attribute__((malloc)); /* clears memory */
+void *xmalloc(size_t size) ATTR_MALLOC; /* does not clear memory */
+void *xzalloc(size_t size) ATTR_MALLOC; /* clears memory */
void *xrealloc(void *ptr, size_t size);
-void *xmemdup(const void *ptr, size_t size) __attribute__((malloc));
-char *xstrdup(const char *s) __attribute__((malloc));
+void *xmemdup(const void *ptr, size_t size) ATTR_MALLOC;
+char *xstrdup(const char *s) ATTR_MALLOC;
/***** Network functions stuff. *****/
@@ -46,7 +51,7 @@ int obfs_vsnprintf(char *str, size_t size,
const char *format, va_list args);
int obfs_snprintf(char *str, size_t size,
const char *format, ...)
- __attribute__((format(printf, 3, 4)));
+ ATTR_PRINTF_3;
/***** Doubly Linked List stuff. *****/
@@ -96,16 +101,16 @@ void close_obfsproxy_logfile(void);
/** Warn-level severity: for messages that only appear when something
has gone wrong. */
void log_warn(const char *format, ...)
- __attribute__((format(printf, 1, 2)));
+ ATTR_PRINTF_1;
/** Info-level severity: for messages that should be sent to the user
during normal operation. */
void log_info(const char *format, ...)
- __attribute__((format(printf, 1, 2)));
+ ATTR_PRINTF_1;
/** Debug-level severity: for hyper-verbose messages of no interest to
anybody but developers. */
void log_debug(const char *format, ...)
- __attribute__((format(printf, 1, 2)));
+ ATTR_PRINTF_1;
#endif
1
0
[obfsproxy/master] All .c files include util.h first. No .h file includes util.h. util.h includes config.h. tinytest_macros.h includes tinytest.h, stdio.h, stdlib.h, string.h.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 443a77087d139943af827688fdb0262f4df82959
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 18 14:51:54 2011 -0700
All .c files include util.h first. No .h file includes util.h. util.h includes config.h. tinytest_macros.h includes tinytest.h, stdio.h, stdlib.h, string.h.
---
src/crypt.c | 3 ++-
src/main.c | 1 +
src/network.c | 3 ++-
src/network.h | 2 --
src/protocol.c | 3 ++-
src/protocols/dummy.c | 3 ++-
src/protocols/obfs2.c | 4 ++--
src/sha256.c | 3 ++-
src/socks.c | 4 ++--
src/test/tinytest_macros.h | 5 +++++
src/test/unittest_crypt.c | 5 +----
src/test/unittest_obfs2.c | 7 +------
src/test/unittest_socks.c | 7 +------
src/util.h | 1 +
14 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/src/crypt.c b/src/crypt.c
index 9984e24..e28e061 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -2,9 +2,10 @@
See LICENSE for other credits and copying information
*/
+#include "util.h"
+
#define CRYPT_PRIVATE
#include "crypt.h"
-#include "util.h"
#include <fcntl.h>
#include <limits.h>
diff --git a/src/main.c b/src/main.c
index c48f81a..a7aa298 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3,6 +3,7 @@
*/
#include "util.h"
+
#include "network.h"
#include "protocol.h"
diff --git a/src/network.c b/src/network.c
index fcbb45c..35e4eaf 100644
--- a/src/network.c
+++ b/src/network.c
@@ -2,10 +2,11 @@
See LICENSE for other credits and copying information
*/
+#include "util.h"
+
#define NETWORK_PRIVATE
#include "network.h"
-#include "util.h"
#include "main.h"
#include "socks.h"
#include "protocol.h"
diff --git a/src/network.h b/src/network.h
index ad54686..e631697 100644
--- a/src/network.h
+++ b/src/network.h
@@ -39,8 +39,6 @@ void start_shutdown(int barbaric);
#ifdef NETWORK_PRIVATE
-#include "util.h"
-
struct bufferevent;
struct socks_state_t;
struct protocol_t;
diff --git a/src/protocol.c b/src/protocol.c
index 4473a94..6abf7f1 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -2,10 +2,11 @@
See LICENSE for other credits and copying information
*/
+#include "util.h"
+
#include "protocol.h"
#include "protocols/obfs2.h"
#include "protocols/dummy.h"
-#include "util.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index b1493ce..c65f7b5 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -2,9 +2,10 @@
See LICENSE for other credits and copying information
*/
+#include "../util.h"
+
#include "dummy.h"
#include "../protocol.h"
-#include "../util.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index 5acd09e..f17af90 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -2,11 +2,11 @@
See LICENSE for other credits and copying information
*/
+#include "../util.h"
+
#define PROTOCOL_OBFS2_PRIVATE
#include "obfs2.h"
-#include "../util.h"
-
#include <stdlib.h>
#include <string.h>
diff --git a/src/sha256.c b/src/sha256.c
index d303f5f..7d273ae 100644
--- a/src/sha256.c
+++ b/src/sha256.c
@@ -4,8 +4,9 @@
LibTomCrypt, version 1.6. Tor uses it on platforms where OpenSSL doesn't
have a SHA256. */
-#include "sha256.h"
#include "util.h"
+
+#include "sha256.h"
#include <string.h>
#include <arpa/inet.h> /* for htonl/ntohl */
diff --git a/src/socks.c b/src/socks.c
index 6bd708f..333c787 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -2,11 +2,11 @@
See LICENSE for other credits and copying information
*/
+#include "util.h"
+
#define SOCKS_PRIVATE
#include "socks.h"
-#include "util.h"
-
#include <errno.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index 089616a..25ee7e2 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -26,6 +26,11 @@
#ifndef _TINYTEST_MACROS_H
#define _TINYTEST_MACROS_H
+#include "tinytest.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
/* Helpers for defining statement-like macros */
#define TT_STMT_BEGIN do {
#define TT_STMT_END } while(0)
diff --git a/src/test/unittest_crypt.c b/src/test/unittest_crypt.c
index 5a3e2aa..a3574f6 100644
--- a/src/test/unittest_crypt.c
+++ b/src/test/unittest_crypt.c
@@ -2,15 +2,12 @@
See LICENSE for other credits and copying information
*/
-#include "tinytest.h"
+#include "../util.h"
#include "tinytest_macros.h"
#define CRYPT_PRIVATE
#include "../crypt.h"
-#include <stdio.h>
-#include <string.h>
-
/* Test vectors for sha256 */
static void
test_crypt_hashvec(void *data)
diff --git a/src/test/unittest_obfs2.c b/src/test/unittest_obfs2.c
index 3ac4c42..099acd2 100644
--- a/src/test/unittest_obfs2.c
+++ b/src/test/unittest_obfs2.c
@@ -2,18 +2,13 @@
See LICENSE for other credits and copying information
*/
-#include "tinytest.h"
+#include "../util.h"
#include "tinytest_macros.h"
#define PROTOCOL_OBFS2_PRIVATE
#define CRYPT_PRIVATE
#include "../protocols/obfs2.h"
#include "../crypt.h"
-#include "../util.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
diff --git a/src/test/unittest_socks.c b/src/test/unittest_socks.c
index db4f120..9ba9e7e 100644
--- a/src/test/unittest_socks.c
+++ b/src/test/unittest_socks.c
@@ -2,17 +2,12 @@
See LICENSE for other credits and copying information
*/
-#include "tinytest.h"
+#include "../util.h"
#include "tinytest_macros.h"
#define SOCKS_PRIVATE
#include "../socks.h"
#include "../crypt.h"
-#include "../util.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <event2/buffer.h>
diff --git a/src/util.h b/src/util.h
index 8e5dd77..d365cbc 100644
--- a/src/util.h
+++ b/src/util.h
@@ -5,6 +5,7 @@
#ifndef UTIL_H
#define UTIL_H
+#include "config.h"
#include <stdarg.h> /* for va_list */
#include <stddef.h> /* size_t, offsetof, NULL, etc */
1
0
[obfsproxy/master] Introduce tt_mem_op and use it throughout existing tests.
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 434162e6900a7ebb1a745cbd1fe3324e1f4c244b
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 18 16:35:28 2011 -0700
Introduce tt_mem_op and use it throughout existing tests.
---
src/test/tinytest.c | 17 +++++++++++++++++
src/test/tinytest.h | 4 ++++
src/test/tinytest_macros.h | 12 ++++++++++++
src/test/unittest_crypt.c | 34 +++++++++++++++++-----------------
src/test/unittest_obfs2.c | 20 ++++++++------------
src/test/unittest_socks.c | 28 ++++++++++++++--------------
6 files changed, 72 insertions(+), 43 deletions(-)
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
index e3107b2..5151bcb 100644
--- a/src/test/tinytest.c
+++ b/src/test/tinytest.c
@@ -367,3 +367,20 @@ _tinytest_set_test_skipped(void)
cur_test_outcome = SKIP;
}
+char *
+tt_base16_encode(const char *value, size_t vlen)
+{
+ static const char hex[] = "0123456789abcdef";
+ char *print = malloc(vlen * 2 + 1);
+ char *p = print;
+ const char *v = value, *vl = value + vlen;
+
+ assert(print);
+ while (v < vl) {
+ unsigned char c = *v++;
+ *p++ = hex[(c >> 4) & 0x0f];
+ *p++ = hex[(c >> 0) & 0x0f];
+ }
+ *p = '\0';
+ return print;
+}
diff --git a/src/test/tinytest.h b/src/test/tinytest.h
index cbe28b7..a3bdcfe 100644
--- a/src/test/tinytest.h
+++ b/src/test/tinytest.h
@@ -26,6 +26,8 @@
#ifndef _TINYTEST_H
#define _TINYTEST_H
+#include <stddef.h> /* size_t */
+
/** Flag for a test that needs to run in a subprocess. */
#define TT_FORK (1<<0)
/** Runtime flag for a test we've decided to skip. */
@@ -73,6 +75,8 @@ int _tinytest_get_verbosity(void);
/** Implementation: Set a flag on tests matching a name; returns number
* of tests that matched. */
int _tinytest_set_flag(struct testgroup_t *, const char *, unsigned long);
+/** Implementation: Helper function for tt_mem_op. */
+char * tt_base16_encode(const char *value, size_t vlen);
/** Set all tests in 'groups' matching the name 'named' to be skipped. */
#define tinytest_skip(groups, named) \
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index 25ee7e2..f3e6d32 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -154,6 +154,9 @@
#define tt_assert_op_type(a,op,b,type,fmt) \
tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt)
+#define tt_bool_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,int,(!!_val1 op !!_val2),"%d")
+
#define tt_int_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld")
@@ -169,4 +172,13 @@
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
(strcmp(_val1,_val2) op 0),"<%s>")
+#define tt_mem_op(expr1, op, expr2, len) \
+ tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2, \
+ const char *, \
+ (memcmp(_val1, _val2, len) op 0), \
+ char *, "%s", \
+ { _print = tt_base16_encode(_value, len); }, \
+ { free(_print); } \
+ );
+
#endif
diff --git a/src/test/unittest_crypt.c b/src/test/unittest_crypt.c
index a3574f6..aef4ead 100644
--- a/src/test/unittest_crypt.c
+++ b/src/test/unittest_crypt.c
@@ -20,10 +20,10 @@ test_crypt_hashvec(void *data)
d = digest_new();
digest_update(d, (unsigned char*)"", 0);
digest_getdigest(d, output, 32);
- tt_int_op(0, ==, memcmp(output,
- "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8"
- "\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c"
- "\xa4\x95\x99\x1b\x78\x52\xb8\x55", 32));
+ tt_mem_op(output, ==,
+ "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8"
+ "\x99\x6f\xb9\x24\x27\xae\x41\xe4\x64\x9b\x93\x4c"
+ "\xa4\x95\x99\x1b\x78\x52\xb8\x55", 32);
/* Second SHA256 test vector:
Test for the 256-bit entry of:
@@ -34,10 +34,10 @@ test_crypt_hashvec(void *data)
"\x10\xb4\x70\xb1\x44\x78\x44\x11\xc9\x3a\x4d\x50\x45\x56\x83"
"\x4d\xae\x3e\xa4\xa5\xbb", 32);
digest_getdigest(d, output, 32);
- tt_int_op(0, ==, memcmp(output,
- "\x56\x05\x9e\x8c\xb3\xc2\x97\x8b\x19\x82\x08\xbf"
- "\x5c\xa1\xe1\xea\x56\x59\xb7\x37\xa5\x06\x32\x4b"
- "\x7c\xec\x75\xb5\xeb\xaf\x05\x7d", 32));
+ tt_mem_op(output, ==,
+ "\x56\x05\x9e\x8c\xb3\xc2\x97\x8b\x19\x82\x08\xbf"
+ "\x5c\xa1\xe1\xea\x56\x59\xb7\x37\xa5\x06\x32\x4b"
+ "\x7c\xec\x75\xb5\xeb\xaf\x05\x7d", 32);
/* Third SHA test vector:
Test for the 1304-bit entry of:
@@ -57,10 +57,10 @@ test_crypt_hashvec(void *data)
"\x8a\x19\xc8\x18\xc2\xea\x2e\x9d\x4e\x2d\xe9\x19\x0c\x9d\xdd"
"\xb8\x06", 163);
digest_getdigest(d, output, 32);
- tt_int_op(0, ==, memcmp(output,
- "\xc9\x07\x18\x04\x43\xde\xe3\xcb\xcc\xb4\xc3\x13"
- "\x28\xe6\x25\x15\x85\x27\xa5\x93\xb8\x78\xde\x1b"
- "\x8e\x4b\xa3\x7f\x1d\x69\xfb\x66", 32));
+ tt_mem_op(output, ==,
+ "\xc9\x07\x18\x04\x43\xde\xe3\xcb\xcc\xb4\xc3\x13"
+ "\x28\xe6\x25\x15\x85\x27\xa5\x93\xb8\x78\xde\x1b"
+ "\x8e\x4b\xa3\x7f\x1d\x69\xfb\x66", 32);
/* XXX Try doing init, update, update, output. */
/* XXX add a base16-decode function so we can implement a tt_mem_op or
@@ -114,13 +114,13 @@ test_crypt_aes1(void *data)
for (i = 0; i < 4; i++) {
tt_int_op(0, ==, crypt->pos);
- tt_int_op(0, ==, memcmp(crypt->ivec, testvec[i].counter, 16));
+ tt_mem_op(crypt->ivec, ==, testvec[i].counter, 16);
memcpy(vec, testvec[i].plaintext, 16);
stream_crypt(crypt, vec, 16);
- tt_int_op(0, ==, memcmp(crypt->ecount_buf, testvec[i].keystream, 16));
- tt_int_op(0, ==, memcmp(vec, testvec[i].ciphertext, 16));
+ tt_mem_op(crypt->ecount_buf, ==, testvec[i].keystream, 16);
+ tt_mem_op(vec, ==, testvec[i].ciphertext, 16);
}
end:
@@ -147,7 +147,7 @@ test_crypt_aes2(void *data)
stream_crypt(crypt1, res1, 16);
stream_crypt(crypt2, res2, 16);
- tt_int_op(0, !=, memcmp(res1, res2, 16));
+ tt_mem_op(res1, !=, res2, 16);
end:
if (crypt1)
@@ -169,7 +169,7 @@ test_crypt_rng(void *data)
tt_int_op(0, ==, random_bytes(data1, 100));
tt_int_op(0, ==, random_bytes(data2, 100));
- tt_int_op(0, !=, memcmp(data1, data2, 100));
+ tt_mem_op(data1, !=, data2, 100);
end:
;
diff --git a/src/test/unittest_obfs2.c b/src/test/unittest_obfs2.c
index 099acd2..00fc12e 100644
--- a/src/test/unittest_obfs2.c
+++ b/src/test/unittest_obfs2.c
@@ -177,13 +177,11 @@ test_obfs2_handshake(void *state)
/* The handshake is now complete. We should have:
client's send_crypto == server's recv_crypto
server's send_crypto == client's recv_crypto . */
- tt_int_op(0, ==, memcmp(client_state->send_crypto,
- server_state->recv_crypto,
- sizeof(crypt_t)));
+ tt_mem_op(client_state->send_crypto, ==, server_state->recv_crypto,
+ sizeof(crypt_t));
- tt_int_op(0, ==, memcmp(client_state->recv_crypto,
- server_state->send_crypto,
- sizeof(crypt_t)));
+ tt_mem_op(client_state->recv_crypto, ==, server_state->send_crypto,
+ sizeof(crypt_t));
end:;
}
@@ -353,13 +351,11 @@ test_obfs2_split_handshake(void *state)
/* The handshake is finally complete. We should have: */
/* client's send_crypto == server's recv_crypto */
/* server's send_crypto == client's recv_crypto . */
- tt_int_op(0, ==, memcmp(client_state->send_crypto,
- server_state->recv_crypto,
- sizeof(crypt_t)));
+ tt_mem_op(client_state->send_crypto, ==, server_state->recv_crypto,
+ sizeof(crypt_t));
- tt_int_op(0, ==, memcmp(client_state->recv_crypto,
- server_state->send_crypto,
- sizeof(crypt_t)));
+ tt_mem_op(client_state->recv_crypto, ==, server_state->send_crypto,
+ sizeof(crypt_t));
end:;
}
diff --git a/src/test/unittest_socks.c b/src/test/unittest_socks.c
index 9ba9e7e..c6039af 100644
--- a/src/test/unittest_socks.c
+++ b/src/test/unittest_socks.c
@@ -331,9 +331,9 @@ test_socks_socks5_request_reply(void *data)
tt_assert(rep1[3] == SOCKS5_ATYP_IPV4);
/* check address */
- tt_int_op(0, ==, memcmp(rep1+4, "\x7f\x00\x00\x01", 4));
+ tt_mem_op(rep1+4, ==, "\x7f\x00\x00\x01", 4);
/* check port */
- tt_int_op(0, ==, memcmp(rep1+4+4,"\x1c\xbd",2));
+ tt_mem_op(rep1+4+4, ==, "\x1c\xbd", 2);
/* emptying s->dest buffer before next test */
size_t buffer_len = evbuffer_get_length(s->dest);
@@ -352,11 +352,11 @@ test_socks_socks5_request_reply(void *data)
tt_assert(rep2[3] = SOCKS5_ATYP_IPV6);
/* Test returned address against inet_pton(d:1:5:e:a:5:e:0) */
- tt_int_op(0, ==, memcmp(rep2+4,
- "\x00\x0d\x00\x01\x00\x05\x00\x0e\x00"
- "\x0a\x00\x05\x00\x0e\x00\x00",
- 16));
- tt_int_op(0, ==, memcmp(rep2+4+16, "\x1c\xbd", 2));
+ tt_mem_op(rep2+4, ==,
+ "\x00\x0d\x00\x01\x00\x05\x00\x0e\x00"
+ "\x0a\x00\x05\x00\x0e\x00\x00",
+ 16);
+ tt_mem_op(rep2+4+16, ==, "\x1c\xbd", 2);
/* emptying dest buffer before next test */
buffer_len = evbuffer_get_length(s->dest);
@@ -377,9 +377,9 @@ test_socks_socks5_request_reply(void *data)
tt_assert(rep3[3] == SOCKS5_ATYP_FQDN);
tt_assert(rep3[4] == strlen(fqdn));
/* check fqdn */
- tt_int_op(0, ==, memcmp(rep3+5,fqdn,strlen(fqdn)));
+ tt_mem_op(rep3+5, ==, fqdn,strlen(fqdn));
/* check port */
- tt_int_op(0, ==, memcmp(rep3+5+strlen(fqdn),"\x1c\xbd",2));
+ tt_mem_op(rep3+5+strlen(fqdn), ==, "\x1c\xbd",2);
/* Fourth test:
We ask the server while having an empty parsereq and with a
@@ -391,8 +391,8 @@ test_socks_socks5_request_reply(void *data)
evbuffer_remove(s->dest,rep4,255);
tt_assert(rep4[3] == SOCKS5_ATYP_IPV4);
- tt_int_op(0, ==, memcmp(rep4+4,"\x00\x00\x00\x00",4));
- tt_int_op(0, ==, memcmp(rep4+4+4, "\x00\x00", 2));
+ tt_mem_op(rep4+4, ==, "\x00\x00\x00\x00",4);
+ tt_mem_op(rep4+4+4, ==, "\x00\x00", 2);
end:;
}
@@ -552,9 +552,9 @@ test_socks_socks4_request_reply(void *data)
tt_assert(rep1[0] == '\x00');
tt_assert(rep1[1] == SOCKS4_SUCCESS);
/* check port */
- tt_int_op(0, ==, memcmp(rep1+2,"\x1c\xbd",2));
+ tt_mem_op(rep1+2, ==, "\x1c\xbd",2);
/* check address */
- tt_int_op(0, ==, memcmp(rep1+2+2,"\x7f\x00\x00\x01", 4));
+ tt_mem_op(rep1+2+2, ==, "\x7f\x00\x00\x01", 4);
/* emptying dest buffer before next test */
size_t buffer_len = evbuffer_get_length(s->dest);
@@ -574,7 +574,7 @@ test_socks_socks4_request_reply(void *data)
tt_assert(rep2[1] == SOCKS4_FAILED);
/* check port */
- tt_int_op(0, ==, memcmp(rep2+2,"\x1c\xbd",2));
+ tt_mem_op(rep2+2, ==, "\x1c\xbd", 2);
/* check address */
/* tt_str_op(rep1+2+2, ==, "www.test.example"); */
1
0
[obfsproxy/master] Switch from C-library assert to an obfs_assert/abort that go through the logging system
by nickm@torproject.org 09 Sep '11
by nickm@torproject.org 09 Sep '11
09 Sep '11
commit 13e30cbac02e24cee9615e35d11fc71ab59fb8d1
Author: Zack Weinberg <zackw(a)panix.com>
Date: Mon Jul 18 14:42:19 2011 -0700
Switch from C-library assert to an obfs_assert/abort that go through the logging system
---
src/crypt.c | 5 +--
src/network.c | 19 ++++++-------
src/protocol.c | 34 ++++++++++++------------
src/protocols/dummy.c | 1 -
src/protocols/obfs2.c | 3 +-
src/sha256.c | 4 +-
src/socks.c | 15 +++++------
src/util.c | 66 ++++++++++++++++++++++++++++++++----------------
src/util.h | 20 +++++++++++++++
9 files changed, 102 insertions(+), 65 deletions(-)
diff --git a/src/crypt.c b/src/crypt.c
index 722fc00..9984e24 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -6,7 +6,6 @@
#include "crypt.h"
#include "util.h"
-#include <assert.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
@@ -160,7 +159,7 @@ crypt_new(const uchar *key, size_t keylen)
{
crypt_t *k;
- assert(keylen == AES_BLOCK_SIZE);
+ obfs_assert(keylen == AES_BLOCK_SIZE);
k = xzalloc(sizeof(crypt_t));
AES_set_encrypt_key(key, AES_BLOCK_SIZE * CHAR_BIT, &k->key);
@@ -173,7 +172,7 @@ crypt_new(const uchar *key, size_t keylen)
void
crypt_set_iv(crypt_t *key, const uchar *iv, size_t ivlen)
{
- assert(ivlen == sizeof(key->ivec));
+ obfs_assert(ivlen == sizeof(key->ivec));
memcpy(key->ivec, iv, ivlen);
}
diff --git a/src/network.c b/src/network.c
index fb770c9..fcbb45c 100644
--- a/src/network.c
+++ b/src/network.c
@@ -10,7 +10,6 @@
#include "socks.h"
#include "protocol.h"
-#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -96,7 +95,7 @@ close_all_connections(void)
conn_t *conn = DOWNCAST(conn_t, dll_node, conn_list.head);
conn_free(conn); /* removes it */
}
- assert(!n_connections);
+ obfs_assert(!n_connections);
}
/**
This function spawns a listener configured according to the
@@ -226,7 +225,7 @@ simple_listener_cb(struct evconnlistener *evcl,
bufferevent_setcb(conn->input,
plaintext_read_cb, NULL, input_event_cb, conn);
} else {
- assert(conn->mode == LSN_SOCKS_CLIENT);
+ obfs_assert(conn->mode == LSN_SOCKS_CLIENT);
bufferevent_setcb(conn->input,
socks_read_cb, NULL, input_event_cb, conn);
}
@@ -303,7 +302,7 @@ conn_free(conn_t *conn)
memset(conn, 0x99, sizeof(conn_t));
free(conn);
- assert(n_connections>=0);
+ obfs_assert(n_connections>=0);
log_debug("Connection destroyed. "
"We currently have %d connections!", n_connections);
@@ -336,19 +335,19 @@ socks_read_cb(struct bufferevent *bev, void *arg)
conn_t *conn = arg;
//struct bufferevent *other;
enum socks_ret socks_ret;
- assert(bev == conn->input); /* socks must be on the initial bufferevent */
+ obfs_assert(bev == conn->input); /* socks must be on the initial bufferevent */
do {
enum socks_status_t status = socks_state_get_status(conn->socks_state);
if (status == ST_SENT_REPLY) {
/* We shouldn't be here. */
- assert(0);
+ obfs_abort();
} else if (status == ST_HAVE_ADDR) {
int af, r, port;
const char *addr=NULL;
r = socks_state_get_address(conn->socks_state, &af, &addr, &port);
- assert(r==0);
+ obfs_assert(r==0);
r = bufferevent_socket_connect_hostname(conn->output,
get_evdns_base(),
af, addr, port);
@@ -461,7 +460,7 @@ static void
input_event_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = arg;
- assert(bev == conn->input);
+ obfs_assert(bev == conn->input);
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
log_warn("Got error: %s",
@@ -478,7 +477,7 @@ static void
output_event_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = arg;
- assert(bev == conn->output);
+ obfs_assert(bev == conn->output);
/**
If we got the BEV_EVENT_ERROR flag *AND* we are in socks mode
@@ -532,7 +531,7 @@ output_event_cb(struct bufferevent *bev, short what, void *arg)
struct sockaddr_storage ss;
struct sockaddr *sa = (struct sockaddr*)&ss;
socklen_t slen = sizeof(&ss);
- assert(conn->socks_state);
+ obfs_assert(conn->socks_state);
if (getpeername(bufferevent_getfd(bev), sa, &slen) == 0) {
/* Figure out where we actually connected to so that we can tell the
* socks client */
diff --git a/src/protocol.c b/src/protocol.c
index 9aa1f8b..4473a94 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -5,8 +5,8 @@
#include "protocol.h"
#include "protocols/obfs2.h"
#include "protocols/dummy.h"
+#include "util.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -50,7 +50,7 @@ proto_params_init(int n_options, const char *const *options)
void
proto_params_free(protocol_params_t *params)
{
- assert(params);
+ obfs_assert(params);
if (params->target_address)
free(params->target_address);
@@ -70,9 +70,9 @@ proto_params_free(protocol_params_t *params)
struct protocol_t *
proto_create(protocol_params_t *params)
{
- assert(params);
- assert(params->vtable);
- assert(params->vtable->create);
+ obfs_assert(params);
+ obfs_assert(params->vtable);
+ obfs_assert(params->vtable->create);
return params->vtable->create(params);
}
@@ -82,9 +82,9 @@ proto_create(protocol_params_t *params)
*/
int
proto_handshake(struct protocol_t *proto, void *buf) {
- assert(proto);
- assert(proto->vtable);
- assert(proto->vtable->handshake);
+ obfs_assert(proto);
+ obfs_assert(proto->vtable);
+ obfs_assert(proto->vtable->handshake);
return proto->vtable->handshake(proto, buf);
}
@@ -93,9 +93,9 @@ proto_handshake(struct protocol_t *proto, void *buf) {
*/
int
proto_send(struct protocol_t *proto, void *source, void *dest) {
- assert(proto);
- assert(proto->vtable);
- assert(proto->vtable->send);
+ obfs_assert(proto);
+ obfs_assert(proto->vtable);
+ obfs_assert(proto->vtable->send);
return proto->vtable->send(proto, source, dest);
}
@@ -104,9 +104,9 @@ proto_send(struct protocol_t *proto, void *source, void *dest) {
*/
enum recv_ret
proto_recv(struct protocol_t *proto, void *source, void *dest) {
- assert(proto);
- assert(proto->vtable);
- assert(proto->vtable->recv);
+ obfs_assert(proto);
+ obfs_assert(proto->vtable);
+ obfs_assert(proto->vtable->recv);
return proto->vtable->recv(proto, source, dest);
}
@@ -116,8 +116,8 @@ proto_recv(struct protocol_t *proto, void *source, void *dest) {
*/
void
proto_destroy(struct protocol_t *proto) {
- assert(proto);
- assert(proto->vtable);
- assert(proto->vtable->destroy);
+ obfs_assert(proto);
+ obfs_assert(proto->vtable);
+ obfs_assert(proto->vtable->destroy);
proto->vtable->destroy(proto);
}
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index 61cdf2b..b1493ce 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -6,7 +6,6 @@
#include "../protocol.h"
#include "../util.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index c42d1c4..5acd09e 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -7,7 +7,6 @@
#include "../util.h"
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -322,7 +321,7 @@ obfs2_handshake(struct protocol_t *s, struct evbuffer *buf)
SEED | E_PAD_KEY( UINT32(MAGIC_VALUE) | UINT32(PADLEN) | WR(PADLEN) )
*/
- assert(sizeof(magic) == 4);
+ obfs_assert(sizeof(magic) == 4);
/* generate padlen */
if (random_bytes((uchar*)&plength, 4) < 0)
diff --git a/src/sha256.c b/src/sha256.c
index ff2cf21..d303f5f 100644
--- a/src/sha256.c
+++ b/src/sha256.c
@@ -5,7 +5,7 @@
have a SHA256. */
#include "sha256.h"
-#include <assert.h>
+#include "util.h"
#include <string.h>
#include <arpa/inet.h> /* for htonl/ntohl */
@@ -23,7 +23,7 @@ get_uint32(const void *ptr)
memcpy(&val, ptr, 4);
return val;
}
-#define LTC_ARGCHK(x) assert((x))
+#define LTC_ARGCHK(x) obfs_assert(x)
#define CRYPT_OK 0
#define CRYPT_NOP -1
diff --git a/src/socks.c b/src/socks.c
index b67455f..6bd708f 100644
--- a/src/socks.c
+++ b/src/socks.c
@@ -7,7 +7,6 @@
#include "util.h"
-#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -189,19 +188,19 @@ socks5_handle_request(struct evbuffer *source, struct parsereq *parsereq)
goto err;
if (evbuffer_remove(source, destaddr, addrlen) != addrlen)
- assert(0);
+ obfs_abort();
if (evbuffer_remove(source, (char *)&destport, 2) != 2)
- assert(0);
+ obfs_abort();
destaddr[addrlen] = '\0';
if (af == AF_UNSPEC) {
- assert(addrlen < sizeof(parsereq->addr));
+ obfs_assert(addrlen < sizeof(parsereq->addr));
memcpy(parsereq->addr, destaddr, addrlen+1);
} else {
char a[16];
- assert(addrlen <= 16);
+ obfs_assert(addrlen <= 16);
memcpy(a, destaddr, addrlen);
if (evutil_inet_ntop(af, destaddr, parsereq->addr,
sizeof(parsereq->addr)) == NULL)
@@ -331,7 +330,7 @@ socks5_handle_negotiation(struct evbuffer *source,
}
if (evbuffer_remove(source, methods, nmethods) < 0)
- assert(0);
+ obfs_abort();
for (found_noauth=0, i=0; i<nmethods ; i++) {
if (methods[i] == SOCKS5_METHOD_NOAUTH) {
@@ -477,7 +476,7 @@ handle_socks(struct evbuffer *source, struct evbuffer *dest,
}
/* ST_SENT_REPLY connections shouldn't be here! */
- assert(socks_state->state != ST_SENT_REPLY &&
+ obfs_assert(socks_state->state != ST_SENT_REPLY &&
socks_state->state != ST_HAVE_ADDR);
if (socks_state->version == 0) {
@@ -527,7 +526,7 @@ handle_socks(struct evbuffer *source, struct evbuffer *dest,
return SOCKS_CMD_NOT_CONNECT;
} else if (r == SOCKS_BROKEN)
goto broken;
- assert(0);
+ obfs_abort();
}
break;
default:
diff --git a/src/util.c b/src/util.c
index ce25375..231c3a8 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4,7 +4,6 @@
#include "util.h"
-#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
@@ -28,8 +27,7 @@
static void ATTR_NORETURN
die_oom(void)
{
- log_warn("Memory allocation failed: %s",strerror(errno));
- exit(1);
+ log_error("Memory allocation failed: %s",strerror(errno));
}
void *
@@ -37,7 +35,7 @@ xmalloc(size_t size)
{
void *result;
- assert(size < SIZE_T_CEILING);
+ obfs_assert(size < SIZE_T_CEILING);
/* Some malloc() implementations return NULL when the input argument
is zero. We don't bother detecting whether the implementation we're
@@ -57,7 +55,7 @@ void *
xrealloc(void *ptr, size_t size)
{
void *result;
- assert (size < SIZE_T_CEILING);
+ obfs_assert (size < SIZE_T_CEILING);
if (size == 0)
size = 1;
@@ -217,8 +215,8 @@ obfs_vsnprintf(char *str, size_t size, const char *format, va_list args)
static void
dll_insert_after(dll_t *list, dll_node_t *node, dll_node_t *new_node)
{
- assert(node);
- assert(new_node);
+ obfs_assert(node);
+ obfs_assert(new_node);
if (!list)
return;
@@ -238,8 +236,8 @@ dll_insert_after(dll_t *list, dll_node_t *node, dll_node_t *new_node)
static void
dll_insert_before(dll_t *list, dll_node_t *node, dll_node_t *new_node)
{
- assert(node);
- assert(new_node);
+ obfs_assert(node);
+ obfs_assert(new_node);
if (!list)
return;
@@ -266,7 +264,7 @@ dll_init(dll_t *list)
static void
dll_insert_beginning(dll_t *list, dll_node_t *node)
{
- assert(node);
+ obfs_assert(node);
if (!list)
return;
@@ -288,8 +286,8 @@ dll_insert_beginning(dll_t *list, dll_node_t *node)
int
dll_append(dll_t *list, dll_node_t *node)
{
- assert(list);
- assert(node);
+ obfs_assert(list);
+ obfs_assert(node);
if (!list->tail)
dll_insert_beginning(list, node);
@@ -306,7 +304,7 @@ dll_append(dll_t *list, dll_node_t *node)
void
dll_remove(dll_t *list, dll_node_t *node)
{
- assert(node);
+ obfs_assert(node);
if (!list)
return;
@@ -326,6 +324,10 @@ dll_remove(dll_t *list, dll_node_t *node)
off tor. It's basicaly a stripped down version of tor's logging
system. Thank you tor. */
+/* Note: obfs_assert and obfs_abort cannot be used anywhere in the
+ logging system, as they will recurse into the logging system and
+ cause an infinite loop. We use plain old abort(3) instead. */
+
/* Size of maximum log entry, including newline and NULL byte. */
#define MAX_LOG_ENTRY 1024
/* String to append when a log entry doesn't fit in MAX_LOG_ENTRY. */
@@ -335,6 +337,7 @@ dll_remove(dll_t *list, dll_node_t *node)
/** Logging severities */
+#define LOG_SEV_ERR 4
#define LOG_SEV_WARN 3
#define LOG_SEV_INFO 2
#define LOG_SEV_DEBUG 1
@@ -351,11 +354,12 @@ static const char *
sev_to_string(int severity)
{
switch (severity) {
+ case LOG_SEV_ERR: return "error";
case LOG_SEV_WARN: return "warn";
case LOG_SEV_INFO: return "info";
case LOG_SEV_DEBUG: return "debug";
default:
- assert(0); return "UNKNOWN";
+ abort();
}
}
@@ -364,6 +368,8 @@ sev_to_string(int severity)
static int
string_to_sev(const char *string)
{
+ if (!strcasecmp(string, "error"))
+ return LOG_SEV_ERR;
if (!strcasecmp(string, "warn"))
return LOG_SEV_WARN;
else if (!strcasecmp(string, "info"))
@@ -381,7 +387,8 @@ string_to_sev(const char *string)
static int
sev_is_valid(int severity)
{
- return (severity == LOG_SEV_WARN ||
+ return (severity == LOG_SEV_ERR ||
+ severity == LOG_SEV_WARN ||
severity == LOG_SEV_INFO ||
severity == LOG_SEV_DEBUG);
}
@@ -473,7 +480,8 @@ log_set_min_severity(const char* sev_string)
static void
logv(int severity, const char *format, va_list ap)
{
- assert(sev_is_valid(severity));
+ if (!sev_is_valid(severity))
+ abort();
if (logging_method == LOG_METHOD_NULL)
return;
@@ -500,7 +508,8 @@ logv(int severity, const char *format, va_list ap)
size_t offset = buflen-TRUNCATED_STR_LEN;
r = obfs_snprintf(buf+offset, TRUNCATED_STR_LEN+1,
"%s", TRUNCATED_STR);
- if (r < 0) assert(0);
+ if (r < 0)
+ abort();
}
n = buflen;
} else
@@ -512,24 +521,26 @@ logv(int severity, const char *format, va_list ap)
if (logging_method == LOG_METHOD_STDOUT)
fprintf(stdout, "%s", buf);
else if (logging_method == LOG_METHOD_FILE) {
- assert(logging_logfile);
+ if (!logging_logfile)
+ abort();
if (write(logging_logfile, buf, strlen(buf)) < 0)
- printf("%s(): Terrible write() error!!!\n", __func__);
+ abort();
} else
- assert(0);
+ abort();
}
/**** Public logging API. ****/
void
-log_info(const char *format, ...)
+log_error(const char *format, ...)
{
va_list ap;
va_start(ap,format);
- logv(LOG_SEV_INFO, format, ap);
+ logv(LOG_SEV_ERR, format, ap);
va_end(ap);
+ exit(1);
}
void
@@ -544,6 +555,17 @@ log_warn(const char *format, ...)
}
void
+log_info(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap,format);
+
+ logv(LOG_SEV_INFO, format, ap);
+
+ va_end(ap);
+}
+
+void
log_debug(const char *format, ...)
{
va_list ap;
diff --git a/src/util.h b/src/util.h
index 0693930..8e5dd77 100644
--- a/src/util.h
+++ b/src/util.h
@@ -98,6 +98,10 @@ void close_obfsproxy_logfile(void);
/** The actual log-emitting functions */
+/** Fatal errors: the program cannot continue and will exit. */
+void log_error(const char *format, ...)
+ ATTR_PRINTF_1 ATTR_NORETURN;
+
/** Warn-level severity: for messages that only appear when something
has gone wrong. */
void log_warn(const char *format, ...)
@@ -113,4 +117,20 @@ void log_info(const char *format, ...)
void log_debug(const char *format, ...)
ATTR_PRINTF_1;
+/** Assertion checking. We don't ever compile assertions out, and we
+ want precise control over the error messages, so we use our own
+ assertion macros. */
+#define obfs_assert(expr) \
+ do { \
+ if (!(expr)) \
+ log_error("assertion failure at %s:%d: %s", \
+ __FILE__, __LINE__, #expr); \
+ } while (0)
+
+#define obfs_abort() \
+ do { \
+ log_error("aborted at %s:%d", __FILE__, __LINE__); \
+ } while (0)
+
+
#endif
1
0