diff --git a/apps/sam/c/Makefile b/apps/sam/c/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..72fa21cd237c0ebcc288adf4bbb76cb4f9da0b43 --- /dev/null +++ b/apps/sam/c/Makefile @@ -0,0 +1,64 @@ +FLAGS+=-g +CFLAGS+=$(FLAGS) +LDFLAGS+=$(FLAGS) + +OBJS:=obj/sam.lo obj/strl.lo obj/parse.lo obj/tinystring.lo +DEPS:=$(patsubst obj/%.lo, .deps/%.d, $(OBJS)) +DESTDIR:=$(if $(DESTDIR),$(DESTDIR)/lib,/usr/lib) + +MAKEFLAGS=-s -r + +PERL=$(shell which perl 2>/dev/null) +ifneq ($(PERL),) +STATUS=$(PERL) ./status +else +STATUS=echo +endif + +LIBTOOL_LOG=libtool.log + +all:: cleanlog .deps/finish + +cleanlog: + echo >$(LIBTOOL_LOG) + +lib/libsam.so: obj/libsam.la + libtool --mode=install install $^ `pwd`/$@ >>$(LIBTOOL_LOG) + +obj/libsam-static.la: $(OBJS) + $(STATUS) library '(static)' + libtool --mode=link gcc -static $(LDFLAGS) -o $@ $^ >>$(LIBTOOL_LOG) + +obj/libsam.la: $(OBJS) + $(STATUS) library '(shared)' + libtool --mode=link gcc -rpath $(DESTDIR) $(LDFLAGS) -o $@ $^ >>$(LIBTOOL_LOG) + +obj/%.lo: src/%.c + $(STATUS) compile $* + libtool --mode=compile gcc $(CFLAGS) -Iinc/ -c -o $@ $< >>$(LIBTOOL_LOG) + +$(OBJS):|obj +obj: + $(STATUS) MKDIR $@ + mkdir -p $@ + +.deps/%.d: src/%.c + $(STATUS) deps $* + gcc -Iinc/ -MM -MT obj/$*.o $< -o $@ + +-include $(DEPS) + +DEPS+=.deps/finish +.deps/finish: lib/libsam.so + libtool --finish $(DESTDIR) >>$(LIBTOOL_LOG) && touch $@ +$(DEPS):|.deps +.deps: + $(STATUS) MKDIR $@ + mkdir -p $@ + +clean: + $(STATUS) clean + libtool --mode=clean rm -f obj/*.l* lib/*.l* lib/*.so* lib/*.a >>$(LIBTOOL_LOG) + rm -Rf .deps libtool.log + +.PHONY: all cleanlog clean \ No newline at end of file diff --git a/apps/sam/c/Makefile.common b/apps/sam/c/Makefile.common deleted file mode 100644 index a8b2a1a725b7154b2acb846a550c3717dcc50762..0000000000000000000000000000000000000000 --- a/apps/sam/c/Makefile.common +++ /dev/null @@ -1,25 +0,0 @@ -# -# This Makefile contains instructions common to all platforms -# - -# -# Build rules -# - -all: clean depend libsam - -depend: - $(CC) $(CFLAGS) -MM $(SRCDIR)/*.c > .depend - -$(OBJDIR)/%.o: $(SRCDIR)/%.c - $(CC) $(CFLAGS) -o $@ -c $< - -libsam: $(OBJS) - $(AR) rcs $(LIBDIR)/libsam.a $(OBJS) - -# -# Cleanup rules -# - -clean: - -$(RM) -f $(LIBDIR)/libsam.a $(OBJDIR)/*.o .depend diff --git a/apps/sam/c/Makefile.cygwin b/apps/sam/c/Makefile.cygwin deleted file mode 100644 index 3ffb2539096bde9ff8fbeb42b3039ff895f36ce5..0000000000000000000000000000000000000000 --- a/apps/sam/c/Makefile.cygwin +++ /dev/null @@ -1,48 +0,0 @@ -# -# This Makefile is compatible with GNU Make and should work on Cygwin -# - -# -# Your operating system -# - -OS = CYGWIN - -# -# Directories -# - -INCDIR = inc -LIBDIR = lib -OBJDIR = obj -SRCDIR = src - -# -# Programs -# - -AR = ar -CC = gcc -RM = rm - -# -# Flags -# - -CFLAGS = -g -O2 -pipe -std=c99 -Wall -CFLAGS += -DOS=$(OS) -CFLAGS += -I$(INCDIR) - -# -# Object files -# - -OBJS = $(OBJDIR)/sam.o \ - $(OBJDIR)/snprintf.o \ - $(OBJDIR)/strl.o - -# -# Include the make instructions common to all platforms -# - -include Makefile.common diff --git a/apps/sam/c/Makefile.freebsd b/apps/sam/c/Makefile.freebsd deleted file mode 100644 index 3fdf8f315e801af2d53d3f229f997c5582c8fcee..0000000000000000000000000000000000000000 --- a/apps/sam/c/Makefile.freebsd +++ /dev/null @@ -1,46 +0,0 @@ -# -# This Makefile is compatible with GNU Make and should work on FreeBSD -# - -# -# Your operating system -# - -OS = FREEBSD - -# -# Directories -# - -INCDIR = inc -LIBDIR = lib -OBJDIR = obj -SRCDIR = src - -# -# Programs -# - -AR = ar -CC = gcc -RM = rm - -# -# Flags -# - -CFLAGS = -g -O2 -pipe -std=c99 -Wall -CFLAGS += -DOS=$(OS) -CFLAGS += -I$(INCDIR) - -# -# Object files -# - -OBJS = $(OBJDIR)/sam.o - -# -# Include the make instructions common to all platforms -# - -include Makefile.common diff --git a/apps/sam/c/Makefile.linux b/apps/sam/c/Makefile.linux deleted file mode 100644 index 7eddeed32d115df162147c5c688f03844f2389bc..0000000000000000000000000000000000000000 --- a/apps/sam/c/Makefile.linux +++ /dev/null @@ -1,47 +0,0 @@ -# -# This Makefile is compatible with GNU Make and should work on Linux -# - -# -# Your operating system -# - -OS = LINUX - -# -# Directories -# - -INCDIR = inc -LIBDIR = lib -OBJDIR = obj -SRCDIR = src - -# -# Programs -# - -AR = ar -CC = gcc -RM = rm - -# -# Flags -# - -CFLAGS = -g -O2 -pipe -std=c99 -Wall -CFLAGS += -DOS=$(OS) -CFLAGS += -I$(INCDIR) - -# -# Object files -# - -OBJS = $(OBJDIR)/sam.o \ - $(OBJDIR)/strl.o - -# -# Include the make instructions common to all platforms -# - -include Makefile.common diff --git a/apps/sam/c/Makefile.mingw b/apps/sam/c/Makefile.mingw deleted file mode 100644 index d418f175a6a42bcbf1b1cdd55e2e271399aaef7b..0000000000000000000000000000000000000000 --- a/apps/sam/c/Makefile.mingw +++ /dev/null @@ -1,47 +0,0 @@ -# -# This Makefile is compatible with GNU Make and should work on Windows (MingW) -# - -# -# Your operating system -# - -OS = MINGW - -# -# Directories -# - -INCDIR = inc -LIBDIR = lib -OBJDIR = obj -SRCDIR = src - -# -# Programs -# - -AR = C:\MinGW\bin\ar -CC = C:\MinGW\bin\gcc -RM = C:\MinGW\bin\rm - -# -# Flags -# - -CFLAGS = -g -O2 -pipe -std=c99 -Wall -CFLAGS += -DOS=$(OS) -CFLAGS += -I$(INCDIR) - -# -# Object files -# - -OBJS = $(OBJDIR)/sam.o \ - $(OBJDIR)/strl.o - -# -# Include the make instructions common to all platforms -# - -include Makefile.common diff --git a/apps/sam/c/examples/i2p-ping/Makefile b/apps/sam/c/examples/i2p-ping/Makefile index b1ce9ddb96d3be2eb3acfb3ba2bd77c8e8ea67e4..9f5c27b5e2a4e7da06e992262cca68ede99c39cc 100644 --- a/apps/sam/c/examples/i2p-ping/Makefile +++ b/apps/sam/c/examples/i2p-ping/Makefile @@ -1,39 +1,54 @@ -# -# This Makefile is compatible with GNU Make and should work on POSIX systems -# +FLAGS+=-g -# -# Programs -# +CFLAGS = $(FLAGS) -pipe -std=c99 -Wall +CFLAGS += -I../../inc +LDFLAGS = $(FLAGS) -L../../lib -lsam -CC = gcc -INSTALL = install -RM = rm +OBJS:=i2p-ping.lo +DEPS:=$(patsubst obj/%.lo, .deps/%.d, $(OBJS)) +DESTDIR:=$(if $(DESTDIR),$(DESTDIR)/lib,/usr/lib) -# -# Flags -# +MAKEFLAGS=-s -r +PERL=$(shell which perl 2>/dev/null) +ifneq ($(PERL),) +STATUS=$(PERL) ../../status +else +STATUS=echo +endif -CFLAGS = -g -O2 -pipe -std=c99 -Wall -CFLAGS += -I../../inc -L../../lib -LIBS = -lsam +LIBTOOL_LOG=libtool.log -# -# Build rules -# +all:: cleanlog i2p-ping -all: clean i2p-ping +cleanlog: + >$(LIBTOOL_LOG) -i2p-ping: i2p-ping.c - $(CC) $(CFLAGS) -o i2p-ping.o -c i2p-ping.c - $(CC) $(CFLAGS) -o i2p-ping i2p-ping.o $(LIBS) +i2p-ping: $(OBJS) + $(STATUS) link + libtool --mode=link gcc $(LDFLAGS) -o $@ $^ >>$(LIBTOOL_LOG) -install: i2p-ping - $(INSTALL) i2p-ping $(HOME)/bin - -# -# Cleanup rules -# +%.lo: %.c + $(STATUS) compile $* + libtool --mode=compile gcc $(CFLAGS) -Iinc/ -c -o $@ $< >>$(LIBTOOL_LOG) +.deps/%.d: src/%.c + $(STATUS) deps $* + gcc -Iinc/ -MM -MT obj/$*.o $^ -o $@ clean: - -$(RM) -f i2p-ping *.o + $(STATUS) clean + rm -Rf .deps obj libtool.log + libtool --mode=clean rm -f i2p-ping i2p-ping.lo >>$(LIBTOOL_LOG) + +$(OBJS):|obj +obj: + $(STATUS) MKDIR $@ + mkdir -p $@ + +-include $(DEPS) +$(DEPS):|.deps +.deps: + $(STATUS) MKDIR $@ + mkdir -p $@ + + +.PHONY: all cleanlog clean \ No newline at end of file diff --git a/apps/sam/c/inc/parse.h b/apps/sam/c/inc/parse.h new file mode 100644 index 0000000000000000000000000000000000000000..960f2d8ca2da96f9aa205bd1ef891e1d6cf59848 --- /dev/null +++ b/apps/sam/c/inc/parse.h @@ -0,0 +1,24 @@ +#ifndef _PARSE_HEADER_FEEP +#define _PARSE_HEADER_FEEP + +#include "tinystring.h" + +typedef struct arg_s { + string_t name; + string_t value; + // int pos; +} arg_t; + +typedef struct { + arg_t* arg; + int num; +} args_t; + +args_t arg_parse(const char*); +void arg_done(args_t); +arg_t* arg_get(args_t,int); +arg_t* arg_find(args_t,string_t); + +#define AG(a,b) arg_get(a,b) + +#endif /* _PARSE_HEADER_FEEP */ diff --git a/apps/sam/c/inc/sam.h b/apps/sam/c/inc/sam.h index 32cce31566f64a7c4dbbc529e0dd53c5ff9e5038..29f5139f2754ebb7ece7afe1f2b216456cc435f1 100644 --- a/apps/sam/c/inc/sam.h +++ b/apps/sam/c/inc/sam.h @@ -121,9 +121,9 @@ bool sam_read_buffer(sam_sess_t *session); const char *sam_strerror(samerr_t code); /* SAM controls - callbacks */ void (*sam_diedback)(sam_sess_t *session); -void (*sam_logback)(char *str); -void (*sam_namingback)(sam_sess_t *session, char *name, - sam_pubkey_t pubkey, samerr_t result); +void (*sam_logback)(const char *str); +void (*sam_namingback)(sam_sess_t *session, const char *name, + sam_pubkey_t pubkey, samerr_t result, const char* message); /* Stream commands */ void sam_stream_close(sam_sess_t *session, sam_sid_t stream_id); @@ -131,14 +131,15 @@ sam_sid_t sam_stream_connect(sam_sess_t *session, const sam_pubkey_t dest); samerr_t sam_stream_send(sam_sess_t *session, sam_sid_t stream_id, const void *data, size_t size); /* Stream commands - callbacks */ -void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, - samerr_t reason); +void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, + samerr_t reason, const char* message); + void (*sam_connectback)(sam_sess_t *session, sam_sid_t stream_id, - sam_pubkey_t dest); -void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, + sam_pubkey_t dest); + void (*sam_databack)(sam_sess_t *session, sam_sid_t stream_id, void *data, size_t size); -void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, - samerr_t result); +void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, + samerr_t result, const char* message); /* Stream send queue (experimental) */ void sam_sendq_add(sam_sess_t *session, sam_sid_t stream_id, diff --git a/apps/sam/c/inc/tinystring.h b/apps/sam/c/inc/tinystring.h new file mode 100644 index 0000000000000000000000000000000000000000..f518e0ebc62f362f29d35bb1569d9774f9578065 --- /dev/null +++ b/apps/sam/c/inc/tinystring.h @@ -0,0 +1,48 @@ +#ifndef TINYSTRING_HEADER +#define TINYSTRING_HEADER + +#include <sys/types.h> + +#ifndef bool +#define bool short int +#endif + +struct string_s; +#define string_t struct string_s* +//Mysteeeerious *waggles mysteriously* + +/*{ + char* data; + long int size; +} *string_t; +*/ + +string_t string_create(const char*); +string_t string_ncreate(const char* cstr,long int length); + +string_t string_wrap(const char*); +//Does not malloc, do NOT pass to string_free + +string_t string_fmt(const char* fmt, ...); +string_t string_cat(string_t,string_t); + +/* Source Dest */ +void string_copy(string_t,string_t); +void string_copy_raw(string_t,void*,size_t); + +const char* string_data(string_t); +long int string_size(string_t); + +void string_free(string_t); + +bool string_equal(string_t,string_t); +bool string_equali(string_t,string_t); +int string_cmp(string_t,string_t); +int string_cmpi(string_t,string_t); + +#define _sw(a) string_wrap(a) +#define _scr(a,b,c) string_copy_raw(a,b,c) + +#define string_is(a,b) (! strncmp(string_data(a),(b),string_size(a))) + +#endif /* TINYSTRING_HEADER */ diff --git a/apps/sam/c/src/parse.c b/apps/sam/c/src/parse.c new file mode 100644 index 0000000000000000000000000000000000000000..6fcb33fc63b86903d2f390d5d0353b3eb8ce2353 --- /dev/null +++ b/apps/sam/c/src/parse.c @@ -0,0 +1,78 @@ +#include "parse.h" + +#include <assert.h> +#include <ctype.h> +#include <malloc.h> +#define _GNU_SOURCE +#include <string.h> + +args_t arg_parse(const char* line_raw) { + args_t self; + int numargs = 0; + const char *end, *last; + /* First pass to count how many args... */ + end = line_raw; + while(*end && isspace(*end)) ++end; + //Skip initial space... + for(;;) { + while(*end && !isspace(*end)) ++end; + //Go to end of argument + ++numargs; + while(*end && isspace(*end)) ++end; + //Go to end of space after argument + if(!*end) break; + } + self.num = numargs; // One more # args than spaces. + self.arg = malloc(sizeof(arg_t)*numargs); + + /* Second pass to assign args. (Lemee alone, is more efficient than a linked list!) */ + last = line_raw; + numargs = 0; //Now numargs is which current arg. + end = line_raw; + while(*end && isspace(*end)) ++end; + //Skip initial space... + for(;;) { + arg_t* nextarg = self.arg + numargs;; + const char* isbinary; + while(*end && !isspace(*end)) ++end; + //Go to end of argument + isbinary = strchr(last,'='); //Is there a value? + + //Make sure not to pass end in our search for = + if(isbinary && (isbinary < end)) { + nextarg->name = string_ncreate(last,isbinary-last); + nextarg->value = string_ncreate(isbinary+1,end-isbinary-1); + } else { + nextarg->name = string_ncreate(last,end-last); + nextarg->value = string_create(NULL); + } + ++numargs; + while(*end && isspace(*end)) ++end; + //Go to end of space after argument + if(!*end) break; + last = end; + } + return self; +} + +void arg_done(args_t self) { + free(self.arg); + self.arg = NULL; + self.num = 0; +} + +arg_t* arg_get(args_t self, int index) { + if(index >= self.num) return NULL; + return self.arg + index; +} + +arg_t* arg_find(args_t self,string_t testname) { + int index; + for(index=0;index<self.num;++index) { + if(string_equali(self.arg[index].name,testname)) { + return self.arg + index; + } + } + + return NULL; +} diff --git a/apps/sam/c/src/sam.c b/apps/sam/c/src/sam.c index 9fe35486edd0f79f8ecb51a66f086230e9b0542f..d9535588576a710acd9e25226623d73091b9c085 100644 --- a/apps/sam/c/src/sam.c +++ b/apps/sam/c/src/sam.c @@ -30,6 +30,10 @@ #include "sam.h" #include "platform.h" +#include "parse.h" +#include "tinystring.h" + +#include <assert.h> static bool sam_hello(sam_sess_t *session); static void sam_log(const char *format, ...); @@ -57,7 +61,7 @@ static ssize_t sam_write(sam_sess_t *session, const void *buf, size_t n); */ /* a peer closed the connection */ -void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason) +void (*sam_closeback)(sam_sess_t *session, sam_sid_t stream_id, samerr_t reason, const char* message) = NULL; /* a peer connected to us */ @@ -76,15 +80,14 @@ void (*sam_dgramback)(sam_sess_t *session, sam_pubkey_t dest, void *data, void (*sam_diedback)(sam_sess_t *session) = NULL; /* logging callback */ -void (*sam_logback)(char *str) = NULL; +void (*sam_logback)(const char *str) = NULL; /* naming lookup reply - `pubkey' will be NULL if `result' isn't SAM_OK */ -void (*sam_namingback)(sam_sess_t *session, char *name, sam_pubkey_t pubkey, - samerr_t result) = NULL; +void (*sam_namingback)(sam_sess_t *session, const char *name, sam_pubkey_t pubkey, samerr_t result, const char* message) = NULL; /* our connection to a peer has completed */ void (*sam_statusback)(sam_sess_t *session, sam_sid_t stream_id, - samerr_t result) = NULL; + samerr_t result, const char* message) = NULL; /* a peer sent some raw data (`data' MUST be freed) */ void (*sam_rawback)(sam_sess_t *session, void *data, size_t size) = NULL; @@ -290,13 +293,13 @@ static void sam_log(const char *format, ...) */ void sam_naming_lookup(sam_sess_t *session, const char *name) { - assert(session != NULL); - char cmd[SAM_CMD_LEN]; + assert(session != NULL); + char cmd[SAM_CMD_LEN]; - snprintf(cmd, sizeof cmd, "NAMING LOOKUP NAME=%s\n", name); - sam_write(session, cmd, strlen(cmd)); + snprintf(cmd, sizeof cmd, "NAMING LOOKUP NAME=%s\n", name); + sam_write(session, cmd, strlen(cmd)); - return; + return; } /* @@ -304,241 +307,192 @@ void sam_naming_lookup(sam_sess_t *session, const char *name) * * s - string of data that we read (read past tense) */ +bool sam_parse_args(sam_sess_t *session, args_t args); static void sam_parse(sam_sess_t *session, char *s) { - assert(session != NULL); -#define SAM_DGRAM_RECEIVED_REPLY "DATAGRAM RECEIVED" -#define SAM_NAMING_REPLY "NAMING REPLY" -#define SAM_NAMING_REPLY_OK "NAMING REPLY RESULT=OK" -#define SAM_NAMING_REPLY_IK "NAMING REPLY RESULT=INVALID_KEY" -#define SAM_NAMING_REPLY_KNF "NAMING REPLY RESULT=KEY_NOT_FOUND" -#define SAM_RAW_RECEIVED_REPLY "RAW RECEIVED" -#define SAM_STREAM_CLOSED_REPLY "STREAM CLOSED" -#define SAM_STREAM_CONNECTED_REPLY "STREAM CONNECTED" -#define SAM_STREAM_RECEIVED_REPLY "STREAM RECEIVED" -#define SAM_STREAM_STATUS_REPLY "STREAM STATUS" -#define SAM_STREAM_STATUS_REPLY_OK "STREAM STATUS RESULT=OK" -#define SAM_STREAM_STATUS_REPLY_CRP "STREAM STATUS RESULT=CANT_REACH_PEER" -#define SAM_STREAM_STATUS_REPLY_I2E "STREAM STATUS RESULT=I2P_ERROR" -#define SAM_STREAM_STATUS_REPLY_IK "STREAM STATUS RESULT=INVALID_KEY" -#define SAM_STREAM_STATUS_REPLY_TO "STREAM STATUS RESULT=TIMEOUT" + //Wrapper for ease of memory management + args_t args; + assert(session != NULL); + args = arg_parse(s); + if(!sam_parse_args(session, args)) { + SAMLOG("Unknown SAM command received: %s", s); + } + arg_done(args); +} - /* - * TODO: add raw parsing - */ +long int strtol_checked(const char* str) { + static char* end = NULL; + long int ret = strtol(str,&end,10); + assert(str != end || "No number found at all!"); + return ret; +} - if (strncmp(s, SAM_DGRAM_RECEIVED_REPLY, - strlen(SAM_DGRAM_RECEIVED_REPLY)) == 0) { - char *p; +bool sam_parse_args(sam_sess_t *session, args_t args) +{ + arg_t* arg; // The current argument being examined... + const char* message = NULL; // Almost EVERYTHING can have a message... + + if(args.num <= 0) return 0; + +#define ARG_IS(a,b) string_equal(AG(args,a)->name,string_wrap(b)) +#define ARG_FIND(a) arg_find(args,_sw(a)) + + // Almost EVERYTHING can have a message... + arg = ARG_FIND("MESSAGE"); + if(arg) { + message = string_data(arg->value); + } + + if(ARG_IS(0,"DATAGRAM") && + ARG_IS(1,"RECEIVED")) { + sam_pubkey_t dest; + size_t size; + void *data; + + arg = ARG_FIND("DESTINATION"); + assert(arg != NULL); + _scr(arg->value, dest, sizeof dest); + + arg = ARG_FIND("SIZE"); + assert(arg != NULL); + size = strtol_checked(string_data(arg->value)); + + data = malloc(size + 1); + /* +1 for NUL termination, so when we are + receiving a string it will just work and it + won't be necessary to send NUL. When binary + data is sent, the extra NUL character will + just be ignored by the client program, + because it is not added to the size */ + if (data == NULL) { + SAMLOGS("Out of memory"); + abort(); + } + if (sam_read2(session, data, size) != -1) { + char* p = data + size; + *p = '\0'; /* see above NUL note */ + sam_dgramback(session, dest, data, size); /* `data' must be freed */ + } else + free(data); + + } else if (ARG_IS(0,"NAMING") && + ARG_IS(1, "REPLY")) { + if(NULL == (arg = ARG_FIND("RESULT"))) { + SAMLOGS("Naming reply with no result"); + return 0; + } + + if (string_is(arg->value,"OK")) { + sam_pubkey_t pubkey; + arg = ARG_FIND("VALUE"); + assert(arg != NULL); + _scr(arg->value, pubkey, sizeof pubkey); + arg = ARG_FIND("NAME"); + assert(arg != NULL); + + sam_namingback(session, string_data(arg->value), pubkey, SAM_OK, message); + } else if(string_is(arg->value,"INVALID_KEY")) { + arg_t* namearg = ARG_FIND("NAME"); + assert(namearg != NULL); + sam_namingback(session, string_data(namearg->value), NULL, + SAM_INVALID_KEY, message); + } else if(string_is(arg->value,"KEY_NOT_FOUND")) { + arg_t* namearg = ARG_FIND("NAME"); + assert(namearg != NULL); + sam_namingback(session, string_data(namearg->value), NULL, + SAM_KEY_NOT_FOUND, message); + } else { + arg_t* namearg = ARG_FIND("NAME"); + assert(namearg != NULL); + sam_namingback(session, string_data(namearg->value), NULL, + SAM_UNKNOWN, message); + } + + } else if (ARG_IS(0,"STREAM")) { + sam_sid_t stream_id; + arg = ARG_FIND("ID"); + assert(arg != 0); + stream_id = strtol_checked(string_data(arg->value)); + + if(ARG_IS(1,"CLOSED")) { + arg = ARG_FIND("RESULT"); + assert(arg != NULL); + if (string_is(arg->value,"OK")) { + sam_closeback(session, stream_id, SAM_OK, message); + } else if (string_is(arg->value,"CANT_REACH_PEER")) { + sam_closeback(session, stream_id, SAM_CANT_REACH_PEER, message); + } else if (string_is(arg->value,"I2P_ERROR")) { + sam_closeback(session, stream_id, SAM_I2P_ERROR, message); + } else if (string_is(arg->value,"PEER_NOT_FOUND")) { + sam_closeback(session, stream_id, SAM_PEER_NOT_FOUND, message); + } else if (string_is(arg->value,"TIMEOUT")) { + sam_closeback(session, stream_id, SAM_TIMEOUT, message); + } else { + sam_closeback(session, stream_id, SAM_UNKNOWN, message); + } + + } else if(ARG_IS(1,"CONNECTED")) { sam_pubkey_t dest; - size_t size; - void *data; - - p = strchr(s, '='); /* DESTINATION= */ - assert(p != NULL); - p++; - strlcpy(dest, p, sizeof dest); - p = strchr(p, '='); /* SIZE= */ - assert(p != NULL); - p++; - size = strtol(p, NULL, 10); - assert(size != 0); - data = malloc(size + 1); /* +1 for NUL termination, so when we are - receiving a string it will just work and it - won't be necessary to send NUL. When binary - data is sent, the extra NUL character will - just be ignored by the client program, - because it is not added to the size */ - if (data == NULL) { - SAMLOGS("Out of memory"); - abort(); - } - if (sam_read2(session, data, size) != -1) { - p = data + size; - *p = '\0'; /* see above NUL note */ - sam_dgramback(session, dest, data, size); /* `data' must be freed */ - } else - free(data); - - return; - - } else if (strncmp(s, SAM_NAMING_REPLY, strlen(SAM_NAMING_REPLY)) == 0) { - char *p; - char *q; - char name[SAM_NAME_LEN]; - p = strchr(s, '='); /* can't use strrchar because of option - MESSAGE= */ - assert(p != NULL); /* RESULT= */ - p++; - p = strchr(p, '='); /* NAME= */ - assert(p != NULL); - p++; + arg = ARG_FIND("DESTINATION"); + assert(arg != NULL); + _scr(arg->value, dest, sizeof dest); - if (strncmp(s, SAM_NAMING_REPLY_OK, strlen(SAM_NAMING_REPLY_OK)) == 0) { - sam_pubkey_t pubkey; - - q = strchr(p, ' '); /* ' 'VAL.. */ - assert(q != NULL); - *q = '\0'; - q++; - q = strchr(q, '='); /* VALUE= */ - assert(q != NULL); - q++; - strlcpy(name, p, sizeof name); - strlcpy(pubkey, q, sizeof pubkey); - sam_namingback(session, name, pubkey, SAM_OK); - - } else if (strncmp(s, SAM_NAMING_REPLY_IK, - strlen(SAM_NAMING_REPLY_IK)) == 0) { - q = strchr(p, ' '); /* ' 'MES.. (optional) */ - if (q != NULL) - *q = '\0'; - strlcpy(name, p, sizeof name); - sam_namingback(session, name, NULL, SAM_INVALID_KEY); - - } else if (strncmp(s, SAM_NAMING_REPLY_KNF, - strlen(SAM_NAMING_REPLY_KNF)) == 0) { - q = strchr(p, ' '); /* ' 'MES.. (optional) */ - if (q != NULL) - *q = '\0'; - strlcpy(name, p, sizeof name); - sam_namingback(session, name, NULL, SAM_KEY_NOT_FOUND); - - } else { - q = strchr(p, ' '); /* ' 'MES.. (optional) */ - if (q != NULL) - *q = '\0'; - strlcpy(name, p, sizeof name); - sam_namingback(session, name, NULL, SAM_UNKNOWN); - } - - return; - - } else if (strncmp(s, SAM_STREAM_CLOSED_REPLY, - strlen(SAM_STREAM_CLOSED_REPLY)) == 0) { - char *p; - sam_sid_t stream_id; - - p = strchr(s, '='); /* can't use strrchar because of option MESSAGE= */ - assert(p != NULL); /* ID= */ - p++; - stream_id = strtol(p, NULL, 10); - assert(stream_id != 0); - p = strchr(p, '='); /* RESULT= */ - assert(p != NULL); - p++; - if (strncmp(p, "OK", strlen("OK")) == 0) - sam_closeback(session, stream_id, SAM_OK); - else if (strncmp(p, "CANT_REACH_PEER", strlen("CANT_REACH_PEER")) == 0) - sam_closeback(session, stream_id, SAM_CANT_REACH_PEER); - else if (strncmp(p, "I2P_ERROR", strlen("I2P_ERROR")) == 0) - sam_closeback(session, stream_id, SAM_I2P_ERROR); - else if (strncmp(p, "PEER_NOT_FOUND", strlen("PEER_NOT_FOUND")) == 0) - sam_closeback(session, stream_id, SAM_PEER_NOT_FOUND); - else if (strncmp(p, "TIMEOUT", strlen("TIMEOUT")) == 0) - sam_closeback(session, stream_id, SAM_TIMEOUT); - else - sam_closeback(session, stream_id, SAM_UNKNOWN); - - return; - - } else if (strncmp(s, SAM_STREAM_CONNECTED_REPLY, - strlen(SAM_STREAM_CONNECTED_REPLY)) == 0) { - char *p; - sam_sid_t stream_id; - sam_pubkey_t dest; - - p = strrchr(s, '='); /* ID= */ - assert(p != NULL); - *p = '\0'; - p++; - stream_id = strtol(p, NULL, 10); - assert(stream_id != 0); - p = strstr(s, "N="); /* DESTINATION= */ - p += 2; - strlcpy(dest, p, sizeof dest); sam_connectback(session, stream_id, dest); - - return; - } else if (strncmp(s, SAM_STREAM_RECEIVED_REPLY, - strlen(SAM_STREAM_RECEIVED_REPLY)) == 0) { - char *p; - sam_sid_t stream_id; + } else if(ARG_IS(1,"RECEIVED")) { size_t size; void *data; - p = strrchr(s, '='); /* SIZE= */ - assert(p != NULL); - p++; - size = strtol(p, NULL, 10); - assert(size != 0); - p -= 6; - *p = '\0'; - p = strrchr(s, '='); /* ID= */ - assert(p != NULL); - p++; - stream_id = strtol(p, NULL, 10); - assert(stream_id != 0); - data = malloc(size + 1); /* +1 for NUL termination, so when we are - receiving a string it will just work and it - won't be necessary to send NUL. When binary - data is sent, the extra NUL character will - just be ignored by the client program, - because it is not added to the size */ + arg = ARG_FIND("SIZE"); + assert(arg != NULL); + size = strtol_checked(string_data(arg->value)); + + data = malloc(size + 1); + /* +1 for NUL termination, so when we are + receiving a string it will just work and it + won't be necessary to send NUL. When binary + data is sent, the extra NUL character will + just be ignored by the client program, + because it is not added to the size */ if (data == NULL) { SAMLOGS("Out of memory"); abort(); } if (sam_read2(session, data, size) != -1) { - p = data + size; + char* p = data + size; *p = '\0'; /* see above NUL note */ sam_databack(session, stream_id, data, size); /* ^^^ `data' must be freed ^^^*/ } else free(data); - return; - - } else if (strncmp(s, SAM_STREAM_STATUS_REPLY, - strlen(SAM_STREAM_STATUS_REPLY)) == 0) { - char *p; - sam_sid_t stream_id; - - p = strchr(s, '='); /* can't use strrchar because of option MESSAGE= */ - assert(p != NULL); /* RESULT= */ - p++; - p = strchr(p, '='); /* ID= */ - assert(p != NULL); - p++; - stream_id = strtol(p, NULL, 10); - assert(stream_id != 0); - if (strncmp(s, SAM_STREAM_STATUS_REPLY_OK, - strlen(SAM_STREAM_STATUS_REPLY_OK)) == 0) - sam_statusback(session, stream_id, SAM_OK); - else if (strncmp(s, SAM_STREAM_STATUS_REPLY_CRP, - strlen(SAM_STREAM_STATUS_REPLY_CRP)) == 0) - sam_statusback(session, stream_id, SAM_CANT_REACH_PEER); - else if (strncmp(s, SAM_STREAM_STATUS_REPLY_I2E, - strlen(SAM_STREAM_STATUS_REPLY_I2E)) == 0) - sam_statusback(session, stream_id, SAM_I2P_ERROR); - else if (strncmp(s, SAM_STREAM_STATUS_REPLY_IK, - strlen(SAM_STREAM_STATUS_REPLY_IK)) == 0) - sam_statusback(session, stream_id, SAM_INVALID_KEY); - else if (strncmp(s, SAM_STREAM_STATUS_REPLY_TO, - strlen(SAM_STREAM_STATUS_REPLY_TO)) == 0) - sam_statusback(session, stream_id, SAM_TIMEOUT); - else - sam_statusback(session, stream_id, SAM_UNKNOWN); + } else if(ARG_IS(1,"STATUS")) { + arg = ARG_FIND("RESULT"); + assert(arg != NULL); + if (string_is(arg->value,"OK")) { + sam_statusback(session, stream_id, SAM_OK, message); + } else if (string_is(arg->value,"CANT_REACH_PEER")) { + sam_statusback(session, stream_id, + SAM_CANT_REACH_PEER, message); + } else if (string_is(arg->value,"I2P_ERROR")) { + sam_statusback(session, stream_id, SAM_I2P_ERROR, message); + } else if (string_is(arg->value,"INVALID_KEY")) { + sam_statusback(session, stream_id, SAM_INVALID_KEY, message); + } else if (string_is(arg->value,"TIMEOUT")) { + sam_statusback(session, stream_id, SAM_TIMEOUT, message); + } else { + sam_statusback(session, stream_id, SAM_UNKNOWN, message); + } + } + } else + return 0; + return -1; +} - return; +#undef ARG_IS +#undef ARG_FIND - } else - SAMLOG("Unknown SAM command received: %s", s); - - return; -} /* * Sends data to a destination in a raw packet diff --git a/apps/sam/c/src/tinystring.c b/apps/sam/c/src/tinystring.c new file mode 100644 index 0000000000000000000000000000000000000000..395a50a88507a77df45fd12098503eee2535bad2 --- /dev/null +++ b/apps/sam/c/src/tinystring.c @@ -0,0 +1,128 @@ +#include "tinystring.h" + +#include <assert.h> +#include <stdarg.h> +#include <stdio.h> +#include <malloc.h> +#define _GNU_SOURCE +#include <string.h> + +#ifndef min +#define min(a,b) ((a) > (b) ? (b) : (a)) +#endif + +extern char *strndup(const char *s, size_t n); + + +struct string_s { + const char* data; + long int size; + bool _no_del; //SIGH... +}; + +string_t string_ncreate(const char* cstr,long int length) { + string_t self = malloc(sizeof(struct string_s)); + self->size = length; + if(cstr) self->data = strndup(cstr,length); + else self->data = NULL; + self->_no_del = 0; + return self; +} + +string_t string_create(const char* cstr) { + if(!cstr) + return string_ncreate(NULL, 0); + return string_ncreate(cstr, strlen(cstr)); +} + +string_t string_nwrap(const char* cstr, long int length) { + static struct string_s self; + self.size = length; + self.data = cstr; + self._no_del = 1; + return &self; +} + +string_t string_wrap(const char* cstr) { + if(!cstr) + return string_nwrap(NULL, 0); + return string_nwrap(cstr, strlen(cstr)); +} + +string_t string_fmt(const char* fmt, ...) { + va_list args; + FILE* tmp = tmpfile(); + string_t self = malloc(sizeof(struct string_s)); + char* data; + va_start(args, fmt); + vfprintf(tmp, fmt, args); + va_end(args); + + self->size = ftell(tmp); + + rewind(tmp); + data = malloc(self->size); + fread(data, self->size, sizeof(char), tmp); + + fclose(tmp); + self->data = data; + return self; +} + +string_t string_cat(string_t head,string_t tail) { + //There are two ways to skin a cat... + string_t self = malloc(sizeof(struct string_s)); + char* data; + self->size = head->size+tail->size; + data = malloc(self->size); + memcpy(data, head->data, head->size); + memcpy(data+head->size,tail->data,tail->size); + self->data = data; + return self; +} + +/* Source Dest */ +void string_copy(string_t src,string_t dest) { + dest->data = realloc((char*)dest->data,src->size); + memcpy((char*)dest->data,src->data,dest->size); +} + +void string_copy_raw(string_t src, void* dest,size_t size) { + size = min(src->size,size); + memcpy(dest,src->data,size); +} + +const char* string_data(string_t self) { + return self->data; +} + +long int string_size(string_t self) { + return self->size; +} + +void string_free(string_t self) { + if(!self->_no_del) + free((char*)self->data); + + free(self); +} + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +bool string_equal(string_t this,string_t that) { + return !memcmp(this->data,that->data,min(this->size,that->size)); +} + +bool string_equali(string_t this,string_t that) { + return !strncasecmp(this->data,that->data,min(this->size,that->size)); +} + +int string_cmp(string_t this,string_t that) { + return memcmp(this->data,that->data,min(this->size,that->size)); +} + +int string_cmpi(string_t this,string_t that) { + return strncasecmp(this->data,that->data,min(this->size,that->size)); +} diff --git a/apps/sam/c/status b/apps/sam/c/status new file mode 100644 index 0000000000000000000000000000000000000000..519f653d1c6097bf71e81be06c13500bf4d49201 --- /dev/null +++ b/apps/sam/c/status @@ -0,0 +1,4 @@ +#!/usr/bin/env perl + +printf "%-8s ",uc(shift @ARGV); +print join(' ', @ARGV),"\n";