Added ping functionality to multistream
This commit is contained in:
parent
e4a4226f5d
commit
8139dc9d48
11 changed files with 181 additions and 45 deletions
16
crypto/rsa.c
16
crypto/rsa.c
|
@ -1,6 +1,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libp2p/crypto/key.h"
|
||||||
#include "libp2p/crypto/rsa.h"
|
#include "libp2p/crypto/rsa.h"
|
||||||
#include "libp2p/crypto/sha256.h"
|
#include "libp2p/crypto/sha256.h"
|
||||||
|
|
||||||
|
@ -16,6 +17,21 @@
|
||||||
#include "mbedtls/oid.h"
|
#include "mbedtls/oid.h"
|
||||||
#include "mbedtls/pk.h"
|
#include "mbedtls/pk.h"
|
||||||
|
|
||||||
|
struct PrivateKey* libp2p_crypto_rsa_to_private_key(struct RsaPrivateKey* in) {
|
||||||
|
struct PrivateKey* out = libp2p_crypto_private_key_new();
|
||||||
|
if (out != NULL) {
|
||||||
|
out->data = (unsigned char*)malloc(in->der_length);
|
||||||
|
if (out->data == NULL) {
|
||||||
|
libp2p_crypto_private_key_free(out);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memcpy(out->data, in->der, in->der_length);
|
||||||
|
out->data_size = in->der_length;
|
||||||
|
out->type = KEYTYPE_RSA;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Take an rsa context and turn it into a der formatted byte stream.
|
* Take an rsa context and turn it into a der formatted byte stream.
|
||||||
* NOTE: the stream starts from the right. So there could be a lot of padding in front.
|
* NOTE: the stream starts from the right. So there could be a lot of padding in front.
|
||||||
|
|
|
@ -27,6 +27,13 @@ struct RsaPrivateKey {
|
||||||
size_t public_key_length;
|
size_t public_key_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a struct RsaPrivateKey to a struct PrivateKey
|
||||||
|
* @param in the RsaPrivateKey
|
||||||
|
* @returns a struct PrivateKey
|
||||||
|
*/
|
||||||
|
struct PrivateKey* libp2p_crypto_rsa_to_private_key(struct RsaPrivateKey* in);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* generate a new private key
|
* generate a new private key
|
||||||
* @param private_key the new private key
|
* @param private_key the new private key
|
||||||
|
|
|
@ -28,3 +28,27 @@ int libp2p_net_multistream_receive(int socket_fd, char** results, size_t* result
|
||||||
* @returns the socket file descriptor of the connection, or -1 on error
|
* @returns the socket file descriptor of the connection, or -1 on error
|
||||||
*/
|
*/
|
||||||
int libp2p_net_multistream_connect(const char* hostname, int port);
|
int libp2p_net_multistream_connect(const char* hostname, int port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Negotiate the multistream protocol by sending and receiving the protocol id. This is a server side function.
|
||||||
|
* Servers should send the protocol ID, and then expect it back.
|
||||||
|
* @param fd the socket file descriptor
|
||||||
|
* @returns true(1) if the negotiation was successful.
|
||||||
|
*/
|
||||||
|
int libp2p_net_multistream_negotiate(int fd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect to read a message, and follow its instructions
|
||||||
|
* @param fd the socket file descriptor
|
||||||
|
* @returns true(1) on success, false(0) if not
|
||||||
|
*/
|
||||||
|
int libp2p_net_multistream_handle_message(int fd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to a multistream host, and this includes the multistream handshaking.
|
||||||
|
* @param hostname the host
|
||||||
|
* @param port the port
|
||||||
|
* @returns the socket file descriptor of the connection, or -1 on error
|
||||||
|
*/
|
||||||
|
int libp2p_net_multistream_connect(const char* hostname, int port);
|
||||||
|
|
||||||
|
|
|
@ -64,3 +64,4 @@ int libp2p_message_protobuf_encode(struct Libp2pMessage* in, unsigned char* buff
|
||||||
* @returns true(1) on success, otherwise false(0)
|
* @returns true(1) on success, otherwise false(0)
|
||||||
*/
|
*/
|
||||||
int libp2p_message_protobuf_decode(unsigned char* buffer, size_t buffer_size, struct Libp2pMessage** out);
|
int libp2p_message_protobuf_decode(unsigned char* buffer, size_t buffer_size, struct Libp2pMessage** out);
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#include "libp2p/net/p2pnet.h"
|
#include "libp2p/net/p2pnet.h"
|
||||||
|
#include "libp2p/record/message.h"
|
||||||
#include "varint.h"
|
#include "varint.h"
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -135,3 +137,67 @@ int libp2p_net_multistream_connect(const char* hostname, int port) {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int libp2p_net_multistream_negotiate(int fd) {
|
||||||
|
const char* protocolID = "/multistream/1.0.0\n";
|
||||||
|
char* results;
|
||||||
|
size_t results_length = 0;
|
||||||
|
// send the protocol id
|
||||||
|
if (!libp2p_net_multistream_send(fd, (unsigned char*)protocolID, strlen(protocolID)))
|
||||||
|
return 0;
|
||||||
|
// expect the same back
|
||||||
|
libp2p_net_multistream_receive(fd, &results, &results_length);
|
||||||
|
if (results_length == 0)
|
||||||
|
return 0;
|
||||||
|
if (strncmp(results, protocolID, strlen(protocolID)) != 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The remote client requested a ping
|
||||||
|
* @param fd the socket file descriptor
|
||||||
|
* @param msg the incoming ping message
|
||||||
|
* @returns true(1) on success, otherwise false(0)
|
||||||
|
*/
|
||||||
|
int libp2p_net_multistream_handle_ping(int fd, struct Libp2pMessage* msg) {
|
||||||
|
// protobuf the message
|
||||||
|
size_t protobuf_size = libp2p_message_protobuf_encode_size(msg);
|
||||||
|
unsigned char protobuf[protobuf_size];
|
||||||
|
libp2p_message_protobuf_encode(msg, &protobuf[0], protobuf_size, &protobuf_size);
|
||||||
|
libp2p_net_multistream_send(fd, protobuf, protobuf_size);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expect to read a message, and follow its instructions
|
||||||
|
* @param fd the socket file descriptor
|
||||||
|
* @returns true(1) on success, false(0) if not
|
||||||
|
*/
|
||||||
|
int libp2p_net_multistream_handle_message(int fd) {
|
||||||
|
int retVal = 0;
|
||||||
|
unsigned char* results = NULL;
|
||||||
|
size_t results_size = 0;
|
||||||
|
struct Libp2pMessage* msg = NULL;
|
||||||
|
// read what they sent
|
||||||
|
libp2p_net_multistream_receive(fd, (char**)&results, &results_size);
|
||||||
|
// unprotobuf it
|
||||||
|
if (!libp2p_message_protobuf_decode(results, results_size, &msg))
|
||||||
|
goto exit;
|
||||||
|
// do what they ask
|
||||||
|
switch (msg->message_type) {
|
||||||
|
case (MESSAGE_TYPE_PING):
|
||||||
|
libp2p_net_multistream_handle_ping(fd, msg);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// clean up
|
||||||
|
retVal = 1;
|
||||||
|
exit:
|
||||||
|
if (results != NULL)
|
||||||
|
free(results);
|
||||||
|
if (msg != NULL)
|
||||||
|
libp2p_message_free(msg);
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
|
@ -71,8 +71,10 @@ struct Libp2pPeer* libp2p_peer_copy(struct Libp2pPeer* in) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in) {
|
size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in) {
|
||||||
|
int sz = 0;
|
||||||
|
if (in != NULL) {
|
||||||
// id + connection_type
|
// id + connection_type
|
||||||
int sz = 11 + in->id_size + 11;
|
sz = 11 + in->id_size + 11;
|
||||||
// loop through the multiaddresses
|
// loop through the multiaddresses
|
||||||
struct Libp2pLinkedList* current = in->addr_head;
|
struct Libp2pLinkedList* current = in->addr_head;
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
|
@ -81,6 +83,7 @@ size_t libp2p_peer_protobuf_encode_size(struct Libp2pPeer* in) {
|
||||||
sz += 11 + data->bsize;
|
sz += 11 + data->bsize;
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,25 +82,34 @@ int libp2p_message_protobuf_encode(struct Libp2pMessage* in, unsigned char* buff
|
||||||
size_t bytes_used = 0;
|
size_t bytes_used = 0;
|
||||||
*bytes_written = 0;
|
*bytes_written = 0;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
|
size_t protobuf_size = 0;
|
||||||
|
unsigned char* protobuf = NULL;
|
||||||
// field 1
|
// field 1
|
||||||
retVal = protobuf_encode_varint(1, WIRETYPE_VARINT, in->message_type, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
retVal = protobuf_encode_varint(1, WIRETYPE_VARINT, in->message_type, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
||||||
if (retVal == 0)
|
if (retVal == 0)
|
||||||
return 0;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
// field 2
|
// field 2
|
||||||
|
if (in->key != NULL) {
|
||||||
retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, in->key, in->key_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
retVal = protobuf_encode_length_delimited(2, WIRETYPE_LENGTH_DELIMITED, in->key, in->key_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
||||||
if (retVal == 0)
|
if (retVal == 0)
|
||||||
return 0;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
|
}
|
||||||
// field 3
|
// field 3
|
||||||
size_t protobuf_size = libp2p_record_protobuf_encode_size(in->record);
|
if (in->record != NULL) {
|
||||||
unsigned char protobuf[protobuf_size];
|
protobuf_size = libp2p_record_protobuf_encode_size(in->record);
|
||||||
if (!libp2p_record_protobuf_encode(in->record, protobuf, protobuf_size, &protobuf_size))
|
protobuf = (unsigned char*) malloc(protobuf_size);
|
||||||
|
if (!libp2p_record_protobuf_encode(in->record, protobuf, protobuf_size, &protobuf_size)) {
|
||||||
|
free(protobuf);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
retVal = protobuf_encode_length_delimited(3, WIRETYPE_LENGTH_DELIMITED, protobuf, protobuf_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
retVal = protobuf_encode_length_delimited(3, WIRETYPE_LENGTH_DELIMITED, protobuf, protobuf_size, &buffer[*bytes_written], max_buffer_size - *bytes_written, &bytes_used);
|
||||||
|
free(protobuf);
|
||||||
if (retVal == 0)
|
if (retVal == 0)
|
||||||
return 0;
|
return 0;
|
||||||
*bytes_written += bytes_used;
|
*bytes_written += bytes_used;
|
||||||
|
}
|
||||||
// field 8 (repeated)
|
// field 8 (repeated)
|
||||||
struct Libp2pLinkedList* current = in->closer_peer_head;
|
struct Libp2pLinkedList* current = in->closer_peer_head;
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
|
|
|
@ -97,11 +97,14 @@ int libp2p_record_protobuf_encode(const struct Libp2pRecord* in, unsigned char*
|
||||||
* @returns the approximate number of bytes required
|
* @returns the approximate number of bytes required
|
||||||
*/
|
*/
|
||||||
size_t libp2p_record_protobuf_encode_size(const struct Libp2pRecord* in) {
|
size_t libp2p_record_protobuf_encode_size(const struct Libp2pRecord* in) {
|
||||||
size_t retVal = 11 + in->key_size;
|
size_t retVal = 0;
|
||||||
|
if (in != NULL) {
|
||||||
|
retVal = 11 + in->key_size;
|
||||||
retVal += 11 + in->value_size;
|
retVal += 11 + in->value_size;
|
||||||
retVal += 11 + in->author_size;
|
retVal += 11 + in->author_size;
|
||||||
retVal += 11 + in->signature_size;
|
retVal += 11 + in->signature_size;
|
||||||
retVal += 11 + in->time_received_size;
|
retVal += 11 + in->time_received_size;
|
||||||
|
}
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -499,21 +499,6 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
char* remote_peer_id = NULL;
|
char* remote_peer_id = NULL;
|
||||||
struct EphemeralPrivateKey* e_private_key = NULL;
|
struct EphemeralPrivateKey* e_private_key = NULL;
|
||||||
|
|
||||||
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
|
|
||||||
|
|
||||||
bytes_written = libp2p_net_multistream_send(local_session->socket_descriptor, protocol, strlen((char*)protocol));
|
|
||||||
if (bytes_written <= 0)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
// we should get back the secio confirmation
|
|
||||||
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
|
||||||
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
free(results);
|
|
||||||
results = NULL;
|
|
||||||
results_size = 0;
|
|
||||||
|
|
||||||
//TODO: make sure we're not talking to ourself
|
//TODO: make sure we're not talking to ourself
|
||||||
|
|
||||||
// generate 16 byte nonce
|
// generate 16 byte nonce
|
||||||
|
@ -561,9 +546,31 @@ int libp2p_secio_handshake(struct SecureSession* local_session, struct RsaPrivat
|
||||||
if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0)
|
if (libp2p_secio_propose_protobuf_encode(propose_out, propose_out_bytes, propose_out_size, &propose_out_size) == 0)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
// prepare the multistream send
|
||||||
|
const unsigned char* protocol = (unsigned char*)"/secio/1.0.0\n";
|
||||||
|
int protocol_len = strlen((char*)protocol);
|
||||||
|
unsigned char* total = malloc(protocol_len + propose_out_size);
|
||||||
|
memcpy(total, protocol, protocol_len);
|
||||||
|
memcpy(&total[protocol_len], propose_out_bytes, propose_out_size);
|
||||||
|
|
||||||
|
bytes_written = libp2p_net_multistream_send(local_session->socket_descriptor, total, protocol_len + propose_out_size);
|
||||||
|
free(total);
|
||||||
|
if (bytes_written <= 0)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/*
|
||||||
bytes_written = libp2p_secio_write(local_session, propose_out_bytes, propose_out_size);
|
bytes_written = libp2p_secio_write(local_session, propose_out_bytes, propose_out_size);
|
||||||
if (bytes_written < propose_out_size)
|
if (bytes_written < propose_out_size)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
*/
|
||||||
|
// we should get back the secio confirmation
|
||||||
|
bytes_written = libp2p_net_multistream_receive(local_session->socket_descriptor, (char**)&results, &results_size);
|
||||||
|
if (bytes_written < 5 || strstr((char*)results, "secio") == NULL)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
free(results);
|
||||||
|
results = NULL;
|
||||||
|
results_size = 0;
|
||||||
|
|
||||||
// now receive the proposal from the new connection
|
// now receive the proposal from the new connection
|
||||||
bytes_written = libp2p_secio_read(local_session, &propose_in_bytes, &propose_in_size);
|
bytes_written = libp2p_secio_read(local_session, &propose_in_bytes, &propose_in_size);
|
||||||
|
|
|
@ -42,7 +42,7 @@ int test_secio_handshake() {
|
||||||
if (!libp2p_crypto_rsa_private_key_fill_public_key(rsa_private_key))
|
if (!libp2p_crypto_rsa_private_key_fill_public_key(rsa_private_key))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
secure_session.host = "10.0.1.9";
|
secure_session.host = "192.210.179.217";
|
||||||
secure_session.port = 4001;
|
secure_session.port = 4001;
|
||||||
secure_session.traffic_type = TCP;
|
secure_session.traffic_type = TCP;
|
||||||
// connect to host
|
// connect to host
|
||||||
|
|
|
@ -34,7 +34,7 @@ const char* names[] = {
|
||||||
//"test_crypto_rsa_sign",
|
//"test_crypto_rsa_sign",
|
||||||
"test_crypto_encoding_base32_encode",
|
"test_crypto_encoding_base32_encode",
|
||||||
"test_protobuf_private_key",
|
"test_protobuf_private_key",
|
||||||
//"test_secio_handshake",
|
"test_secio_handshake",
|
||||||
"test_multistream_connect",
|
"test_multistream_connect",
|
||||||
"test_multistream_get_list",
|
"test_multistream_get_list",
|
||||||
"test_ephemeral_key_generate",
|
"test_ephemeral_key_generate",
|
||||||
|
@ -70,7 +70,7 @@ int (*funcs[])(void) = {
|
||||||
//test_crypto_rsa_sign,
|
//test_crypto_rsa_sign,
|
||||||
test_crypto_encoding_base32_encode,
|
test_crypto_encoding_base32_encode,
|
||||||
test_protobuf_private_key,
|
test_protobuf_private_key,
|
||||||
//test_secio_handshake,
|
test_secio_handshake,
|
||||||
test_multistream_connect,
|
test_multistream_connect,
|
||||||
test_multistream_get_list,
|
test_multistream_get_list,
|
||||||
test_ephemeral_key_generate,
|
test_ephemeral_key_generate,
|
||||||
|
|
Loading…
Reference in a new issue