[mw-devel] [Git][arthur/mw][master] 4 commits: Add includes required on freebsd
Andrew Price
welshbyte at sucs.org
Sun Jul 30 17:49:52 BST 2017
Andrew Price pushed to branch master at Justin Mitchell / mw
Commits:
4a26c344 by Andrew Price at 2017-07-30T11:05:04+01:00
Add includes required on freebsd
On Linux this just makes some implicit includes explicit.
- - - - -
9801780d by Andrew Price at 2017-07-30T11:55:25+01:00
Set appropriate build flags for FreeBSD
And don't try to use strfry() on it.
- - - - -
8538d135 by Andrew Price at 2017-07-30T15:20:35+01:00
server: abstract out the event polling bits
- - - - -
a7dff10a by Andrew Price at 2017-07-30T17:47:14+01:00
Add a kqueue implementation of server/poll.h
MW now works on FreeBSD
- - - - -
17 changed files:
- Makefile.common
- src/Makefile
- src/client/Makefile
- src/client/edit.c
- src/client/main.c
- src/client/mod.c
- src/client/newmain.c
- src/list.h
- src/server/Makefile
- src/server/gags.c
- + src/server/poll-epoll.c
- + src/server/poll-kqueue.c
- + src/server/poll.h
- src/server/servsock.c
- src/socket.c
- src/user.c
- src/webclient/comms.c
Changes:
=====================================
Makefile.common
=====================================
--- a/Makefile.common
+++ b/Makefile.common
@@ -1,3 +1,4 @@
+UNAME = $(shell uname)
GITVER = $(shell git describe --always --dirty)
VERSION = $(GITVER)
@@ -68,6 +69,10 @@ MWLDFLAGS += -O0
endif
MWCFLAGS = -std=gnu99 -g $(DEFS) $(CCSEC) $(WARNINGS)
+ifeq ($(UNAME),FreeBSD)
+MWCFLAGS += -I/usr/local/include
+MWLDFLAGS = -L/usr/local/lib
+endif
ifneq ($(RELEASE_BUILD),0)
MWCFLAGS += -O2
# This requires optimisation so add it here instead of CCSEC
=====================================
src/Makefile
=====================================
--- a/src/Makefile
+++ b/src/Makefile
@@ -3,8 +3,8 @@ DEPTH=../
include ../Makefile.common
build: libmw.a
- $(MAKE) -C server $@
$(MAKE) -C client $@
+ $(MAKE) -C server $@
$(MAKE) -C webclient $@
$(MAKE) -C utils $@
ln -fs server/mwserv client/mw .
=====================================
src/client/Makefile
=====================================
--- a/src/client/Makefile
+++ b/src/client/Makefile
@@ -13,8 +13,12 @@ JSDIR = $(JSDIR_$(JSENGINE))
JSOBJ = $(JSOBJ_$(JSENGINE))
JSFLAGS = $(JSFLAGS_$(JSENGINE))
-LDLIBS+= -lreadline -ltermcap -lcrypt -lsqlite3 -lcurl -lpthread -lcrypto -ljansson -lz -lm
-CFLAGS+= -I.. $(JSFLAGS)
+LDLIBS += -lreadline -ltermcap -lcrypt -lsqlite3 -lcurl -lpthread -lcrypto -ljansson -lz -lm
+ifeq ($(UNAME),FreeBSD)
+LDLIBS += -lintl
+endif
+
+CFLAGS += -I.. $(JSFLAGS)
# Force build order as we need generated mozjs headers to build mw
build: $(JSOBJ)
=====================================
src/client/edit.c
=====================================
--- a/src/client/edit.c
+++ b/src/client/edit.c
@@ -15,6 +15,7 @@
#include <time.h>
#include <stdbool.h>
#include <sys/stat.h>
+#include <signal.h>
#include <util.h>
#include "talker_privs.h"
=====================================
src/client/main.c
=====================================
--- a/src/client/main.c
+++ b/src/client/main.c
@@ -12,6 +12,10 @@
#include <termcap.h>
#include <stdbool.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <signal.h>
#include "command.h"
#include "alarm.h"
=====================================
src/client/mod.c
=====================================
--- a/src/client/mod.c
+++ b/src/client/mod.c
@@ -8,6 +8,7 @@
#include <time.h>
#include <stdio.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include <string.h>
#include "files.h"
#include "str_util.h"
=====================================
src/client/newmain.c
=====================================
--- a/src/client/newmain.c
+++ b/src/client/newmain.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
=====================================
src/list.h
=====================================
--- a/src/list.h
+++ b/src/list.h
@@ -27,6 +27,7 @@ struct hlist_node {
#define LIST_HEAD_INIT(name) { &(name), &(name) }
+#undef LIST_HEAD
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
=====================================
src/server/Makefile
=====================================
--- a/src/server/Makefile
+++ b/src/server/Makefile
@@ -2,8 +2,16 @@ SRCROOT = $(CURDIR)/../..
DEPTH=../../
include $(DEPTH)Makefile.common
-CFLAGS+= -I..
-LDLIBS+= -ljansson -lsqlite3
+POLLER = epoll
+CFLAGS += -I..
+ifeq ($(UNAME),FreeBSD)
+CFLAGS += -DSTRFRY_MISSING
+POLLER := kqueue
+endif
+
+CODE := $(filter-out poll-%.c, $(CODE)) poll-$(POLLER).c
+
+LDLIBS += -ljansson -lsqlite3
build: mwserv
=====================================
src/server/gags.c
=====================================
--- a/src/server/gags.c
+++ b/src/server/gags.c
@@ -10,9 +10,6 @@
#include "talker_privs.h"
#include "gags.h"
-/* should be defined by strings.h */
-char *strfry(char *string);
-
/* local prototypes */
void gag_normal(char *text);
void gag_chef(char *text);
@@ -385,6 +382,7 @@ void gag_swab(char *text)
/* strfry */
void gag_strfry(char *text)
{
+#ifndef STRFRY_MISSING
char *new;
char *old = strdup(text);
char str[MAXTEXTLENGTH];
@@ -398,6 +396,7 @@ void gag_strfry(char *text)
free(new);
free(old);
+#endif
}
static char *duplstr(char *text)
=====================================
src/server/poll-epoll.c
=====================================
--- /dev/null
+++ b/src/server/poll-epoll.c
@@ -0,0 +1,91 @@
+#include <sys/epoll.h>
+#include <strings.h>
+
+#include <socket.h>
+#include "poll.h"
+
+struct epoll_priv {
+ int pollfd;
+};
+
+struct epoll_priv ep = {
+ .pollfd = -1
+};
+
+int poll_addconn(ipc_connection_t *conn)
+{
+ struct epoll_event ev;
+ int ret;
+
+ bzero(&ev, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLERR;
+ ev.data.ptr = conn;
+ ret = epoll_ctl(ep.pollfd, EPOLL_CTL_ADD, conn->fd, &ev);
+ return ret;
+}
+
+int poll_init(void)
+{
+ if (ep.pollfd == -1)
+ ep.pollfd = epoll_create(30);
+ return 0;
+}
+
+void poll_delete(int fd)
+{
+ struct epoll_event ev;
+
+ bzero(&ev, sizeof(ev));
+ epoll_ctl(ep.pollfd, EPOLL_CTL_DEL, fd, &ev);
+}
+
+int poll_with_writes(ipc_connection_t *conn)
+{
+ struct epoll_event ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLOUT | EPOLLERR;
+ ev.data.ptr = conn;
+ return epoll_ctl(ep.pollfd, EPOLL_CTL_MOD, conn->fd, &ev);
+}
+
+int poll_without_writes(ipc_connection_t *conn)
+{
+ struct epoll_event ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLERR;
+ ev.data.ptr = conn;
+ return epoll_ctl(ep.pollfd, EPOLL_CTL_MOD, conn->fd, &ev);
+}
+
+int poll_fd_without_writes(int fd)
+{
+ struct epoll_event ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.events = EPOLLIN | EPOLLERR;
+ ev.data.ptr = NULL;
+ return epoll_ctl(ep.pollfd, EPOLL_CTL_ADD, fd, &ev);
+}
+
+int poll_wait(int timeout_millis, int (*callback)(poll_event_t *, int, void *), void *data)
+{
+#define NEVENTS (20)
+ struct epoll_event evs[NEVENTS];
+ poll_event_t pevs[NEVENTS];
+ int ret;
+
+ ret = epoll_wait(ep.pollfd, evs, NEVENTS, timeout_millis);
+ if (ret < 0)
+ return ret;
+ for (int i = 0; i < ret; i++) {
+ bzero(&pevs[i], sizeof(pevs[i]));
+ pevs[i].data = evs[i].data.ptr;
+ pevs[i].is_error = (evs[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP));
+ pevs[i].is_read = (evs[i].events & (EPOLLIN | EPOLLPRI));
+ pevs[i].is_write = (evs[i].events & (EPOLLOUT));
+ }
+ ret = callback(pevs, ret, data);
+ return ret;
+}
=====================================
src/server/poll-kqueue.c
=====================================
--- /dev/null
+++ b/src/server/poll-kqueue.c
@@ -0,0 +1,102 @@
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <strings.h>
+#include <errno.h>
+
+#include <socket.h>
+#include "poll.h"
+
+struct kq_priv {
+ int kqd;
+};
+
+struct kq_priv kp = {
+ .kqd = -1
+};
+
+int poll_addconn(ipc_connection_t *conn)
+{
+ struct kevent ev;
+
+ EV_SET(&ev, conn->fd, EVFILT_READ, EV_ADD, 0, 0, conn);
+ return kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+}
+
+int poll_init(void)
+{
+ if (kp.kqd == -1)
+ kp.kqd = kqueue();
+ return 0;
+}
+
+void poll_delete(int fd)
+{
+ struct kevent ev;
+
+ EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
+ kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+ EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+}
+
+int poll_with_writes(ipc_connection_t *conn)
+{
+ struct kevent ev;
+
+ EV_SET(&ev, conn->fd, EVFILT_WRITE, EV_ADD, 0, 0, conn);
+ return kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+}
+
+int poll_without_writes(ipc_connection_t *conn)
+{
+ struct kevent ev;
+ int ret;
+
+ EV_SET(&ev, conn->fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ ret = kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+ if (ret != 0 && errno != ENOENT)
+ return ret;
+ return 0;
+}
+
+int poll_fd_without_writes(int fd)
+{
+ struct kevent ev;
+ int ret;
+
+ EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ ret = kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+ if (ret != 0)
+ return ret;
+ EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
+ ret = kevent(kp.kqd, &ev, 1, NULL, 0, NULL);
+ if (ret != 0 && errno != ENOENT)
+ return ret;
+ return 0;
+}
+
+int poll_wait(int timeout_millis, int (*callback)(poll_event_t *, int, void *), void *data)
+{
+#define NEVENTS (20)
+ struct timespec timeout = {
+ .tv_sec = timeout_millis / 1000,
+ .tv_nsec = timeout_millis % 1000 * 1000000
+ };
+ struct kevent evs[NEVENTS];
+ poll_event_t pevs[NEVENTS];
+ int ret;
+
+ ret = kevent(kp.kqd, NULL, 0, evs, NEVENTS, &timeout);
+ if (ret == -1)
+ return ret;
+ for (int i = 0; i < ret; i++) {
+ bzero(&pevs[i], sizeof(pevs[i]));
+ pevs[i].data = evs[i].udata;
+ pevs[i].is_error = (evs[i].flags & (EV_EOF | EV_ERROR));
+ pevs[i].is_read = (evs[i].filter == EVFILT_READ);
+ pevs[i].is_write = (evs[i].filter == EVFILT_WRITE);
+ }
+ ret = callback(pevs, ret, data);
+ return ret;
+}
=====================================
src/server/poll.h
=====================================
--- /dev/null
+++ b/src/server/poll.h
@@ -0,0 +1,19 @@
+#ifndef SERVER_POLL_H
+#define SERVER_POLL_H
+
+typedef struct {
+ int is_read;
+ int is_write;
+ int is_error;
+ void *data;
+} poll_event_t;
+
+extern int poll_addconn(ipc_connection_t *conn);
+extern int poll_init(void);
+extern void poll_delete(int fd);
+extern int poll_with_writes(ipc_connection_t *conn);
+extern int poll_without_writes(ipc_connection_t *conn);
+extern int poll_fd_without_writes(int fd);
+extern int poll_wait(int timeout_millis, int (*callback)(poll_event_t *events, int nmemb, void *data), void *data);
+
+#endif /* SERVER_POLL_H */
=====================================
src/server/servsock.c
=====================================
--- a/src/server/servsock.c
+++ b/src/server/servsock.c
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
-#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -26,13 +25,13 @@
#include "replay.h"
#include "actions.h"
#include "gags.h"
+#include "poll.h"
#include <folders.h>
#include <perms.h>
#include <special.h>
struct list_head connection_list;
-static int pollfd = -1;
int mainsock_die = 0;
int open_mainsock(uint16_t port)
@@ -83,11 +82,7 @@ ipc_connection_t * add_connection(int fd)
list_add_tail(&(new->list), &connection_list);
/* register interest in read events */
- struct epoll_event ev;
- bzero(&ev, sizeof(ev));
- ev.events = EPOLLIN | EPOLLERR;
- ev.data.ptr = new;
- if (epoll_ctl( pollfd, EPOLL_CTL_ADD, new->fd, &ev)) {
+ if (poll_addconn(new)) {
fprintf(stderr, "Error adding new conn to poll: %s\n", strerror(errno));
}
@@ -114,11 +109,8 @@ void accept_connection(int mainsock)
void drop_connection(ipc_connection_t * conn)
{
- struct epoll_event ev;
-
printf("Drop connection fd=%d\n", conn->fd);
- bzero(&ev, sizeof(ev));
- epoll_ctl(pollfd, EPOLL_CTL_DEL, conn->fd, &ev);
+ poll_delete(conn->fd);
list_del_init(&conn->list);
if (conn->fd != -1) close(conn->fd);
conn->fd = -1;
@@ -141,79 +133,78 @@ void drop_connection(ipc_connection_t * conn)
ipcmsg_destroy(whoinfo);
}
-void watch_mainsock(int mainsock)
+static int mainsock_event_cb(poll_event_t *events, int nmemb, void *data)
{
- struct epoll_event ev;
-
- /* add the mainsock to the epoll list
- * it will only generate read events */
- bzero(&ev, sizeof(ev));
- ev.events = EPOLLIN | EPOLLERR;
- ev.data.ptr = NULL;
- if (epoll_ctl(pollfd, EPOLL_CTL_ADD, mainsock, &ev)) {
- fprintf(stderr, "Error adding mainsock: %s\n", strerror(errno));
- return;
- }
+ int *mainsock = data;
- struct epoll_event event[20];
- int ret;
- struct timeval last;
- gettimeofday(&last, NULL);
+ for (int i = 0; i < nmemb; i++) {
+ poll_event_t *ev = &events[i];
-bodge:
- while ((ret = epoll_wait(pollfd, event, 20, 1000)) >= 0) {
- for (int i=0; i<ret; i++) {
- /* even on mainsock */
- if (event[i].data.ptr == NULL) {
- if (event[i].events & (EPOLLERR | EPOLLHUP)) {
- return;
- } else
- if (event[i].events & EPOLLIN) {
- accept_connection(mainsock);
- } else {
- fprintf(stderr, "unexpected event on mainsock.\n");
- }
+ /* event on mainsock */
+ if (ev->data == NULL) {
+ if (ev->is_error) {
+ return 1;
+ } else
+ if (ev->is_read) {
+ accept_connection(*mainsock);
} else {
- ipc_connection_t *c = event[i].data.ptr;
- if (event[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
- ipcconn_bad(c);
- } else
- if (event[i].events & (EPOLLIN | EPOLLPRI)) {
- ipc_message_t *msg = read_socket(c, 1);
- while (msg != NULL) {
- process_msg(c, msg);
- msg=read_socket(c,0);
- }
- } else
- if (event[i].events & EPOLLOUT) {
- write_socket(c);
- } else {
- fprintf(stderr, "unexpected event on fd=%d.\n", c->fd);
+ fprintf(stderr, "unexpected event on mainsock.\n");
+ }
+ } else {
+ ipc_connection_t *c = ev->data;
+ if (ev->is_error) {
+ ipcconn_bad(c);
+ } else
+ if (ev->is_read) {
+ ipc_message_t *msg = read_socket(c, 1);
+ while (msg != NULL) {
+ process_msg(c, msg);
+ msg=read_socket(c,0);
}
+ } else
+ if (ev->is_write) {
+ write_socket(c);
+ } else {
+ fprintf(stderr, "unexpected event on fd=%d.\n", c->fd);
}
+ }
- /* check if we had to drop any connections and clean them away */
- struct list_head *pos, *q;
- list_for_each_safe(pos, q, &connection_list) {
- ipc_connection_t * c = list_entry(pos, ipc_connection_t, list);
- /* connections that went bad */
- if (c->fd != -1 && c->state == IPCSTATE_ERROR) {
- drop_connection(c);
- }
- /* connections with a soft close */
- if (c->state == IPCSTATE_PURGE && list_empty(&(c->outq))) {
- drop_connection(c);
- }
+ /* check if we had to drop any connections and clean them away */
+ struct list_head *pos, *q;
+ list_for_each_safe(pos, q, &connection_list) {
+ ipc_connection_t * c = list_entry(pos, ipc_connection_t, list);
+ /* connections that went bad */
+ if (c->fd != -1 && c->state == IPCSTATE_ERROR) {
+ drop_connection(c);
+ }
+ /* connections with a soft close */
+ if (c->state == IPCSTATE_PURGE && list_empty(&(c->outq))) {
+ drop_connection(c);
}
}
- /* end of events handling, do periodic stuff here */
}
+ return 0;
+}
- /* epoll got interupted, not actually an error, go around again */
- if (ret == -1 && errno == EINTR) goto bodge;
+void watch_mainsock(int mainsock)
+{
+ int ret;
+ struct timeval last;
+ gettimeofday(&last, NULL);
- /* epoll gave an error */
- fprintf(stderr, "epoll error: %s\n", strerror(errno));
+ if (poll_fd_without_writes(mainsock)) {
+ fprintf(stderr, "Error adding mainsock: %s\n", strerror(errno));
+ return;
+ }
+
+ do {
+ while ((ret = poll_wait(1000, mainsock_event_cb, &mainsock)) >= 0) {
+ /* end of events handling, do periodic stuff here */
+ }
+ /* poll got interrupted, not actually an error, go around again */
+ } while (ret == -1 && errno == EINTR);
+
+ fprintf(stderr, "poll error: %s\n", strerror(errno));
}
void write_socket(ipc_connection_t * conn)
@@ -223,13 +214,9 @@ void write_socket(ipc_connection_t * conn)
if (list_empty(&conn->outq)) {
/* tx queue is empty, stop write events */
- struct epoll_event ev;
- bzero(&ev, sizeof(ev));
- ev.events = EPOLLIN | EPOLLERR;
- ev.data.ptr = conn;
- if (epoll_ctl(pollfd, EPOLL_CTL_MOD, conn->fd, &ev)) {
- fprintf(stderr, "Error updating poll fd=%d: %s\n", conn->fd, strerror(errno));
- }
+ if (poll_without_writes(conn))
+ fprintf(stderr, "Error updating poll fd=%d: %s\n",
+ conn->fd, strerror(errno));
return;
}
struct list_head * pos = conn->outq.next;
@@ -624,13 +611,8 @@ void msg_attach(ipc_message_t *msg, ipc_connection_t *conn)
int wasempty = msg_queue(msg, conn);
/* nothing was queueed, switch on write notifications */
- if (wasempty) {
- struct epoll_event ev;
- bzero(&ev, sizeof(ev));
- ev.events = EPOLLIN | EPOLLOUT | EPOLLERR;
- ev.data.ptr = conn;
- epoll_ctl(pollfd, EPOLL_CTL_MOD, conn->fd, &ev);
- }
+ if (wasempty)
+ poll_with_writes(conn);
}
/* test if the user is gagged and apply the filter
@@ -750,9 +732,7 @@ void migrate_old_folders(void)
void init_server()
{
INIT_LIST_HEAD(&connection_list);
- if (pollfd == -1) {
- pollfd = epoll_create(30);
- }
+ poll_init();
}
ipc_message_t * msg_wholist(void)
=====================================
src/socket.c
=====================================
--- a/src/socket.c
+++ b/src/socket.c
@@ -2,8 +2,10 @@
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
+#include <sys/uio.h>
#include <unistd.h>
#include <sys/socket.h>
+#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
=====================================
src/user.c
=====================================
--- a/src/user.c
+++ b/src/user.c
@@ -1,3 +1,5 @@
+#include <sys/types.h>
+#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
=====================================
src/webclient/comms.c
=====================================
--- a/src/webclient/comms.c
+++ b/src/webclient/comms.c
@@ -84,7 +84,7 @@ void open_command_socket()
}
sa.sun_family = AF_UNIX;
snprintf(sa.sun_path, UNIX_PATH_MAX, MSGDIR"/mwpoll.%d", getpid());
- if (bind(command_sock, &sa, sizeof(sa))) {
+ if (bind(command_sock, (struct sockaddr *)&sa, sizeof(sa))) {
fprintf(stderr, "Error binding %s: %s\n", sa.sun_path, strerror(errno));
close(command_sock);
command_sock = -1;
View it on GitLab: https://projects.sucs.org/arthur/mw/compare/52ffb48b380225c2ab23d73cada72dd693d6e183...a7dff10a26dae1ea180f857f7ea8efe6f9f520b2
---
View it on GitLab: https://projects.sucs.org/arthur/mw/compare/52ffb48b380225c2ab23d73cada72dd693d6e183...a7dff10a26dae1ea180f857f7ea8efe6f9f520b2
You're receiving this email because of your account on projects.sucs.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.sucs.org/pipermail/mw-devel/attachments/20170730/59c40673/attachment-0001.html>
More information about the mw-devel
mailing list