Skip to content

Commit

Permalink
Merge pull request #7 from trekawek/events
Browse files Browse the repository at this point in the history
Support native event mechanisms on BSD and Linux.
  • Loading branch information
tschak909 authored Jul 7, 2024
2 parents 993fbcb + f7af3a0 commit caf45f5
Show file tree
Hide file tree
Showing 14 changed files with 341 additions and 53 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin
src/*.o
15 changes: 11 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
FROM ubuntu:latest AS build
RUN apt update && apt install -y build-essential
WORKDIR /src
COPY src/* .
RUN make clean all OS=LINUX

FROM ubuntu:latest
MAINTAINER Thomas Cherryhomes <[email protected]>
LABEL org.opencontainers.image.authors="[email protected]"
EXPOSE 16384
EXPOSE 16384/udp
VOLUME /data
ADD bin/tnfsd /bin
RUN chmod +x /bin/tnfsd
ENTRYPOINT ["/bin/tnfsd","/data"]
COPY --from=build /bin/tnfsd /bin/tnfsd

ENTRYPOINT ["/bin/tnfsd", "/data"]
8 changes: 4 additions & 4 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ endif

ifeq ($(OS),LINUX)
FLAGS = -Wall -DUNIX -DNEED_BSDCOMPAT -DENABLE_CHROOT -DNEED_ERRTABLE
EXOBJS = strlcpy.o strlcat.o
EXOBJS = strlcpy.o strlcat.o event_epoll.o
LIBS =
EXEC = tnfsd
endif
ifeq ($(OS),Windows_NT)
FLAGS = -Wall -DWIN32 -DNEED_ERRTABLE -DNEED_BSDCOMPAT
EXOBJS = strlcpy.o strlcat.o
EXOBJS = strlcpy.o strlcat.o event_select.o
LIBS = -lwsock32
EXEC = tnfsd.exe
endif
ifeq ($(OS),BSD)
FLAGS = -Wall -DUNIX -DENABLE_CHROOT -DNEED_ERRTABLE
EXOBJS =
EXOBJS = event_kqueue.o
LIBS =
EXEC = tnfsd
endif
Expand All @@ -32,7 +32,7 @@ ifdef USAGELOG
endif

CFLAGS=$(FLAGS) $(EXFLAGS) $(LOGFLAGS)
OBJS=main.o datagram.o log.o session.o endian.o directory.o errortable.o tnfs_file.o chroot.o fileinfo.o stats.o $(EXOBJS)
OBJS=main.o datagram.o event_common.o log.o session.o endian.o directory.o errortable.o tnfs_file.o chroot.o fileinfo.o stats.o $(EXOBJS)

all: $(OBJS)
$(CC) -o ../bin/$(EXEC) $(OBJS) $(LIBS)
Expand Down
2 changes: 1 addition & 1 deletion src/chroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void chroot_tnfs(const char *user, const char *group, const char *newroot)

void warn_if_root(void)
{
if((getuid() == 0) | (getgid() == 0))
if((getuid() == 0) || (getgid() == 0))
fprintf(stderr, "WARNING: running as root.\nConsider running tnfsd jailed with -u user -g group\n");
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#define MAX_DHND_PER_CONN 8 /* max open directories per client */
#define MAX_SESSIONS 4096 /* maximum number of opened sessions */
#define MAX_SESSIONS_PER_IP 4096 /* maximum number of sessions from a single IP */
#define MAX_TCP_CONN 1022 /* maximum number of TCP connections */
#define MAX_TCP_CONN 4096 /* maximum number of TCP connections */
#define SESSION_TIMEOUT 21600 /* Sessions are thrown out after no contact for this many seconds. 0 = no timeout */
#define TNFS_HEADERSZ 4 /* minimum header size */
#define TNFS_MAX_PAYLOAD (MAXMSGSZ - TNFS_HEADERSZ - 1) /* Maximum usuable payload in a UDP datagram (-1 for status byte) */
Expand Down
72 changes: 35 additions & 37 deletions src/datagram.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ TNFS daemon datagram handler
#ifdef UNIX
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#define SOCKET_ERROR -1
#endif

