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/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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
// 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));
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue