IPFS protocols now implement an interface to make marshalling easier
This commit is contained in:
parent
1a45924151
commit
6f77a64adb
7 changed files with 147 additions and 19 deletions
38
include/libp2p/net/protocol.h
Normal file
38
include/libp2p/net/protocol.h
Normal 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);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
27
net/protocol.c
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue