corrected the sample code and made them easier to build

This commit is contained in:
idk
2019-02-11 10:03:20 -05:00
parent c15b28b267
commit cbcefc71c4
21 changed files with 2209 additions and 1750 deletions

View File

@ -31,7 +31,8 @@ libsam3-tests: ${TEST_OBJS} ${LIB}
${CC} $^ -o $@
clean:
rm -f libsam3-tests ${LIB} ${OBJS}
rm -f libsam3-tests ${LIB} ${OBJS} examples/sam3/samtest
%.o: %.c Makefile
${CC} ${CFLAGS} -c $< -o $@

1
examples/libsam3 Symbolic link
View File

@ -0,0 +1 @@
/home/idk/local-manifest/crypto-manifest/i2p-manifest/libsam3/src/libsam3

24
examples/sam3/Makefile Normal file
View File

@ -0,0 +1,24 @@
CFLAGS := -Wall -g -O2 -std=gnu99
examples: example lookup dclient dserver sclient sserver
example:
${CC} ${CFLAGS} samtest.c -o samtest ../libsam3/libsam3.o
lookup:
${CC} ${CFLAGS} namelookup.c -o lookup ../libsam3/libsam3.o
dclient:
${CC} ${CFLAGS} dgramc.c -o datagram-client ../libsam3/libsam3.o
dserver:
${CC} ${CFLAGS} dgrams.c -o datagram-server ../libsam3/libsam3.o
sclient:
${CC} ${CFLAGS} streamc.c -o stream-client ../libsam3/libsam3.o
sserver:
${CC} ${CFLAGS} streams.c -o stream-server ../libsam3/libsam3.o
clean:
rm -f samtest lookup datagram-client datagram-server stream-client stream-server

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -14,23 +15,20 @@
#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 BIG (32000 - 1024)
#define KEYFILE "dgrams.key"
#define KEYFILE "dgrams.key"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3Session ses;
char buf[1024];
char destkey[517] = {0}; // 516 chars + \0
int sz;
//
//libsam3_debug = 1;
// libsam3_debug = 1;
//
if (argc < 2) {
FILE *fl = fopen(KEYFILE, "rb");
@ -55,7 +53,9 @@ int main (int argc, char *argv[]) {
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, NULL) < 0) {
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_DGRAM,
NULL) < 0) {
fprintf(stderr, "FATAL: can't create session\n");
return 1;
}
@ -66,7 +66,7 @@ ok:
goto error;
}
/** receive reply */
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf)-1)) < 0) {
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) {
fprintf(stderr, "ERROR: %s\n", ses.error);
goto error;
}
@ -76,16 +76,16 @@ ok:
//
#ifdef BIG
{
char *big = calloc(BIG+1024, sizeof(char));
char *big = calloc(BIG + 1024, sizeof(char));
/** generate random string */
sam3GenChannelName(big, BIG+1023, BIG+1023);
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) {
if ((sz = sam3DatagramReceive(&ses, big, BIG + 512)) < 0) {
free(big);
fprintf(stderr, "ERROR: %s\n", ses.error);
goto error;
@ -101,7 +101,7 @@ ok:
fprintf(stderr, "ERROR: %s\n", ses.error);
goto error;
}
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf)-1)) < 0) {
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) {
fprintf(stderr, "ERROR: %s\n", ses.error);
goto error;
}

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -14,28 +15,25 @@
#include "../libsam3/libsam3.h"
#define KEYFILE "dgrams.key"
#define KEYFILE "dgrams.key"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3Session ses;
char privkey[1024], pubkey[1024], buf[33*1024];
char privkey[1024], pubkey[1024], buf[33 * 1024];
/** quit command */
const char * quitstr = "quit";
const size_t quitlen = strlen(quistr);
const char *quitstr = "quit";
const size_t quitlen = strlen(quitstr);
/** reply response */
const char * replystr = "reply: ";
const char *replystr = "reply: ";
const size_t replylen = strlen(replystr);
FILE *fl;
//
//libsam3_debug = 1;
// libsam3_debug = 1;
//
/** generate new destination keypair */
printf("generating keys...\n");
if (sam3GenerateKeys(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT) < 0) {
@ -47,7 +45,8 @@ int main (int argc, char *argv[]) {
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, NULL) < 0) {
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, privkey,
SAM3_SESSION_DGRAM, NULL) < 0) {
fprintf(stderr, "FATAL: can't create session\n");
return 1;
}
@ -70,12 +69,12 @@ int main (int argc, char *argv[]) {
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;
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, datagarmMaxLen) < 0)) {
if ((sz = sam3DatagramReceive(&ses, datagramBuf, datagramMaxLen) < 0)) {
fprintf(stderr, "ERROR: %s\n", ses.error);
goto error;
}
@ -89,12 +88,13 @@ int main (int argc, char *argv[]) {
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) {
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 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 */

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <stdio.h>
#include <stdlib.h>
@ -13,8 +14,7 @@
#include "../libsam3/libsam3.h"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3Session ses;
//
if (argc < 2) {
@ -23,9 +23,11 @@ int main (int argc, char *argv[]) {
}
/** for each name in arguments ... */
for (int n = 1; n < argc; ++n) {
fprintf(stdout, "%s ... ", argv[n]); fflush(stdout);
fprintf(stdout, "%s ... ", argv[n]);
fflush(stdout);
/** do oneshot name lookup */
if (sam3NameLookup(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, argv[n]) >= 0) {
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);

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -14,19 +15,22 @@
#include "../libsam3/libsam3.h"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
int fd;
SAMFieldList *rep = NULL;
const char *v;
//
if ((fd = sam3Handshake(NULL, 0, NULL)) < 0) return 1;
if ((fd = sam3Handshake(NULL, 0, NULL)) < 0)
return 1;
//
if (sam3tcpPrintf(fd, "DEST GENERATE\n") < 0) goto error;
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;
// 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");

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -14,16 +15,14 @@
#include "../libsam3/libsam3.h"
#define KEYFILE "streams.key"
#define KEYFILE "streams.key"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3Session ses;
Sam3Connection *conn;
char cmd[1024], destkey[517]; // 516 chars + \0
//
//libsam3_debug = 1;
// libsam3_debug = 1;
//
memset(destkey, 0, sizeof(destkey));
//
@ -50,7 +49,9 @@ int main (int argc, char *argv[]) {
ok:
printf("creating session...\n");
// create TRANSIENT session
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, NULL) < 0) {
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM,
NULL) < 0) {
fprintf(stderr, "FATAL: can't create session\n");
return 1;
}
@ -64,12 +65,15 @@ ok:
//
// 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;
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;
if (sam3tcpPrintf(conn->fd, "quit\n") < 0)
goto error;
//
sam3CloseConnection(conn);
sam3CloseSession(&ses);

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -14,20 +15,20 @@
#include "../libsam3/libsam3.h"
#define KEYFILE "streams.key"
#define KEYFILE "streams.key"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3Session ses;
Sam3Connection *conn;
FILE *fl;
//
//libsam3_debug = 1;
// 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, NULL) < 0) {
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM,
NULL) < 0) {
fprintf(stderr, "FATAL: can't create session\n");
return 1;
}
@ -50,11 +51,14 @@ int main (int argc, char *argv[]) {
for (;;) {
char cmd[256];
//
if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0) goto error;
if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0)
goto error;
printf("cmd: [%s]\n", cmd);
if (strcmp(cmd, "quit") == 0) break;
if (strcmp(cmd, "quit") == 0)
break;
// echo command
if (sam3tcpPrintf(conn->fd, "re: %s\n", cmd) < 0) goto error;
if (sam3tcpPrintf(conn->fd, "re: %s\n", cmd) < 0)
goto error;
}
//
sam3CloseSession(&ses);

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -18,97 +19,97 @@
#include "../libsam3a/libsam3a.h"
////////////////////////////////////////////////////////////////////////////////
static void scbErrorClose (Sam3ASession *ses) {
fprintf(stderr, "\n===============================\nSESION_ERROR: [%s]\n===============================\n", ses->error);
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);
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,
.cbError = scbErrorClose,
.cbCreated = scbNRCreated,
.cbDisconnected = NULL,
.cbDatagramRead = NULL,
.cbDestroy = NULL,
};
////////////////////////////////////////////////////////////////////////////////
static void scbKGCreated (Sam3ASession *ses) {
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,
.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 scbError(Sam3ASession *ses) {
fprintf(stderr,
"\n===============================\nSESION_ERROR: "
"[%s]\n===============================\n",
ses->error);
}
static void scbCreated (Sam3ASession *ses) {
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 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 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 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,
.cbError = scbError,
.cbCreated = scbCreated,
.cbDisconnected = scbDisconnected,
.cbDatagramRead = scbDGramRead,
.cbDestroy = scbDestroy,
};
////////////////////////////////////////////////////////////////////////////////
#define HOST SAM3A_HOST_DEFAULT
#define HOST SAM3A_HOST_DEFAULT
//#define HOST "google.com"
int main (int argc, char *argv[]) {
int main(int argc, char *argv[]) {
Sam3ASession ses, snr, skg;
//
//libsam3a_debug = 1;
// libsam3a_debug = 1;
//
if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT, SAM3A_DESTINATION_TRANSIENT, SAM3A_SESSION_STREAM) < 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;
}
@ -126,7 +127,8 @@ int main (int argc, char *argv[]) {
return 1;
}
// while we have sessions ...
while (sam3aIsActiveSession(&ses) || sam3aIsActiveSession(&snr) || sam3aIsActiveSession(&skg)) {
while (sam3aIsActiveSession(&ses) || sam3aIsActiveSession(&snr) ||
sam3aIsActiveSession(&skg)) {
fd_set rds, wrs;
int res, maxfd = 0;
struct timeval to;
@ -134,26 +136,37 @@ int main (int argc, char *argv[]) {
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;
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);
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
if (res < 0) {
if (errno == EINTR) continue;
if (errno == EINTR)
continue;
fprintf(stderr, "FATAL: select() error!\n");
break;
}
if (res == 0) {
// idle, no activity
fprintf(stdout, "."); fflush(stdout);
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);
if (sam3aIsActiveSession(&ses))
sam3aProcessSessionIO(&ses, &rds, &wrs);
if (sam3aIsActiveSession(&snr))
sam3aProcessSessionIO(&snr, &rds, &wrs);
if (sam3aIsActiveSession(&skg))
sam3aProcessSessionIO(&skg, &rds, &wrs);
}
}
// close seessions

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -18,86 +19,90 @@
#include "../libsam3a/libsam3a.h"
////////////////////////////////////////////////////////////////////////////////
#define KEYFILE "streams.key"
////////////////////////////////////////////////////////////////////////////////
#define KEYFILE "streams.key"
////////////////////////////////////////////////////////////////////////////////
static void ccbError (Sam3AConnection *ct) {
fprintf(stderr, "\n===============================\nCONNECTION_ERROR: [%s]\n===============================\n", ct->error);
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 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 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 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
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;
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);
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 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 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,
.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 scbError(Sam3ASession *ses) {
fprintf(stderr,
"\n===============================\nSESION_ERROR: "
"[%s]\n===============================\n",
ses->error);
}
static void scbCreated (Sam3ASession *ses) {
static void scbCreated(Sam3ASession *ses) {
char destkey[517];
FILE *fl;
//
@ -128,42 +133,41 @@ static void scbCreated (Sam3ASession *ses) {
fprintf(stderr, "GOON: creating connection...\n");
}
static void scbDisconnected (Sam3ASession *ses) {
fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n===============================\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 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 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,
.cbError = scbError,
.cbCreated = scbCreated,
.cbDisconnected = scbDisconnected,
.cbDatagramRead = scbDGramRead,
.cbDestroy = scbDestroy,
};
////////////////////////////////////////////////////////////////////////////////
#define HOST SAM3A_HOST_DEFAULT
#define HOST SAM3A_HOST_DEFAULT
//#define HOST "google.com"
int main (int argc, char *argv[]) {
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) {
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;
}
@ -175,18 +179,23 @@ int main (int argc, char *argv[]) {
//
FD_ZERO(&rds);
FD_ZERO(&wrs);
if (sam3aIsActiveSession(&ses) && (maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0) break;
if (sam3aIsActiveSession(&ses) &&
(maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0)
break;
sam3ams2timeval(&to, 1000);
res = select(maxfd+1, &rds, &wrs, NULL, &to);
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
if (res < 0) {
if (errno == EINTR) continue;
if (errno == EINTR)
continue;
fprintf(stderr, "FATAL: select() error!\n");
break;
}
if (res == 0) {
fprintf(stdout, "."); fflush(stdout);
fprintf(stdout, ".");
fflush(stdout);
} else {
if (sam3aIsActiveSession(&ses)) sam3aProcessSessionIO(&ses, &rds, &wrs);
if (sam3aIsActiveSession(&ses))
sam3aProcessSessionIO(&ses, &rds, &wrs);
}
}
//

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <errno.h>
#include <stdio.h>
@ -18,10 +19,8 @@
#include "../libsam3a/libsam3a.h"
////////////////////////////////////////////////////////////////////////////////
#define KEYFILE "streams.key"
#define KEYFILE "streams.key"
////////////////////////////////////////////////////////////////////////////////
typedef struct {
@ -31,63 +30,67 @@ typedef struct {
int doQuit;
} ConnData;
static void cdAppendChar (ConnData *d, char ch) {
if (d->strused+1 >= d->strsize) {
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->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 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 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 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 ccbAccepted(Sam3AConnection *ct) {
fprintf(stderr, "\n===============================\nCONNECTION_ACCEPTED\n===="
"===========================\n");
fprintf(stderr, "FROM: %s\n===============================\n", ct->destkey);
}
static void ccbSent (Sam3AConnection *ct) {
static void ccbSent(Sam3AConnection *ct) {
ConnData *d = (ConnData *)ct->udata;
//
fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n===============================\n");
fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n==="
"============================\n");
if (d->doQuit) {
sam3aCancelSession(ct->ses); // hehe
}
}
static void ccbRead (Sam3AConnection *ct, const void *buf, int bufsize) {
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);
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 (strcasecmp(d->str, "quit\n") == 0)
d->doQuit = 1;
if (sam3aSend(ct, d->str, -1) < 0) {
//sam3aCancelConnection(ct); // hehe
// sam3aCancelConnection(ct); // hehe
sam3aCancelSession(ct->ses); // hehe
return;
}
@ -99,36 +102,37 @@ static void ccbRead (Sam3AConnection *ct, const void *buf, int bufsize) {
}
}
static void ccbDestroy (Sam3AConnection *ct) {
fprintf(stderr, "\n===============================\nCONNECTION_DESTROY\n===============================\n");
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);
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,
.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 scbError(Sam3ASession *ses) {
fprintf(stderr,
"\n===============================\nSESION_ERROR: "
"[%s]\n===============================\n",
ses->error);
}
static void scbCreated (Sam3ASession *ses) {
static void scbCreated(Sam3ASession *ses) {
FILE *fl;
Sam3AConnection *conn;
//
@ -160,42 +164,41 @@ static void scbCreated (Sam3ASession *ses) {
fprintf(stderr, "GOON: accepting connection...\n");
}
static void scbDisconnected (Sam3ASession *ses) {
fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n===============================\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 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 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,
.cbError = scbError,
.cbCreated = scbCreated,
.cbDisconnected = scbDisconnected,
.cbDatagramRead = scbDGramRead,
.cbDestroy = scbDestroy,
};
////////////////////////////////////////////////////////////////////////////////
#define HOST SAM3A_HOST_DEFAULT
#define HOST SAM3A_HOST_DEFAULT
//#define HOST "google.com"
int main (int argc, char *argv[]) {
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) {
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;
}
@ -207,18 +210,23 @@ int main (int argc, char *argv[]) {
//
FD_ZERO(&rds);
FD_ZERO(&wrs);
if (sam3aIsActiveSession(&ses) && (maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0) break;
if (sam3aIsActiveSession(&ses) &&
(maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0)
break;
sam3ams2timeval(&to, 1000);
res = select(maxfd+1, &rds, &wrs, NULL, &to);
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
if (res < 0) {
if (errno == EINTR) continue;
if (errno == EINTR)
continue;
fprintf(stderr, "FATAL: select() error!\n");
break;
}
if (res == 0) {
fprintf(stdout, "."); fflush(stdout);
fprintf(stdout, ".");
fflush(stdout);
} else {
if (sam3aIsActiveSession(&ses)) sam3aProcessSessionIO(&ses, &rds, &wrs);
if (sam3aIsActiveSession(&ses))
sam3aProcessSessionIO(&ses, &rds, &wrs);
}
}
//

View File

@ -26,10 +26,10 @@
#include "tinytest_local.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifndef NO_FORKING
@ -42,8 +42,8 @@
#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)
#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>
@ -62,18 +62,18 @@
#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 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;
const struct testlist_alias_t *cfg_aliases = NULL;
enum outcome { SKIP=2, OK=1, FAIL=0 };
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 */
@ -81,413 +81,386 @@ const char *cur_test_name = NULL;
#ifdef _WIN32
/* Copy of argv[0] for win32. */
static char commandname[MAX_PATH+1];
static char commandname[MAX_PATH + 1];
#endif
static void usage(struct testgroup_t *groups, int list_groups)
__attribute__((noreturn));
__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;
}
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;
cur_test_outcome = OK;
testcase->fn(env);
outcome = cur_test_outcome;
if (testcase->setup) {
if (testcase->setup->cleanup_fn(testcase, env) == 0)
outcome = FAIL;
}
if (testcase->setup) {
if (testcase->setup->cleanup_fn(testcase, env) == 0)
outcome = FAIL;
}
return outcome;
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)
{
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.
/* 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;
(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] ");
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);
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);
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;
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;
int outcome_pipe[2];
pid_t pid;
(void)group;
if (pipe(outcome_pipe))
perror("opening pipe");
if (pipe(outcome_pipe))
perror("opening pipe");
if (opt_verbosity>0)
printf("[forking] ");
pid = fork();
if (opt_verbosity > 0)
printf("[forking] ");
pid = fork();
#ifdef FORK_BREAKS_GCOV
vproc_transaction_begin(0);
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);
}
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;
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 (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;
}
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 {
if ((testcase->flags & TT_FORK) && !(opt_forked || opt_nofork)) {
outcome = testcase_run_forked_(group, testcase);
} else {
#else
{
{
#endif
outcome = testcase_run_bare_(testcase);
}
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 (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;
}
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;
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 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_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;
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;
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;
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';
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_);
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);
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;
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;
--in_tinytest_main;
if (opt_verbosity==0)
puts("");
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);
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;
return (n_bad == 0) ? 0 : 1;
}
int
tinytest_get_verbosity_(void)
{
return opt_verbosity;
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_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;
}
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;
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;
if (!val)
return strdup("null");
if (!(result = (char *)malloc(len * 2 + 1)))
return strdup("<allocation failure>");
cp = result;
for (i = 0; i < len; ++i) {
*cp++ = "0123456789ABCDEF"[val[i] >> 4];
*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
}
*cp = 0;
return result;
}

View File

@ -27,15 +27,15 @@
#define TINYTEST_H_INCLUDED_
/** Flag for a test that needs to run in a subprocess. */
#define TT_FORK (1<<0)
#define TT_FORK (1 << 0)
/** Runtime flag for a test we've decided to skip. */
#define TT_SKIP (1<<1)
#define TT_SKIP (1 << 1)
/** Internal runtime flag for a test we've decided to run. */
#define TT_ENABLED_ (1<<2)
#define TT_ENABLED_ (1 << 2)
/** Flag for a test that's off by default. */
#define TT_OFF_BY_DEFAULT (1<<3)
#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)
#define TT_FIRST_USER_FLAG (1 << 4)
typedef void (*testcase_fn)(void *);
@ -43,34 +43,37 @@ 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 *);
/** 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 */
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 }
#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 */
const char *prefix; /**< Prefix to prepend to testnames. */
struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */
};
#define END_OF_GROUPS { NULL, NULL}
#define END_OF_GROUPS \
{ NULL, NULL }
struct testlist_alias_t {
const char *name;
const char **tests;
const char *name;
const char **tests;
};
#define END_OF_ALIASES { NULL, NULL }
#define END_OF_ALIASES \
{ NULL, NULL }
/** Implementation: called from a test to indicate failure, before logging. */
void tinytest_set_test_failed_(void);
@ -80,16 +83,17 @@ void tinytest_set_test_skipped_(void);
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);
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)
#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 *);
int testcase_run_one(const struct testgroup_t *, const struct testcase_t *);
void tinytest_set_aliases(const struct testlist_alias_t *aliases);

View File

@ -28,182 +28,192 @@
/* Helpers for defining statement-like macros */
#define TT_STMT_BEGIN do {
#define TT_STMT_END } while (0)
#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
#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
#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_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_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
#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_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_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_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
#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, );
#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);
#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")")
#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(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_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(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)
#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_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_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_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_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_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_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_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_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_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_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 \
);
#define tt_want_mem_op(expr1, op, expr2, len) \
tt_assert_test_fmt_type( \
expr1, expr2, #expr1 " " #op " " #expr2, const void *, \
(val1_ && val2_ && memcmp(val1_, val2_, len) op 0), char *, "%s", \
{ print_ = tinytest_format_hex_(value_, (len)); }, \
{ \
if (print_) \
free(print_); \
}, \
(void)0);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#ifndef LIBSAM3_H
#define LIBSAM3_H
@ -16,55 +17,57 @@
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////////////
extern int libsam3_debug;
////////////////////////////////////////////////////////////////////////////////
#define SAM3_HOST_DEFAULT (NULL)
#define SAM3_PORT_DEFAULT (0)
#define SAM3_HOST_DEFAULT (NULL)
#define SAM3_PORT_DEFAULT (0)
#define SAM3_DESTINATION_TRANSIENT (NULL)
#define SAM3_PUBKEY_SIZE (516)
#define SAM3_PRIVKEY_SIZE (884)
#define SAM3_DESTINATION_TRANSIENT (NULL)
#define SAM3_PUBKEY_SIZE (516)
#define SAM3_CERT_SIZE (100)
#define SAM3_PRIVKEY_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);
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);
extern int sam3tcpDisconnect(int fd);
/* <0: error; 0: ok */
extern int sam3tcpSetTimeoutSend (int fd, int timeoutms);
extern int sam3tcpSetTimeoutSend(int fd, int timeoutms);
/* <0: error; 0: ok */
extern int sam3tcpSetTimeoutReceive (int fd, int timeoutms);
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);
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);
/* 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 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 sam3tcpPrintf(int fd, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
extern int sam3tcpReceiveStr (int fd, char *dest, size_t maxSize);
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);
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 {
@ -73,16 +76,16 @@ typedef struct SAMFieldList {
struct SAMFieldList *next;
} SAMFieldList;
extern void sam3FreeFieldList (SAMFieldList *list);
extern void sam3DumpFieldList (const SAMFieldList *list);
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);
/* 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);
extern SAMFieldList *sam3ParseReply(const char *rep);
/*
* example:
@ -92,17 +95,17 @@ extern SAMFieldList *sam3ParseReply (const char *rep);
* 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);
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);
extern int sam3Handshake(const char *hostname, int port, uint32_t *ip);
extern int sam3HandshakeIP(uint32_t ip, int port);
////////////////////////////////////////////////////////////////////////////////
typedef enum {
@ -111,31 +114,31 @@ typedef enum {
SAM3_SESSION_STREAM
} Sam3SessionType;
typedef struct Sam3Session {
Sam3SessionType type;
int fd;
char privkey[SAM3_PRIVKEY_SIZE+1]; // destination private key (asciiz)
char pubkey[SAM3_PUBKEY_SIZE+1]; // destination public key (asciiz)
char privkey[SAM3_PRIVKEY_SIZE + 1]; // destination private key (asciiz)
char pubkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE +
1]; // destination public key (asciiz)
// char cert[SAM3_CERT_SIZE+1]
char channel[66]; // name of this sam session (asciiz)
char destkey[SAM3_PUBKEY_SIZE+1]; // for DGRAM sessions (asciiz)
char error[32]; // error message (asciiz)
char destkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE +
1]; // for DGRAM sessions (asciiz)
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;
} Sam3Session;
typedef struct Sam3Connection {
Sam3Session *ses;
struct Sam3Connection *next;
int fd;
char destkey[SAM3_PUBKEY_SIZE+1]; // remote destination public key (asciiz)
char error[32]; // error message (asciiz)
char destkey[SAM3_PUBKEY_SIZE + 1]; // remote destination public key (asciiz)
char error[32]; // error message (asciiz)
} Sam3Connection;
////////////////////////////////////////////////////////////////////////////////
/*
* create SAM session
@ -144,19 +147,20 @@ typedef struct Sam3Connection {
* '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
* 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,
const char *params);
extern int sam3CreateSession(Sam3Session *ses, const char *hostname, int port,
const char *privkey, Sam3SessionType type,
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);
extern int sam3CloseSession(Sam3Session *ses);
/*
* open stream connection to 'destkey' endpoint
@ -165,7 +169,7 @@ extern int sam3CloseSession (Sam3Session *ses);
* you still have to call sam3CloseSession() on failure
* sets ses->error on error
*/
extern Sam3Connection *sam3StreamConnect (Sam3Session *ses, const char *destkey);
extern Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey);
/*
* accepts stream connection and sets 'destkey'
@ -175,7 +179,7 @@ extern Sam3Connection *sam3StreamConnect (Sam3Session *ses, const char *destkey)
* sets ses->error on error
* note that there is no timeouts for now, but you can use sam3tcpSetTimeout*()
*/
extern Sam3Connection *sam3StreamAccept (Sam3Session *ses);
extern Sam3Connection *sam3StreamAccept(Sam3Session *ses);
/*
* sets up forwarding stream connection
@ -184,7 +188,7 @@ extern Sam3Connection *sam3StreamAccept (Sam3Session *ses);
* 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);
extern int sam3StreamForward(Sam3Session *ses, const char *hostname, int port);
/*
* close SAM connection
@ -192,8 +196,7 @@ extern int sam3StreamForward (Sam3Session *ses, const char *hostname, int port);
* 'conn' must be properly initialized
* 'conn' is invalid after call
*/
extern int sam3CloseConnection (Sam3Connection *conn);
extern int sam3CloseConnection(Sam3Connection *conn);
////////////////////////////////////////////////////////////////////////////////
/*
@ -203,7 +206,7 @@ extern int sam3CloseConnection (Sam3Connection *conn);
* will not set 'error' field
* returns <0 on error, 0 on ok
*/
extern int sam3GenerateKeys (Sam3Session *ses, const char *hostname, int port);
extern int sam3GenerateKeys(Sam3Session *ses, const char *hostname, int port);
/*
* do name lookup (something like gethostbyname())
@ -212,8 +215,8 @@ extern int sam3GenerateKeys (Sam3Session *ses, const char *hostname, int port);
* will set 'error' field
* returns <0 on error, 0 on ok
*/
extern int sam3NameLookup (Sam3Session *ses, const char *hostname, int port, const char *name);
extern int sam3NameLookup(Sam3Session *ses, const char *hostname, int port,
const char *name);
////////////////////////////////////////////////////////////////////////////////
/*
@ -224,32 +227,34 @@ extern int sam3NameLookup (Sam3Session *ses, const char *hostname, int port, con
* 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);
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)
* 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);
extern ssize_t sam3DatagramReceive(Sam3Session *ses, void *buf, size_t bufsize);
/*
* generate random sam channel name
* generate random sam channel name
* return the size of the string
*/
extern size_t sam3GenChannelName (char *dest, size_t minlen, size_t maxlen);
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); }
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);
extern ssize_t sam3Base32Encode(char *dest, size_t destsz, const void *srcbuf,
size_t srcsize);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#ifndef LIBSAM3A_H
#define LIBSAM3A_H
@ -21,50 +22,42 @@
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)
////////////////////////////////////////////////////////////////////////////////
#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 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);
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;
@ -79,38 +72,42 @@ typedef struct {
/** 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 */
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 */
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
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;
};
@ -118,22 +115,24 @@ struct Sam3ASession {
/** 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);
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);
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);
void (*cbRead)(Sam3AConnection *ct, const void *buf, int bufsize);
/** fd already closed, but keys is not cleared */
void (*cbDestroy) (Sam3AConnection *ct);
void (*cbDestroy)(Sam3AConnection *ct);
} Sam3AConnectionCallbacks;
struct Sam3AConnection {
/** parent session */
Sam3ASession *ses;
@ -141,39 +140,37 @@ struct Sam3AConnection {
/** 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)
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
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);
extern int sam3aIsActiveSession(const Sam3ASession *ses);
/*
* check if connection is active (i.e. have opened socket)
* returns bool
*/
extern int sam3aIsActiveConnection (const Sam3AConnection *conn);
extern int sam3aIsActiveConnection(const Sam3AConnection *conn);
////////////////////////////////////////////////////////////////////////////////
/*
@ -188,35 +185,40 @@ extern int sam3aIsActiveConnection (const Sam3AConnection *conn);
* '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
* 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);
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)
{
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);
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);
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
* 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);
extern int sam3aCancelSession(Sam3ASession *ses);
/*
* open stream connection to 'destkey' endpoint
@ -224,10 +226,14 @@ extern int sam3aCancelSession (Sam3ASession *ses);
* 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);
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) {
static inline Sam3AConnection *
sam3aStreamConnect(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb,
const char *destkey) {
return sam3aStreamConnectEx(ses, cb, destkey, -1);
}
@ -239,9 +245,12 @@ static inline Sam3AConnection *sam3aStreamConnect (Sam3ASession *ses, const Sam3
* 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);
extern Sam3AConnection *sam3aStreamAcceptEx(Sam3ASession *ses,
const Sam3AConnectionCallbacks *cb,
int timeoutms);
static inline Sam3AConnection *sam3aStreamAccept (Sam3ASession *ses, const Sam3AConnectionCallbacks *cb) {
static inline Sam3AConnection *
sam3aStreamAccept(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb) {
return sam3aStreamAcceptEx(ses, cb, -1);
}
@ -251,7 +260,7 @@ static inline Sam3AConnection *sam3aStreamAccept (Sam3ASession *ses, const Sam3A
* 'conn' must be properly initialized
* 'conn' is invalid after call
*/
extern int sam3aCloseConnection (Sam3AConnection *conn);
extern int sam3aCloseConnection(Sam3AConnection *conn);
/*
* cancel SAM connection, but don't free() or clear anything except fd
@ -259,17 +268,16 @@ extern int sam3aCloseConnection (Sam3AConnection *conn);
* 'conn' must be properly initialized
* 'conn' is invalid after call
*/
extern int sam3aCancelConnection (Sam3AConnection *conn);
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);
extern int sam3aSend(Sam3AConnection *conn, const void *data, int datasize);
/*
* sends datagram to 'destkey' endpoint
@ -279,16 +287,15 @@ extern int sam3aSend (Sam3AConnection *conn, const void *data, int datasize);
* 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);
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);
extern int sam3aGenChannelName(char *dest, int minlen, int maxlen);
////////////////////////////////////////////////////////////////////////////////
/*
@ -298,31 +305,34 @@ extern int sam3aGenChannelName (char *dest, int minlen, int maxlen);
* 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);
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) {
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
* 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);
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)
{
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
@ -330,20 +340,20 @@ static inline int sam3aNameLookup (Sam3ASession *ses, const Sam3ASessionCallback
* 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);
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);
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)));
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
}

View File

@ -4,7 +4,8 @@
* 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
* I2P-Bote:
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
* we are the Borg. */
#include <stdio.h>
#include <stdlib.h>
@ -15,8 +16,7 @@
#include "../../src/ext/tinytest_macros.h"
#include "../../src/libsam3/libsam3.h"
static int testb32 (const char *src, const char *res) {
static int testb32(const char *src, const char *res) {
size_t dlen = sam3Base32EncodedLength(strlen(src)), len;
char dest[128];
//
@ -41,11 +41,11 @@ void test_b32_encode(void *data) {
tt_assert(testb32("fooba", "mzxw6ytb"));
tt_assert(testb32("foobar", "mzxw6ytboi======"));
end:
;
end:;
}
struct testcase_t b32_tests[] = {
{ "encode", test_b32_encode, },
END_OF_TESTCASES
};
struct testcase_t b32_tests[] = {{
"encode",
test_b32_encode,
},
END_OF_TESTCASES};

View File

@ -5,10 +5,7 @@
extern struct testcase_t b32_tests[];
struct testgroup_t test_groups[] = {
{ "b32/", b32_tests },
END_OF_GROUPS
};
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);