Skip to content

Commit

Permalink
Merge pull request #61 from hamishcoleman/main
Browse files Browse the repository at this point in the history
Handle more TCP edge cases
  • Loading branch information
hamishcoleman authored Dec 16, 2024
2 parents b0b6944 + 73d198a commit 91c05f0
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 30 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/quick.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ jobs:

smoketest_all_opts:
name: Smoke test With all options turned on
runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:
- name: Generate coverage reports
run: |
make gcov
make cover COVERAGEDIR=coverage/ubuntu-latest
make cover COVERAGEDIR=coverage/ubuntu-22.04
shell: bash

- name: Upload gcovr report artifact
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:

lint:
name: Code syntax
runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v4
Expand Down
46 changes: 46 additions & 0 deletions doc/Containerfile.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#
# A simple example of how to build a docker container for n3n-edge
#
# Build with the command:
# podman build \
# --device=/dev/net/tun \
# --cap-add=NET_ADMIN \
# -t=n3n \
# -f doc/Containerfile.example \
# .
#
# Start a n3n session with:
# podman run \
# -it \
# --name=n3n \
# --device=/dev/net/tun \
# --cap-add=NET_ADMIN \
# -v $PWD/n3n:/etc/n3n/ \
# n3n start -vvvv
#
# Note that the build could be done without the --device and --cap-add if
# the `make test` is omitted

FROM docker.io/library/debian:12 AS builder

RUN apt-get update
RUN apt-get install -y build-essential autoconf git python3 jq sudo

WORKDIR /n3n

COPY . .

RUN \
./autogen.sh && \
./configure && \
make clean all && \
make test


FROM docker.io/library/debian:12

COPY --from=builder /n3n/apps/n3n-edge /n3n-edge

VOLUME [ "/etc/n3n" ]
ENTRYPOINT ["/n3n-edge"]
CMD ["start"]
39 changes: 25 additions & 14 deletions libs/connslot/connslot.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ void conn_check_ready(conn_t *conn) {
return;
}

void conn_read(conn_t *conn, int fd) {
ssize_t conn_read(conn_t *conn, int fd) {
conn->state = CONN_READING;

// If no space available, try increasing our capacity
Expand All @@ -195,28 +195,26 @@ void conn_read(conn_t *conn, int fd) {
// zero-sized read request, the only time we get a zero back is if the
// far end has closed
conn->state = CONN_CLOSED;
return;
return 0;
}

if (size == -1) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
conn->state = CONN_EMPTY;
return;
return 0;
}
conn->state = CONN_ERROR;
return;
return 0;
}

// This will truncate the time to a int - usually 32bits
conn->activity = time(NULL);
conn_check_ready(conn);
return size;
}

