Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/maglar0/libcurvecpr into …
Browse files Browse the repository at this point in the history
…bug/9, refs #9
  • Loading branch information
impl committed May 5, 2014
2 parents 3939c78 + 0920edb commit ea950e6
Show file tree
Hide file tree
Showing 18 changed files with 1,623 additions and 16 deletions.
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

0 comments on commit ea950e6

Please sign in to comment.