From 47a4b726a3f218cfcbed9af85886169c63718d60 Mon Sep 17 00:00:00 2001 From: sehraf Date: Thu, 19 Nov 2020 17:12:15 +0100 Subject: [PATCH] update libsam3 --- supportlibs/libsam3/Makefile | 6 +- supportlibs/libsam3/README.md | 36 ++++++- supportlibs/libsam3/examples/sam3/streamcs.c | 87 ++++++++++++++++ supportlibs/libsam3/examples/sam3/streamss.c | 72 +++++++++++++ supportlibs/libsam3/src/libsam3/libsam3.c | 101 ++++++++++++------- supportlibs/libsam3/src/libsam3/libsam3.h | 34 +++++++ supportlibs/libsam3/src/libsam3a/libsam3a.c | 18 +++- supportlibs/libsam3/src/libsam3a/libsam3a.h | 11 ++ 8 files changed, 323 insertions(+), 42 deletions(-) create mode 100644 supportlibs/libsam3/examples/sam3/streamcs.c create mode 100644 supportlibs/libsam3/examples/sam3/streamss.c diff --git a/supportlibs/libsam3/Makefile b/supportlibs/libsam3/Makefile index fc6f52245..f8d92a090 100644 --- a/supportlibs/libsam3/Makefile +++ b/supportlibs/libsam3/Makefile @@ -16,7 +16,6 @@ OBJS := ${LIB_OBJS} ${TEST_OBJS} LIB := libsam3.a - all: build check check: libsam3-tests @@ -34,8 +33,11 @@ clean: rm -f libsam3-tests ${LIB} ${OBJS} examples/sam3/samtest %.o: %.c Makefile - ${CC} ${CFLAGS} -c $< -o $@ + ${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 index 98dfe4205..cd6b291a5 100644 --- a/supportlibs/libsam3/README.md +++ b/supportlibs/libsam3/README.md @@ -6,7 +6,7 @@ A C library for the [SAM v3 API](https://geti2p.net/en/docs/api/samv3). ## Development Status -Unmaintained, but PRs welcome! +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 @@ -16,3 +16,37 @@ Copy the two files from one of the following locations into your codebase: - `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/sam3/streamcs.c b/supportlibs/libsam3/examples/sam3/streamcs.c new file mode 100644 index 000000000..25bd22072 --- /dev/null +++ b/supportlibs/libsam3/examples/sam3/streamcs.c @@ -0,0 +1,87 @@ +/* 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/streamss.c b/supportlibs/libsam3/examples/sam3/streamss.c new file mode 100644 index 000000000..ffbc974da --- /dev/null +++ b/supportlibs/libsam3/examples/sam3/streamss.c @@ -0,0 +1,72 @@ +/* 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/src/libsam3/libsam3.c b/supportlibs/libsam3/src/libsam3/libsam3.c index 476372a0b..5a645806f 100644 --- a/supportlibs/libsam3/src/libsam3/libsam3.c +++ b/supportlibs/libsam3/src/libsam3/libsam3.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #include @@ -20,16 +19,27 @@ #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 - -#ifdef WINDOWS_SYS -#include -#endif // WINDOWS_SYS - +#endif //////////////////////////////////////////////////////////////////////////////// int libsam3_debug = 0; @@ -104,11 +114,6 @@ int sam3tcpConnectIP(uint32_t ip, int port) { } } // - // Set this for all outgoing SAM connections. Most SAM commands should be answered rather fast except CREATE SESSION maybe. - // This should be enough to let SAM establish a session. - sam3tcpSetTimeoutSend(fd, 5 * 60 * 1000); - sam3tcpSetTimeoutReceive(fd, 5 * 60 * 1000); - // setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); // if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { @@ -161,13 +166,8 @@ int sam3tcpConnect(const char *hostname, int port, uint32_t *ip) { // <0: error; 0: ok int sam3tcpDisconnect(int fd) { if (fd >= 0) { -#ifndef WINDOWS_SYS // ie UNIX - shutdown(fd, SHUT_RDWR); - return close(fd); -#else - return closesocket(fd); -#endif - + shutdown(fd, SHUT_RDWR); + return close(fd); } // return -1; @@ -823,6 +823,18 @@ int sam3CloseSession(Sam3Session *ses) { 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) { @@ -840,6 +852,7 @@ int sam3CreateSession(Sam3Session *ses, const char *hostname, int port, 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; @@ -936,8 +949,9 @@ Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey) { strcpyerr(ses, "IO_ERROR_SK"); goto error; } - if (sam3tcpPrintf(conn->fd, "STREAM CONNECT ID=%s DESTINATION=%s\n", - ses->channel, destkey) < 0) { + 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; } @@ -945,16 +959,18 @@ Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey) { strcpyerr(ses, "IO_ERROR"); goto error; } - 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); + 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) { @@ -1002,11 +1018,13 @@ Sam3Connection *sam3StreamAccept(Sam3Session *ses) { 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; + 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"); @@ -1040,6 +1058,14 @@ Sam3Connection *sam3StreamAccept(Sam3Session *ses) { 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; @@ -1060,8 +1086,9 @@ int sam3StreamForward(Sam3Session *ses, const char *hostname, int port) { strcpyerr(ses, "IO_ERROR_SK"); goto error; } - if (sam3tcpPrintf(ses->fwd_fd, "STREAM FORWARD ID=%s PORT=%d HOST=%s SILENT=true\n", - ses->channel, port, hostname) < 0) { + 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; } diff --git a/supportlibs/libsam3/src/libsam3/libsam3.h b/supportlibs/libsam3/src/libsam3/libsam3.h index 3eb261d89..16942f594 100644 --- a/supportlibs/libsam3/src/libsam3/libsam3.h +++ b/supportlibs/libsam3/src/libsam3/libsam3.h @@ -10,9 +10,19 @@ #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 @@ -138,6 +148,7 @@ typedef struct Sam3Session { 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 { @@ -166,6 +177,22 @@ 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 @@ -173,6 +200,13 @@ extern int sam3CreateSession(Sam3Session *ses, const char *hostname, int port, */ 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. diff --git a/supportlibs/libsam3/src/libsam3a/libsam3a.c b/supportlibs/libsam3/src/libsam3a/libsam3a.c index 40921e6ba..e5983b008 100644 --- a/supportlibs/libsam3/src/libsam3a/libsam3a.c +++ b/supportlibs/libsam3/src/libsam3a/libsam3a.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -22,13 +21,28 @@ #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; diff --git a/supportlibs/libsam3/src/libsam3a/libsam3a.h b/supportlibs/libsam3/src/libsam3a/libsam3a.h index 4ddec7952..dfd4c0cba 100644 --- a/supportlibs/libsam3/src/libsam3a/libsam3a.h +++ b/supportlibs/libsam3/src/libsam3a/libsam3a.h @@ -18,6 +18,17 @@ #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