247 lines
7.2 KiB
C
247 lines
7.2 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "multiaddr/multiaddr.h"
|
|
#include "libp2p/crypto/ephemeral.h"
|
|
#include "libp2p/conn/session.h"
|
|
#include "libp2p/net/stream.h"
|
|
|
|
struct SessionContext* libp2p_session_context_new() {
|
|
struct SessionContext* context = (struct SessionContext*) malloc(sizeof(struct SessionContext));
|
|
if (context != NULL) {
|
|
context->aes_decode_nonce_offset = 0;
|
|
memset(&context->aes_decode_stream_block[0], 0, 16);
|
|
context->aes_encode_nonce_offset = 0;
|
|
memset(&context->aes_encode_stream_block[0], 0, 16);
|
|
context->chosen_cipher = NULL;
|
|
context->chosen_curve = NULL;
|
|
context->chosen_hash = NULL;
|
|
context->datastore = NULL;
|
|
context->default_stream = NULL;
|
|
context->ephemeral_private_key = NULL;
|
|
context->filestore = NULL;
|
|
context->host = NULL;
|
|
context->insecure_stream = NULL;
|
|
memset(&context->local_nonce[0], 0, 16);
|
|
context->local_stretched_key = NULL;
|
|
context->mac_function = NULL;
|
|
context->port = 0;
|
|
context->remote_ephemeral_public_key = NULL;
|
|
context->remote_ephemeral_public_key_size = 0;
|
|
context->remote_key.data_size = 0;
|
|
context->remote_key.data = NULL;
|
|
context->remote_key.type = KEYTYPE_INVALID;
|
|
memset(&context->remote_nonce[0], 0, 16);
|
|
context->remote_peer_id = NULL;
|
|
context->remote_stretched_key = NULL;
|
|
context->secure_stream = NULL;
|
|
context->shared_key = NULL;
|
|
context->shared_key_size = 0;
|
|
context->traffic_type = TCP;
|
|
}
|
|
return context;
|
|
}
|
|
|
|
int libp2p_session_context_free(struct SessionContext* context) {
|
|
if (context != NULL) {
|
|
if (context->default_stream != NULL)
|
|
context->default_stream->close(context->default_stream);
|
|
context->default_stream = NULL;
|
|
context->insecure_stream = NULL;
|
|
context->secure_stream = NULL;
|
|
if (context->chosen_cipher != NULL) {
|
|
free(context->chosen_cipher);
|
|
context->chosen_cipher = NULL;
|
|
}
|
|
if (context->chosen_curve != NULL) {
|
|
free(context->chosen_curve);
|
|
context->chosen_curve = NULL;
|
|
}
|
|
if (context->chosen_hash != NULL) {
|
|
free(context->chosen_hash);
|
|
context->chosen_hash = NULL;
|
|
}
|
|
if (context->shared_key != NULL) {
|
|
free(context->shared_key);
|
|
context->shared_key = NULL;
|
|
}
|
|
if (context->remote_peer_id != NULL) {
|
|
free(context->remote_peer_id);
|
|
context->remote_peer_id = NULL;
|
|
}
|
|
if (context->remote_ephemeral_public_key != NULL) {
|
|
free(context->remote_ephemeral_public_key);
|
|
context->remote_ephemeral_public_key = NULL;
|
|
}
|
|
if (context->local_stretched_key != NULL) {
|
|
libp2p_crypto_ephemeral_stretched_key_free(context->local_stretched_key);
|
|
context->local_stretched_key = NULL;
|
|
}
|
|
if (context->remote_stretched_key != NULL) {
|
|
libp2p_crypto_ephemeral_stretched_key_free(context->remote_stretched_key);
|
|
context->remote_stretched_key = NULL;
|
|
}
|
|
if (context->ephemeral_private_key != NULL) {
|
|
libp2p_crypto_ephemeral_key_free(context->ephemeral_private_key);
|
|
context->ephemeral_private_key = NULL;
|
|
}
|
|
free(context);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/***
|
|
* Attempt to lock a stream for personal use. Does not block.
|
|
* @param stream the stream to lock
|
|
* @returns true(1) on success, false(0) otherwise
|
|
*/
|
|
int libp2p_stream_try_lock(struct Stream* stream) {
|
|
if (stream == NULL)
|
|
return 0;
|
|
if (pthread_mutex_trylock(stream->socket_mutex) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/***
|
|
* Attempt to lock a stream for personal use. Blocks until the lock is acquired
|
|
* @param stream the stream to lock
|
|
* @returns true(1) on success, false(0) otherwise
|
|
*/
|
|
int libp2p_stream_lock(struct Stream* stream) {
|
|
if (stream == NULL)
|
|
return 0;
|
|
if (pthread_mutex_lock(stream->socket_mutex) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/***
|
|
* Attempt to unlock the mutex for this stream
|
|
* @param stream the stream to unlock
|
|
* @returns true(1) on success, false(0) otherwise
|
|
*/
|
|
int libp2p_stream_unlock(struct Stream* stream) {
|
|
if (stream == NULL)
|
|
return 0;
|
|
if (pthread_mutex_unlock(stream->socket_mutex) == 0)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/***
|
|
* Create a new StreamMessage struct
|
|
* @returns a StreamMessage struct
|
|
*/
|
|
struct StreamMessage* libp2p_stream_message_new() {
|
|
struct StreamMessage* out = (struct StreamMessage*) malloc(sizeof(struct StreamMessage));
|
|
if (out != NULL) {
|
|
out->data = NULL;
|
|
out->data_size = 0;
|
|
out->error_number = 0;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* free resources of a StreamMessage struct
|
|
* @param msg the StreamMessage to free
|
|
*/
|
|
void libp2p_stream_message_free(struct StreamMessage* msg) {
|
|
if (msg != NULL) {
|
|
if (msg->data != NULL) {
|
|
free(msg->data);
|
|
msg->data = NULL;
|
|
}
|
|
free(msg);
|
|
msg = NULL;
|
|
}
|
|
}
|
|
|
|
/***
|
|
* Make a copy of a message
|
|
* @param original the original message
|
|
* @returns a StreamMessage that is a copy of the original
|
|
*/
|
|
struct StreamMessage* libp2p_stream_message_copy(const struct StreamMessage* original) {
|
|
struct StreamMessage* copy = libp2p_stream_message_new();
|
|
if (copy != NULL) {
|
|
copy->error_number = original->error_number;
|
|
copy->data_size = original->data_size;
|
|
copy->data = (uint8_t*) malloc(copy->data_size);
|
|
if (copy->data == NULL) {
|
|
libp2p_stream_message_free(copy);
|
|
return NULL;
|
|
}
|
|
memcpy(copy->data, original->data, copy->data_size);
|
|
}
|
|
return copy;
|
|
}
|
|
|
|
/****
|
|
* Make a copy of a SessionContext
|
|
* @param original the original
|
|
* @returns a copy of the original, or NULL on error
|
|
*/
|
|
struct SessionContext* libp2p_session_context_copy(const struct SessionContext* original) {
|
|
struct SessionContext* new_ctx = libp2p_session_context_new();
|
|
if (new_ctx != NULL) {
|
|
new_ctx->aes_decode_nonce_offset = original->aes_decode_nonce_offset;
|
|
memcpy(new_ctx->aes_decode_stream_block, original->aes_decode_stream_block, 16);
|
|
new_ctx->aes_encode_nonce_offset = original->aes_encode_nonce_offset;
|
|
memcpy(new_ctx->aes_encode_stream_block, original->aes_encode_stream_block, 16);
|
|
new_ctx->chosen_cipher = (char*) malloc(strlen(original->chosen_cipher) + 1);
|
|
strcpy(new_ctx->chosen_cipher, original->chosen_cipher);
|
|
new_ctx->chosen_curve = (char*) malloc(strlen(original->chosen_curve) + 1);
|
|
strcpy(new_ctx->chosen_curve, original->chosen_curve);
|
|
new_ctx->chosen_hash = (char*) malloc(strlen(original->chosen_hash) + 1);
|
|
strcpy(new_ctx->chosen_hash, original->chosen_hash);
|
|
// TODO: Copy everything else
|
|
}
|
|
return new_ctx;
|
|
}
|
|
|
|
int libp2p_session_context_compare_streams(const struct Stream* a, const struct Stream* b) {
|
|
if (a == NULL && b == NULL)
|
|
return 0;
|
|
if (a == NULL && b != NULL)
|
|
return -1;
|
|
if (a != NULL && b == NULL)
|
|
return 1;
|
|
return multiaddress_compare(a->address, b->address);
|
|
}
|
|
|
|
int libp2p_session_context_compare_remote_key(const struct PublicKey* a, const struct PublicKey* b) {
|
|
if (a == NULL && b == NULL)
|
|
return 0;
|
|
if (a == NULL && b != NULL)
|
|
return -1;
|
|
if (a != NULL && b == NULL)
|
|
return 1;
|
|
int total = b->data_size - a->data_size;
|
|
if (total != 0)
|
|
return total;
|
|
for(size_t i = 0; i < b->data_size; i++) {
|
|
total = b->data[i] - a->data[i];
|
|
if (total != 0)
|
|
return total;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int libp2p_session_context_compare(const struct SessionContext* a, const struct SessionContext* b) {
|
|
int total = 0;
|
|
if (a == NULL && b == NULL)
|
|
return 0;
|
|
if (a == NULL && b != NULL)
|
|
return -1;
|
|
if (a != NULL && b == NULL)
|
|
return 1;
|
|
// streams
|
|
total = libp2p_session_context_compare_streams(a->default_stream, b->default_stream);
|
|
if (total != 0)
|
|
return total;
|
|
// remote key
|
|
total = libp2p_session_context_compare_remote_key(&a->remote_key, &b->remote_key);
|
|
return total;
|
|
}
|
|
|