[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [obfsproxy/master] Implements the parsing logic of the new CLI.
commit 1d3d01d5b22ea60614936d7850dddf493a96c0fc
Author: George Kadianakis <desnacked@xxxxxxxxx>
Date: Sun May 29 04:02:10 2011 +0200
Implements the parsing logic of the new CLI.
---
src/main.c | 257 +++++++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 186 insertions(+), 71 deletions(-)
diff --git a/src/main.c b/src/main.c
index 4c3c48c..8f03df1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -21,13 +21,25 @@
static void usage(void) __attribute__((noreturn));
+#define SEPERATOR "+"
+#define MAXPROTOCOLS 20
+
+const char *supported_protocols[] = { "obfs2", "dummy" };
+const int n_supported_protocols = 2;
+
static void
usage(void)
{
+ int i;
fprintf(stderr,
- "Usage: obfsproxy {client/server/socks} {obfs2/dummy} listenaddr[:port] targetaddr:port <shared secret>\n"
- " (Default listen port is 48988 for client; 23548 for socks; 11253 for server)\n"
- );
+ "Usage: obfsproxy protocol_name [protocol_args] protocol_options %s protocol_name ...\n"
+ "Available protocols:",
+ SEPERATOR);
+ /* cheapie */
+ for (i=0;i<n_supported_protocols;i++)
+ fprintf(stderr," [%s]", supported_protocols[i]);
+ fprintf(stderr,"\n");
+
exit(1);
}
@@ -36,109 +48,212 @@ handle_signal_cb(evutil_socket_t fd, short what, void *arg)
{
struct event_base *base = arg;
/* int signum = (int) fd; */
-
+
event_base_loopexit(base, NULL);
}
+/**
+ This function visits all the command line arguments in 'argv' between
+ 'start' and 'end' and writes them in 'options_string'.
+ */
+static int
+populate_options(char **options_string,
+ const char **argv, int n_options)
+{
+ int x,g;
+ for (g=0;g<=n_options-1;g++) {
+ options_string[g] = strdup(argv[g]);
+ if (!options_string[x]) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/**
+ Runs through all the supported protocols and checks if 'name'
+ matches with the name of any of them.
+*/
+static int
+is_supported_protocol(const char *name) {
+ int f;
+ for (f=0;f<n_supported_protocols;f++) {
+ if (!strcmp(name,supported_protocols[f]))
+ return 1;
+ }
+ return 0;
+}
+
int
main(int argc, const char **argv)
{
- int protocol;
- int is_client, is_socks = 0, mode;
- struct sockaddr_storage ss_listen, ss_target;
- struct sockaddr *sa_target=NULL;
- int sl_listen, sl_target=0;
- const char *defport;
- char *shared_secret = NULL;
-
struct event_base *base;
struct event *sigevent;
- listener_t *listener;
- /* XXXXX the interface is crap. Fix that. XXXXX */
- if (argc < 4)
- usage();
- if (!strcmp(argv[1], "client")) {
- is_client = 1;
- defport = "48988"; /* bf5c */
- mode = LSN_SIMPLE_CLIENT;
- } else if (!strcmp(argv[1], "socks")) {
- is_client = 1;
- is_socks = 1;
- defport = "23548"; /* 5bf5 */
- mode = LSN_SOCKS_CLIENT;
- } else if (!strcmp(argv[1], "server")) {
- is_client = 0;
- defport = "11253"; /* 2bf5 */
- mode = LSN_SIMPLE_SERVER;
- } else {
+ /* Yes, these are three stars right there. This is an array of
+ arrays of strings! Every element of the array is an array of
+ strings that contains all the options of a protocol.
+ At runtime it should look like this:
+ char protocol_options[<number of protocols>][<number of options>][<length of option>]
+ */
+ char ***protocol_options = NULL;
+ /* This is an array of integers! Each integer is the number of
+ options of the respective protocol. */
+ int *n_options_array = NULL;
+ /* This is an integer! It contains the number of protocols that we
+ managed to recognize, by their protocol name. Of course it's not
+ the *actual* actual_protocols since some of them could have wrong
+ options or arguments, but this will be resolved by
+ set_up_protocol() and listener_new(). */
+ int actual_protocols=0;
+
+ int start;
+ int end;
+ int n_options;
+ void *temp;
+ int i;
+
+ unsigned int n_protocols=1;
+ unsigned int protocols[MAXPROTOCOLS+1];
+ protocols[0] = 0;
+
+ if (argc < 2) {
usage();
}
- if (!strcmp(argv[2], "obfs2"))
- protocol = OBFS2_PROTOCOL;
- else if (!strcmp(argv[2], "dummy"))
- protocol = DUMMY_PROTOCOL;
- else
- usage();
+ /* Iterate through command line arguments and find protocols. */
+ for (i=0;i<argc;i++) {
+ if (!strcmp(argv[i],SEPERATOR)) {
+ protocols[n_protocols] = i;
+ n_protocols++;
+ if (n_protocols > MAXPROTOCOLS) {
+ printf("Sorry, we only allow %d protocols. Don't ask me why. "
+ "Exiting.\n", MAXPROTOCOLS);
+ return 5;
+ }
+ }
+ }
+ protocols[n_protocols] = argc;
+ if (n_protocols > 1)
+ printf("Found %d protocols.\n", n_protocols);
- /* figure out what port(s) to listen on as client/server */
- if (resolve_address_port(argv[3], 1, 1, &ss_listen, &sl_listen, defport) < 0)
- usage();
+ /* Iterate through protocols. */
+ for (i=0;i<n_protocols;i++) {
+ /* This "points" to the first argument of this protocol in argv. */
+ start = protocols[i]+1;
+ /* This "points" to the last argument of this protocol in argv. */
+ end = protocols[i+1]-1;
+ n_options = end-start+1;
- /* figure out what place to connect to as a client/server. */
- /* XXXX when we add socks support, clients will not have a fixed "target"
- * XXXX address but will instead connect to a client-selected address. */
- if (resolve_address_port(argv[4], 1, 0, &ss_target, &sl_target, NULL) < 0)
- usage();
- sa_target = (struct sockaddr *)&ss_target;
+ if (!is_supported_protocol(argv[start])) {
+ printf("We don't support crappy protocols, son.\n");
+ continue;
+ }
- /* Let's see if the user wants a shared secret.
- So ugly. So ugly. So ugly. So ugly. So ugly interface.
- */
- if (argc > 5 && argc != 6)
- usage();
- if (argc == 6) {
- if (protocol != OBFS2_PROTOCOL) {
- printf("shared secret is only supported with obfs2 atm.\n");
+ /* Okay seems like we support this protocol. */
+ actual_protocols++;
+
+ /* We now allocate enough space for our parsing adventures.
+
+ We first allocate space for a pointer in protocol_options,
+ which points to an array carrying the options of this protocol.
+ We then allocate space for the array carrying the options of
+ this protocol.
+ Finally, we allocate space on the n_options_array so that we
+ can put the number of options there.
+ */
+ temp =
+ realloc(protocol_options, sizeof(char**)*actual_protocols);
+ if (!temp)
exit(1);
- }
+ protocol_options = temp;
+ /* We should now allocate some space for all the strings
+ carrying the protocol options. */
+ protocol_options[actual_protocols-1] =
+ malloc(sizeof(char*)*(n_options));
+ if (!protocol_options[actual_protocols-1])
+ exit(1);
+ temp = realloc(n_options_array, sizeof(int)*actual_protocols);
+ if (!temp)
+ exit(1);
+ n_options_array = temp;
+ n_options_array[actual_protocols-1] = n_options;
- shared_secret = strdup(argv[5]);
+ /* Finally! Let's fill protocol_options. */
+ populate_options(protocol_options[actual_protocols-1],
+ &argv[start], n_options);
}
+ /* Excellent. Now we should have protocol_options populated with all
+ the protocol options we got from the user. */
+
/* Initialize libevent */
base = event_base_new();
- if (base == NULL) {
+ if (!base) {
fprintf(stderr, "Can't initialize Libevent; failing\n");
return 2;
}
- if (is_socks && init_evdns_base(base) < 0) {
+ /* ASN should this happen only when SOCKS is enabled? */
+ if (init_evdns_base(base) < 0) {
fprintf(stderr, "Can't initialize evdns; failing\n");
return 3;
}
-
+
/* Handle signals */
signal(SIGPIPE, SIG_IGN);
sigevent = evsignal_new(base, SIGINT, handle_signal_cb, (void*) base);
-
- /* start an evconnlistener on the appropriate port(s) */
- listener = listener_new(base,
- mode, protocol,
- (struct sockaddr *)&ss_listen, sl_listen,
- sa_target, sl_target,
- shared_secret,
- shared_secret ? strlen(shared_secret) : 0);
- if (! listener) {
- printf("Couldn't create listener!\n");
+ if (event_add(sigevent,NULL)) {
+ printf("Oh come on! We can't even add events for signals! Exiting.\n");
return 4;
}
- /* run the event loop */
- event_base_dispatch(base);
+ /*Let's open a new listener for each protocol. */
+ int h;
+ listener_t *listeners[actual_protocols];
+ listener_t *temp_listener;
+ int n_listeners=0;
+ for (h=0;h<actual_protocols;h++) {
+ if (n_protocols > 1) {
+ printf("===========================\n"
+ "Spawning listener %d!\n"
+ "===========================\n", h+1);
+ }
+
+ temp_listener = listener_new(base, n_options_array[h], protocol_options[h]);
+
+ /** Free the space allocated for this protocol's options. */
+ for (i=0;i<n_options_array[h];i++)
+ free(protocol_options[h][i]);
+ free(protocol_options[h]);
+
+ if (!temp_listener) {
+ continue;
+ }
+
+ printf("Succesfully created listener.\n");
+ listeners[n_listeners] = temp_listener;
+
+ n_listeners++;
+ }
+
+ if (n_protocols > 1) {
+ printf("\n===========================\n"
+ "From the original %d protocols only %d were parsed from main.c. "
+ "In the end only %d survived.\n\nStarting up...\n"
+ "===========================\n",
+ n_protocols, actual_protocols,n_listeners);
+ }
+
+ /* run the event loop if at least a listener was created. */
+ if (n_listeners)
+ event_base_dispatch(base);
- listener_free(listener);
+ /* We are exiting. Clean everything. */
+ for (h=0;h<n_listeners;h++)
+ listener_free(listeners[h]);
+ free(protocol_options);
+ free(n_options_array);
return 0;
}
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits