secio and multistream now working. Need to negotiate yamux
This commit is contained in:
parent
746682ebef
commit
65194c06ee
5 changed files with 98 additions and 11 deletions
|
@ -9,6 +9,7 @@
|
||||||
#include "libp2p/conn/transport_dialer.h"
|
#include "libp2p/conn/transport_dialer.h"
|
||||||
#include "libp2p/crypto/key.h"
|
#include "libp2p/crypto/key.h"
|
||||||
#include "libp2p/utils/linked_list.h"
|
#include "libp2p/utils/linked_list.h"
|
||||||
|
#include "libp2p/utils/logger.h"
|
||||||
#include "multiaddr/multiaddr.h"
|
#include "multiaddr/multiaddr.h"
|
||||||
#include "libp2p/net/multistream.h"
|
#include "libp2p/net/multistream.h"
|
||||||
#include "libp2p/secio/secio.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
|
// kademlia over yamux
|
||||||
// circuit relay over yamux
|
// circuit relay over yamux
|
||||||
return 1;
|
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;
|
return 0;
|
||||||
|
|
|
@ -91,7 +91,7 @@ struct Stream {
|
||||||
* Checks to see if something is waiting on the stream
|
* Checks to see if something is waiting on the stream
|
||||||
*
|
*
|
||||||
* @param stream the stream context
|
* @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);
|
int (*peek)(void* stream_context);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,8 +8,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "libp2p/net/stream.h"
|
#include "libp2p/net/stream.h"
|
||||||
#include "libp2p/net/p2pnet.h"
|
#include "libp2p/net/p2pnet.h"
|
||||||
|
#include "libp2p/utils/logger.h"
|
||||||
#include "multiaddr/multiaddr.h"
|
#include "multiaddr/multiaddr.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,8 +49,10 @@ int libp2p_net_connection_peek(void* stream_context) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int bytes = 0;
|
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.
|
// 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 -1;
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
|
|
|
@ -249,7 +249,7 @@ int libp2p_net_multistream_read(void* stream_context, struct StreamMessage** res
|
||||||
size_t num_bytes_requested = 0;
|
size_t num_bytes_requested = 0;
|
||||||
size_t varint_length = 0;
|
size_t varint_length = 0;
|
||||||
for(int i = 0; i < 12; i++) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (varint[i] >> 7 == 0) {
|
if (varint[i] >> 7 == 0) {
|
||||||
|
@ -363,17 +363,45 @@ int libp2p_net_multistream_negotiate(struct MultistreamContext* ctx) {
|
||||||
struct StreamMessage outgoing;
|
struct StreamMessage outgoing;
|
||||||
struct StreamMessage* results = NULL;
|
struct StreamMessage* results = NULL;
|
||||||
int retVal = 0;
|
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
|
// send the protocol id
|
||||||
outgoing.data = (uint8_t*)protocolID;
|
outgoing.data = (uint8_t*)protocolID;
|
||||||
outgoing.data_size = strlen(protocolID);
|
outgoing.data_size = strlen(protocolID);
|
||||||
if (!libp2p_net_multistream_write(ctx, &outgoing))
|
if (!libp2p_net_multistream_write(ctx, &outgoing))
|
||||||
goto exit;
|
goto exit;
|
||||||
// expect the same back
|
|
||||||
libp2p_net_multistream_read(ctx, &results, multistream_default_timeout);
|
// wait for them to send the protocol id back
|
||||||
if (results == NULL || results->data_size == 0)
|
if (!haveTheirs) {
|
||||||
goto exit;
|
// expect the same back
|
||||||
if (strncmp((char*)results->data, protocolID, strlen(protocolID)) != 0)
|
libp2p_net_multistream_read(ctx, &results, multistream_default_timeout);
|
||||||
goto exit;
|
if (results == NULL || results->data_size == 0)
|
||||||
|
goto exit;
|
||||||
|
if (strncmp((char*)results->data, protocolID, strlen(protocolID)) != 0)
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
retVal = 1;
|
retVal = 1;
|
||||||
exit:
|
exit:
|
||||||
if (results != NULL)
|
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
|
* Create a new MultiStream structure
|
||||||
* @param socket_fd the file descriptor
|
* @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->read = libp2p_net_multistream_read;
|
||||||
out->write = libp2p_net_multistream_write;
|
out->write = libp2p_net_multistream_write;
|
||||||
out->peek = libp2p_net_multistream_peek;
|
out->peek = libp2p_net_multistream_peek;
|
||||||
|
out->read_raw = libp2p_net_multistream_read_raw;
|
||||||
out->address = parent_stream->address;
|
out->address = parent_stream->address;
|
||||||
// build MultistreamContext
|
// build MultistreamContext
|
||||||
struct MultistreamContext* ctx = (struct MultistreamContext*) malloc(sizeof(struct MultistreamContext));
|
struct MultistreamContext* ctx = (struct MultistreamContext*) malloc(sizeof(struct MultistreamContext));
|
||||||
|
|
|
@ -35,6 +35,9 @@ const char* SupportedExchanges = "P-256,P-384,P-521";
|
||||||
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
|
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
|
||||||
const char* SupportedHashes = "SHA256,SHA512";
|
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) {
|
int libp2p_secio_can_handle(const struct StreamMessage* msg) {
|
||||||
const char* protocol = "/secio/1.0.0";
|
const char* protocol = "/secio/1.0.0";
|
||||||
// sanity checks
|
// sanity checks
|
||||||
|
@ -1298,6 +1301,41 @@ int libp2p_secio_handshake(struct SecioContext* secio_context) {
|
||||||
return retVal;
|
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
|
* 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
|
* 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;
|
ctx->private_key = rsa_private_key;
|
||||||
new_stream->parent_stream = parent_stream;
|
new_stream->parent_stream = parent_stream;
|
||||||
new_stream->close = libp2p_secio_shutdown;
|
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 = 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;
|
new_stream->write = libp2p_secio_encrypted_write;
|
||||||
if (!libp2p_secio_send_protocol(ctx)
|
if (!libp2p_secio_send_protocol(ctx)
|
||||||
|| !libp2p_secio_receive_protocol(ctx)
|
|| !libp2p_secio_receive_protocol(ctx)
|
||||||
|
|
Loading…
Reference in a new issue