remove own copy of libsam3

This commit is contained in:
sehraf 2020-11-27 15:44:49 +01:00
parent 719adaae9b
commit 59fa96eb5f
No known key found for this signature in database
GPG Key ID: DF09F6EAE356B2C6
24 changed files with 0 additions and 6036 deletions

View File

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

View File

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

View File

@ -1 +0,0 @@
../src/libsam3

View File

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

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#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;
}

View File

@ -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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#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;
}

View File

@ -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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef NO_FORKING
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#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 <vproc.h>
#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("<allocation failure>");
cp = result;
for (i = 0; i < len; ++i) {
*cp++ = "0123456789ABCDEF"[val[i] >> 4];
*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
}
*cp = 0;
return result;
}

View File

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

View File

@ -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_ : "<NULL>"; }, {}, \
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

File diff suppressed because it is too large Load Diff

View File

@ -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 <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#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

File diff suppressed because it is too large Load Diff

View File

@ -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 <stdarg.h>
#include <stdint.h>
#include <time.h>
#include <sys/types.h>
#ifdef __MINGW32__
//#include <winsock.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
//#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

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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};

View File

@ -1,12 +0,0 @@
#include <stddef.h>
#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);
}