IPFS protocols now implement an interface to make marshalling easier

This commit is contained in:
John Jones 2017-08-09 08:03:40 -05:00
parent 1a45924151
commit 6f77a64adb
7 changed files with 147 additions and 19 deletions

View file

@ -0,0 +1,38 @@
#pragma once
#include "libp2p/conn/session.h"
#include "libp2p/utils/vector.h"
/***
* An "interface" for different IPFS protocols
*/
struct Libp2pProtocolHandler {
/**
* A protocol dependent context (often an IpfsNode pointer, but libp2p doesn't know about that)
*/
void* context;
/**
* Determines if this protocol can handle the incoming message
* @param incoming the incoming data
* @param incoming_size the size of the incoming data buffer
* @returns true(1) if it can handle this message, false(0) if not
*/
int (*CanHandle)(const uint8_t* incoming, size_t incoming_size);
/***
* Handles the message
* @param incoming the incoming data buffer
* @param incoming_size the size of the incoming data buffer
* @param session_context the information about the incoming connection
* @param protocol_context the protocol-dependent context
* @returns 0 if the caller should not continue looping, <0 on error, >0 on success
*/
int (*HandleMessage)(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* protocol_context);
/**
* Shutting down. Clean up any memory allocations
* @param protocol_context the context
* @returns true(1)
*/
int (*Shutdown)(void* protocol_context);
};
int libp2p_protocol_marshal(const uint8_t* incoming, size_t incoming_size, struct SessionContext* context, struct Libp2pVector* protocol_handlers);

View file

@ -3,12 +3,15 @@
#include "libp2p/conn/session.h"
#include "libp2p/peer/peerstore.h"
#include "libp2p/peer/providerstore.h"
#include "libp2p/net/protocol.h"
/***
* This is where kademlia and dht talk to the outside world
*/
struct Libp2pProtocolHandler* libp2p_routing_dht_build_protocol_handler(struct Peerstore* peer_store, struct ProviderStore* provider_store);
/**
* Take existing stream and upgrade to the Kademlia / DHT protocol/codec
* @param context the context

View file

@ -4,12 +4,15 @@
#include "libp2p/crypto/rsa.h"
#include "libp2p/conn/session.h"
#include "libp2p/peer/peerstore.h"
#include "libp2p/net/protocol.h"
/**
* Handling of a secure connection
*/
struct Libp2pProtocolHandler* libp2p_secio_build_protocol_handler(struct RsaPrivateKey* private_key, struct Peerstore* peer_store);
/***
* performs initial communication over an insecure channel to share
* keys, IDs, and initiate connection. This is a framed messaging system

View file

@ -7,7 +7,7 @@ endif
LFLAGS =
DEPS =
OBJS = sctp.o socket.o tcp.o udp.o multistream.o
OBJS = sctp.o socket.o tcp.o udp.o multistream.o protocol.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

27
net/protocol.c Normal file
View file

@ -0,0 +1,27 @@
#include <stdlib.h>
#include "libp2p/net/protocol.h"
/***
* Compare incoming to see if they are requesting a protocol upgrade
* @param incoming the incoming string
* @param incoming_size the size of the incoming string
* @param test the protocol string to compare it with (i.e. "/secio" or "/nodeio"
* @returns true(1) if there was a match, false(0) otherwise
*/
const struct Libp2pProtocolHandler* protocol_compare(const unsigned char* incoming, size_t incoming_size, struct Libp2pVector* protocol_handlers) {
for(int i = 0; i < protocol_handlers->total; i++) {
const struct Libp2pProtocolHandler* handler = (const struct Libp2pProtocolHandler*) libp2p_utils_vector_get(protocol_handlers, i);
if (handler->CanHandle(incoming, incoming_size)) {
return handler;
}
}
return NULL;
}
int libp2p_protocol_marshal(const unsigned char* incoming, size_t incoming_size, struct SessionContext* session, struct Libp2pVector* handlers) {
const struct Libp2pProtocolHandler* handler = protocol_compare(incoming, incoming_size, handlers);
if (handler != NULL) {
return handler->HandleMessage(incoming, incoming_size, session, handler->context);
}
return 0;
}

View file

