mirror of
https://github.com/yarrick/iodine.git
synced 2024-11-25 11:05:15 +00:00
Server-side sliding window implementation mostly finished. Requires
testing.
This commit is contained in:
parent
844abefcf8
commit
d8c08191cc
@ -294,6 +294,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
|
server_init();
|
||||||
|
|
||||||
#ifdef WINDOWS32
|
#ifdef WINDOWS32
|
||||||
WSAStartup(req_version, &wsa_data);
|
WSAStartup(req_version, &wsa_data);
|
||||||
#endif
|
#endif
|
||||||
|
0
src/osflags
Executable file → Normal file
0
src/osflags
Executable file → Normal file
216
src/server.c
216
src/server.c
@ -44,6 +44,7 @@
|
|||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "fw_query.h"
|
#include "fw_query.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
# include <systemd/sd-daemon.h>
|
# include <systemd/sd-daemon.h>
|
||||||
@ -119,15 +120,6 @@ send_raw(int fd, uint8_t *buf, size_t buflen, int user, int cmd, struct query *q
|
|||||||
sendto(fd, packet, len, 0, (struct sockaddr *) &q->from, q->fromlen);
|
sendto(fd, packet, len, 0, (struct sockaddr *) &q->from, q->fromlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_new_outpacket(int userid, uint8_t *data, size_t datalen)
|
|
||||||
/* Copies data to .outpacket and resets all counters.
|
|
||||||
data is expected to be compressed already. */
|
|
||||||
{
|
|
||||||
// TODO: window add to outgoing data
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
answer_from_qmem(int dns_fd, struct query *q, unsigned char *qmem_cmc,
|
answer_from_qmem(int dns_fd, struct query *q, unsigned char *qmem_cmc,
|
||||||
unsigned short *qmem_type, int qmem_len,
|
unsigned short *qmem_type, int qmem_len,
|
||||||
@ -378,10 +370,41 @@ forward_query(int bind_fd, struct query *q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
send_ping_response(int dns_fd, int userid, struct query *q)
|
||||||
|
{
|
||||||
|
static uint8_t pkt[10];
|
||||||
|
size_t datalen = 5;
|
||||||
|
/* Build downstream data + ping header (see doc/proto_xxxxxxxx.txt) for details */
|
||||||
|
pkt[0] = users[userid].outgoing->start_seq_id & 0xFF;
|
||||||
|
pkt[1] = users[userid].incoming->start_seq_id & 0xFF;
|
||||||
|
pkt[2] = (1 << 5); /* ping flag */
|
||||||
|
pkt[3] = users[userid].outgoing->windowsize & 0xFF;
|
||||||
|
pkt[4] = users[userid].incoming->windowsize & 0xFF;
|
||||||
|
|
||||||
|
write_dns(dns_fd, q, (char *)pkt, datalen, users[userid].downenc);
|
||||||
|
|
||||||
|
if (q->id2 != 0) { /* rotate pending duplicate queries */
|
||||||
|
q->id = q->id2;
|
||||||
|
q->fromlen = q->fromlen2;
|
||||||
|
memcpy(&(q->from), &(q->from2), q->fromlen2);
|
||||||
|
if (debug >= 1)
|
||||||
|
warnx("OUT again to last duplicate");
|
||||||
|
write_dns(dns_fd, q, (char *)pkt, datalen, users[userid].downenc);
|
||||||
|
}
|
||||||
|
|
||||||
|
save_to_qmem_pingordata(userid, q);
|
||||||
|
|
||||||
|
#ifdef DNSCACHE_LEN
|
||||||
|
save_to_dnscache(userid, q, (char *)pkt, datalen + 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
q->id = 0; /* this query is used */
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_frag_or_dataless(int dns_fd, int userid, struct query *q)
|
send_frag_or_dataless(int dns_fd, int userid, struct query *q)
|
||||||
/* Sends current fragment to user, or dataless packet if there is no
|
/* Sends current fragment to user, or a ping if no data available.
|
||||||
current fragment available (-> normal "quiet" ping reply).
|
|
||||||
Does not update anything, except:
|
Does not update anything, except:
|
||||||
- discards q always (query is used)
|
- discards q always (query is used)
|
||||||
- forgets entire users[userid].outpacket if it was sent in one go,
|
- forgets entire users[userid].outpacket if it was sent in one go,
|
||||||
@ -390,43 +413,60 @@ send_frag_or_dataless(int dns_fd, int userid, struct query *q)
|
|||||||
0 = don't call us again for now.
|
0 = don't call us again for now.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char pkt[4096];
|
static uint8_t pkt[MAX_FRAGSIZE + DOWNSTREAM_HDR];
|
||||||
int datalen = 0;
|
int ping = 0;
|
||||||
|
size_t datalen;
|
||||||
|
fragment *f;
|
||||||
|
struct frag_buffer *out;
|
||||||
|
|
||||||
/* TODO: If re-sent too many times, drop entire packet */
|
out = users[userid].outgoing;
|
||||||
|
|
||||||
/* Build downstream data header (see doc/proto_xxxxxxxx.txt) */
|
f = window_get_next_sending_fragment(out, users[userid].next_upstream_ack);
|
||||||
|
if (!f && user_sending(userid)) {
|
||||||
|
/* Need to tell client to sync stuff - send data header with ping stuff */
|
||||||
|
ping = 1;
|
||||||
|
} /* TODO: If re-sent too many times, drop stuff */
|
||||||
|
|
||||||
// /* First byte is 1 bit compression flag, 3 bits upstream seqno, 4 bits upstream fragment */
|
/* Build downstream data header (see doc/proto_xxxxxxxx.txt) for details */
|
||||||
// pkt[0] = (1<<7) | ((users[userid].inpacket.seqno & 7) << 4) |
|
pkt[0] = f->seqID & 0xFF;
|
||||||
// (users[userid].inpacket.fragment & 15);
|
pkt[1] = f->ack_other & 0xFF;
|
||||||
// /* Second byte is 3 bits downstream seqno, 4 bits downstream fragment, 1 bit last flag */
|
pkt[2] = ((ping & 1) << 5) | ((f->compressed & 1) << 4) | ((f->ack_other < 0 ? 0 : 1) << 3)
|
||||||
// pkt[1] = ((users[userid].outpacket.seqno & 7) << 5) |
|
| (f->is_nack << 2) | (f->start << 1) | f->end;
|
||||||
// ((users[userid].outpacket.fragment & 15) << 1) | (last & 1);
|
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (ping) {
|
||||||
// TODO: display packet data
|
pkt[3] = out->windowsize & 0xFF;
|
||||||
|
pkt[4] = users[userid].incoming->windowsize & 0xFF;
|
||||||
|
datalen = 5;
|
||||||
|
} else {
|
||||||
|
datalen = DOWNSTREAM_HDR + f->len;
|
||||||
|
if (datalen > sizeof(pkt)) {
|
||||||
|
warnx("send_frag_or_dataless: fragment too large to send!");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc);
|
memcpy(&pkt, f->data, f->len);
|
||||||
|
}
|
||||||
|
write_dns(dns_fd, q, (char *)pkt, datalen, users[userid].downenc);
|
||||||
|
|
||||||
if (q->id2 != 0) {
|
if (q->id2 != 0) { /* reply to any duplicates */
|
||||||
q->id = q->id2;
|
q->id = q->id2;
|
||||||
q->fromlen = q->fromlen2;
|
q->fromlen = q->fromlen2;
|
||||||
memcpy(&(q->from), &(q->from2), q->fromlen2);
|
memcpy(&(q->from), &(q->from2), q->fromlen2);
|
||||||
if (debug >= 1)
|
if (debug >= 1)
|
||||||
warnx("OUT again to last duplicate");
|
warnx("OUT again to last duplicate");
|
||||||
write_dns(dns_fd, q, pkt, datalen + 2, users[userid].downenc);
|
write_dns(dns_fd, q, (char *)pkt, datalen, users[userid].downenc);
|
||||||
}
|
}
|
||||||
|
|
||||||
save_to_qmem_pingordata(userid, q);
|
save_to_qmem_pingordata(userid, q);
|
||||||
|
|
||||||
#ifdef DNSCACHE_LEN
|
#ifdef DNSCACHE_LEN
|
||||||
save_to_dnscache(userid, q, pkt, datalen + 2);
|
save_to_dnscache(userid, q, (char *)pkt, datalen + 2);
|
||||||
#endif
|
#endif
|
||||||
|
/* this query has been */
|
||||||
|
q->id = 0;
|
||||||
|
window_tick(out);
|
||||||
|
|
||||||
q->id = 0; /* this query is used */
|
/* call again if we have more things to send */
|
||||||
|
return users[userid].outgoing->numitems > 0;
|
||||||
return 0; /* don't call us again */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -446,6 +486,7 @@ send_version_response(int fd, version_ack_t ack, uint32_t payload, int userid, s
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use htonl for compatibility with big-endian systems
|
||||||
out[4] = ((payload >> 24) & 0xff);
|
out[4] = ((payload >> 24) & 0xff);
|
||||||
out[5] = ((payload >> 16) & 0xff);
|
out[5] = ((payload >> 16) & 0xff);
|
||||||
out[6] = ((payload >> 8) & 0xff);
|
out[6] = ((payload >> 8) & 0xff);
|
||||||
@ -526,7 +567,7 @@ tunnel_tun(int tun_fd, struct dnsfd *dns_fds)
|
|||||||
|
|
||||||
if (users[userid].conn == CONN_DNS_NULL) {
|
if (users[userid].conn == CONN_DNS_NULL) {
|
||||||
|
|
||||||
start_new_outpacket(userid, out, outlen);
|
window_add_outgoing_data(users[userid].outgoing, out, outlen, 1);
|
||||||
|
|
||||||
/* Start sending immediately if query is waiting */
|
/* Start sending immediately if query is waiting */
|
||||||
if (users[userid].q_sendrealsoon.id != 0) {
|
if (users[userid].q_sendrealsoon.id != 0) {
|
||||||
@ -633,15 +674,14 @@ server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
|||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
/* Adjust timeout if there is anything to send realsoon.
|
/* Adjust timeout if there is anything to send realsoon.
|
||||||
Clients won't be sending new data until we send our ack,
|
Clients won't be sending new data until we send our ack, TODO: adjust stuff in this function
|
||||||
so don't keep them waiting long. This only triggers at
|
so don't keep them waiting long. This only triggers at
|
||||||
final upstream fragments, which is about once per eight
|
final upstream fragments, which is about once per eight
|
||||||
requests during heavy upstream traffic.
|
requests during heavy upstream traffic.
|
||||||
20msec: ~8 packs every 1/50sec = ~400 DNSreq/sec,
|
20msec: ~8 packets every 1/50sec = ~400 DNSreq/sec,
|
||||||
or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */
|
or ~1200bytes every 1/50sec = ~0.5 Mbit/sec upstream */
|
||||||
for (userid = 0; userid < created_users; userid++) {
|
for (userid = 0; userid < created_users; userid++) {
|
||||||
if (users[userid].active && !users[userid].disabled &&
|
if (user_active(userid)) {
|
||||||
users[userid].last_pkt + 60 > time(NULL)) {
|
|
||||||
users[userid].q_sendrealsoon_new = 0;
|
users[userid].q_sendrealsoon_new = 0;
|
||||||
if (users[userid].q_sendrealsoon.id != 0) {
|
if (users[userid].q_sendrealsoon.id != 0) {
|
||||||
tv.tv_sec = 0;
|
tv.tv_sec = 0;
|
||||||
@ -683,7 +723,7 @@ server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i==0) {
|
if (i == 0) {
|
||||||
if (max_idle_time) {
|
if (max_idle_time) {
|
||||||
/* only trigger the check if that's worth ( ie, no need to loop over if there
|
/* only trigger the check if that's worth ( ie, no need to loop over if there
|
||||||
is something to send */
|
is something to send */
|
||||||
@ -714,11 +754,8 @@ server_tunnel(int tun_fd, struct dnsfd *dns_fds, int bind_fd, int max_idle_time)
|
|||||||
|
|
||||||
/* Send realsoon's if tun or dns didn't already */
|
/* Send realsoon's if tun or dns didn't already */
|
||||||
for (userid = 0; userid < created_users; userid++)
|
for (userid = 0; userid < created_users; userid++)
|
||||||
if (users[userid].active && !users[userid].disabled &&
|
if (user_active(userid) && users[userid].q_sendrealsoon.id != 0 &&
|
||||||
users[userid].last_pkt + 60 > time(NULL) &&
|
users[userid].conn == CONN_DNS_NULL && !users[userid].q_sendrealsoon_new) {
|
||||||
users[userid].q_sendrealsoon.id != 0 &&
|
|
||||||
users[userid].conn == CONN_DNS_NULL &&
|
|
||||||
!users[userid].q_sendrealsoon_new) {
|
|
||||||
int dns_fd = get_dns_fd(dns_fds, &users[userid].q_sendrealsoon.from);
|
int dns_fd = get_dns_fd(dns_fds, &users[userid].q_sendrealsoon.from);
|
||||||
send_frag_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon);
|
send_frag_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon);
|
||||||
}
|
}
|
||||||
@ -749,7 +786,7 @@ handle_full_packet(int tun_fd, struct dnsfd *dns_fds, int userid, uint8_t *data,
|
|||||||
/* send the compressed(!) packet to other client */
|
/* send the compressed(!) packet to other client */
|
||||||
if (users[touser].conn == CONN_DNS_NULL) {
|
if (users[touser].conn == CONN_DNS_NULL) {
|
||||||
if (window_buffer_available(users[touser].outgoing) * users[touser].outgoing->maxfraglen >= len) {
|
if (window_buffer_available(users[touser].outgoing) * users[touser].outgoing->maxfraglen >= len) {
|
||||||
start_new_outpacket(touser, data, len);
|
window_add_outgoing_data(users[touser].outgoing, data, len, 1);
|
||||||
|
|
||||||
/* Start sending immediately if query is waiting */
|
/* Start sending immediately if query is waiting */
|
||||||
if (users[touser].q_sendrealsoon.id != 0) {
|
if (users[touser].q_sendrealsoon.id != 0) {
|
||||||
@ -781,9 +818,7 @@ handle_raw_login(uint8_t *packet, size_t len, struct query *q, int fd, int useri
|
|||||||
/* can't use check_authenticated_user_and_ip() since IP address will be different,
|
/* can't use check_authenticated_user_and_ip() since IP address will be different,
|
||||||
so duplicate here except IP address */
|
so duplicate here except IP address */
|
||||||
if (userid < 0 || userid >= created_users) return;
|
if (userid < 0 || userid >= created_users) return;
|
||||||
if (!users[userid].active || users[userid].disabled) return;
|
if (!check_authenticated_user_and_ip(userid, q)) return;
|
||||||
if (!users[userid].authenticated) return;
|
|
||||||
if (users[userid].last_pkt + 60 < time(NULL)) return;
|
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
fprintf(stderr, "IN login raw, len %lu, from user %d\n", len, userid);
|
fprintf(stderr, "IN login raw, len %lu, from user %d\n", len, userid);
|
||||||
@ -1128,10 +1163,10 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
char in[512];
|
char in[512];
|
||||||
char logindata[16];
|
char logindata[16];
|
||||||
char out[64*1024];
|
char out[64*1024];
|
||||||
char unpacked[64*1024];
|
static char unpacked[64*1024];
|
||||||
char *tmp[2];
|
char *tmp[2];
|
||||||
int userid;
|
int userid;
|
||||||
int read;
|
size_t read;
|
||||||
|
|
||||||
userid = -1;
|
userid = -1;
|
||||||
|
|
||||||
@ -1181,6 +1216,7 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
// TODO: client specified window size
|
// TODO: client specified window size
|
||||||
users[userid].incoming = window_buffer_init(128, 10, MAX_FRAGSIZE, WINDOW_RECVING);
|
users[userid].incoming = window_buffer_init(128, 10, MAX_FRAGSIZE, WINDOW_RECVING);
|
||||||
users[userid].outgoing = window_buffer_init(16, 10, users[userid].fragsize, WINDOW_SENDING);
|
users[userid].outgoing = window_buffer_init(16, 10, users[userid].fragsize, WINDOW_SENDING);
|
||||||
|
users[userid].next_upstream_ack = -1;
|
||||||
#ifdef DNSCACHE_LEN
|
#ifdef DNSCACHE_LEN
|
||||||
{
|
{
|
||||||
for (i = 0; i < DNSCACHE_LEN; i++) {
|
for (i = 0; i < DNSCACHE_LEN; i++) {
|
||||||
@ -1517,9 +1553,9 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if(in[0] == 'P' || in[0] == 'p') {
|
} else if(in[0] == 'P' || in[0] == 'p') {
|
||||||
int dn_seq;
|
int dn_seq, up_seq, dn_wins, up_wins;
|
||||||
int dn_frag;
|
|
||||||
int didsend = 0;
|
int didsend = 0;
|
||||||
|
int respond;
|
||||||
|
|
||||||
/* We can't handle id=0, that's "no packet" to us. So drop
|
/* We can't handle id=0, that's "no packet" to us. So drop
|
||||||
request completely. Note that DNS servers rewrite the id.
|
request completely. Note that DNS servers rewrite the id.
|
||||||
@ -1531,7 +1567,7 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
|
read = unpack_data(unpacked, sizeof(unpacked), &(in[1]), domain_len - 1, b32);
|
||||||
if (read < 4)
|
if (read < 7)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Ping packet, store userid */
|
/* Ping packet, store userid */
|
||||||
@ -1591,22 +1627,22 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO new ping header
|
dn_seq = unpacked[1];
|
||||||
dn_seq = unpacked[1] >> 4;
|
up_seq = unpacked[2];
|
||||||
dn_frag = unpacked[1] & 15;
|
up_wins = unpacked[3];
|
||||||
|
dn_wins = unpacked[4];
|
||||||
|
respond = unpacked[5] & 1;
|
||||||
|
|
||||||
if (debug >= 1) {
|
if (debug >= 1) {
|
||||||
fprintf(stderr, "PING pkt from user %d, ack for downstream %d/%d\n",
|
fprintf(stderr, "PING pkt from user %d, down %d/%d, up %d/%d\n", userid, dn_seq, dn_wins, up_seq, up_wins);
|
||||||
userid, dn_seq, dn_frag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: process incoming ACK for downstream data
|
|
||||||
|
|
||||||
/* If there is a query that must be returned real soon, do it.
|
/* If there is a query that must be returned real soon, do it.
|
||||||
May contain new downstream data if the ping had a new ack.
|
May contain new downstream data if the ping had a new ack.
|
||||||
Otherwise, may also be re-sending old data. */
|
Otherwise, may also be re-sending old data. */
|
||||||
if (users[userid].q_sendrealsoon.id != 0) {
|
if (users[userid].q_sendrealsoon.id != 0) {
|
||||||
send_frag_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon);
|
if (respond) send_ping_response(dns_fd, userid, &users[userid].q_sendrealsoon);
|
||||||
|
else send_frag_or_dataless(dns_fd, userid, &users[userid].q_sendrealsoon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need to store a new query, so if there still is an
|
/* We need to store a new query, so if there still is an
|
||||||
@ -1616,6 +1652,9 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
(This is duplicate data if we had q_sendrealsoon above.) */
|
(This is duplicate data if we had q_sendrealsoon above.) */
|
||||||
if (users[userid].q.id != 0) {
|
if (users[userid].q.id != 0) {
|
||||||
didsend = 1;
|
didsend = 1;
|
||||||
|
if (respond)
|
||||||
|
send_ping_response(dns_fd, userid, &users[userid].q);
|
||||||
|
else
|
||||||
if (send_frag_or_dataless(dns_fd, userid, &users[userid].q) == 1)
|
if (send_frag_or_dataless(dns_fd, userid, &users[userid].q) == 1)
|
||||||
/* new packet from queue, send immediately */
|
/* new packet from queue, send immediately */
|
||||||
didsend = 0;
|
didsend = 0;
|
||||||
@ -1634,9 +1673,9 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
} else if((in[0] >= '0' && in[0] <= '9') /* Data packet */
|
} else if((in[0] >= '0' && in[0] <= '9') /* Data packet */
|
||||||
|| (in[0] >= 'a' && in[0] <= 'f')
|
|| (in[0] >= 'a' && in[0] <= 'f')
|
||||||
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
|| (in[0] >= 'A' && in[0] <= 'F')) {
|
||||||
int upstream_ok = 1;
|
|
||||||
int didsend = 0;
|
int didsend = 0;
|
||||||
int code = -1;
|
int code = -1;
|
||||||
|
static fragment f;
|
||||||
|
|
||||||
/* Need 6 char header + >=1 char data */
|
/* Need 6 char header + >=1 char data */
|
||||||
if (domain_len < 7)
|
if (domain_len < 7)
|
||||||
@ -1705,42 +1744,43 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
}
|
}
|
||||||
users[userid].q_sendrealsoon.id2 = q->id;
|
users[userid].q_sendrealsoon.id2 = q->id;
|
||||||
users[userid].q_sendrealsoon.fromlen2 = q->fromlen;
|
users[userid].q_sendrealsoon.fromlen2 = q->fromlen;
|
||||||
memcpy(&(users[userid].q_sendrealsoon.from2),
|
memcpy(&(users[userid].q_sendrealsoon.from2), &(q->from), q->fromlen);
|
||||||
&(q->from), q->fromlen);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Decode data header */
|
/* Decode upstream data header - see docs/proto_XXXXXXXX.txt */
|
||||||
// up_seq = (b32_8to5(in[1]) >> 2) & 7;
|
/* First byte (after userid) = CMC (ignored?) */
|
||||||
// up_frag = ((b32_8to5(in[1]) & 3) << 2) | ((b32_8to5(in[2]) >> 3) & 3);
|
f.seqID = (b32_8to5(in[2]) << 2) | (b32_8to5(in[3]) >> 2);
|
||||||
// dn_seq = (b32_8to5(in[2]) & 7);
|
f.ack_other = (b32_8to5(in[5]) & 8) ? ((b32_8to5(in[3]) & 3) << 6)
|
||||||
// dn_frag = b32_8to5(in[3]) >> 1;
|
| (b32_8to5(in[4]) << 1) | (b32_8to5(in[5]) & 1) : -1;
|
||||||
// lastfrag = b32_8to5(in[3]) & 1; TODO: new data header
|
f.is_nack = (b32_8to5(in[5]) >> 2) & 1;
|
||||||
|
f.start = (b32_8to5(in[5]) >> 1) & 1;
|
||||||
|
f.end = b32_8to5(in[5]) & 1;
|
||||||
|
|
||||||
// TODO: handle following scenarios
|
/* Decode remainder of data with user encoding */
|
||||||
/* Got repeated old packet _with data_, probably
|
read = unpack_data(unpacked, sizeof(unpacked), in + UPSTREAM_HDR,
|
||||||
because client didn't receive our ack. So re-send
|
domain_len - UPSTREAM_HDR, users[userid].encoder);
|
||||||
our ack(+data) immediately to keep things flowing
|
|
||||||
fast.
|
|
||||||
If it's a _really_ old frag, it's a nameserver
|
|
||||||
that tries again, and sending our current (non-
|
|
||||||
matching) fragno won't be a problem. */
|
|
||||||
|
|
||||||
/* Duplicate of recent upstream data packet; probably
|
f.len = MIN(read, MAX_FRAGSIZE);
|
||||||
need to answer this to keep DNS server happy */
|
memcpy(f.data, unpacked, read);
|
||||||
// upstream_ok = 0;
|
|
||||||
|
|
||||||
/* Really new packet has arrived, no recent duplicate */
|
window_process_incoming_fragment(users[userid].incoming, &f);
|
||||||
/* Forget any old packet, even if incomplete */
|
|
||||||
|
|
||||||
if (upstream_ok) {
|
window_ack(users[userid].outgoing, f.ack_other);
|
||||||
/* decode with this user's encoding */
|
|
||||||
read = unpack_data(unpacked, sizeof(unpacked), &(in[UPSTREAM_HDR]),
|
/* if waiting for an ACK to be sent back upstream (on incoming buffer) */
|
||||||
domain_len - 5, users[userid].encoder);
|
if (users[userid].next_upstream_ack < 0) {
|
||||||
// TODO append fragment to window
|
users[userid].next_upstream_ack = window_get_next_ack(users[userid].incoming);
|
||||||
}
|
}
|
||||||
// TODO reassemble data
|
|
||||||
|
read = window_reassemble_data(users[userid].incoming, (uint8_t *)unpacked, sizeof(unpacked), NULL);
|
||||||
|
|
||||||
|
if (read > 0) { /* Data reassembled successfully + cleared out of buffer */
|
||||||
|
handle_full_packet(tun_fd, dns_fds, userid, (uint8_t *)unpacked, read);
|
||||||
|
}
|
||||||
|
|
||||||
|
window_tick(users[userid].incoming);
|
||||||
|
|
||||||
/* If there is a query that must be returned real soon, do it.
|
/* If there is a query that must be returned real soon, do it.
|
||||||
Includes an ack of the just received upstream fragment,
|
Includes an ack of the just received upstream fragment,
|
||||||
@ -1801,13 +1841,9 @@ handle_null_request(int tun_fd, int dns_fd, struct dnsfd *dns_fds, struct query
|
|||||||
if (!didsend) // TODO: also check if sending
|
if (!didsend) // TODO: also check if sending
|
||||||
send_frag_or_dataless(dns_fd, userid, &users[userid].q);
|
send_frag_or_dataless(dns_fd, userid, &users[userid].q);
|
||||||
else if (!didsend || !users[userid].lazy) {
|
else if (!didsend || !users[userid].lazy) {
|
||||||
if (upstream_ok) { /* rotate pending queries */
|
|
||||||
memcpy(&(users[userid].q_sendrealsoon), &(users[userid].q), sizeof(struct query));
|
memcpy(&(users[userid].q_sendrealsoon), &(users[userid].q), sizeof(struct query));
|
||||||
users[userid].q_sendrealsoon_new = 1;
|
users[userid].q_sendrealsoon_new = 1;
|
||||||
users[userid].q.id = 0; /* used */
|
users[userid].q.id = 0; /* used */
|
||||||
} else {
|
|
||||||
send_frag_or_dataless(dns_fd, userid, &users[userid].q);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user