secio and multistream now working. Need to negotiate yamux

yamux
John Jones 2017-11-02 13:20:40 -05:00
parent 746682ebef
commit 65194c06ee
5 changed files with 98 additions and 11 deletions

View File

@ -9,6 +9,7 @@
#include "libp2p/conn/transport_dialer.h"
#include "libp2p/crypto/key.h"
#include "libp2p/utils/linked_list.h"
#include "libp2p/utils/logger.h"
#include "multiaddr/multiaddr.h"
#include "libp2p/net/multistream.h"
#include "libp2p/secio/secio.h"
@ -144,9 +145,17 @@ int libp2p_conn_dialer_join_swarm(const struct Dialer* dialer, struct Libp2pPeer
// kademlia over yamux
// circuit relay over yamux
return 1;
} else {
libp2p_logger_error("dialer", "Unable to do yamux negotiation.\n");
}
} else {
libp2p_logger_error("dialer", "Unable to do secio/multistream negotiation.\n");
}
} else {
libp2p_logger_error("dialer", "Unable to do secio negotiation.\n");
}
} else {
libp2p_logger_error("dialer", "Unable to do initial multistream negotiation.\n");
}
return 0;

View File

@ -91,7 +91,7 @@ struct Stream {
* Checks to see if something is waiting on the stream
*
* @param stream the stream context
* @returns true(1) if something is waiting, false(0) otherwise
* @returns true(1) if something is waiting, false(0) if not, -1 on error
*/
int (*peek)(void* stream_context);
};

View File

