Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfixes and some tests #9

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
19 changes: 18 additions & 1 deletion libcurvecpr/include/curvecpr/chicago.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
#ifndef __CURVECPR_CHICAGO_H
#define __CURVECPR_CHICAGO_H

struct curvecpr_chicago_ops {
/* Get current time in nanoseconds. The time 0 can be any time as long
as present time is not too close to it (>100 seconds should be ok) and
it doesn't change during the lifetime of this chicago instance (i.e.
it doesn't have to be for example 1970-01-01, but can be the number of
nanoseconds since the computer booted+100s or whatever).
You can pass in curvecpr_util_nanoseconds() here if you want. */
long long (*get_nanoseconds)(void *priv);
};

struct curvecpr_chicago_cf {
struct curvecpr_chicago_ops ops;
void *priv;
};

struct curvecpr_chicago {
long long clock;

Expand All @@ -24,9 +39,11 @@ struct curvecpr_chicago {
long long ns_last_edge;
long long ns_last_doubling;
long long ns_last_panic;

struct curvecpr_chicago_cf cf;
};

void curvecpr_chicago_new (struct curvecpr_chicago *chicago);
void curvecpr_chicago_new (struct curvecpr_chicago *chicago, const struct curvecpr_chicago_cf *cf);
void curvecpr_chicago_refresh_clock (struct curvecpr_chicago *chicago);
void curvecpr_chicago_on_timeout (struct curvecpr_chicago *chicago);
void curvecpr_chicago_on_recv (struct curvecpr_chicago *chicago, long long ns_sent);
Expand Down
31 changes: 31 additions & 0 deletions libcurvecpr/include/curvecpr/messager.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@

struct curvecpr_messager;


/* The callbacks you need to implement to get a reliable stream transport.
You need to implement the three data structures mentioned below.
Terminology:
sendq (send queue): The data waiting to get sent. When you want to send
something, you divide it into curvecpr_block:s (each at most
messager->my_maximum_send_bytes in size) and put it in this
queue (you have to do this yourself). When you call
curvecpr_messager_process_sendq() it will check
this queue for data ready to be sent. It might not happen
immediately, but at a later invocation depending on the
decongestion algorithm and packets waiting to be resent etc.
sendmarkq (sent-to-be-marked queue): When a curvecpr_block is sent
(using the send() callback function), it is moved from sendq to
sendmarkq (if it wasn't moved earlier and this is just a resend).
It waits here until it has been acknowledged by the recipient.
recvmarkq (received-to-be-marked): Received curvecpr_block:s are stored
here until we have sent an ACK (which happens right after they are
stored actually). You need to assemble the stream data from this
data structure yourself.
*/
struct curvecpr_messager_ops {
int (*sendq_head)(struct curvecpr_messager *messager, struct curvecpr_block **block_stored);
int (*sendq_move_to_sendmarkq)(struct curvecpr_messager *messager, const struct curvecpr_block *block, struct curvecpr_block **block_stored);
Expand All @@ -19,17 +41,22 @@ struct curvecpr_messager_ops {
the time at which they were last sent. */
int (*sendmarkq_head)(struct curvecpr_messager *messager, struct curvecpr_block **block_stored);
int (*sendmarkq_get)(struct curvecpr_messager *messager, crypto_uint32 acknowledging_id, struct curvecpr_block **block_stored);

/* This is called for all ranges in incoming messages's acknowledge structure */
int (*sendmarkq_remove_range)(struct curvecpr_messager *messager, unsigned long long start, unsigned long long end);
unsigned char (*sendmarkq_is_full)(struct curvecpr_messager *messager);

/* This is called once for each message coming in that is not a pure acknowledgement */
int (*recvmarkq_put)(struct curvecpr_messager *messager, const struct curvecpr_block *block, struct curvecpr_block **block_stored);

int (*recvmarkq_get_nth_unacknowledged)(struct curvecpr_messager *messager, unsigned int n, struct curvecpr_block **block_stored);
unsigned char (*recvmarkq_is_empty)(struct curvecpr_messager *messager);
int (*recvmarkq_remove_range)(struct curvecpr_messager *messager, unsigned long long start, unsigned long long end);

int (*send)(struct curvecpr_messager *messager, const unsigned char *buf, size_t num);

void (*put_next_timeout)(struct curvecpr_messager *messager, const long long timeout_ns);
long long (*get_nanoseconds)(void *priv);
};

struct curvecpr_messager_cf {
Expand All @@ -50,6 +77,9 @@ struct curvecpr_messager {
unsigned char my_eof;
unsigned char my_final;

/* The client can only send 512 bytes/message until we know that an
initiation packet has reached the server. Then this variable is raised
to 1024 bytes. The server can send 1024 bytes/message from the start. */
size_t my_maximum_send_bytes;

crypto_uint64 my_sent_bytes;
Expand All @@ -68,6 +98,7 @@ struct curvecpr_messager {

void curvecpr_messager_new (struct curvecpr_messager *messager, const struct curvecpr_messager_cf *cf, unsigned char client);
int curvecpr_messager_recv (struct curvecpr_messager *messager, const unsigned char *buf, size_t num);
/* Call this function on timeout and when you have added things to sendq if it was empty. */
int curvecpr_messager_process_sendq (struct curvecpr_messager *messager);
long long curvecpr_messager_next_timeout (struct curvecpr_messager *messager);

Expand Down
2 changes: 1 addition & 1 deletion libcurvecpr/include/curvecpr/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define __CURVECPR_UTIL_H

long long curvecpr_util_random_mod_n (long long n);
long long curvecpr_util_nanoseconds (void);
long long curvecpr_util_nanoseconds (void *);
int curvecpr_util_encode_domain_name (unsigned char *destination, const char *source);

#endif
7 changes: 5 additions & 2 deletions libcurvecpr/lib/chicago.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,13 @@ static void _update_on_timeout (struct curvecpr_chicago *chicago)
}
}

void curvecpr_chicago_new (struct curvecpr_chicago *chicago)
void curvecpr_chicago_new (struct curvecpr_chicago *chicago, const struct curvecpr_chicago_cf *cf)
{
curvecpr_bytes_zero(chicago, sizeof(struct curvecpr_chicago));

if (cf)
curvecpr_bytes_copy(&chicago->cf, cf, sizeof(struct curvecpr_chicago_cf));

curvecpr_chicago_refresh_clock(chicago);

chicago->rtt_latest = 0;
Expand All @@ -153,7 +156,7 @@ void curvecpr_chicago_new (struct curvecpr_chicago *chicago)

void curvecpr_chicago_refresh_clock (struct curvecpr_chicago *chicago)
{
chicago->clock = curvecpr_util_nanoseconds();
chicago->clock = chicago->cf.ops.get_nanoseconds(chicago->cf.priv);
}

void curvecpr_chicago_on_timeout (struct curvecpr_chicago *chicago)
Expand Down
5 changes: 4 additions & 1 deletion libcurvecpr/lib/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include <sodium/crypto_box.h>

#include <errno.h>

static const unsigned char _zeros[128] = { 0 };

void curvecpr_client_new (struct curvecpr_client *client, const struct curvecpr_client_cf *cf)
Expand Down Expand Up @@ -70,7 +72,8 @@ int curvecpr_client_connected (struct curvecpr_client *client)
curvecpr_bytes_copy(p.box, data + 16, 80);
}

cf->ops.send(client, (const unsigned char *)&p, sizeof(struct curvecpr_packet_hello));
if (cf->ops.send(client, (const unsigned char *)&p, sizeof(struct curvecpr_packet_hello)))
return -EAGAIN;

return 0;
}
17 changes: 14 additions & 3 deletions libcurvecpr/lib/messager.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,17 @@ void curvecpr_messager_new (struct curvecpr_messager *messager, const struct cur
curvecpr_bytes_zero(messager, sizeof(struct curvecpr_messager));

/* Initialize configuration. */
if (cf)
curvecpr_bytes_copy(&messager->cf, cf, sizeof(struct curvecpr_messager_cf));
curvecpr_bytes_copy(&messager->cf, cf, sizeof(struct curvecpr_messager_cf));

/* Initialize congestion handling. */
curvecpr_chicago_new(&messager->chicago);
struct curvecpr_chicago_ops chicago_ops = {
.get_nanoseconds = cf->ops.get_nanoseconds
};
struct curvecpr_chicago_cf chicago_cf = {
.ops = chicago_ops,
.priv = cf->priv
};
curvecpr_chicago_new(&messager->chicago, &chicago_cf);

/* If we're in client mode, initiate packets have a maximum size of 512 bytes.
Otherwise, we're in server mode, and we can start at 1024. */
Expand Down Expand Up @@ -517,6 +523,11 @@ long long curvecpr_messager_next_timeout (struct curvecpr_messager *messager)

if (at > block->clock + chicago->rtt_timeout)
at = block->clock + chicago->rtt_timeout;

/* Writing faster than wr_rate does not make sense and will cause spinning. BUT, if
there is something to acknowledge, block might still be resent. */
if (cf->ops.recvmarkq_is_empty(messager) && at < messager->my_sent_clock + chicago->wr_rate)
at = messager->my_sent_clock + chicago->wr_rate;
}

if (chicago->clock > at)
Expand Down
3 changes: 2 additions & 1 deletion libcurvecpr/lib/server_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static int _handle_initiate (struct curvecpr_server *server, struct curvecpr_ses
curvecpr_bytes_zero(vouch, 16);
curvecpr_bytes_copy(vouch + 16, p_box->vouch, 48);

if (crypto_box_afternm(vouch, vouch, 64, nonce, s_new.my_global_their_global_key))
if (crypto_box_open_afternm(vouch, vouch, 64, nonce, s_new.my_global_their_global_key))
return -EINVAL;

if (!curvecpr_bytes_equal(vouch + 32, s_new.their_session_pk, 32))
Expand All @@ -171,6 +171,7 @@ static int _handle_initiate (struct curvecpr_server *server, struct curvecpr_ses
/* All good, we can go ahead and submit the client for registration. */
s_new.their_session_nonce = curvecpr_bytes_unpack_uint64(p->nonce);
curvecpr_bytes_copy(s_new.my_domain_name, p_box->server_domain_name, 256);
curvecpr_bytes_copy(s_new.their_extension, p->client_extension, 16);

if (cf->ops.put_session(server, &s_new, priv, &s_new_stored))
return -EINVAL; /* This can fail for a variety of reasons that are up to
Expand Down
2 changes: 1 addition & 1 deletion libcurvecpr/lib/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ long long curvecpr_util_random_mod_n (long long n)

/* XXX: Y2036 problems; should upgrade to a 128-bit type for this. */
/* XXX: Nanosecond granularity limits users to 1 terabyte per second. */
long long curvecpr_util_nanoseconds (void)
long long curvecpr_util_nanoseconds (void *priv)
{
/* XXX: host_get_clock_service() has been officially deprecated for years;
this may need to be updated in the future. */
Expand Down
6 changes: 6 additions & 0 deletions libcurvecpr/test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ messager_test_send_with_1_failure_moves_message_from_sendq_SOURCES = messager/te
check_PROGRAMS += messager/test_timeout_callback_fires
messager_test_timeout_callback_fires_SOURCES = messager/test_timeout_callback_fires.c

check_PROGRAMS += messager/test_delivery
messager_test_delivery_SOURCES = messager/test_delivery.c

check_PROGRAMS += util/test_nanoseconds
util_test_nanoseconds_SOURCES = util/test_nanoseconds.c

check_PROGRAMS += packet_delivery/packet_delivery
packet_delivery_packet_delivery_SOURCES = packet_delivery/packet_delivery.c

TESTS = $(check_PROGRAMS)
1 change: 1 addition & 0 deletions libcurvecpr/test/messager/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/test_recv_requests_removal_from_sendmarkq
/test_send_with_1_failure_moves_message_from_sendq
/test_timeout_callback_fires
/test_delivery
Loading