diff --git a/conn/connection.c b/conn/connection.c index 8e18ea9..4fc5d79 100644 --- a/conn/connection.c +++ b/conn/connection.c @@ -2,7 +2,7 @@ #include "libp2p/conn/connection.h" -struct Connection* libp2p_conn_connection_open(struct TransportDialer* transport_dialer, struct maddr* multiaddress) { +struct Connection* libp2p_conn_connection_new(struct TransportDialer* transport_dialer, struct MultiAddress* multiaddress) { struct Connection* out = NULL; if (transport_dialer != NULL) { @@ -13,3 +13,11 @@ struct Connection* libp2p_conn_connection_open(struct TransportDialer* transport } return out; } + +void libp2p_conn_connection_free(struct Connection* connection) { + if (connection != NULL) { + fclose(connection->socket_handle); + free(connection); + } +} + diff --git a/conn/dialer.c b/conn/dialer.c index 65b0c26..b842036 100644 --- a/conn/dialer.c +++ b/conn/dialer.c @@ -15,12 +15,20 @@ struct Dialer* libp2p_conn_dialer_new(char* peer_id, struct PrivateKey* private_key) { struct Dialer* dialer = (struct Dialer*)malloc(sizeof(struct Dialer)); if (dialer != NULL) { - dialer->peer_id = peer_id; - dialer->private_key = private_key; - dialer->fallback_dialer = NULL; - dialer->transport_dialers = NULL; + dialer->peer_id = malloc(strlen(peer_id) + 1); + if (dialer->peer_id != NULL) { + strcpy(dialer->peer_id, peer_id); + dialer->private_key = (struct PrivateKey*)malloc(sizeof(struct PrivateKey)); + if (dialer->private_key != NULL) { + libp2p_crypto_private_key_copy(private_key, dialer->private_key); + dialer->fallback_dialer = NULL; + dialer->transport_dialers = NULL; + return dialer; + } + } } - return dialer; + libp2p_conn_dialer_free(dialer); + return NULL; } /** @@ -49,10 +57,10 @@ 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 maddr* multiaddress) { +struct Connection* libp2p_conn_dialer_get_connection(struct Dialer* dialer, struct MultiAddress* multiaddress) { struct Connection* conn = libp2p_conn_transport_dialer_get(dialer->transport_dialers, multiaddress); if (conn == NULL) { - conn = libp2p_conn_connection_open(dialer->fallback_dialer, multiaddress); + conn = libp2p_conn_connection_new(dialer->fallback_dialer, multiaddress); } return conn; } diff --git a/conn/transport_dialer.c b/conn/transport_dialer.c index 1a6dc45..7b8e3ed 100644 --- a/conn/transport_dialer.c +++ b/conn/transport_dialer.c @@ -2,17 +2,18 @@ #include "libp2p/conn/transport_dialer.h" -struct TransportDialer* libp2p_conn_transport_dialer_new(struct maddr* multiaddr) { +struct TransportDialer* libp2p_conn_transport_dialer_new(struct MultiAddress* multiaddr) { struct TransportDialer* out = (struct TransportDialer*)malloc(sizeof(struct TransportDialer)); if (out != NULL) { - out->multiaddr = (struct maddr*)malloc(sizeof(struct maddr)); + out->multiaddr = (struct MultiAddress*)malloc(sizeof(struct MultiAddress)); if (out->multiaddr == NULL) { - free(out); + libp2p_conn_transport_dialer_free(out); + return NULL; + } + if (multiaddress_copy(multiaddr, out->multiaddr) == 0) { + libp2p_conn_transport_dialer_free(out); return NULL; } - out->multiaddr->bsize[0] = multiaddr->bsize[0]; - memcpy(out->multiaddr->bytes, multiaddr->bytes, 400); - memcpy(out->multiaddr->string, multiaddr->string, 800); } return out; } @@ -31,7 +32,7 @@ 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 maddr* multiaddr) { +struct Connection* libp2p_conn_transport_dialer_get(struct Libp2pLinkedList* transport_dialers, struct MultiAddress* multiaddr) { //TODO: implement this method return NULL; } diff --git a/crypto/encoding/base64.c b/crypto/encoding/base64.c index 708e05e..b3a3db7 100644 --- a/crypto/encoding/base64.c +++ b/crypto/encoding/base64.c @@ -24,7 +24,7 @@ int libp2p_crypto_encoding_base64_encode(const unsigned char* input_data, size_t * @param output_data the buffer to store the output * @param max_output_length the length of the output buffer * @param bytes_written the number of bytes written to output_data - * @returns a pointer to the decoded data + * @returns true(1) on success, otherwise 0 */ int libp2p_crypto_encoding_base64_decode(const unsigned char* input_data, size_t input_length, unsigned char* output_data, size_t max_output_length, size_t* bytes_written) { int retVal = mbedtls_base64_decode(output_data, max_output_length, bytes_written, input_data, input_length); diff --git a/crypto/key.c b/crypto/key.c index bfd7dc7..b44be15 100644 --- a/crypto/key.c +++ b/crypto/key.c @@ -130,11 +130,25 @@ void libp2p_crypto_private_key_free(struct PrivateKey* in) { } } -int libp2p_crypto_private_key_protobuf_encode_size(struct PrivateKey* in) { +int libp2p_crypto_private_key_copy(const struct PrivateKey* source, struct PrivateKey* destination) { + if (source != NULL && destination != NULL) { + destination->type = source->type; + destination->data = (unsigned char*)malloc(source->data_size); + if (destination->data != NULL) { + memcpy(destination->data, source->data, source->data_size); + destination->data_size = source->data_size; + return 1; + } + libp2p_crypto_private_key_free(destination); + } + return 0; +} + +size_t libp2p_crypto_private_key_protobuf_encode_size(const struct PrivateKey* in) { return 22 + in->data_size; } -int libp2p_crypto_private_key_protobuf_encode(struct PrivateKey* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) { +int libp2p_crypto_private_key_protobuf_encode(const struct PrivateKey* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written) { *bytes_written = 0; size_t bytes_used; // type (RSA vs ED25519) diff --git a/include/libp2p/conn/connection.h b/include/libp2p/conn/connection.h index 7a37da5..49d32bf 100644 --- a/include/libp2p/conn/connection.h +++ b/include/libp2p/conn/connection.h @@ -1,3 +1,4 @@ +#pragma once /** * Implements an interface to connect and talk to different nodes. * A Dialer will connect, and return a Connection structure @@ -7,15 +8,15 @@ #include "multiaddr/multiaddr.h" struct Connection { - int socket_handle; + FILE* socket_handle; /** * Read from the stream * @param socket_handle the socket to read from * @param in what was read in NOTE: this allocates memory * @param in_size the number of bytes read in - * @returns 0 on success, otherwise an error code + * @returns number of bytes written or negative number on error */ - int (*read)(int socket_handle, char** in, size_t* in_size); + int (*read)(const struct Connection* conn, char** in, size_t* in_size); /** * Write to the stream * @param socket_handle the socket to write to @@ -23,7 +24,21 @@ struct Connection { * @param out_size the number of bytes to write * @returns 0 on success, otherwise an error code */ - int (*write)(int socket_handle, char* out, size_t* out_size); + int (*write)(const struct Connection* conn, char* out, size_t out_size); }; -struct Connection* libp2p_conn_connection_open(struct TransportDialer* transport_dialer, struct maddr* multiaddress); +/** + * creates a new connection + * @param transport_dialer the TransportDialer to use + * @param multiaddress the destination + * @returns a connection that is ready to be read from / written to + */ +struct Connection* libp2p_conn_connection_new(struct TransportDialer* transport_dialer, struct MultiAddress* multiaddress); + +/*** + * close a connection and dispose of struct + * @param connection the resource to clean up + */ +void libp2p_conn_connection_free(struct Connection* connection); + + diff --git a/include/libp2p/conn/dialer.h b/include/libp2p/conn/dialer.h index 635e452..c7c66d6 100644 --- a/include/libp2p/conn/dialer.h +++ b/include/libp2p/conn/dialer.h @@ -6,6 +6,8 @@ #include "libp2p/crypto/key.h" #include "multiaddr/multiaddr.h" +#include "libp2p/conn/connection.h" +#include "libp2p/conn/transport_dialer.h" struct Dialer { /** @@ -41,4 +43,4 @@ 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 maddr* multiaddress); +struct Connection* libp2p_conn_dialer_get_connection(struct Dialer* dialer, struct MultiAddress* multiaddress); diff --git a/include/libp2p/conn/transport_dialer.h b/include/libp2p/conn/transport_dialer.h index 8aac91a..f8bb581 100644 --- a/include/libp2p/conn/transport_dialer.h +++ b/include/libp2p/conn/transport_dialer.h @@ -4,10 +4,10 @@ #include "libp2p/utils/linked_list.h" struct TransportDialer { - struct maddr* multiaddr; + struct MultiAddress* multiaddr; }; -struct TransportDialer* libp2p_conn_transport_dialer_new(struct maddr* multiaddr); +struct TransportDialer* libp2p_conn_transport_dialer_new(struct MultiAddress* multiaddr); void libp2p_conn_transport_dialer_free(struct TransportDialer* in); -struct Connection* libp2p_conn_transport_dialer_get(struct Libp2pLinkedList* transport_dialers, struct maddr* multiaddr); +struct Connection* libp2p_conn_transport_dialer_get(struct Libp2pLinkedList* transport_dialers, struct MultiAddress* multiaddr); diff --git a/include/libp2p/crypto/key.h b/include/libp2p/crypto/key.h index 4ab75ac..1139785 100644 --- a/include/libp2p/crypto/key.h +++ b/include/libp2p/crypto/key.h @@ -23,6 +23,7 @@ void libp2p_crypto_public_key_free(struct PublicKey* in); struct PrivateKey* libp2p_crypto_private_key_new(); void libp2p_crypto_private_key_free(struct PrivateKey* in); +int libp2p_crypto_private_key_copy(const struct PrivateKey* source, struct PrivateKey* destination); /** * Unmarshal a public key from a protobuf @@ -30,7 +31,10 @@ void libp2p_crypto_private_key_free(struct PrivateKey* in); int libp2p_crypto_public_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PublicKey** out); size_t libp2p_crypto_public_key_protobuf_encode_size(const struct PublicKey* in); int libp2p_crypto_public_key_protobuf_encode(const struct PublicKey* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written); +// private key int libp2p_crypto_private_key_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct PrivateKey** out); +size_t libp2p_crypto_private_key_protobuf_encode_size(const struct PrivateKey* in); +int libp2p_crypto_private_key_protobuf_encode(const struct PrivateKey* in, unsigned char* buffer, size_t max_buffer_length, size_t* bytes_written); /** * convert a public key into a peer id diff --git a/test/Makefile b/test/Makefile index 90582c9..aabceac 100644 --- a/test/Makefile +++ b/test/Makefile @@ -5,7 +5,7 @@ ifdef DEBUG CFLAGS += -g3 endif -LFLAGS = -L../ -L../../c-multihash +LFLAGS = -L../ -L../../c-multihash -L../../c-multiaddr DEPS = crypto/test_base58.h crypto/test_rsa.h test_mbedtls.h OBJS = testit.o ../../c-protobuf/protobuf.o ../../c-protobuf/varint.o ../libp2p.a @@ -13,7 +13,7 @@ OBJS = testit.o ../../c-protobuf/protobuf.o ../../c-protobuf/varint.o ../libp2p. $(CC) -c -o $@ $< $(CFLAGS) testit_libp2p: $(OBJS) $(DEPS) - $(CC) -o $@ $(OBJS) $(LFLAGS) -lp2p -lm -lmultihash + $(CC) -o $@ $(OBJS) $(LFLAGS) -lp2p -lm -lmultihash -lmultiaddr all_others: cd ../crypto; make all; diff --git a/test/test_conn.h b/test/test_conn.h index 0d58315..64db0d9 100644 --- a/test/test_conn.h +++ b/test/test_conn.h @@ -1,12 +1,64 @@ #include #include "libp2p/conn/dialer.h" +#include "test_helper.h" int test_dialer_new() { - struct PrivateKey* private_key = NULL; - struct Dialer* dialer = libp2p_conn_dialer_new("ABC", private_key); + char* peer_id = "QmQSDGgxSVTkHmtT25rTzQtc5C1Yg8SpGK3BTws8YsJ4x3"; + struct PrivateKey* private_key = libp2p_crypto_private_key_new(); + struct Dialer* dialer = libp2p_conn_dialer_new(peer_id, private_key); if (dialer == NULL) return 0; libp2p_conn_dialer_free(dialer); return 1; } + +int test_dialer_dial() { + int retVal = 0; + char* config_dir = "/home/parallels/.ipfs/config"; + char* destination_string = "/ip/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 Connection* conn = 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 + conn = libp2p_conn_dialer_get_connection(dialer, destination_address); + 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: + if (result != NULL) + free(result); + multiaddress_free(destination_address); + libp2p_conn_dialer_free(dialer); + libp2p_crypto_private_key_free(private_key); + libp2p_conn_connection_free(conn); + return retVal; +} diff --git a/test/test_helper.h b/test/test_helper.h new file mode 100644 index 0000000..1ac8431 --- /dev/null +++ b/test/test_helper.h @@ -0,0 +1,92 @@ +#include +#include + +#include "libp2p/crypto/key.h" + +void read_file(char* path, char** contents) { + FILE* fd = fopen(path, "r"); + fseek(fd, 0L, SEEK_END); + size_t num_bytes = ftell(fd); + rewind(fd); + *contents = malloc(num_bytes); + fread(*contents, 1, num_bytes, fd); + fclose(fd); + return; +} + +struct PrivateKey* base64ToPrivateKey(char* base64) { + int retVal = 0; + size_t decode_base64_size = 0; + unsigned char* decode_base64 = NULL; + struct PrivateKey* out = NULL; + + // 1) take the private key and turn it back into bytes (decode base 64) + decode_base64_size = libp2p_crypto_encoding_base64_decode_size(strlen(base64)); + decode_base64 = (unsigned char*)malloc(decode_base64_size); + if (decode_base64 == NULL) + goto exit; + memset(decode_base64, 0, decode_base64_size); + + if (!libp2p_crypto_encoding_base64_decode((unsigned char*)base64, strlen(base64), &decode_base64[0], decode_base64_size, &decode_base64_size)) + goto exit; + + if (!libp2p_crypto_private_key_protobuf_decode(decode_base64, decode_base64_size, &out)) + goto exit; + + retVal = 1; + exit: + if (retVal != 1) { + libp2p_crypto_private_key_free(out); + out = NULL; + } + return out; +} + +int test_helper_get_id_from_config(char* path, struct PrivateKey** private_ptr, char** peer_ptr) { + int retVal = 0; + char* contents = NULL; + char* ptr = NULL; + char* end = NULL; + int length = 0; + read_file(path, &contents); + if (contents == NULL) + goto exit; + + // peer id + ptr = strstr(contents, "PeerID"); + if (ptr == NULL) + goto exit; + + ptr = strstr(ptr, "Qm"); + if (ptr == NULL) + goto exit; + + end = strstr(ptr, "\""); + + length = end - ptr; + *peer_ptr = malloc(length + 1); + if (*peer_ptr == NULL) + goto exit; + memcpy(*peer_ptr, ptr, length); + (*peer_ptr)[length] = 0; + + // private key + ptr = strstr(contents, "PrivKey\":"); + if (ptr == NULL) + goto exit; + ptr += 9; + ptr = strstr(ptr, "\""); + ptr++; + + end = strstr(ptr, "\""); + end[0] = 0; + + // turn the encoded private key into a struct + *private_ptr = base64ToPrivateKey(ptr); + + retVal = 1; + exit: + if (contents != NULL) + free(contents); + return retVal; +} diff --git a/test/testit.c b/test/testit.c index a92a45d..3840d52 100644 --- a/test/testit.c +++ b/test/testit.c @@ -36,7 +36,8 @@ const char* names[] = { "test_multistream_connect", "test_multistream_get_list", "test_ephemeral_key_generate", - "test_dialer_new" + "test_dialer_new", + "test_dialer_dial" }; int (*funcs[])(void) = { @@ -65,7 +66,8 @@ int (*funcs[])(void) = { test_multistream_connect, test_multistream_get_list, test_ephemeral_key_generate, - test_dialer_new + test_dialer_new, + test_dialer_dial }; int testit(const char* name, int (*func)(void)) {