@ -8,8 +8,10 @@
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <errno.h>
#include "libp2p/net/stream.h"
#include "libp2p/net/p2pnet.h"
#include "libp2p/utils/logger.h"
#include "multiaddr/multiaddr.h"
/**
@ -47,8 +49,10 @@ int libp2p_net_connection_peek(void* stream_context) {
return -1;
int bytes = 0;
if (ioctl(socket_fd, FIONREAD, &bytes) < 0) {
int retVal = ioctl(socket_fd, FIONREAD, &bytes);
if (retVal < 0) {
// Ooff, we're having problems. Don't use this socket again.
libp2p_logger_error("connectionstream", "Attempted a peek, but ioctl reported %s.\n", strerror(errno));
return -1;
}
return bytes;

View File

@ -249,7 +249,7 @@ int libp2p_net_multistream_read(void* stream_context, struct StreamMessage** res
size_t num_bytes_requested = 0;
size_t varint_length = 0;
for(int i = 0; i < 12; i++) {
if (!parent_stream->read_raw(parent_stream->stream_context, &varint[i], 1, timeout_secs)) {
if (parent_stream->read_raw(parent_stream->stream_context, &varint[i], 1, timeout_secs) == -1) {
return 0;
}
if (varint[i] >> 7 == 0) {
@ -363,17 +363,45 @@ int libp2p_net_multistream_negotiate(struct MultistreamContext* ctx) {
struct StreamMessage outgoing;
struct StreamMessage* results = NULL;
int retVal = 0;
int haveTheirs = 0;
int peek_result = 0;
// see if they're trying to send something first
peek_result = libp2p_net_multistream_peek(ctx);
/*
if (peek_result < 0) {
libp2p_logger_error("multistream", "Attempted a peek, but received an error.\n");
return 0;
}
*/
if (peek_result > 0) {
libp2p_logger_debug("multistream", "There is %d bytes waiting for us. Perhaps it is the multistream header we're expecting.\n", peek_result);
// get the protocol
//ctx->stream->parent_stream->read(ctx->stream->parent_stream->stream_context, &results, multistream_default_timeout);
libp2p_net_multistream_read(ctx, &results, multistream_default_timeout);
if (results == NULL || results->data_size == 0)
goto exit;
if (strncmp((char*)results->data, protocolID, strlen(protocolID)) != 0)
goto exit;
haveTheirs = 1;
}
// send the protocol id
outgoing.data = (uint8_t*)protocolID;
outgoing.data_size = strlen(protocolID);
if (!libp2p_net_multistream_write(ctx, &outgoing))
goto exit;
// expect the same back
libp2p_net_multistream_read(ctx, &results, multistream_default_timeout);
if (results == NULL || results->data_size == 0)
goto exit;
if (strncmp((char*)results->data, protocolID, strlen(protocolID)) != 0)
goto exit;
// wait for them to send the protocol id back
if (!haveTheirs) {
// expect the same back
libp2p_net_multistream_read(ctx, &results, multistream_default_timeout);
if (results == NULL || results->data_size == 0)
goto exit;
if (strncmp((char*)results->data, protocolID, strlen(protocolID)) != 0)
goto exit;
}
retVal = 1;
exit:
if (results != NULL)
@ -388,6 +416,13 @@ void libp2p_net_multistream_stream_free(struct Stream* stream) {
}
}
int libp2p_net_multistream_read_raw(void* stream_context, uint8_t* buffer, int buffer_len, int timeout_secs) {
if (stream_context == NULL)
return 0;
struct MultistreamContext* ctx = (struct MultistreamContext*) stream_context;
return ctx->stream->parent_stream->read_raw(ctx->stream->parent_stream->stream_context, buffer, buffer_len, timeout_secs);
}
/**
* Create a new MultiStream structure
* @param socket_fd the file descriptor
@ -402,6 +437,7 @@ struct Stream* libp2p_net_multistream_stream_new(struct Stream* parent_stream) {
out->read = libp2p_net_multistream_read;
out->write = libp2p_net_multistream_write;
out->peek = libp2p_net_multistream_peek;
out->read_raw = libp2p_net_multistream_read_raw;
out->address = parent_stream->address;
// build MultistreamContext
struct MultistreamContext* ctx = (struct MultistreamContext*) malloc(sizeof(struct MultistreamContext));

View File

@ -35,6 +35,9 @@ const char* SupportedExchanges = "P-256,P-384,P-521";
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
const char* SupportedHashes = "SHA256,SHA512";
static struct StreamMessage* secio_buffered_message;
static size_t secio_buffered_message_pos = -1;
int libp2p_secio_can_handle(const struct StreamMessage* msg) {
const char* protocol = "/secio/1.0.0";
// sanity checks
@ -1298,6 +1301,41 @@ int libp2p_secio_handshake(struct SecioContext* secio_context) {
return retVal;
}
int libp2p_secio_peek(void* stream_context) {
if (stream_context == NULL) {
return -1;
}
struct SecioContext* ctx = (struct SecioContext*)stream_context;
return ctx->stream->parent_stream->peek(ctx->stream->parent_stream->stream_context);
}
int libp2p_secio_read_raw(void* stream_context, uint8_t* buffer, int buffer_size, int timeout_secs) {
if (stream_context == NULL) {
return -1;
}
struct SecioContext* ctx = (struct SecioContext*)stream_context;
if (secio_buffered_message_pos == -1) {
// we need to get info from the network
if (!ctx->stream->read(ctx->stream->stream_context, &secio_buffered_message, timeout_secs)) {
return -1;
}
secio_buffered_message_pos = 0;
}
int max_to_read = (buffer_size > secio_buffered_message->data_size ? secio_buffered_message->data_size : buffer_size);
memcpy(buffer, &secio_buffered_message->data[secio_buffered_message_pos], max_to_read);
secio_buffered_message_pos += max_to_read;
if (secio_buffered_message_pos == secio_buffered_message->data_size) {
// we read everything
libp2p_stream_message_free(secio_buffered_message);
secio_buffered_message = NULL;
secio_buffered_message_pos = -1;
} else {
// we didn't read everything.
secio_buffered_message_pos = max_to_read;
}
return max_to_read;
}
/***
* Initiates a secio handshake. Use this method when you want to initiate a secio
* session. This should not be used to respond to incoming secio requests
@ -1323,9 +1361,9 @@ struct Stream* libp2p_secio_stream_new(struct Stream* parent_stream, struct Libp
ctx->private_key = rsa_private_key;
new_stream->parent_stream = parent_stream;
new_stream->close = libp2p_secio_shutdown;
new_stream->peek = libp2p_net_connection_peek;
new_stream->peek = libp2p_secio_peek;
new_stream->read = libp2p_secio_encrypted_read;
new_stream->read_raw = libp2p_net_connection_read_raw;
new_stream->read_raw = libp2p_secio_read_raw;
new_stream->write = libp2p_secio_encrypted_write;
if (!libp2p_secio_send_protocol(ctx)
|| !libp2p_secio_receive_protocol(ctx)