ssize_t conn_write(conn_t *conn, int fd) {
ssize_t sent;

conn->state = CONN_SENDING;

if (fd == -1) {
return 0;
}
Expand Down Expand Up @@ -267,11 +265,17 @@ ssize_t conn_write(conn_t *conn, int fd) {
unsigned int end_pos = sb_len(conn->reply_header) + sb_len(conn->reply);
#endif

if (sent == -1) {
sent = 0;
if (errno != EAGAIN && errno != EWOULDBLOCK) {
conn->state = CONN_ERROR;
}
}

conn->reply_sendpos += sent;

if (conn->reply_sendpos >= end_pos) {
// We have sent the last bytes of this reply
conn->state = CONN_EMPTY;
conn->reply_sendpos = 0;
sb_zero(conn->reply_header);
sb_zero(conn->reply);
Expand All @@ -282,13 +286,20 @@ ssize_t conn_write(conn_t *conn, int fd) {
return sent;
}

int conn_iswriter(conn_t *conn) {
switch (conn->state) {
case CONN_SENDING:
return 1;
default:
return 0;
bool conn_iswriter(conn_t *conn) {
int endpos = 0;
if (conn->reply_header) {
endpos += sb_len(conn->reply_header);
}
if (conn->reply) {
endpos += sb_len(conn->reply);
}

// If there are any bytes ready to send, then we are writable
if(endpos) {
return true;
}
return false;
}

void conn_close(conn_t *conn, int fd) {
Expand Down
5 changes: 2 additions & 3 deletions libs/connslot/connslot.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ enum __attribute__((__packed__)) conn_state {
CONN_EMPTY = 0,
CONN_READING = 1,
CONN_READY = 2,
CONN_SENDING = 3,
CONN_CLOSED = 4,
CONN_ERROR = 5,
};
Expand Down Expand Up @@ -64,9 +63,9 @@ void conn_zero(conn_t *);
int conn_init(conn_t *, size_t, size_t);
void conn_accept(conn_t *, int, enum conn_proto);
void conn_check_ready(conn_t *);
void conn_read(conn_t *, int);
ssize_t conn_read(conn_t *, int);
ssize_t conn_write(conn_t *, int);
int conn_iswriter(conn_t *);
bool conn_iswriter(conn_t *);
void conn_close(conn_t *, int);
bool conn_closeidle(conn_t *, int, int, int);
void conn_dump(strbuf_t **, conn_t *);
Expand Down
12 changes: 7 additions & 5 deletions src/edge_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1630,11 +1630,13 @@ void update_supernode_reg (struct n3n_runtime_data * eee, time_t now) {
if(eee->conf.bind_address) {
// do not explicitly disconnect every time as the condition described is rare, so ...
// ... check that there are no external peers (indicating a working socket) ...
HASH_ITER(hh, eee->known_peers, peer, tmp_peer)
if(!peer->local) {
cnt++;
break;
HASH_ITER(hh, eee->known_peers, peer, tmp_peer) {
if(!peer->local) {
cnt++;
break;
}
}

if(!cnt) {
// ... and then count the connection retries
(eee->close_socket_counter)++;
Expand Down Expand Up @@ -2297,7 +2299,7 @@ void process_udp (struct n3n_runtime_data *eee,
via_multicast = (in_sock == eee->udp_multicast_sock);
#endif

traceEvent(TRACE_DEBUG, "Rx N2N_UDP of size %d from [%s]",
traceEvent(TRACE_DEBUG, "Rx VPN packet of size %d from [%s]",
(signed int)udp_size, sock_to_cstr(sockbuf1, &sender));

if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) {
Expand Down
6 changes: 4 additions & 2 deletions src/mainloop.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ static int fdlist_allocslot (int fd, enum fd_info_proto proto) {

static void fdlist_freefd (int fd) {
int slot = 0;
if(fd == -1) {
// Cannot release an error fd!
return;
}
while(slot < MAX_HANDLES) {
if(fdlist[slot].fd != fd) {
slot++;
Expand Down Expand Up @@ -331,7 +335,6 @@ static void handle_fd (const time_t now, const struct fd_info info, struct n3n_r
switch(conn->state) {
case CONN_EMPTY:
case CONN_READING:
case CONN_SENDING:
// These states dont require us to do anything
// TODO:
// - handle reading/sending simultaneous?
Expand Down Expand Up @@ -402,7 +405,6 @@ static void handle_fd (const time_t now, const struct fd_info info, struct n3n_r
switch(conn->state) {
case CONN_EMPTY:
case CONN_READING:
case CONN_SENDING:
// These states dont require us to do anything
// TODO:
// - handle reading/sending simultaneous?
Expand Down
35 changes: 34 additions & 1 deletion src/n2n.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,41 @@ SOCKET open_socket (struct sockaddr *local_address, socklen_t addrlen, int type
/* fcntl(sock_fd, F_SETFL, O_NONBLOCK); */
#endif

int result;

sockopt = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt));
result = setsockopt(
sock_fd,
SOL_SOCKET,
SO_REUSEADDR,
(char *)&sockopt,
sizeof(sockopt)
);
if(result == -1) {
traceEvent(
TRACE_ERROR,
"SO_REUSEADDR fd=%i, error=%s\n",
sock_fd,
strerror(errno)
);
}
#ifdef SO_REUSEPORT /* no SO_REUSEPORT in Windows / old linux versions */
result = setsockopt(
sock_fd,
SOL_SOCKET,
SO_REUSEPORT,
(char *)&sockopt,
sizeof(sockopt)
);
if(result == -1) {
traceEvent(
TRACE_ERROR,
"SO_REUSEPORT fd=%i, error=%s\n",
sock_fd,
strerror(errno)
);
}
#endif

if(!local_address) {
// skip binding if we dont have the right details
Expand Down
10 changes: 8 additions & 2 deletions tools/crypto_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ static void cmd_header_decrypt (int argc, char **argv, void *conf) {
exit(1);
}

write(1, &buf, size);
int r = write(1, &buf, size);
if(r != size) {
printf("Short write\n");
}
exit(0);

}
Expand Down Expand Up @@ -130,7 +133,10 @@ static void cmd_pearson_128 (int argc, char **argv, void *conf) {
unsigned char hash[16];
size = read(0, &buf, sizeof(buf));
pearson_hash_128(hash, buf, size);
write(1, &hash, sizeof(hash));
int r = write(1, &hash, sizeof(hash));
if(r != sizeof(hash)) {
printf("Short write\n");
}
exit(0);
}

Expand Down

0 comments on commit 91c05f0

Please sign in to comment.