diff --git a/supportlibs/libsam3/Makefile b/supportlibs/libsam3/Makefile deleted file mode 100644 index f8d92a090..000000000 --- a/supportlibs/libsam3/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -CFLAGS := -Wall -g -O2 -std=gnu99 - -SRCS := \ - src/libsam3/libsam3.c \ - src/libsam3a/libsam3a.c - -TESTS := \ - src/ext/tinytest.c \ - test/test.c \ - test/libsam3/test_b32.c - -LIB_OBJS := ${SRCS:.c=.o} -TEST_OBJS := ${TESTS:.c=.o} - -OBJS := ${LIB_OBJS} ${TEST_OBJS} - -LIB := libsam3.a - -all: build check - -check: libsam3-tests - ./libsam3-tests - -build: ${LIB} - -${LIB}: ${LIB_OBJS} - ${AR} -sr ${LIB} ${LIB_OBJS} - -libsam3-tests: ${TEST_OBJS} ${LIB} - ${CC} $^ -o $@ - -clean: - rm -f libsam3-tests ${LIB} ${OBJS} examples/sam3/samtest - -%.o: %.c Makefile - ${CC} ${CFLAGS} $(LDFLAGS) -c $< -o $@ - -fmt: - find . -name '*.c' -exec clang-format -i {} \; - find . -name '*.h' -exec clang-format -i {} \; - -info: - @echo $(AR) diff --git a/supportlibs/libsam3/README.md b/supportlibs/libsam3/README.md deleted file mode 100644 index cd6b291a5..000000000 --- a/supportlibs/libsam3/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# libsam3 - -[![Build Status](https://travis-ci.org/i2p/libsam3.svg?branch=master)](https://travis-ci.org/i2p/libsam3) - -A C library for the [SAM v3 API](https://geti2p.net/en/docs/api/samv3). - -## Development Status - -Maintained by idk, PRs are accepted on [I2P gitlab](https://i2pgit.org/i2p-hackers/libsam3)/[I2P gitlab](http://git.idk.i2p/i2p-hackers/libsam3), and on github at the official mirror repository: [i2p/libsam3](https://github.com/i2p/libsam3). - -## Usage - -Copy the two files from one of the following locations into your codebase: - -- `src/libsam3` - Synchronous implementation. -- `src/libsam3a` - Asynchronous implementation. - -See `examples/` for how to use various parts of the API. - -## Cross-Compiling for Windows from debian: - -Set your cross-compiler up: - -``` sh -export CC=x86_64-w64-mingw32-gcc -export CFLAGS='-Wall -O2 ' -export LDFLAGS='-lmingw32 -lws2_32 -lwsock32 -mwindows' -``` - -and run `make build`. Only libsam3 is available for Windows, libsam3a will be -made available at a later date. -` - -## Linker(Windows) - -When building for Windows remember to set the flags to link to the Winsock and Windows -libraries. - -`-lmingw32 -lws2_32 -lwsock32 -mwindows` - -This may apply when cross-compiling or compiling from Windows with mingw. - -## Cool Projects using libsam3 - -Are you using libsam3 to provide an a cool I2P based feature to your project? Let us know about it(and how -it uses libsam3) and we'll think about adding it here*! - - 1. [Retroshare](https://retroshare.cc) - -*Projects which are listed here must be actively maintained. Those which intentionally violate -the law or the rights of a person or persons directly won't be considered. Neither will obvious -trolling. The maintainer will make the final decision. diff --git a/supportlibs/libsam3/examples/libsam3 b/supportlibs/libsam3/examples/libsam3 deleted file mode 120000 index 136138896..000000000 --- a/supportlibs/libsam3/examples/libsam3 +++ /dev/null @@ -1 +0,0 @@ -../src/libsam3 \ No newline at end of file diff --git a/supportlibs/libsam3/examples/sam3/README.md b/supportlibs/libsam3/examples/sam3/README.md deleted file mode 100644 index 1228e4984..000000000 --- a/supportlibs/libsam3/examples/sam3/README.md +++ /dev/null @@ -1,26 +0,0 @@ -Examples -======== - -These examples show various ways of using libsam3 to enable i2p in your -application, and are also useful in other ways. If you implement an i2p -application library in another language, making variants basic tools wouldn't be -the worst way to make sure that it works. - -building --------- - -Once you have build the library in the root of this repository by running make -all, you can build all these examples at once by running - - make - -in this directory. I think it makes things easier to experiment with quickly. - -namelookup ----------- - -Namelookup uses the SAM API to find the base64 destination of an readable "jump" -or base32 i2p address. You can use it like this: - - ./lookup i2p-projekt.i2p - diff --git a/supportlibs/libsam3/examples/sam3/dgramc.c b/supportlibs/libsam3/examples/sam3/dgramc.c deleted file mode 100644 index 898a9aec1..000000000 --- a/supportlibs/libsam3/examples/sam3/dgramc.c +++ /dev/null @@ -1,116 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -// comment the following if you don't want to stress UDP with 'big' datagram -// seems that up to 32000 bytes can be used for localhost -// note that we need 516+6+? bytes for header; lets reserve 1024 bytes for it -#define BIG (32000 - 1024) - -#define KEYFILE "dgrams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - char buf[1024]; - char destkey[517] = {0}; // 516 chars + \0 - int sz; - // - libsam3_debug = 1; - // - if (argc < 2) { - FILE *fl = fopen(KEYFILE, "rb"); - // - if (fl != NULL) { - if (fread(destkey, 516, 1, fl) == 1) { - fclose(fl); - goto ok; - } - fclose(fl); - } - printf("usage: dgramc PUBKEY\n"); - return 1; - } else { - if (strlen(argv[1]) != 516) { - fprintf(stderr, "FATAL: invalid key length!\n"); - return 1; - } - strcpy(destkey, argv[1]); - } - // -ok: - printf("creating session...\n"); - /* create TRANSIENT session with temporary disposible destination */ - if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, - SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_DGRAM, 4, - NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - /* send datagram */ - printf("sending test datagram...\n"); - if (sam3DatagramSend(&ses, destkey, "test", 4) < 0) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - /** receive reply */ - if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - /** null terminated string */ - buf[sz] = 0; - printf("received: [%s]\n", buf); - // -#ifdef BIG - { - char *big = calloc(BIG + 1024, sizeof(char)); - /** generate random string */ - sam3GenChannelName(big, BIG + 1023, BIG + 1023); - printf("sending BIG datagram...\n"); - if (sam3DatagramSend(&ses, destkey, big, BIG) < 0) { - free(big); - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - if ((sz = sam3DatagramReceive(&ses, big, BIG + 512)) < 0) { - free(big); - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - big[sz] = 0; - printf("received (%d): [%s]\n", sz, big); - free(big); - } -#endif - // - printf("sending quit datagram...\n"); - if (sam3DatagramSend(&ses, destkey, "quit", 4) < 0) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - buf[sz] = 0; - printf("received: [%s]\n", buf); - // - sam3CloseSession(&ses); - return 0; -error: - sam3CloseSession(&ses); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/dgrams.c b/supportlibs/libsam3/examples/sam3/dgrams.c deleted file mode 100644 index 1fe0fc0f7..000000000 --- a/supportlibs/libsam3/examples/sam3/dgrams.c +++ /dev/null @@ -1,113 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -#define KEYFILE "dgrams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - char privkey[1024], pubkey[1024], buf[33 * 1024]; - - /** quit command */ - const char *quitstr = "quit"; - const size_t quitlen = strlen(quitstr); - - /** reply response */ - const char *replystr = "reply: "; - const size_t replylen = strlen(replystr); - - FILE *fl; - // - libsam3_debug = 1; - // - - /** generate new destination keypair */ - printf("generating keys...\n"); - if (sam3GenerateKeys(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, 4) < 0) { - fprintf(stderr, "FATAL: can't generate keys\n"); - return 1; - } - /** copy keypair into local buffer */ - strncpy(pubkey, ses.pubkey, sizeof(pubkey)); - strncpy(privkey, ses.privkey, sizeof(privkey)); - /** create sam session */ - printf("creating session...\n"); - if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, privkey, - SAM3_SESSION_DGRAM, 5, NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - /** make sure we have the right destination */ - // FIXME: probably not needed - if (strcmp(pubkey, ses.pubkey) != 0) { - fprintf(stderr, "FATAL: destination keys don't match\n"); - sam3CloseSession(&ses); - return 1; - } - /** print destination to stdout */ - printf("PUB KEY\n=======\n%s\n=======\n", ses.pubkey); - if ((fl = fopen(KEYFILE, "wb")) != NULL) { - /** write public key to keyfile */ - fwrite(pubkey, strlen(pubkey), 1, fl); - fclose(fl); - } - - /* now listen for UDP packets */ - printf("starting main loop...\n"); - for (;;) { - /** save replylen bytes for out reply at begining */ - char *datagramBuf = buf + replylen; - const size_t datagramMaxLen = sizeof(buf) - replylen; - int sz, isquit; - printf("waiting for datagram...\n"); - /** blocks until we get a UDP packet */ - if ((sz = sam3DatagramReceive(&ses, datagramBuf, datagramMaxLen) < 0)) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - /** ensure null terminated string */ - datagramBuf[sz] = 0; - /** print out datagram payload to user */ - printf("FROM\n====\n%s\n====\n", ses.destkey); - printf("SIZE=%d\n", sz); - printf("data: [%s]\n", datagramBuf); - /** check for "quit" */ - isquit = (sz == quitlen && memcmp(datagramBuf, quitstr, quitlen) == 0); - /** echo datagram back to sender with "reply: " at the beginning */ - memcpy(buf, replystr, replylen); - - if (sam3DatagramSend(&ses, ses.destkey, buf, sz + replylen) < 0) { - fprintf(stderr, "ERROR: %s\n", ses.error); - goto error; - } - /** if we got a quit command wait for 10 seconds and break out of the - * mainloop */ - if (isquit) { - printf("shutting down...\n"); - sleep(10); /* let dgram reach it's destination */ - break; - } - } - /** close session and delete keyfile */ - sam3CloseSession(&ses); - unlink(KEYFILE); - return 0; -error: - /** error case, close session, delete keyfile and return exit code 1 */ - sam3CloseSession(&ses); - unlink(KEYFILE); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/namelookup.c b/supportlibs/libsam3/examples/sam3/namelookup.c deleted file mode 100644 index 772e4aceb..000000000 --- a/supportlibs/libsam3/examples/sam3/namelookup.c +++ /dev/null @@ -1,43 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -int main(int argc, char *argv[]) { - Sam3Session ses; - // - // - libsam3_debug = 1; - // - if (argc < 2) { - printf("usage: %s name [name...]\n", argv[0]); - return 1; - } - /** for each name in arguments ... */ - for (int n = 1; n < argc; ++n) { - if (!getenv("I2P_LOOKUP_QUIET")) { - fprintf(stdout, "%s ... ", argv[n]); - fflush(stdout); - } - /** do oneshot name lookup */ - if (sam3NameLookup(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, argv[n]) >= - 0) { - fprintf(stdout, "%s\n\n", ses.destkey); - } else { - fprintf(stdout, "FAILED [%s]\n", ses.error); - } - } - // - return 0; -} diff --git a/supportlibs/libsam3/examples/sam3/samtest.c b/supportlibs/libsam3/examples/sam3/samtest.c deleted file mode 100644 index b2d0b9983..000000000 --- a/supportlibs/libsam3/examples/sam3/samtest.c +++ /dev/null @@ -1,51 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -int main(int argc, char *argv[]) { - int fd; - SAMFieldList *rep = NULL; - const char *v; - // - libsam3_debug = 1; - // - // - if ((fd = sam3Handshake(NULL, 0, NULL)) < 0) - return 1; - // - if (sam3tcpPrintf(fd, "DEST GENERATE\n") < 0) - goto error; - rep = sam3ReadReply(fd); - // sam3DumpFieldList(rep); - if (!sam3IsGoodReply(rep, "DEST", "REPLY", "PUB", NULL)) - goto error; - if (!sam3IsGoodReply(rep, "DEST", "REPLY", "PRIV", NULL)) - goto error; - v = sam3FindField(rep, "PUB"); - printf("PUB KEY\n=======\n%s\n", v); - v = sam3FindField(rep, "PRIV"); - printf("PRIV KEY\n========\n%s\n", v); - sam3FreeFieldList(rep); - rep = NULL; - // - sam3FreeFieldList(rep); - sam3tcpDisconnect(fd); - return 0; -error: - sam3FreeFieldList(rep); - sam3tcpDisconnect(fd); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/streamc.c b/supportlibs/libsam3/examples/sam3/streamc.c deleted file mode 100644 index 672831c3a..000000000 --- a/supportlibs/libsam3/examples/sam3/streamc.c +++ /dev/null @@ -1,87 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -#define KEYFILE "streams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - Sam3Connection *conn; - char cmd[1024], destkey[617]; // 616 chars + \0 - // - libsam3_debug = 1; - // - memset(destkey, 0, sizeof(destkey)); - // - if (argc < 2) { - FILE *fl = fopen(KEYFILE, "rb"); - // - if (fl != NULL) { - if (fread(destkey, 616, 1, fl) == 1) { - fclose(fl); - goto ok; - } - fclose(fl); - } - printf("usage: streamc PUBKEY\n"); - return 1; - } else { - if (!sam3CheckValidKeyLength(argv[1])) { - fprintf(stderr, "FATAL: invalid key length! %s %lu\n", argv[1], - strlen(argv[1])); - return 1; - } - strcpy(destkey, argv[1]); - } - // -ok: - printf("creating session...\n"); - // create TRANSIENT session - if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, - SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, 4, - NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - // - printf("connecting...\n"); - if ((conn = sam3StreamConnect(&ses, destkey)) == NULL) { - fprintf(stderr, "FATAL: can't connect: %s\n", ses.error); - sam3CloseSession(&ses); - return 1; - } - // - // now waiting for incoming connection - printf("sending test command...\n"); - if (sam3tcpPrintf(conn->fd, "test\n") < 0) - goto error; - if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0) - goto error; - printf("echo: %s\n", cmd); - // - printf("sending quit command...\n"); - if (sam3tcpPrintf(conn->fd, "quit\n") < 0) - goto error; - // - sam3CloseConnection(conn); - sam3CloseSession(&ses); - return 0; -error: - fprintf(stderr, "FATAL: some error occured!\n"); - sam3CloseConnection(conn); - sam3CloseSession(&ses); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/streamcs.c b/supportlibs/libsam3/examples/sam3/streamcs.c deleted file mode 100644 index 25bd22072..000000000 --- a/supportlibs/libsam3/examples/sam3/streamcs.c +++ /dev/null @@ -1,87 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -#define KEYFILE "streams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - Sam3Connection *conn; - char cmd[1024], destkey[617]; // 616 chars + \0 - // - libsam3_debug = 1; - // - memset(destkey, 0, sizeof(destkey)); - // - if (argc < 2) { - FILE *fl = fopen(KEYFILE, "rb"); - // - if (fl != NULL) { - if (fread(destkey, 616, 1, fl) == 1) { - fclose(fl); - goto ok; - } - fclose(fl); - } - printf("usage: streamc PUBKEY\n"); - return 1; - } else { - if (!sam3CheckValidKeyLength(argv[1])) { - fprintf(stderr, "FATAL: invalid key length! %s %lu\n", argv[1], - strlen(argv[1])); - return 1; - } - strcpy(destkey, argv[1]); - } - // -ok: - printf("creating session...\n"); - // create TRANSIENT session - if (sam3CreateSilentSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, - SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, - 4, NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - // - printf("connecting...\n"); - if ((conn = sam3StreamConnect(&ses, destkey)) == NULL) { - fprintf(stderr, "FATAL: can't connect: %s\n", ses.error); - sam3CloseSession(&ses); - return 1; - } - // - // now waiting for incoming connection - printf("sending test command...\n"); - if (sam3tcpPrintf(conn->fd, "test\n") < 0) - goto error; - if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0) - goto error; - printf("echo: %s\n", cmd); - // - printf("sending quit command...\n"); - if (sam3tcpPrintf(conn->fd, "quit\n") < 0) - goto error; - // - sam3CloseConnection(conn); - sam3CloseSession(&ses); - return 0; -error: - fprintf(stderr, "FATAL: some error occured!\n"); - sam3CloseConnection(conn); - sam3CloseSession(&ses); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/streams.c b/supportlibs/libsam3/examples/sam3/streams.c deleted file mode 100644 index 2fa000c1c..000000000 --- a/supportlibs/libsam3/examples/sam3/streams.c +++ /dev/null @@ -1,72 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -#define KEYFILE "streams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - Sam3Connection *conn; - FILE *fl; - // - libsam3_debug = 1; - // - printf("creating session...\n"); - // create TRANSIENT session - if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, - SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, 4, - NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - // - printf("PUB KEY\n=======\n%s\n=======\n", ses.pubkey); - if ((fl = fopen(KEYFILE, "wb")) != NULL) { - fwrite(ses.pubkey, strlen(ses.pubkey), 1, fl); - fclose(fl); - } - // - printf("starting stream acceptor...\n"); - if ((conn = sam3StreamAccept(&ses)) == NULL) { - fprintf(stderr, "FATAL: can't accept: %s\n", ses.error); - sam3CloseSession(&ses); - return 1; - } - printf("FROM\n====\n%s\n====\n", conn->destkey); - // - printf("starting main loop...\n"); - for (;;) { - char cmd[256]; - // - if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0) - goto error; - printf("cmd: [%s]\n", cmd); - if (strcmp(cmd, "quit") == 0) - break; - // echo command - if (sam3tcpPrintf(conn->fd, "re: %s\n", cmd) < 0) - goto error; - } - // - sam3CloseSession(&ses); - unlink(KEYFILE); - return 0; -error: - fprintf(stderr, "FATAL: some error occured!\n"); - sam3CloseSession(&ses); - unlink(KEYFILE); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3/streamss.c b/supportlibs/libsam3/examples/sam3/streamss.c deleted file mode 100644 index ffbc974da..000000000 --- a/supportlibs/libsam3/examples/sam3/streamss.c +++ /dev/null @@ -1,72 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include "../libsam3/libsam3.h" - -#define KEYFILE "streams.key" - -int main(int argc, char *argv[]) { - Sam3Session ses; - Sam3Connection *conn; - FILE *fl; - // - libsam3_debug = 1; - // - printf("creating session...\n"); - // create TRANSIENT session - if (sam3CreateSilentSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, - SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, - 4, NULL) < 0) { - fprintf(stderr, "FATAL: can't create session\n"); - return 1; - } - // - printf("PUB KEY\n=======\n%s\n=======\n", ses.pubkey); - if ((fl = fopen(KEYFILE, "wb")) != NULL) { - fwrite(ses.pubkey, strlen(ses.pubkey), 1, fl); - fclose(fl); - } - // - printf("starting stream acceptor...\n"); - if ((conn = sam3StreamAccept(&ses)) == NULL) { - fprintf(stderr, "FATAL: can't accept: %s\n", ses.error); - sam3CloseSession(&ses); - return 1; - } - printf("FROM\n====\n%s\n====\n", conn->destkey); - // - printf("starting main loop...\n"); - for (;;) { - char cmd[256]; - // - if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0) - goto error; - printf("cmd: [%s]\n", cmd); - if (strcmp(cmd, "quit") == 0) - break; - // echo command - if (sam3tcpPrintf(conn->fd, "re: %s\n", cmd) < 0) - goto error; - } - // - sam3CloseSession(&ses); - unlink(KEYFILE); - return 0; -error: - fprintf(stderr, "FATAL: some error occured!\n"); - sam3CloseSession(&ses); - unlink(KEYFILE); - return 1; -} diff --git a/supportlibs/libsam3/examples/sam3a/test00.c b/supportlibs/libsam3/examples/sam3a/test00.c deleted file mode 100644 index 5596053e9..000000000 --- a/supportlibs/libsam3/examples/sam3a/test00.c +++ /dev/null @@ -1,178 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../libsam3a/libsam3a.h" - -//////////////////////////////////////////////////////////////////////////////// -static void scbErrorClose(Sam3ASession *ses) { - fprintf(stderr, - "\n===============================\nSESION_ERROR: " - "[%s]\n===============================\n", - ses->error); - sam3aCloseSession(ses); // it's safe here -} - -static void scbNRCreated(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nNAME RESOLVED: [%s]\n", - ses->params); - fprintf(stderr, "PUB: %s\n===============================\n", ses->destkey); - sam3aCloseSession(ses); // it's safe here -} - -static const Sam3ASessionCallbacks scbNR = { - .cbError = scbErrorClose, - .cbCreated = scbNRCreated, - .cbDisconnected = NULL, - .cbDatagramRead = NULL, - .cbDestroy = NULL, -}; - -//////////////////////////////////////////////////////////////////////////////// -static void scbKGCreated(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nKEYS GENERATED\n"); - fprintf(stderr, "\rPRIV: %s\n", ses->privkey); - fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey); - sam3aCloseSession(ses); // it's safe here -} - -static const Sam3ASessionCallbacks scbKG = { - .cbError = scbErrorClose, - .cbCreated = scbKGCreated, - .cbDisconnected = NULL, - .cbDatagramRead = NULL, - .cbDestroy = NULL, -}; - -//////////////////////////////////////////////////////////////////////////////// -static void scbError(Sam3ASession *ses) { - fprintf(stderr, - "\n===============================\nSESION_ERROR: " - "[%s]\n===============================\n", - ses->error); -} - -static void scbCreated(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_CREATED\n"); - fprintf(stderr, "\rPRIV: %s\n", ses->privkey); - fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey); - sam3aCancelSession(ses); // it's safe here -} - -static void scbDisconnected(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n====" - "===========================\n"); -} - -static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) { - fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n===" - "============================\n"); -} - -static void scbDestroy(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DESTROYED\n=======" - "========================\n"); -} - -/** callbacks for our SAM session */ -static const Sam3ASessionCallbacks scb = { - .cbError = scbError, - .cbCreated = scbCreated, - .cbDisconnected = scbDisconnected, - .cbDatagramRead = scbDGramRead, - .cbDestroy = scbDestroy, -}; - -//////////////////////////////////////////////////////////////////////////////// -#define HOST SAM3A_HOST_DEFAULT -//#define HOST "google.com" - -int main(int argc, char *argv[]) { - Sam3ASession ses, snr, skg; - // - // libsam3a_debug = 1; - // - if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT, - SAM3A_DESTINATION_TRANSIENT, - SAM3A_SESSION_STREAM) < 0) { - fprintf(stderr, "FATAL: can't create main session!\n"); - return 1; - } - // generate keys - if (sam3aGenerateKeys(&skg, &scbKG, HOST, SAM3A_PORT_DEFAULT) < 0) { - sam3aCloseSession(&ses); - fprintf(stderr, "FATAL: can't create keygen session!\n"); - return 1; - } - // do a name lookup for zzz.i2p - if (sam3aNameLookup(&snr, &scbNR, HOST, SAM3A_PORT_DEFAULT, "zzz.i2p") < 0) { - sam3aCloseSession(&skg); - sam3aCloseSession(&ses); - fprintf(stderr, "FATAL: can't create name resolving session!\n"); - return 1; - } - // while we have sessions ... - while (sam3aIsActiveSession(&ses) || sam3aIsActiveSession(&snr) || - sam3aIsActiveSession(&skg)) { - fd_set rds, wrs; - int res, maxfd = 0; - struct timeval to; - // set up file descriptors for select() - FD_ZERO(&rds); - FD_ZERO(&wrs); - // obtain the maximum fd for select() - if (sam3aIsActiveSession(&ses) && - (maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0) - break; - if (sam3aIsActiveSession(&snr) && - (maxfd = sam3aAddSessionToFDS(&snr, -1, &rds, &wrs)) < 0) - break; - if (sam3aIsActiveSession(&skg) && - (maxfd = sam3aAddSessionToFDS(&skg, -1, &rds, &wrs)) < 0) - break; - // set timeout to 1 second - sam3ams2timeval(&to, 1000); - // call select() - res = select(maxfd + 1, &rds, &wrs, NULL, &to); - if (res < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, "FATAL: select() error!\n"); - break; - } - if (res == 0) { - // idle, no activity - fprintf(stdout, "."); - fflush(stdout); - } else { - // we have activity, process io - if (sam3aIsActiveSession(&ses)) - sam3aProcessSessionIO(&ses, &rds, &wrs); - if (sam3aIsActiveSession(&snr)) - sam3aProcessSessionIO(&snr, &rds, &wrs); - if (sam3aIsActiveSession(&skg)) - sam3aProcessSessionIO(&skg, &rds, &wrs); - } - } - // close seessions - sam3aCloseSession(&ses); - sam3aCloseSession(&skg); - sam3aCloseSession(&snr); - // exit - return 0; -} diff --git a/supportlibs/libsam3/examples/sam3a/test_sc.c b/supportlibs/libsam3/examples/sam3a/test_sc.c deleted file mode 100644 index 8feeb5d52..000000000 --- a/supportlibs/libsam3/examples/sam3a/test_sc.c +++ /dev/null @@ -1,205 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../libsam3a/libsam3a.h" - -//////////////////////////////////////////////////////////////////////////////// -#define KEYFILE "streams.key" - -//////////////////////////////////////////////////////////////////////////////// -static void ccbError(Sam3AConnection *ct) { - fprintf(stderr, - "\n===============================\nCONNECTION_ERROR: " - "[%s]\n===============================\n", - ct->error); -} - -static void ccbDisconnected(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_" - "DISCONNECTED\n===============================\n"); -} - -static void ccbConnected(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_CONNECTED\n===" - "============================\n"); - // sam3aCancelConnection(ct); // cbSent() will not be called -} - -static void ccbAccepted(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_ACCEPTED\n====" - "===========================\n"); -} - -static void ccbSent(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n===" - "============================\n"); - // sam3aCancelConnection(ct); - // sam3aCancelSession(ct->ses); // hehe - fprintf(stderr, "(%p)\n", ct->udata); - // - switch ((intptr_t)ct->udata) { - case 0: - if (sam3aSend(ct, "test\n", -1) < 0) { - fprintf(stderr, "SEND ERROR!\n"); - sam3aCancelSession(ct->ses); // hehe - } - break; - case 1: - if (sam3aSend(ct, "quit\n", -1) < 0) { - fprintf(stderr, "SEND ERROR!\n"); - sam3aCancelSession(ct->ses); // hehe - } - break; - default: - return; - } - ct->udata = (void *)(((intptr_t)ct->udata) + 1); -} - -static void ccbRead(Sam3AConnection *ct, const void *buf, int bufsize) { - fprintf(stderr, - "\n===============================\nCONNECTION_GOTBYTES " - "(%d)\n===============================\n", - bufsize); -} - -static void ccbDestroy(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_DESTROY\n=====" - "==========================\n"); -} - -static const Sam3AConnectionCallbacks ccb = { - .cbError = ccbError, - .cbDisconnected = ccbDisconnected, - .cbConnected = ccbConnected, - .cbAccepted = ccbAccepted, - .cbSent = ccbSent, - .cbRead = ccbRead, - .cbDestroy = ccbDestroy, -}; - -//////////////////////////////////////////////////////////////////////////////// -static void scbError(Sam3ASession *ses) { - fprintf(stderr, - "\n===============================\nSESION_ERROR: " - "[%s]\n===============================\n", - ses->error); -} - -static void scbCreated(Sam3ASession *ses) { - char destkey[517]; - FILE *fl; - // - fprintf(stderr, "\n===============================\nSESION_CREATED\n"); - fprintf(stderr, "\rPRIV: %s\n", ses->privkey); - fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey); - // - fl = fopen(KEYFILE, "rb"); - // - if (fl == NULL) { - fprintf(stderr, "ERROR: NO KEY FILE!\n"); - sam3aCancelSession(ses); - return; - } - if (fread(destkey, 516, 1, fl) != 1) { - fprintf(stderr, "ERROR: INVALID KEY FILE!\n"); - fclose(fl); - sam3aCancelSession(ses); - return; - } - fclose(fl); - destkey[516] = 0; - if (sam3aStreamConnect(ses, &ccb, destkey) == NULL) { - fprintf(stderr, "ERROR: CAN'T CREATE CONNECTION!\n"); - sam3aCancelSession(ses); - return; - } - fprintf(stderr, "GOON: creating connection...\n"); -} - -static void scbDisconnected(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n====" - "===========================\n"); -} - -static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) { - fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n===" - "============================\n"); -} - -static void scbDestroy(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DESTROYED\n=======" - "========================\n"); -} - -static const Sam3ASessionCallbacks scb = { - .cbError = scbError, - .cbCreated = scbCreated, - .cbDisconnected = scbDisconnected, - .cbDatagramRead = scbDGramRead, - .cbDestroy = scbDestroy, -}; - -//////////////////////////////////////////////////////////////////////////////// -#define HOST SAM3A_HOST_DEFAULT -//#define HOST "google.com" - -int main(int argc, char *argv[]) { - Sam3ASession ses; - // - libsam3a_debug = 0; - // - if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT, - SAM3A_DESTINATION_TRANSIENT, - SAM3A_SESSION_STREAM) < 0) { - fprintf(stderr, "FATAL: can't create main session!\n"); - return 1; - } - // - while (sam3aIsActiveSession(&ses)) { - fd_set rds, wrs; - int res, maxfd = 0; - struct timeval to; - // - FD_ZERO(&rds); - FD_ZERO(&wrs); - if (sam3aIsActiveSession(&ses) && - (maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0) - break; - sam3ams2timeval(&to, 1000); - res = select(maxfd + 1, &rds, &wrs, NULL, &to); - if (res < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, "FATAL: select() error!\n"); - break; - } - if (res == 0) { - fprintf(stdout, "."); - fflush(stdout); - } else { - if (sam3aIsActiveSession(&ses)) - sam3aProcessSessionIO(&ses, &rds, &wrs); - } - } - // - sam3aCloseSession(&ses); - // - return 0; -} diff --git a/supportlibs/libsam3/examples/sam3a/test_ss.c b/supportlibs/libsam3/examples/sam3a/test_ss.c deleted file mode 100644 index c2ff3399c..000000000 --- a/supportlibs/libsam3/examples/sam3a/test_ss.c +++ /dev/null @@ -1,236 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../libsam3a/libsam3a.h" - -//////////////////////////////////////////////////////////////////////////////// -#define KEYFILE "streams.key" - -//////////////////////////////////////////////////////////////////////////////// -typedef struct { - char *str; - int strsize; - int strused; - int doQuit; -} ConnData; - -static void cdAppendChar(ConnData *d, char ch) { - if (d->strused + 1 >= d->strsize) { - // fuck errors - d->strsize = d->strused + 1024; - d->str = realloc(d->str, d->strsize + 1); - } - d->str[d->strused++] = ch; - d->str[d->strused] = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -static void ccbError(Sam3AConnection *ct) { - fprintf(stderr, - "\n===============================\nCONNECTION_ERROR: " - "[%s]\n===============================\n", - ct->error); -} - -static void ccbDisconnected(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_" - "DISCONNECTED\n===============================\n"); -} - -static void ccbConnected(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_CONNECTED\n===" - "============================\n"); - // sam3aCancelConnection(ct); // cbSent() will not be called -} - -static void ccbAccepted(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_ACCEPTED\n====" - "===========================\n"); - fprintf(stderr, "FROM: %s\n===============================\n", ct->destkey); -} - -static void ccbSent(Sam3AConnection *ct) { - ConnData *d = (ConnData *)ct->udata; - // - fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n===" - "============================\n"); - if (d->doQuit) { - sam3aCancelSession(ct->ses); // hehe - } -} - -static void ccbRead(Sam3AConnection *ct, const void *buf, int bufsize) { - const char *b = (const char *)buf; - ConnData *d = (ConnData *)ct->udata; - // - fprintf(stderr, - "\n===============================\nCONNECTION_GOTBYTES " - "(%d)\n===============================\n", - bufsize); - while (bufsize > 0) { - cdAppendChar(ct->udata, *b); - if (*b == '\n') { - fprintf(stderr, "cmd: %s", d->str); - if (strcasecmp(d->str, "quit\n") == 0) - d->doQuit = 1; - if (sam3aSend(ct, d->str, -1) < 0) { - // sam3aCancelConnection(ct); // hehe - sam3aCancelSession(ct->ses); // hehe - return; - } - d->str[0] = 0; - d->strused = 0; - } - ++b; - --bufsize; - } -} - -static void ccbDestroy(Sam3AConnection *ct) { - fprintf(stderr, "\n===============================\nCONNECTION_DESTROY\n=====" - "==========================\n"); - if (ct->udata != NULL) { - ConnData *d = (ConnData *)ct->udata; - // - if (d->str != NULL) - free(d->str); - free(d); - } -} - -static const Sam3AConnectionCallbacks ccb = { - .cbError = ccbError, - .cbDisconnected = ccbDisconnected, - .cbConnected = ccbConnected, - .cbAccepted = ccbAccepted, - .cbSent = ccbSent, - .cbRead = ccbRead, - .cbDestroy = ccbDestroy, -}; - -//////////////////////////////////////////////////////////////////////////////// -static void scbError(Sam3ASession *ses) { - fprintf(stderr, - "\n===============================\nSESION_ERROR: " - "[%s]\n===============================\n", - ses->error); -} - -static void scbCreated(Sam3ASession *ses) { - FILE *fl; - Sam3AConnection *conn; - // - fprintf(stderr, "\n===============================\nSESION_CREATED\n"); - fprintf(stderr, "\rPRIV: %s\n", ses->privkey); - fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey); - // - fl = fopen(KEYFILE, "wb"); - // - if (fl == NULL) { - fprintf(stderr, "ERROR: CAN'T CREATE KEY FILE!\n"); - sam3aCancelSession(ses); - return; - } - if (fwrite(ses->pubkey, 516, 1, fl) != 1) { - fprintf(stderr, "ERROR: CAN'T WRITE KEY FILE!\n"); - fclose(fl); - sam3aCancelSession(ses); - return; - } - fclose(fl); - if ((conn = sam3aStreamAccept(ses, &ccb)) == NULL) { - fprintf(stderr, "ERROR: CAN'T CREATE CONNECTION!\n"); - sam3aCancelSession(ses); - return; - } - // - conn->udata = calloc(1, sizeof(ConnData)); - fprintf(stderr, "GOON: accepting connection...\n"); -} - -static void scbDisconnected(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n====" - "===========================\n"); -} - -static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) { - fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n===" - "============================\n"); -} - -static void scbDestroy(Sam3ASession *ses) { - fprintf(stderr, "\n===============================\nSESION_DESTROYED\n=======" - "========================\n"); -} - -static const Sam3ASessionCallbacks scb = { - .cbError = scbError, - .cbCreated = scbCreated, - .cbDisconnected = scbDisconnected, - .cbDatagramRead = scbDGramRead, - .cbDestroy = scbDestroy, -}; - -//////////////////////////////////////////////////////////////////////////////// -#define HOST SAM3A_HOST_DEFAULT -//#define HOST "google.com" - -int main(int argc, char *argv[]) { - Sam3ASession ses; - // - libsam3a_debug = 0; - // - if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT, - SAM3A_DESTINATION_TRANSIENT, - SAM3A_SESSION_STREAM) < 0) { - fprintf(stderr, "FATAL: can't create main session!\n"); - return 1; - } - // - while (sam3aIsActiveSession(&ses)) { - fd_set rds, wrs; - int res, maxfd = 0; - struct timeval to; - // - FD_ZERO(&rds); - FD_ZERO(&wrs); - if (sam3aIsActiveSession(&ses) && - (maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0) - break; - sam3ams2timeval(&to, 1000); - res = select(maxfd + 1, &rds, &wrs, NULL, &to); - if (res < 0) { - if (errno == EINTR) - continue; - fprintf(stderr, "FATAL: select() error!\n"); - break; - } - if (res == 0) { - fprintf(stdout, "."); - fflush(stdout); - } else { - if (sam3aIsActiveSession(&ses)) - sam3aProcessSessionIO(&ses, &rds, &wrs); - } - } - // - sam3aCloseSession(&ses); - // - return 0; -} diff --git a/supportlibs/libsam3/src/ext/tinytest.c b/supportlibs/libsam3/src/ext/tinytest.c deleted file mode 100644 index 252f03051..000000000 --- a/supportlibs/libsam3/src/ext/tinytest.c +++ /dev/null @@ -1,466 +0,0 @@ -/* tinytest.c -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef TINYTEST_LOCAL -#include "tinytest_local.h" -#endif - -#include -#include -#include -#include - -#ifndef NO_FORKING - -#ifdef _WIN32 -#include -#else -#include -#include -#include -#endif - -#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) -/* Workaround for a stupid bug in OSX 10.6 */ -#define FORK_BREAKS_GCOV -#include -#endif -#endif - -#endif /* !NO_FORKING */ - -#ifndef __GNUC__ -#define __attribute__(x) -#endif - -#include "tinytest.h" -#include "tinytest_macros.h" - -#define LONGEST_TEST_NAME 16384 - -static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ -static int n_ok = 0; /**< Number of tests that have passed */ -static int n_bad = 0; /**< Number of tests that have failed. */ -static int n_skipped = 0; /**< Number of tests that have been skipped. */ - -static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ -static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ -static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ -const char *verbosity_flag = ""; - -const struct testlist_alias_t *cfg_aliases = NULL; - -enum outcome { SKIP = 2, OK = 1, FAIL = 0 }; -static enum outcome cur_test_outcome = FAIL; -const char *cur_test_prefix = NULL; /**< prefix of the current test group */ -/** Name of the current test, if we haven't logged is yet. Used for --quiet */ -const char *cur_test_name = NULL; - -#ifdef _WIN32 -/* Copy of argv[0] for win32. */ -static char commandname[MAX_PATH + 1]; -#endif - -static void usage(struct testgroup_t *groups, int list_groups) - __attribute__((noreturn)); -static int process_test_option(struct testgroup_t *groups, const char *test); - -static enum outcome testcase_run_bare_(const struct testcase_t *testcase) { - void *env = NULL; - enum outcome outcome; - if (testcase->setup) { - env = testcase->setup->setup_fn(testcase); - if (!env) - return FAIL; - else if (env == (void *)TT_SKIP) - return SKIP; - } - - cur_test_outcome = OK; - testcase->fn(env); - outcome = cur_test_outcome; - - if (testcase->setup) { - if (testcase->setup->cleanup_fn(testcase, env) == 0) - outcome = FAIL; - } - - return outcome; -} - -#define MAGIC_EXITCODE 42 - -#ifndef NO_FORKING - -static enum outcome testcase_run_forked_(const struct testgroup_t *group, - const struct testcase_t *testcase) { -#ifdef _WIN32 - /* Fork? On Win32? How primitive! We'll do what the smart kids do: - we'll invoke our own exe (whose name we recall from the command - line) with a command line that tells it to run just the test we - want, and this time without forking. - - (No, threads aren't an option. The whole point of forking is to - share no state between tests.) - */ - int ok; - char buffer[LONGEST_TEST_NAME + 256]; - STARTUPINFOA si; - PROCESS_INFORMATION info; - DWORD exitcode; - - if (!in_tinytest_main) { - printf("\nERROR. On Windows, testcase_run_forked_ must be" - " called from within tinytest_main.\n"); - abort(); - } - if (opt_verbosity > 0) - printf("[forking] "); - - snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", commandname, - verbosity_flag, group->prefix, testcase->name); - - memset(&si, 0, sizeof(si)); - memset(&info, 0, sizeof(info)); - si.cb = sizeof(si); - - ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, 0, NULL, NULL, &si, - &info); - if (!ok) { - printf("CreateProcess failed!\n"); - return 0; - } - WaitForSingleObject(info.hProcess, INFINITE); - GetExitCodeProcess(info.hProcess, &exitcode); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); - if (exitcode == 0) - return OK; - else if (exitcode == MAGIC_EXITCODE) - return SKIP; - else - return FAIL; -#else - int outcome_pipe[2]; - pid_t pid; - (void)group; - - if (pipe(outcome_pipe)) - perror("opening pipe"); - - if (opt_verbosity > 0) - printf("[forking] "); - pid = fork(); -#ifdef FORK_BREAKS_GCOV - vproc_transaction_begin(0); -#endif - if (!pid) { - /* child. */ - int test_r, write_r; - char b[1]; - close(outcome_pipe[0]); - test_r = testcase_run_bare_(testcase); - assert(0 <= (int)test_r && (int)test_r <= 2); - b[0] = "NYS"[test_r]; - write_r = (int)write(outcome_pipe[1], b, 1); - if (write_r != 1) { - perror("write outcome to pipe"); - exit(1); - } - exit(0); - return FAIL; /* unreachable */ - } else { - /* parent */ - int status, r; - char b[1]; - /* Close this now, so that if the other side closes it, - * our read fails. */ - close(outcome_pipe[1]); - r = (int)read(outcome_pipe[0], b, 1); - if (r == 0) { - printf("[Lost connection!] "); - return FAIL; - } else if (r != 1) { - perror("read outcome from pipe"); - } - waitpid(pid, &status, 0); - close(outcome_pipe[0]); - return b[0] == 'Y' ? OK : (b[0] == 'S' ? SKIP : FAIL); - } -#endif -} - -#endif /* !NO_FORKING */ - -int testcase_run_one(const struct testgroup_t *group, - const struct testcase_t *testcase) { - enum outcome outcome; - - if (testcase->flags & (TT_SKIP | TT_OFF_BY_DEFAULT)) { - if (opt_verbosity > 0) - printf("%s%s: %s\n", group->prefix, testcase->name, - (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); - ++n_skipped; - return SKIP; - } - - if (opt_verbosity > 0 && !opt_forked) { - printf("%s%s: ", group->prefix, testcase->name); - } else { - if (opt_verbosity == 0) - printf("."); - cur_test_prefix = group->prefix; - cur_test_name = testcase->name; - } - -#ifndef NO_FORKING - if ((testcase->flags & TT_FORK) && !(opt_forked || opt_nofork)) { - outcome = testcase_run_forked_(group, testcase); - } else { -#else - { -#endif - outcome = testcase_run_bare_(testcase); - } - - if (outcome == OK) { - ++n_ok; - if (opt_verbosity > 0 && !opt_forked) - puts(opt_verbosity == 1 ? "OK" : ""); - } else if (outcome == SKIP) { - ++n_skipped; - if (opt_verbosity > 0 && !opt_forked) - puts("SKIPPED"); - } else { - ++n_bad; - if (!opt_forked) - printf("\n [%s FAILED]\n", testcase->name); - } - - if (opt_forked) { - exit(outcome == OK ? 0 : (outcome == SKIP ? MAGIC_EXITCODE : 1)); - return 1; /* unreachable */ - } else { - return (int)outcome; - } -} - -int tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, - unsigned long flag) { - int i, j; - size_t length = LONGEST_TEST_NAME; - char fullname[LONGEST_TEST_NAME]; - int found = 0; - if (strstr(arg, "..")) - length = strstr(arg, "..") - arg; - for (i = 0; groups[i].prefix; ++i) { - for (j = 0; groups[i].cases[j].name; ++j) { - struct testcase_t *testcase = &groups[i].cases[j]; - snprintf(fullname, sizeof(fullname), "%s%s", groups[i].prefix, - testcase->name); - if (!flag) { /* Hack! */ - printf(" %s", fullname); - if (testcase->flags & TT_OFF_BY_DEFAULT) - puts(" (Off by default)"); - else if (testcase->flags & TT_SKIP) - puts(" (DISABLED)"); - else - puts(""); - } - if (!strncmp(fullname, arg, length)) { - if (set) - testcase->flags |= flag; - else - testcase->flags &= ~flag; - ++found; - } - } - } - return found; -} - -static void usage(struct testgroup_t *groups, int list_groups) { - puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); - puts(" Specify tests by name, or using a prefix ending with '..'"); - puts(" To skip a test, prefix its name with a colon."); - puts(" To enable a disabled test, prefix its name with a plus."); - puts(" Use --list-tests for a list of tests."); - if (list_groups) { - puts("Known tests are:"); - tinytest_set_flag_(groups, "..", 1, 0); - } - exit(0); -} - -static int process_test_alias(struct testgroup_t *groups, const char *test) { - int i, j, n, r; - for (i = 0; cfg_aliases && cfg_aliases[i].name; ++i) { - if (!strcmp(cfg_aliases[i].name, test)) { - n = 0; - for (j = 0; cfg_aliases[i].tests[j]; ++j) { - r = process_test_option(groups, cfg_aliases[i].tests[j]); - if (r < 0) - return -1; - n += r; - } - return n; - } - } - printf("No such test alias as @%s!", test); - return -1; -} - -static int process_test_option(struct testgroup_t *groups, const char *test) { - int flag = TT_ENABLED_; - int n = 0; - if (test[0] == '@') { - return process_test_alias(groups, test + 1); - } else if (test[0] == ':') { - ++test; - flag = TT_SKIP; - } else if (test[0] == '+') { - ++test; - ++n; - if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { - printf("No such test as %s!\n", test); - return -1; - } - } else { - ++n; - } - if (!tinytest_set_flag_(groups, test, 1, flag)) { - printf("No such test as %s!\n", test); - return -1; - } - return n; -} - -void tinytest_set_aliases(const struct testlist_alias_t *aliases) { - cfg_aliases = aliases; -} - -int tinytest_main(int c, const char **v, struct testgroup_t *groups) { - int i, j, n = 0; - -#ifdef _WIN32 - const char *sp = strrchr(v[0], '.'); - const char *extension = ""; - if (!sp || stricmp(sp, ".exe")) - extension = ".exe"; /* Add an exe so CreateProcess will work */ - snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); - commandname[MAX_PATH] = '\0'; -#endif - for (i = 1; i < c; ++i) { - if (v[i][0] == '-') { - if (!strcmp(v[i], "--RUNNING-FORKED")) { - opt_forked = 1; - } else if (!strcmp(v[i], "--no-fork")) { - opt_nofork = 1; - } else if (!strcmp(v[i], "--quiet")) { - opt_verbosity = -1; - verbosity_flag = "--quiet"; - } else if (!strcmp(v[i], "--verbose")) { - opt_verbosity = 2; - verbosity_flag = "--verbose"; - } else if (!strcmp(v[i], "--terse")) { - opt_verbosity = 0; - verbosity_flag = "--terse"; - } else if (!strcmp(v[i], "--help")) { - usage(groups, 0); - } else if (!strcmp(v[i], "--list-tests")) { - usage(groups, 1); - } else { - printf("Unknown option %s. Try --help\n", v[i]); - return -1; - } - } else { - int r = process_test_option(groups, v[i]); - if (r < 0) - return -1; - n += r; - } - } - if (!n) - tinytest_set_flag_(groups, "..", 1, TT_ENABLED_); - -#ifdef _IONBF - setvbuf(stdout, NULL, _IONBF, 0); -#endif - - ++in_tinytest_main; - for (i = 0; groups[i].prefix; ++i) - for (j = 0; groups[i].cases[j].name; ++j) - if (groups[i].cases[j].flags & TT_ENABLED_) - testcase_run_one(&groups[i], &groups[i].cases[j]); - - --in_tinytest_main; - - if (opt_verbosity == 0) - puts(""); - - if (n_bad) - printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad, n_bad + n_ok, - n_skipped); - else if (opt_verbosity >= 1) - printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); - - return (n_bad == 0) ? 0 : 1; -} - -int tinytest_get_verbosity_(void) { return opt_verbosity; } - -void tinytest_set_test_failed_(void) { - if (opt_verbosity <= 0 && cur_test_name) { - if (opt_verbosity == 0) - puts(""); - printf("%s%s: ", cur_test_prefix, cur_test_name); - cur_test_name = NULL; - } - cur_test_outcome = FAIL; -} - -void tinytest_set_test_skipped_(void) { - if (cur_test_outcome == OK) - cur_test_outcome = SKIP; -} - -char *tinytest_format_hex_(const void *val_, unsigned long len) { - const unsigned char *val = (unsigned char *)val_; - char *result, *cp; - size_t i; - - if (!val) - return strdup("null"); - if (!(result = (char *)malloc(len * 2 + 1))) - return strdup(""); - cp = result; - for (i = 0; i < len; ++i) { - *cp++ = "0123456789ABCDEF"[val[i] >> 4]; - *cp++ = "0123456789ABCDEF"[val[i] & 0x0f]; - } - *cp = 0; - return result; -} diff --git a/supportlibs/libsam3/src/ext/tinytest.h b/supportlibs/libsam3/src/ext/tinytest.h deleted file mode 100644 index bdddcbb54..000000000 --- a/supportlibs/libsam3/src/ext/tinytest.h +++ /dev/null @@ -1,104 +0,0 @@ -/* tinytest.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_H_INCLUDED_ -#define TINYTEST_H_INCLUDED_ - -/** 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. */ -#define TT_SKIP (1 << 1) -/** Internal runtime flag for a test we've decided to run. */ -#define TT_ENABLED_ (1 << 2) -/** Flag for a test that's off by default. */ -#define TT_OFF_BY_DEFAULT (1 << 3) -/** If you add your own flags, make them start at this point. */ -#define TT_FIRST_USER_FLAG (1 << 4) - -typedef void (*testcase_fn)(void *); - -struct testcase_t; - -/** Functions to initialize/teardown a structure for a testcase. */ -struct testcase_setup_t { - /** Return a new structure for use by a given testcase. */ - void *(*setup_fn)(const struct testcase_t *); - /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ - int (*cleanup_fn)(const struct testcase_t *, void *); -}; - -/** A single test-case that you can run. */ -struct testcase_t { - const char *name; /**< An identifier for this case. */ - testcase_fn fn; /**< The function to run to implement this case. */ - unsigned long flags; /**< Bitfield of TT_* flags. */ - const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ - void *setup_data; /**< Extra data usable by setup function */ -}; -#define END_OF_TESTCASES \ - { NULL, NULL, 0, NULL, NULL } - -/** A group of tests that are selectable together. */ -struct testgroup_t { - const char *prefix; /**< Prefix to prepend to testnames. */ - struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ -}; -#define END_OF_GROUPS \ - { NULL, NULL } - -struct testlist_alias_t { - const char *name; - const char **tests; -}; -#define END_OF_ALIASES \ - { NULL, NULL } - -/** Implementation: called from a test to indicate failure, before logging. */ -void tinytest_set_test_failed_(void); -/** Implementation: called from a test to indicate that we're skipping. */ -void tinytest_set_test_skipped_(void); -/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ -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 *, int set, - unsigned long); -/** Implementation: Put a chunk of memory into hex. */ -char *tinytest_format_hex_(const void *, unsigned long); - -/** Set all tests in 'groups' matching the name 'named' to be skipped. */ -#define tinytest_skip(groups, named) \ - tinytest_set_flag_(groups, named, 1, TT_SKIP) - -/** Run a single testcase in a single group. */ -int testcase_run_one(const struct testgroup_t *, const struct testcase_t *); - -void tinytest_set_aliases(const struct testlist_alias_t *aliases); - -/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, - as selected from the command line. */ -int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); - -#endif diff --git a/supportlibs/libsam3/src/ext/tinytest_macros.h b/supportlibs/libsam3/src/ext/tinytest_macros.h deleted file mode 100644 index 817734020..000000000 --- a/supportlibs/libsam3/src/ext/tinytest_macros.h +++ /dev/null @@ -1,219 +0,0 @@ -/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_MACROS_H_INCLUDED_ -#define TINYTEST_MACROS_H_INCLUDED_ - -/* Helpers for defining statement-like macros */ -#define TT_STMT_BEGIN do { -#define TT_STMT_END \ - } \ - while (0) - -/* Redefine this if your test functions want to abort with something besides - * "goto end;" */ -#ifndef TT_EXIT_TEST_FUNCTION -#define TT_EXIT_TEST_FUNCTION \ - TT_STMT_BEGIN goto end; \ - TT_STMT_END -#endif - -/* Redefine this if you want to note success/failure in some different way. */ -#ifndef TT_DECLARE -#define TT_DECLARE(prefix, args) \ - TT_STMT_BEGIN \ - printf("\n %s %s:%d: ", prefix, __FILE__, __LINE__); \ - printf args; \ - TT_STMT_END -#endif - -/* Announce a failure. Args are parenthesized printf args. */ -#define TT_GRIPE(args) TT_DECLARE("FAIL", args) - -/* Announce a non-failure if we're verbose. */ -#define TT_BLATHER(args) \ - TT_STMT_BEGIN \ - if (tinytest_get_verbosity_() > 1) \ - TT_DECLARE(" OK", args); \ - TT_STMT_END - -#define TT_DIE(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define TT_FAIL(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_STMT_END - -/* Fail and abort the current test for the reason in msg */ -#define tt_abort_printf(msg) TT_DIE(msg) -#define tt_abort_perror(op) \ - TT_DIE(("%s: %s [%d]", (op), strerror(errno), errno)) -#define tt_abort_msg(msg) TT_DIE(("%s", msg)) -#define tt_abort() TT_DIE(("%s", "(Failed.)")) - -/* Fail but do not abort the current test for the reason in msg. */ -#define tt_fail_printf(msg) TT_FAIL(msg) -#define tt_fail_perror(op) \ - TT_FAIL(("%s: %s [%d]", (op), strerror(errno), errno)) -#define tt_fail_msg(msg) TT_FAIL(("%s", msg)) -#define tt_fail() TT_FAIL(("%s", "(Failed.)")) - -/* End the current test, and indicate we are skipping it. */ -#define tt_skip() \ - TT_STMT_BEGIN \ - tinytest_set_test_skipped_(); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define tt_want_(b, msg, fail) \ - TT_STMT_BEGIN \ - if (!(b)) { \ - tinytest_set_test_failed_(); \ - TT_GRIPE(("%s", msg)); \ - fail; \ - } else { \ - TT_BLATHER(("%s", msg)); \ - } \ - TT_STMT_END - -/* Assert b, but do not stop the test if b fails. Log msg on failure. */ -#define tt_want_msg(b, msg) tt_want_(b, msg, ); - -/* Assert b and stop the test if b fails. Log msg on failure. */ -#define tt_assert_msg(b, msg) tt_want_(b, msg, TT_EXIT_TEST_FUNCTION); - -/* Assert b, but do not stop the test if b fails. */ -#define tt_want(b) tt_want_msg((b), "want(" #b ")") -/* Assert b, and stop the test if b fails. */ -#define tt_assert(b) tt_assert_msg((b), "assert(" #b ")") - -#define tt_assert_test_fmt_type(a, b, str_test, type, test, printf_type, \ - printf_fmt, setup_block, cleanup_block, \ - die_on_fail) \ - TT_STMT_BEGIN \ - type val1_ = (a); \ - type val2_ = (b); \ - int tt_status_ = (test); \ - if (!tt_status_ || tinytest_get_verbosity_() > 1) { \ - printf_type print_; \ - printf_type print1_; \ - printf_type print2_; \ - type value_ = val1_; \ - setup_block; \ - print1_ = print_; \ - value_ = val2_; \ - setup_block; \ - print2_ = print_; \ - TT_DECLARE(tt_status_ ? " OK" : "FAIL", \ - ("assert(%s): " printf_fmt " vs " printf_fmt, str_test, \ - print1_, print2_)); \ - print_ = print1_; \ - cleanup_block; \ - print_ = print2_; \ - cleanup_block; \ - if (!tt_status_) { \ - tinytest_set_test_failed_(); \ - die_on_fail; \ - } \ - } \ - TT_STMT_END - -#define tt_assert_test_type(a, b, str_test, type, test, fmt, die_on_fail) \ - tt_assert_test_fmt_type(a, b, str_test, type, test, type, fmt, \ - { print_ = value_; }, {}, die_on_fail) - -#define tt_assert_test_type_opt(a, b, str_test, type, test, fmt, die_on_fail) \ - tt_assert_test_fmt_type(a, b, str_test, type, test, type, fmt, \ - { print_ = value_ ? value_ : ""; }, {}, \ - die_on_fail) - -/* Helper: assert that a op b, when cast to type. Format the values with - * printf format fmt on failure. */ -#define tt_assert_op_type(a, op, b, type, fmt) \ - tt_assert_test_type(a, b, #a " " #op " " #b, type, (val1_ op val2_), fmt, \ - TT_EXIT_TEST_FUNCTION) - -#define tt_int_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, long, (val1_ op val2_), "%ld", \ - TT_EXIT_TEST_FUNCTION) - -#define tt_uint_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, unsigned long, \ - (val1_ op val2_), "%lu", TT_EXIT_TEST_FUNCTION) - -#define tt_ptr_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, const void *, (val1_ op val2_), \ - "%p", TT_EXIT_TEST_FUNCTION) - -#define tt_str_op(a, op, b) \ - tt_assert_test_type_opt(a, b, #a " " #op " " #b, const char *, \ - (val1_ && val2_ && strcmp(val1_, val2_) op 0), \ - "<%s>", TT_EXIT_TEST_FUNCTION) - -#define tt_mem_op(expr1, op, expr2, len) \ - tt_assert_test_fmt_type( \ - expr1, expr2, #expr1 " " #op " " #expr2, const void *, \ - (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), char *, "%s", \ - { print_ = tinytest_format_hex_(value_, (len)); }, \ - { \ - if (print_) \ - free(print_); \ - }, \ - TT_EXIT_TEST_FUNCTION); - -#define tt_want_int_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, long, (val1_ op val2_), "%ld", \ - (void)0) - -#define tt_want_uint_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, unsigned long, \ - (val1_ op val2_), "%lu", (void)0) - -#define tt_want_ptr_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, const void *, (val1_ op val2_), \ - "%p", (void)0) - -#define tt_want_str_op(a, op, b) \ - tt_assert_test_type(a, b, #a " " #op " " #b, const char *, \ - (strcmp(val1_, val2_) op 0), "<%s>", (void)0) - -#define tt_want_mem_op(expr1, op, expr2, len) \ - tt_assert_test_fmt_type( \ - expr1, expr2, #expr1 " " #op " " #expr2, const void *, \ - (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), char *, "%s", \ - { print_ = tinytest_format_hex_(value_, (len)); }, \ - { \ - if (print_) \ - free(print_); \ - }, \ - (void)0); - -#endif diff --git a/supportlibs/libsam3/src/libsam3/libsam3.c b/supportlibs/libsam3/src/libsam3/libsam3.c deleted file mode 100644 index 5a645806f..000000000 --- a/supportlibs/libsam3/src/libsam3/libsam3.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include "libsam3.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __MINGW32__ -//#include -#include -#include -#include -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif -#ifndef SHUT_RDWR -#define SHUT_RDWR 2 -#endif -#endif - -#ifdef __unix__ -#include -#include -#include -#include -#include -#include -#endif -//////////////////////////////////////////////////////////////////////////////// -int libsam3_debug = 0; - -//////////////////////////////////////////////////////////////////////////////// -/* convert struct timeval to milliseconds */ -/* -static inline uint64_t timeval2ms (const struct timeval *tv) { - return ((uint64_t)tv->tv_sec)*1000+((uint64_t)tv->tv_usec)/1000; -} -*/ - -/* convert milliseconds to timeval struct */ -static inline void ms2timeval(struct timeval *tv, uint64_t ms) { - tv->tv_sec = ms / 1000; - tv->tv_usec = (ms % 1000) * 1000; -} - -int sam3tcpSetTimeoutSend(int fd, int timeoutms) { - if (fd >= 0 && timeoutms >= 0) { - struct timeval tv; - // - ms2timeval(&tv, timeoutms); - return (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ? -1 - : 0); - } - return -1; -} - -int sam3tcpSetTimeoutReceive(int fd, int timeoutms) { - if (fd >= 0 && timeoutms >= 0) { - struct timeval tv; - // - ms2timeval(&tv, timeoutms); - return (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ? -1 - : 0); - } - return -1; -} - -int sam3CheckValidKeyLength(const char *pubkey) { - if (strlen(pubkey) >= SAM3_PUBKEY_SIZE && - strlen(pubkey) <= SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE) { - return 1; - } - return 0; -} - -int sam3tcpConnectIP(uint32_t ip, int port) { - struct sockaddr_in addr; - int fd, val = 1; - char ipstr[18]; - // - if (ip == 0 || ip == 0xffffffffUL || port < 1 || port > 65535) - return -1; - // - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - if (libsam3_debug) - fprintf(stderr, "ERROR: can't create socket\n"); - return -1; - } - // - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = ip; - // - ipstr[0] = 0; - if (libsam3_debug) { - if (getnameinfo((struct sockaddr *)&addr, sizeof(struct sockaddr_in), ipstr, - sizeof(ipstr), NULL, 0, NI_NUMERICHOST) == 0) { - fprintf(stderr, "connecting to [%s:%d]...\n", ipstr, port); - } - } - // - setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); - // - if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { - if (libsam3_debug) - fprintf(stderr, "ERROR: can't connect\n"); - close(fd); - return -1; - } - // - if (libsam3_debug && ipstr[0]) - fprintf(stderr, "connected to [%s:%d]\n", ipstr, port); - // - return fd; -} - -/* returns fd or -1 */ -int sam3tcpConnect(const char *hostname, int port, uint32_t *ip) { - struct hostent *host = NULL; - // - if (hostname == NULL || !hostname[0] || port < 1 || port > 65535) - return -1; - // - host = gethostbyname(hostname); - if (host == NULL || host->h_name == NULL || !host->h_name[0]) { - if (libsam3_debug) - fprintf(stderr, "ERROR: can't resolve '%s'\n", hostname); - return -1; - } - // - if (libsam3_debug) { - char ipstr[18]; - // - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr = *((struct in_addr *)host->h_addr); - // - if (getnameinfo((struct sockaddr *)&addr, sizeof(struct sockaddr_in), ipstr, - sizeof(ipstr), NULL, 0, NI_NUMERICHOST) == 0) { - fprintf(stderr, "resolving: %s is [%s]...\n", hostname, ipstr); - } - } - // - if (ip != NULL) - *ip = ((struct in_addr *)host->h_addr)->s_addr; - return sam3tcpConnectIP(((struct in_addr *)host->h_addr)->s_addr, port); -} - -// <0: error; 0: ok -int sam3tcpDisconnect(int fd) { - if (fd >= 0) { - shutdown(fd, SHUT_RDWR); - return close(fd); - } - // - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// <0: error; 0: ok -int sam3tcpSend(int fd, const void *buf, size_t bufSize) { - const char *c = (const char *)buf; - // - if (fd < 0 || (buf == NULL && bufSize > 0)) - return -1; - // - while (bufSize > 0) { - int wr = send(fd, c, bufSize, MSG_NOSIGNAL); - // - if (wr < 0 && errno == EINTR) - continue; // interrupted by signal - if (wr <= 0) - return -1; // either error or - c += wr; - bufSize -= wr; - } - // - return 0; -} - -/* <0: received (-res) bytes; read error */ -/* can return less that requesten bytes even if `allowPartial` is 0 when - * connection is closed */ -ssize_t sam3tcpReceiveEx(int fd, void *buf, size_t bufSize, int allowPartial) { - char *c = (char *)buf; - ssize_t total = 0; - // - if (fd < 0 || (buf == NULL && bufSize > 0)) - return -1; - // - while (bufSize > 0) { - int rd = recv(fd, c, bufSize, 0); - // - if (rd < 0 && errno == EINTR) - continue; // interrupted by signal - if (rd == 0) - return total; - if (rd < 0) - return -total; - c += rd; - total += rd; - bufSize -= rd; - if (allowPartial) - break; - } - // - return total; -} - -ssize_t sam3tcpReceive(int fd, void *buf, size_t bufSize) { - return sam3tcpReceiveEx(fd, buf, bufSize, 0); -} - -//////////////////////////////////////////////////////////////////////////////// -__attribute__((format(printf, 2, 3))) int sam3tcpPrintf(int fd, const char *fmt, - ...) { - int res; - char buf[1024], *p = buf; - int size = sizeof(buf) - 1; - // - for (;;) { - va_list ap; - char *np; - int n; - // - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); - // - if (n > -1 && n < size) - break; - if (n > -1) - size = n + 1; - else - size *= 2; - if (p == buf) { - if ((p = malloc(size + 4)) == NULL) - return -1; - } else { - if ((np = realloc(p, size + 4)) == NULL) { - free(p); - return -1; - } - p = np; - } - } - // - if (libsam3_debug) - fprintf(stderr, "SENDING: %s", p); - res = sam3tcpSend(fd, p, strlen(p)); - if (p != buf) - free(p); - return res; -} - -int sam3tcpReceiveStr(int fd, char *dest, size_t maxSize) { - char *d = dest; - // - if (maxSize < 1 || fd < 0 || dest == NULL) - return -1; - memset(dest, 0, maxSize); - while (maxSize > 1) { - char *e; - int rd = recv(fd, d, maxSize - 1, MSG_PEEK); - // - if (rd < 0 && errno == EINTR) - continue; // interrupted by signal - if (rd == 0) { - rd = recv(fd, d, 1, 0); - if (rd < 0 && errno == EINTR) - continue; // interrupted by signal - if (d[0] == '\n') { - d[0] = 0; // remove '\n' - return 0; - } - } else { - if (rd < 0) - return -1; // error or connection closed; alas - } - // check for EOL - d[maxSize - 1] = 0; - if ((e = strchr(d, '\n')) != NULL) { - rd = e - d + 1; // bytes to receive - if (sam3tcpReceive(fd, d, rd) < 0) - return -1; // alas - d[rd - 1] = 0; // remove '\n' - return 0; // done - } else { - // let's receive this part and go on - if (sam3tcpReceive(fd, d, rd) < 0) - return -1; // alas - maxSize -= rd; - d += rd; - } - } - // alas, the string is too big - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3udpSendToIP(uint32_t ip, int port, const void *buf, size_t bufSize) { - // TODO: ipv6 - struct sockaddr_in addr; - int fd, res; - // - if (buf == NULL || bufSize < 1) - return -1; - if (port < 1 || port > 65535) - port = 7655; - // - if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - if (libsam3_debug) - fprintf(stderr, "ERROR: can't create socket\n"); - return -1; - } - // - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = ip; - // - res = sendto(fd, buf, bufSize, 0, (struct sockaddr *)&addr, sizeof(addr)); - // - if (res < 0) { - if (libsam3_debug) { - res = errno; - fprintf(stderr, "UDP ERROR (%d): %s\n", res, strerror(res)); - } - res = -1; - } else { - if (libsam3_debug) - fprintf(stderr, "UDP: %d bytes sent\n", res); - } - // - close(fd); - // - return (res >= 0 ? 0 : -1); -} - -int sam3udpSendTo(const char *hostname, int port, const void *buf, - size_t bufSize, uint32_t *ip) { - struct hostent *host = NULL; - // TODO: ipv6 - if (buf == NULL || bufSize < 1) - return -1; - if (hostname == NULL || !hostname[0]) - hostname = "localhost"; - if (port < 1 || port > 65535) - port = 7655; - // - host = gethostbyname(hostname); - if (host == NULL || host->h_name == NULL || !host->h_name[0]) { - if (libsam3_debug) - fprintf(stderr, "ERROR: can't resolve '%s'\n", hostname); - return -1; - } - // - if (ip != NULL) - *ip = ((struct in_addr *)host->h_addr)->s_addr; - return sam3udpSendToIP(((struct in_addr *)host->h_addr)->s_addr, port, buf, - bufSize); -} - -//////////////////////////////////////////////////////////////////////////////// -void sam3FreeFieldList(SAMFieldList *list) { - while (list != NULL) { - SAMFieldList *c = list; - // - list = list->next; - if (c->name != NULL) - free(c->name); - if (c->value != NULL) - free(c->value); - free(c); - } -} - -void sam3DumpFieldList(const SAMFieldList *list) { - for (; list != NULL; list = list->next) { - fprintf(stderr, "%s=[%s]\n", list->name, list->value); - } -} - -const char *sam3FindField(const SAMFieldList *list, const char *field) { - if (list != NULL && field != NULL) { - for (list = list->next; list != NULL; list = list->next) { - if (list->name != NULL && strcmp(field, list->name) == 0) - return list->value; - } - } - return NULL; -} - -static char *xstrdup(const char *s, int len) { - if (len >= 0) { - char *res = malloc(len + 1); - // - if (res != NULL) { - if (len > 0) - memcpy(res, s, len); - res[len] = 0; - } - // - return res; - } - // - return NULL; -} - -// returns NULL if there are no more tokens -static inline const char *xstrtokend(const char *s) { - while (*s && isspace(*s)) - ++s; - // - if (*s) { - char qch = 0; - // - while (*s) { - if (*s == qch) { - qch = 0; - } else if (*s == '"') { - qch = *s; - } else if (qch) { - if (*s == '\\' && s[1]) - ++s; - } else if (isspace(*s)) { - break; - } - ++s; - } - } else { - s = NULL; - } - // - return s; -} - -SAMFieldList *sam3ParseReply(const char *rep) { - SAMFieldList *first = NULL, *last, *c; - const char *p = rep, *e, *e1; - // - // first 2 words - while (*p && isspace(*p)) - ++p; - if ((e = xstrtokend(p)) == NULL) - return NULL; - if ((e1 = xstrtokend(e)) == NULL) - return NULL; - // - if ((first = last = c = malloc(sizeof(SAMFieldList))) == NULL) - return NULL; - c->next = NULL; - c->name = c->value = NULL; - if ((c->name = xstrdup(p, e - p)) == NULL) - goto error; - while (*e && isspace(*e)) - ++e; - if ((c->value = xstrdup(e, e1 - e)) == NULL) - goto error; - // - p = e1; - while (*p) { - while (*p && isspace(*p)) - ++p; - if ((e = xstrtokend(p)) == NULL) - break; // no more tokens - // - if (libsam3_debug) - fprintf(stderr, "<%s>\n", p); - // - if ((c = malloc(sizeof(SAMFieldList))) == NULL) - return NULL; - c->next = NULL; - c->name = c->value = NULL; - last->next = c; - last = c; - // - if ((e1 = memchr(p, '=', e - p)) != NULL) { - // key=value - if ((c->name = xstrdup(p, e1 - p)) == NULL) - goto error; - if ((c->value = xstrdup(e1 + 1, e - e1 - 1)) == NULL) - goto error; - } else { - // only key (there is no such replies in SAMv3, but... - if ((c->name = xstrdup(p, e - p)) == NULL) - goto error; - if ((c->value = strdup("")) == NULL) - goto error; - } - p = e; - } - // - if (libsam3_debug) - sam3DumpFieldList(first); - // - return first; -error: - sam3FreeFieldList(first); - return NULL; -} - -// NULL: error; else: list of fields -// first item is always 2-word reply, with first word in name and second in -// value -SAMFieldList *sam3ReadReply(int fd) { - char rep[2048]; // should be enough for any reply - // - if (sam3tcpReceiveStr(fd, rep, sizeof(rep)) < 0) - return NULL; - if (libsam3_debug) - fprintf(stderr, "SAM REPLY: [%s]\n", rep); - return sam3ParseReply(rep); -} - -// example: -// r0: 'HELLO' -// r1: 'REPLY' -// field: NULL or 'RESULT' -// VALUE: NULL or 'OK' -// returns bool -int sam3IsGoodReply(const SAMFieldList *list, const char *r0, const char *r1, - const char *field, const char *value) { - if (list != NULL && list->name != NULL && list->value != NULL) { - if (r0 != NULL && strcmp(r0, list->name) != 0) - return 0; - if (r1 != NULL && strcmp(r1, list->value) != 0) - return 0; - if (field != NULL) { - for (list = list->next; list != NULL; list = list->next) { - if (list->name == NULL || list->value == NULL) - return 0; // invalid list, heh - if (strcmp(field, list->name) == 0) { - if (value != NULL && strcmp(value, list->value) != 0) - return 0; - return 1; - } - } - } - return 1; - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// by Bob Jenkins -// public domain -// http://burtleburtle.net/bob/rand/smallprng.html -// -//////////////////////////////////////////////////////////////////////////////// -typedef struct { - uint32_t a, b, c, d; -} BJRandCtx; - -#define BJPRNG_ROT(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) - -static uint32_t bjprngRand(BJRandCtx *x) { - uint32_t e; - /* original: - e = x->a-BJPRNG_ROT(x->b, 27); - x->a = x->b^BJPRNG_ROT(x->c, 17); - x->b = x->c+x->d; - x->c = x->d+e; - x->d = e+x->a; - */ - /* better, but slower at least in idiotic m$vc */ - e = x->a - BJPRNG_ROT(x->b, 23); - x->a = x->b ^ BJPRNG_ROT(x->c, 16); - x->b = x->c + BJPRNG_ROT(x->d, 11); - x->c = x->d + e; - x->d = e + x->a; - // - return x->d; -} - -static void bjprngInit(BJRandCtx *x, uint32_t seed) { - x->a = 0xf1ea5eed; - x->b = x->c = x->d = seed; - for (int i = 0; i < 20; ++i) - bjprngRand(x); -} - -static inline uint32_t hashint(uint32_t a) { - a -= (a << 6); - a ^= (a >> 17); - a -= (a << 9); - a ^= (a << 4); - a -= (a << 3); - a ^= (a << 10); - a ^= (a >> 15); - return a; -} - -static uint32_t genSeed(void) { - uint32_t res; -#ifndef WIN32 - struct sysinfo sy; - pid_t pid = getpid(); - // - sysinfo(&sy); - res = hashint((uint32_t)pid) ^ hashint((uint32_t)time(NULL)) ^ - hashint((uint32_t)sy.sharedram) ^ hashint((uint32_t)sy.bufferram) ^ - hashint((uint32_t)sy.uptime); -#else - res = hashint((uint32_t)GetCurrentProcessId()) ^ - hashint((uint32_t)GetTickCount()); -#endif - return hashint(res); -} - -//////////////////////////////////////////////////////////////////////////////// -size_t sam3GenChannelName(char *dest, size_t minlen, size_t maxlen) { - BJRandCtx rc; - size_t len; - size_t retlen; - // - if (dest == NULL || minlen < 1 || maxlen < minlen || minlen > 65536 || - maxlen > 65536) - return -1; - bjprngInit(&rc, genSeed()); - len = minlen + (bjprngRand(&rc) % (maxlen - minlen + 1)); - retlen = len; - while (len--) { - int ch = bjprngRand(&rc) % 64; - // - if (ch >= 0 && ch < 10) - ch += '0'; - else if (ch >= 10 && ch < 36) - ch += 'A' - 10; - else if (ch >= 36 && ch < 62) - ch += 'a' - 36; - else if (ch == 62) - ch = '-'; - else if (ch == 63) - ch = '_'; - else if (ch > 64) - abort(); - *dest++ = ch; - } - *dest++ = 0; - return retlen; -} - -//////////////////////////////////////////////////////////////////////////////// -static int sam3HandshakeInternal(int fd) { - SAMFieldList *rep = NULL; - // - if (sam3tcpPrintf(fd, "HELLO VERSION MIN=3.0 MAX=3.1\n") < 0) - goto error; - rep = sam3ReadReply(fd); - if (!sam3IsGoodReply(rep, "HELLO", "REPLY", "RESULT", "OK")) - goto error; - sam3FreeFieldList(rep); - return fd; -error: - sam3tcpDisconnect(fd); - if (rep != NULL) - sam3FreeFieldList(rep); - return -1; -} - -int sam3HandshakeIP(uint32_t ip, int port) { - int fd; - // - if ((fd = sam3tcpConnectIP(ip, (port < 1 || port > 65535 ? 7656 : port))) < 0) - return -1; - return sam3HandshakeInternal(fd); -} - -int sam3Handshake(const char *hostname, int port, uint32_t *ip) { - int fd; - // - if ((fd = sam3tcpConnect( - (hostname == NULL || !hostname[0] ? "localhost" : hostname), - (port < 1 || port > 65535 ? 7656 : port), ip)) < 0) - return -1; - return sam3HandshakeInternal(fd); -} - -//////////////////////////////////////////////////////////////////////////////// -static inline void strcpyerr(Sam3Session *ses, const char *errstr) { - memset(ses->error, 0, sizeof(ses->error)); - if (errstr != NULL) - strncpy(ses->error, errstr, sizeof(ses->error) - 1); -} - -int sam3GenerateKeys(Sam3Session *ses, const char *hostname, int port, - int sigType) { - if (ses != NULL) { - SAMFieldList *rep = NULL; - int fd, res = -1; - static const char *sigtypes[5] = { - "SIGNATURE_TYPE=DSA_SHA1", "SIGNATURE_TYPE=ECDSA_SHA256_P256", - "SIGNATURE_TYPE=ECDSA_SHA384_P384", "SIGNATURE_TYPE=ECDSA_SHA512_P521", - "SIGNATURE_TYPE=EdDSA_SHA512_Ed25519"}; - // - if ((fd = sam3Handshake(hostname, port, NULL)) < 0) { - strcpyerr(ses, "I2P_ERROR"); - return -1; - } - // - if (sam3tcpPrintf(fd, "DEST GENERATE %s\n", sigtypes[sigType]) >= 0) { - if ((rep = sam3ReadReply(fd)) != NULL && - sam3IsGoodReply(rep, "DEST", "REPLY", NULL, NULL)) { - const char *pub = sam3FindField(rep, "PUB"), - *priv = sam3FindField(rep, "PRIV"); - // - if (pub != NULL && sam3CheckValidKeyLength(pub) && priv != NULL && - strlen(priv) >= SAM3_PRIVKEY_MIN_SIZE) { - strcpy(ses->pubkey, pub); - strcpy(ses->privkey, priv); - res = 0; - } - } - } - // - sam3FreeFieldList(rep); - sam3tcpDisconnect(fd); - // - return res; - } - return -1; -} - -int sam3NameLookup(Sam3Session *ses, const char *hostname, int port, - const char *name) { - if (ses != NULL && name != NULL && name[0]) { - SAMFieldList *rep = NULL; - int fd, res = -1; - // - if ((fd = sam3Handshake(hostname, port, NULL)) < 0) { - strcpyerr(ses, "I2P_ERROR"); - return -1; - } - // - strcpyerr(ses, "I2P_ERROR"); - if (sam3tcpPrintf(fd, "NAMING LOOKUP NAME=%s\n", name) >= 0) { - if ((rep = sam3ReadReply(fd)) != NULL && - sam3IsGoodReply(rep, "NAMING", "REPLY", "RESULT", NULL)) { - const char *rs = sam3FindField(rep, "RESULT"), - *pub = sam3FindField(rep, "VALUE"); - // - if (strcmp(rs, "OK") == 0) { - if (pub != NULL && sam3CheckValidKeyLength(pub)) { - strcpy(ses->destkey, pub); - strcpyerr(ses, NULL); - res = 0; - } - } else if (rs[0]) { - strcpyerr(ses, rs); - } - } - } - // - sam3FreeFieldList(rep); - sam3tcpDisconnect(fd); - // - return res; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -static int sam3CloseConnectionInternal(Sam3Connection *conn) { - return (conn->fd >= 0 ? sam3tcpDisconnect(conn->fd) : 0); -} - -int sam3CloseConnection(Sam3Connection *conn) { - if (conn != NULL) { - int res = sam3CloseConnectionInternal(conn); - // - if (conn->ses != NULL) { - for (Sam3Connection *p = NULL, *c = conn->ses->connlist; c != NULL; - p = c, c = c->next) { - if (c == conn) { - if (p == NULL) - conn->ses->connlist = c->next; - else - p->next = c->next; - break; - } - } - } - free(conn); - // - return res; - } - return -1; -} - -int sam3CloseSession(Sam3Session *ses) { - if (ses != NULL) { - for (Sam3Connection *n, *c = ses->connlist; c != NULL; c = n) { - n = c->next; - sam3CloseConnectionInternal(c); - free(c); - } - if (ses->fwd_fd >= 0) - sam3tcpDisconnect(ses->fwd_fd); - if (ses->fd >= 0) - sam3tcpDisconnect(ses->fd); - memset(ses, 0, sizeof(Sam3Session)); - ses->fd = -1; - return 0; - } - return -1; -} - -int sam3CreateSilentSession(Sam3Session *ses, const char *hostname, int port, - const char *privkey, Sam3SessionType type, - Sam3SigType sigType, const char *params) { - int r = - sam3CreateSession(ses, hostname, port, privkey, type, sigType, params); - if (r != 0) { - return r; - } - ses->silent = true; - return 0; -} - -int sam3CreateSession(Sam3Session *ses, const char *hostname, int port, - const char *privkey, Sam3SessionType type, - Sam3SigType sigType, const char *params) { - if (ses != NULL) { - static const char *typenames[3] = {"RAW", "DATAGRAM", "STREAM"}; - static const char *sigtypes[5] = { - "SIGNATURE_TYPE=DSA_SHA1", "SIGNATURE_TYPE=ECDSA_SHA256_P256", - "SIGNATURE_TYPE=ECDSA_SHA384_P384", "SIGNATURE_TYPE=ECDSA_SHA512_P521", - "SIGNATURE_TYPE=EdDSA_SHA512_Ed25519"}; - - SAMFieldList *rep; - const char *v = NULL; - const char *pdel = (params != NULL ? " " : ""); - // - memset(ses, 0, sizeof(Sam3Session)); - ses->fd = -1; - ses->fwd_fd = -1; - ses->silent = false; - // - if (privkey != NULL && strlen(privkey) < SAM3_PRIVKEY_MIN_SIZE) - goto error; - if ((int)type < 0 || (int)type > 2) - goto error; - if (privkey == NULL) - privkey = "TRANSIENT"; - // - ses->type = type; - ses->sigType = sigType; - ses->port = (type == SAM3_SESSION_STREAM ? (port ? port : 7656) : 7655); - sam3GenChannelName(ses->channel, 32, 64); - if (libsam3_debug) - fprintf(stderr, "sam3CreateSession: channel=[%s]\n", ses->channel); - // - if ((ses->fd = sam3Handshake(hostname, port, &ses->ip)) < 0) - goto error; - // - if (libsam3_debug) - fprintf(stderr, "sam3CreateSession: creating session (%s)...\n", - typenames[(int)type]); - if (sam3tcpPrintf( - ses->fd, "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s %s %s %s\n", - typenames[(int)type], ses->channel, privkey, sigtypes[(int)sigType], - pdel, (params != NULL ? params : "")) < 0) - goto error; - if ((rep = sam3ReadReply(ses->fd)) == NULL) - goto error; - if (!sam3IsGoodReply(rep, "SESSION", "STATUS", "RESULT", "OK") || - (v = sam3FindField(rep, "DESTINATION")) == NULL || - strlen(v) < SAM3_PRIVKEY_MIN_SIZE) { - if (libsam3_debug) - fprintf(stderr, "sam3CreateSession: invalid reply (%ld)...\n", - (v != NULL ? strlen(v) : -1)); - if (libsam3_debug) - sam3DumpFieldList(rep); - sam3FreeFieldList(rep); - goto error; - } - // save our keys - strcpy(ses->privkey, v); - sam3FreeFieldList(rep); - // get public key - if (sam3tcpPrintf(ses->fd, "NAMING LOOKUP NAME=ME\n") < 0) - goto error; - if ((rep = sam3ReadReply(ses->fd)) == NULL) - goto error; - v = NULL; - if (!sam3IsGoodReply(rep, "NAMING", "REPLY", "RESULT", "OK") || - (v = sam3FindField(rep, "VALUE")) == NULL || - !sam3CheckValidKeyLength(v)) { - if (libsam3_debug) - fprintf(stderr, "sam3CreateSession: invalid NAMING reply (%ld)...\n", - (v != NULL ? strlen(v) : -1)); - if (libsam3_debug) - sam3DumpFieldList(rep); - sam3FreeFieldList(rep); - goto error; - } - strcpy(ses->pubkey, v); - sam3FreeFieldList(rep); - // - if (libsam3_debug) - fprintf(stderr, "sam3CreateSession: complete.\n"); - return 0; - } -error: - sam3CloseSession(ses); - return -1; -} - -Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey) { - if (ses != NULL) { - SAMFieldList *rep; - Sam3Connection *conn; - // - if (ses->type != SAM3_SESSION_STREAM) { - strcpyerr(ses, "INVALID_SESSION_TYPE"); - return NULL; - } - if (ses->fd < 0) { - strcpyerr(ses, "INVALID_SESSION"); - return NULL; - } - if (destkey == NULL || !sam3CheckValidKeyLength(destkey)) { - strcpyerr(ses, "INVALID_KEY"); - return NULL; - } - if ((conn = calloc(1, sizeof(Sam3Connection))) == NULL) { - strcpyerr(ses, "NO_MEMORY"); - return NULL; - } - if ((conn->fd = sam3HandshakeIP(ses->ip, ses->port)) < 0) { - strcpyerr(ses, "IO_ERROR_SK"); - goto error; - } - if (sam3tcpPrintf(conn->fd, - "STREAM CONNECT ID=%s DESTINATION=%s SILENT=%s\n", - ses->channel, destkey, checkIsSilent(ses)) < 0) { - strcpyerr(ses, "IO_ERROR"); - goto error; - } - if ((rep = sam3ReadReply(conn->fd)) == NULL) { - strcpyerr(ses, "IO_ERROR"); - goto error; - } - if (!ses->silent) { - if (!sam3IsGoodReply(rep, "STREAM", "STATUS", "RESULT", "OK")) { - const char *v = sam3FindField(rep, "RESULT"); - // - strcpyerr(ses, (v != NULL && v[0] ? v : "I2P_ERROR")); - sam3CloseConnectionInternal(conn); - free(conn); - conn = NULL; - } else { - // no error - strcpyerr(ses, NULL); - } - } - sam3FreeFieldList(rep); - if (conn != NULL) { - strcpy(conn->destkey, destkey); - conn->ses = ses; - conn->next = ses->connlist; - ses->connlist = conn; - } - return conn; - error: - sam3CloseConnectionInternal(conn); - free(conn); - return NULL; - } - return NULL; -} - -Sam3Connection *sam3StreamAccept(Sam3Session *ses) { - if (ses != NULL) { - SAMFieldList *rep = NULL; - char repstr[1024]; - Sam3Connection *conn; - // - if (ses->type != SAM3_SESSION_STREAM) { - strcpyerr(ses, "INVALID_SESSION_TYPE"); - return NULL; - } - if (ses->fd < 0) { - strcpyerr(ses, "INVALID_SESSION"); - return NULL; - } - if ((conn = calloc(1, sizeof(Sam3Connection))) == NULL) { - strcpyerr(ses, "NO_MEMORY"); - return NULL; - } - if ((conn->fd = sam3HandshakeIP(ses->ip, ses->port)) < 0) { - strcpyerr(ses, "IO_ERROR_SK"); - goto error; - } - if (sam3tcpPrintf(conn->fd, "STREAM ACCEPT ID=%s\n", ses->channel) < 0) { - strcpyerr(ses, "IO_ERROR_PF"); - goto error; - } - if ((rep = sam3ReadReply(conn->fd)) == NULL) { - strcpyerr(ses, "IO_ERROR_RP"); - goto error; - } - if (!ses->silent) { - if (!sam3IsGoodReply(rep, "STREAM", "STATUS", "RESULT", "OK")) { - const char *v = sam3FindField(rep, "RESULT"); - // - strcpyerr(ses, (v != NULL && v[0] ? v : "I2P_ERROR_RES")); - goto error; - } - } - if (sam3tcpReceiveStr(conn->fd, repstr, sizeof(repstr)) < 0) { - strcpyerr(ses, "IO_ERROR_RP1"); - goto error; - } - sam3FreeFieldList(rep); - if ((rep = sam3ParseReply(repstr)) != NULL) { - const char *v = sam3FindField(rep, "RESULT"); - // - strcpyerr(ses, (v != NULL && v[0] ? v : "I2P_ERROR_RES1")); - goto error; - } - if (!sam3CheckValidKeyLength(repstr)) { - strcpyerr(ses, "INVALID_KEY"); - goto error; - } - sam3FreeFieldList(rep); - strcpy(conn->destkey, repstr); - conn->ses = ses; - conn->next = ses->connlist; - ses->connlist = conn; - strcpyerr(ses, NULL); - return conn; - error: - if (rep != NULL) - sam3FreeFieldList(rep); - sam3CloseConnectionInternal(conn); - free(conn); - return NULL; - } - return NULL; -} - -const char *checkIsSilent(Sam3Session *ses) { - if (ses->silent == true) { - return "true"; - } else { - return "false"; - } -} - -int sam3StreamForward(Sam3Session *ses, const char *hostname, int port) { - if (ses != NULL) { - SAMFieldList *rep = NULL; - // - if (ses->type != SAM3_SESSION_STREAM) { - strcpyerr(ses, "INVALID_SESSION_TYPE"); - return -1; - } - if (ses->fd < 0) { - strcpyerr(ses, "INVALID_SESSION"); - return -1; - } - if (ses->fwd_fd >= 0) { - strcpyerr(ses, "DUPLICATE_FORWARD"); - return -1; - } - if ((ses->fwd_fd = sam3HandshakeIP(ses->ip, ses->port)) < 0) { - strcpyerr(ses, "IO_ERROR_SK"); - goto error; - } - if (sam3tcpPrintf(ses->fwd_fd, - "STREAM FORWARD ID=%s PORT=%d HOST=%s SILENT=%s\n", - ses->channel, port, hostname, checkIsSilent(ses)) < 0) { - strcpyerr(ses, "IO_ERROR_PF"); - goto error; - } - if ((rep = sam3ReadReply(ses->fwd_fd)) == NULL) { - strcpyerr(ses, "IO_ERROR_RP"); - goto error; - } - if (!sam3IsGoodReply(rep, "STREAM", "STATUS", "RESULT", "OK")) { - const char *v = sam3FindField(rep, "RESULT"); - // - strcpyerr(ses, (v != NULL && v[0] ? v : "I2P_ERROR_RES")); - goto error; - } - sam3FreeFieldList(rep); - strcpyerr(ses, NULL); - return 0; - error: - if (rep != NULL) - sam3FreeFieldList(rep); - return -1; - } - return -1; -} - -int sam3DatagramSend(Sam3Session *ses, const char *destkey, const void *buf, - size_t bufsize) { - if (ses != NULL) { - char *dbuf; - int res, dbufsz; - // - if (ses->type == SAM3_SESSION_STREAM) { - strcpyerr(ses, "INVALID_SESSION_TYPE"); - return -1; - } - if (ses->fd < 0) { - strcpyerr(ses, "INVALID_SESSION"); - return -1; - } - if (destkey == NULL || !sam3CheckValidKeyLength(destkey)) { - strcpyerr(ses, "INVALID_KEY"); - return -1; - } - if (buf == NULL || bufsize < 1 || bufsize > 31744) { - strcpyerr(ses, "INVALID_DATA"); - return -1; - } - dbufsz = bufsize + 4 + SAM3_PUBKEY_SIZE + 1 + strlen(ses->channel) + 1; - if ((dbuf = malloc(dbufsz)) == NULL) { - strcpyerr(ses, "OUT_OF_MEMORY"); - return -1; - } - sprintf(dbuf, "3.0 %s %s\n", ses->channel, destkey); - memcpy(dbuf + strlen(dbuf), buf, bufsize); - res = sam3udpSendToIP(ses->ip, ses->port, dbuf, dbufsz); - free(dbuf); - strcpyerr(ses, (res < 0 ? "IO_ERROR" : NULL)); - return (res < 0 ? -1 : 0); - } - return -1; -} - -ssize_t sam3DatagramReceive(Sam3Session *ses, void *buf, size_t bufsize) { - if (ses != NULL) { - SAMFieldList *rep; - const char *v; - ssize_t size = 0; - // - if (ses->type == SAM3_SESSION_STREAM) { - strcpyerr(ses, "INVALID_SESSION_TYPE"); - return -1; - } - if (ses->fd < 0) { - strcpyerr(ses, "INVALID_SESSION"); - return -1; - } - if (buf == NULL || bufsize < 1) { - strcpyerr(ses, "INVALID_BUFFER"); - return -1; - } - if ((rep = sam3ReadReply(ses->fd)) == NULL) { - strcpyerr(ses, "IO_ERROR"); - return -1; - } - if (!sam3IsGoodReply(rep, "DATAGRAM", "RECEIVED", "SIZE", NULL)) { - strcpyerr(ses, "I2P_ERROR"); - sam3FreeFieldList(rep); - return -1; - } - // - if ((v = sam3FindField(rep, "DESTINATION")) != NULL && - sam3CheckValidKeyLength(v)) - strncpy(ses->destkey, v, sizeof(ses->destkey)); - v = sam3FindField(rep, "SIZE"); // we have this field -- for sure - if (!v[0] || !isdigit(*v)) { - strcpyerr(ses, "I2P_ERROR_SIZE"); - sam3FreeFieldList(rep); - return -1; - } - // - while (*v && isdigit(*v)) { - if ((size = size * 10 + v[0] - '0') > bufsize) { - strcpyerr(ses, "I2P_ERROR_BUFFER_TOO_SMALL"); - sam3FreeFieldList(rep); - return -1; - } - ++v; - } - // - if (*v) { - strcpyerr(ses, "I2P_ERROR_SIZE"); - sam3FreeFieldList(rep); - return -1; - } - sam3FreeFieldList(rep); - // - if (sam3tcpReceive(ses->fd, buf, size) != size) { - strcpyerr(ses, "IO_ERROR"); - return -1; - } - strcpyerr(ses, NULL); - return size; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// output 8 bytes for every 5 input -// return size or <0 on error -ssize_t sam3Base32Encode(char *dest, size_t destsz, const void *srcbuf, - size_t srcsize) { - if (dest != NULL && srcbuf != NULL && srcsize >= 0) { - static const char *const b32chars = "abcdefghijklmnopqrstuvwxyz234567="; - const unsigned char *src = (const unsigned char *)srcbuf; - ssize_t destsize = 0; - // - while (srcsize > 0) { - int blksize = (srcsize < 5 ? srcsize : 5); - unsigned char n[8]; - // - memset(n, 0, sizeof(n)); - switch (blksize) { - case 5: - n[7] = (src[4] & 0x1f); - n[6] = ((src[4] & 0xe0) >> 5); - case 4: - n[6] |= ((src[3] & 0x03) << 3); - n[5] = ((src[3] & 0x7c) >> 2); - n[4] = ((src[3] & 0x80) >> 7); - case 3: - n[4] |= ((src[2] & 0x0f) << 1); - n[3] = ((src[2] & 0xf0) >> 4); - case 2: - n[3] |= ((src[1] & 0x01) << 4); - n[2] = ((src[1] & 0x3e) >> 1); - n[1] = ((src[1] & 0xc0) >> 6); - case 1: - n[1] |= ((src[0] & 0x07) << 2); - n[0] = ((src[0] & 0xf8) >> 3); - break; - } - src += blksize; - srcsize -= blksize; - // pad - switch (blksize) { - case 1: - n[2] = n[3] = 32; - case 2: - n[4] = 32; - case 3: - n[5] = n[6] = 32; - case 4: - n[7] = 32; - case 5: - break; - } - // output - if (destsize + 8 <= destsz) { - for (int f = 0; f < 8; ++f) - *dest++ = b32chars[n[f]]; - } - destsize += 8; - } - if (destsize <= destsz) { - *dest++ = 0; // make valid asciiz string - } - return destsize; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// output 8 bytes for every 5 input -// return size or <0 on error -ssize_t sam3Base32Decode(char *dest, size_t destsz, const void *srcbuf, - size_t srcsize) { - if (dest != NULL && srcbuf != NULL && srcsize >= 0) { - static const char *const b32chars = "abcdefghijklmnopqrstuvwxyz234567="; - const unsigned char *src = (const unsigned char *)srcbuf; - int destsize = 0; - // - while (srcsize > 0) { - int blksize = (srcsize < 5 ? srcsize : 5); - unsigned char n[8]; - // - memset(n, 0, sizeof(n)); - switch (blksize) { - case 5: - n[7] = (src[4] & 0x1f); - n[6] = ((src[4] & 0xe0) >> 5); - case 4: - n[6] |= ((src[3] & 0x03) << 3); - n[5] = ((src[3] & 0x7c) >> 2); - n[4] = ((src[3] & 0x80) >> 7); - case 3: - n[4] |= ((src[2] & 0x0f) << 1); - n[3] = ((src[2] & 0xf0) >> 4); - case 2: - n[3] |= ((src[1] & 0x01) << 4); - n[2] = ((src[1] & 0x3e) >> 1); - n[1] = ((src[1] & 0xc0) >> 6); - case 1: - n[1] |= ((src[0] & 0x07) << 2); - n[0] = ((src[0] & 0xf8) >> 3); - break; - } - src += blksize; - srcsize -= blksize; - // pad - switch (blksize) { - case 1: - n[2] = n[3] = 32; - case 2: - n[4] = 32; - case 3: - n[5] = n[6] = 32; - case 4: - n[7] = 32; - case 5: - break; - } - // output - if (destsize + 8 <= destsz) { - for (int f = 0; f < 8; ++f) - *dest++ = b32chars[n[f]]; - } - destsize += 8; - } - if (destsize <= destsz) { - *dest++ = 0; // make valid asciiz string - } - return destsize; - } - return -1; -} diff --git a/supportlibs/libsam3/src/libsam3/libsam3.h b/supportlibs/libsam3/src/libsam3/libsam3.h deleted file mode 100644 index 16942f594..000000000 --- a/supportlibs/libsam3/src/libsam3/libsam3.h +++ /dev/null @@ -1,314 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#ifndef LIBSAM3_H -#define LIBSAM3_H - -#include -#include -#include - -#ifndef _SSIZE_T_DEFINED -#define _SSIZE_T_DEFINED -#undef ssize_t -#ifdef _WIN64 -typedef signed int64 ssize_t; -typedef int ssize_t; -#endif /* _WIN64 */ -#endif /* _SSIZE_T_DEFINED */ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////////////// -extern int libsam3_debug; - -//////////////////////////////////////////////////////////////////////////////// -#define SAM3_HOST_DEFAULT (NULL) -#define SAM3_PORT_DEFAULT (0) - -#define SAM3_DESTINATION_TRANSIENT (NULL) - -#define SAM3_PUBKEY_SIZE (516) -#define SAM3_CERT_SIZE (100) -#define SAM3_PRIVKEY_MIN_SIZE (884) - -//////////////////////////////////////////////////////////////////////////////// -/* returns fd or -1 */ -/* 'ip': host IP; can be NULL */ -extern int sam3tcpConnect(const char *hostname, int port, uint32_t *ip); -extern int sam3tcpConnectIP(uint32_t ip, int port); - -/* <0: error; 0: ok */ -extern int sam3tcpDisconnect(int fd); - -/* <0: error; 0: ok */ -extern int sam3tcpSetTimeoutSend(int fd, int timeoutms); - -/* <0: error; 0: ok */ -extern int sam3tcpSetTimeoutReceive(int fd, int timeoutms); - -/* <0: error; 0: ok */ -/* sends the whole buffer */ -extern int sam3tcpSend(int fd, const void *buf, size_t bufSize); - -/* <0: received (-res) bytes; read error */ -/* can return less that requesten bytes even if `allowPartial` is 0 when - * connection is closed */ -extern ssize_t sam3tcpReceiveEx(int fd, void *buf, size_t bufSize, - int allowPartial); - -extern ssize_t sam3tcpReceive(int fd, void *buf, size_t bufSize); - -extern int sam3tcpPrintf(int fd, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); - -extern int sam3tcpReceiveStr(int fd, char *dest, size_t maxSize); - -/* pass NULL for 'localhost' and 0 for 7655 */ -/* 'ip': host IP; can be NULL */ -extern int sam3udpSendTo(const char *hostname, int port, const void *buf, - size_t bufSize, uint32_t *ip); -extern int sam3udpSendToIP(uint32_t ip, int port, const void *buf, - size_t bufSize); - -//////////////////////////////////////////////////////////////////////////////// -typedef struct SAMFieldList { - char *name; - char *value; - struct SAMFieldList *next; -} SAMFieldList; - -extern void sam3FreeFieldList(SAMFieldList *list); -extern void sam3DumpFieldList(const SAMFieldList *list); - -/* read and parse SAM reply */ -/* NULL: error; else: list of fields */ -/* first item is always 2-word reply, with first word in name and second in - * value */ -extern SAMFieldList *sam3ReadReply(int fd); - -extern SAMFieldList *sam3ParseReply(const char *rep); - -/* - * example: - * r0: 'HELLO' - * r1: 'REPLY' - * field: NULL or 'RESULT' - * VALUE: NULL or 'OK' - * returns bool - */ -extern int sam3IsGoodReply(const SAMFieldList *list, const char *r0, - const char *r1, const char *field, - const char *value); - -extern const char *sam3FindField(const SAMFieldList *list, const char *field); - -//////////////////////////////////////////////////////////////////////////////// -/* pass NULL for 'localhost' and 0 for 7656 */ -/* returns <0 on error or socket fd on success */ -extern int sam3Handshake(const char *hostname, int port, uint32_t *ip); -extern int sam3HandshakeIP(uint32_t ip, int port); - -//////////////////////////////////////////////////////////////////////////////// -typedef enum { - SAM3_SESSION_RAW, - SAM3_SESSION_DGRAM, - SAM3_SESSION_STREAM -} Sam3SessionType; - -typedef enum { - DSA_SHA1, - ECDSA_SHA256_P256, - ECDSA_SHA384_P384, - ECDSA_SHA512_P521, - EdDSA_SHA512_Ed25519 -} Sam3SigType; - -typedef struct Sam3Session { - Sam3SessionType type; - Sam3SigType sigType; - int fd; - char privkey[SAM3_PRIVKEY_MIN_SIZE + 1]; // destination private key (asciiz) - char pubkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE + - 1]; // destination public key (asciiz) - char channel[66]; // name of this sam session (asciiz) - char destkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE + - 1]; // for DGRAM sessions (asciiz) - // int destsig; - char error[32]; // error message (asciiz) - uint32_t ip; - int port; // this will be changed to UDP port for DRAM/RAW (can be 0) - struct Sam3Connection *connlist; // list of opened connections - int fwd_fd; - bool silent; -} Sam3Session; - -typedef struct Sam3Connection { - Sam3Session *ses; - struct Sam3Connection *next; - int fd; - char destkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE + - 1]; // remote destination public key (asciiz) - int destcert; - char error[32]; // error message (asciiz) -} Sam3Connection; - -//////////////////////////////////////////////////////////////////////////////// -/* - * create SAM session - * pass NULL as hostname for 'localhost' and 0 as port for 7656 - * pass NULL as privkey to create TRANSIENT session - * 'params' can be NULL - * see http://www.i2p2.i2p/i2cp.html#options for common options, - * and http://www.i2p2.i2p/streaming.html#options for STREAM options - * if result<0: error, 'ses' fields are undefined, no need to call - * sam3CloseSession() if result==0: ok, all 'ses' fields are filled - * TODO: don't clear 'error' field on error (and set it to something meaningful) - */ -extern int sam3CreateSession(Sam3Session *ses, const char *hostname, int port, - const char *privkey, Sam3SessionType type, - Sam3SigType sigType, const char *params); - -/* - * create SAM session with SILENT=True - * pass NULL as hostname for 'localhost' and 0 as port for 7656 - * pass NULL as privkey to create TRANSIENT session - * 'params' can be NULL - * see http://www.i2p2.i2p/i2cp.html#options for common options, - * and http://www.i2p2.i2p/streaming.html#options for STREAM options - * if result<0: error, 'ses' fields are undefined, no need to call - * sam3CloseSession() if result==0: ok, all 'ses' fields are filled - * TODO: don't clear 'error' field on error (and set it to something meaningful) - */ -extern int sam3CreateSilentSession(Sam3Session *ses, const char *hostname, - int port, const char *privkey, - Sam3SessionType type, Sam3SigType sigType, - const char *params); - -/* - * close SAM session (and all it's connections) - * returns <0 on error, 0 on ok - * 'ses' must be properly initialized - */ -extern int sam3CloseSession(Sam3Session *ses); - -/* - * check to see if a SAM session is silent and output - * characters for use with sam3tcpPrintf() checkIsSilent - */ - -const char *checkIsSilent(Sam3Session *ses); - -/* - * Check to make sure that the destination in use is of a valid length, returns - * 1 if true and 0 if false. - */ -int sam3CheckValidKeyLength(const char *pubkey); - -/* - * open stream connection to 'destkey' endpoint - * 'destkey' is 516-byte public key (asciiz) - * returns <0 on error, fd on ok - * you still have to call sam3CloseSession() on failure - * sets ses->error on error - */ -extern Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey); - -/* - * accepts stream connection and sets 'destkey' - * 'destkey' is 516-byte public key - * returns <0 on error, fd on ok - * you still have to call sam3CloseSession() on failure - * sets ses->error on error - * note that there is no timeouts for now, but you can use sam3tcpSetTimeout*() - */ -extern Sam3Connection *sam3StreamAccept(Sam3Session *ses); - -/* - * sets up forwarding stream connection - * returns <0 on error, 0 on ok - * you still have to call sam3CloseSession() on failure - * sets ses->error on error - * note that there is no timeouts for now, but you can use sam3tcpSetTimeout*() - */ -extern int sam3StreamForward(Sam3Session *ses, const char *hostname, int port); - -/* - * close SAM connection - * returns <0 on error, 0 on ok - * 'conn' must be properly initialized - * 'conn' is invalid after call - */ -extern int sam3CloseConnection(Sam3Connection *conn); - -//////////////////////////////////////////////////////////////////////////////// -/* - * generate new keypair - * fills 'privkey' and 'pubkey' only - * you should not call sam3CloseSession() on 'ses' - * will not set 'error' field - * returns <0 on error, 0 on ok - */ -extern int sam3GenerateKeys(Sam3Session *ses, const char *hostname, int port, - int sigType); - -/* - * do name lookup (something like gethostbyname()) - * fills 'destkey' only - * you should not call sam3CloseSession() on 'ses' - * will set 'error' field - * returns <0 on error, 0 on ok - */ -extern int sam3NameLookup(Sam3Session *ses, const char *hostname, int port, - const char *name); - -//////////////////////////////////////////////////////////////////////////////// -/* - * sends datagram to 'destkey' endpoint - * 'destkey' is 516-byte public key - * returns <0 on error, 0 on ok - * you still have to call sam3CloseSession() on failure - * sets ses->error on error - * don't send datagrams bigger than 31KB! - */ -extern int sam3DatagramSend(Sam3Session *ses, const char *destkey, - const void *buf, size_t bufsize); - -/* - * receives datagram and sets 'destkey' to source pubkey (if not RAW) - * returns <0 on error (buffer too small is error too) or number of bytes - * written to 'buf' you still have to call sam3CloseSession() on failure sets - * ses->error on error will necer receive datagrams bigger than 31KB (32KB for - * RAW) - */ -extern ssize_t sam3DatagramReceive(Sam3Session *ses, void *buf, size_t bufsize); - -/* - * generate random sam channel name - * return the size of the string - */ -extern size_t sam3GenChannelName(char *dest, size_t minlen, size_t maxlen); - -//////////////////////////////////////////////////////////////////////////////// -// NOT including '\0' terminator -static inline size_t sam3Base32EncodedLength(size_t size) { - return (((size + 5 - 1) / 5) * 8); -} - -// output 8 bytes for every 5 input -// return size or <0 on error -extern ssize_t sam3Base32Encode(char *dest, size_t destsz, const void *srcbuf, - size_t srcsize); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/supportlibs/libsam3/src/libsam3a/libsam3a.c b/supportlibs/libsam3/src/libsam3a/libsam3a.c deleted file mode 100644 index e5983b008..000000000 --- a/supportlibs/libsam3/src/libsam3a/libsam3a.c +++ /dev/null @@ -1,1771 +0,0 @@ -/* async SAMv3 library - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include "libsam3a.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __MINGW32__ -//#include -#include -#include -#include -#ifndef MSG_NOSIGNAL -#define MSG_NOSIGNAL 0 -#endif -#ifndef SHUT_RDWR -#define SHUT_RDWR 2 -#endif -#endif - -#ifdef __unix__ -#include -#include -#include -#include -#include -#include -#include -#endif -//////////////////////////////////////////////////////////////////////////////// -int libsam3a_debug = 0; - -#define DEFAULT_TCP_PORT (7656) -#define DEFAULT_UDP_PORT (7655) - -//////////////////////////////////////////////////////////////////////////////// -uint64_t sam3atimeval2ms(const struct timeval *tv) { - return ((uint64_t)tv->tv_sec) * 1000 + ((uint64_t)tv->tv_usec) / 1000; -} - -void sam3ams2timeval(struct timeval *tv, uint64_t ms) { - tv->tv_sec = ms / 1000; - tv->tv_usec = (ms % 1000) * 1000; -} - -//////////////////////////////////////////////////////////////////////////////// -static inline int isValidKeyChar(char ch) { - return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || - (ch >= '0' && ch <= '9') || ch == '-' || ch == '~'; -} - -int sam3aIsValidPubKey(const char *key) { - if (key != NULL && strlen(key) == SAM3A_PUBKEY_SIZE) { - for (int f = 0; f < SAM3A_PUBKEY_SIZE; ++f) - if (!isValidKeyChar(key[f])) - return 0; - return 1; - } - return 0; -} - -int sam3aIsValidPrivKey(const char *key) { - if (key != NULL && strlen(key) == SAM3A_PRIVKEY_SIZE) { - for (int f = 0; f < SAM3A_PRIVKEY_SIZE; ++f) - if (!isValidKeyChar(key[f])) - return 0; - return 1; - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -/* -static int sam3aSocketSetTimeoutSend (int fd, int timeoutms) { - if (fd >= 0 && timeoutms >= 0) { - struct timeval tv; - // - ms2timeval(&tv, timeoutms); - return (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0 ? -1 : -0); - } - return -1; -} - - -static int sam3aSocketSetTimeoutReceive (int fd, int timeoutms) { - if (fd >= 0 && timeoutms >= 0) { - struct timeval tv; - // - ms2timeval(&tv, timeoutms); - return (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ? -1 : -0); - } - return -1; -} -*/ - -static int sam3aBytesAvail(int fd) { - int av = 0; - // - if (ioctl(fd, FIONREAD, &av) < 0) - return -1; - return av; -} - -static uint32_t sam3aResolveHost(const char *hostname) { - struct hostent *host; - // - if (hostname == NULL || !hostname[0]) - return 0; - if ((host = gethostbyname(hostname)) == NULL || host->h_name == NULL || - !host->h_addr_list[0][0]) { - if (libsam3a_debug) - fprintf(stderr, "ERROR: can't resolve '%s'\n", hostname); - return 0; - } - return ((struct in_addr *)host->h_addr_list[0])->s_addr; -} - -static int sam3aConnect(uint32_t ip, int port, int *complete) { - int fd, val = 1; - // - if (complete != NULL) - *complete = 0; - if (ip == 0 || ip == 0xffffffffUL || port < 1 || port > 65535) - return -1; - // - // yes, this is Linux-specific; you know what? i don't care. - if ((fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)) < 0) - return -1; - // - setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); - // - for (;;) { - struct sockaddr_in addr; - // - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = ip; - // - if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { - if (errno == EINPROGRESS) - break; // the process is started - if (errno != EINTR) { - close(fd); - return -1; - } - } else { - // connection complete - if (complete != NULL) - *complete = 1; - break; - } - } - // - return fd; -} - -// <0: error; 0: ok -static int sam3aDisconnect(int fd) { - if (fd >= 0) { - shutdown(fd, SHUT_RDWR); - return close(fd); - } - // - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// <0: error; >=0: bytes sent -static int sam3aSendBytes(int fd, const void *buf, int bufSize) { - const char *c = (const char *)buf; - int total = 0; - // - if (fd < 0 || (buf == NULL && bufSize > 0)) - return -1; - // - while (bufSize > 0) { - int wr = send(fd, c, bufSize, MSG_NOSIGNAL); - // - if (wr < 0) { - if (errno == EINTR) - continue; // interrupted by signal - if (errno == EAGAIN || errno == EWOULDBLOCK) { - // bufSize is too big - if (bufSize == 1) - break; // can't send anything - // try to send a half of a buffer - if ((wr = sam3aSendBytes(fd, c, bufSize / 2)) < 0) - return wr; // error - } else { - return -1; // alas - } - } - // - if (wr == 0) - break; // can't send anything - c += wr; - bufSize -= wr; - total += wr; - } - // - return total; -} - -/* <0: error; >=0: bytes received */ -/* note that you should call this function when there is some bytes to read, so - * 0 means 'connection closed' */ -/* -static int sam3aReceive (int fd, void *buf, int bufSize) { - char *c = (char *)buf; - int total = 0; - // - if (fd < 0 || (buf == NULL && bufSize > 0)) return -1; - // - while (bufSize > 0) { - int av = sam3aBytesAvail(fd), rd; - // - if (av == 0) break; // no more - if (av > bufSize) av = bufSize; - rd = recv(fd, c, av, 0); - if (rd < 0) { - if (errno == EINTR) continue; // interrupted by signal - if (errno == EAGAIN || errno == EWOULDBLOCK) break; // the thing that -should not be return -1; // error - } - if (rd == 0) break; - c += rd; - bufSize -= rd; - total += rd; - } - // - return total; -} -*/ - -//////////////////////////////////////////////////////////////////////////////// -char *sam3PrintfVA(int *plen, const char *fmt, va_list app) { - char buf[1024], *p = buf; - int size = sizeof(buf) - 1, len = 0; - // - if (plen != NULL) - *plen = 0; - for (;;) { - va_list ap; - char *np; - int n; - // - va_copy(ap, app); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); - // - if (n > -1 && n < size) { - len = n; - break; - } - if (n > -1) - size = n + 1; - else - size *= 2; - if (p == buf) { - if ((p = malloc(size)) == NULL) - return NULL; - } else { - if ((np = realloc(p, size)) == NULL) { - free(p); - return NULL; - } - p = np; - } - } - // - if (p == buf) { - if ((p = malloc(len + 1)) == NULL) - return NULL; - memcpy(p, buf, len + 1); - } - if (plen != NULL) - *plen = len; - return p; -} - -__attribute__((format(printf, 2, 3))) char *sam3Printf(int *plen, - const char *fmt, ...) { - va_list ap; - char *res; - // - va_start(ap, fmt); - res = sam3PrintfVA(plen, fmt, ap); - va_end(ap); - // - return res; -} - -/* - * check if we have EOL in received socket data - * this function should be called when sam3aBytesAvail() result > 0 - * return: <0: error; 0: no EOL in bytes2check, else: # of bytes to EOL - * (including EOL itself) - */ -/* -static int sam3aCheckEOL (int fd, int bytes2check) { - char *d = dest; - // - if (bytes2check < 0 || fd < 0) return -1; - memset(dest, 0, maxSize); - while (maxSize > 1) { - char *e; - int rd = recv(fd, d, maxSize-1, MSG_PEEK); - // - if (rd < 0 && errno == EINTR) continue; // interrupted by signal - if (rd == 0) { - rd = recv(fd, d, 1, 0); - if (rd < 0 && errno == EINTR) continue; // interrupted by signal - if (d[0] == '\n') { - d[0] = 0; // remove '\n' - return 0; - } - } else { - if (rd < 0) return -1; // error or connection closed; alas - } - // check for EOL - d[maxSize-1] = 0; - if ((e = strchr(d, '\n')) != NULL) { - rd = e-d+1; // bytes to receive - if (sam3atcpReceive(fd, d, rd) < 0) return -1; // alas - d[rd-1] = 0; // remove '\n' - return 0; // done - } else { - // let's receive this part and go on - if (sam3atcpReceive(fd, d, rd) < 0) return -1; // alas - maxSize -= rd; - d += rd; - } - } - // alas, the string is too big - return -1; -} -*/ - -//////////////////////////////////////////////////////////////////////////////// -/* -int sam3audpSendToIP (uint32_t ip, int port, const void *buf, int bufSize) { - struct sockaddr_in addr; - int fd, res; - // - if (buf == NULL || bufSize < 1) return -1; - if (port < 1 || port > 65535) port = 7655; - // - if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - if (libsam3a_debug) fprintf(stderr, "ERROR: can't create socket\n"); - return -1; - } - // - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = ip; - // - res = sendto(fd, buf, bufSize, 0, (struct sockaddr *)&addr, sizeof(addr)); - // - if (res < 0) { - if (libsam3a_debug) { - res = errno; - fprintf(stderr, "UDP ERROR (%d): %s\n", res, strerror(res)); - } - res = -1; - } else { - if (libsam3a_debug) fprintf(stderr, "UDP: %d bytes sent\n", res); - } - // - close(fd); - // - return (res >= 0 ? 0 : -1); -} - - -int sam3audpSendTo (const char *hostname, int port, const void *buf, int -bufSize, uint32_t *ip) { struct hostent *host = NULL; - // - if (buf == NULL || bufSize < 1) return -1; - if (hostname == NULL || !hostname[0]) hostname = "localhost"; - if (port < 1 || port > 65535) port = 7655; - // - host = gethostbyname(hostname); - if (host == NULL || host->h_name == NULL || !host->h_name[0]) { - if (libsam3a_debug) fprintf(stderr, "ERROR: can't resolve '%s'\n", -hostname); return -1; - } - // - if (ip != NULL) *ip = ((struct in_addr *)host->h_addr)->s_addr; - return sam3audpSendToIP(((struct in_addr *)host->h_addr)->s_addr, port, buf, -bufSize); -} -*/ - -//////////////////////////////////////////////////////////////////////////////// -typedef struct SAMFieldList { - char *name; - char *value; - struct SAMFieldList *next; -} SAMFieldList; - -static void sam3aFreeFieldList(SAMFieldList *list) { - while (list != NULL) { - SAMFieldList *c = list; - // - list = list->next; - if (c->name != NULL) - free(c->name); - if (c->value != NULL) - free(c->value); - free(c); - } -} - -static void sam3aDumpFieldList(const SAMFieldList *list) { - for (; list != NULL; list = list->next) { - fprintf(stderr, "%s=[%s]\n", list->name, list->value); - } -} - -static const char *sam3aFindField(const SAMFieldList *list, const char *field) { - if (list != NULL && field != NULL) { - for (list = list->next; list != NULL; list = list->next) { - if (list->name != NULL && strcmp(field, list->name) == 0) - return list->value; - } - } - return NULL; -} - -static char *xstrdup(const char *s, int len) { - if (len >= 0) { - char *res = malloc(len + 1); - // - if (res != NULL) { - if (len > 0) - memcpy(res, s, len); - res[len] = 0; - } - // - return res; - } - // - return NULL; -} - -// returns NULL if there are no more tokens -static inline const char *xstrtokend(const char *s) { - while (*s && isspace(*s)) - ++s; - // - if (*s) { - char qch = 0; - // - while (*s) { - if (*s == qch) { - qch = 0; - } else if (*s == '"') { - qch = *s; - } else if (qch) { - if (*s == '\\' && s[1]) - ++s; - } else if (isspace(*s)) { - break; - } - ++s; - } - } else { - s = NULL; - } - // - return s; -} - -SAMFieldList *sam3aParseReply(const char *rep) { - SAMFieldList *first = NULL, *last, *c; - const char *p = rep, *e, *e1; - // - // first 2 words - while (*p && isspace(*p)) - ++p; - if ((e = xstrtokend(p)) == NULL) - return NULL; - if ((e1 = xstrtokend(e)) == NULL) - return NULL; - // - if ((first = last = c = malloc(sizeof(SAMFieldList))) == NULL) - return NULL; - c->next = NULL; - c->name = c->value = NULL; - if ((c->name = xstrdup(p, e - p)) == NULL) - goto error; - while (*e && isspace(*e)) - ++e; - if ((c->value = xstrdup(e, e1 - e)) == NULL) - goto error; - // - p = e1; - while (*p) { - while (*p && isspace(*p)) - ++p; - if ((e = xstrtokend(p)) == NULL) - break; // no more tokens - // - if (libsam3a_debug) - fprintf(stderr, "<%s>\n", p); - // - if ((c = malloc(sizeof(SAMFieldList))) == NULL) - return NULL; - c->next = NULL; - c->name = c->value = NULL; - last->next = c; - last = c; - // - if ((e1 = memchr(p, '=', e - p)) != NULL) { - // key=value - if ((c->name = xstrdup(p, e1 - p)) == NULL) - goto error; - if ((c->value = xstrdup(e1 + 1, e - e1 - 1)) == NULL) - goto error; - } else { - // only key (there is no such replies in SAMv3, but... - if ((c->name = xstrdup(p, e - p)) == NULL) - goto error; - if ((c->value = strdup("")) == NULL) - goto error; - } - p = e; - } - // - if (libsam3a_debug) - sam3aDumpFieldList(first); - // - return first; -error: - sam3aFreeFieldList(first); - return NULL; -} - -// example: -// r0: 'HELLO' -// r1: 'REPLY' -// field: NULL or 'RESULT' -// VALUE: NULL or 'OK' -// returns bool -int sam3aIsGoodReply(const SAMFieldList *list, const char *r0, const char *r1, - const char *field, const char *value) { - if (list != NULL && list->name != NULL && list->value != NULL) { - if (r0 != NULL && strcmp(r0, list->name) != 0) - return 0; - if (r1 != NULL && strcmp(r1, list->value) != 0) - return 0; - if (field != NULL) { - for (list = list->next; list != NULL; list = list->next) { - if (list->name == NULL || list->value == NULL) - return 0; // invalid list, heh - if (strcmp(field, list->name) == 0) { - if (value != NULL && strcmp(value, list->value) != 0) - return 0; - return 1; - } - } - } - return 1; - } - return 0; -} - -// NULL: error; else: list of fields -// first item is always 2-word reply, with first word in name and second in -// value -/* -SAMFieldList *sam3aReadReply (int fd) { - char rep[2048]; // should be enough for any reply - // - if (sam3atcpReceiveStr(fd, rep, sizeof(rep)) < 0) return NULL; - if (libsam3a_debug) fprintf(stderr, "SAM REPLY: [%s]\n", rep); - return sam3aParseReply(rep); -} -*/ - -//////////////////////////////////////////////////////////////////////////////// -// by Bob Jenkins -// public domain -// http://burtleburtle.net/bob/rand/smallprng.html -// -//////////////////////////////////////////////////////////////////////////////// -typedef struct { - uint32_t a, b, c, d; -} BJRandCtx; - -#define BJPRNG_ROT(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) - -static uint32_t bjprngRand(BJRandCtx *x) { - uint32_t e; - /* original: - e = x->a-BJPRNG_ROT(x->b, 27); - x->a = x->b^BJPRNG_ROT(x->c, 17); - x->b = x->c+x->d; - x->c = x->d+e; - x->d = e+x->a; - */ - /* better, but slower at least in idiotic m$vc */ - e = x->a - BJPRNG_ROT(x->b, 23); - x->a = x->b ^ BJPRNG_ROT(x->c, 16); - x->b = x->c + BJPRNG_ROT(x->d, 11); - x->c = x->d + e; - x->d = e + x->a; - // - return x->d; -} - -static void bjprngInit(BJRandCtx *x, uint32_t seed) { - x->a = 0xf1ea5eed; - x->b = x->c = x->d = seed; - for (int i = 0; i < 20; ++i) - bjprngRand(x); -} - -static inline uint32_t hashint(uint32_t a) { - a -= (a << 6); - a ^= (a >> 17); - a -= (a << 9); - a ^= (a << 4); - a -= (a << 3); - a ^= (a << 10); - a ^= (a >> 15); - return a; -} - -static uint32_t genSeed(void) { - volatile uint32_t seed = 1; - uint32_t res; -#ifndef WIN32 - struct sysinfo sy; - pid_t pid = getpid(); - // - sysinfo(&sy); - res = hashint((uint32_t)pid) ^ hashint((uint32_t)time(NULL)) ^ - hashint((uint32_t)sy.sharedram) ^ hashint((uint32_t)sy.bufferram) ^ - hashint((uint32_t)sy.uptime); -#else - res = hashint((uint32_t)GetCurrentProcessId()) ^ - hashint((uint32_t)GetTickCount()); -#endif - res += __sync_fetch_and_add(&seed, 1); - // - return hashint(res); -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aGenChannelName(char *dest, int minlen, int maxlen) { - BJRandCtx rc; - int len; - // - if (dest == NULL || minlen < 1 || maxlen < minlen || minlen > 65536 || - maxlen > 65536) - return -1; - bjprngInit(&rc, genSeed()); - len = minlen + (bjprngRand(&rc) % (maxlen - minlen + 1)); - while (len-- > 0) { - int ch = bjprngRand(&rc) % 64; - // - if (ch >= 0 && ch < 10) - ch += '0'; - else if (ch >= 10 && ch < 36) - ch += 'A' - 10; - else if (ch >= 36 && ch < 62) - ch += 'a' - 36; - else if (ch == 62) - ch = '-'; - else if (ch == 63) - ch = '_'; - else if (ch > 64) - abort(); - *dest++ = ch; - } - *dest++ = 0; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aIsActiveSession(const Sam3ASession *ses) { - return (ses != NULL && ses->fd >= 0 && !ses->cancelled); -} - -int sam3aIsActiveConnection(const Sam3AConnection *conn) { - return (conn != NULL && conn->fd >= 0 && !conn->cancelled); -} - -//////////////////////////////////////////////////////////////////////////////// -static inline void strcpyerrs(Sam3ASession *ses, const char *errstr) { - // memset(ses->error, 0, sizeof(ses->error)); - ses->error[sizeof(ses->error) - 1] = 0; - if (errstr != NULL) - strncpy(ses->error, errstr, sizeof(ses->error) - 1); -} - -static inline void strcpyerrc(Sam3AConnection *conn, const char *errstr) { - // memset(conn->error, 0, sizeof(conn->error)); - conn->error[sizeof(conn->error) - 1] = 0; - if (errstr != NULL) - strncpy(conn->error, errstr, sizeof(conn->error) - 1); -} - -static void connDisconnect(Sam3AConnection *conn) { - conn->cbAIOProcessorR = conn->cbAIOProcessorW = NULL; - if (conn->aio.data != NULL) { - free(conn->aio.data); - conn->aio.data = NULL; - } - if (!conn->cancelled && conn->fd >= 0) { - conn->cancelled = 1; - shutdown(conn->fd, SHUT_RDWR); - if (conn->callDisconnectCB && conn->cb.cbDisconnected != NULL) - conn->cb.cbDisconnected(conn); - } -} - -static void sesDisconnect(Sam3ASession *ses) { - ses->cbAIOProcessorR = ses->cbAIOProcessorW = NULL; - if (ses->aio.data != NULL) { - free(ses->aio.data); - ses->aio.data = NULL; - } - if (!ses->cancelled && ses->fd >= 0) { - ses->cancelled = 1; - shutdown(ses->fd, SHUT_RDWR); - for (Sam3AConnection *c = ses->connlist; c != NULL; c = c->next) - connDisconnect(c); - if (ses->callDisconnectCB && ses->cb.cbDisconnected != NULL) - ses->cb.cbDisconnected(ses); - } -} - -static void sesError(Sam3ASession *ses, const char *errstr) { - if (errstr == NULL || !errstr[0]) - errstr = "I2P_ERROR"; - strcpyerrs(ses, errstr); - if (ses->cb.cbError != NULL) - ses->cb.cbError(ses); - sesDisconnect(ses); -} - -static void connError(Sam3AConnection *conn, const char *errstr) { - if (errstr == NULL || !errstr[0]) - errstr = "I2P_ERROR"; - strcpyerrc(conn, errstr); - if (conn->cb.cbError != NULL) - conn->cb.cbError(conn); - connDisconnect(conn); -} - -//////////////////////////////////////////////////////////////////////////////// -static int aioSender(int fd, Sam3AIO *aio) { - int wr = sam3aSendBytes(fd, aio->data + aio->dataPos, - aio->dataUsed - aio->dataPos); - // - if (wr < 0) - return -1; - aio->dataPos += wr; - return 0; -} - -// dataUsed: max line size (with '\n') -// dataSize: must be at least (dataUsed+1) -static int aioLineReader(int fd, Sam3AIO *aio) { - // - for (;;) { - int av = sam3aBytesAvail(fd), rd; - // - if (av < 0) - return -1; - if (av == 0) - return 0; // do nothing - if (aio->dataPos >= aio->dataUsed - 1) - return -1; // line too long - if ((rd = (aio->dataUsed - 1) - aio->dataPos) > av) - rd = av; - if ((rd = recv(fd, aio->data + aio->dataPos, rd, MSG_PEEK)) < 0) { - if (errno == EINTR) - continue; - return -1; - } - if (rd == 0) - return 0; // do nothing - // now look for '\n' - for (int f = aio->dataPos; f < aio->dataPos + rd; ++f) { - if (aio->data[f] == '\n') { - // got it! - if (recv(fd, aio->data + aio->dataPos, f - aio->dataPos + 1, 0) != - f + 1) - return -1; // the thing that should not be - aio->data[f] = 0; // convert to asciiz - aio->dataUsed = aio->dataPos = f; // length - return 1; // '\n' found! - } - if (!aio->data[f]) - return -1; // there should not be zero bytes - } - // no '\n' found - if (recv(fd, aio->data + aio->dataPos, rd, 0) != rd) - return -1; // the thing that should not be - aio->dataPos += rd; - } -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioSesCmdReplyReader(Sam3ASession *ses) { - int res = aioLineReader(ses->fd, &ses->aio); - // - if (res < 0) { - sesError(ses, "IO_ERROR"); - return; - } - if (res > 0) { - // we got full line - if (libsam3a_debug) - fprintf(stderr, "CMDREPLY: %s\n", ses->aio.data); - if (ses->aio.cbReplyCheckSes != NULL) - ses->aio.cbReplyCheckSes(ses); - } -} - -static void aioSesCmdSender(Sam3ASession *ses) { - if (ses->aio.dataPos < ses->aio.dataUsed) { - if (aioSender(ses->fd, &ses->aio) < 0) { - sesError(ses, "IO_ERROR"); - return; - } - } - // - if (ses->aio.dataPos == ses->aio.dataUsed) { - // hello sent, now wait for reply - // 2048 bytes of reply line should be enough - if (ses->aio.dataSize < 2049) { - char *n = realloc(ses->aio.data, 2049); - // - if (n == NULL) { - sesError(ses, "MEMORY_ERROR"); - return; - } - ses->aio.data = n; - ses->aio.dataSize = 2049; - } - ses->aio.dataUsed = 2048; - ses->aio.dataPos = 0; - ses->cbAIOProcessorR = aioSesCmdReplyReader; - ses->cbAIOProcessorW = NULL; - } -} - -static __attribute__((format(printf, 3, 4))) int -aioSesSendCmdWaitReply(Sam3ASession *ses, void (*cbCheck)(Sam3ASession *ses), - const char *fmt, ...) { - va_list ap; - char *str; - int len; - // - va_start(ap, fmt); - str = sam3PrintfVA(&len, fmt, ap); - va_end(ap); - // - if (str == NULL) - return -1; - if (ses->aio.data != NULL) - free(ses->aio.data); - ses->aio.data = str; - ses->aio.dataUsed = len; - ses->aio.dataSize = len + 1; - ses->aio.dataPos = 0; - ses->aio.cbReplyCheckSes = cbCheck; - ses->cbAIOProcessorR = NULL; - ses->cbAIOProcessorW = aioSesCmdSender; - // - if (libsam3a_debug) - fprintf(stderr, "CMD: %s", str); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioSesHelloChecker(Sam3ASession *ses) { - SAMFieldList *rep = sam3aParseReply(ses->aio.data); - // - if (rep != NULL && sam3aIsGoodReply(rep, "HELLO", "REPLY", "RESULT", "OK") && - sam3aIsGoodReply(rep, NULL, NULL, "VERSION", "3.0")) { - ses->cbAIOProcessorR = ses->cbAIOProcessorW = NULL; - sam3aFreeFieldList(rep); - if (ses->aio.udata != NULL) { - void (*cbComplete)(Sam3ASession * ses) = ses->aio.udata; - // - cbComplete(ses); - } - } else { - sam3aFreeFieldList(rep); - sesError(ses, NULL); - } -} - -static int sam3aSesStartHandshake(Sam3ASession *ses, - void (*cbComplete)(Sam3ASession *ses)) { - if (cbComplete != NULL) - ses->aio.udata = cbComplete; - if (aioSesSendCmdWaitReply(ses, aioSesHelloChecker, "%s\n", - "HELLO VERSION MIN=3.0 MAX=3.0") < 0) - return -1; - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioSesNameMeChecker(Sam3ASession *ses) { - SAMFieldList *rep = sam3aParseReply(ses->aio.data); - const char *v = NULL; - // - if (rep == NULL) { - sesError(ses, NULL); - return; - } - if (!sam3aIsGoodReply(rep, "NAMING", "REPLY", "RESULT", "OK") || - (v = sam3aFindField(rep, "VALUE")) == NULL || - strlen(v) != SAM3A_PUBKEY_SIZE) { - // if (libsam3a_debug) fprintf(stderr, "sam3aCreateSession: invalid NAMING - // reply (%d)...\n", (v != NULL ? strlen(v) : -1)); - if ((v = sam3aFindField(rep, "RESULT")) != NULL && strcmp(v, "OK") == 0) - v = NULL; - sesError(ses, v); - sam3aFreeFieldList(rep); - return; - } - strcpy(ses->pubkey, v); - sam3aFreeFieldList(rep); - // - ses->cbAIOProcessorR = ses->cbAIOProcessorW = NULL; - ses->callDisconnectCB = 1; - if (ses->cb.cbCreated != NULL) - ses->cb.cbCreated(ses); -} - -static void aioSesCreateChecker(Sam3ASession *ses) { - SAMFieldList *rep = sam3aParseReply(ses->aio.data); - const char *v; - // - if (rep == NULL) { - sesError(ses, NULL); - return; - } - if (!sam3aIsGoodReply(rep, "SESSION", "STATUS", "RESULT", "OK") || - (v = sam3aFindField(rep, "DESTINATION")) == NULL || - strlen(v) != SAM3A_PRIVKEY_SIZE) { - sam3aFreeFieldList(rep); - if ((v = sam3aFindField(rep, "RESULT")) != NULL && strcmp(v, "OK") == 0) - v = NULL; - sesError(ses, v); - return; - } - // ok - // fprintf(stderr, "\nPK: %s\n", v); - strcpy(ses->privkey, v); - sam3aFreeFieldList(rep); - // get our public key - if (aioSesSendCmdWaitReply(ses, aioSesNameMeChecker, "%s\n", - "NAMING LOOKUP NAME=ME") < 0) { - sesError(ses, "MEMORY_ERROR"); - } -} - -// handshake for SESSION CREATE complete -static void aioSesHandshacked(Sam3ASession *ses) { - static const char *typenames[3] = {"RAW", "DATAGRAM", "STREAM"}; - // - if (aioSesSendCmdWaitReply( - ses, aioSesCreateChecker, - "SESSION CREATE STYLE=%s ID=%s DESTINATION=%s%s%s\n", - typenames[(int)ses->type], ses->channel, ses->privkey, - (ses->params != NULL ? " " : ""), - (ses->params != NULL ? ses->params : "")) < 0) { - sesError(ses, "MEMORY_ERROR"); - } -} - -static void aioSesConnected(Sam3ASession *ses) { - int res; - socklen_t len = sizeof(res); - // - if (getsockopt(ses->fd, SOL_SOCKET, SO_ERROR, &res, &len) == 0 && res == 0) { - // ok, connected - if (sam3aSesStartHandshake(ses, NULL) < 0) - sesError(ses, NULL); - } else { - // connection error - sesError(ses, "CONNECTION_ERROR"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aCreateSessionEx(Sam3ASession *ses, const Sam3ASessionCallbacks *cb, - const char *hostname, int port, const char *privkey, - Sam3ASessionType type, const char *params, - int timeoutms) { - if (ses != NULL) { - // int complete = 0; - // - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - if (cb != NULL) - ses->cb = *cb; - if (hostname == NULL || !hostname[0]) - hostname = "127.0.0.1"; - if (port < 0 || port > 65535) - goto error; - if (privkey != NULL && strlen(privkey) != SAM3A_PRIVKEY_SIZE) - goto error; - if ((int)type < 0 || (int)type > 2) - goto error; - if (privkey == NULL) - privkey = "TRANSIENT"; - strcpy(ses->privkey, privkey); - if (params != NULL && (ses->params = strdup(params)) == NULL) - goto error; - ses->timeoutms = timeoutms; - // - if (!port) - port = DEFAULT_TCP_PORT; - ses->type = type; - ses->port = (type == SAM3A_SESSION_STREAM ? port : DEFAULT_UDP_PORT); - if ((ses->ip = sam3aResolveHost(hostname)) == 0) - goto error; - sam3aGenChannelName(ses->channel, 32, 64); - if (libsam3a_debug) - fprintf(stderr, "sam3aCreateSession: channel=[%s]\n", ses->channel); - // - ses->aio.udata = aioSesHandshacked; - ses->cbAIOProcessorW = aioSesConnected; - if ((ses->fd = sam3aConnect(ses->ip, port, NULL)) < 0) - goto error; - /* - if (complete) { - ses->cbAIOProcessorW(ses); - if (!sam3aIsActiveSession(ses)) return -1; - } - */ - // - return 0; // ok, connection process initiated - error: - if (ses->fd >= 0) - sam3aDisconnect(ses->fd); - if (ses->params != NULL) - free(ses->params); - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aCancelSession(Sam3ASession *ses) { - if (ses != NULL) { - sesDisconnect(ses); - return 0; - } - return -1; -} - -int sam3aCloseSession(Sam3ASession *ses) { - if (ses != NULL) { - sam3aCancelSession(ses); - while (ses->connlist != NULL) - sam3aCloseConnection(ses->connlist); - if (ses->cb.cbDestroy != NULL) - ses->cb.cbDestroy(ses); - if (ses->params != NULL) { - free(ses->params); - ses->params = NULL; - } - memset(ses, 0, sizeof(Sam3ASession)); - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioSesKeyGenChecker(Sam3ASession *ses) { - SAMFieldList *rep = sam3aParseReply(ses->aio.data); - // - if (rep == NULL) { - sesError(ses, NULL); - return; - } - if (sam3aIsGoodReply(rep, "DEST", "REPLY", NULL, NULL)) { - const char *pub = sam3aFindField(rep, "PUB"), - *priv = sam3aFindField(rep, "PRIV"); - // - if (pub != NULL && strlen(pub) == SAM3A_PUBKEY_SIZE && priv != NULL && - strlen(priv) == SAM3A_PRIVKEY_SIZE) { - strcpy(ses->pubkey, pub); - strcpy(ses->privkey, priv); - sam3aFreeFieldList(rep); - if (ses->cb.cbCreated != NULL) - ses->cb.cbCreated(ses); - sam3aCancelSession(ses); - return; - } - } - sam3aFreeFieldList(rep); - sesError(ses, NULL); -} - -// handshake for SESSION CREATE complete -static void aioSesKeyGenHandshacked(Sam3ASession *ses) { - if (aioSesSendCmdWaitReply(ses, aioSesKeyGenChecker, "%s\n", - "DEST GENERATE") < 0) { - sesError(ses, "MEMORY_ERROR"); - } -} - -int sam3aGenerateKeysEx(Sam3ASession *ses, const Sam3ASessionCallbacks *cb, - const char *hostname, int port, int timeoutms) { - if (ses != NULL) { - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - if (cb != NULL) - ses->cb = *cb; - if (hostname == NULL || !hostname[0]) - hostname = "127.0.0.1"; - if (port < 0 || port > 65535) - goto error; - ses->timeoutms = timeoutms; - // - if (!port) - port = DEFAULT_TCP_PORT; - ses->port = port; - if ((ses->ip = sam3aResolveHost(hostname)) == 0) - goto error; - // - ses->aio.udata = aioSesKeyGenHandshacked; - ses->cbAIOProcessorW = aioSesConnected; - if ((ses->fd = sam3aConnect(ses->ip, port, NULL)) < 0) - goto error; - // - return 0; // ok, connection process initiated - error: - if (ses->fd >= 0) - sam3aDisconnect(ses->fd); - if (ses->params != NULL) - free(ses->params); - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioSesNameResChecker(Sam3ASession *ses) { - SAMFieldList *rep = sam3aParseReply(ses->aio.data); - // - if (rep == NULL) { - sesError(ses, NULL); - return; - } - if (sam3aIsGoodReply(rep, "NAMING", "REPLY", "RESULT", NULL)) { - const char *rs = sam3aFindField(rep, "RESULT"), - *pub = sam3aFindField(rep, "VALUE"); - // - if (strcmp(rs, "OK") == 0) { - if (pub != NULL && strlen(pub) == SAM3A_PUBKEY_SIZE) { - strcpy(ses->destkey, pub); - sam3aFreeFieldList(rep); - if (ses->cb.cbCreated != NULL) - ses->cb.cbCreated(ses); - sam3aCancelSession(ses); - return; - } - sam3aFreeFieldList(rep); - sesError(ses, NULL); - } else { - sesError(ses, rs); - sam3aFreeFieldList(rep); - } - } -} - -// handshake for SESSION CREATE complete -static void aioSesNameResHandshacked(Sam3ASession *ses) { - if (aioSesSendCmdWaitReply(ses, aioSesNameResChecker, - "NAMING LOOKUP NAME=%s\n", ses->params) < 0) { - sesError(ses, "MEMORY_ERROR"); - } -} - -int sam3aNameLookupEx(Sam3ASession *ses, const Sam3ASessionCallbacks *cb, - const char *hostname, int port, const char *name, - int timeoutms) { - if (ses != NULL) { - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - if (cb != NULL) - ses->cb = *cb; - if (name == NULL || !name[0] || - (name[0] && toupper(name[0]) == 'M' && name[1] && - toupper(name[1]) == 'E' && (!name[2] || isspace(name[2])))) - goto error; - if (hostname == NULL || !hostname[0]) - hostname = "127.0.0.1"; - if (port < 0 || port > 65535) - goto error; - if ((ses->params = strdup(name)) == NULL) - goto error; - ses->timeoutms = timeoutms; - // - if (!port) - port = DEFAULT_TCP_PORT; - ses->port = port; - if ((ses->ip = sam3aResolveHost(hostname)) == 0) - goto error; - // - ses->aio.udata = aioSesNameResHandshacked; - ses->cbAIOProcessorW = aioSesConnected; - if ((ses->fd = sam3aConnect(ses->ip, port, NULL)) < 0) - goto error; - // - return 0; // ok, connection process initiated - error: - if (ses->fd >= 0) - sam3aDisconnect(ses->fd); - if (ses->params != NULL) - free(ses->params); - memset(ses, 0, sizeof(Sam3ASession)); - ses->fd = -1; - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioConnCmdReplyReader(Sam3AConnection *conn) { - int res = aioLineReader(conn->fd, &conn->aio); - // - if (res < 0) { - connError(conn, "IO_ERROR"); - return; - } - if (res > 0) { - // we got full line - if (libsam3a_debug) - fprintf(stderr, "CMDREPLY: %s\n", conn->aio.data); - if (conn->aio.cbReplyCheckConn != NULL) - conn->aio.cbReplyCheckConn(conn); - } -} - -static void aioConnCmdSender(Sam3AConnection *conn) { - if (conn->aio.dataPos < conn->aio.dataUsed) { - if (aioSender(conn->fd, &conn->aio) < 0) { - connError(conn, "IO_ERROR"); - return; - } - } - // - if (conn->aio.dataPos == conn->aio.dataUsed) { - // hello sent, now wait for reply - // 2048 bytes of reply line should be enough - if (conn->aio.dataSize < 2049) { - char *n = realloc(conn->aio.data, 2049); - // - if (n == NULL) { - connError(conn, "MEMORY_ERROR"); - return; - } - conn->aio.data = n; - conn->aio.dataSize = 2049; - } - conn->aio.dataUsed = 2048; - conn->aio.dataPos = 0; - conn->cbAIOProcessorR = aioConnCmdReplyReader; - conn->cbAIOProcessorW = NULL; - } -} - -static __attribute__((format(printf, 3, 4))) int -aioConnSendCmdWaitReply(Sam3AConnection *conn, - void (*cbCheck)(Sam3AConnection *conn), const char *fmt, - ...) { - va_list ap; - char *str; - int len; - // - va_start(ap, fmt); - str = sam3PrintfVA(&len, fmt, ap); - va_end(ap); - // - if (str == NULL) - return -1; - if (conn->aio.data != NULL) - free(conn->aio.data); - conn->aio.data = str; - conn->aio.dataUsed = len; - conn->aio.dataSize = len + 1; - conn->aio.dataPos = 0; - conn->aio.cbReplyCheckConn = cbCheck; - conn->cbAIOProcessorR = NULL; - conn->cbAIOProcessorW = aioConnCmdSender; - // - if (libsam3a_debug) - fprintf(stderr, "CMD: %s", str); - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioConnDataReader(Sam3AConnection *conn) { - char *buf = NULL; - int bufsz = 0; - // - while (sam3aIsActiveConnection(conn)) { - int av = sam3aBytesAvail(conn->fd), rd; - // - if (av < 0) { - if (buf != NULL) - free(buf); - connError(conn, "IO_ERROR"); - return; - } - if (av == 0) - av = 1; - if (bufsz < av) { - char *n = realloc(buf, av + 1); - // - if (n == NULL) { - if (buf != NULL) - free(buf); - connError(conn, "IO_ERROR"); - return; - } - buf = n; - bufsz = av; - } - memset(buf, 0, av + 1); - // - rd = recv(conn->fd, buf, av, 0); - // - if (rd < 0) { - if (errno == EINTR) - continue; // interrupted by signal - if (errno == EAGAIN || errno == EWOULDBLOCK) - break; // no more data - free(buf); - connError(conn, "IO_ERROR"); - return; - } - // - if (rd == 0) { - // connection closed - free(buf); - connDisconnect(conn); - return; - } - // - if (conn->cb.cbRead != NULL) - conn->cb.cbRead(conn, buf, rd); - } - free(buf); -} - -static void aioConnDataWriter(Sam3AConnection *conn) { - if (!sam3aIsActiveConnection(conn)) { - conn->aio.dataPos = conn->aio.dataUsed = 0; - return; - } - // - if (conn->aio.dataPos >= conn->aio.dataUsed) { - conn->aio.dataPos = conn->aio.dataUsed = 0; - return; - } - // - while (sam3aIsActiveConnection(conn) && - conn->aio.dataPos < conn->aio.dataUsed) { - int wr = sam3aSendBytes(conn->fd, conn->aio.data + conn->aio.dataPos, - conn->aio.dataUsed - conn->aio.dataPos); - // - if (wr < 0) { - connError(conn, "IO_ERROR"); - return; - } - if (wr == 0) - break; // can't write more bytes - conn->aio.dataPos += wr; - if (conn->aio.dataPos < conn->aio.dataUsed) { - memmove(conn->aio.data, conn->aio.data + conn->aio.dataPos, - conn->aio.dataUsed - conn->aio.dataPos); - conn->aio.dataUsed -= conn->aio.dataPos; - conn->aio.dataPos = 0; - } - } - // - if (conn->aio.dataPos >= conn->aio.dataUsed) { - conn->aio.dataPos = conn->aio.dataUsed = 0; - if (conn->cb.cbSent != NULL) - conn->cb.cbSent(conn); - if (conn->aio.dataSize > 8192) { - // shrink buffer - char *nn = realloc(conn->aio.data, 8192); - // - if (nn != NULL) { - conn->aio.data = nn; - conn->aio.dataSize = 8192; - } - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioConnHelloChecker(Sam3AConnection *conn) { - SAMFieldList *rep = sam3aParseReply(conn->aio.data); - // - if (rep != NULL && sam3aIsGoodReply(rep, "HELLO", "REPLY", "RESULT", "OK") && - sam3aIsGoodReply(rep, NULL, NULL, "VERSION", "3.0")) { - conn->cbAIOProcessorR = conn->cbAIOProcessorW = NULL; - sam3aFreeFieldList(rep); - if (conn->aio.udata != NULL) { - void (*cbComplete)(Sam3AConnection * conn) = conn->aio.udata; - // - cbComplete(conn); - } - } else { - sam3aFreeFieldList(rep); - connError(conn, NULL); - } -} - -static int sam3aConnStartHandshake(Sam3AConnection *conn, - void (*cbComplete)(Sam3AConnection *conn)) { - if (cbComplete != NULL) - conn->aio.udata = cbComplete; - if (aioConnSendCmdWaitReply(conn, aioConnHelloChecker, "%s\n", - "HELLO VERSION MIN=3.0 MAX=3.0") < 0) - return -1; - return 0; -} - -static void aioConnConnected(Sam3AConnection *conn) { - int res; - socklen_t len = sizeof(res); - // - if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &res, &len) == 0 && res == 0) { - // ok, connected - if (sam3aConnStartHandshake(conn, NULL) < 0) - connError(conn, NULL); - } else { - // connection error - connError(conn, "CONNECTION_ERROR"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioConnConnectChecker(Sam3AConnection *conn) { - SAMFieldList *rep = sam3aParseReply(conn->aio.data); - // - if (rep == NULL) { - connError(conn, NULL); - return; - } - if (!sam3aIsGoodReply(rep, "STREAM", "STATUS", "RESULT", "OK")) { - const char *v = sam3aFindField(rep, "RESULT"); - // - connError(conn, v); - sam3aFreeFieldList(rep); - } else { - // no error - sam3aFreeFieldList(rep); - conn->callDisconnectCB = 1; - conn->cbAIOProcessorR = aioConnDataReader; - conn->cbAIOProcessorW = aioConnDataWriter; - conn->aio.dataPos = conn->aio.dataUsed = 0; - if (conn->cb.cbConnected != NULL) - conn->cb.cbConnected(conn); - // indicate that we are ready for new data - if (sam3aIsActiveConnection(conn) && conn->cb.cbSent != NULL) - conn->cb.cbSent(conn); - } -} - -// handshake for SESSION CREATE complete -static void aioConConnectHandshacked(Sam3AConnection *conn) { - if (aioConnSendCmdWaitReply(conn, aioConnConnectChecker, - "STREAM CONNECT ID=%s DESTINATION=%s\n", - conn->ses->channel, conn->destkey) < 0) { - connError(conn, "MEMORY_ERROR"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -Sam3AConnection *sam3aStreamConnectEx(Sam3ASession *ses, - const Sam3AConnectionCallbacks *cb, - const char *destkey, int timeoutms) { - if (sam3aIsActiveSession(ses) && ses->type == SAM3A_SESSION_STREAM && - destkey != NULL && strlen(destkey) == SAM3A_PUBKEY_SIZE) { - Sam3AConnection *conn = calloc(1, sizeof(Sam3AConnection)); - // - if (conn == NULL) - return NULL; - if (cb != NULL) - conn->cb = *cb; - strcpy(conn->destkey, destkey); - conn->timeoutms = timeoutms; - // - conn->aio.udata = aioConConnectHandshacked; - conn->cbAIOProcessorW = aioConnConnected; - if ((conn->fd = sam3aConnect(ses->ip, ses->port, NULL)) < 0) - goto error; - // - conn->ses = ses; - conn->next = ses->connlist; - ses->connlist = conn; - return conn; // ok, connection process initiated - error: - if (conn->fd >= 0) - sam3aDisconnect(conn->fd); - memset(conn, 0, sizeof(Sam3AConnection)); - free(conn); - } - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -static void aioConnAcceptCheckerA(Sam3AConnection *conn) { - SAMFieldList *rep = sam3aParseReply(conn->aio.data); - // - if (rep != NULL || strlen(conn->aio.data) != SAM3A_PUBKEY_SIZE || - !sam3aIsValidPubKey(conn->aio.data)) { - sam3aFreeFieldList(rep); - connError(conn, NULL); - return; - } - sam3aFreeFieldList(rep); - strcpy(conn->destkey, conn->aio.data); - conn->callDisconnectCB = 1; - conn->cbAIOProcessorR = aioConnDataReader; - conn->cbAIOProcessorW = aioConnDataWriter; - conn->aio.dataPos = conn->aio.dataUsed = 0; - if (conn->cb.cbAccepted != NULL) - conn->cb.cbAccepted(conn); - // indicate that we are ready for new data - if (sam3aIsActiveConnection(conn) && conn->cb.cbSent != NULL) - conn->cb.cbSent(conn); -} - -static void aioConnAcceptChecker(Sam3AConnection *conn) { - SAMFieldList *rep = sam3aParseReply(conn->aio.data); - // - if (rep == NULL) { - connError(conn, NULL); - return; - } - if (!sam3aIsGoodReply(rep, "STREAM", "STATUS", "RESULT", "OK")) { - const char *v = sam3aFindField(rep, "RESULT"); - // - connError(conn, v); - sam3aFreeFieldList(rep); - } else { - // no error - sam3aFreeFieldList(rep); - // 2048 bytes of reply line should be enough - if (conn->aio.dataSize < 2049) { - char *n = realloc(conn->aio.data, 2049); - // - if (n == NULL) { - connError(conn, "MEMORY_ERROR"); - return; - } - conn->aio.data = n; - conn->aio.dataSize = 2049; - } - conn->aio.dataUsed = 2048; - conn->aio.dataPos = 0; - conn->cbAIOProcessorR = aioConnCmdReplyReader; - conn->cbAIOProcessorW = NULL; - conn->aio.cbReplyCheckConn = aioConnAcceptCheckerA; - } -} - -// handshake for SESSION CREATE complete -static void aioConAcceptHandshacked(Sam3AConnection *conn) { - if (aioConnSendCmdWaitReply(conn, aioConnAcceptChecker, - "STREAM ACCEPT ID=%s\n", - conn->ses->channel) < 0) { - connError(conn, "MEMORY_ERROR"); - } -} - -//////////////////////////////////////////////////////////////////////////////// -Sam3AConnection *sam3aStreamAcceptEx(Sam3ASession *ses, - const Sam3AConnectionCallbacks *cb, - int timeoutms) { - if (sam3aIsActiveSession(ses) && ses->type == SAM3A_SESSION_STREAM) { - Sam3AConnection *conn = calloc(1, sizeof(Sam3AConnection)); - // - if (conn == NULL) - return NULL; - if (cb != NULL) - conn->cb = *cb; - conn->timeoutms = timeoutms; - // - conn->aio.udata = aioConAcceptHandshacked; - conn->cbAIOProcessorW = aioConnConnected; - if ((conn->fd = sam3aConnect(ses->ip, ses->port, NULL)) < 0) - goto error; - // - conn->ses = ses; - conn->next = ses->connlist; - ses->connlist = conn; - return conn; // ok, connection process initiated - error: - if (conn->fd >= 0) - sam3aDisconnect(conn->fd); - memset(conn, 0, sizeof(Sam3AConnection)); - free(conn); - } - return NULL; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aSend(Sam3AConnection *conn, const void *data, int datasize) { - if (datasize == -1) - datasize = (data != NULL ? strlen((const char *)data) : 0); - // - if (sam3aIsActiveConnection(conn) && conn->callDisconnectCB && - conn->cbAIOProcessorW != NULL && - ((datasize > 0 && data != NULL) || datasize == 0)) { - // try to add data to send buffer - if (datasize > 0) { - if (conn->aio.dataUsed + datasize > conn->aio.dataSize) { - // we need more pepper! - int newsz = conn->aio.dataUsed + datasize; - char *nb = realloc(conn->aio.data, newsz); - // - if (nb == NULL) - return -1; // alas - conn->aio.data = nb; - conn->aio.dataSize = newsz; - } - // - memcpy(conn->aio.data + conn->aio.dataUsed, data, datasize); - conn->aio.dataUsed += datasize; - } - return 0; - } - // - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aIsHaveActiveConnections(const Sam3ASession *ses) { - if (sam3aIsActiveSession(ses)) { - for (const Sam3AConnection *c = ses->connlist; c != NULL; c = c->next) { - if (sam3aIsActiveConnection(c)) - return 1; - } - } - return 0; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aCancelConnection(Sam3AConnection *conn) { - if (conn != NULL) { - connDisconnect(conn); - return 0; - } - return -1; -} - -int sam3aCloseConnection(Sam3AConnection *conn) { - if (conn != NULL) { - sam3aCancelConnection(conn); - if (conn->cb.cbDestroy != NULL) - conn->cb.cbDestroy(conn); - for (Sam3AConnection *p = NULL, *c = conn->ses->connlist; c != NULL; - p = c, c = c->next) { - if (c == conn) { - // got it! - if (p == NULL) - c->ses->connlist = c->next; - else - p->next = c->next; - break; - } - } - if (conn->params != NULL) { - free(conn->params); - conn->params = NULL; - } - memset(conn, 0, sizeof(Sam3AConnection)); - free(conn); - } - return -1; -} - -//////////////////////////////////////////////////////////////////////////////// -int sam3aAddSessionToFDS(Sam3ASession *ses, int maxfd, fd_set *rds, - fd_set *wrs) { - if (ses != NULL) { - if (sam3aIsActiveSession(ses)) { - if (rds != NULL && ses->cbAIOProcessorR != NULL) { - if (maxfd < ses->fd) - maxfd = ses->fd; - FD_SET(ses->fd, rds); - } - // - if (wrs != NULL && ses->cbAIOProcessorW != NULL) { - if (maxfd < ses->fd) - maxfd = ses->fd; - FD_SET(ses->fd, wrs); - } - // - for (Sam3AConnection *c = ses->connlist; c != NULL; c = c->next) { - if (sam3aIsActiveConnection(c)) { - if (rds != NULL && c->cbAIOProcessorR != NULL) { - if (maxfd < c->fd) - maxfd = c->fd; - FD_SET(c->fd, rds); - } - // - if (wrs != NULL && c->cbAIOProcessorW != NULL) { - if (!c->callDisconnectCB || (c->aio.dataPos < c->aio.dataUsed)) - if (maxfd < c->fd) - maxfd = c->fd; - FD_SET(c->fd, wrs); - } - } - } - } - return maxfd; - } - // - return -1; -} - -void sam3aProcessSessionIO(Sam3ASession *ses, fd_set *rds, fd_set *wrs) { - if (sam3aIsActiveSession(ses)) { - if (ses->fd >= 0 && !ses->cancelled && ses->cbAIOProcessorR != NULL && - rds != NULL && FD_ISSET(ses->fd, rds)) - ses->cbAIOProcessorR(ses); - if (ses->fd >= 0 && !ses->cancelled && ses->cbAIOProcessorW != NULL && - wrs != NULL && FD_ISSET(ses->fd, wrs)) - ses->cbAIOProcessorW(ses); - // - for (Sam3AConnection *c = ses->connlist; c != NULL; c = c->next) { - if (c->fd >= 0 && !c->cancelled && c->cbAIOProcessorR != NULL && - rds != NULL && FD_ISSET(c->fd, rds)) - c->cbAIOProcessorR(c); - if (c->fd >= 0 && !c->cancelled && c->cbAIOProcessorW != NULL && - wrs != NULL && FD_ISSET(c->fd, wrs)) - c->cbAIOProcessorW(c); - } - } -} diff --git a/supportlibs/libsam3/src/libsam3a/libsam3a.h b/supportlibs/libsam3/src/libsam3a/libsam3a.h deleted file mode 100644 index dfd4c0cba..000000000 --- a/supportlibs/libsam3/src/libsam3a/libsam3a.h +++ /dev/null @@ -1,372 +0,0 @@ -/* async SAMv3 library - * - * This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#ifndef LIBSAM3A_H -#define LIBSAM3A_H - -#include -#include -#include - -#include - -#ifdef __MINGW32__ -//#include -#include -#include -#include -//#define SOCK_CLOEXEC O_CLOEXEC -//#define SOCK_NONBLOCK O_NONBLOCK -#define SOCK_CLOEXEC 02000000 -#define SOCK_NONBLOCK FIONBIO -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////////////// -/* - * TODO: - * [.] block sam3aClose*() in callbacks - */ - -//////////////////////////////////////////////////////////////////////////////// -extern int libsam3a_debug; - -//////////////////////////////////////////////////////////////////////////////// -#define SAM3A_HOST_DEFAULT (NULL) -#define SAM3A_PORT_DEFAULT (0) - -#define SAM3A_DESTINATION_TRANSIENT (NULL) - -#define SAM3A_PUBKEY_SIZE (516) -#define SAM3A_PRIVKEY_SIZE (884) - -//////////////////////////////////////////////////////////////////////////////// -extern uint64_t sam3atimeval2ms(const struct timeval *tv); -extern void sam3ams2timeval(struct timeval *tv, uint64_t ms); - -//////////////////////////////////////////////////////////////////////////////// -extern int sam3aIsValidPubKey(const char *key); -extern int sam3aIsValidPrivKey(const char *key); - -//////////////////////////////////////////////////////////////////////////////// -typedef struct Sam3ASession Sam3ASession; -typedef struct Sam3AConnection Sam3AConnection; - -typedef enum { - SAM3A_SESSION_RAW, - SAM3A_SESSION_DGRAM, - SAM3A_SESSION_STREAM -} Sam3ASessionType; - -typedef struct { - char *data; - int dataSize; - int dataUsed; - int dataPos; - void *udata; - union { - void (*cbReplyCheckSes)(Sam3ASession *ses); - void (*cbReplyCheckConn)(Sam3AConnection *conn); - }; -} Sam3AIO; - -/** session callback functions */ -typedef struct { - void (*cbError)(Sam3ASession *ses); /** called on error */ - void (*cbCreated)( - Sam3ASession *ses); /** called when we created the session */ - void (*cbDisconnected)(Sam3ASession *ses); /* call when closed; will called - only after cbCreated() */ - void (*cbDatagramRead)(Sam3ASession *ses, const void *buf, - int bufsize); /* called when we got a datagram; bufsize - >= 0; destkey set */ - void (*cbDestroy)(Sam3ASession *ses); /* called when fd is already closed, but - keys is not cleared */ -} Sam3ASessionCallbacks; - -struct Sam3ASession { - Sam3ASessionType type; /** session type */ - int fd; /** socket file descriptor */ - int cancelled; /** fd was shutdown()ed, but not closed yet */ - char privkey[SAM3A_PRIVKEY_SIZE + 1]; /** private key (asciiz) */ - char pubkey[SAM3A_PUBKEY_SIZE + 1]; /** public key (asciiz) */ - char channel[66]; /** channel name (asciiz) */ - char destkey[SAM3A_PUBKEY_SIZE + 1]; /** for DGRAM sessions (asciiz) */ - char error[64]; /** error message (asciiz) */ - uint32_t ip; /** ipv4 address of sam api interface */ - int port; /** UDP port for DRAM/RAW (can be 0) */ - Sam3AConnection *connlist; /** list of opened connections */ - - /** begin internal members */ - // for async i/o - Sam3AIO aio; - void (*cbAIOProcessorR)(Sam3ASession *ses); // internal - void (*cbAIOProcessorW)(Sam3ASession *ses); // internal - int callDisconnectCB; - char *params; // will be cleared only by sam3aCloseSession() - int timeoutms; - - /** end internal members */ - - Sam3ASessionCallbacks cb; - void *udata; -}; - -/** connection callbacks for data sockets */ -typedef struct { - /** called on error */ - void (*cbError)(Sam3AConnection *ct); - /** called when closed or only after cbConnected()/cbAccepted(); note that - * force disconnect is ok */ - void (*cbDisconnected)(Sam3AConnection *ct); - /** called when connected */ - void (*cbConnected)(Sam3AConnection *ct); - /** called instead of cbConnected() for sam3aStreamAccept*(), destkey filled - * with remote destination */ - void (*cbAccepted)(Sam3AConnection *ct); - /** send callback, data sent, can add new data; will be called after - * connect/accept */ - void (*cbSent)(Sam3AConnection *ct); - /** read callback, data read from socket (bufsize is always > 0) */ - void (*cbRead)(Sam3AConnection *ct, const void *buf, int bufsize); - /** fd already closed, but keys is not cleared */ - void (*cbDestroy)(Sam3AConnection *ct); -} Sam3AConnectionCallbacks; - -struct Sam3AConnection { - /** parent session */ - Sam3ASession *ses; - Sam3AConnection *next; - /** file descriptor */ - int fd; - int cancelled; // fd was shutdown()ed, but not closed yet - char destkey[SAM3A_PUBKEY_SIZE + 1]; // (asciiz) - char error[32]; // (asciiz) - - /** begin internal members */ - // for async i/o - Sam3AIO aio; - void (*cbAIOProcessorR)(Sam3AConnection *ct); // internal - void (*cbAIOProcessorW)(Sam3AConnection *ct); // internal - int callDisconnectCB; - char *params; // will be cleared only by sam3aCloseConnection() - int timeoutms; - /** end internal members */ - - /** callbacks */ - Sam3AConnectionCallbacks cb; - /** user data */ - void *udata; -}; - -//////////////////////////////////////////////////////////////////////////////// -/* - * check if session is active (i.e. have opened socket) - * returns bool - */ -extern int sam3aIsActiveSession(const Sam3ASession *ses); - -/* - * check if connection is active (i.e. have opened socket) - * returns bool - */ -extern int sam3aIsActiveConnection(const Sam3AConnection *conn); - -//////////////////////////////////////////////////////////////////////////////// -/* - * note, that return error codes indicates invalid structure, pointer or fd - * (i.e. immediate errors); all network errors indicated with cbError() callback - */ - -/* - * create SAM session - * pass NULL as hostname for 'localhost' and 0 as port for 7656 - * pass NULL as privkey to create TRANSIENT session - * 'params' can be NULL - * see http://www.i2p2.i2p/i2cp.html#options for common options, - * and http://www.i2p2.i2p/streaming.html#options for STREAM options - * if result<0: error, 'ses' fields are undefined, no need to call - * sam3aCloseSession() if result==0: ok, all 'ses' fields are filled - * TODO: don't clear 'error' field on error (and set it to something meaningful) - */ -extern int sam3aCreateSessionEx(Sam3ASession *ses, - const Sam3ASessionCallbacks *cb, - const char *hostname, int port, - const char *privkey, Sam3ASessionType type, - const char *params, int timeoutms); - -static inline int sam3aCreateSession(Sam3ASession *ses, - const Sam3ASessionCallbacks *cb, - const char *hostname, int port, - const char *privkey, - Sam3ASessionType type) { - return sam3aCreateSessionEx(ses, cb, hostname, port, privkey, type, NULL, -1); -} - -/* returns <0 on error, 0 if no, >0 if yes */ -extern int sam3aIsHaveActiveConnections(const Sam3ASession *ses); - -/* - * close SAM session (and all it's connections) - * returns <0 on error, 0 on ok - * 'ses' must be properly initialized - */ -extern int sam3aCloseSession(Sam3ASession *ses); - -/* - * cancel SAM session (and all it's connections), but don't free() or clear - * anything except fds returns <0 on error, 0 on ok 'ses' must be properly - * initialized - */ -extern int sam3aCancelSession(Sam3ASession *ses); - -/* - * open stream connection to 'destkey' endpoint - * 'destkey' is 516-byte public key (asciiz) - * returns <0 on error - * sets ses->error on memory or socket creation error - */ -extern Sam3AConnection *sam3aStreamConnectEx(Sam3ASession *ses, - const Sam3AConnectionCallbacks *cb, - const char *destkey, - int timeoutms); - -static inline Sam3AConnection * -sam3aStreamConnect(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb, - const char *destkey) { - return sam3aStreamConnectEx(ses, cb, destkey, -1); -} - -/* - * accepts stream connection and sets 'destkey' - * 'destkey' is 516-byte public key - * returns <0 on error, fd on ok - * you still have to call sam3aCloseSession() on failure - * sets ses->error on error - * note that there is no timeouts for now, but you can use sam3atcpSetTimeout*() - */ -extern Sam3AConnection *sam3aStreamAcceptEx(Sam3ASession *ses, - const Sam3AConnectionCallbacks *cb, - int timeoutms); - -static inline Sam3AConnection * -sam3aStreamAccept(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb) { - return sam3aStreamAcceptEx(ses, cb, -1); -} - -/* - * close SAM connection, remove it from session and free memory - * returns <0 on error, 0 on ok - * 'conn' must be properly initialized - * 'conn' is invalid after call - */ -extern int sam3aCloseConnection(Sam3AConnection *conn); - -/* - * cancel SAM connection, but don't free() or clear anything except fd - * returns <0 on error, 0 on ok - * 'conn' must be properly initialized - * 'conn' is invalid after call - */ -extern int sam3aCancelConnection(Sam3AConnection *conn); - -//////////////////////////////////////////////////////////////////////////////// -/* - * send data - * this function can be used in cbSent() callback - * - * return: <0: error; 0: ok - */ -extern int sam3aSend(Sam3AConnection *conn, const void *data, int datasize); - -/* - * sends datagram to 'destkey' endpoint - * 'destkey' is 516-byte public key - * returns <0 on error, 0 on ok - * you still have to call sam3aCloseSession() on failure - * sets ses->error on error - * don't send datagrams bigger than 31KB! - */ -extern int sam3aDatagramSend(Sam3ASession *ses, const char *destkey, - const void *buf, int bufsize); - -//////////////////////////////////////////////////////////////////////////////// -/* - * generate random channel name - * dest should be at least (maxlen+1) bytes big - */ -extern int sam3aGenChannelName(char *dest, int minlen, int maxlen); - -//////////////////////////////////////////////////////////////////////////////// -/* - * generate new keypair - * fills 'privkey' and 'pubkey' only - * you should call sam3aCloseSession() on 'ses' - * cbCreated callback will be called when keys generated - * returns <0 on error, 0 on ok - */ -extern int sam3aGenerateKeysEx(Sam3ASession *ses, - const Sam3ASessionCallbacks *cb, - const char *hostname, int port, int timeoutms); - -static inline int sam3aGenerateKeys(Sam3ASession *ses, - const Sam3ASessionCallbacks *cb, - const char *hostname, int port) { - return sam3aGenerateKeysEx(ses, cb, hostname, port, -1); -} - -/* - * do name lookup (something like gethostbyname()) - * fills 'destkey' only - * you should call sam3aCloseSession() on 'ses' - * cbCreated callback will be called when keys generated, ses->destkey will be - * set returns <0 on error, 0 on ok - */ -extern int sam3aNameLookupEx(Sam3ASession *ses, const Sam3ASessionCallbacks *cb, - const char *hostname, int port, const char *name, - int timeoutms); - -static inline int sam3aNameLookup(Sam3ASession *ses, - const Sam3ASessionCallbacks *cb, - const char *hostname, int port, - const char *name) { - return sam3aNameLookupEx(ses, cb, hostname, port, name, -1); -} - -//////////////////////////////////////////////////////////////////////////////// -/* - * append session fd to read and write sets if necessary - * adds all alive session connections too - * returns maxfd or -1 - * TODO: should keep fd count so it will not exceed FD_SETSIZE! - */ -extern int sam3aAddSessionToFDS(Sam3ASession *ses, int maxfd, fd_set *rds, - fd_set *wrs); - -/* - * process session i/o (and all session connections i/o) - * should be called after successful select() - */ -extern void sam3aProcessSessionIO(Sam3ASession *ses, fd_set *rds, fd_set *wrs); - -//////////////////////////////////////////////////////////////////////////////// -/* return malloc()ed buffer and len in 'plen' (if plen != NULL) */ -extern char *sam3PrintfVA(int *plen, const char *fmt, va_list app); -extern char *sam3Printf(int *plen, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/supportlibs/libsam3/test/libsam3/test_b32.c b/supportlibs/libsam3/test/libsam3/test_b32.c deleted file mode 100644 index 9a852853d..000000000 --- a/supportlibs/libsam3/test/libsam3/test_b32.c +++ /dev/null @@ -1,51 +0,0 @@ -/* This program is free software. It comes without any warranty, to - * the extent permitted by applicable law. You can redistribute it - * and/or modify it under the terms of the Do What The Fuck You Want - * To Public License, Version 2, as published by Sam Hocevar. See - * http://sam.zoy.org/wtfpl/COPYING for more details. - * - * I2P-Bote: - * 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV - * we are the Borg. */ -#include -#include -#include -#include - -#include "../../src/ext/tinytest.h" -#include "../../src/ext/tinytest_macros.h" -#include "../../src/libsam3/libsam3.h" - -static int testb32(const char *src, const char *res) { - size_t dlen = sam3Base32EncodedLength(strlen(src)), len; - char dest[128]; - // - len = sam3Base32Encode(dest, sizeof(dest), src, strlen(src)); - tt_int_op(len, ==, dlen); - tt_int_op(len, ==, strlen(res)); - tt_str_op(res, ==, dest); - return 1; - -end: - return 0; -} - -void test_b32_encode(void *data) { - (void)data; /* This testcase takes no data. */ - - tt_assert(testb32("", "")); - tt_assert(testb32("f", "my======")); - tt_assert(testb32("fo", "mzxq====")); - tt_assert(testb32("foo", "mzxw6===")); - tt_assert(testb32("foob", "mzxw6yq=")); - tt_assert(testb32("fooba", "mzxw6ytb")); - tt_assert(testb32("foobar", "mzxw6ytboi======")); - -end:; -} - -struct testcase_t b32_tests[] = {{ - "encode", - test_b32_encode, - }, - END_OF_TESTCASES}; diff --git a/supportlibs/libsam3/test/test.c b/supportlibs/libsam3/test/test.c deleted file mode 100644 index 9e7357962..000000000 --- a/supportlibs/libsam3/test/test.c +++ /dev/null @@ -1,12 +0,0 @@ -#include - -#include "../src/ext/tinytest.h" -#include "../src/ext/tinytest_macros.h" - -extern struct testcase_t b32_tests[]; - -struct testgroup_t test_groups[] = {{"b32/", b32_tests}, END_OF_GROUPS}; - -int main(int argc, const char **argv) { - return tinytest_main(argc, argv, test_groups); -}