Reading from stream now uses StreamMessage struct
This commit is contained in:
parent
0166a89d48
commit
6147769f4b
10 changed files with 191 additions and 127 deletions
|
@ -27,6 +27,7 @@
|
||||||
<option id="gnu.c.compiler.option.include.paths.1688271638" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
<option id="gnu.c.compiler.option.include.paths.1688271638" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/c-multihash/include}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/c-multihash/include}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/c-libp2p/include}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/c-libp2p/include}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/c-multiaddr/include}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1284958161" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.1284958161" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||||
</tool>
|
</tool>
|
||||||
|
|
|
@ -129,6 +129,35 @@ int libp2p_stream_unlock(struct Stream* stream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Create a new StreamMessage struct
|
||||||
|
* @returns a StreamMessage struct
|
||||||
|
*/
|
||||||
|
struct StreamMessage* libp2p_stream_message_new() {
|
||||||
|
struct StreamMessage* out = (struct StreamMessage*) malloc(sizeof(struct StreamMessage));
|
||||||
|
if (out != NULL) {
|
||||||
|
out->data = NULL;
|
||||||
|
out->data_size = 0;
|
||||||
|
out->error_number = 0;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* free resources of a StreamMessage struct
|
||||||
|
* @param msg the StreamMessage to free
|
||||||
|
*/
|
||||||
|
void libp2p_stream_message_free(struct StreamMessage* msg) {
|
||||||
|
if (msg != NULL) {
|
||||||
|
if (msg->data != NULL) {
|
||||||
|
free(msg->data);
|
||||||
|
msg->data = NULL;
|
||||||
|
}
|
||||||
|
free(msg);
|
||||||
|
msg = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
* Make a copy of a SessionContext
|
* Make a copy of a SessionContext
|
||||||
* @param original the original
|
* @param original the original
|
||||||
|
|
|
@ -44,12 +44,12 @@ int libp2p_net_multistream_receive_protocol(struct SessionContext* context);
|
||||||
/**
|
/**
|
||||||
* Read from a multistream socket
|
* Read from a multistream socket
|
||||||
* @param socket_fd the socket file descriptor
|
* @param socket_fd the socket file descriptor
|
||||||
* @param data the data to send
|
* @param data where to put the results
|
||||||
* @param data_length the length of the data
|
|
||||||
* @param timeout_secs number of seconds before read gives up. Will return 0 data length.
|
* @param timeout_secs number of seconds before read gives up. Will return 0 data length.
|
||||||
* @returns the number of bytes written
|
* @returns the number of bytes written
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_read(void* stream_context, unsigned char** data, size_t* data_length, int timeout_secs);
|
int libp2p_net_multistream_read(void* stream_context, struct StreamMessage** data, int timeout_secs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write to an open multistream host
|
* Write to an open multistream host
|
||||||
* @param socket_fd the socket file descriptor
|
* @param socket_fd the socket file descriptor
|
||||||
|
|
|
@ -2,6 +2,29 @@
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates a message that (was/will be) sent
|
||||||
|
* across a stream
|
||||||
|
*/
|
||||||
|
struct StreamMessage {
|
||||||
|
uint8_t* data;
|
||||||
|
size_t data_size;
|
||||||
|
int error_number;
|
||||||
|
};
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Create a new StreamMessage struct
|
||||||
|
* @returns a StreamMessage struct
|
||||||
|
*/
|
||||||
|
struct StreamMessage* libp2p_stream_message_new();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* free resources of a StreamMessage struct
|
||||||
|
* @param msg the StreamMessage to free
|
||||||
|
*/
|
||||||
|
void libp2p_stream_message_free(struct StreamMessage* msg);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface in front of various streams
|
* An interface in front of various streams
|
||||||
*/
|
*/
|
||||||
|
@ -16,12 +39,11 @@ struct Stream {
|
||||||
/**
|
/**
|
||||||
* Reads from the stream
|
* Reads from the stream
|
||||||
* @param stream the stream context (usually a SessionContext pointer)
|
* @param stream the stream context (usually a SessionContext pointer)
|
||||||
* @param buffer where to put the results
|
* @param message where to put the incoming message (will be allocated)
|
||||||
* @param bytes_read how many bytes were read
|
|
||||||
* @param timeout_secs number of seconds before a timeout
|
* @param timeout_secs number of seconds before a timeout
|
||||||
* @returns true(1) on success, false(0) otherwise
|
* @returns true(1) on success, false(0) otherwise
|
||||||
*/
|
*/
|
||||||
int (*read)(void* stream_context, unsigned char** buffer, size_t* bytes_read, int timeout_secs);
|
int (*read)(void* stream_context, struct StreamMessage** message, int timeout_secs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes to a stream
|
* Writes to a stream
|
||||||
|
|
|
@ -60,9 +60,8 @@ int libp2p_net_multistream_send_protocol(struct SessionContext *context) {
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_receive_protocol(struct SessionContext* context) {
|
int libp2p_net_multistream_receive_protocol(struct SessionContext* context) {
|
||||||
char* protocol = "/multistream/1.0.0\n";
|
char* protocol = "/multistream/1.0.0\n";
|
||||||
uint8_t* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_size = 0;
|
if (!context->default_stream->read(context, &results, 30)) {
|
||||||
if (!context->default_stream->read(context, &results, &results_size, 30)) {
|
|
||||||
libp2p_logger_error("multistream", "receive_protocol: Unable to read results.\n");
|
libp2p_logger_error("multistream", "receive_protocol: Unable to read results.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -82,21 +81,20 @@ int libp2p_net_multistream_handle_message(const uint8_t *incoming, size_t incomi
|
||||||
struct MultistreamContext* multistream_context = (struct MultistreamContext*) protocol_context;
|
struct MultistreamContext* multistream_context = (struct MultistreamContext*) protocol_context;
|
||||||
|
|
||||||
// try to read from the network
|
// try to read from the network
|
||||||
uint8_t *results = 0;
|
struct StreamMessage* results = NULL;
|
||||||
size_t bytes_read = 0;
|
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
int max_retries = 10;
|
int max_retries = 10;
|
||||||
int numRetries = 0;
|
int numRetries = 0;
|
||||||
// handle the call
|
// handle the call
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// try to read for 5 seconds
|
// try to read for 5 seconds
|
||||||
if (context->default_stream->read(context, &results, &bytes_read, 5)) {
|
if (context->default_stream->read(context, &results, 5)) {
|
||||||
// we read something from the network. Process it.
|
// we read something from the network. Process it.
|
||||||
// NOTE: If it is a multistream protocol that we are receiving, ignore it.
|
// NOTE: If it is a multistream protocol that we are receiving, ignore it.
|
||||||
if (libp2p_net_multistream_can_handle(results, bytes_read))
|
if (libp2p_net_multistream_can_handle(results->data, results->data_size))
|
||||||
continue;
|
continue;
|
||||||
numRetries = 0;
|
numRetries = 0;
|
||||||
retVal = libp2p_protocol_marshal(results, bytes_read, context, multistream_context->handlers);
|
retVal = libp2p_protocol_marshal(results->data, results->data_size, context, multistream_context->handlers);
|
||||||
if (results != NULL)
|
if (results != NULL)
|
||||||
free(results);
|
free(results);
|
||||||
// exit the loop on error (or if they ask us to no longer loop by returning 0)
|
// exit the loop on error (or if they ask us to no longer loop by returning 0)
|
||||||
|
@ -244,7 +242,7 @@ int libp2p_net_multistream_write(void* stream_context, const unsigned char* data
|
||||||
* @param timeout_secs the seconds before a timeout
|
* @param timeout_secs the seconds before a timeout
|
||||||
* @returns number of bytes received
|
* @returns number of bytes received
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_read(void* stream_context, unsigned char** results, size_t* results_size, int timeout_secs) {
|
int libp2p_net_multistream_read(void* stream_context, struct StreamMessage** results, int timeout_secs) {
|
||||||
struct SessionContext* session_context = (struct SessionContext*)stream_context;
|
struct SessionContext* session_context = (struct SessionContext*)stream_context;
|
||||||
struct Stream* stream = session_context->default_stream;
|
struct Stream* stream = session_context->default_stream;
|
||||||
int bytes = 0;
|
int bytes = 0;
|
||||||
|
@ -300,39 +298,52 @@ int libp2p_net_multistream_read(void* stream_context, unsigned char** results, s
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// parse the results, removing the leading size indicator
|
// parse the results, removing the leading size indicator
|
||||||
*results = malloc(num_bytes_requested);
|
*results = libp2p_stream_message_new();
|
||||||
if (*results == NULL)
|
struct StreamMessage* rslts = *results;
|
||||||
|
if (rslts == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
memcpy(*results, buffer, num_bytes_requested);
|
rslts->data_size = num_bytes_requested;
|
||||||
*results_size = num_bytes_requested;
|
rslts->data = (uint8_t*) malloc(num_bytes_requested);
|
||||||
|
if (rslts->data == NULL) {
|
||||||
|
libp2p_stream_message_free(rslts);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(rslts->data, buffer, num_bytes_requested);
|
||||||
session_context->last_comm_epoch = os_utils_gmtime();
|
session_context->last_comm_epoch = os_utils_gmtime();
|
||||||
} else { // use secio instead of raw read/writes
|
} else { // use secio instead of raw read/writes
|
||||||
unsigned char* read_from_stream;
|
struct StreamMessage* read_from_stream;
|
||||||
size_t size_read_from_stream;
|
if (session_context->default_stream->read(session_context, &read_from_stream, timeout_secs) == 0) {
|
||||||
if (session_context->default_stream->read(session_context, &read_from_stream, &size_read_from_stream, timeout_secs) == 0) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// pull out num_bytes_requested
|
// pull out num_bytes_requested
|
||||||
num_bytes_requested = varint_decode(read_from_stream, size_read_from_stream, &left);
|
num_bytes_requested = varint_decode(read_from_stream->data, read_from_stream->data_size, &left);
|
||||||
memcpy(buffer, read_from_stream, size_read_from_stream);
|
memcpy(buffer, read_from_stream->data, read_from_stream->data_size);
|
||||||
free(read_from_stream);
|
buffer_size = read_from_stream->data_size;
|
||||||
buffer_size = size_read_from_stream;
|
libp2p_stream_message_free(read_from_stream);
|
||||||
|
read_from_stream = NULL;
|
||||||
while (num_bytes_requested > buffer_size - left) {
|
while (num_bytes_requested > buffer_size - left) {
|
||||||
// need to read more into buffer
|
// need to read more into buffer
|
||||||
if (session_context->default_stream->read(session_context, &read_from_stream, &size_read_from_stream, timeout_secs) == 0) {
|
if (session_context->default_stream->read(session_context, &read_from_stream, timeout_secs) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(&buffer[buffer_size], read_from_stream, size_read_from_stream);
|
memcpy(&buffer[buffer_size], read_from_stream->data, read_from_stream->data_size);
|
||||||
free(read_from_stream);
|
buffer_size += read_from_stream->data_size;
|
||||||
buffer_size += size_read_from_stream;
|
libp2p_stream_message_free(read_from_stream);
|
||||||
}
|
}
|
||||||
*results = malloc(num_bytes_requested);
|
*results = libp2p_stream_message_new();
|
||||||
*results_size = num_bytes_requested;
|
struct StreamMessage* rslts = *results;
|
||||||
if (*results == NULL) {
|
if (rslts == NULL) {
|
||||||
libp2p_logger_error("multistream", "Unable to allocate %lu bytes of memory.", num_bytes_requested);
|
libp2p_logger_error("multistream", "Unable to allocate %lu bytes of memory.", num_bytes_requested);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(*results, &buffer[left], num_bytes_requested);
|
rslts->data_size = num_bytes_requested;
|
||||||
|
rslts->data = (uint8_t*) malloc(num_bytes_requested);
|
||||||
|
if (rslts->data == NULL) {
|
||||||
|
libp2p_stream_message_free(rslts);
|
||||||
|
libp2p_logger_error("multistream", "Unable to allocate %lu bytes of memory.", num_bytes_requested);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(rslts->data, &buffer[left], num_bytes_requested);
|
||||||
session_context->last_comm_epoch = os_utils_gmtime();
|
session_context->last_comm_epoch = os_utils_gmtime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,8 +370,7 @@ struct Stream* libp2p_net_multistream_connect(const char* hostname, int port) {
|
||||||
*/
|
*/
|
||||||
struct Stream* libp2p_net_multistream_connect_with_timeout(const char* hostname, int port, int timeout_secs) {
|
struct Stream* libp2p_net_multistream_connect_with_timeout(const char* hostname, int port, int timeout_secs) {
|
||||||
int retVal = -1, return_result = -1, socket = -1;
|
int retVal = -1, return_result = -1, socket = -1;
|
||||||
unsigned char* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_size;
|
|
||||||
struct Stream* stream = NULL;
|
struct Stream* stream = NULL;
|
||||||
|
|
||||||
uint32_t ip = hostname_to_ip(hostname);
|
uint32_t ip = hostname_to_ip(hostname);
|
||||||
|
@ -381,8 +391,8 @@ struct Stream* libp2p_net_multistream_connect_with_timeout(const char* hostname,
|
||||||
session.default_stream = stream;
|
session.default_stream = stream;
|
||||||
|
|
||||||
// try to receive the protocol id
|
// try to receive the protocol id
|
||||||
return_result = libp2p_net_multistream_read(&session, &results, &results_size, timeout_secs);
|
return_result = libp2p_net_multistream_read(&session, &results, timeout_secs);
|
||||||
if (return_result == 0 || results_size < 1 || !libp2p_net_multistream_can_handle(results, results_size)) {
|
if (results == NULL || return_result == 0 || results->data_size < 1 || !libp2p_net_multistream_can_handle(results->data, results->data_size)) {
|
||||||
libp2p_logger_error("multistream", "Attempted to receive the multistream protocol header, but received %s.\n", results);
|
libp2p_logger_error("multistream", "Attempted to receive the multistream protocol header, but received %s.\n", results);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -418,15 +428,14 @@ struct Stream* libp2p_net_multistream_connect_with_timeout(const char* hostname,
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_negotiate(struct SessionContext* session) {
|
int libp2p_net_multistream_negotiate(struct SessionContext* session) {
|
||||||
const char* protocolID = "/multistream/1.0.0\n";
|
const char* protocolID = "/multistream/1.0.0\n";
|
||||||
unsigned char* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_length = 0;
|
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
// send the protocol id
|
// send the protocol id
|
||||||
if (!libp2p_net_multistream_write(session, (unsigned char*)protocolID, strlen(protocolID)))
|
if (!libp2p_net_multistream_write(session, (unsigned char*)protocolID, strlen(protocolID)))
|
||||||
goto exit;
|
goto exit;
|
||||||
// expect the same back
|
// expect the same back
|
||||||
libp2p_net_multistream_read(session, &results, &results_length, multistream_default_timeout);
|
libp2p_net_multistream_read(session, &results, multistream_default_timeout);
|
||||||
if (results_length == 0)
|
if (results == NULL || results->data_size == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
if (strncmp((char*)results, protocolID, strlen(protocolID)) != 0)
|
if (strncmp((char*)results, protocolID, strlen(protocolID)) != 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -82,30 +82,27 @@ int libp2p_routing_dht_protobuf_message(struct KademliaMessage* message, unsigne
|
||||||
int libp2p_routing_dht_upgrade_stream(struct SessionContext* context) {
|
int libp2p_routing_dht_upgrade_stream(struct SessionContext* context) {
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
char* protocol = "/ipfs/kad/1.0.0\n";
|
char* protocol = "/ipfs/kad/1.0.0\n";
|
||||||
unsigned char* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_size = 0;
|
|
||||||
if (!context->default_stream->write(context, (unsigned char*)protocol, strlen(protocol))) {
|
if (!context->default_stream->write(context, (unsigned char*)protocol, strlen(protocol))) {
|
||||||
libp2p_logger_error("dht_protocol", "Unable to write to stream during upgrade attempt.\n");
|
libp2p_logger_error("dht_protocol", "Unable to write to stream during upgrade attempt.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!context->default_stream->read(context, &results, &results_size, 5)) {
|
if (!context->default_stream->read(context, &results, 5)) {
|
||||||
libp2p_logger_error("dht_protocol", "Unable to read from stream during upgrade attempt.\n");
|
libp2p_logger_error("dht_protocol", "Unable to read from stream during upgrade attempt.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (results_size != strlen(protocol)) {
|
if (results == NULL || results->data_size != strlen(protocol)) {
|
||||||
libp2p_logger_error("dht_protocol", "Expected response size incorrect during upgrade attempt.\n");
|
libp2p_logger_error("dht_protocol", "Expected response size incorrect during upgrade attempt.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (strncmp((char*)results, protocol, results_size) != 0) {
|
if (strncmp((char*)results->data, protocol, results->data_size) != 0) {
|
||||||
libp2p_logger_error("dht_protocol", "Expected %s but received %s.\n", protocol, results);
|
libp2p_logger_error("dht_protocol", "Expected %s but received %s.\n", protocol, results);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
exit:
|
exit:
|
||||||
if (results != NULL) {
|
libp2p_stream_message_free(results);
|
||||||
free(results);
|
|
||||||
results = NULL;
|
results = NULL;
|
||||||
}
|
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,16 +440,17 @@ int libp2p_routing_dht_handle_find_node(struct SessionContext* session, struct K
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @returns true(1) on success, otherwise false(0)
|
||||||
*/
|
*/
|
||||||
int libp2p_routing_dht_handle_message(struct SessionContext* session, struct Peerstore* peerstore, struct ProviderStore* providerstore) {
|
int libp2p_routing_dht_handle_message(struct SessionContext* session, struct Peerstore* peerstore, struct ProviderStore* providerstore) {
|
||||||
unsigned char* buffer = NULL, *result_buffer = NULL;
|
unsigned char *result_buffer = NULL;
|
||||||
size_t buffer_size = 0, result_buffer_size = 0;
|
struct StreamMessage* buffer = NULL;
|
||||||
|
size_t result_buffer_size = 0;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
struct KademliaMessage* message = NULL;
|
struct KademliaMessage* message = NULL;
|
||||||
|
|
||||||
// read from stream
|
// read from stream
|
||||||
if (!session->default_stream->read(session, &buffer, &buffer_size, 5))
|
if (!session->default_stream->read(session, &buffer, 5))
|
||||||
goto exit;
|
goto exit;
|
||||||
// unprotobuf
|
// unprotobuf
|
||||||
if (!libp2p_message_protobuf_decode(buffer, buffer_size, &message))
|
if (!libp2p_message_protobuf_decode(buffer->data, buffer->data_size, &message))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// handle message
|
// handle message
|
||||||
|
@ -486,8 +484,7 @@ int libp2p_routing_dht_handle_message(struct SessionContext* session, struct Pee
|
||||||
}
|
}
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
exit:
|
exit:
|
||||||
if (buffer != NULL)
|
libp2p_stream_message_free(buffer);
|
||||||
free(buffer);
|
|
||||||
if (result_buffer != NULL)
|
if (result_buffer != NULL)
|
||||||
free(result_buffer);
|
free(result_buffer);
|
||||||
if (message != NULL)
|
if (message != NULL)
|
||||||
|
@ -503,20 +500,20 @@ int libp2p_routing_dht_handle_message(struct SessionContext* session, struct Pee
|
||||||
* @returns true(1) on success, false(0) otherwise
|
* @returns true(1) on success, false(0) otherwise
|
||||||
*/
|
*/
|
||||||
int libp2p_routing_dht_receive_message(struct SessionContext* sessionContext, struct KademliaMessage** result) {
|
int libp2p_routing_dht_receive_message(struct SessionContext* sessionContext, struct KademliaMessage** result) {
|
||||||
uint8_t* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_size = 0;
|
|
||||||
|
|
||||||
if (!sessionContext->default_stream->read(sessionContext, &results, &results_size, 5)) {
|
if (!sessionContext->default_stream->read(sessionContext, &results, 5)) {
|
||||||
libp2p_logger_error("online", "Attempted to read from Kademlia stream, but could not.\n");
|
libp2p_logger_error("online", "Attempted to read from Kademlia stream, but could not.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if we can unprotobuf
|
// see if we can unprotobuf
|
||||||
if (!libp2p_message_protobuf_decode(results, results_size, result)) {
|
if (!libp2p_message_protobuf_decode(results->data, results->data_size, result)) {
|
||||||
libp2p_logger_error("online", "Received kademlia response, but cannot decode it.\n");
|
libp2p_logger_error("online", "Received kademlia response, but cannot decode it.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
|
libp2p_stream_message_free(results);
|
||||||
return result != NULL;
|
return result != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -659,25 +659,22 @@ int libp2p_secio_send_protocol(struct SessionContext* session) {
|
||||||
int libp2p_secio_receive_protocol(struct SessionContext* session) {
|
int libp2p_secio_receive_protocol(struct SessionContext* session) {
|
||||||
char* protocol = "/secio/1.0.0\n";
|
char* protocol = "/secio/1.0.0\n";
|
||||||
int numSecs = 30;
|
int numSecs = 30;
|
||||||
unsigned char* buffer = NULL;
|
int retVal = 0;
|
||||||
size_t buffer_size = 0;
|
struct StreamMessage* buffer = NULL;
|
||||||
int retVal = session->default_stream->read(session, &buffer, &buffer_size, numSecs);
|
session->default_stream->read(session, &buffer, numSecs);
|
||||||
if (retVal == 0 || buffer != NULL) {
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
libp2p_logger_error("secio", "Expected the secio protocol header, but received NULL.\n");
|
libp2p_logger_error("secio", "Expected the secio protocol header, but received NULL.\n");
|
||||||
} else {
|
} else {
|
||||||
if (strncmp(protocol, (char*)buffer, strlen(protocol)) == 0) {
|
// see if they sent the correct response
|
||||||
free(buffer);
|
if (strncmp(protocol, (char*)buffer->data, strlen(protocol)) == 0) {
|
||||||
return 1;
|
retVal = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
libp2p_logger_error("secio", "Expected the secio protocol header, but received %s.\n", buffer);
|
libp2p_logger_error("secio", "Expected the secio protocol header, but received %s.\n", buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
libp2p_stream_message_free(buffer);
|
||||||
if (buffer != NULL)
|
return retVal;
|
||||||
free(buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -782,9 +779,8 @@ int libp2p_secio_encrypted_write(void* stream_context, const unsigned char* byte
|
||||||
* @param outgoing_size the amount of memory allocated for the results
|
* @param outgoing_size the amount of memory allocated for the results
|
||||||
* @returns number of unencrypted bytes
|
* @returns number of unencrypted bytes
|
||||||
*/
|
*/
|
||||||
int libp2p_secio_decrypt(struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, unsigned char** outgoing, size_t* outgoing_size) {
|
int libp2p_secio_decrypt(struct SessionContext* session, const unsigned char* incoming, size_t incoming_size, struct StreamMessage** outgoing) {
|
||||||
size_t data_section_size = incoming_size - 32;
|
size_t data_section_size = incoming_size - 32;
|
||||||
*outgoing_size = 0;
|
|
||||||
unsigned char* buffer;
|
unsigned char* buffer;
|
||||||
|
|
||||||
// verify MAC
|
// verify MAC
|
||||||
|
@ -802,9 +798,13 @@ int libp2p_secio_decrypt(struct SessionContext* session, const unsigned char* in
|
||||||
// MAC verification failed
|
// MAC verification failed
|
||||||
libp2p_logger_error("secio", "libp2p_secio_decrypt: MAC verification failed.\n");
|
libp2p_logger_error("secio", "libp2p_secio_decrypt: MAC verification failed.\n");
|
||||||
// copy the raw bytes into outgoing for further analysis
|
// copy the raw bytes into outgoing for further analysis
|
||||||
*outgoing = (unsigned char*)malloc(incoming_size);
|
*outgoing = libp2p_stream_message_new();
|
||||||
*outgoing_size = incoming_size;
|
struct StreamMessage* message = *outgoing;
|
||||||
memcpy(*outgoing, incoming, incoming_size);
|
if (message != NULL) {
|
||||||
|
message->data_size = incoming_size;
|
||||||
|
message->data = (uint8_t*) malloc(incoming_size);
|
||||||
|
memcpy(message->data, incoming, incoming_size);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,22 +824,28 @@ int libp2p_secio_decrypt(struct SessionContext* session, const unsigned char* in
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_aes_free(&cipher_ctx);
|
mbedtls_aes_free(&cipher_ctx);
|
||||||
*outgoing = malloc(data_section_size);
|
*outgoing = libp2p_stream_message_new();
|
||||||
*outgoing_size = data_section_size;
|
struct StreamMessage* message = *outgoing;
|
||||||
memcpy(*outgoing, buffer, data_section_size);
|
message->data_size = data_section_size;
|
||||||
|
message->data = (uint8_t*) malloc(data_section_size);
|
||||||
|
if (message->data == NULL) {
|
||||||
|
libp2p_stream_message_free(message);
|
||||||
|
*outgoing = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(message->data, buffer, data_section_size);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
return *outgoing_size;
|
return message->data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read from an encrypted stream
|
* Read from an encrypted stream
|
||||||
* @param session the session parameters
|
* @param session the session parameters
|
||||||
* @param bytes where the bytes will be stored
|
* @param bytes where the bytes will be stored
|
||||||
* @param num_bytes the number of bytes read from the stream
|
|
||||||
* @returns the number of bytes read
|
* @returns the number of bytes read
|
||||||
*/
|
*/
|
||||||
int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, size_t* num_bytes, int timeout_secs) {
|
int libp2p_secio_encrypted_read(void* stream_context, struct StreamMessage** bytes, int timeout_secs) {
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
struct SessionContext* session = (struct SessionContext*)stream_context;
|
struct SessionContext* session = (struct SessionContext*)stream_context;
|
||||||
// reader uses the remote cipher and mac
|
// reader uses the remote cipher and mac
|
||||||
|
@ -850,7 +856,7 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
|
||||||
libp2p_logger_error("secio", "Unencrypted_read returned false.\n");
|
libp2p_logger_error("secio", "Unencrypted_read returned false.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
retVal = libp2p_secio_decrypt(session, incoming, incoming_size, bytes, num_bytes);
|
retVal = libp2p_secio_decrypt(session, incoming, incoming_size, bytes);
|
||||||
if (!retVal)
|
if (!retVal)
|
||||||
libp2p_logger_error("secio", "Decrypting incoming stream returned false.\n");
|
libp2p_logger_error("secio", "Decrypting incoming stream returned false.\n");
|
||||||
exit:
|
exit:
|
||||||
|
@ -871,6 +877,7 @@ int libp2p_secio_encrypted_read(void* stream_context, unsigned char** bytes, siz
|
||||||
int libp2p_secio_handshake(struct SessionContext* local_session, const struct RsaPrivateKey* private_key, struct Peerstore* peerstore) {
|
int libp2p_secio_handshake(struct SessionContext* local_session, const struct RsaPrivateKey* private_key, struct Peerstore* peerstore) {
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
size_t results_size = 0, bytes_written = 0;
|
size_t results_size = 0, bytes_written = 0;
|
||||||
|
struct StreamMessage* stream_message = NULL;
|
||||||
unsigned char* propose_in_bytes = NULL; // the remote protobuf
|
unsigned char* propose_in_bytes = NULL; // the remote protobuf
|
||||||
size_t propose_in_size = 0;
|
size_t propose_in_size = 0;
|
||||||
unsigned char* propose_out_bytes = NULL; // the local protobuf
|
unsigned char* propose_out_bytes = NULL; // the local protobuf
|
||||||
|
@ -1172,16 +1179,16 @@ int libp2p_secio_handshake(struct SessionContext* local_session, const struct Rs
|
||||||
// receive our nonce to verify encryption works
|
// receive our nonce to verify encryption works
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Receiving our nonce\n");
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Receiving our nonce\n");
|
||||||
results = NULL;
|
results = NULL;
|
||||||
int bytes_read = libp2p_secio_encrypted_read(local_session, &results, &results_size, 10);
|
int bytes_read = libp2p_secio_encrypted_read(local_session, &stream_message, 10);
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0 || stream_message == NULL) {
|
||||||
libp2p_logger_error("secio", "Encrypted read returned %d\n", bytes_read);
|
libp2p_logger_error("secio", "Encrypted read returned %d\n", bytes_read);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (results_size != 16) {
|
if (stream_message->data_size != 16) {
|
||||||
libp2p_logger_error("secio", "Results_size should be 16 but was %d\n", results_size);
|
libp2p_logger_error("secio", "Results_size should be 16 but was %d\n", stream_message->data_size);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (libp2p_secio_bytes_compare(results, (unsigned char*)local_session->local_nonce, 16) != 0) {
|
if (libp2p_secio_bytes_compare(stream_message->data, (unsigned char*)local_session->local_nonce, 16) != 0) {
|
||||||
libp2p_logger_error("secio", "Bytes of nonce did not match\n");
|
libp2p_logger_error("secio", "Bytes of nonce did not match\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -1221,10 +1228,9 @@ int libp2p_secio_handshake(struct SessionContext* local_session, const struct Rs
|
||||||
|
|
||||||
libp2p_secio_propose_free(propose_out);
|
libp2p_secio_propose_free(propose_out);
|
||||||
libp2p_secio_propose_free(propose_in);
|
libp2p_secio_propose_free(propose_in);
|
||||||
|
libp2p_stream_message_free(stream_message);
|
||||||
|
|
||||||
if (retVal == 1) {
|
if (retVal != 1) {
|
||||||
//libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake success!\n");
|
|
||||||
} else {
|
|
||||||
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false\n");
|
libp2p_logger_log("secio", LOGLEVEL_DEBUG, "Handshake returning false\n");
|
||||||
}
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
|
@ -30,8 +30,7 @@ int test_multistream_connect() {
|
||||||
|
|
||||||
int test_multistream_get_list() {
|
int test_multistream_get_list() {
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
unsigned char* response;
|
struct StreamMessage* response;
|
||||||
size_t response_size;
|
|
||||||
char* filtered = NULL;
|
char* filtered = NULL;
|
||||||
|
|
||||||
struct SessionContext session;
|
struct SessionContext session;
|
||||||
|
@ -47,13 +46,13 @@ int test_multistream_get_list() {
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
// retrieve response
|
// retrieve response
|
||||||
retVal = libp2p_net_multistream_read(&session, &response, &response_size, 5);
|
retVal = libp2p_net_multistream_read(&session, &response, 5);
|
||||||
if (retVal <= 0)
|
if (retVal <= 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
filtered = malloc(response_size + 1);
|
filtered = malloc(response->data_size + 1);
|
||||||
strncpy(filtered, (char*)response, response_size);
|
strncpy(filtered, (char*)response->data, response->data_size);
|
||||||
filtered[response_size] = 0;
|
filtered[response->data_size] = 0;
|
||||||
|
|
||||||
fprintf(stdout, "Response from multistream ls: %s", (char*)filtered);
|
fprintf(stdout, "Response from multistream ls: %s", (char*)filtered);
|
||||||
|
|
||||||
|
@ -64,8 +63,7 @@ int test_multistream_get_list() {
|
||||||
session.insecure_stream->close(&session);
|
session.insecure_stream->close(&session);
|
||||||
libp2p_net_multistream_stream_free(session.insecure_stream);
|
libp2p_net_multistream_stream_free(session.insecure_stream);
|
||||||
}
|
}
|
||||||
if (response != NULL)
|
libp2p_stream_message_free(response);
|
||||||
free(response);
|
|
||||||
if (filtered != NULL)
|
if (filtered != NULL)
|
||||||
free(filtered);
|
free(filtered);
|
||||||
|
|
||||||
|
|
|
@ -159,17 +159,16 @@ int test_secio_handshake() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve the response
|
// retrieve the response
|
||||||
unsigned char* results;
|
struct StreamMessage* results;
|
||||||
size_t results_size;
|
if (libp2p_net_multistream_read(secure_session, &results, 30) == 0) {
|
||||||
if (libp2p_net_multistream_read(secure_session, &results, &results_size, 30) == 0) {
|
|
||||||
fprintf(stdout, "Unable to read ls results from multistream\n");
|
fprintf(stdout, "Unable to read ls results from multistream\n");
|
||||||
free(results);
|
free(results);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Results of ls (%d bytes long):\n%s\n", (int)results_size, results);
|
fprintf(stdout, "Results of ls (%d bytes long):\n%s\n", (int)results->data_size, results->data);
|
||||||
|
|
||||||
free(results);
|
libp2p_stream_message_free(results);
|
||||||
results = NULL;
|
results = NULL;
|
||||||
// try to yamux
|
// try to yamux
|
||||||
char* yamux_string = "/yamux/1.0.0\n";
|
char* yamux_string = "/yamux/1.0.0\n";
|
||||||
|
@ -177,14 +176,14 @@ int test_secio_handshake() {
|
||||||
libp2p_logger_error("test_secio", "Unable to send yamux protocol request\n");
|
libp2p_logger_error("test_secio", "Unable to send yamux protocol request\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if (!libp2p_net_multistream_read(secure_session, &results, &results_size, 30)) {
|
if (!libp2p_net_multistream_read(secure_session, &results, 30)) {
|
||||||
libp2p_logger_error("test_secio", "Unable to read reply to yamux request.\n");
|
libp2p_logger_error("test_secio", "Unable to read reply to yamux request.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Results of yamux request: %s\n", results);
|
fprintf(stdout, "Results of yamux request: %s\n", results->data);
|
||||||
|
|
||||||
free(results);
|
libp2p_stream_message_free(results);
|
||||||
results = NULL;
|
results = NULL;
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
@ -496,17 +495,16 @@ int test_secio_handshake_go() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve the response
|
// retrieve the response
|
||||||
unsigned char* results;
|
struct StreamMessage* results;
|
||||||
size_t results_size;
|
if (libp2p_net_multistream_read(secure_session, &results, 30) == 0) {
|
||||||
if (libp2p_net_multistream_read(secure_session, &results, &results_size, 30) == 0) {
|
|
||||||
fprintf(stdout, "Unable to read ls results from multistream\n");
|
fprintf(stdout, "Unable to read ls results from multistream\n");
|
||||||
free(results);
|
free(results);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Results of ls: %.*s", (int)results_size, results);
|
fprintf(stdout, "Results of ls: %.*s", (int)results->data_size, results->data);
|
||||||
|
|
||||||
free(results);
|
libp2p_stream_message_free(results);
|
||||||
results = NULL;
|
results = NULL;
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
|
|
|
@ -71,18 +71,22 @@ int yamux_send_protocol(struct SessionContext* context) {
|
||||||
*/
|
*/
|
||||||
int yamux_receive_protocol(struct SessionContext* context) {
|
int yamux_receive_protocol(struct SessionContext* context) {
|
||||||
char* protocol = "/yamux/1.0.0\n";
|
char* protocol = "/yamux/1.0.0\n";
|
||||||
uint8_t* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
size_t results_size = 0;
|
int retVal = 0;
|
||||||
if (!context->default_stream->read(context, &results, &results_size, 30)) {
|
|
||||||
|
if (!context->default_stream->read(context, &results, 30)) {
|
||||||
libp2p_logger_error("yamux", "receive_protocol: Unable to read results.\n");
|
libp2p_logger_error("yamux", "receive_protocol: Unable to read results.\n");
|
||||||
return 0;
|
goto exit;
|
||||||
}
|
}
|
||||||
// the first byte is the size, so skip it
|
// the first byte is the size, so skip it
|
||||||
char* ptr = strstr((char*)&results[1], protocol);
|
char* ptr = strstr((char*)&results->data[1], protocol);
|
||||||
if (ptr == NULL || ptr - (char*)results > 1) {
|
if (ptr == NULL || ptr - (char*)results->data > 1) {
|
||||||
return 0;
|
goto exit;
|
||||||
}
|
}
|
||||||
return 1;
|
retVal = 1;
|
||||||
|
exit:
|
||||||
|
libp2p_stream_message_free(results);
|
||||||
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
|
Loading…
Reference in a new issue