+#include <std.h>
#include <liba.h>
+#include <sys/resource.h>
+#include <poll.h>
-#define MAX_CONNS 1024
+#define BITS_PER_SLOT ((long)sizeof(long) * 8u)
-char* Usage = "mbusd DIALSTR";
+typedef enum {
+ STATE_DISCONNECTED = 0,
+ STATE_AUTHORIZING = 1,
+ STATE_CONNECTED = 2,
+} ClientState_T;
+
+typedef struct {
+ ClientState_T state;
+ Int fd;
+} Client_T;
+char* Usage = "mbusd DIALSTR";
Thread_T MessagingThread;
Mutex_T Lock;
-long ConnectionMap[MAX_CONNS / sizeof(long)] = {0};
+size_t MaxClients;
+long* ClientMap;
+struct pollfd* PollItems;
+Client_T* Clients;
+
+size_t UpdateMaxFileDescriptorCount(void)
+{
+ struct rlimit rlim = {0};
+ if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)
+ {
+ fatal("getrlimit:");
+ }
+ rlim.rlim_cur = rlim.rlim_max;
+ if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)
+ {
+ fatal("setrlimit:");
+ }
+ return rlim.rlim_cur;
+}
void RegisterNewClient(Int cfd)
{
+ long slot_pos = cfd / BITS_PER_SLOT;
+ long bit_pos = cfd % BITS_PER_SLOT;
Mutex_Lock(&Lock);
- // Add fd to connection map
+ Clients[cfd].fd = cfd;
+ Clients[cfd].state = STATE_DISCONNECTED;
+ ClientMap[slot_pos] |= ((long)1 << bit_pos);
Mutex_Unlock(&Lock);
- (void)cfd;
+}
+
+size_t PollClients(void)
+{
+ size_t fd_count = 0;
+ size_t num_slots = MaxClients / BITS_PER_SLOT;
+ Mutex_Lock(&Lock);
+ for (size_t i = 0; i < num_slots; i++)
+ {
+ long slot = ClientMap[i];
+ for (int bit = 0; slot && bit < BITS_PER_SLOT; bit++)
+ {
+ if (slot & ((long)1 << bit))
+ {
+ PollItems[fd_count].fd = slot + bit;
+ PollItems[fd_count].events = POLLIN;
+ PollItems[fd_count].revents = 0;
+ fd_count++;
+ }
+ }
+ }
+ Mutex_Unlock(&Lock);
+ errno = 0;
+ if ((poll(PollItems, fd_count, 10) < 0) && (errno != EINTR))
+ {
+ fatal("poll():");
+ }
+ return fd_count;
}
Int ProcessMessages(void* arg)
(void)arg;
for (;;)
{
- Mutex_Lock(&Lock);
- // for each FD in set
- // Setup poll struct
- Mutex_Unlock(&Lock);
- // poll() for input
- // for each poll struct
- // if closed
+ size_t fd_count = PollClients();
+ for (size_t i = 0; i < fd_count; i++)
+ {
+ if (PollItems[i].revents & POLLIN)
+ {
+ // Read the message
+ // publish the message
+ }
+ else /* POLLERR | POLLHUP */
+ {
+ int cfd = PollItems[i].fd;
+ long slot_pos = cfd / BITS_PER_SLOT;
+ long bit_pos = cfd % BITS_PER_SLOT;
Mutex_Lock(&Lock);
- // clear it from map
- // close fd
+ Clients[cfd].fd = cfd;
+ Clients[cfd].state = STATE_DISCONNECTED;
+ ClientMap[slot_pos] &= ~((long)1 << bit_pos);
Mutex_Unlock(&Lock);
- // else if data available
- // read message
- // publish message to subscribing clients
+ close(cfd);
+ }
+ }
}
return 0;
int main(int argc, char** argv)
{
+ /* check the arguments for validity */
if (argc != 1)
{
Options_PrintHelp();
return 1;
}
+ /* initialize the global state */
Mutex_Init(&Lock);
+ MaxClients = UpdateMaxFileDescriptorCount();
+ Clients = calloc(MaxClients, sizeof(Client_T));
+ ClientMap = calloc(MaxClients, sizeof(Client_T));
+ PollItems = calloc(MaxClients, sizeof(struct pollfd));
+
+ /* now start the client thread and server */
Thread_Create(&MessagingThread, ProcessMessages, NULL);
Net_Serve(argv[0], RegisterNewClient);
--- /dev/null
+$(OUTDIR)/obj/lib/a/UTF8.o: lib/a/UTF8.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/UTF8.o
+-include $(OUTDIR)/obj/lib/a/UTF8.d
+$(OUTDIR)/obj/lib/a/stdlib/erealloc.o: lib/a/stdlib/erealloc.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/erealloc.o
+-include $(OUTDIR)/obj/lib/a/stdlib/erealloc.d
+$(OUTDIR)/obj/lib/a/stdlib/forkexec.o: lib/a/stdlib/forkexec.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/forkexec.o
+-include $(OUTDIR)/obj/lib/a/stdlib/forkexec.d
+$(OUTDIR)/obj/lib/a/stdlib/efreadline.o: lib/a/stdlib/efreadline.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/efreadline.o
+-include $(OUTDIR)/obj/lib/a/stdlib/efreadline.d
+$(OUTDIR)/obj/lib/a/stdlib/esignal.o: lib/a/stdlib/esignal.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/esignal.o
+-include $(OUTDIR)/obj/lib/a/stdlib/esignal.d
+$(OUTDIR)/obj/lib/a/stdlib/estrdup.o: lib/a/stdlib/estrdup.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/estrdup.o
+-include $(OUTDIR)/obj/lib/a/stdlib/estrdup.d
+$(OUTDIR)/obj/lib/a/stdlib/eraise.o: lib/a/stdlib/eraise.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/eraise.o
+-include $(OUTDIR)/obj/lib/a/stdlib/eraise.d
+$(OUTDIR)/obj/lib/a/stdlib/strmcat.o: lib/a/stdlib/strmcat.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/strmcat.o
+-include $(OUTDIR)/obj/lib/a/stdlib/strmcat.d
+$(OUTDIR)/obj/lib/a/stdlib/efopen.o: lib/a/stdlib/efopen.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/efopen.o
+-include $(OUTDIR)/obj/lib/a/stdlib/efopen.d
+$(OUTDIR)/obj/lib/a/stdlib/ecalloc.o: lib/a/stdlib/ecalloc.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/ecalloc.o
+-include $(OUTDIR)/obj/lib/a/stdlib/ecalloc.d
+$(OUTDIR)/obj/lib/a/stdlib/smprintf.o: lib/a/stdlib/smprintf.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/smprintf.o
+-include $(OUTDIR)/obj/lib/a/stdlib/smprintf.d
+$(OUTDIR)/obj/lib/a/stdlib/warn.o: lib/a/stdlib/warn.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/warn.o
+-include $(OUTDIR)/obj/lib/a/stdlib/warn.d
+$(OUTDIR)/obj/lib/a/stdlib/emalloc.o: lib/a/stdlib/emalloc.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/emalloc.o
+-include $(OUTDIR)/obj/lib/a/stdlib/emalloc.d
+$(OUTDIR)/obj/lib/a/stdlib/fatal.o: lib/a/stdlib/fatal.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/stdlib/fatal.o
+-include $(OUTDIR)/obj/lib/a/stdlib/fatal.d
+$(OUTDIR)/obj/lib/a/Mutex.o: lib/a/Mutex.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/Mutex.o
+-include $(OUTDIR)/obj/lib/a/Mutex.d
+$(OUTDIR)/obj/lib/a/Thread.o: lib/a/Thread.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/Thread.o
+-include $(OUTDIR)/obj/lib/a/Thread.d
+$(OUTDIR)/obj/lib/a/defaults/argv0.o: lib/a/defaults/argv0.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/defaults/argv0.o
+-include $(OUTDIR)/obj/lib/a/defaults/argv0.d
+$(OUTDIR)/obj/lib/a/defaults/set_option.o: lib/a/defaults/set_option.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/defaults/set_option.o
+-include $(OUTDIR)/obj/lib/a/defaults/set_option.d
+$(OUTDIR)/obj/lib/a/defaults/options.o: lib/a/defaults/options.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/defaults/options.o
+-include $(OUTDIR)/obj/lib/a/defaults/options.d
+$(OUTDIR)/obj/lib/a/defaults/usage.o: lib/a/defaults/usage.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/defaults/usage.o
+-include $(OUTDIR)/obj/lib/a/defaults/usage.d
+$(OUTDIR)/obj/lib/a/GC.o: lib/a/GC.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/GC.o
+-include $(OUTDIR)/obj/lib/a/GC.d
+$(OUTDIR)/obj/lib/a/Net.o: lib/a/Net.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/Net.o
+-include $(OUTDIR)/obj/lib/a/Net.d
+$(OUTDIR)/obj/lib/a/Options.o: lib/a/Options.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/liba.a: $(OUTDIR)/obj/lib/a/Options.o
+-include $(OUTDIR)/obj/lib/a/Options.d
+$(OUTDIR)/lib/liba.a:
+ $(ARCHIVE)
+libs: $(OUTDIR)/lib/liba.a
+$(OUTDIR)/obj/lib/ui/window_hide.o: lib/ui/window_hide.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/window_hide.o
+-include $(OUTDIR)/obj/lib/ui/window_hide.d
+$(OUTDIR)/obj/lib/ui/window_show.o: lib/ui/window_show.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/window_show.o
+-include $(OUTDIR)/obj/lib/ui/window_show.d
+$(OUTDIR)/obj/lib/ui/font_close.o: lib/ui/font_close.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/font_close.o
+-include $(OUTDIR)/obj/lib/ui/font_close.d
+$(OUTDIR)/obj/lib/ui/font_load.o: lib/ui/font_load.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/font_load.o
+-include $(OUTDIR)/obj/lib/ui/font_load.d
+$(OUTDIR)/obj/lib/ui/window_create.o: lib/ui/window_create.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/window_create.o
+-include $(OUTDIR)/obj/lib/ui/window_create.d
+$(OUTDIR)/obj/lib/ui/ui_begin.o: lib/ui/ui_begin.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/ui_begin.o
+-include $(OUTDIR)/obj/lib/ui/ui_begin.d
+$(OUTDIR)/obj/lib/ui/window_delete.o: lib/ui/window_delete.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/window_delete.o
+-include $(OUTDIR)/obj/lib/ui/window_delete.d
+$(OUTDIR)/obj/lib/ui/ui_end.o: lib/ui/ui_end.c config.mk
+ $(OBJECT)
+$(OUTDIR)/lib/libui.a: $(OUTDIR)/obj/lib/ui/ui_end.o
+-include $(OUTDIR)/obj/lib/ui/ui_end.d
+$(OUTDIR)/lib/libui.a:
+ $(ARCHIVE)
+libs: $(OUTDIR)/lib/libui.a
+libs = $(OUTDIR)/lib/liba.a $(OUTDIR)/lib/libui.a
+$(OUTDIR)/obj/bin/dial.o: bin/dial.c
+ $(OBJECT)
+$(OUTDIR)/bin/dial: | $(libs)
+$(OUTDIR)/bin/dial: $(OUTDIR)/obj/bin/dial.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/dial
+$(OUTDIR)/obj/bin/edit.o: bin/edit.c
+ $(OBJECT)
+$(OUTDIR)/bin/edit: | $(libs)
+$(OUTDIR)/bin/edit: $(OUTDIR)/obj/bin/edit.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/edit
+$(OUTDIR)/obj/bin/init.o: bin/init.c
+ $(OBJECT)
+$(OUTDIR)/bin/init: | $(libs)
+$(OUTDIR)/bin/init: $(OUTDIR)/obj/bin/init.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/init
+$(OUTDIR)/obj/bin/listen.o: bin/listen.c
+ $(OBJECT)
+$(OUTDIR)/bin/listen: | $(libs)
+$(OUTDIR)/bin/listen: $(OUTDIR)/obj/bin/listen.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/listen
+$(OUTDIR)/obj/bin/mbusd.o: bin/mbusd.c
+ $(OBJECT)
+$(OUTDIR)/bin/mbusd: | $(libs)
+$(OUTDIR)/bin/mbusd: $(OUTDIR)/obj/bin/mbusd.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/mbusd
+$(OUTDIR)/obj/bin/pick.o: bin/pick.c
+ $(OBJECT)
+$(OUTDIR)/bin/pick: | $(libs)
+$(OUTDIR)/bin/pick: $(OUTDIR)/obj/bin/pick.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/pick
+$(OUTDIR)/obj/bin/screenlock.o: bin/screenlock.c
+ $(OBJECT)
+$(OUTDIR)/bin/screenlock: | $(libs)
+$(OUTDIR)/bin/screenlock: $(OUTDIR)/obj/bin/screenlock.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/screenlock
+$(OUTDIR)/obj/bin/shell.o: bin/shell.c
+ $(OBJECT)
+$(OUTDIR)/bin/shell: | $(libs)
+$(OUTDIR)/bin/shell: $(OUTDIR)/obj/bin/shell.o
+ $(BINARY)
+bins: $(OUTDIR)/bin/shell
+$(OUTDIR)/obj/bin/winmgr/keys.o: bin/winmgr/keys.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/keys.o
+-include $(OUTDIR)/obj/bin/winmgr/keys.d
+$(OUTDIR)/obj/bin/winmgr/mons.o: bin/winmgr/mons.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/mons.o
+-include $(OUTDIR)/obj/bin/winmgr/mons.d
+$(OUTDIR)/obj/bin/winmgr/tile.o: bin/winmgr/tile.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/tile.o
+-include $(OUTDIR)/obj/bin/winmgr/tile.d
+$(OUTDIR)/obj/bin/winmgr/error.o: bin/winmgr/error.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/error.o
+-include $(OUTDIR)/obj/bin/winmgr/error.d
+$(OUTDIR)/obj/bin/winmgr/client.o: bin/winmgr/client.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/client.o
+-include $(OUTDIR)/obj/bin/winmgr/client.d
+$(OUTDIR)/obj/bin/winmgr/winmgr.o: bin/winmgr/winmgr.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/winmgr.o
+-include $(OUTDIR)/obj/bin/winmgr/winmgr.d
+$(OUTDIR)/obj/bin/winmgr/mouse.o: bin/winmgr/mouse.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/mouse.o
+-include $(OUTDIR)/obj/bin/winmgr/mouse.d
+$(OUTDIR)/obj/bin/winmgr/util.o: bin/winmgr/util.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/util.o
+-include $(OUTDIR)/obj/bin/winmgr/util.d
+$(OUTDIR)/obj/bin/winmgr/list.o: bin/winmgr/list.c config.mk
+ $(OBJECT)
+$(OUTDIR)/bin/winmgr: $(OUTDIR)/obj/bin/winmgr/list.o
+-include $(OUTDIR)/obj/bin/winmgr/list.d
+$(OUTDIR)/bin/winmgr: | $(libs)
+ $(BINARY)
+bins: $(OUTDIR)/bin/winmgr