#ifdef WIN32
Expand All @@ -52,6 +50,7 @@ TNFS daemon datagram handler
#include "errortable.h"
#include "directory.h"
#include "tnfs_file.h"
#include "event.h"

int sockfd; /* UDP global socket file descriptor */
int tcplistenfd; /* TCP listening socket file descriptor */
Expand Down Expand Up @@ -174,54 +173,40 @@ void tnfs_sockinit(int port)

void tnfs_mainloop()
{
int readyfds, i;
fd_set fdset;
fd_set errfdset;
int i;
TcpConnection tcpsocks[MAX_TCP_CONN];
struct timeval select_timeout;
time_t last_stats_report = 0;
time_t now = 0;

memset(&tcpsocks, 0, sizeof(tcpsocks));

/* add UDP socket and TCP listen socket to event listener */
tnfs_event_register(sockfd);
tnfs_event_register(tcplistenfd);

while (1)
{
FD_ZERO(&fdset);

/* add UDP socket and TCP listen socket to fdset */
FD_SET(sockfd, &fdset);
FD_SET(tcplistenfd, &fdset);

for (i = 0; i < MAX_TCP_CONN; i++)
event_wait_res_t *wait_res = tnfs_event_wait(1);
if (wait_res->size == SOCKET_ERROR)
{
if (tcpsocks[i].cli_fd)
{
FD_SET(tcpsocks[i].cli_fd, &fdset);
}
}

FD_COPY(&fdset, &errfdset);
select_timeout.tv_sec = 1;

readyfds = select(FD_SETSIZE, &fdset, NULL, &errfdset, &select_timeout);
if (readyfds == SOCKET_ERROR) {
LOG("tnfs_mainloop: select failed\n");
break;
}

if (readyfds == 0) {
if (wait_res->size == 0)
{
// Just a normal timeout, reloop
continue;
}

/* UDP message? */
if (FD_ISSET(sockfd, &fdset))
if (tnfs_event_is_active(wait_res, sockfd))
{
tnfs_handle_udpmsg();
}

/* Incoming TCP connection? */
if (FD_ISSET(tcplistenfd, &fdset))
if (tnfs_event_is_active(wait_res, tcplistenfd))
{
tcp_accept(&tcpsocks[0]);
}
Expand All @@ -231,7 +216,7 @@ void tnfs_mainloop()
{
if (tcpsocks[i].cli_fd)
{
if (FD_ISSET(tcpsocks[i].cli_fd, &fdset))
if (tnfs_event_is_active(wait_res, tcpsocks[i].cli_fd))
{
tnfs_handle_tcpmsg(&tcpsocks[i]);
}
Expand Down Expand Up @@ -269,17 +254,26 @@ void tcp_accept(TcpConnection *tcp_conn_list)
return;
}

tcp_conn = tcp_conn_list;
for (i = 0; i < MAX_TCP_CONN; i++)
bool event_registered = false;
if (tnfs_event_register(acc_fd))
{
if (tcp_conn->cli_fd == 0)
event_registered = true;
tcp_conn = tcp_conn_list;
for (i = 0; i < MAX_TCP_CONN; i++)
{
MSGLOG(cliaddr.sin_addr.s_addr, "New TCP connection at index %d.", i);
tcp_conn->cli_fd = acc_fd;
tcp_conn->cliaddr = cliaddr;
return;
if (tcp_conn->cli_fd == 0)
{
MSGLOG(cliaddr.sin_addr.s_addr, "New TCP connection at index %d.", i);
tcp_conn->cli_fd = acc_fd;
tcp_conn->cliaddr = cliaddr;
return;
}
tcp_conn++;
}
tcp_conn++;
}
if (event_registered)
{
tnfs_event_unregister(acc_fd);
}

MSGLOG(cliaddr.sin_addr.s_addr, "Can't accept client; too many connections.");
Expand All @@ -300,7 +294,11 @@ void tcp_accept(TcpConnection *tcp_conn_list)

void tnfs_handle_udpmsg()
{
#ifdef WIN32
int len;
#else
socklen_t len;
#endif
int rxbytes;
struct sockaddr_in cliaddr;
unsigned char rxbuf[MAXMSGSZ];
Expand Down Expand Up @@ -349,7 +347,7 @@ void tnfs_handle_tcpmsg(TcpConnection *tcp_conn)
#else
close(tcp_conn->cli_fd);
#endif

tnfs_event_unregister(tcp_conn->cli_fd);
tcp_conn->cli_fd = 0;
return;
}
Expand Down
5 changes: 0 additions & 5 deletions src/datagram.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@
#define in_addr_t uint32_t
#endif

/* definition of FD_COPY macro used in OpenBSD */
#ifndef FD_COPY
#define FD_COPY(f, t) memcpy(t, f, sizeof(*(f)))
#endif

#include "stats.h"
#include "tnfs.h"

Expand Down
2 changes: 1 addition & 1 deletion src/directory.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ int _load_directory(dir_handle *dirh, uint8_t diropts, uint8_t sortopts, uint16_
{
struct dirent *entry;
char statpath[MAX_TNFSPATH];
char temp_statpath[MAX_TNFSPATH*2];
char temp_statpath[MAX_TNFSPATH*2 + 4];

// Free any existing entries
dirlist_free(dirh->entry_list);
Expand Down
36 changes: 36 additions & 0 deletions src/event.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef _EVENT_H
#define _EVENT_H

#include <stdbool.h>

#ifndef SOCKET_ERROR
#define SOCKET_ERROR -1
#endif

struct event_wait_res
{
int *fds;
int size;
};
typedef struct event_wait_res event_wait_res_t;

// Initializes the event queue.
void tnfs_event_init();

// Registers the file descriptor to watch.
bool tnfs_event_register(int fd);

// Unregisters the file descriptor.
void tnfs_event_unregister(int fd);

// Waits for a given amount of time for an event on any registered file descriptor.
// Returns the file descriptor number of 0 if timeout occurs.
event_wait_res_t* tnfs_event_wait(int timeout_sec);

// Returns
bool tnfs_event_is_active(event_wait_res_t* res, int fds);

// Closes the event queue.
void tnfs_event_close();

#endif
13 changes: 13 additions & 0 deletions src/event_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include "event.h"

bool tnfs_event_is_active(event_wait_res_t* res, int fds)
{
for (int i = 0; i < res->size; i++)
{
if (res->fds[i] == fds)
{
return true;
}
}
return false;
}
66 changes: 66 additions & 0 deletions src/event_epoll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "event.h"
#include "log.h"

#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <unistd.h>

#define _EVENT_MAX_FDS 4096

struct epoll_event events[_EVENT_MAX_FDS];
int epfd;
event_wait_res_t wait_result;

void tnfs_event_init()
{
epfd = epoll_create(1);
wait_result.fds = calloc(_EVENT_MAX_FDS, sizeof(int));
}

bool tnfs_event_register(int fd)
{
struct epoll_event ev;
ev.events = EPOLLIN | EPOLLET | EPOLLRDHUP;
ev.data.fd = fd;

if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
{
LOG("tnfs_event_register: can't register epoll descriptor\n");
return false;
}
return true;
}

void tnfs_event_unregister(int fd)
{
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);
}

event_wait_res_t* tnfs_event_wait(int timeout_sec)
{
int readyfds = epoll_wait(epfd, events, _EVENT_MAX_FDS, timeout_sec * 1000);

wait_result.size = readyfds;
memset(wait_result.fds, 0, _EVENT_MAX_FDS * sizeof(int));

if (readyfds == -1)
{
LOG("tnfs_event_wait: epoll_wait failed\n");
wait_result.size = -1;
return &wait_result;
}

for (int i = 0; i < readyfds; i++)
{
wait_result.fds[i] = events[i].data.fd;
}

return &wait_result;

}

void tnfs_event_close()
{
close(epfd);
}
Loading

0 comments on commit caf45f5

Please sign in to comment.