@ -13,6 +13,45 @@
* This is where kademlia and dht talk to the outside world
*/
struct DhtContext {
struct Peerstore* peer_store;
struct ProviderStore* provider_store;
};
int libp2p_routing_dht_can_handle(const uint8_t* incoming, size_t incoming_size) {
if (incoming_size < 8)
return 0;
char* result = strstr((char*)incoming, "/ipfs/kad");
if (result == NULL || result != (char*)incoming)
return 0;
return 1;
}
int libp2p_routing_dht_shutdown(void* context) {
free(context);
return 1;
}
int libp2p_routing_dht_handle_msg(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* context) {
struct DhtContext* ctx = (struct DhtContext*)context;
if (!libp2p_routing_dht_handshake(session_context))
return 0;
return libp2p_routing_dht_handle_message(session_context, ctx->peer_store, ctx->provider_store);
}
struct Libp2pProtocolHandler* libp2p_routing_dht_build_protocol_handler(struct Peerstore* peer_store, struct ProviderStore* provider_store) {
struct Libp2pProtocolHandler* handler = (struct Libp2pProtocolHandler*) malloc(sizeof(struct Libp2pProtocolHandler));
if (handler != NULL) {
struct DhtContext* ctx = (struct DhtContext*) malloc(sizeof(struct DhtContext));
ctx->peer_store = peer_store;
ctx->provider_store = provider_store;
handler->context = ctx;
handler->CanHandle = libp2p_routing_dht_can_handle;
handler->HandleMessage = libp2p_routing_dht_handle_msg;
handler->Shutdown = libp2p_routing_dht_shutdown;
}
return handler;
}
/***
* Helper method to protobuf a message

View file

@ -23,6 +23,7 @@
#include "libp2p/utils/string_list.h"
#include "libp2p/utils/vector.h"
#include "libp2p/utils/logger.h"
#include "libp2p/net/protocol.h"
#include "mbedtls/md.h"
#include "mbedtls/cipher.h"
#include "mbedtls/md_internal.h"
@ -32,26 +33,43 @@ const char* SupportedExchanges = "P-256,P-384,P-521";
const char* SupportedCiphers = "AES-256,AES-128,Blowfish";
const char* SupportedHashes = "SHA256,SHA512";
/***
* Create a new SecureSession struct
* @returns a pointer to a new SecureSession object
*/
struct SessionContext* libp2p_secio_secure_session_new() {
struct SessionContext* ss = (struct SessionContext*) malloc(sizeof(struct SessionContext));
if (ss == NULL)
return NULL;
ss->insecure_stream = NULL;
ss->secure_stream = NULL;
return ss;
struct SecioContext {
struct RsaPrivateKey* private_key;
struct Peerstore* peer_store;
};
int libp2p_secio_can_handle(const uint8_t* incoming, size_t incoming_size) {
// sanity checks
if (incoming_size < 11)
return 0;
char* result = strstr((char*)incoming, "/ipfs/secio");
if (result != NULL && result == (char*)incoming)
return 0;
return 1;
}
/***
* Clean up resources from a SecureSession struct
* @param in the SecureSession to be deallocated
*/
void libp2p_secio_secure_session_free(struct SessionContext* in) {
//TODO: should we close the socket?
free(in);
int libp2p_secio_handle_message(const uint8_t* incoming, size_t incoming_size, struct SessionContext* session_context, void* protocol_context) {
struct SecioContext* ctx = (struct SecioContext*)protocol_context;
return libp2p_secio_handshake(session_context, ctx->private_key, ctx->peer_store, 1);
}
int libp2p_secio_shutdown(void* context) {
free(context);
return 1;
}
struct Libp2pProtocolHandler* libp2p_secio_build_protocol_handler(struct RsaPrivateKey* private_key, struct Peerstore* peer_store) {
struct Libp2pProtocolHandler* handler = (struct Libp2pProtocolHandler*) malloc(sizeof(struct Libp2pProtocolHandler));
if (handler != NULL) {
struct SecioContext* context = (struct SecioContext*) malloc(sizeof(struct SecioContext));
context->private_key = private_key;
context->peer_store = peer_store;
handler->context = context;
handler->CanHandle = libp2p_secio_can_handle;
handler->HandleMessage = libp2p_secio_handle_message;
handler->Shutdown = libp2p_secio_shutdown;
}
return handler;
}
/**