mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
remove own copy of libsam3
This commit is contained in:
parent
719adaae9b
commit
59fa96eb5f
@ -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)
|
@ -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.
|
@ -1 +0,0 @@
|
||||
../src/libsam3
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
@ -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
@ -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
@ -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
|
@ -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};
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user