Remove pull/push

This commit is contained in:
Adrien Gallouët
2016-10-27 15:00:03 +00:00
parent df0d941241
commit 22d61780fd
2 changed files with 143 additions and 254 deletions

392
mud.c
View File

@@ -41,8 +41,6 @@
#define MUD_DFRAG_OPT IP_PMTUDISC_DO
#endif
#define MUD_COUNT(X) (sizeof(X)/sizeof(X[0]))
#define MUD_ONE_MSEC (UINT64_C(1000))
#define MUD_ONE_SEC (1000*MUD_ONE_MSEC)
#define MUD_ONE_MIN (60*MUD_ONE_SEC)
@@ -53,9 +51,6 @@
#define MUD_PACKET_MIN_SIZE (MUD_U48_SIZE+MUD_MAC_SIZE)
#define MUD_PACKET_MAX_SIZE (1500U)
#define MUD_PACKET_MASK (0x3FFU)
#define MUD_PACKET_COUNT ((MUD_PACKET_MASK)+1)
#define MUD_PACKET_NEXT(X) (((X)+1)&(MUD_PACKET_MASK))
#define MUD_PACKET_SIZEOF(X) ((X)+MUD_PACKET_MIN_SIZE)
#define MUD_PONG_SIZE MUD_PACKET_SIZEOF(MUD_U48_SIZE*3)
@@ -108,18 +103,6 @@ struct path {
struct path *next;
};
struct packet {
size_t size;
int tc;
unsigned char data[MUD_PACKET_MAX_SIZE];
};
struct queue {
struct packet *packet;
unsigned start;
unsigned end;
};
struct public {
unsigned char send[MUD_PKEY_SIZE];
unsigned char recv[MUD_PKEY_SIZE];
@@ -159,8 +142,6 @@ struct mud {
uint64_t mtu;
uint64_t recv_mtu;
int send_mtu;
struct queue tx;
struct queue rx;
struct path *path;
struct crypto crypto;
};
@@ -688,17 +669,6 @@ int mud_create_socket (int port, int v4, int v6)
return fd;
}
static
int mud_create_queue (struct queue *queue)
{
queue->packet = calloc(MUD_PACKET_COUNT, sizeof(struct packet));
if (!queue->packet)
return -1;
return 0;
}
static
void mud_keyx_init (struct mud *mud)
{
@@ -725,12 +695,6 @@ struct mud *mud_create (int port, int v4, int v6, int aes, int mtu)
return NULL;
}
if (mud_create_queue(&mud->tx) ||
mud_create_queue(&mud->rx)) {
mud_delete(mud);
return NULL;
}
mud->send_timeout = MUD_SEND_TIMEOUT;
mud->time_tolerance = MUD_TIME_TOLERANCE;
mud->mtu = mtu;
@@ -756,9 +720,6 @@ void mud_delete (struct mud *mud)
if (!mud)
return;
free(mud->tx.packet);
free(mud->rx.packet);
while (mud->path) {
struct path *path = mud->path;
mud->path = path->next;
@@ -843,16 +804,6 @@ int mud_decrypt (struct mud *mud,
return size;
}
int mud_can_pull (struct mud *mud)
{
return (mud->rx.start != MUD_PACKET_NEXT(mud->rx.end));
}
int mud_can_push (struct mud *mud)
{
return (mud->tx.start != mud->tx.end);
}
int mud_peer_is_up (struct mud *mud, const char *name, const char *host, int port)
{
if (!name || !host || !port)
@@ -1032,145 +983,118 @@ void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
mud->crypto.time = now;
}
int mud_pull (struct mud *mud)
{
unsigned char ctrl[256];
while (1) {
unsigned next = MUD_PACKET_NEXT(mud->rx.end);
if (mud->rx.start == next) {
errno = ENOBUFS;
return -1;
}
struct packet *packet = &mud->rx.packet[mud->rx.end];
struct sockaddr_storage addr;
struct iovec iov = {
.iov_base = &packet->data,
.iov_len = sizeof(packet->data),
};
struct msghdr msg = {
.msg_name = &addr,
.msg_namelen = sizeof(addr),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = ctrl,
.msg_controllen = sizeof(ctrl),
};
ssize_t ret = recvmsg(mud->fd, &msg, 0);
if (ret <= (ssize_t)MUD_PACKET_MIN_SIZE) {
if (ret <= (ssize_t)0)
return (int)ret;
continue;
}
uint64_t now = mud_now(mud);
uint64_t send_time = mud_read48(packet->data);
int mud_packet = !send_time;
if (mud_packet) {
if (ret < (ssize_t)MUD_PACKET_SIZEOF(MUD_U48_SIZE))
continue;
send_time = mud_read48(&packet->data[MUD_U48_SIZE]);
}
if (mud_dt(now, send_time) >= mud->time_tolerance)
continue;
if (mud_packet) {
unsigned char tmp[sizeof(packet->data)];
struct crypto_opt opt = {
.dst = tmp,
.src = { .data = packet->data+ret-MUD_MAC_SIZE,
.size = MUD_MAC_SIZE },
.ad = { .data = packet->data,
.size = ret-MUD_MAC_SIZE },
};
if (mud_decrypt_opt(&mud->crypto.private, &opt))
continue;
}
mud_unmapv4((struct sockaddr *)&addr);
struct ipaddr local_addr;
if (mud_localaddr(&local_addr, &msg, addr.ss_family))
continue;
struct path *path = mud_path(mud, &local_addr,
(struct sockaddr *)&addr, mud_packet);
if (!path)
return -1;
if (mud_packet)
path->state.up = 1;
int64_t dt = (now-path->recv_time)-(send_time-path->recv_send_time);
if (path->recv_time && path->recv_send_time && (dt > 0))
path->rdt = (path->rdt*UINT64_C(7)+dt)/UINT64_C(8);
path->recv_send_time = send_time;
path->recv_time = now;
if (mud_packet && (ret == (ssize_t)MUD_PONG_SIZE)) {
uint64_t st = mud_read48(&packet->data[MUD_U48_SIZE*2]);
uint64_t dt = mud_read48(&packet->data[MUD_U48_SIZE*3]);
path->dt = dt;
path->sdt = send_time-st;
path->rtt = now-st;
continue;
}
if ((!path->pong_time) ||
(now-path->pong_time >= MUD_PONG_TIMEOUT)) {
mud_ctrl_path(mud, mud_pong, path, now);
path->pong_time = now;
}
if (mud_packet) {
if (ret == (ssize_t)MUD_KEYX_SIZE) {
mud_recv_keyx(mud, path, now, &packet->data[MUD_U48_SIZE*2]);
} else if (ret == (ssize_t)MUD_MTUX_SIZE) {
mud->recv_mtu = mud_read48(&packet->data[MUD_U48_SIZE*2]);
mud->send_mtu = 0;
if (!path->state.active)
mud_ctrl_path(mud, mud_mtux, path, now);
}
continue;
}
packet->size = ret;
mud->rx.end = next;
}
return 0;
}
int mud_recv (struct mud *mud, void *data, size_t size)
{
if (mud->rx.start == mud->rx.end) {
errno = EAGAIN;
return -1;
unsigned char packet[MUD_PACKET_MAX_SIZE];
struct iovec iov = {
.iov_base = packet,
.iov_len = sizeof(packet),
};
struct sockaddr_storage addr;
unsigned char ctrl[256];
struct msghdr msg = {
.msg_name = &addr,
.msg_namelen = sizeof(addr),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = ctrl,
.msg_controllen = sizeof(ctrl),
};
ssize_t packet_size = recvmsg(mud->fd, &msg, 0);
if (packet_size <= (ssize_t)MUD_PACKET_MIN_SIZE) {
if (packet_size == (ssize_t)-1)
return -1;
return 0;
}
struct packet *packet = &mud->rx.packet[mud->rx.start];
uint64_t now = mud_now(mud);
uint64_t send_time = mud_read48(packet);
int ret = mud_decrypt(mud, data, size, packet->data, packet->size);
int mud_packet = !send_time;
mud->rx.start = MUD_PACKET_NEXT(mud->rx.start);
if (mud_packet) {
if (packet_size < (ssize_t)MUD_PACKET_SIZEOF(MUD_U48_SIZE))
return 0;
send_time = mud_read48(&packet[MUD_U48_SIZE]);
}
if (mud_dt(now, send_time) >= mud->time_tolerance)
return 0;
if (mud_packet) {
unsigned char tmp[sizeof(packet)];
struct crypto_opt opt = {
.dst = tmp,
.src = { .data = packet+packet_size-MUD_MAC_SIZE,
.size = MUD_MAC_SIZE },
.ad = { .data = packet,
.size = packet_size-MUD_MAC_SIZE },
};
if (mud_decrypt_opt(&mud->crypto.private, &opt))
return 0;
}
mud_unmapv4((struct sockaddr *)&addr);
struct ipaddr local_addr;
if (mud_localaddr(&local_addr, &msg, addr.ss_family))
return 0;
struct path *path = mud_path(mud, &local_addr,
(struct sockaddr *)&addr, mud_packet);
if (!path)
return -1;
if (mud_packet)
path->state.up = 1;
int64_t dt = (now-path->recv_time)-(send_time-path->recv_send_time);
if (path->recv_time && path->recv_send_time && (dt > 0))
path->rdt = (path->rdt*UINT64_C(7)+dt)/UINT64_C(8);
path->recv_send_time = send_time;
path->recv_time = now;
if (mud_packet && (packet_size == (ssize_t)MUD_PONG_SIZE)) {
uint64_t st = mud_read48(&packet[MUD_U48_SIZE*2]);
uint64_t dt = mud_read48(&packet[MUD_U48_SIZE*3]);
path->dt = dt;
path->sdt = send_time-st;
path->rtt = now-st;
return 0;
}
if ((!path->pong_time) ||
(now-path->pong_time >= MUD_PONG_TIMEOUT)) {
mud_ctrl_path(mud, mud_pong, path, now);
path->pong_time = now;
}
if (mud_packet) {
if (packet_size == (ssize_t)MUD_KEYX_SIZE) {
mud_recv_keyx(mud, path, now, &packet[MUD_U48_SIZE*2]);
} else if (packet_size == (ssize_t)MUD_MTUX_SIZE) {
mud->recv_mtu = mud_read48(&packet[MUD_U48_SIZE*2]);
mud->send_mtu = 0;
if (!path->state.active)
mud_ctrl_path(mud, mud_mtux, path, now);
}
return 0;
}
int ret = mud_decrypt(mud, data, size, packet, packet_size);
if (ret == -1) {
mud->crypto.bad_key = 1;
@@ -1180,7 +1104,7 @@ int mud_recv (struct mud *mud, void *data, size_t size)
return ret;
}
int mud_push (struct mud *mud)
int mud_send_ctrl (struct mud *mud)
{
struct path *path;
@@ -1221,64 +1145,12 @@ int mud_push (struct mud *mud)
mud_ctrl_path(mud, mud_ping, path, now);
}
while (mud->tx.start != mud->tx.end) {
uint64_t now = mud_now(mud);
struct packet *packet = &mud->tx.packet[mud->tx.start];
struct path *path_min = NULL;
int64_t limit_min = INT64_MAX;
for (path = mud->path; path; path = path->next) {
if (!path->state.up || !path->state.on)
continue;
int64_t limit = path->limit;
uint64_t elapsed = now-path->send_time;
if (limit > elapsed) {
limit += path->rtt/2-elapsed;
} else {
limit = path->rtt/2;
}
if (limit_min > limit) {
limit_min = limit;
path_min = path;
}
}
if (!path_min)
break;
ssize_t ret = mud_send_path(mud, path_min, now,
packet->data, packet->size, packet->tc);
if (ret == -1) {
switch (errno) {
case EAGAIN:
case EINTR:
case ENOMEM:
case ENOBUFS:
return 0;
}
}
mud->tx.start = MUD_PACKET_NEXT(mud->tx.start);
// if (ret == -1 && errno == EMSGSIZE)
// return -1;
if (ret == packet->size)
path_min->limit = limit_min;
}
return 0;
}
int mud_send (struct mud *mud, const void *data, size_t size, int tc)
{
mud_send_ctrl(mud);
if (!size)
return 0;
@@ -1287,28 +1159,50 @@ int mud_send (struct mud *mud, const void *data, size_t size, int tc)
return -1;
}
unsigned next = MUD_PACKET_NEXT(mud->tx.end);
uint64_t now = mud_now(mud);
if (mud->tx.start == next) {
errno = ENOBUFS;
return -1;
struct path *path;
struct path *path_min = NULL;
int64_t limit_min = INT64_MAX;
for (path = mud->path; path; path = path->next) {
if (!path->state.up || !path->state.on)
continue;
int64_t limit = path->limit;
uint64_t elapsed = now-path->send_time;
if (limit > elapsed) {
limit += path->rtt/2-elapsed;
} else {
limit = path->rtt/2;
}
if (limit_min > limit) {
limit_min = limit;
path_min = path;
}
}
struct packet *packet = &mud->tx.packet[mud->tx.end];
if (!path_min)
return -1;
int ret = mud_encrypt(mud, mud_now(mud),
packet->data, sizeof(packet->data),
unsigned char packet[2048];
int packet_size = mud_encrypt(mud, now,
packet, sizeof(packet),
data, size);
if (!ret) {
if (!packet_size) {
errno = EMSGSIZE;
return -1;
}
packet->size = ret;
packet->tc = tc;
ssize_t ret = mud_send_path(mud, path_min, now,
packet, packet_size, tc);
mud->tx.end = next;
if (ret == packet_size)
path_min->limit = limit_min;
return size;
return (int)ret;
}

5
mud.h
View File

@@ -22,12 +22,7 @@ int mud_set_on (struct mud *, const char *, int);
int mud_peer (struct mud *, const char *, const char *, int);
int mud_peer_is_up (struct mud *, const char *, const char *, int);
int mud_can_pull (struct mud *);
int mud_can_push (struct mud *);
int mud_is_up (struct mud *);
int mud_pull (struct mud *);
int mud_push (struct mud *);
int mud_recv (struct mud *, void *, size_t);
int mud_send (struct mud *, const void *, size_t, int);