aboutsummaryrefslogtreecommitdiff
path: root/source/archived/v1/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/archived/v1/server.c')
-rw-r--r--source/archived/v1/server.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/source/archived/v1/server.c b/source/archived/v1/server.c
new file mode 100644
index 0000000..7edf558
--- /dev/null
+++ b/source/archived/v1/server.c
@@ -0,0 +1,148 @@
+// Server for chatty
+#include "common.h"
+#include <arpa/inet.h>
+#include <errno.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#define MAX_CONNECTIONS 5
+#define FD_MAX MAX_CONNECTIONS + 1
+
+// static const u8 *filename = "history.dat";
+
+enum { FD_SERVER = 0 };
+u32 serverfd;
+
+void err_exit(const char *msg)
+{
+ if (serverfd)
+ if (close(serverfd))
+ writef("Error while closing server socket. errno: %d\n", errno);
+ fprintf(stderr, "%s errno: %d\n", msg, errno);
+ _exit(1);
+}
+
+int main(void)
+{
+ u32 clientfd;
+ u16 nclient = 0;
+ u32 on = 1;
+ Message msg_recv = {0};
+
+ serverfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
+ if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)))
+ err_exit("Error while setting socket option.");
+
+ const struct sockaddr_in address = {
+ AF_INET,
+ htons(PORT),
+ {0},
+ };
+
+ if (bind(serverfd, (struct sockaddr *)&address, sizeof(address)))
+ err_exit("Error while binding.");
+
+ if (listen(serverfd, BUF_MAX))
+ err_exit("Error while listening");
+
+ writef("Listening on localhost:%d\n", PORT);
+
+ struct pollfd fds[MAX_CONNECTIONS + 1] = {
+ {serverfd, POLLIN, 0}, // FD_SERVER
+ { -1, POLLIN, 0},
+ { -1, POLLIN, 0},
+ { -1, POLLIN, 0},
+ { -1, POLLIN, 0},
+ { -1, POLLIN, 0},
+ };
+
+ for (;;) {
+ u32 ret = poll(fds, FD_MAX, 50000);
+ if (ret == -1)
+ err_exit("Error while polling");
+ else if (ret == 0) {
+ writef("polling timed out.\n");
+ continue;
+ }
+
+ // New client tries to connect to serverfd
+ if (fds[FD_SERVER].revents & POLLIN) {
+ clientfd = accept(serverfd, NULL, NULL);
+
+ // When MAX_CONNECTIONS is reached, close new clients trying to connect.
+ if (nclient == MAX_CONNECTIONS) {
+ writef("Max connections reached.\n");
+ if (send(clientfd, 0, 0, 0) == -1)
+ err_exit("Error while sending EOF to client socket.");
+ if (shutdown(clientfd, SHUT_RDWR))
+ err_exit("Error while shutting down client socket.");
+ if (close(clientfd))
+ err_exit("Error while closing client socket.");
+ } else if (clientfd != -1) {
+ nclient++;
+
+ // get a new available spot in the fds array
+ u32 i;
+ for (i = 0; i < MAX_CONNECTIONS; i++)
+ if (fds[i].fd == -1)
+ break;
+ fds[i].fd = clientfd;
+ writef("New client: %d, %d\n", i, clientfd);
+
+ } else {
+ writef("Could not accept client errno: %d\n", errno);
+ }
+ }
+
+ // Check for events on connected clients
+ for (u32 i = 1; i <= nclient; i++) {
+ if (!(fds[i].revents & POLLIN))
+ continue;
+
+ u32 nrecv;
+
+ clientfd = fds[i].fd;
+
+ nrecv = message_receive(&msg_recv, clientfd);
+ if (nrecv == 0) {
+ printf("client %d disconnected.\n", i);
+ fds[i].fd = -1;
+ fds[i].revents = 0;
+ if (shutdown(clientfd, SHUT_RDWR))
+ err_exit("Error while shutting down client %d socket.");
+ if (close(clientfd))
+ err_exit("Error while cloing client socket.");
+ nclient--;
+ break;
+ } else if (nrecv == -1) {
+ // TODO: this can happen when connect is reset by pear
+ err_exit("Error while receiving from client socket.");
+ }
+
+ writef("Received %d bytes from client(%d): %s [%s] (%d)%s\n", nrecv, clientfd - serverfd, msg_recv.timestamp, msg_recv.author, msg_recv.text_len, msg_recv.text);
+
+ // TODO:
+ for (u32 j = 1; j <= nclient; j++) {
+ // skip the client that sent the message
+ if (j == i)
+ continue;
+ if (message_send(&msg_recv, fds[j].fd) == -1)
+ printf("Error while sendig message to client %d. errno: %d\n", j, errno);
+ else
+ printf("Retransmitted message to client %d.\n", j);
+ }
+
+ // // TODO: Serialize received message
+ // FILE *f = fopen(filename, "wb");
+ // save_message(&msg_recv, f);
+ // fclose(f);
+ // // return 0;
+ }
+ }
+
+ return 0;
+}