mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-13 05:21:32 -05:00
add fork of libsam3
add funtion to get i2p certificate crypto algo names
This commit is contained in:
parent
130d846e47
commit
76f0678820
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,3 +15,5 @@ Thumbs.db
|
|||||||
*.pro.user
|
*.pro.user
|
||||||
.kdev4
|
.kdev4
|
||||||
*.kdev4
|
*.kdev4
|
||||||
|
|
||||||
|
!supportlibs/libsam3/Makefile
|
||||||
|
@ -70,13 +70,14 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
uint8_t certType = 0;
|
uint8_t certType = 0;
|
||||||
uint16_t len = 0;
|
uint16_t len = 0;
|
||||||
uint16_t signingKeyType = 0;
|
uint16_t signingKeyType = 0;
|
||||||
uint16_t cryptKey = 0;
|
uint16_t cryptKeyType = 0;
|
||||||
|
|
||||||
// only used for easy break
|
// only used for easy break
|
||||||
do {
|
do {
|
||||||
try {
|
try {
|
||||||
// jump to certificate
|
// jump to certificate
|
||||||
p += publicKeyLen;
|
p += publicKeyLen;
|
||||||
|
|
||||||
// try to read type and length
|
// try to read type and length
|
||||||
certType = *p++;
|
certType = *p++;
|
||||||
len = readTwoBytesBE(p);
|
len = readTwoBytesBE(p);
|
||||||
@ -87,7 +88,7 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
/*
|
/*
|
||||||
* CertType.Null
|
* CertType.Null
|
||||||
* type null is followed by 0x00 0x00 <END>
|
* type null is followed by 0x00 0x00 <END>
|
||||||
* so has to be 0!
|
* so len has to be 0!
|
||||||
*/
|
*/
|
||||||
RS_DBG("cert is CertType.Null");
|
RS_DBG("cert is CertType.Null");
|
||||||
publicKeyLen += 3; // add 0x00 0x00 0x00
|
publicKeyLen += 3; // add 0x00 0x00 0x00
|
||||||
@ -119,7 +120,7 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
// likely 7
|
// likely 7
|
||||||
signingKeyType = readTwoBytesBE(p);
|
signingKeyType = readTwoBytesBE(p);
|
||||||
|
|
||||||
RS_DBG("signing pubkey type ", certType);
|
RS_DBG("signing pubkey type ", signingKeyType);
|
||||||
if (signingKeyType >= 3 && signingKeyType <= 6) {
|
if (signingKeyType >= 3 && signingKeyType <= 6) {
|
||||||
RS_DBG("signing pubkey type ", certType, " has oversize");
|
RS_DBG("signing pubkey type ", certType, " has oversize");
|
||||||
// calculate oversize
|
// calculate oversize
|
||||||
@ -137,18 +138,18 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKeyLen += values.first - 128; // 128 = default DSA key length = the space than can be used before the key must be splitted
|
publicKeyLen += values.first - 128; // 128 = default DSA key length = the space that can be used before the key must be splitted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crypto Public Key
|
// Crypto Public Key
|
||||||
// likely 0
|
// likely 0
|
||||||
cryptKey = readTwoBytesBE(p);
|
cryptKeyType = readTwoBytesBE(p);
|
||||||
RS_DBG("crypto pubkey type ", cryptKey);
|
RS_DBG("crypto pubkey type ", cryptKeyType);
|
||||||
// info: these are all smaller than the default 256 bytes, so no oversize calculation is needed
|
// info: these are all smaller than the default 256 bytes, so no oversize calculation is needed
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} catch (const std::out_of_range &e) {
|
} catch (const std::out_of_range &e) {
|
||||||
RS_DBG("hit exception! ", e.what());
|
RS_DBG("hit an exception! ", e.what());
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
} while(false);
|
} while(false);
|
||||||
@ -160,4 +161,102 @@ std::string publicKeyFromPrivate(std::string const &priv)
|
|||||||
return pub;
|
return pub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey)
|
||||||
|
{
|
||||||
|
// creat a copy to work on, need to convert it to standard base64
|
||||||
|
auto key_copy(key);
|
||||||
|
std::replace(key_copy.begin(), key_copy.end(), '~', '/');
|
||||||
|
// replacing the - with a + is not necessary, as RsBase64 can handle base64url encoding, too
|
||||||
|
// std::replace(copy.begin(), copy.end(), '-', '+');
|
||||||
|
|
||||||
|
// get raw data
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
RsBase64::decode(key_copy, data);
|
||||||
|
|
||||||
|
auto p = data.cbegin();
|
||||||
|
|
||||||
|
constexpr size_t publicKeyLen = 256 + 128; // default length (bytes)
|
||||||
|
uint8_t certType = 0;
|
||||||
|
uint16_t signingKeyType = 0;
|
||||||
|
uint16_t cryptKeyType = 0;
|
||||||
|
|
||||||
|
// try to read types
|
||||||
|
try {
|
||||||
|
// jump to certificate
|
||||||
|
p += publicKeyLen;
|
||||||
|
|
||||||
|
// try to read type and skip length
|
||||||
|
certType = *p++;
|
||||||
|
p += 2;
|
||||||
|
|
||||||
|
// only 0 and 5 are used / valid at this point
|
||||||
|
// check for == 0
|
||||||
|
if (certType == static_cast<typename std::underlying_type<CertType>::type>(CertType::Null)) {
|
||||||
|
RS_DBG("cert is CertType.Null");
|
||||||
|
|
||||||
|
signingKey = "DSA_SHA1";
|
||||||
|
cryptoKey = "ElGamal";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for != 5
|
||||||
|
if (certType != static_cast<typename std::underlying_type<CertType>::type>(CertType::Key)) {
|
||||||
|
// unsupported
|
||||||
|
RS_DBG("cert type ", certType, " is unsupported");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RS_DBG("cert is CertType.Key");
|
||||||
|
|
||||||
|
// Signing Public Key
|
||||||
|
// likely 7
|
||||||
|
signingKeyType = readTwoBytesBE(p);
|
||||||
|
RS_DBG("signing pubkey type ", signingKeyType);
|
||||||
|
|
||||||
|
// Crypto Public Key
|
||||||
|
// likely 0
|
||||||
|
cryptKeyType = readTwoBytesBE(p);
|
||||||
|
RS_DBG("crypto pubkey type ", cryptKeyType);
|
||||||
|
} catch (const std::out_of_range &e) {
|
||||||
|
RS_DBG("hit an exception! ", e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now convert to string (this would be easier with c++17)
|
||||||
|
#define HELPER(a, b, c) \
|
||||||
|
case static_cast<typename std::underlying_type<a>::type>(a::c): \
|
||||||
|
b = "c"; \
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (signingKeyType) {
|
||||||
|
HELPER(SigningKeyType, signingKey, DSA_SHA1)
|
||||||
|
HELPER(SigningKeyType, signingKey, ECDSA_SHA256_P256)
|
||||||
|
HELPER(SigningKeyType, signingKey, ECDSA_SHA384_P384)
|
||||||
|
HELPER(SigningKeyType, signingKey, ECDSA_SHA512_P521)
|
||||||
|
HELPER(SigningKeyType, signingKey, RSA_SHA256_2048)
|
||||||
|
HELPER(SigningKeyType, signingKey, RSA_SHA384_3072)
|
||||||
|
HELPER(SigningKeyType, signingKey, RSA_SHA512_4096)
|
||||||
|
HELPER(SigningKeyType, signingKey, EdDSA_SHA512_Ed25519)
|
||||||
|
HELPER(SigningKeyType, signingKey, EdDSA_SHA512_Ed25519ph)
|
||||||
|
HELPER(SigningKeyType, signingKey, RedDSA_SHA512_Ed25519)
|
||||||
|
default:
|
||||||
|
RsWarn("unkown signing key type:", signingKeyType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cryptKeyType) {
|
||||||
|
HELPER(CryptoKeyType, cryptoKey, ElGamal)
|
||||||
|
HELPER(CryptoKeyType, cryptoKey, P256)
|
||||||
|
HELPER(CryptoKeyType, cryptoKey, P384)
|
||||||
|
HELPER(CryptoKeyType, cryptoKey, P521)
|
||||||
|
HELPER(CryptoKeyType, cryptoKey, X25519)
|
||||||
|
default:
|
||||||
|
RsWarn("unkown crypto key type:", cryptKeyType);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#undef HELPER
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace i2p
|
} // namespace i2p
|
||||||
|
@ -208,6 +208,15 @@ std::string keyToBase32Addr(const std::string &key);
|
|||||||
*/
|
*/
|
||||||
std::string publicKeyFromPrivate(const std::string &priv);
|
std::string publicKeyFromPrivate(const std::string &priv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getKeyTypes returns the name of the utilized algorithms used by the key
|
||||||
|
* @param key public key (private works, too)
|
||||||
|
* @param signingKey name of the signing key, e.g. DSA_SHA1
|
||||||
|
* @param cryptoKey name of the crpyto key, e.g. ElGamal
|
||||||
|
* @return true on success, false otherwise
|
||||||
|
*/
|
||||||
|
bool getKeyTypes(const std::string &key, std::string &signingKey, std::string &cryptoKey);
|
||||||
|
|
||||||
} // namespace i2p
|
} // namespace i2p
|
||||||
|
|
||||||
#endif // I2PCOMMON_H
|
#endif // I2PCOMMON_H
|
||||||
|
41
supportlibs/libsam3/Makefile
Normal file
41
supportlibs/libsam3/Makefile
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
CFLAGS := -Wall -g -O2 -std=gnu99
|
||||||
|
|
||||||
|
SRCS := \
|
||||||
|
src/libsam3/libsam3.c \
|
||||||
|
src/libsam3a/libsam3a.c
|
||||||
|
|
||||||
|
TESTS := \
|
||||||
|
src/ext/tinytest.c \
|
||||||
|
test/test.c \
|
||||||
|
test/libsam3/test_b32.c
|
||||||
|
|
||||||
|
LIB_OBJS := ${SRCS:.c=.o}
|
||||||
|
TEST_OBJS := ${TESTS:.c=.o}
|
||||||
|
|
||||||
|
OBJS := ${LIB_OBJS} ${TEST_OBJS}
|
||||||
|
|
||||||
|
LIB := libsam3.a
|
||||||
|
|
||||||
|
|
||||||
|
all: build check
|
||||||
|
|
||||||
|
check: libsam3-tests
|
||||||
|
./libsam3-tests
|
||||||
|
|
||||||
|
build: ${LIB}
|
||||||
|
|
||||||
|
${LIB}: ${LIB_OBJS}
|
||||||
|
${AR} -sr ${LIB} ${LIB_OBJS}
|
||||||
|
|
||||||
|
libsam3-tests: ${TEST_OBJS} ${LIB}
|
||||||
|
${CC} $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f libsam3-tests ${LIB} ${OBJS} examples/sam3/samtest
|
||||||
|
|
||||||
|
%.o: %.c Makefile
|
||||||
|
${CC} ${CFLAGS} -c $< -o $@
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
find . -name '*.c' -exec clang-format -i {} \;
|
||||||
|
find . -name '*.h' -exec clang-format -i {} \;
|
18
supportlibs/libsam3/README.md
Normal file
18
supportlibs/libsam3/README.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# libsam3
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/i2p/libsam3.svg?branch=master)](https://travis-ci.org/i2p/libsam3)
|
||||||
|
|
||||||
|
A C library for the [SAM v3 API](https://geti2p.net/en/docs/api/samv3).
|
||||||
|
|
||||||
|
## Development Status
|
||||||
|
|
||||||
|
Unmaintained, but PRs welcome!
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Copy the two files from one of the following locations into your codebase:
|
||||||
|
|
||||||
|
- `src/libsam3` - Synchronous implementation.
|
||||||
|
- `src/libsam3a` - Asynchronous implementation.
|
||||||
|
|
||||||
|
See `examples/` for how to use various parts of the API.
|
1
supportlibs/libsam3/examples/libsam3
Symbolic link
1
supportlibs/libsam3/examples/libsam3
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../src/libsam3
|
26
supportlibs/libsam3/examples/sam3/README.md
Normal file
26
supportlibs/libsam3/examples/sam3/README.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
These examples show various ways of using libsam3 to enable i2p in your
|
||||||
|
application, and are also useful in other ways. If you implement an i2p
|
||||||
|
application library in another language, making variants basic tools wouldn't be
|
||||||
|
the worst way to make sure that it works.
|
||||||
|
|
||||||
|
building
|
||||||
|
--------
|
||||||
|
|
||||||
|
Once you have build the library in the root of this repository by running make
|
||||||
|
all, you can build all these examples at once by running
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
in this directory. I think it makes things easier to experiment with quickly.
|
||||||
|
|
||||||
|
namelookup
|
||||||
|
----------
|
||||||
|
|
||||||
|
Namelookup uses the SAM API to find the base64 destination of an readable "jump"
|
||||||
|
or base32 i2p address. You can use it like this:
|
||||||
|
|
||||||
|
./lookup i2p-projekt.i2p
|
||||||
|
|
116
supportlibs/libsam3/examples/sam3/dgramc.c
Normal file
116
supportlibs/libsam3/examples/sam3/dgramc.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
// comment the following if you don't want to stress UDP with 'big' datagram
|
||||||
|
// seems that up to 32000 bytes can be used for localhost
|
||||||
|
// note that we need 516+6+? bytes for header; lets reserve 1024 bytes for it
|
||||||
|
#define BIG (32000 - 1024)
|
||||||
|
|
||||||
|
#define KEYFILE "dgrams.key"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3Session ses;
|
||||||
|
char buf[1024];
|
||||||
|
char destkey[517] = {0}; // 516 chars + \0
|
||||||
|
int sz;
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
if (argc < 2) {
|
||||||
|
FILE *fl = fopen(KEYFILE, "rb");
|
||||||
|
//
|
||||||
|
if (fl != NULL) {
|
||||||
|
if (fread(destkey, 516, 1, fl) == 1) {
|
||||||
|
fclose(fl);
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
fclose(fl);
|
||||||
|
}
|
||||||
|
printf("usage: dgramc PUBKEY\n");
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (strlen(argv[1]) != 516) {
|
||||||
|
fprintf(stderr, "FATAL: invalid key length!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(destkey, argv[1]);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
ok:
|
||||||
|
printf("creating session...\n");
|
||||||
|
/* create TRANSIENT session with temporary disposible destination */
|
||||||
|
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
|
||||||
|
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_DGRAM, 4,
|
||||||
|
NULL) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create session\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* send datagram */
|
||||||
|
printf("sending test datagram...\n");
|
||||||
|
if (sam3DatagramSend(&ses, destkey, "test", 4) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/** receive reply */
|
||||||
|
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/** null terminated string */
|
||||||
|
buf[sz] = 0;
|
||||||
|
printf("received: [%s]\n", buf);
|
||||||
|
//
|
||||||
|
#ifdef BIG
|
||||||
|
{
|
||||||
|
char *big = calloc(BIG + 1024, sizeof(char));
|
||||||
|
/** generate random string */
|
||||||
|
sam3GenChannelName(big, BIG + 1023, BIG + 1023);
|
||||||
|
printf("sending BIG datagram...\n");
|
||||||
|
if (sam3DatagramSend(&ses, destkey, big, BIG) < 0) {
|
||||||
|
free(big);
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((sz = sam3DatagramReceive(&ses, big, BIG + 512)) < 0) {
|
||||||
|
free(big);
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
big[sz] = 0;
|
||||||
|
printf("received (%d): [%s]\n", sz, big);
|
||||||
|
free(big);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
printf("sending quit datagram...\n");
|
||||||
|
if (sam3DatagramSend(&ses, destkey, "quit", 4) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ((sz = sam3DatagramReceive(&ses, buf, sizeof(buf) - 1)) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
buf[sz] = 0;
|
||||||
|
printf("received: [%s]\n", buf);
|
||||||
|
//
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 1;
|
||||||
|
}
|
113
supportlibs/libsam3/examples/sam3/dgrams.c
Normal file
113
supportlibs/libsam3/examples/sam3/dgrams.c
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
#define KEYFILE "dgrams.key"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3Session ses;
|
||||||
|
char privkey[1024], pubkey[1024], buf[33 * 1024];
|
||||||
|
|
||||||
|
/** quit command */
|
||||||
|
const char *quitstr = "quit";
|
||||||
|
const size_t quitlen = strlen(quitstr);
|
||||||
|
|
||||||
|
/** reply response */
|
||||||
|
const char *replystr = "reply: ";
|
||||||
|
const size_t replylen = strlen(replystr);
|
||||||
|
|
||||||
|
FILE *fl;
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
|
||||||
|
/** generate new destination keypair */
|
||||||
|
printf("generating keys...\n");
|
||||||
|
if (sam3GenerateKeys(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, 4) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't generate keys\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/** copy keypair into local buffer */
|
||||||
|
strncpy(pubkey, ses.pubkey, sizeof(pubkey));
|
||||||
|
strncpy(privkey, ses.privkey, sizeof(privkey));
|
||||||
|
/** create sam session */
|
||||||
|
printf("creating session...\n");
|
||||||
|
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, privkey,
|
||||||
|
SAM3_SESSION_DGRAM, 5, NULL) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create session\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/** make sure we have the right destination */
|
||||||
|
// FIXME: probably not needed
|
||||||
|
if (strcmp(pubkey, ses.pubkey) != 0) {
|
||||||
|
fprintf(stderr, "FATAL: destination keys don't match\n");
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/** print destination to stdout */
|
||||||
|
printf("PUB KEY\n=======\n%s\n=======\n", ses.pubkey);
|
||||||
|
if ((fl = fopen(KEYFILE, "wb")) != NULL) {
|
||||||
|
/** write public key to keyfile */
|
||||||
|
fwrite(pubkey, strlen(pubkey), 1, fl);
|
||||||
|
fclose(fl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now listen for UDP packets */
|
||||||
|
printf("starting main loop...\n");
|
||||||
|
for (;;) {
|
||||||
|
/** save replylen bytes for out reply at begining */
|
||||||
|
char *datagramBuf = buf + replylen;
|
||||||
|
const size_t datagramMaxLen = sizeof(buf) - replylen;
|
||||||
|
int sz, isquit;
|
||||||
|
printf("waiting for datagram...\n");
|
||||||
|
/** blocks until we get a UDP packet */
|
||||||
|
if ((sz = sam3DatagramReceive(&ses, datagramBuf, datagramMaxLen) < 0)) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/** ensure null terminated string */
|
||||||
|
datagramBuf[sz] = 0;
|
||||||
|
/** print out datagram payload to user */
|
||||||
|
printf("FROM\n====\n%s\n====\n", ses.destkey);
|
||||||
|
printf("SIZE=%d\n", sz);
|
||||||
|
printf("data: [%s]\n", datagramBuf);
|
||||||
|
/** check for "quit" */
|
||||||
|
isquit = (sz == quitlen && memcmp(datagramBuf, quitstr, quitlen) == 0);
|
||||||
|
/** echo datagram back to sender with "reply: " at the beginning */
|
||||||
|
memcpy(buf, replystr, replylen);
|
||||||
|
|
||||||
|
if (sam3DatagramSend(&ses, ses.destkey, buf, sz + replylen) < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s\n", ses.error);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/** if we got a quit command wait for 10 seconds and break out of the
|
||||||
|
* mainloop */
|
||||||
|
if (isquit) {
|
||||||
|
printf("shutting down...\n");
|
||||||
|
sleep(10); /* let dgram reach it's destination */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** close session and delete keyfile */
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
unlink(KEYFILE);
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
/** error case, close session, delete keyfile and return exit code 1 */
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
unlink(KEYFILE);
|
||||||
|
return 1;
|
||||||
|
}
|
43
supportlibs/libsam3/examples/sam3/namelookup.c
Normal file
43
supportlibs/libsam3/examples/sam3/namelookup.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3Session ses;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("usage: %s name [name...]\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/** for each name in arguments ... */
|
||||||
|
for (int n = 1; n < argc; ++n) {
|
||||||
|
if (!getenv("I2P_LOOKUP_QUIET")) {
|
||||||
|
fprintf(stdout, "%s ... ", argv[n]);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
/** do oneshot name lookup */
|
||||||
|
if (sam3NameLookup(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT, argv[n]) >=
|
||||||
|
0) {
|
||||||
|
fprintf(stdout, "%s\n\n", ses.destkey);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "FAILED [%s]\n", ses.error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
51
supportlibs/libsam3/examples/sam3/samtest.c
Normal file
51
supportlibs/libsam3/examples/sam3/samtest.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int fd;
|
||||||
|
SAMFieldList *rep = NULL;
|
||||||
|
const char *v;
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
//
|
||||||
|
if ((fd = sam3Handshake(NULL, 0, NULL)) < 0)
|
||||||
|
return 1;
|
||||||
|
//
|
||||||
|
if (sam3tcpPrintf(fd, "DEST GENERATE\n") < 0)
|
||||||
|
goto error;
|
||||||
|
rep = sam3ReadReply(fd);
|
||||||
|
// sam3DumpFieldList(rep);
|
||||||
|
if (!sam3IsGoodReply(rep, "DEST", "REPLY", "PUB", NULL))
|
||||||
|
goto error;
|
||||||
|
if (!sam3IsGoodReply(rep, "DEST", "REPLY", "PRIV", NULL))
|
||||||
|
goto error;
|
||||||
|
v = sam3FindField(rep, "PUB");
|
||||||
|
printf("PUB KEY\n=======\n%s\n", v);
|
||||||
|
v = sam3FindField(rep, "PRIV");
|
||||||
|
printf("PRIV KEY\n========\n%s\n", v);
|
||||||
|
sam3FreeFieldList(rep);
|
||||||
|
rep = NULL;
|
||||||
|
//
|
||||||
|
sam3FreeFieldList(rep);
|
||||||
|
sam3tcpDisconnect(fd);
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
sam3FreeFieldList(rep);
|
||||||
|
sam3tcpDisconnect(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
87
supportlibs/libsam3/examples/sam3/streamc.c
Normal file
87
supportlibs/libsam3/examples/sam3/streamc.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
#define KEYFILE "streams.key"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3Session ses;
|
||||||
|
Sam3Connection *conn;
|
||||||
|
char cmd[1024], destkey[617]; // 616 chars + \0
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
memset(destkey, 0, sizeof(destkey));
|
||||||
|
//
|
||||||
|
if (argc < 2) {
|
||||||
|
FILE *fl = fopen(KEYFILE, "rb");
|
||||||
|
//
|
||||||
|
if (fl != NULL) {
|
||||||
|
if (fread(destkey, 616, 1, fl) == 1) {
|
||||||
|
fclose(fl);
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
fclose(fl);
|
||||||
|
}
|
||||||
|
printf("usage: streamc PUBKEY\n");
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if (!sam3CheckValidKeyLength(argv[1])) {
|
||||||
|
fprintf(stderr, "FATAL: invalid key length! %s %lu\n", argv[1],
|
||||||
|
strlen(argv[1]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(destkey, argv[1]);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
ok:
|
||||||
|
printf("creating session...\n");
|
||||||
|
// create TRANSIENT session
|
||||||
|
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
|
||||||
|
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, 4,
|
||||||
|
NULL) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create session\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
printf("connecting...\n");
|
||||||
|
if ((conn = sam3StreamConnect(&ses, destkey)) == NULL) {
|
||||||
|
fprintf(stderr, "FATAL: can't connect: %s\n", ses.error);
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// now waiting for incoming connection
|
||||||
|
printf("sending test command...\n");
|
||||||
|
if (sam3tcpPrintf(conn->fd, "test\n") < 0)
|
||||||
|
goto error;
|
||||||
|
if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0)
|
||||||
|
goto error;
|
||||||
|
printf("echo: %s\n", cmd);
|
||||||
|
//
|
||||||
|
printf("sending quit command...\n");
|
||||||
|
if (sam3tcpPrintf(conn->fd, "quit\n") < 0)
|
||||||
|
goto error;
|
||||||
|
//
|
||||||
|
sam3CloseConnection(conn);
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
fprintf(stderr, "FATAL: some error occured!\n");
|
||||||
|
sam3CloseConnection(conn);
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 1;
|
||||||
|
}
|
72
supportlibs/libsam3/examples/sam3/streams.c
Normal file
72
supportlibs/libsam3/examples/sam3/streams.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../libsam3/libsam3.h"
|
||||||
|
|
||||||
|
#define KEYFILE "streams.key"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3Session ses;
|
||||||
|
Sam3Connection *conn;
|
||||||
|
FILE *fl;
|
||||||
|
//
|
||||||
|
libsam3_debug = 1;
|
||||||
|
//
|
||||||
|
printf("creating session...\n");
|
||||||
|
// create TRANSIENT session
|
||||||
|
if (sam3CreateSession(&ses, SAM3_HOST_DEFAULT, SAM3_PORT_DEFAULT,
|
||||||
|
SAM3_DESTINATION_TRANSIENT, SAM3_SESSION_STREAM, 4,
|
||||||
|
NULL) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create session\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
printf("PUB KEY\n=======\n%s\n=======\n", ses.pubkey);
|
||||||
|
if ((fl = fopen(KEYFILE, "wb")) != NULL) {
|
||||||
|
fwrite(ses.pubkey, strlen(ses.pubkey), 1, fl);
|
||||||
|
fclose(fl);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
printf("starting stream acceptor...\n");
|
||||||
|
if ((conn = sam3StreamAccept(&ses)) == NULL) {
|
||||||
|
fprintf(stderr, "FATAL: can't accept: %s\n", ses.error);
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printf("FROM\n====\n%s\n====\n", conn->destkey);
|
||||||
|
//
|
||||||
|
printf("starting main loop...\n");
|
||||||
|
for (;;) {
|
||||||
|
char cmd[256];
|
||||||
|
//
|
||||||
|
if (sam3tcpReceiveStr(conn->fd, cmd, sizeof(cmd)) < 0)
|
||||||
|
goto error;
|
||||||
|
printf("cmd: [%s]\n", cmd);
|
||||||
|
if (strcmp(cmd, "quit") == 0)
|
||||||
|
break;
|
||||||
|
// echo command
|
||||||
|
if (sam3tcpPrintf(conn->fd, "re: %s\n", cmd) < 0)
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
unlink(KEYFILE);
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
fprintf(stderr, "FATAL: some error occured!\n");
|
||||||
|
sam3CloseSession(&ses);
|
||||||
|
unlink(KEYFILE);
|
||||||
|
return 1;
|
||||||
|
}
|
178
supportlibs/libsam3/examples/sam3a/test00.c
Normal file
178
supportlibs/libsam3/examples/sam3a/test00.c
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "../libsam3a/libsam3a.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void scbErrorClose(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nSESION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ses->error);
|
||||||
|
sam3aCloseSession(ses); // it's safe here
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbNRCreated(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nNAME RESOLVED: [%s]\n",
|
||||||
|
ses->params);
|
||||||
|
fprintf(stderr, "PUB: %s\n===============================\n", ses->destkey);
|
||||||
|
sam3aCloseSession(ses); // it's safe here
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3ASessionCallbacks scbNR = {
|
||||||
|
.cbError = scbErrorClose,
|
||||||
|
.cbCreated = scbNRCreated,
|
||||||
|
.cbDisconnected = NULL,
|
||||||
|
.cbDatagramRead = NULL,
|
||||||
|
.cbDestroy = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void scbKGCreated(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nKEYS GENERATED\n");
|
||||||
|
fprintf(stderr, "\rPRIV: %s\n", ses->privkey);
|
||||||
|
fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey);
|
||||||
|
sam3aCloseSession(ses); // it's safe here
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3ASessionCallbacks scbKG = {
|
||||||
|
.cbError = scbErrorClose,
|
||||||
|
.cbCreated = scbKGCreated,
|
||||||
|
.cbDisconnected = NULL,
|
||||||
|
.cbDatagramRead = NULL,
|
||||||
|
.cbDestroy = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void scbError(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nSESION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ses->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbCreated(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_CREATED\n");
|
||||||
|
fprintf(stderr, "\rPRIV: %s\n", ses->privkey);
|
||||||
|
fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey);
|
||||||
|
sam3aCancelSession(ses); // it's safe here
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDisconnected(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n===="
|
||||||
|
"===========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n==="
|
||||||
|
"============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDestroy(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DESTROYED\n======="
|
||||||
|
"========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** callbacks for our SAM session */
|
||||||
|
static const Sam3ASessionCallbacks scb = {
|
||||||
|
.cbError = scbError,
|
||||||
|
.cbCreated = scbCreated,
|
||||||
|
.cbDisconnected = scbDisconnected,
|
||||||
|
.cbDatagramRead = scbDGramRead,
|
||||||
|
.cbDestroy = scbDestroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define HOST SAM3A_HOST_DEFAULT
|
||||||
|
//#define HOST "google.com"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3ASession ses, snr, skg;
|
||||||
|
//
|
||||||
|
// libsam3a_debug = 1;
|
||||||
|
//
|
||||||
|
if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT,
|
||||||
|
SAM3A_DESTINATION_TRANSIENT,
|
||||||
|
SAM3A_SESSION_STREAM) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create main session!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// generate keys
|
||||||
|
if (sam3aGenerateKeys(&skg, &scbKG, HOST, SAM3A_PORT_DEFAULT) < 0) {
|
||||||
|
sam3aCloseSession(&ses);
|
||||||
|
fprintf(stderr, "FATAL: can't create keygen session!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// do a name lookup for zzz.i2p
|
||||||
|
if (sam3aNameLookup(&snr, &scbNR, HOST, SAM3A_PORT_DEFAULT, "zzz.i2p") < 0) {
|
||||||
|
sam3aCloseSession(&skg);
|
||||||
|
sam3aCloseSession(&ses);
|
||||||
|
fprintf(stderr, "FATAL: can't create name resolving session!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// while we have sessions ...
|
||||||
|
while (sam3aIsActiveSession(&ses) || sam3aIsActiveSession(&snr) ||
|
||||||
|
sam3aIsActiveSession(&skg)) {
|
||||||
|
fd_set rds, wrs;
|
||||||
|
int res, maxfd = 0;
|
||||||
|
struct timeval to;
|
||||||
|
// set up file descriptors for select()
|
||||||
|
FD_ZERO(&rds);
|
||||||
|
FD_ZERO(&wrs);
|
||||||
|
// obtain the maximum fd for select()
|
||||||
|
if (sam3aIsActiveSession(&ses) &&
|
||||||
|
(maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0)
|
||||||
|
break;
|
||||||
|
if (sam3aIsActiveSession(&snr) &&
|
||||||
|
(maxfd = sam3aAddSessionToFDS(&snr, -1, &rds, &wrs)) < 0)
|
||||||
|
break;
|
||||||
|
if (sam3aIsActiveSession(&skg) &&
|
||||||
|
(maxfd = sam3aAddSessionToFDS(&skg, -1, &rds, &wrs)) < 0)
|
||||||
|
break;
|
||||||
|
// set timeout to 1 second
|
||||||
|
sam3ams2timeval(&to, 1000);
|
||||||
|
// call select()
|
||||||
|
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
fprintf(stderr, "FATAL: select() error!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
// idle, no activity
|
||||||
|
fprintf(stdout, ".");
|
||||||
|
fflush(stdout);
|
||||||
|
} else {
|
||||||
|
// we have activity, process io
|
||||||
|
if (sam3aIsActiveSession(&ses))
|
||||||
|
sam3aProcessSessionIO(&ses, &rds, &wrs);
|
||||||
|
if (sam3aIsActiveSession(&snr))
|
||||||
|
sam3aProcessSessionIO(&snr, &rds, &wrs);
|
||||||
|
if (sam3aIsActiveSession(&skg))
|
||||||
|
sam3aProcessSessionIO(&skg, &rds, &wrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// close seessions
|
||||||
|
sam3aCloseSession(&ses);
|
||||||
|
sam3aCloseSession(&skg);
|
||||||
|
sam3aCloseSession(&snr);
|
||||||
|
// exit
|
||||||
|
return 0;
|
||||||
|
}
|
205
supportlibs/libsam3/examples/sam3a/test_sc.c
Normal file
205
supportlibs/libsam3/examples/sam3a/test_sc.c
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "../libsam3a/libsam3a.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define KEYFILE "streams.key"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void ccbError(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nCONNECTION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ct->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbDisconnected(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_"
|
||||||
|
"DISCONNECTED\n===============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbConnected(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_CONNECTED\n==="
|
||||||
|
"============================\n");
|
||||||
|
// sam3aCancelConnection(ct); // cbSent() will not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbAccepted(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_ACCEPTED\n===="
|
||||||
|
"===========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbSent(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n==="
|
||||||
|
"============================\n");
|
||||||
|
// sam3aCancelConnection(ct);
|
||||||
|
// sam3aCancelSession(ct->ses); // hehe
|
||||||
|
fprintf(stderr, "(%p)\n", ct->udata);
|
||||||
|
//
|
||||||
|
switch ((intptr_t)ct->udata) {
|
||||||
|
case 0:
|
||||||
|
if (sam3aSend(ct, "test\n", -1) < 0) {
|
||||||
|
fprintf(stderr, "SEND ERROR!\n");
|
||||||
|
sam3aCancelSession(ct->ses); // hehe
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (sam3aSend(ct, "quit\n", -1) < 0) {
|
||||||
|
fprintf(stderr, "SEND ERROR!\n");
|
||||||
|
sam3aCancelSession(ct->ses); // hehe
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ct->udata = (void *)(((intptr_t)ct->udata) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbRead(Sam3AConnection *ct, const void *buf, int bufsize) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nCONNECTION_GOTBYTES "
|
||||||
|
"(%d)\n===============================\n",
|
||||||
|
bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbDestroy(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_DESTROY\n====="
|
||||||
|
"==========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3AConnectionCallbacks ccb = {
|
||||||
|
.cbError = ccbError,
|
||||||
|
.cbDisconnected = ccbDisconnected,
|
||||||
|
.cbConnected = ccbConnected,
|
||||||
|
.cbAccepted = ccbAccepted,
|
||||||
|
.cbSent = ccbSent,
|
||||||
|
.cbRead = ccbRead,
|
||||||
|
.cbDestroy = ccbDestroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void scbError(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nSESION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ses->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbCreated(Sam3ASession *ses) {
|
||||||
|
char destkey[517];
|
||||||
|
FILE *fl;
|
||||||
|
//
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_CREATED\n");
|
||||||
|
fprintf(stderr, "\rPRIV: %s\n", ses->privkey);
|
||||||
|
fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey);
|
||||||
|
//
|
||||||
|
fl = fopen(KEYFILE, "rb");
|
||||||
|
//
|
||||||
|
if (fl == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: NO KEY FILE!\n");
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fread(destkey, 516, 1, fl) != 1) {
|
||||||
|
fprintf(stderr, "ERROR: INVALID KEY FILE!\n");
|
||||||
|
fclose(fl);
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose(fl);
|
||||||
|
destkey[516] = 0;
|
||||||
|
if (sam3aStreamConnect(ses, &ccb, destkey) == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: CAN'T CREATE CONNECTION!\n");
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "GOON: creating connection...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDisconnected(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n===="
|
||||||
|
"===========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n==="
|
||||||
|
"============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDestroy(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DESTROYED\n======="
|
||||||
|
"========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3ASessionCallbacks scb = {
|
||||||
|
.cbError = scbError,
|
||||||
|
.cbCreated = scbCreated,
|
||||||
|
.cbDisconnected = scbDisconnected,
|
||||||
|
.cbDatagramRead = scbDGramRead,
|
||||||
|
.cbDestroy = scbDestroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define HOST SAM3A_HOST_DEFAULT
|
||||||
|
//#define HOST "google.com"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3ASession ses;
|
||||||
|
//
|
||||||
|
libsam3a_debug = 0;
|
||||||
|
//
|
||||||
|
if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT,
|
||||||
|
SAM3A_DESTINATION_TRANSIENT,
|
||||||
|
SAM3A_SESSION_STREAM) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create main session!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
while (sam3aIsActiveSession(&ses)) {
|
||||||
|
fd_set rds, wrs;
|
||||||
|
int res, maxfd = 0;
|
||||||
|
struct timeval to;
|
||||||
|
//
|
||||||
|
FD_ZERO(&rds);
|
||||||
|
FD_ZERO(&wrs);
|
||||||
|
if (sam3aIsActiveSession(&ses) &&
|
||||||
|
(maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0)
|
||||||
|
break;
|
||||||
|
sam3ams2timeval(&to, 1000);
|
||||||
|
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
fprintf(stderr, "FATAL: select() error!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
fprintf(stdout, ".");
|
||||||
|
fflush(stdout);
|
||||||
|
} else {
|
||||||
|
if (sam3aIsActiveSession(&ses))
|
||||||
|
sam3aProcessSessionIO(&ses, &rds, &wrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
sam3aCloseSession(&ses);
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
236
supportlibs/libsam3/examples/sam3a/test_ss.c
Normal file
236
supportlibs/libsam3/examples/sam3a/test_ss.c
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "../libsam3a/libsam3a.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define KEYFILE "streams.key"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef struct {
|
||||||
|
char *str;
|
||||||
|
int strsize;
|
||||||
|
int strused;
|
||||||
|
int doQuit;
|
||||||
|
} ConnData;
|
||||||
|
|
||||||
|
static void cdAppendChar(ConnData *d, char ch) {
|
||||||
|
if (d->strused + 1 >= d->strsize) {
|
||||||
|
// fuck errors
|
||||||
|
d->strsize = d->strused + 1024;
|
||||||
|
d->str = realloc(d->str, d->strsize + 1);
|
||||||
|
}
|
||||||
|
d->str[d->strused++] = ch;
|
||||||
|
d->str[d->strused] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void ccbError(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nCONNECTION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ct->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbDisconnected(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_"
|
||||||
|
"DISCONNECTED\n===============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbConnected(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_CONNECTED\n==="
|
||||||
|
"============================\n");
|
||||||
|
// sam3aCancelConnection(ct); // cbSent() will not be called
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbAccepted(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_ACCEPTED\n===="
|
||||||
|
"===========================\n");
|
||||||
|
fprintf(stderr, "FROM: %s\n===============================\n", ct->destkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbSent(Sam3AConnection *ct) {
|
||||||
|
ConnData *d = (ConnData *)ct->udata;
|
||||||
|
//
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_WANTBYTES\n==="
|
||||||
|
"============================\n");
|
||||||
|
if (d->doQuit) {
|
||||||
|
sam3aCancelSession(ct->ses); // hehe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbRead(Sam3AConnection *ct, const void *buf, int bufsize) {
|
||||||
|
const char *b = (const char *)buf;
|
||||||
|
ConnData *d = (ConnData *)ct->udata;
|
||||||
|
//
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nCONNECTION_GOTBYTES "
|
||||||
|
"(%d)\n===============================\n",
|
||||||
|
bufsize);
|
||||||
|
while (bufsize > 0) {
|
||||||
|
cdAppendChar(ct->udata, *b);
|
||||||
|
if (*b == '\n') {
|
||||||
|
fprintf(stderr, "cmd: %s", d->str);
|
||||||
|
if (strcasecmp(d->str, "quit\n") == 0)
|
||||||
|
d->doQuit = 1;
|
||||||
|
if (sam3aSend(ct, d->str, -1) < 0) {
|
||||||
|
// sam3aCancelConnection(ct); // hehe
|
||||||
|
sam3aCancelSession(ct->ses); // hehe
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d->str[0] = 0;
|
||||||
|
d->strused = 0;
|
||||||
|
}
|
||||||
|
++b;
|
||||||
|
--bufsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccbDestroy(Sam3AConnection *ct) {
|
||||||
|
fprintf(stderr, "\n===============================\nCONNECTION_DESTROY\n====="
|
||||||
|
"==========================\n");
|
||||||
|
if (ct->udata != NULL) {
|
||||||
|
ConnData *d = (ConnData *)ct->udata;
|
||||||
|
//
|
||||||
|
if (d->str != NULL)
|
||||||
|
free(d->str);
|
||||||
|
free(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3AConnectionCallbacks ccb = {
|
||||||
|
.cbError = ccbError,
|
||||||
|
.cbDisconnected = ccbDisconnected,
|
||||||
|
.cbConnected = ccbConnected,
|
||||||
|
.cbAccepted = ccbAccepted,
|
||||||
|
.cbSent = ccbSent,
|
||||||
|
.cbRead = ccbRead,
|
||||||
|
.cbDestroy = ccbDestroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static void scbError(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n===============================\nSESION_ERROR: "
|
||||||
|
"[%s]\n===============================\n",
|
||||||
|
ses->error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbCreated(Sam3ASession *ses) {
|
||||||
|
FILE *fl;
|
||||||
|
Sam3AConnection *conn;
|
||||||
|
//
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_CREATED\n");
|
||||||
|
fprintf(stderr, "\rPRIV: %s\n", ses->privkey);
|
||||||
|
fprintf(stderr, "\nPUB: %s\n===============================\n", ses->pubkey);
|
||||||
|
//
|
||||||
|
fl = fopen(KEYFILE, "wb");
|
||||||
|
//
|
||||||
|
if (fl == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: CAN'T CREATE KEY FILE!\n");
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fwrite(ses->pubkey, 516, 1, fl) != 1) {
|
||||||
|
fprintf(stderr, "ERROR: CAN'T WRITE KEY FILE!\n");
|
||||||
|
fclose(fl);
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose(fl);
|
||||||
|
if ((conn = sam3aStreamAccept(ses, &ccb)) == NULL) {
|
||||||
|
fprintf(stderr, "ERROR: CAN'T CREATE CONNECTION!\n");
|
||||||
|
sam3aCancelSession(ses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
conn->udata = calloc(1, sizeof(ConnData));
|
||||||
|
fprintf(stderr, "GOON: accepting connection...\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDisconnected(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DISCONNECTED\n===="
|
||||||
|
"===========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDGramRead(Sam3ASession *ses, const void *buf, int bufsize) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DATAGRAM_READ\n==="
|
||||||
|
"============================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scbDestroy(Sam3ASession *ses) {
|
||||||
|
fprintf(stderr, "\n===============================\nSESION_DESTROYED\n======="
|
||||||
|
"========================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Sam3ASessionCallbacks scb = {
|
||||||
|
.cbError = scbError,
|
||||||
|
.cbCreated = scbCreated,
|
||||||
|
.cbDisconnected = scbDisconnected,
|
||||||
|
.cbDatagramRead = scbDGramRead,
|
||||||
|
.cbDestroy = scbDestroy,
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define HOST SAM3A_HOST_DEFAULT
|
||||||
|
//#define HOST "google.com"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
Sam3ASession ses;
|
||||||
|
//
|
||||||
|
libsam3a_debug = 0;
|
||||||
|
//
|
||||||
|
if (sam3aCreateSession(&ses, &scb, HOST, SAM3A_PORT_DEFAULT,
|
||||||
|
SAM3A_DESTINATION_TRANSIENT,
|
||||||
|
SAM3A_SESSION_STREAM) < 0) {
|
||||||
|
fprintf(stderr, "FATAL: can't create main session!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
while (sam3aIsActiveSession(&ses)) {
|
||||||
|
fd_set rds, wrs;
|
||||||
|
int res, maxfd = 0;
|
||||||
|
struct timeval to;
|
||||||
|
//
|
||||||
|
FD_ZERO(&rds);
|
||||||
|
FD_ZERO(&wrs);
|
||||||
|
if (sam3aIsActiveSession(&ses) &&
|
||||||
|
(maxfd = sam3aAddSessionToFDS(&ses, -1, &rds, &wrs)) < 0)
|
||||||
|
break;
|
||||||
|
sam3ams2timeval(&to, 1000);
|
||||||
|
res = select(maxfd + 1, &rds, &wrs, NULL, &to);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
fprintf(stderr, "FATAL: select() error!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
fprintf(stdout, ".");
|
||||||
|
fflush(stdout);
|
||||||
|
} else {
|
||||||
|
if (sam3aIsActiveSession(&ses))
|
||||||
|
sam3aProcessSessionIO(&ses, &rds, &wrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
sam3aCloseSession(&ses);
|
||||||
|
//
|
||||||
|
return 0;
|
||||||
|
}
|
466
supportlibs/libsam3/src/ext/tinytest.c
Normal file
466
supportlibs/libsam3/src/ext/tinytest.c
Normal file
@ -0,0 +1,466 @@
|
|||||||
|
/* tinytest.c -- Copyright 2009-2012 Nick Mathewson
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#ifdef TINYTEST_LOCAL
|
||||||
|
#include "tinytest_local.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef NO_FORKING
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
|
||||||
|
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
|
||||||
|
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
|
||||||
|
/* Workaround for a stupid bug in OSX 10.6 */
|
||||||
|
#define FORK_BREAKS_GCOV
|
||||||
|
#include <vproc.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !NO_FORKING */
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
#define __attribute__(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "tinytest.h"
|
||||||
|
#include "tinytest_macros.h"
|
||||||
|
|
||||||
|
#define LONGEST_TEST_NAME 16384
|
||||||
|
|
||||||
|
static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/
|
||||||
|
static int n_ok = 0; /**< Number of tests that have passed */
|
||||||
|
static int n_bad = 0; /**< Number of tests that have failed. */
|
||||||
|
static int n_skipped = 0; /**< Number of tests that have been skipped. */
|
||||||
|
|
||||||
|
static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/
|
||||||
|
static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
|
||||||
|
static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
|
||||||
|
const char *verbosity_flag = "";
|
||||||
|
|
||||||
|
const struct testlist_alias_t *cfg_aliases = NULL;
|
||||||
|
|
||||||
|
enum outcome { SKIP = 2, OK = 1, FAIL = 0 };
|
||||||
|
static enum outcome cur_test_outcome = FAIL;
|
||||||
|
const char *cur_test_prefix = NULL; /**< prefix of the current test group */
|
||||||
|
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
|
||||||
|
const char *cur_test_name = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Copy of argv[0] for win32. */
|
||||||
|
static char commandname[MAX_PATH + 1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void usage(struct testgroup_t *groups, int list_groups)
|
||||||
|
__attribute__((noreturn));
|
||||||
|
static int process_test_option(struct testgroup_t *groups, const char *test);
|
||||||
|
|
||||||
|
static enum outcome testcase_run_bare_(const struct testcase_t *testcase) {
|
||||||
|
void *env = NULL;
|
||||||
|
enum outcome outcome;
|
||||||
|
if (testcase->setup) {
|
||||||
|
env = testcase->setup->setup_fn(testcase);
|
||||||
|
if (!env)
|
||||||
|
return FAIL;
|
||||||
|
else if (env == (void *)TT_SKIP)
|
||||||
|
return SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_test_outcome = OK;
|
||||||
|
testcase->fn(env);
|
||||||
|
outcome = cur_test_outcome;
|
||||||
|
|
||||||
|
if (testcase->setup) {
|
||||||
|
if (testcase->setup->cleanup_fn(testcase, env) == 0)
|
||||||
|
outcome = FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAGIC_EXITCODE 42
|
||||||
|
|
||||||
|
#ifndef NO_FORKING
|
||||||
|
|
||||||
|
static enum outcome testcase_run_forked_(const struct testgroup_t *group,
|
||||||
|
const struct testcase_t *testcase) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Fork? On Win32? How primitive! We'll do what the smart kids do:
|
||||||
|
we'll invoke our own exe (whose name we recall from the command
|
||||||
|
line) with a command line that tells it to run just the test we
|
||||||
|
want, and this time without forking.
|
||||||
|
|
||||||
|
(No, threads aren't an option. The whole point of forking is to
|
||||||
|
share no state between tests.)
|
||||||
|
*/
|
||||||
|
int ok;
|
||||||
|
char buffer[LONGEST_TEST_NAME + 256];
|
||||||
|
STARTUPINFOA si;
|
||||||
|
PROCESS_INFORMATION info;
|
||||||
|
DWORD exitcode;
|
||||||
|
|
||||||
|
if (!in_tinytest_main) {
|
||||||
|
printf("\nERROR. On Windows, testcase_run_forked_ must be"
|
||||||
|
" called from within tinytest_main.\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (opt_verbosity > 0)
|
||||||
|
printf("[forking] ");
|
||||||
|
|
||||||
|
snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", commandname,
|
||||||
|
verbosity_flag, group->prefix, testcase->name);
|
||||||
|
|
||||||
|
memset(&si, 0, sizeof(si));
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
|
||||||
|
ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, 0, NULL, NULL, &si,
|
||||||
|
&info);
|
||||||
|
if (!ok) {
|
||||||
|
printf("CreateProcess failed!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
WaitForSingleObject(info.hProcess, INFINITE);
|
||||||
|
GetExitCodeProcess(info.hProcess, &exitcode);
|
||||||
|
CloseHandle(info.hProcess);
|
||||||
|
CloseHandle(info.hThread);
|
||||||
|
if (exitcode == 0)
|
||||||
|
return OK;
|
||||||
|
else if (exitcode == MAGIC_EXITCODE)
|
||||||
|
return SKIP;
|
||||||
|
else
|
||||||
|
return FAIL;
|
||||||
|
#else
|
||||||
|
int outcome_pipe[2];
|
||||||
|
pid_t pid;
|
||||||
|
(void)group;
|
||||||
|
|
||||||
|
if (pipe(outcome_pipe))
|
||||||
|
perror("opening pipe");
|
||||||
|
|
||||||
|
if (opt_verbosity > 0)
|
||||||
|
printf("[forking] ");
|
||||||
|
pid = fork();
|
||||||
|
#ifdef FORK_BREAKS_GCOV
|
||||||
|
vproc_transaction_begin(0);
|
||||||
|
#endif
|
||||||
|
if (!pid) {
|
||||||
|
/* child. */
|
||||||
|
int test_r, write_r;
|
||||||
|
char b[1];
|
||||||
|
close(outcome_pipe[0]);
|
||||||
|
test_r = testcase_run_bare_(testcase);
|
||||||
|
assert(0 <= (int)test_r && (int)test_r <= 2);
|
||||||
|
b[0] = "NYS"[test_r];
|
||||||
|
write_r = (int)write(outcome_pipe[1], b, 1);
|
||||||
|
if (write_r != 1) {
|
||||||
|
perror("write outcome to pipe");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
return FAIL; /* unreachable */
|
||||||
|
} else {
|
||||||
|
/* parent */
|
||||||
|
int status, r;
|
||||||
|
char b[1];
|
||||||
|
/* Close this now, so that if the other side closes it,
|
||||||
|
* our read fails. */
|
||||||
|
close(outcome_pipe[1]);
|
||||||
|
r = (int)read(outcome_pipe[0], b, 1);
|
||||||
|
if (r == 0) {
|
||||||
|
printf("[Lost connection!] ");
|
||||||
|
return FAIL;
|
||||||
|
} else if (r != 1) {
|
||||||
|
perror("read outcome from pipe");
|
||||||
|
}
|
||||||
|
waitpid(pid, &status, 0);
|
||||||
|
close(outcome_pipe[0]);
|
||||||
|
return b[0] == 'Y' ? OK : (b[0] == 'S' ? SKIP : FAIL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !NO_FORKING */
|
||||||
|
|
||||||
|
int testcase_run_one(const struct testgroup_t *group,
|
||||||
|
const struct testcase_t *testcase) {
|
||||||
|
enum outcome outcome;
|
||||||
|
|
||||||
|
if (testcase->flags & (TT_SKIP | TT_OFF_BY_DEFAULT)) {
|
||||||
|
if (opt_verbosity > 0)
|
||||||
|
printf("%s%s: %s\n", group->prefix, testcase->name,
|
||||||
|
(testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED");
|
||||||
|
++n_skipped;
|
||||||
|
return SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_verbosity > 0 && !opt_forked) {
|
||||||
|
printf("%s%s: ", group->prefix, testcase->name);
|
||||||
|
} else {
|
||||||
|
if (opt_verbosity == 0)
|
||||||
|
printf(".");
|
||||||
|
cur_test_prefix = group->prefix;
|
||||||
|
cur_test_name = testcase->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NO_FORKING
|
||||||
|
if ((testcase->flags & TT_FORK) && !(opt_forked || opt_nofork)) {
|
||||||
|
outcome = testcase_run_forked_(group, testcase);
|
||||||
|
} else {
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
outcome = testcase_run_bare_(testcase);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outcome == OK) {
|
||||||
|
++n_ok;
|
||||||
|
if (opt_verbosity > 0 && !opt_forked)
|
||||||
|
puts(opt_verbosity == 1 ? "OK" : "");
|
||||||
|
} else if (outcome == SKIP) {
|
||||||
|
++n_skipped;
|
||||||
|
if (opt_verbosity > 0 && !opt_forked)
|
||||||
|
puts("SKIPPED");
|
||||||
|
} else {
|
||||||
|
++n_bad;
|
||||||
|
if (!opt_forked)
|
||||||
|
printf("\n [%s FAILED]\n", testcase->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt_forked) {
|
||||||
|
exit(outcome == OK ? 0 : (outcome == SKIP ? MAGIC_EXITCODE : 1));
|
||||||
|
return 1; /* unreachable */
|
||||||
|
} else {
|
||||||
|
return (int)outcome;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set,
|
||||||
|
unsigned long flag) {
|
||||||
|
int i, j;
|
||||||
|
size_t length = LONGEST_TEST_NAME;
|
||||||
|
char fullname[LONGEST_TEST_NAME];
|
||||||
|
int found = 0;
|
||||||
|
if (strstr(arg, ".."))
|
||||||
|
length = strstr(arg, "..") - arg;
|
||||||
|
for (i = 0; groups[i].prefix; ++i) {
|
||||||
|
for (j = 0; groups[i].cases[j].name; ++j) {
|
||||||
|
struct testcase_t *testcase = &groups[i].cases[j];
|
||||||
|
snprintf(fullname, sizeof(fullname), "%s%s", groups[i].prefix,
|
||||||
|
testcase->name);
|
||||||
|
if (!flag) { /* Hack! */
|
||||||
|
printf(" %s", fullname);
|
||||||
|
if (testcase->flags & TT_OFF_BY_DEFAULT)
|
||||||
|
puts(" (Off by default)");
|
||||||
|
else if (testcase->flags & TT_SKIP)
|
||||||
|
puts(" (DISABLED)");
|
||||||
|
else
|
||||||
|
puts("");
|
||||||
|
}
|
||||||
|
if (!strncmp(fullname, arg, length)) {
|
||||||
|
if (set)
|
||||||
|
testcase->flags |= flag;
|
||||||
|
else
|
||||||
|
testcase->flags &= ~flag;
|
||||||
|
++found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(struct testgroup_t *groups, int list_groups) {
|
||||||
|
puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
|
||||||
|
puts(" Specify tests by name, or using a prefix ending with '..'");
|
||||||
|
puts(" To skip a test, prefix its name with a colon.");
|
||||||
|
puts(" To enable a disabled test, prefix its name with a plus.");
|
||||||
|
puts(" Use --list-tests for a list of tests.");
|
||||||
|
if (list_groups) {
|
||||||
|
puts("Known tests are:");
|
||||||
|
tinytest_set_flag_(groups, "..", 1, 0);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_test_alias(struct testgroup_t *groups, const char *test) {
|
||||||
|
int i, j, n, r;
|
||||||
|
for (i = 0; cfg_aliases && cfg_aliases[i].name; ++i) {
|
||||||
|
if (!strcmp(cfg_aliases[i].name, test)) {
|
||||||
|
n = 0;
|
||||||
|
for (j = 0; cfg_aliases[i].tests[j]; ++j) {
|
||||||
|
r = process_test_option(groups, cfg_aliases[i].tests[j]);
|
||||||
|
if (r < 0)
|
||||||
|
return -1;
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("No such test alias as @%s!", test);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int process_test_option(struct testgroup_t *groups, const char *test) {
|
||||||
|
int flag = TT_ENABLED_;
|
||||||
|
int n = 0;
|
||||||
|
if (test[0] == '@') {
|
||||||
|
return process_test_alias(groups, test + 1);
|
||||||
|
} else if (test[0] == ':') {
|
||||||
|
++test;
|
||||||
|
flag = TT_SKIP;
|
||||||
|
} else if (test[0] == '+') {
|
||||||
|
++test;
|
||||||
|
++n;
|
||||||
|
if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
|
||||||
|
printf("No such test as %s!\n", test);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
if (!tinytest_set_flag_(groups, test, 1, flag)) {
|
||||||
|
printf("No such test as %s!\n", test);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tinytest_set_aliases(const struct testlist_alias_t *aliases) {
|
||||||
|
cfg_aliases = aliases;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tinytest_main(int c, const char **v, struct testgroup_t *groups) {
|
||||||
|
int i, j, n = 0;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const char *sp = strrchr(v[0], '.');
|
||||||
|
const char *extension = "";
|
||||||
|
if (!sp || stricmp(sp, ".exe"))
|
||||||
|
extension = ".exe"; /* Add an exe so CreateProcess will work */
|
||||||
|
snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension);
|
||||||
|
commandname[MAX_PATH] = '\0';
|
||||||
|
#endif
|
||||||
|
for (i = 1; i < c; ++i) {
|
||||||
|
if (v[i][0] == '-') {
|
||||||
|
if (!strcmp(v[i], "--RUNNING-FORKED")) {
|
||||||
|
opt_forked = 1;
|
||||||
|
} else if (!strcmp(v[i], "--no-fork")) {
|
||||||
|
opt_nofork = 1;
|
||||||
|
} else if (!strcmp(v[i], "--quiet")) {
|
||||||
|
opt_verbosity = -1;
|
||||||
|
verbosity_flag = "--quiet";
|
||||||
|
} else if (!strcmp(v[i], "--verbose")) {
|
||||||
|
opt_verbosity = 2;
|
||||||
|
verbosity_flag = "--verbose";
|
||||||
|
} else if (!strcmp(v[i], "--terse")) {
|
||||||
|
opt_verbosity = 0;
|
||||||
|
verbosity_flag = "--terse";
|
||||||
|
} else if (!strcmp(v[i], "--help")) {
|
||||||
|
usage(groups, 0);
|
||||||
|
} else if (!strcmp(v[i], "--list-tests")) {
|
||||||
|
usage(groups, 1);
|
||||||
|
} else {
|
||||||
|
printf("Unknown option %s. Try --help\n", v[i]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int r = process_test_option(groups, v[i]);
|
||||||
|
if (r < 0)
|
||||||
|
return -1;
|
||||||
|
n += r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!n)
|
||||||
|
tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
|
||||||
|
|
||||||
|
#ifdef _IONBF
|
||||||
|
setvbuf(stdout, NULL, _IONBF, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
++in_tinytest_main;
|
||||||
|
for (i = 0; groups[i].prefix; ++i)
|
||||||
|
for (j = 0; groups[i].cases[j].name; ++j)
|
||||||
|
if (groups[i].cases[j].flags & TT_ENABLED_)
|
||||||
|
testcase_run_one(&groups[i], &groups[i].cases[j]);
|
||||||
|
|
||||||
|
--in_tinytest_main;
|
||||||
|
|
||||||
|
if (opt_verbosity == 0)
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
if (n_bad)
|
||||||
|
printf("%d/%d TESTS FAILED. (%d skipped)\n", n_bad, n_bad + n_ok,
|
||||||
|
n_skipped);
|
||||||
|
else if (opt_verbosity >= 1)
|
||||||
|
printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped);
|
||||||
|
|
||||||
|
return (n_bad == 0) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tinytest_get_verbosity_(void) { return opt_verbosity; }
|
||||||
|
|
||||||
|
void tinytest_set_test_failed_(void) {
|
||||||
|
if (opt_verbosity <= 0 && cur_test_name) {
|
||||||
|
if (opt_verbosity == 0)
|
||||||
|
puts("");
|
||||||
|
printf("%s%s: ", cur_test_prefix, cur_test_name);
|
||||||
|
cur_test_name = NULL;
|
||||||
|
}
|
||||||
|
cur_test_outcome = FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tinytest_set_test_skipped_(void) {
|
||||||
|
if (cur_test_outcome == OK)
|
||||||
|
cur_test_outcome = SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *tinytest_format_hex_(const void *val_, unsigned long len) {
|
||||||
|
const unsigned char *val = (unsigned char *)val_;
|
||||||
|
char *result, *cp;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!val)
|
||||||
|
return strdup("null");
|
||||||
|
if (!(result = (char *)malloc(len * 2 + 1)))
|
||||||
|
return strdup("<allocation failure>");
|
||||||
|
cp = result;
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
*cp++ = "0123456789ABCDEF"[val[i] >> 4];
|
||||||
|
*cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
|
||||||
|
}
|
||||||
|
*cp = 0;
|
||||||
|
return result;
|
||||||
|
}
|
104
supportlibs/libsam3/src/ext/tinytest.h
Normal file
104
supportlibs/libsam3/src/ext/tinytest.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/* tinytest.h -- Copyright 2009-2012 Nick Mathewson
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TINYTEST_H_INCLUDED_
|
||||||
|
#define TINYTEST_H_INCLUDED_
|
||||||
|
|
||||||
|
/** Flag for a test that needs to run in a subprocess. */
|
||||||
|
#define TT_FORK (1 << 0)
|
||||||
|
/** Runtime flag for a test we've decided to skip. */
|
||||||
|
#define TT_SKIP (1 << 1)
|
||||||
|
/** Internal runtime flag for a test we've decided to run. */
|
||||||
|
#define TT_ENABLED_ (1 << 2)
|
||||||
|
/** Flag for a test that's off by default. */
|
||||||
|
#define TT_OFF_BY_DEFAULT (1 << 3)
|
||||||
|
/** If you add your own flags, make them start at this point. */
|
||||||
|
#define TT_FIRST_USER_FLAG (1 << 4)
|
||||||
|
|
||||||
|
typedef void (*testcase_fn)(void *);
|
||||||
|
|
||||||
|
struct testcase_t;
|
||||||
|
|
||||||
|
/** Functions to initialize/teardown a structure for a testcase. */
|
||||||
|
struct testcase_setup_t {
|
||||||
|
/** Return a new structure for use by a given testcase. */
|
||||||
|
void *(*setup_fn)(const struct testcase_t *);
|
||||||
|
/** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */
|
||||||
|
int (*cleanup_fn)(const struct testcase_t *, void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A single test-case that you can run. */
|
||||||
|
struct testcase_t {
|
||||||
|
const char *name; /**< An identifier for this case. */
|
||||||
|
testcase_fn fn; /**< The function to run to implement this case. */
|
||||||
|
unsigned long flags; /**< Bitfield of TT_* flags. */
|
||||||
|
const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/
|
||||||
|
void *setup_data; /**< Extra data usable by setup function */
|
||||||
|
};
|
||||||
|
#define END_OF_TESTCASES \
|
||||||
|
{ NULL, NULL, 0, NULL, NULL }
|
||||||
|
|
||||||
|
/** A group of tests that are selectable together. */
|
||||||
|
struct testgroup_t {
|
||||||
|
const char *prefix; /**< Prefix to prepend to testnames. */
|
||||||
|
struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */
|
||||||
|
};
|
||||||
|
#define END_OF_GROUPS \
|
||||||
|
{ NULL, NULL }
|
||||||
|
|
||||||
|
struct testlist_alias_t {
|
||||||
|
const char *name;
|
||||||
|
const char **tests;
|
||||||
|
};
|
||||||
|
#define END_OF_ALIASES \
|
||||||
|
{ NULL, NULL }
|
||||||
|
|
||||||
|
/** Implementation: called from a test to indicate failure, before logging. */
|
||||||
|
void tinytest_set_test_failed_(void);
|
||||||
|
/** Implementation: called from a test to indicate that we're skipping. */
|
||||||
|
void tinytest_set_test_skipped_(void);
|
||||||
|
/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */
|
||||||
|
int tinytest_get_verbosity_(void);
|
||||||
|
/** Implementation: Set a flag on tests matching a name; returns number
|
||||||
|
* of tests that matched. */
|
||||||
|
int tinytest_set_flag_(struct testgroup_t *, const char *, int set,
|
||||||
|
unsigned long);
|
||||||
|
/** Implementation: Put a chunk of memory into hex. */
|
||||||
|
char *tinytest_format_hex_(const void *, unsigned long);
|
||||||
|
|
||||||
|
/** Set all tests in 'groups' matching the name 'named' to be skipped. */
|
||||||
|
#define tinytest_skip(groups, named) \
|
||||||
|
tinytest_set_flag_(groups, named, 1, TT_SKIP)
|
||||||
|
|
||||||
|
/** Run a single testcase in a single group. */
|
||||||
|
int testcase_run_one(const struct testgroup_t *, const struct testcase_t *);
|
||||||
|
|
||||||
|
void tinytest_set_aliases(const struct testlist_alias_t *aliases);
|
||||||
|
|
||||||
|
/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups,
|
||||||
|
as selected from the command line. */
|
||||||
|
int tinytest_main(int argc, const char **argv, struct testgroup_t *groups);
|
||||||
|
|
||||||
|
#endif
|
219
supportlibs/libsam3/src/ext/tinytest_macros.h
Normal file
219
supportlibs/libsam3/src/ext/tinytest_macros.h
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TINYTEST_MACROS_H_INCLUDED_
|
||||||
|
#define TINYTEST_MACROS_H_INCLUDED_
|
||||||
|
|
||||||
|
/* Helpers for defining statement-like macros */
|
||||||
|
#define TT_STMT_BEGIN do {
|
||||||
|
#define TT_STMT_END \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
/* Redefine this if your test functions want to abort with something besides
|
||||||
|
* "goto end;" */
|
||||||
|
#ifndef TT_EXIT_TEST_FUNCTION
|
||||||
|
#define TT_EXIT_TEST_FUNCTION \
|
||||||
|
TT_STMT_BEGIN goto end; \
|
||||||
|
TT_STMT_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Redefine this if you want to note success/failure in some different way. */
|
||||||
|
#ifndef TT_DECLARE
|
||||||
|
#define TT_DECLARE(prefix, args) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
printf("\n %s %s:%d: ", prefix, __FILE__, __LINE__); \
|
||||||
|
printf args; \
|
||||||
|
TT_STMT_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Announce a failure. Args are parenthesized printf args. */
|
||||||
|
#define TT_GRIPE(args) TT_DECLARE("FAIL", args)
|
||||||
|
|
||||||
|
/* Announce a non-failure if we're verbose. */
|
||||||
|
#define TT_BLATHER(args) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
if (tinytest_get_verbosity_() > 1) \
|
||||||
|
TT_DECLARE(" OK", args); \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
#define TT_DIE(args) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
tinytest_set_test_failed_(); \
|
||||||
|
TT_GRIPE(args); \
|
||||||
|
TT_EXIT_TEST_FUNCTION; \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
#define TT_FAIL(args) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
tinytest_set_test_failed_(); \
|
||||||
|
TT_GRIPE(args); \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
/* Fail and abort the current test for the reason in msg */
|
||||||
|
#define tt_abort_printf(msg) TT_DIE(msg)
|
||||||
|
#define tt_abort_perror(op) \
|
||||||
|
TT_DIE(("%s: %s [%d]", (op), strerror(errno), errno))
|
||||||
|
#define tt_abort_msg(msg) TT_DIE(("%s", msg))
|
||||||
|
#define tt_abort() TT_DIE(("%s", "(Failed.)"))
|
||||||
|
|
||||||
|
/* Fail but do not abort the current test for the reason in msg. */
|
||||||
|
#define tt_fail_printf(msg) TT_FAIL(msg)
|
||||||
|
#define tt_fail_perror(op) \
|
||||||
|
TT_FAIL(("%s: %s [%d]", (op), strerror(errno), errno))
|
||||||
|
#define tt_fail_msg(msg) TT_FAIL(("%s", msg))
|
||||||
|
#define tt_fail() TT_FAIL(("%s", "(Failed.)"))
|
||||||
|
|
||||||
|
/* End the current test, and indicate we are skipping it. */
|
||||||
|
#define tt_skip() \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
tinytest_set_test_skipped_(); \
|
||||||
|
TT_EXIT_TEST_FUNCTION; \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
#define tt_want_(b, msg, fail) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
if (!(b)) { \
|
||||||
|
tinytest_set_test_failed_(); \
|
||||||
|
TT_GRIPE(("%s", msg)); \
|
||||||
|
fail; \
|
||||||
|
} else { \
|
||||||
|
TT_BLATHER(("%s", msg)); \
|
||||||
|
} \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
/* Assert b, but do not stop the test if b fails. Log msg on failure. */
|
||||||
|
#define tt_want_msg(b, msg) tt_want_(b, msg, );
|
||||||
|
|
||||||
|
/* Assert b and stop the test if b fails. Log msg on failure. */
|
||||||
|
#define tt_assert_msg(b, msg) tt_want_(b, msg, TT_EXIT_TEST_FUNCTION);
|
||||||
|
|
||||||
|
/* Assert b, but do not stop the test if b fails. */
|
||||||
|
#define tt_want(b) tt_want_msg((b), "want(" #b ")")
|
||||||
|
/* Assert b, and stop the test if b fails. */
|
||||||
|
#define tt_assert(b) tt_assert_msg((b), "assert(" #b ")")
|
||||||
|
|
||||||
|
#define tt_assert_test_fmt_type(a, b, str_test, type, test, printf_type, \
|
||||||
|
printf_fmt, setup_block, cleanup_block, \
|
||||||
|
die_on_fail) \
|
||||||
|
TT_STMT_BEGIN \
|
||||||
|
type val1_ = (a); \
|
||||||
|
type val2_ = (b); \
|
||||||
|
int tt_status_ = (test); \
|
||||||
|
if (!tt_status_ || tinytest_get_verbosity_() > 1) { \
|
||||||
|
printf_type print_; \
|
||||||
|
printf_type print1_; \
|
||||||
|
printf_type print2_; \
|
||||||
|
type value_ = val1_; \
|
||||||
|
setup_block; \
|
||||||
|
print1_ = print_; \
|
||||||
|
value_ = val2_; \
|
||||||
|
setup_block; \
|
||||||
|
print2_ = print_; \
|
||||||
|
TT_DECLARE(tt_status_ ? " OK" : "FAIL", \
|
||||||
|
("assert(%s): " printf_fmt " vs " printf_fmt, str_test, \
|
||||||
|
print1_, print2_)); \
|
||||||
|
print_ = print1_; \
|
||||||
|
cleanup_block; \
|
||||||
|
print_ = print2_; \
|
||||||
|
cleanup_block; \
|
||||||
|
if (!tt_status_) { \
|
||||||
|
tinytest_set_test_failed_(); \
|
||||||
|
die_on_fail; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
TT_STMT_END
|
||||||
|
|
||||||
|
#define tt_assert_test_type(a, b, str_test, type, test, fmt, die_on_fail) \
|
||||||
|
tt_assert_test_fmt_type(a, b, str_test, type, test, type, fmt, \
|
||||||
|
{ print_ = value_; }, {}, die_on_fail)
|
||||||
|
|
||||||
|
#define tt_assert_test_type_opt(a, b, str_test, type, test, fmt, die_on_fail) \
|
||||||
|
tt_assert_test_fmt_type(a, b, str_test, type, test, type, fmt, \
|
||||||
|
{ print_ = value_ ? value_ : "<NULL>"; }, {}, \
|
||||||
|
die_on_fail)
|
||||||
|
|
||||||
|
/* Helper: assert that a op b, when cast to type. Format the values with
|
||||||
|
* printf format fmt on failure. */
|
||||||
|
#define tt_assert_op_type(a, op, b, type, fmt) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, type, (val1_ op val2_), fmt, \
|
||||||
|
TT_EXIT_TEST_FUNCTION)
|
||||||
|
|
||||||
|
#define tt_int_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, long, (val1_ op val2_), "%ld", \
|
||||||
|
TT_EXIT_TEST_FUNCTION)
|
||||||
|
|
||||||
|
#define tt_uint_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, unsigned long, \
|
||||||
|
(val1_ op val2_), "%lu", TT_EXIT_TEST_FUNCTION)
|
||||||
|
|
||||||
|
#define tt_ptr_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, const void *, (val1_ op val2_), \
|
||||||
|
"%p", TT_EXIT_TEST_FUNCTION)
|
||||||
|
|
||||||
|
#define tt_str_op(a, op, b) \
|
||||||
|
tt_assert_test_type_opt(a, b, #a " " #op " " #b, const char *, \
|
||||||
|
(val1_ && val2_ && strcmp(val1_, val2_) op 0), \
|
||||||
|
"<%s>", TT_EXIT_TEST_FUNCTION)
|
||||||
|
|
||||||
|
#define tt_mem_op(expr1, op, expr2, len) \
|
||||||
|
tt_assert_test_fmt_type( \
|
||||||
|
expr1, expr2, #expr1 " " #op " " #expr2, const void *, \
|
||||||
|
(val1_ && val2_ && memcmp(val1_, val2_, len) op 0), char *, "%s", \
|
||||||
|
{ print_ = tinytest_format_hex_(value_, (len)); }, \
|
||||||
|
{ \
|
||||||
|
if (print_) \
|
||||||
|
free(print_); \
|
||||||
|
}, \
|
||||||
|
TT_EXIT_TEST_FUNCTION);
|
||||||
|
|
||||||
|
#define tt_want_int_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, long, (val1_ op val2_), "%ld", \
|
||||||
|
(void)0)
|
||||||
|
|
||||||
|
#define tt_want_uint_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, unsigned long, \
|
||||||
|
(val1_ op val2_), "%lu", (void)0)
|
||||||
|
|
||||||
|
#define tt_want_ptr_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, const void *, (val1_ op val2_), \
|
||||||
|
"%p", (void)0)
|
||||||
|
|
||||||
|
#define tt_want_str_op(a, op, b) \
|
||||||
|
tt_assert_test_type(a, b, #a " " #op " " #b, const char *, \
|
||||||
|
(strcmp(val1_, val2_) op 0), "<%s>", (void)0)
|
||||||
|
|
||||||
|
#define tt_want_mem_op(expr1, op, expr2, len) \
|
||||||
|
tt_assert_test_fmt_type( \
|
||||||
|
expr1, expr2, #expr1 " " #op " " #expr2, const void *, \
|
||||||
|
(val1_ && val2_ && memcmp(val1_, val2_, len) op 0), char *, "%s", \
|
||||||
|
{ print_ = tinytest_format_hex_(value_, (len)); }, \
|
||||||
|
{ \
|
||||||
|
if (print_) \
|
||||||
|
free(print_); \
|
||||||
|
}, \
|
||||||
|
(void)0);
|
||||||
|
|
||||||
|
#endif
|
1304
supportlibs/libsam3/src/libsam3/libsam3.c
Normal file
1304
supportlibs/libsam3/src/libsam3/libsam3.c
Normal file
File diff suppressed because it is too large
Load Diff
280
supportlibs/libsam3/src/libsam3/libsam3.h
Normal file
280
supportlibs/libsam3/src/libsam3/libsam3.h
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#ifndef LIBSAM3_H
|
||||||
|
#define LIBSAM3_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
extern int libsam3_debug;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define SAM3_HOST_DEFAULT (NULL)
|
||||||
|
#define SAM3_PORT_DEFAULT (0)
|
||||||
|
|
||||||
|
#define SAM3_DESTINATION_TRANSIENT (NULL)
|
||||||
|
|
||||||
|
#define SAM3_PUBKEY_SIZE (516)
|
||||||
|
#define SAM3_CERT_SIZE (100)
|
||||||
|
#define SAM3_PRIVKEY_MIN_SIZE (884)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/* returns fd or -1 */
|
||||||
|
/* 'ip': host IP; can be NULL */
|
||||||
|
extern int sam3tcpConnect(const char *hostname, int port, uint32_t *ip);
|
||||||
|
extern int sam3tcpConnectIP(uint32_t ip, int port);
|
||||||
|
|
||||||
|
/* <0: error; 0: ok */
|
||||||
|
extern int sam3tcpDisconnect(int fd);
|
||||||
|
|
||||||
|
/* <0: error; 0: ok */
|
||||||
|
extern int sam3tcpSetTimeoutSend(int fd, int timeoutms);
|
||||||
|
|
||||||
|
/* <0: error; 0: ok */
|
||||||
|
extern int sam3tcpSetTimeoutReceive(int fd, int timeoutms);
|
||||||
|
|
||||||
|
/* <0: error; 0: ok */
|
||||||
|
/* sends the whole buffer */
|
||||||
|
extern int sam3tcpSend(int fd, const void *buf, size_t bufSize);
|
||||||
|
|
||||||
|
/* <0: received (-res) bytes; read error */
|
||||||
|
/* can return less that requesten bytes even if `allowPartial` is 0 when
|
||||||
|
* connection is closed */
|
||||||
|
extern ssize_t sam3tcpReceiveEx(int fd, void *buf, size_t bufSize,
|
||||||
|
int allowPartial);
|
||||||
|
|
||||||
|
extern ssize_t sam3tcpReceive(int fd, void *buf, size_t bufSize);
|
||||||
|
|
||||||
|
extern int sam3tcpPrintf(int fd, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
extern int sam3tcpReceiveStr(int fd, char *dest, size_t maxSize);
|
||||||
|
|
||||||
|
/* pass NULL for 'localhost' and 0 for 7655 */
|
||||||
|
/* 'ip': host IP; can be NULL */
|
||||||
|
extern int sam3udpSendTo(const char *hostname, int port, const void *buf,
|
||||||
|
size_t bufSize, uint32_t *ip);
|
||||||
|
extern int sam3udpSendToIP(uint32_t ip, int port, const void *buf,
|
||||||
|
size_t bufSize);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef struct SAMFieldList {
|
||||||
|
char *name;
|
||||||
|
char *value;
|
||||||
|
struct SAMFieldList *next;
|
||||||
|
} SAMFieldList;
|
||||||
|
|
||||||
|
extern void sam3FreeFieldList(SAMFieldList *list);
|
||||||
|
extern void sam3DumpFieldList(const SAMFieldList *list);
|
||||||
|
|
||||||
|
/* read and parse SAM reply */
|
||||||
|
/* NULL: error; else: list of fields */
|
||||||
|
/* first item is always 2-word reply, with first word in name and second in
|
||||||
|
* value */
|
||||||
|
extern SAMFieldList *sam3ReadReply(int fd);
|
||||||
|
|
||||||
|
extern SAMFieldList *sam3ParseReply(const char *rep);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* example:
|
||||||
|
* r0: 'HELLO'
|
||||||
|
* r1: 'REPLY'
|
||||||
|
* field: NULL or 'RESULT'
|
||||||
|
* VALUE: NULL or 'OK'
|
||||||
|
* returns bool
|
||||||
|
*/
|
||||||
|
extern int sam3IsGoodReply(const SAMFieldList *list, const char *r0,
|
||||||
|
const char *r1, const char *field,
|
||||||
|
const char *value);
|
||||||
|
|
||||||
|
extern const char *sam3FindField(const SAMFieldList *list, const char *field);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/* pass NULL for 'localhost' and 0 for 7656 */
|
||||||
|
/* returns <0 on error or socket fd on success */
|
||||||
|
extern int sam3Handshake(const char *hostname, int port, uint32_t *ip);
|
||||||
|
extern int sam3HandshakeIP(uint32_t ip, int port);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef enum {
|
||||||
|
SAM3_SESSION_RAW,
|
||||||
|
SAM3_SESSION_DGRAM,
|
||||||
|
SAM3_SESSION_STREAM
|
||||||
|
} Sam3SessionType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DSA_SHA1,
|
||||||
|
ECDSA_SHA256_P256,
|
||||||
|
ECDSA_SHA384_P384,
|
||||||
|
ECDSA_SHA512_P521,
|
||||||
|
EdDSA_SHA512_Ed25519
|
||||||
|
} Sam3SigType;
|
||||||
|
|
||||||
|
typedef struct Sam3Session {
|
||||||
|
Sam3SessionType type;
|
||||||
|
Sam3SigType sigType;
|
||||||
|
int fd;
|
||||||
|
char privkey[SAM3_PRIVKEY_MIN_SIZE + 1]; // destination private key (asciiz)
|
||||||
|
char pubkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE +
|
||||||
|
1]; // destination public key (asciiz)
|
||||||
|
char channel[66]; // name of this sam session (asciiz)
|
||||||
|
char destkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE +
|
||||||
|
1]; // for DGRAM sessions (asciiz)
|
||||||
|
// int destsig;
|
||||||
|
char error[32]; // error message (asciiz)
|
||||||
|
uint32_t ip;
|
||||||
|
int port; // this will be changed to UDP port for DRAM/RAW (can be 0)
|
||||||
|
struct Sam3Connection *connlist; // list of opened connections
|
||||||
|
int fwd_fd;
|
||||||
|
} Sam3Session;
|
||||||
|
|
||||||
|
typedef struct Sam3Connection {
|
||||||
|
Sam3Session *ses;
|
||||||
|
struct Sam3Connection *next;
|
||||||
|
int fd;
|
||||||
|
char destkey[SAM3_PUBKEY_SIZE + SAM3_CERT_SIZE +
|
||||||
|
1]; // remote destination public key (asciiz)
|
||||||
|
int destcert;
|
||||||
|
char error[32]; // error message (asciiz)
|
||||||
|
} Sam3Connection;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* create SAM session
|
||||||
|
* pass NULL as hostname for 'localhost' and 0 as port for 7656
|
||||||
|
* pass NULL as privkey to create TRANSIENT session
|
||||||
|
* 'params' can be NULL
|
||||||
|
* see http://www.i2p2.i2p/i2cp.html#options for common options,
|
||||||
|
* and http://www.i2p2.i2p/streaming.html#options for STREAM options
|
||||||
|
* if result<0: error, 'ses' fields are undefined, no need to call
|
||||||
|
* sam3CloseSession() if result==0: ok, all 'ses' fields are filled
|
||||||
|
* TODO: don't clear 'error' field on error (and set it to something meaningful)
|
||||||
|
*/
|
||||||
|
extern int sam3CreateSession(Sam3Session *ses, const char *hostname, int port,
|
||||||
|
const char *privkey, Sam3SessionType type,
|
||||||
|
Sam3SigType sigType, const char *params);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close SAM session (and all it's connections)
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* 'ses' must be properly initialized
|
||||||
|
*/
|
||||||
|
extern int sam3CloseSession(Sam3Session *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to make sure that the destination in use is of a valid length, returns
|
||||||
|
* 1 if true and 0 if false.
|
||||||
|
*/
|
||||||
|
int sam3CheckValidKeyLength(const char *pubkey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open stream connection to 'destkey' endpoint
|
||||||
|
* 'destkey' is 516-byte public key (asciiz)
|
||||||
|
* returns <0 on error, fd on ok
|
||||||
|
* you still have to call sam3CloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
*/
|
||||||
|
extern Sam3Connection *sam3StreamConnect(Sam3Session *ses, const char *destkey);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accepts stream connection and sets 'destkey'
|
||||||
|
* 'destkey' is 516-byte public key
|
||||||
|
* returns <0 on error, fd on ok
|
||||||
|
* you still have to call sam3CloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
* note that there is no timeouts for now, but you can use sam3tcpSetTimeout*()
|
||||||
|
*/
|
||||||
|
extern Sam3Connection *sam3StreamAccept(Sam3Session *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sets up forwarding stream connection
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* you still have to call sam3CloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
* note that there is no timeouts for now, but you can use sam3tcpSetTimeout*()
|
||||||
|
*/
|
||||||
|
extern int sam3StreamForward(Sam3Session *ses, const char *hostname, int port);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close SAM connection
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* 'conn' must be properly initialized
|
||||||
|
* 'conn' is invalid after call
|
||||||
|
*/
|
||||||
|
extern int sam3CloseConnection(Sam3Connection *conn);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* generate new keypair
|
||||||
|
* fills 'privkey' and 'pubkey' only
|
||||||
|
* you should not call sam3CloseSession() on 'ses'
|
||||||
|
* will not set 'error' field
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
*/
|
||||||
|
extern int sam3GenerateKeys(Sam3Session *ses, const char *hostname, int port,
|
||||||
|
int sigType);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do name lookup (something like gethostbyname())
|
||||||
|
* fills 'destkey' only
|
||||||
|
* you should not call sam3CloseSession() on 'ses'
|
||||||
|
* will set 'error' field
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
*/
|
||||||
|
extern int sam3NameLookup(Sam3Session *ses, const char *hostname, int port,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* sends datagram to 'destkey' endpoint
|
||||||
|
* 'destkey' is 516-byte public key
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* you still have to call sam3CloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
* don't send datagrams bigger than 31KB!
|
||||||
|
*/
|
||||||
|
extern int sam3DatagramSend(Sam3Session *ses, const char *destkey,
|
||||||
|
const void *buf, size_t bufsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* receives datagram and sets 'destkey' to source pubkey (if not RAW)
|
||||||
|
* returns <0 on error (buffer too small is error too) or number of bytes
|
||||||
|
* written to 'buf' you still have to call sam3CloseSession() on failure sets
|
||||||
|
* ses->error on error will necer receive datagrams bigger than 31KB (32KB for
|
||||||
|
* RAW)
|
||||||
|
*/
|
||||||
|
extern ssize_t sam3DatagramReceive(Sam3Session *ses, void *buf, size_t bufsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* generate random sam channel name
|
||||||
|
* return the size of the string
|
||||||
|
*/
|
||||||
|
extern size_t sam3GenChannelName(char *dest, size_t minlen, size_t maxlen);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// NOT including '\0' terminator
|
||||||
|
static inline size_t sam3Base32EncodedLength(size_t size) {
|
||||||
|
return (((size + 5 - 1) / 5) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// output 8 bytes for every 5 input
|
||||||
|
// return size or <0 on error
|
||||||
|
extern ssize_t sam3Base32Encode(char *dest, size_t destsz, const void *srcbuf,
|
||||||
|
size_t srcsize);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
1757
supportlibs/libsam3/src/libsam3a/libsam3a.c
Normal file
1757
supportlibs/libsam3/src/libsam3a/libsam3a.c
Normal file
File diff suppressed because it is too large
Load Diff
361
supportlibs/libsam3/src/libsam3a/libsam3a.h
Normal file
361
supportlibs/libsam3/src/libsam3a/libsam3a.h
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/* async SAMv3 library
|
||||||
|
*
|
||||||
|
* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#ifndef LIBSAM3A_H
|
||||||
|
#define LIBSAM3A_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* TODO:
|
||||||
|
* [.] block sam3aClose*() in callbacks
|
||||||
|
*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
extern int libsam3a_debug;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define SAM3A_HOST_DEFAULT (NULL)
|
||||||
|
#define SAM3A_PORT_DEFAULT (0)
|
||||||
|
|
||||||
|
#define SAM3A_DESTINATION_TRANSIENT (NULL)
|
||||||
|
|
||||||
|
#define SAM3A_PUBKEY_SIZE (516)
|
||||||
|
#define SAM3A_PRIVKEY_SIZE (884)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
extern uint64_t sam3atimeval2ms(const struct timeval *tv);
|
||||||
|
extern void sam3ams2timeval(struct timeval *tv, uint64_t ms);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
extern int sam3aIsValidPubKey(const char *key);
|
||||||
|
extern int sam3aIsValidPrivKey(const char *key);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
typedef struct Sam3ASession Sam3ASession;
|
||||||
|
typedef struct Sam3AConnection Sam3AConnection;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SAM3A_SESSION_RAW,
|
||||||
|
SAM3A_SESSION_DGRAM,
|
||||||
|
SAM3A_SESSION_STREAM
|
||||||
|
} Sam3ASessionType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *data;
|
||||||
|
int dataSize;
|
||||||
|
int dataUsed;
|
||||||
|
int dataPos;
|
||||||
|
void *udata;
|
||||||
|
union {
|
||||||
|
void (*cbReplyCheckSes)(Sam3ASession *ses);
|
||||||
|
void (*cbReplyCheckConn)(Sam3AConnection *conn);
|
||||||
|
};
|
||||||
|
} Sam3AIO;
|
||||||
|
|
||||||
|
/** session callback functions */
|
||||||
|
typedef struct {
|
||||||
|
void (*cbError)(Sam3ASession *ses); /** called on error */
|
||||||
|
void (*cbCreated)(
|
||||||
|
Sam3ASession *ses); /** called when we created the session */
|
||||||
|
void (*cbDisconnected)(Sam3ASession *ses); /* call when closed; will called
|
||||||
|
only after cbCreated() */
|
||||||
|
void (*cbDatagramRead)(Sam3ASession *ses, const void *buf,
|
||||||
|
int bufsize); /* called when we got a datagram; bufsize
|
||||||
|
>= 0; destkey set */
|
||||||
|
void (*cbDestroy)(Sam3ASession *ses); /* called when fd is already closed, but
|
||||||
|
keys is not cleared */
|
||||||
|
} Sam3ASessionCallbacks;
|
||||||
|
|
||||||
|
struct Sam3ASession {
|
||||||
|
Sam3ASessionType type; /** session type */
|
||||||
|
int fd; /** socket file descriptor */
|
||||||
|
int cancelled; /** fd was shutdown()ed, but not closed yet */
|
||||||
|
char privkey[SAM3A_PRIVKEY_SIZE + 1]; /** private key (asciiz) */
|
||||||
|
char pubkey[SAM3A_PUBKEY_SIZE + 1]; /** public key (asciiz) */
|
||||||
|
char channel[66]; /** channel name (asciiz) */
|
||||||
|
char destkey[SAM3A_PUBKEY_SIZE + 1]; /** for DGRAM sessions (asciiz) */
|
||||||
|
char error[64]; /** error message (asciiz) */
|
||||||
|
uint32_t ip; /** ipv4 address of sam api interface */
|
||||||
|
int port; /** UDP port for DRAM/RAW (can be 0) */
|
||||||
|
Sam3AConnection *connlist; /** list of opened connections */
|
||||||
|
|
||||||
|
/** begin internal members */
|
||||||
|
// for async i/o
|
||||||
|
Sam3AIO aio;
|
||||||
|
void (*cbAIOProcessorR)(Sam3ASession *ses); // internal
|
||||||
|
void (*cbAIOProcessorW)(Sam3ASession *ses); // internal
|
||||||
|
int callDisconnectCB;
|
||||||
|
char *params; // will be cleared only by sam3aCloseSession()
|
||||||
|
int timeoutms;
|
||||||
|
|
||||||
|
/** end internal members */
|
||||||
|
|
||||||
|
Sam3ASessionCallbacks cb;
|
||||||
|
void *udata;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** connection callbacks for data sockets */
|
||||||
|
typedef struct {
|
||||||
|
/** called on error */
|
||||||
|
void (*cbError)(Sam3AConnection *ct);
|
||||||
|
/** called when closed or only after cbConnected()/cbAccepted(); note that
|
||||||
|
* force disconnect is ok */
|
||||||
|
void (*cbDisconnected)(Sam3AConnection *ct);
|
||||||
|
/** called when connected */
|
||||||
|
void (*cbConnected)(Sam3AConnection *ct);
|
||||||
|
/** called instead of cbConnected() for sam3aStreamAccept*(), destkey filled
|
||||||
|
* with remote destination */
|
||||||
|
void (*cbAccepted)(Sam3AConnection *ct);
|
||||||
|
/** send callback, data sent, can add new data; will be called after
|
||||||
|
* connect/accept */
|
||||||
|
void (*cbSent)(Sam3AConnection *ct);
|
||||||
|
/** read callback, data read from socket (bufsize is always > 0) */
|
||||||
|
void (*cbRead)(Sam3AConnection *ct, const void *buf, int bufsize);
|
||||||
|
/** fd already closed, but keys is not cleared */
|
||||||
|
void (*cbDestroy)(Sam3AConnection *ct);
|
||||||
|
} Sam3AConnectionCallbacks;
|
||||||
|
|
||||||
|
struct Sam3AConnection {
|
||||||
|
/** parent session */
|
||||||
|
Sam3ASession *ses;
|
||||||
|
Sam3AConnection *next;
|
||||||
|
/** file descriptor */
|
||||||
|
int fd;
|
||||||
|
int cancelled; // fd was shutdown()ed, but not closed yet
|
||||||
|
char destkey[SAM3A_PUBKEY_SIZE + 1]; // (asciiz)
|
||||||
|
char error[32]; // (asciiz)
|
||||||
|
|
||||||
|
/** begin internal members */
|
||||||
|
// for async i/o
|
||||||
|
Sam3AIO aio;
|
||||||
|
void (*cbAIOProcessorR)(Sam3AConnection *ct); // internal
|
||||||
|
void (*cbAIOProcessorW)(Sam3AConnection *ct); // internal
|
||||||
|
int callDisconnectCB;
|
||||||
|
char *params; // will be cleared only by sam3aCloseConnection()
|
||||||
|
int timeoutms;
|
||||||
|
/** end internal members */
|
||||||
|
|
||||||
|
/** callbacks */
|
||||||
|
Sam3AConnectionCallbacks cb;
|
||||||
|
/** user data */
|
||||||
|
void *udata;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* check if session is active (i.e. have opened socket)
|
||||||
|
* returns bool
|
||||||
|
*/
|
||||||
|
extern int sam3aIsActiveSession(const Sam3ASession *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check if connection is active (i.e. have opened socket)
|
||||||
|
* returns bool
|
||||||
|
*/
|
||||||
|
extern int sam3aIsActiveConnection(const Sam3AConnection *conn);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* note, that return error codes indicates invalid structure, pointer or fd
|
||||||
|
* (i.e. immediate errors); all network errors indicated with cbError() callback
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create SAM session
|
||||||
|
* pass NULL as hostname for 'localhost' and 0 as port for 7656
|
||||||
|
* pass NULL as privkey to create TRANSIENT session
|
||||||
|
* 'params' can be NULL
|
||||||
|
* see http://www.i2p2.i2p/i2cp.html#options for common options,
|
||||||
|
* and http://www.i2p2.i2p/streaming.html#options for STREAM options
|
||||||
|
* if result<0: error, 'ses' fields are undefined, no need to call
|
||||||
|
* sam3aCloseSession() if result==0: ok, all 'ses' fields are filled
|
||||||
|
* TODO: don't clear 'error' field on error (and set it to something meaningful)
|
||||||
|
*/
|
||||||
|
extern int sam3aCreateSessionEx(Sam3ASession *ses,
|
||||||
|
const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port,
|
||||||
|
const char *privkey, Sam3ASessionType type,
|
||||||
|
const char *params, int timeoutms);
|
||||||
|
|
||||||
|
static inline int sam3aCreateSession(Sam3ASession *ses,
|
||||||
|
const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port,
|
||||||
|
const char *privkey,
|
||||||
|
Sam3ASessionType type) {
|
||||||
|
return sam3aCreateSessionEx(ses, cb, hostname, port, privkey, type, NULL, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns <0 on error, 0 if no, >0 if yes */
|
||||||
|
extern int sam3aIsHaveActiveConnections(const Sam3ASession *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close SAM session (and all it's connections)
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* 'ses' must be properly initialized
|
||||||
|
*/
|
||||||
|
extern int sam3aCloseSession(Sam3ASession *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cancel SAM session (and all it's connections), but don't free() or clear
|
||||||
|
* anything except fds returns <0 on error, 0 on ok 'ses' must be properly
|
||||||
|
* initialized
|
||||||
|
*/
|
||||||
|
extern int sam3aCancelSession(Sam3ASession *ses);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* open stream connection to 'destkey' endpoint
|
||||||
|
* 'destkey' is 516-byte public key (asciiz)
|
||||||
|
* returns <0 on error
|
||||||
|
* sets ses->error on memory or socket creation error
|
||||||
|
*/
|
||||||
|
extern Sam3AConnection *sam3aStreamConnectEx(Sam3ASession *ses,
|
||||||
|
const Sam3AConnectionCallbacks *cb,
|
||||||
|
const char *destkey,
|
||||||
|
int timeoutms);
|
||||||
|
|
||||||
|
static inline Sam3AConnection *
|
||||||
|
sam3aStreamConnect(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb,
|
||||||
|
const char *destkey) {
|
||||||
|
return sam3aStreamConnectEx(ses, cb, destkey, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* accepts stream connection and sets 'destkey'
|
||||||
|
* 'destkey' is 516-byte public key
|
||||||
|
* returns <0 on error, fd on ok
|
||||||
|
* you still have to call sam3aCloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
* note that there is no timeouts for now, but you can use sam3atcpSetTimeout*()
|
||||||
|
*/
|
||||||
|
extern Sam3AConnection *sam3aStreamAcceptEx(Sam3ASession *ses,
|
||||||
|
const Sam3AConnectionCallbacks *cb,
|
||||||
|
int timeoutms);
|
||||||
|
|
||||||
|
static inline Sam3AConnection *
|
||||||
|
sam3aStreamAccept(Sam3ASession *ses, const Sam3AConnectionCallbacks *cb) {
|
||||||
|
return sam3aStreamAcceptEx(ses, cb, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* close SAM connection, remove it from session and free memory
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* 'conn' must be properly initialized
|
||||||
|
* 'conn' is invalid after call
|
||||||
|
*/
|
||||||
|
extern int sam3aCloseConnection(Sam3AConnection *conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cancel SAM connection, but don't free() or clear anything except fd
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* 'conn' must be properly initialized
|
||||||
|
* 'conn' is invalid after call
|
||||||
|
*/
|
||||||
|
extern int sam3aCancelConnection(Sam3AConnection *conn);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* send data
|
||||||
|
* this function can be used in cbSent() callback
|
||||||
|
*
|
||||||
|
* return: <0: error; 0: ok
|
||||||
|
*/
|
||||||
|
extern int sam3aSend(Sam3AConnection *conn, const void *data, int datasize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sends datagram to 'destkey' endpoint
|
||||||
|
* 'destkey' is 516-byte public key
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
* you still have to call sam3aCloseSession() on failure
|
||||||
|
* sets ses->error on error
|
||||||
|
* don't send datagrams bigger than 31KB!
|
||||||
|
*/
|
||||||
|
extern int sam3aDatagramSend(Sam3ASession *ses, const char *destkey,
|
||||||
|
const void *buf, int bufsize);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* generate random channel name
|
||||||
|
* dest should be at least (maxlen+1) bytes big
|
||||||
|
*/
|
||||||
|
extern int sam3aGenChannelName(char *dest, int minlen, int maxlen);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* generate new keypair
|
||||||
|
* fills 'privkey' and 'pubkey' only
|
||||||
|
* you should call sam3aCloseSession() on 'ses'
|
||||||
|
* cbCreated callback will be called when keys generated
|
||||||
|
* returns <0 on error, 0 on ok
|
||||||
|
*/
|
||||||
|
extern int sam3aGenerateKeysEx(Sam3ASession *ses,
|
||||||
|
const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port, int timeoutms);
|
||||||
|
|
||||||
|
static inline int sam3aGenerateKeys(Sam3ASession *ses,
|
||||||
|
const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port) {
|
||||||
|
return sam3aGenerateKeysEx(ses, cb, hostname, port, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do name lookup (something like gethostbyname())
|
||||||
|
* fills 'destkey' only
|
||||||
|
* you should call sam3aCloseSession() on 'ses'
|
||||||
|
* cbCreated callback will be called when keys generated, ses->destkey will be
|
||||||
|
* set returns <0 on error, 0 on ok
|
||||||
|
*/
|
||||||
|
extern int sam3aNameLookupEx(Sam3ASession *ses, const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port, const char *name,
|
||||||
|
int timeoutms);
|
||||||
|
|
||||||
|
static inline int sam3aNameLookup(Sam3ASession *ses,
|
||||||
|
const Sam3ASessionCallbacks *cb,
|
||||||
|
const char *hostname, int port,
|
||||||
|
const char *name) {
|
||||||
|
return sam3aNameLookupEx(ses, cb, hostname, port, name, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* append session fd to read and write sets if necessary
|
||||||
|
* adds all alive session connections too
|
||||||
|
* returns maxfd or -1
|
||||||
|
* TODO: should keep fd count so it will not exceed FD_SETSIZE!
|
||||||
|
*/
|
||||||
|
extern int sam3aAddSessionToFDS(Sam3ASession *ses, int maxfd, fd_set *rds,
|
||||||
|
fd_set *wrs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process session i/o (and all session connections i/o)
|
||||||
|
* should be called after successful select()
|
||||||
|
*/
|
||||||
|
extern void sam3aProcessSessionIO(Sam3ASession *ses, fd_set *rds, fd_set *wrs);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/* return malloc()ed buffer and len in 'plen' (if plen != NULL) */
|
||||||
|
extern char *sam3PrintfVA(int *plen, const char *fmt, va_list app);
|
||||||
|
extern char *sam3Printf(int *plen, const char *fmt, ...)
|
||||||
|
__attribute__((format(printf, 2, 3)));
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
51
supportlibs/libsam3/test/libsam3/test_b32.c
Normal file
51
supportlibs/libsam3/test/libsam3/test_b32.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* This program is free software. It comes without any warranty, to
|
||||||
|
* the extent permitted by applicable law. You can redistribute it
|
||||||
|
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||||
|
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||||
|
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||||
|
*
|
||||||
|
* I2P-Bote:
|
||||||
|
* 5m77dFKGEq6~7jgtrfw56q3t~SmfwZubmGdyOLQOPoPp8MYwsZ~pfUCwud6LB1EmFxkm4C3CGlzq-hVs9WnhUV
|
||||||
|
* we are the Borg. */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "../../src/ext/tinytest.h"
|
||||||
|
#include "../../src/ext/tinytest_macros.h"
|
||||||
|
#include "../../src/libsam3/libsam3.h"
|
||||||
|
|
||||||
|
static int testb32(const char *src, const char *res) {
|
||||||
|
size_t dlen = sam3Base32EncodedLength(strlen(src)), len;
|
||||||
|
char dest[128];
|
||||||
|
//
|
||||||
|
len = sam3Base32Encode(dest, sizeof(dest), src, strlen(src));
|
||||||
|
tt_int_op(len, ==, dlen);
|
||||||
|
tt_int_op(len, ==, strlen(res));
|
||||||
|
tt_str_op(res, ==, dest);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
end:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_b32_encode(void *data) {
|
||||||
|
(void)data; /* This testcase takes no data. */
|
||||||
|
|
||||||
|
tt_assert(testb32("", ""));
|
||||||
|
tt_assert(testb32("f", "my======"));
|
||||||
|
tt_assert(testb32("fo", "mzxq===="));
|
||||||
|
tt_assert(testb32("foo", "mzxw6==="));
|
||||||
|
tt_assert(testb32("foob", "mzxw6yq="));
|
||||||
|
tt_assert(testb32("fooba", "mzxw6ytb"));
|
||||||
|
tt_assert(testb32("foobar", "mzxw6ytboi======"));
|
||||||
|
|
||||||
|
end:;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct testcase_t b32_tests[] = {{
|
||||||
|
"encode",
|
||||||
|
test_b32_encode,
|
||||||
|
},
|
||||||
|
END_OF_TESTCASES};
|
12
supportlibs/libsam3/test/test.c
Normal file
12
supportlibs/libsam3/test/test.c
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "../src/ext/tinytest.h"
|
||||||
|
#include "../src/ext/tinytest_macros.h"
|
||||||
|
|
||||||
|
extern struct testcase_t b32_tests[];
|
||||||
|
|
||||||
|
struct testgroup_t test_groups[] = {{"b32/", b32_tests}, END_OF_GROUPS};
|
||||||
|
|
||||||
|
int main(int argc, const char **argv) {
|
||||||
|
return tinytest_main(argc, argv, test_groups);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user