Many fixes around secio

yamux
John Jones 2017-03-02 16:14:52 -05:00
parent c5fa775534
commit 6d9473069b
22 changed files with 317 additions and 137 deletions

View File

@ -8,6 +8,8 @@
#include "libp2p/conn/transport_dialer.h"
#include "libp2p/crypto/key.h"
#include "libp2p/utils/linked_list.h"
#include "libp2p/utils/multiaddress.h"
#include "libp2p/net/multistream.h"
struct TransportDialer* libp2p_conn_tcp_transport_dialer_new();
@ -60,14 +62,38 @@ void libp2p_conn_dialer_free(struct Dialer* in) {
/**
* Retrieve a Connection struct from the dialer
* NOTE: This should no longer be used. _get_stream should
* be used instead (which calls this method internally).
* @param dialer the dialer to use
* @param muiltiaddress who to connect to
* @returns a Connection, or NULL
*/
struct Connection* libp2p_conn_dialer_get_connection(struct Dialer* dialer, struct MultiAddress* multiaddress) {
struct Connection* libp2p_conn_dialer_get_connection(const struct Dialer* dialer, const struct MultiAddress* multiaddress) {
struct Connection* conn = libp2p_conn_transport_dialer_get(dialer->transport_dialers, multiaddress);
if (conn == NULL) {
conn = dialer->fallback_dialer->dial(dialer->fallback_dialer, multiaddress);
}
return conn;
}
/**
* return a Stream that is already set up to use the passed in protocol
* @param dialer the dialer to use
* @param multiaddress the host to dial
* @param protocol the protocol to use (right now only 'multistream' is supported)
* @returns the ready-to-use stream
*/
struct Stream* libp2p_conn_dialer_get_stream(const struct Dialer* dialer, const struct MultiAddress* multiaddress, const char* protocol) {
// this is a shortcut for now. Other protocols will soon be implemented
if (strcmp(protocol, "multistream") != 0)
return NULL;
char* ip;
int port;
if (!libp2p_utils_multiaddress_parse_ip4_tcp(multiaddress, &ip, &port)) {
free(ip);
return NULL;
}
struct Stream* stream = libp2p_net_multistream_connect(ip, port);
free(ip);
return stream;
}

View File

@ -6,43 +6,13 @@
#include "libp2p/net/p2pnet.h"
#include "libp2p/conn/connection.h"
#include "libp2p/conn/transport_dialer.h"
#include "libp2p/utils/multiaddress.h"
/**
* An implementation of a tcp transport dialer
*/
struct TcpIp {
char* ip;
int port;
};
struct TcpIp* libp2p_conn_parse_ip_multiaddress(struct MultiAddress* addr) {
struct TcpIp* out = (struct TcpIp*)malloc(sizeof(struct TcpIp));
char* address = malloc(strlen(addr->string) + 1);
strcpy(address, addr->string);
char* tok = strtok(address, "/");
int pos = 0;
while (tok != NULL) {
switch (pos) {
case 1: {
out->ip = malloc(strlen(tok) + 1);
strcpy(out->ip, tok);
break;
}
case 3: {
out->port = strtol(tok, NULL, 10);
break;
}
}
tok = strtok(NULL, "/");
pos++;
}
//TODO: do a better job of parsing the results
return out;
}
int libp2p_conn_tcp_can_handle(struct MultiAddress* addr) {
int libp2p_conn_tcp_can_handle(const struct MultiAddress* addr) {
return 1;
}
@ -59,13 +29,15 @@ int libp2p_conn_tcp_write(const struct Connection* connection, const char* in, s
return bytes == num_bytes;
}
struct Connection* libp2p_conn_tcp_dial(struct TransportDialer* transport_dialer, struct MultiAddress* addr) {
struct Connection* libp2p_conn_tcp_dial(const struct TransportDialer* transport_dialer, const struct MultiAddress* addr) {
struct Connection* conn = (struct Connection*) malloc(sizeof(struct Connection*));
conn->socket_handle = socket_open4();
struct TcpIp* results = libp2p_conn_parse_ip_multiaddress(addr);
struct hostent* host = gethostbyname(results->ip);
char* ip;
int port;
libp2p_utils_multiaddress_parse_ip4_tcp(addr, &ip, &port);
struct hostent* host = gethostbyname(ip);
struct in_addr** addr_list = (struct in_addr**)host->h_addr_list;
socket_connect4(conn->socket_handle, (*addr_list[0]).s_addr, results->port);
socket_connect4(conn->socket_handle, (*addr_list[0]).s_addr, port);
conn->read = libp2p_conn_tcp_read;
conn->write = libp2p_conn_tcp_write;
return conn;

View File

@ -33,8 +33,8 @@ void libp2p_conn_transport_dialer_free(struct TransportDialer* in) {
* @param multiaddr the address
* @returns a connection, or NULL if no appropriate dialer was found
*/
struct Connection* libp2p_conn_transport_dialer_get(struct Libp2pLinkedList* transport_dialers, struct MultiAddress* multiaddr) {
struct Libp2pLinkedList* current = transport_dialers;
struct Connection* libp2p_conn_transport_dialer_get(const struct Libp2pLinkedList* transport_dialers, const struct MultiAddress* multiaddr) {
const struct Libp2pLinkedList* current = transport_dialers;
struct TransportDialer* t_dialer = NULL;
while (current != NULL) {
t_dialer = (struct TransportDialer*)current->item;

20
crypto/aes.c Normal file
View File

@ -0,0 +1,20 @@
#include "mbedtls/aes.h"
/**
* Encrypt a block of text
* @param key the aes key
* @param iv the random part of encryption
* @param input the text to encrypt
* @param input_size the length of the array
* @param output where the output will be placed
* @param output_size the length of the memory allocated for output
* @returns true(1) on success, otherwise false(0)
*/
int libp2p_crypto_aes_encrypt(char* key, char* iv, char* input, size_t input_size, unsigned char* output, size_t* output_size) {
mbedtls_aes_context ctx;
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 256);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 24, iv, input, output);
//TODO Implement this method
return 0;
}

View File

@ -1,7 +1,12 @@
/***
* A local dialer. Uses MultiAddr to figure out the best way to
* connect to a client, then returns an open Connection that can be
* closed, read from and written to.
* closed, read from and written to. The normal procedure is as follows:
* 1) Create a Dialer struct, with the required information about the local host
* 2) Call _get_connection to create the connection with a specific host
* NOTE: 1 Dialer could be used to create all connections, saving time and resources
* if it is not too difficult to pass it around. The struct has enough information to
* build connections that negotiate many protocols
*/
#include "libp2p/crypto/key.h"
@ -29,11 +34,16 @@ struct Dialer {
/**
* Create a Dialer with the specified local information
* NOTE: This fills in the fallback_dialer too
* @param peer_id the local PeerID
* @param private_key the local private key
* @returns a new Dialer struct
*/
struct Dialer* libp2p_conn_dialer_new(char* peer_id, struct PrivateKey* private_key);
/**
* free resources from the Dialer
* free resources from the Dialer struct
* @param in the Dialer struct to relieve of their resources
*/
void libp2p_conn_dialer_free(struct Dialer* in);
@ -43,4 +53,14 @@ void libp2p_conn_dialer_free(struct Dialer* in);
* @param muiltiaddress who to connect to
* @returns a Connection, or NULL
*/
struct Connection* libp2p_conn_dialer_get_connection(struct Dialer* dialer, struct MultiAddress* multiaddress);
struct Connection* libp2p_conn_dialer_get_connection(const struct Dialer* dialer, const struct MultiAddress* multiaddress);
/**
* return a Stream that is already set up to use the passed in protocol
* @param dialer the dialer to use
* @param multiaddress the host to dial
* @param protocol the protocol to use (right now only 'multistream' is supported)
* @returns the ready-to-use stream
*/
struct Stream* libp2p_conn_dialer_get_stream(const struct Dialer* dialer, const struct MultiAddress* multiaddress, const char* protocol);

View File

@ -6,11 +6,11 @@
struct TransportDialer {
char* peer_id;
struct PrivateKey* private_key;
int (*can_handle)(struct MultiAddress* multiaddr);
struct Connection* (*dial)(struct TransportDialer* transport_dialer, struct MultiAddress* multiaddr);
int (*can_handle)(const struct MultiAddress* multiaddr);
struct Connection* (*dial)(const struct TransportDialer* transport_dialer, const struct MultiAddress* multiaddr);
};
struct TransportDialer* libp2p_conn_transport_dialer_new(char* peer_id, struct PrivateKey* private_key);
void libp2p_conn_transport_dialer_free(struct TransportDialer* in);
struct Connection* libp2p_conn_transport_dialer_get(struct Libp2pLinkedList* transport_dialers, struct MultiAddress* multiaddr);
struct Connection* libp2p_conn_transport_dialer_get(const struct Libp2pLinkedList* transport_dialers, const struct MultiAddress* multiaddr);

View File

@ -0,0 +1,11 @@
#pragma once
/**
* Encrypt a block of text
* @param input the text to encrypt
* @param input_size the length of the array
* @param output where the output will be placed
* @param output_size the length of the memory allocated for output
* @returns true(1) on success, otherwise false(0)
*/
int libp2p_crypto_aes_encrypt(char* input, size_t input_size, unsigned char* output, size_t& output_size);

View File

@ -11,7 +11,7 @@ struct StretchedKey {
size_t iv_size;
char* cipher_key;
size_t cipher_size;
char* mac_key;
unsigned char* mac_key;
size_t mac_size;
};

View File

@ -14,8 +14,8 @@ enum ConnectionType {
};
struct Libp2pPeer {
char* id; // protobuf field 1
size_t id_size;
char* id; // protobuf field 1; the ID (aka peer id) of the peer
size_t id_size; // the length of id
struct Libp2pLinkedList* addr_head; // protobuf field 2 of multiaddr bytes (repeatable) (stored here as a struct MultiAddr)
enum ConnectionType connection_type; // protobuf field 3 (a varint)
};

View File

@ -15,7 +15,7 @@ struct SecureSession {
int port;
enum IPTrafficType traffic_type;
// once the connection is established
int socket_descriptor;
struct Stream* stream;
struct PublicKey remote_key;
char* remote_peer_id;
// filled in during negotiations
@ -28,6 +28,8 @@ struct SecureSession {
size_t shared_key_size;
char nonce[16];
struct StretchedKey* stretched_key;
unsigned char* mac;
size_t mac_size;
};
/***

View File

@ -0,0 +1,13 @@
#pragma once
#include "multiaddr/multiaddr.h"
/**
* This is a hack to get ip4/tcp working
* TODO: this should be moved further down in the networking stack and generified for different multiaddresses
* This makes too many assumptions
* @param address the multiaddress to parse
* @param ip the first IP address in the multiaddress
* @param port the first port in the multiaddress
* @returns true(1) on success, false(0) on failure
*/
int libp2p_utils_multiaddress_parse_ip4_tcp(const struct MultiAddress* address, char** ip, int* port);

View File

@ -128,15 +128,15 @@ struct Stream* libp2p_net_multistream_connect(const char* hostname, int port) {
if (stream == NULL)
goto exit;
num_bytes = libp2p_net_multistream_write(stream, (unsigned char*)protocol_buffer, strlen(protocol_buffer));
if (num_bytes <= 0)
goto exit;
// try to receive the protocol id
return_result = libp2p_net_multistream_read(stream, &results, &results_size);
if (return_result == 0 || results_size < 1)
goto exit;
num_bytes = libp2p_net_multistream_write(stream, (unsigned char*)protocol_buffer, strlen(protocol_buffer));
if (num_bytes <= 0)
goto exit;
if (strstr((char*)results, "multistream") == NULL)
goto exit;

View File

@ -184,19 +184,27 @@ ssize_t socket_write_size(int s, unsigned long size, int flags) {
*/
uint32_t hostname_to_ip(const char* hostname)
{
struct hostent *he;
struct in_addr **addr_list;
struct sockaddr_in sa;
int result = inet_pton(AF_INET, hostname, &(sa.sin_addr));
if (result != 0) {
// an ip address was passed in instead of a hostname
return sa.sin_addr.s_addr;
} else {
// it is probably an actual host name and not just an ip address
struct hostent *he;
struct in_addr **addr_list;
if ( (he = gethostbyname( hostname ) ) == NULL)
{
// get the host info
herror("gethostbyname");
return 1;
}
if ( (he = gethostbyname( hostname ) ) == NULL)
{
// get the host info
herror("gethostbyname");
return 1;
}
addr_list = (struct in_addr **) he->h_addr_list;
if ((*addr_list) == NULL)
return 0;
addr_list = (struct in_addr **) he->h_addr_list;
if ((*addr_list) == NULL)
return 0;
return addr_list[0]->s_addr;
return addr_list[0]->s_addr;
}
}

View File

@ -71,7 +71,7 @@ int libp2p_secio_exchange_protobuf_decode(unsigned char* buffer, size_t buffer_l
size_t pos = 0;
int retVal = 0;
if (libp2p_secio_exchange_new(out) == 0)
if ( (*out = libp2p_secio_exchange_new()) == NULL)
goto exit;
while(pos < buffer_length) {

View File

@ -78,11 +78,11 @@ int libp2p_secio_propose_protobuf_encode(struct Propose* in, unsigned char* buff
return 0;
*bytes_written += bytes_used;
// exchanges
if (!protobuf_encode_length_delimited(4, secio_propose_message_fields[3], in->exchanges, in->exchanges_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
if (!protobuf_encode_length_delimited(3, secio_propose_message_fields[2], in->exchanges, in->exchanges_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
return 0;
*bytes_written += bytes_used;
// ciphers
if (!protobuf_encode_length_delimited(3, secio_propose_message_fields[2], in->ciphers, in->ciphers_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
if (!protobuf_encode_length_delimited(4, secio_propose_message_fields[3], in->ciphers, in->ciphers_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used))
return 0;
*bytes_written += bytes_used;
// hashes
@ -131,11 +131,11 @@ int libp2p_secio_propose_protobuf_decode(unsigned char* buffer, size_t buffer_le
got_something = 1;
break;
case (3): // exchanges
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->exchanges), &((*out)->exchanges_size), &bytes_read) == 0)
goto exit;
pos += bytes_read;
got_something = 1;
break;
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->exchanges), &((*out)->exchanges_size), &bytes_read) == 0)
goto exit;
pos += bytes_read;
got_something = 1;
break;
case (4): // ciphers
if (protobuf_decode_length_delimited(&buffer[pos], buffer_length - pos, (char**)&((*out)->ciphers), &((*out)->ciphers_size), &bytes_read) == 0)
goto exit;

View File

@ -29,7 +29,7 @@ struct SecureSession* libp2p_secio_secure_session_new() {
struct SecureSession* ss = (struct SecureSession*) malloc(sizeof(struct SecureSession));
if (ss == NULL)
return NULL;
ss->socket_descriptor = -1;
ss->stream = NULL;
return ss;
}
@ -291,8 +291,10 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
if (num_needed > hash_size)
num_needed = hash_size;
// combine current_hash with first_seed
if (temp != NULL)
if (temp != NULL) {
free(temp);
temp = NULL;
}
seed_size = secret_size + strlen(first_seed) + hash_size;
temp = malloc(seed_size);
memcpy(temp, secret, secret_size);
@ -305,6 +307,7 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
num_filled += num_needed;
// redo the hashes by adding the secret to the current hash
free(temp);
temp = NULL;
seed_size = secret_size + hash_size;
temp = malloc(seed_size);
memcpy(temp, secret, secret_size);
@ -336,6 +339,8 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
memcpy(k2->mac_key, temp, k2->mac_size);
temp += k2->mac_size;
temp = NULL;
retVal = 1;
// cleanup
@ -362,8 +367,35 @@ int libp2p_secio_stretch_keys(char* cipherType, char* hashType, unsigned char* s
}
int libp2p_secio_make_mac_and_cipher(struct SecureSession* session) {
// TODO: Implement this method
return 0;
// mac
int (*mac_func)(const char*, size_t, unsigned char*);
if (strcmp(session->chosen_hash, "SHA1") == 0) {
session->stretched_key->mac_size = 40;
mac_func = libp2p_crypto_hashing_sha1;
} else if (strcmp(session->chosen_hash, "SHA512") == 0) {
session->stretched_key->mac_size = 32;
mac_func = libp2p_crypto_hashing_sha512;
} else if (strcmp(session->chosen_hash, "SHA256") == 0) {
session->stretched_key->mac_size = 16;
mac_func = libp2p_crypto_hashing_sha256;
} else {
return 0;
}
session->stretched_key->mac_key = malloc(session->stretched_key->mac_size);
mac_func(session->stretched_key->cipher_key, session->stretched_key->cipher_size, session->stretched_key->mac_key);
// block cipher
if (strcmp(session->chosen_cipher, "AES-128") == 0) {
} else if (strcmp(session->chosen_cipher, "AES-256") == 0) {
} else if (strcmp(session->chosen_cipher, "Blowfish") == 0) {
} else {
return 0;
}
return 1;
}
int libp2p_secio_write(struct SecureSession* session, unsigned char* bytes, size_t data_length) {
@ -377,7 +409,7 @@ int libp2p_secio_write(struct SecureSession* session, unsigned char* bytes, size
int written = 0;
int written_this_time = 0;
do {
written_this_time = socket_write(session->socket_descriptor, &size_as_char[written], left, 0);
written_this_time = socket_write(*((int*)session->stream->socket_descriptor), &size_as_char[written], left, 0);
if (written_this_time < 0) {
written_this_time = 0;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
@ -393,7 +425,7 @@ int libp2p_secio_write(struct SecureSession* session, unsigned char* bytes, size
left = data_length;
written = 0;
do {
written_this_time = socket_write(session->socket_descriptor, (char*)&bytes[written], left, 0);
written_this_time = socket_write(*((int*)session->stream->socket_descriptor), (char*)&bytes[written], left, 0);
if (written_this_time < 0) {
written_this_time = 0;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
@ -420,7 +452,7 @@ int libp2p_secio_read(struct SecureSession* session, unsigned char** results, si
int read = 0;
int read_this_time = 0;
do {
read_this_time = socket_read(session->socket_descriptor, &size[read], 1, 0);
read_this_time = socket_read(*((int*)session->stream->socket_descriptor), &size[read], 1, 0);
if (read_this_time < 0) {
read_this_time = 0;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
@ -449,7 +481,7 @@ int libp2p_secio_read(struct SecureSession* session, unsigned char** results, si
*results = malloc(left);
unsigned char* ptr = *results;
do {
read_this_time = socket_read(session->socket_descriptor, (char*)&ptr[read], left, 0);
read_this_time = socket_read(*((int*)session->stream->socket_descriptor), (char*)&ptr[read], left, 0);
if (read_this_time < 0) {
read_this_time = 0;
if ( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
@ -474,9 +506,6 @@ int libp2p_secio_read(struct SecureSession* session, unsigned char** results, si
* @returns true(1) on success, false(0) otherwise
*/
int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivateKey* private_key) {
// this needs to be redone
return 0;
/*
int retVal = 0;
size_t results_size = 0, bytes_written = 0;
unsigned char* propose_in_bytes = NULL; // the remote protobuf
@ -504,6 +533,27 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
//TODO: make sure we're not talking to ourself
// prepare the multistream send of the protocol ID
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
int protocol_len = strlen((char*)protocol);
unsigned char* total = malloc(protocol_len + propose_out_size);
memcpy(total, protocol, protocol_len);
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
bytes_written = libp2p_net_multistream_write(local_session->stream, total, protocol_len + propose_out_size);
free(total);
if (bytes_written <= 0)
goto exit;
// we should get back the secio confirmation
bytes_written = libp2p_net_multistream_read(local_session->stream, &results, &results_size);
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
goto exit;
free(results);
results = NULL;
results_size = 0;
// generate 16 byte nonce
if (!libp2p_secio_generate_nonce(&local_session->nonce[0], 16)) {
goto exit;
@ -549,30 +599,11 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0)
goto exit;
// prepare the multistream send
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
int protocol_len = strlen((char*)protocol);
unsigned char* total = malloc(protocol_len + propose_out_size);
memcpy(total, protocol, protocol_len);
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
bytes_written = libp2p_net_multistream_write(local_session->socket_descriptor, total, protocol_len + propose_out_size);
free(total);
if (bytes_written <= 0)
bytes_written = libp2p_secio_write(local_session, propose_out_bytes, propose_out_size);
if (bytes_written < propose_out_size)
goto exit;
//bytes_written = libp2p_secio_write(local_session, propose_out_bytes, propose_out_size);
//if (bytes_written < propose_out_size)
// goto exit;
// we should get back the secio confirmation
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
goto exit;
free(results);
results = NULL;
results_size = 0;
// now receive the proposal from the new connection
bytes_written = libp2p_secio_read(local_session, &propose_in_bytes, &propose_in_size);
if (bytes_written <= 0)
@ -587,6 +618,11 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
// generate their peer id
libp2p_crypto_public_key_to_peer_id(public_key, &remote_peer_id);
// receive Exchange packet
bytes_written = libp2p_secio_read(local_session, &results, &results_size);
if (bytes_written == 0)
goto exit;
libp2p_secio_exchange_protobuf_decode(results, results_size, &exchange_in);
// negotiate encryption parameters NOTE: SelectBest must match, otherwise this won't work
// first determine order
@ -653,12 +689,6 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
free(exchange_out_protobuf);
exchange_out_protobuf = NULL;
// receive Exchange packet
bytes_written = libp2p_secio_read(local_session, &results, &results_size);
if (bytes_written == 0)
goto exit;
libp2p_secio_exchange_protobuf_decode(results, results_size, &exchange_in);
// parse and verify
remote_session.ephemeral_public_key = exchange_in->epubkey;
remote_session.ephemeral_public_key_size = exchange_in->epubkey_size;
@ -669,8 +699,9 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
libp2p_utils_vector_add(char_buffer, propose_in_bytes, propose_in_size);
libp2p_utils_vector_add(char_buffer, propose_out_bytes, propose_out_size);
libp2p_utils_vector_add(char_buffer, remote_session.ephemeral_public_key, remote_session.ephemeral_public_key_size);
if (!libp2p_secio_verify_signature(public_key, char_buffer->buffer, char_buffer->buffer_size, exchange_in->signature))
goto exit;
// TODO: signature verification
//if (!libp2p_secio_verify_signature(public_key, char_buffer->buffer, char_buffer->buffer_size, exchange_in->signature))
// goto exit;
libp2p_utils_vector_free(char_buffer);
char_buffer = NULL;
@ -727,5 +758,4 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
libp2p_secio_propose_free(propose_in);
return retVal;
*/
}

View File

@ -1,6 +1,7 @@
#include <stdlib.h>
#include "libp2p/conn/dialer.h"
#include "libp2p/net/stream.h"
#include "test_helper.h"
int test_dialer_new() {
@ -42,15 +43,6 @@ int test_dialer_dial() {
if (conn == NULL)
goto exit;
if (conn->write(conn, "ping", 4) == 0)
goto exit;
if (conn->read(conn, &result, &result_size) == 0)
goto exit;
if (result_size < 4 || strncmp(result, "pong", 4) != 0)
goto exit;
// clean up resources
retVal = 1;
exit:
@ -63,3 +55,47 @@ int test_dialer_dial() {
libp2p_conn_connection_free(conn);
return retVal;
}
int test_dialer_dial_multistream() {
int retVal = 0;
char* config_dir = "/home/parallels/.ipfs/config";
char* destination_string = "/ip4/192.210.179.217/tcp/4001/";
char* peer_id = NULL;
struct PrivateKey* private_key = NULL;
struct Dialer* dialer = NULL;
struct MultiAddress* destination_address = NULL;
struct Stream* stream = NULL;
char* result = NULL;
size_t result_size = 0;
test_helper_get_id_from_config(config_dir, &private_key, &peer_id);
if (private_key == NULL)
goto exit;
dialer = libp2p_conn_dialer_new(peer_id, private_key);
if (dialer == NULL)
goto exit;
destination_address = multiaddress_new_from_string(destination_string);
if (destination_address == NULL)
goto exit;
// now try to dial
stream = libp2p_conn_dialer_get_stream(dialer, destination_address, "multistream");
if (stream == NULL)
goto exit;
// now ping
// clean up resources
retVal = 1;
exit:
if (result != NULL)
free(result);
free(peer_id);
multiaddress_free(destination_address);
libp2p_conn_dialer_free(dialer);
libp2p_crypto_private_key_free(private_key);
stream->close(stream);
return retVal;
}

View File

@ -23,12 +23,13 @@ int test_multistream_connect() {
}
int test_multistream_get_list() {
int retVal = 0, socket_fd = -1;
int retVal = 0;
unsigned char* response;
size_t response_size;
char* filtered = NULL;
struct Stream* stream = libp2p_net_multistream_connect("www.jmjatlanta.com", 4001);
if (socket_fd < 0)
if (*((int*)stream->socket_descriptor) < 0)
goto exit;
// try to respond something, ls command
@ -42,7 +43,12 @@ int test_multistream_get_list() {
if (retVal <= 0)
goto exit;
fprintf(stdout, "Response from multistream ls: %s", (char*)response);
filtered = malloc(response_size + 1);
strncpy(filtered, response, response_size);
filtered[response_size] = 0;
fprintf(stdout, "Response from multistream ls: %s", (char*)filtered);
free(filtered);
retVal = 1;

View File

@ -5,16 +5,13 @@
#include "libp2p/net/p2pnet.h"
int test_secio_handshake() {
return 0;
/*
* this needs to be redone
int retVal = 0;
size_t decode_base64_size = 0;
unsigned char* decode_base64 = NULL;
// this is a base64 encoded private key. It makes it easier to test if it is in base64 form
// these were pulled from the GO version of ipfs
char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQCwfp3DpbTP/nD1R+1PcP7nDOV9MEDiLUoNf9cBVhWGefJT0ES81do1COwLXiD/k7gAHJu197F7AfFYKt+NQu6jpCDC/uRtK0M0MpeDGI0LV1oz0rKLTN79zQwKDHFimWCmNyOZRLfR3PF5TgLc0qiFOZw9WwYNJkohu6k6yVMDJiy3l/+K5Vdw9VVyz7mRulXdDvEMxccraKaTvjLAUNFjiqm5Zs3hrcZszuuP2RhcpZU40kuWDtyN9TAEge0NfhS5Fj7GtgQsHWJ4RxTdebHkQmX49ltI/nIw9TxGIVcA50g7eF/3a3zZtkh48JadbHiT2Mfr6SPXl0328gyg7v7tAgMBAAECggEABGlFvCwaFtC/NgI0NjYWyOOToMth88U6AphdYVUreI73tYyRCz81EvpEHAygOoMQqEAOzD+CmhZ0V8XKjJdNq51gjD8eqnPYXCefjdFBRTVLtdvgRocHU8SaNm4VL2ex+LWMGDqVdZNWHbgLbkV9nMbR1t69ifqZA7rTAfsiLgPtneu4kGjrO1nr+uFC0srch2o0stmiqxmcGOrkD9x2kXkw33O8wTSyBp3+STlTOehePuUqEho9BXdT7b2nXC8MNdTCekG9f3oUeKsK9pxH7ZlG3yUOBoM0mEm/N7BrPfJnQbogomUapWOpssWKSz0LCpKuy4El3mFpua0jmd3nAQKBgQDWvVHj44gSecjsrWH/QpMIn8W/ISXfJRxJKrdVBRC5Ey0h3wdLnF6Olz4kuD7KurPOWNR+IKaLzOWxZdX79aQn+oY8lB+UCM+0w1TWJeSWBUYATPtUU4xpKdD6YZ8ksOdgZ4hbn9VD49uu/SJUPVNGV+eHibnvdR+/sFJuHTAb4QKBgQDSaBd1V7z5R6NK8373QNMDHZnSa2qH8uAGvoSuajYGgcpAzDY3aueQFpQS66scrZK6zLQyOQgtyrIg/hKbeP+vV5LGBirzOtAH7Kko5BYeY/SCXOkHBsHhuPGyghqWl6KR2Vj8cjJZFCAiUvoqf3Ws0vW58kp/KgDCnlKGmgQkjQKBgDPYi7/4vG6xhqhWCDYIDdXkNWs7BpjErfqgXJkjWvFERv5Jicpgm5fTvkZBUa/CugzU96DoIy3Xr5FQJATsPtEENIrFvIYSRou/KWl2xqTN6yPBcmDetyTg2rrI/RJvv71P4eU1RtlYVz79kN9D2yo9qQHZZ9H/tkWivZQmaeohAoGAIafa0L9HEAzAdvW6AmzRE/eBKmJaOQLFiO6ipI+CssnCA1lm9rhX7/lcmCYwSbcN+GlUDZCH2WNJ2PMrIMlbBL4aUSidaCipLAtUB6FsVFIiw1N/Rsty6ds+dhJPlHUO4QuGK2NM4GjStwrUz0VyGkHoYmT6O5sJYhgXFUa/kOUCgYEAv1VGeX6EPsFgp+FKM1Q/8MYi7PPpSUI2fqMhnwe36u7UdNYa3Ismmo/ipfCw7DdX5qRcUh44PodTp4Zwp67Bd2KRzEAZmMvIurzclQB7VWUT7pB7yfbO9bjBUVbPTagjiqb30zq9A4kt+B/0MSPxa/Kh8EkgI02Jqh2Q97Ij4sc=";
char* orig_peer_id = "QmYm3WdMQqqQuEyCWmRVNEjtXjhGhyRRNshdvqV7YLGvpA";
char* orig_priv_key = "CAASpwkwggSjAgEAAoIBAQCo+BYd213u8PNHNcnXZ6TcUc7oXEoCtWL12XJEFqAiC7emadkp+WtujmuR993L6uCRPU/+mNXIvetodMQ5GORq0MxsPlKFNuVuqHS4PCdWYYFKeel4QsG17T3XMo72Kxm7/pQ1Dbs6tzWD4Ie4Zsa7ziyffjeak1/EExkFf0AKtj4UdXErNRI5gZhkDnWp6Si117Z2VVTslE+kKXWpLK0RYZ4w8DhhZa+ykt2tleOOJt8ocJ3s3yVZQxOafL1lwA8f10VEEeJLPGKJ1Y7mmW7OJhLmrq9tvdTLhum1H5kdYu/pheCm5b6/NSGKS+XbQztu5zedsKSPHsOlYhxYu3GJAgMBAAECggEAZIz93Fam14Jbw4ymyKDM4q9sSapiAKqgcV0tOoecU6ZVa5qhuPDMlcX7DapLOwZTDRtHd2LMFeGvLUIPY0sE4uvOOrv7r3qznd5xVxG09xqfLgrOfNp9HB5KJr3XhXawocclu0yolpBgMFJ1ca73pNtUgrVBsaLx4mTbBwJqwfQpQb/Xdkrdgc663bwXkSl4vApwhZGzi5CFJ6SFC6l6fMKoteWM1ay5e2VCfxi/1g41EINkrqm+QPWhy11bo21ScozxiFiywcxQ8Huo+I5GDHI5EUfIHP97NSRG24/IDSebxsGTukMdpLmiiwizV7hHP2eDlikHAhxBBAF2GkbkAQKBgQDg69jPHrETvHGlKjlEDE8sYQUrwpmGLHfsfZYqBxcz65jPYFAypG4icIU6f8Uhz9c42jLEBssNPT8LyLl2uY467hZZA2SkeWKS66Vi5wBGTN5qOBWUejhzTx8UzasYroWl/0RqFZhU9Xhwg4YqT9X8jYw5mXyOMLatp/d/Y96p0QKBgQDAUQodQZc9yc7olsmNvbuHZtBA+VndKCokFOuJ6YLRK69AL7y6n6eUjne6JqcEIKDC7vr33ryuOdFI+zNzMsdYykE8xcg2c5itWRqG7EdMxgR1dYLUqGC5ustRM/mmhmRzW8DXy88sS+vM4U84yPKv/rfeKAoYgE722R0kkpQCOQKBgQCKfm63yiw6/NP1YXR1hCbUKsFmWqLxzTvisMngAxG0dKNZPfLj2/+80RAYH0ihMztQ1Hph3dT1x/qkJOqeQk9j1eqI0OANrniWAueJaLfwkbB6MyKGlGNiDRwUUTfDMOM2fWIA+F8eITASB8p7D0GyCu6HIQ1i+HfjogNxu2sFoQKBgE4ZGthiqH6JE6NUiKks4ZjM4clg+WNcSjC45iXtVBiJevO/7w6Cg1VKvcg0piKA9Yfz8Kr0Iv9Fr33JtU0U0+t0xyVc1D94lgnfY2xjS1kcGPdyLx0Y+56xApwJVVqQvP4zxo5bz9gXRLzAyqEuyY87C4QGEoN8p5SK+tC9TanRAoGAbC+uVaBtqRqv3LY16+H58BW8lVfN+8dqtBOWluM2uImB1qL2EbKk0X/OChz3Dgzef5VTox6nHcMyYPwXLirS9aIYPggjdpDTjfbWPxUcwYmIB1U++F/mRk1IeDgl9g7t/OlPMg4snxQGEzMPPDVrj/KeLEKv5x+T5yFZ/y+8xNo=";
char* orig_peer_id = "QmZigcoDKaAafGSwot2tchJarCafxKapoRmnYTrZ69ckjb";
size_t orig_peer_id_size = strlen(orig_peer_id);
struct RsaPrivateKey* rsa_private_key = NULL;
unsigned char hashed[32] = {0};
@ -45,12 +42,12 @@ int test_secio_handshake() {
if (!libp2p_crypto_rsa_private_key_fill_public_key(rsa_private_key))
goto exit;
secure_session.host = "192.210.179.217";
secure_session.host = "www.jmjatlanta.com";
secure_session.port = 4001;
secure_session.traffic_type = TCP;
// connect to host
secure_session.socket_descriptor = libp2p_net_multistream_connect(secure_session.host, secure_session.port);
if (secure_session.socket_descriptor == -1) {
secure_session.stream = libp2p_net_multistream_connect(secure_session.host, secure_session.port);
if (*((int*)secure_session.stream->socket_descriptor) == -1) {
fprintf(stderr, "test_secio_handshake: Unable to get socket descriptor\n");
goto exit;
}
@ -77,5 +74,4 @@ int test_secio_handshake() {
if (rsa_private_key != NULL)
libp2p_crypto_rsa_rsa_private_key_free(rsa_private_key);
return retVal;
*/
}

View File

@ -40,6 +40,7 @@ const char* names[] = {
"test_ephemeral_key_generate",
"test_dialer_new",
"test_dialer_dial",
"test_dialer_dial_multistream",
"test_record_protobuf",
"test_record_make_put_record",
"test_record_peer_protobuf",
@ -76,6 +77,7 @@ int (*funcs[])(void) = {
test_ephemeral_key_generate,
test_dialer_new,
test_dialer_dial,
test_dialer_dial_multistream,
test_record_protobuf,
test_record_make_put_record,
test_record_peer_protobuf,

View File

@ -1,5 +1,5 @@
CC = gcc
CFLAGS = -O0 -Wall -I../include
CFLAGS = -O0 -Wall -I../include -I../../c-multiaddr/include
ifdef DEBUG
CFLAGS += -g3
@ -7,7 +7,7 @@ endif
LFLAGS =
DEPS =
OBJS = string_list.o vector.o linked_list.o
OBJS = string_list.o vector.o linked_list.o multiaddress.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

38
utils/multiaddress.c Normal file
View File

@ -0,0 +1,38 @@
#include <stdlib.h>
/**
* A central repository for parsing Multiaddress structs
*/
#include "libp2p/utils/multiaddress.h"
/**
* This is a hack to get ip4/tcp working
* TODO: this should be moved further down in the networking stack and generified for different multiaddresses
* This makes too many assumptions
* @param address the multiaddress to parse
* @param ip the first IP address in the multiaddress
* @param port the first port in the multiaddress
* @returns true(1) on success, false(0) on failure
*/
int libp2p_utils_multiaddress_parse_ip4_tcp(const struct MultiAddress* address, char** ip, int* port) {
// the incoming address is not what was expected
if (strncmp(address->string, "/ip4/", 5) != 0)
return 0;
if (strstr(address->string, "/tcp/") == NULL)
return 0;
// ip
char* str = malloc(strlen(address->string));
if (str == NULL)
return 0;
strcpy(str, &address->string[5]); // gets rid of /ip4/
char* pos = strchr(str, '/');
pos[0] = 0;
*ip = malloc(strlen(str) + 1);
strcpy(*ip, str);
free(str);
// port
str = strstr(address->string, "/tcp/");
str += 5;
*port = atoi(str);
return 1;
}