corrected the sample code and made them easier to build
This commit is contained in:
3
Makefile
3
Makefile
@ -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
1
examples/libsam3
Symbolic link
@ -0,0 +1 @@
|
||||
/home/idk/local-manifest/crypto-manifest/i2p-manifest/libsam3/src/libsam3
|
24
examples/sam3/Makefile
Normal file
24
examples/sam3/Makefile
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
@ -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
@ -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
|
||||
}
|
||||
|
@ -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};
|
||||
|
@ -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);
|
||||
|
Reference in New Issue
Block a user