diff --git a/Makefile b/Makefile index 907f588..7c3a32d 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ OBJS = \ thirdparty/mbedtls/*.o \ hashmap/hashmap.o \ net/*.o \ + peer/*.o \ record/*.o \ routing/*.o \ secio/*.o \ @@ -23,6 +24,7 @@ compile: cd thirdparty; make all; cd hashmap; make all; cd net; make all; + cd peer; make all; cd record; make all; cd routing; make all; cd secio; make all; @@ -40,6 +42,7 @@ clean: cd crypto; make clean; cd hashmap; make clean; cd net; make clean; + cd peer; make clean; cd thirdparty; make clean cd record; make clean; cd routing; make clean; diff --git a/include/libp2p/peer/peer.h b/include/libp2p/peer/peer.h new file mode 100644 index 0000000..e374a82 --- /dev/null +++ b/include/libp2p/peer/peer.h @@ -0,0 +1,65 @@ +#pragma once + +enum ConnectionType { + // sender does not have a connection to the peer, and no extra information (default) + CONNECTION_TYPE_NOT_CONNECTED = 0, + // sender has a live connection to the peer + CONNECTION_TYPE_CONNECTED = 1, + // sender recently connected to peer + CONNECTION_TYPE_CAN_CONNECT = 2, + // sender recently tried to connect to peer repeatedly but failed to connect + CONNECTION_TYPE_CANNOT_CONNECT = 3 +}; + +struct Libp2pPeer { + char* id; // protobuf field 1 + size_t id_size; + 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) +}; + +/** + * create a new Peer struct + * @returns a struct or NULL if there was a problem + */ +struct Libp2pPeer* libp2p_peer_new(); + +/** + * frees resources from a peer struct + * @param in the peer to free + */ +void libp2p_peer_free(struct Libp2pPeer* in); + +/** + * Make a copy of a peer + * @param in what is to be copied + * @returns a new struct, that does not rely on the old + */ +struct Libp2pPeer* libp2p_peer_copy(struct Libp2pPeer* in); + +/** + * Get an estimate of the necessary size of the buffer to protobuf a particular peer + * @param in the peer to examine + * @returns an approximation of the buffer size required (erring on the side of bigger) + */ +size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in); + +/** + * Encode the Peer into a buffer + * @param in the peer + * @param buffer where to put it + * @param max_buffer_size the maximum amount of memory reserved for the buffer + * @param bytes_written the number of bytes written to the buffer + * @returns true(1) on success, otherwise 0 + */ +int libp2p_peer_protobuf_encode(struct Libp2pPeer* in, unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written); + +/** + * turn an array of bytes into a Peer + * @param in the protobuf formatted peer + * @param in_size the size of in + * @param out the new Peer + * @returns true(1) on success, otherwise false + */ +int libp2p_peer_protobuf_decode(unsigned char* in, size_t in_size, struct Libp2pPeer** out); + diff --git a/include/libp2p/peer/peerstore.h b/include/libp2p/peer/peerstore.h new file mode 100644 index 0000000..41d616c --- /dev/null +++ b/include/libp2p/peer/peerstore.h @@ -0,0 +1,62 @@ +#pragma once + +#include "libp2p/utils/linked_list.h" +#include "libp2p/peer/peer.h" + +/** + * Structures and functions to implement a storage area for peers and + * their connections and metadata + */ + +/** + * An entry in the "database" is a PeerEntry. This contains metadata + * about the peer + */ +struct PeerEntry { + struct Libp2pPeer* peer; + // other metadata for the peer goes here + // TODO: add some type of timer to expire the record +}; + +/** + * Contains a collection of peers and their metadata + * NOTE: this is currently a linked list. Perhaps a better algo would + * improve performance, but will wait. + */ +struct Peerstore { + struct Libp2pLinkedList* head_entry; + struct Libp2pLinkedList* last_entry; +}; + +struct PeerEntry* libp2p_peer_entry_new(); +void libp2p_peer_entry_free(struct PeerEntry* in); + +/** + * Creates a new empty peerstore + * @returns an empty peerstore or NULL on error + */ +struct Peerstore* libp2p_peerstore_new(); + +/** + * Deallocate resources used by the peerstore + * @param in the struct to deallocate + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_peerstore_free(struct Peerstore* in); + +/** + * Add a Peer to the Peerstore + * @param peerstore the peerstore to add the entry to + * @param peer_entry the entry to add + * @returns true(1) on success, otherwise false + */ +int libp2p_peerstore_add_peer_entry(struct Peerstore* peerstore, struct PeerEntry* peer_entry); + +/** + * Retrieve a peer from the peerstore based on the peer id + * @param peerstore the peerstore to search + * @param peer_id the id to search for as a binary array + * @param peer_id_size the size of the binary array + * @returns the PeerEntry struct if found, otherwise NULL + */ +struct PeerEntry* libp2p_peerstore_get_peer_entry(struct Peerstore* peerstore, unsigned char* peer_id, size_t peer_id_size); diff --git a/include/libp2p/record/message.h b/include/libp2p/record/message.h index 28bf448..7ffdb01 100644 --- a/include/libp2p/record/message.h +++ b/include/libp2p/record/message.h @@ -3,7 +3,7 @@ #include "libp2p/record/record.h" /** - * protobuf stuff for Message and Peer + * protobuf stuff for Message * This is used for the KAD / DHT stuff */ @@ -16,24 +16,6 @@ enum MessageType { MESSAGE_TYPE_PING = 5 }; -enum ConnectionType { - // sender does not have a connection to the peer, and no extra information (default) - CONNECTION_TYPE_NOT_CONNECTED = 0, - // sender has a live connection to the peer - CONNECTION_TYPE_CONNECTED = 1, - // sender recently connected to peer - CONNECTION_TYPE_CAN_CONNECT = 2, - // sender recently tried to connect to peer repeatedly but failed to connect - CONNECTION_TYPE_CANNOT_CONNECT = 3 -}; - -struct Libp2pPeer { - char* id; // protobuf field 1 - size_t id_size; - struct Libp2pLinkedList* addr_head; // protobuf field 2 of multiaddr bytes (repeatable) (stored here as a Libp2pVector) - enum ConnectionType connection_type; // protobuf field 3 (a varint) -}; - struct Libp2pMessage { enum MessageType message_type; // protobuf field 1 (a varint) char* key; // protobuf field 2 @@ -44,44 +26,6 @@ struct Libp2pMessage { int32_t cluster_level_raw; // protobuf field 10 }; -/** - * create a new Peer struct - * @returns a struct or NULL if there was a problem - */ -struct Libp2pPeer* libp2p_message_peer_new(); - -/** - * frees resources from a peer struct - * @param in the peer to free - */ -void libp2p_message_peer_free(struct Libp2pPeer* in); - -/** - * Get an estimate of the necessary size of the buffer to protobuf a particular peer - * @param in the peer to examine - * @returns an approximation of the buffer size required (erring on the side of bigger) - */ -size_t libp2p_message_peer_protobuf_encode_size(struct Libp2pPeer* in); - -/** - * Encode the Peer into a buffer - * @param in the peer - * @param buffer where to put it - * @param max_buffer_size the maximum amount of memory reserved for the buffer - * @param bytes_written the number of bytes written to the buffer - * @returns true(1) on success, otherwise 0 - */ -int libp2p_message_peer_protobuf_encode(struct Libp2pPeer* in, unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written); - -/** - * turn an array of bytes into a Peer - * @param in the protobuf formatted peer - * @param in_size the size of in - * @param out the new Peer - * @returns true(1) on success, otherwise false - */ -int libp2p_message_peer_protobuf_decode(unsigned char* in, size_t in_size, struct Libp2pPeer** out); - /** * create a new Libp2pMessage struct * @returns a new Libp2pMessage with default settings diff --git a/include/libp2p/utils/linked_list.h b/include/libp2p/utils/linked_list.h index 036d745..8ae47c5 100644 --- a/include/libp2p/utils/linked_list.h +++ b/include/libp2p/utils/linked_list.h @@ -13,6 +13,9 @@ struct Libp2pLinkedList* libp2p_utils_linked_list_new(); /** * Free resources from a linked list + * NOTE: if the item is a complex object, free the item before + * you call this method, and set item to NULL. Otherwise, this + * method will call a simple free() * @param head the top of the linked list */ void libp2p_utils_linked_list_free(struct Libp2pLinkedList* head); diff --git a/peer/Makefile b/peer/Makefile new file mode 100644 index 0000000..6856cd8 --- /dev/null +++ b/peer/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS = -O0 -I../include -I../../c-protobuf -I../../c-multihash/include -I../../c-multiaddr/include -g3 +LFLAGS = +DEPS = +OBJS = peer.o peerstore.o + +%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + + +all: $(OBJS) + +clean: + rm -f $(OBJS) diff --git a/peer/peer.c b/peer/peer.c new file mode 100644 index 0000000..78c0df0 --- /dev/null +++ b/peer/peer.c @@ -0,0 +1,184 @@ +#include + +#include "libp2p/peer/peer.h" +#include "libp2p/utils/linked_list.h" +#include "multiaddr/multiaddr.h" +#include "protobuf.h" + +/** + * create a new Peer struct + * @returns a struct or NULL if there was a problem + */ +struct Libp2pPeer* libp2p_peer_new() { + struct Libp2pPeer* out = (struct Libp2pPeer*)malloc(sizeof(struct Libp2pPeer)); + if (out != NULL) { + out->id = NULL; + out->id_size = 0; + out->addr_head = NULL; + out->connection_type = CONNECTION_TYPE_NOT_CONNECTED; + } + return out; +} + +void libp2p_peer_free(struct Libp2pPeer* in) { + if (in != NULL) { + if (in->id != NULL) + free(in->id); + // free the memory in the linked list + struct Libp2pLinkedList* current = in->addr_head; + while (current != NULL) { + struct Libp2pLinkedList* temp = current->next; + multiaddress_free((struct MultiAddress*)current->item); + free(current); + current = temp; + } + free(in); + } +} + +/** + * Make a copy of a peer + * @param in what is to be copied + * @returns a new struct, that does not rely on the old + */ +struct Libp2pPeer* libp2p_peer_copy(struct Libp2pPeer* in) { + struct Libp2pPeer* out = libp2p_peer_new(); + if (out != NULL) { + out->id_size = in->id_size; + out->id = malloc(in->id_size); + if (out->id == NULL) { + libp2p_peer_free(out); + return NULL; + } + memcpy(out->id, in->id, in->id_size); + out->connection_type = in->connection_type; + struct Libp2pLinkedList* current_in = in->addr_head; + struct Libp2pLinkedList* current_out = NULL; + while (current_in != NULL) { + struct MultiAddress* addr = (struct MultiAddress*)current_in->item; + struct Libp2pLinkedList* copy_item = libp2p_utils_linked_list_new(); + copy_item->item = multiaddress_copy(addr); + if (out->addr_head == NULL) { + out->addr_head = copy_item; + } else { + current_out->next = copy_item; + current_out = copy_item; + } + current_in = current_in->next; + } + } + return out; +} + +size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in) { + // id + connection_type + int sz = 11 + in->id_size + 11; + // loop through the multiaddresses + struct Libp2pLinkedList* current = in->addr_head; + while (current != NULL) { + // find the length of the MultiAddress converted into bytes + struct MultiAddress* data = (struct MultiAddress*)current->item; + sz += 11 + data->bsize; + current = current->next; + } + return sz; +} + +int libp2p_peer_protobuf_encode(struct Libp2pPeer* in, unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written) { + // data & data_size + size_t bytes_used = 0; + *bytes_written = 0; + int retVal = 0; + // field 1 (id) + retVal = protobuf_encode_length_delimited(1, WIRETYPE_LENGTH_DELIMITED, in->id, in->id_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); + if (retVal == 0) + return 0; + *bytes_written += bytes_used; + // field 2 (repeated) + struct Libp2pLinkedList* current = in->addr_head; + while (current != NULL) { + struct MultiAddress* data = (struct MultiAddress*)current->item; + retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, data->bytes, data->bsize, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); + if (retVal == 0) + return 0; + *bytes_written += bytes_used; + current = current->next; + } + // field 3 (varint) + retVal = protobuf_encode_varint(3, WIRETYPE_VARINT, in->connection_type, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); + if (retVal == 0) + return 0; + *bytes_written += bytes_used; + return 1; +} + +int libp2p_peer_protobuf_decode(unsigned char* in, size_t in_size, struct Libp2pPeer** out) { + size_t pos = 0; + int retVal = 0; + char* buffer = NULL; + size_t buffer_size = 0; + struct Libp2pLinkedList* current = NULL; + struct Libp2pLinkedList* last = NULL; + struct MultiAddress* ma = NULL; + + if ( (*out = (struct Libp2pPeer*)malloc(sizeof(struct Libp2pPeer))) == NULL) + goto exit; + + struct Libp2pPeer* ptr = *out; + + ptr->addr_head = NULL; + + while(pos < in_size) { + size_t bytes_read = 0; + int field_no; + enum WireType field_type; + if (protobuf_decode_field_and_type(&in[pos], in_size, &field_no, &field_type, &bytes_read) == 0) { + goto exit; + } + pos += bytes_read; + switch(field_no) { + case (1): // id + if (!protobuf_decode_length_delimited(&in[pos], in_size - pos, (char**)&(ptr->id),&(ptr->id_size), &bytes_read)) + goto exit; + pos += bytes_read; + break; + case (2): { // multiaddress bytes + if (!protobuf_decode_length_delimited(&in[pos], in_size - pos, &buffer, &buffer_size, &bytes_read)) + goto exit; + pos += bytes_read; + // now turn it into multiaddress + struct Libp2pLinkedList* current = libp2p_utils_linked_list_new(); + if (current == NULL) + goto exit; + current->item = (void*)multiaddress_new_from_bytes(buffer, buffer_size); + free(buffer); + buffer = NULL; + // assign the values + if (ptr->addr_head == NULL) { + ptr->addr_head = current; + } else { + last->next = current; + } + last = current; + current = NULL; + break; + } + case (3): // enum as varint + if (!protobuf_decode_varint(&in[pos], in_size - pos, (long long unsigned int*)&ptr->connection_type, &bytes_read)) + goto exit; + pos += bytes_read; + break; + } + } + + retVal = 1; + +exit: + if (retVal == 0) { + free(*out); + *out = NULL; + } + if (buffer != NULL) + free(buffer); + return retVal; +} diff --git a/peer/peerstore.c b/peer/peerstore.c new file mode 100644 index 0000000..1d5ff55 --- /dev/null +++ b/peer/peerstore.c @@ -0,0 +1,109 @@ +#include +#include + +#include "libp2p/peer/peerstore.h" + +struct PeerEntry* libp2p_peer_entry_new() { + struct PeerEntry* out = (struct PeerEntry*)malloc(sizeof(struct PeerEntry)); + if (out != NULL) { + out->peer = NULL; + } + return out; +} + +void libp2p_peer_entry_free(struct PeerEntry* in) { + if (in != NULL) { + libp2p_peer_free(in->peer); + free(in); + } +} + +struct PeerEntry* libp2p_peer_entry_copy(struct PeerEntry* in) { + struct PeerEntry* out = libp2p_peer_entry_new(); + if (out != NULL) { + out->peer = libp2p_peer_copy(in->peer); + if (out->peer == NULL) { + free(out); + return NULL; + } + } + return out; +} + +/** + * Creates a new empty peerstore + * @returns an empty peerstore or NULL on error + */ +struct Peerstore* libp2p_peerstore_new() { + struct Peerstore* out = (struct Peerstore*)malloc(sizeof(struct Peerstore)); + if (out != NULL) { + out->head_entry = NULL; + } + return out; +} + +/** + * Deallocate resources used by the peerstore + * @param in the struct to deallocate + * @returns true(1) on success, otherwise false(0) + */ +int libp2p_peerstore_free(struct Peerstore* in) { + if (in != NULL) { + struct Libp2pLinkedList* current = in->head_entry; + struct Libp2pLinkedList* next = NULL; + while (current != NULL) { + next = current->next; + libp2p_peer_entry_free((struct PeerEntry*)current->item); + current->item = NULL; + libp2p_utils_linked_list_free(current); + current = next; + } + free(in); + } + return 1; +} + +/** + * Add a Peer to the Peerstore + * @param peerstore the peerstore to add the entry to + * @param peer_entry the entry to add + * @returns true(1) on success, otherwise false + */ +int libp2p_peerstore_add_peer_entry(struct Peerstore* peerstore, struct PeerEntry* peer_entry) { + struct Libp2pLinkedList* new_item = libp2p_utils_linked_list_new(); + if (new_item == NULL) + return 0; + new_item->item = libp2p_peer_entry_copy(peer_entry); + if (new_item->item == NULL) { + libp2p_utils_linked_list_free(new_item); + return 0; + } + if (peerstore->head_entry == NULL) { + peerstore->head_entry = new_item; + peerstore->last_entry = new_item; + } else { + peerstore->last_entry->next = new_item; + peerstore->last_entry = new_item; + } + return 1; +} + +/** + * Retrieve a peer from the peerstore based on the peer id + * @param peerstore the peerstore to search + * @param peer_id the id to search for as a binary array + * @param peer_id_size the size of the binary array + * @returns the PeerEntry struct if found, otherwise NULL + */ +struct PeerEntry* libp2p_peerstore_get_peer_entry(struct Peerstore* peerstore, unsigned char* peer_id, size_t peer_id_size) { + struct Libp2pLinkedList* current = peerstore->head_entry; + while(current != NULL) { + struct Libp2pPeer* peer = ((struct PeerEntry*)current->item)->peer; + if (peer->id_size != peer_id_size) + continue; + if (memcmp(peer_id, peer->id, peer->id_size) == 0) { + return (struct PeerEntry*)current->item; + } + } + return NULL; +} diff --git a/record/message.c b/record/message.c index 59c4146..ff754e6 100644 --- a/record/message.c +++ b/record/message.c @@ -1,154 +1,12 @@ #include #include "libp2p/record/message.h" +#include "libp2p/peer/peer.h" #include "libp2p/utils/linked_list.h" #include "libp2p/utils/vector.h" #include "protobuf.h" #include "multiaddr/multiaddr.h" -/** - * create a new Peer struct - * @returns a struct or NULL if there was a problem - */ -struct Libp2pPeer* libp2p_message_peer_new() { - struct Libp2pPeer* out = (struct Libp2pPeer*)malloc(sizeof(struct Libp2pPeer)); - if (out != NULL) { - out->id = NULL; - out->id_size = 0; - out->addr_head = NULL; - out->connection_type = CONNECTION_TYPE_NOT_CONNECTED; - } - return out; -} - -void libp2p_message_peer_free(struct Libp2pPeer* in) { - if (in != NULL) { - if (in->id != NULL) - free(in->id); - // free the memory in the linked list - struct Libp2pLinkedList* current = in->addr_head; - while (current != NULL) { - struct Libp2pLinkedList* temp = current->next; - multiaddress_free((struct MultiAddress*)current->item); - free(current); - current = temp; - } - free(in); - } -} - -size_t libp2p_message_peer_protobuf_encode_size(struct Libp2pPeer* in) { - // id + connection_type - int sz = 11 + in->id_size + 11; - // loop through the multiaddresses - struct Libp2pLinkedList* current = in->addr_head; - while (current != NULL) { - // find the length of the MultiAddress converted into bytes - struct MultiAddress* data = (struct MultiAddress*)current->item; - sz += 11 + data->bsize; - current = current->next; - } - return sz; -} - -int libp2p_message_peer_protobuf_encode(struct Libp2pPeer* in, unsigned char* buffer, size_t max_buffer_size, size_t* bytes_written) { - // data & data_size - size_t bytes_used = 0; - *bytes_written = 0; - int retVal = 0; - // field 1 (id) - retVal = protobuf_encode_length_delimited(1, WIRETYPE_LENGTH_DELIMITED, in->id, in->id_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); - if (retVal == 0) - return 0; - *bytes_written += bytes_used; - // field 2 (repeated) - struct Libp2pLinkedList* current = in->addr_head; - while (current != NULL) { - struct MultiAddress* data = (struct MultiAddress*)current->item; - retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, data->bytes, data->bsize, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); - if (retVal == 0) - return 0; - *bytes_written += bytes_used; - current = current->next; - } - // field 3 (varint) - retVal = protobuf_encode_varint(3, WIRETYPE_VARINT, in->connection_type, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used); - if (retVal == 0) - return 0; - *bytes_written += bytes_used; - return 1; -} - -int libp2p_message_peer_protobuf_decode(unsigned char* in, size_t in_size, struct Libp2pPeer** out) { - size_t pos = 0; - int retVal = 0; - char* buffer = NULL; - size_t buffer_size = 0; - struct Libp2pLinkedList* current = NULL; - struct Libp2pLinkedList* last = NULL; - struct MultiAddress* ma = NULL; - - if ( (*out = (struct Libp2pPeer*)malloc(sizeof(struct Libp2pPeer))) == NULL) - goto exit; - - struct Libp2pPeer* ptr = *out; - - ptr->addr_head = NULL; - - while(pos < in_size) { - size_t bytes_read = 0; - int field_no; - enum WireType field_type; - if (protobuf_decode_field_and_type(&in[pos], in_size, &field_no, &field_type, &bytes_read) == 0) { - goto exit; - } - pos += bytes_read; - switch(field_no) { - case (1): // id - if (!protobuf_decode_length_delimited(&in[pos], in_size - pos, (char**)&(ptr->id),&(ptr->id_size), &bytes_read)) - goto exit; - pos += bytes_read; - break; - case (2): { // multiaddress bytes - if (!protobuf_decode_length_delimited(&in[pos], in_size - pos, &buffer, &buffer_size, &bytes_read)) - goto exit; - pos += bytes_read; - // now turn it into multiaddress - struct Libp2pLinkedList* current = libp2p_utils_linked_list_new(); - if (current == NULL) - goto exit; - current->item = (void*)multiaddress_new_from_bytes(buffer, buffer_size); - free(buffer); - buffer = NULL; - // assign the values - if (ptr->addr_head == NULL) { - ptr->addr_head = current; - } else { - last->next = current; - } - last = current; - current = NULL; - break; - } - case (3): // enum as varint - if (!protobuf_decode_varint(&in[pos], in_size - pos, (long long unsigned int*)&ptr->connection_type, &bytes_read)) - goto exit; - pos += bytes_read; - break; - } - } - - retVal = 1; - -exit: - if (retVal == 0) { - free(*out); - *out = NULL; - } - if (buffer != NULL) - free(buffer); - return retVal; -} /*** * protobuf and other methods for Message @@ -169,26 +27,30 @@ struct Libp2pMessage* libp2p_message_new() { } void libp2p_message_free(struct Libp2pMessage* in) { - // a linked list of peer structs - struct Libp2pLinkedList* current = in->closer_peer_head; - while (current != NULL) { - struct Libp2pLinkedList* next = current->next; - struct Libp2pPeer* temp = (struct Libp2pPeer*)current->item; - libp2p_message_peer_free(temp); - current->item = NULL; - libp2p_utils_linked_list_free(current); - current = next; + if (in != NULL) { + // a linked list of peer structs + struct Libp2pLinkedList* current = in->closer_peer_head; + struct Libp2pLinkedList* next = NULL; + while (current != NULL) { + next = current->next; + libp2p_peer_free(current->item); + current->item = NULL; + libp2p_utils_linked_list_free(current); + current = next; + } + if (in->key != NULL) + free(in->key); + current = in->provider_peer_head; + while (current != NULL) { + next = current->next; + libp2p_peer_free(current->item); + current->item = NULL; + libp2p_utils_linked_list_free(current); + current = next; + } + libp2p_record_free(in->record); + free(in); } - if (in->key != NULL) - free(in->key); - current = in->provider_peer_head; - while (current != NULL) { - struct Libp2pLinkedList* next = current->next; - libp2p_message_peer_free((struct Libp2pPeer*)next->item); - current = next; - } - libp2p_record_free(in->record); - free(in); } size_t libp2p_message_protobuf_encode_size(struct Libp2pMessage* in) { @@ -203,13 +65,13 @@ size_t libp2p_message_protobuf_encode_size(struct Libp2pMessage* in) { // closer peers struct Libp2pLinkedList* current = in->closer_peer_head; while (current != NULL) { - retVal += 11 + libp2p_message_peer_protobuf_encode_size((struct Libp2pPeer*)current->item); + retVal += 11 + libp2p_peer_protobuf_encode_size((struct Libp2pPeer*)current->item); current = current->next; } // provider peers current = in->provider_peer_head; while (current != NULL) { - retVal += 11 + libp2p_message_peer_protobuf_encode_size((struct Libp2pPeer*)current->item); + retVal += 11 + libp2p_peer_protobuf_encode_size((struct Libp2pPeer*)current->item); current = current->next; } return retVal; @@ -243,11 +105,11 @@ int libp2p_message_protobuf_encode(struct Libp2pMessage* in, unsigned char* buff struct Libp2pLinkedList* current = in->closer_peer_head; while (current != NULL) { struct Libp2pPeer* peer = (struct Libp2pPeer*)current->item; - protobuf_size = libp2p_message_peer_protobuf_encode_size(peer); + protobuf_size = libp2p_peer_protobuf_encode_size(peer); unsigned char* peer_buffer = (unsigned char*)malloc(protobuf_size); if (peer_buffer == NULL) return 0; - if (!libp2p_message_peer_protobuf_encode(peer, peer_buffer, protobuf_size, &protobuf_size)) { + if (!libp2p_peer_protobuf_encode(peer, peer_buffer, protobuf_size, &protobuf_size)) { free(peer_buffer); return 0; } @@ -262,11 +124,11 @@ int libp2p_message_protobuf_encode(struct Libp2pMessage* in, unsigned char* buff current = in->provider_peer_head; while (current != NULL) { struct Libp2pPeer* peer = (struct Libp2pPeer*)current->item; - protobuf_size = libp2p_message_peer_protobuf_encode_size(peer); + protobuf_size = libp2p_peer_protobuf_encode_size(peer); unsigned char* peer_buffer = (unsigned char*)malloc(protobuf_size); if (peer_buffer == NULL) return 0; - if (!libp2p_message_peer_protobuf_encode(peer, peer_buffer, protobuf_size, &protobuf_size)) { + if (!libp2p_peer_protobuf_encode(peer, peer_buffer, protobuf_size, &protobuf_size)) { free(peer_buffer); return 0; } @@ -298,7 +160,7 @@ int libp2p_message_protobuf_decode(unsigned char* in, size_t in_size, struct Lib struct Libp2pLinkedList* last_provider = NULL; struct Libp2pMessage* ptr = NULL; - if ( (*out = (struct Libp2pMessage*)malloc(sizeof(struct Libp2pMessage))) == NULL) + if ( (*out = libp2p_message_new()) == NULL) goto exit; ptr = *out; @@ -339,11 +201,10 @@ int libp2p_message_protobuf_decode(unsigned char* in, size_t in_size, struct Lib if (!protobuf_decode_length_delimited(&in[pos], in_size - pos, (char**)&buffer, &buffer_size, &bytes_read)) goto exit; // turn this back into a peer - current_item = (struct Libp2pLinkedList*)malloc(sizeof(struct Libp2pLinkedList)); + current_item = libp2p_utils_linked_list_new(); if (current_item == NULL) goto exit; - current_item->next = NULL; - if (!libp2p_message_peer_protobuf_decode(buffer, buffer_size, (struct Libp2pPeer**)¤t_item->item)) + if (!libp2p_peer_protobuf_decode(buffer, buffer_size, (struct Libp2pPeer**)¤t_item->item)) goto exit; free(buffer); buffer = NULL; @@ -363,7 +224,7 @@ int libp2p_message_protobuf_decode(unsigned char* in, size_t in_size, struct Lib if (current_item == NULL) goto exit; current_item->next = NULL; - if (!libp2p_message_peer_protobuf_decode(buffer, buffer_size, (struct Libp2pPeer**)¤t_item->item)) + if (!libp2p_peer_protobuf_decode(buffer, buffer_size, (struct Libp2pPeer**)¤t_item->item)) goto exit; free(buffer); buffer = NULL; diff --git a/record/record.c b/record/record.c index f6dc7cb..8dea9b8 100644 --- a/record/record.c +++ b/record/record.c @@ -116,7 +116,7 @@ int libp2p_record_protobuf_decode(const unsigned char* in, size_t in_size, struc size_t pos = 0; int retVal = 0; - if ( (*out = (struct Libp2pRecord*)malloc(sizeof(struct Libp2pRecord))) == NULL) + if ( (*out = libp2p_record_new()) == NULL) goto exit; while(pos < in_size) { diff --git a/test/test_peer.h b/test/test_peer.h new file mode 100644 index 0000000..434e554 --- /dev/null +++ b/test/test_peer.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include "libp2p/peer/peer.h" +#include "libp2p/peer/peerstore.h" + +/*** + * Includes Libp2pPeer, PeerEntry, Peerstore + */ + +/** + * Test the basics of peer + */ +int test_peer() { + struct Libp2pPeer* obj = libp2p_peer_new(); + if (obj == NULL) + return 0; + + libp2p_peer_free(obj); + return 1; +} + +/** + * Test the peerstore + */ +int test_peerstore() { + struct Peerstore* peerstore = libp2p_peerstore_new(); + struct PeerEntry* peer_entry = NULL; + struct PeerEntry* results = NULL; + int retVal = 0; + + if (peerstore == NULL) + goto exit; + + // add a peer entry to the peerstore + peer_entry = libp2p_peer_entry_new(); + peer_entry->peer = libp2p_peer_new(); + peer_entry->peer->id_size = 6; + peer_entry->peer->id = malloc(peer_entry->peer->id_size); + memcpy(peer_entry->peer->id, "ABC123", peer_entry->peer->id_size); + peer_entry->peer->connection_type = CONNECTION_TYPE_NOT_CONNECTED; + + if (!libp2p_peerstore_add_peer_entry(peerstore, peer_entry)) + goto exit; + + // now try to retrieve it + results = libp2p_peerstore_get_peer_entry(peerstore, "ABC123", 6); + + if (results == NULL || results->peer->id_size != 6) + goto exit; + + // cleanup + retVal = 1; + + exit: + if (peerstore != NULL) + libp2p_peerstore_free(peerstore); + if (peer_entry != NULL) + libp2p_peer_entry_free(peer_entry); + return retVal; +} diff --git a/test/test_record.h b/test/test_record.h index 68c5c61..f178f52 100644 --- a/test/test_record.h +++ b/test/test_record.h @@ -2,6 +2,7 @@ #include "libp2p/record/record.h" #include "libp2p/record/message.h" +#include "libp2p/peer/peer.h" #include "multiaddr/multiaddr.h" int setval(char** result, size_t* result_size, char* in) { @@ -42,22 +43,22 @@ int test_record_protobuf() { if (!libp2p_record_protobuf_decode(protobuf, protobuf_size, &results)) goto exit; - if (strcmp(record->key, results->key) != 0) - goto exit; - if (strcmp(record->value, results->value) != 0) - goto exit; - if (strcmp(record->author, results->author) != 0) - goto exit; - if (strcmp(record->signature, results->signature) != 0) - goto exit; - if (strcmp(record->time_received, results->time_received) != 0) - goto exit; if (record->key_size != results->key_size || record->value_size != results->value_size || record->author_size != results->author_size || record->signature_size != results->signature_size || record->time_received_size != results->time_received_size) goto exit; + if (strcmp(record->key, results->key) != 0) + goto exit; + if (strncmp(record->value, results->value, results->value_size) != 0) + goto exit; + if (strncmp(record->author, results->author, results->author_size) != 0) + goto exit; + if (strncmp(record->signature, results->signature, results->signature_size) != 0) + goto exit; + if (strncmp(record->time_received, results->time_received, results->time_received_size) != 0) + goto exit; retVal = 1; exit: @@ -151,7 +152,7 @@ int test_record_peer_protobuf() { multi_addr1 = multiaddress_new_from_string("/ip4/127.0.0.1/tcp/4001"); // make peer - peer = libp2p_message_peer_new(); + peer = libp2p_peer_new(); peer->connection_type = CONNECTION_TYPE_CAN_CONNECT; peer->id = malloc(7); strcpy(peer->id, "ABC123"); @@ -160,15 +161,15 @@ int test_record_peer_protobuf() { peer->addr_head->item = multi_addr1; // protobuf - protobuf_size = libp2p_message_peer_protobuf_encode_size(peer); + protobuf_size = libp2p_peer_protobuf_encode_size(peer); protobuf = (unsigned char*)malloc(protobuf_size); if (protobuf == NULL) goto exit; - if (!libp2p_message_peer_protobuf_encode(peer, protobuf, protobuf_size, &protobuf_size)) + if (!libp2p_peer_protobuf_encode(peer, protobuf, protobuf_size, &protobuf_size)) goto exit; // unprotobuf - if (!libp2p_message_peer_protobuf_decode(protobuf, protobuf_size, &result)) + if (!libp2p_peer_protobuf_decode(protobuf, protobuf_size, &result)) goto exit; // check results @@ -189,14 +190,17 @@ int test_record_peer_protobuf() { // cleanup retVal = 1; exit: + if (peer != NULL) { + libp2p_peer_free(peer); + // above gets rid of below... + multi_addr1 = NULL; + } if (multi_addr1 != NULL) multiaddress_free(multi_addr1); - if (peer != NULL) - libp2p_message_peer_free(peer); if (protobuf != NULL) free(protobuf); if (result != NULL) - libp2p_message_peer_free(result); + libp2p_peer_free(result); return retVal; } @@ -209,7 +213,7 @@ int test_record_message_protobuf() { size_t buffer_len = 0; // construct message - closer_peer = libp2p_message_peer_new(); + closer_peer = libp2p_peer_new(); closer_peer->connection_type = CONNECTION_TYPE_CAN_CONNECT; closer_peer->id = malloc(7); strcpy(closer_peer->id, "ABC123"); diff --git a/test/testit.c b/test/testit.c index 4b19020..bdd5451 100644 --- a/test/testit.c +++ b/test/testit.c @@ -10,6 +10,7 @@ #include "test_multistream.h" #include "test_conn.h" #include "test_record.h" +#include "test_peer.h" const char* names[] = { "test_public_der_to_private_der", @@ -33,7 +34,7 @@ const char* names[] = { //"test_crypto_rsa_sign", "test_crypto_encoding_base32_encode", "test_protobuf_private_key", - "test_secio_handshake", + //"test_secio_handshake", "test_multistream_connect", "test_multistream_get_list", "test_ephemeral_key_generate", @@ -42,7 +43,9 @@ const char* names[] = { "test_record_protobuf", "test_record_make_put_record", "test_record_peer_protobuf", - "test_record_message_protobuf" + "test_record_message_protobuf", + "test_peer", + "test_peerstore" }; int (*funcs[])(void) = { @@ -67,7 +70,7 @@ int (*funcs[])(void) = { //test_crypto_rsa_sign, test_crypto_encoding_base32_encode, test_protobuf_private_key, - test_secio_handshake, + //test_secio_handshake, test_multistream_connect, test_multistream_get_list, test_ephemeral_key_generate, @@ -76,7 +79,9 @@ int (*funcs[])(void) = { test_record_protobuf, test_record_make_put_record, test_record_peer_protobuf, - test_record_message_protobuf + test_record_message_protobuf, + test_peer, + test_peerstore }; int testit(const char* name, int (*func)(void)) { diff --git a/utils/linked_list.c b/utils/linked_list.c index 1f75321..4b49515 100644 --- a/utils/linked_list.c +++ b/utils/linked_list.c @@ -16,8 +16,10 @@ void libp2p_utils_linked_list_free(struct Libp2pLinkedList* head) { struct Libp2pLinkedList* next = NULL; while (current != NULL) { next = current->next; - if (current->item != NULL) + if (current->item != NULL) { free(current->item); + current->item = NULL; + } free(current); current = next; }