I removed those dumb platform specific makefiles. They weren't doing what they ought anyway. If there are platform specific issues, someone please tell me and I'll provide support for it here. Or patch it yourself.

And this is the big "Fix the Parser" patch.  It turns the sam_parse function in src/parse.c into something that actually works.  Generating the argument list from an incoming SAM thingy is a bit memory churn-y; perhaps when I have time I'll replace all those strdups with structures that simply track the (start,end) indices.
Oh and also I moved i2p-ping to the new system.  Which required 0 change in code.  All I did was fix the Makefile, and add shared library libtool support.  Anyway, so enjoy folks.  It's rare I'm this productive
- polecat
This commit is contained in:
polecat
2005-04-23 03:28:40 +00:00
committed by zzz
parent 20cec857d2
commit dae6be14b7
14 changed files with 578 additions and 475 deletions

64
apps/sam/c/Makefile Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

24
apps/sam/c/inc/parse.h Normal file
View File

@ -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 */

View File

@ -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,

View File

@ -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 */

78
apps/sam/c/src/parse.c Normal file
View File

@ -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;
}

View File

@ -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,242 +307,193 @@ 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;
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++;
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);
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...
return;
if(args.num <= 0) return 0;
} else if (strncmp(s, SAM_STREAM_RECEIVED_REPLY,
strlen(SAM_STREAM_RECEIVED_REPLY)) == 0) {
char *p;
sam_sid_t stream_id;
#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;
arg = ARG_FIND("DESTINATION");
assert(arg != NULL);
_scr(arg->value, dest, sizeof dest);
sam_connectback(session, stream_id, dest);
} 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);
return;
} else
SAMLOG("Unknown SAM command received: %s", s);
return;
} 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;
}
#undef ARG_IS
#undef ARG_FIND
/*
* Sends data to a destination in a raw packet
*

128
apps/sam/c/src/tinystring.c Normal file
View File

@ -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));
}

4
apps/sam/c/status Normal file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env perl
printf "%-8s ",uc(shift @ARGV);
print join(' ', @ARGV),"\n";