]> PatchyGit - patchyircd.git/commitdiff
Organized everything
authorSam Smith <sam@patchysicp.xyz>
Sun, 24 Apr 2022 18:44:55 +0000 (11:44 -0700)
committerSam Smith <sam@patchysicp.xyz>
Sun, 24 Apr 2022 18:44:55 +0000 (11:44 -0700)
NetSock/netsock.c [new file with mode: 0644]
NetSock/netsock.h [new file with mode: 0644]
common.h [new file with mode: 0644]
config.h [new file with mode: 0644]
irc.c [new file with mode: 0644]
irc.h [new file with mode: 0644]
main.c [changed mode: 0755->0644]
net.c [new file with mode: 0644]
net.h [new file with mode: 0644]
networking-tests/client.c [moved from client.c with 100% similarity]
networking-tests/main.c [new file with mode: 0755]

diff --git a/NetSock/netsock.c b/NetSock/netsock.c
new file mode 100644 (file)
index 0000000..322479b
--- /dev/null
@@ -0,0 +1,98 @@
+#include "netsock.h"
+
+// Windows
+#if defined(_WIN32)
+// Variables
+struct WSAData net_wd;
+// Funcs
+#define net_errno() (WSAGetLastError())
+const char *net_strerror(int e) {
+       static char msg[256];
+       if (!FormatMessageA(\
+              FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+              NULL, e, 0, msg, 256, NULL))
+               sprintf(msg, "WSA Error %d", e);
+       return msg;
+}
+int net_nonblock(SOCKET fd) {
+       u_long v = 1;
+       return ioctlsocket(fd, FIONBIO, &v);
+}
+
+// POSIX
+#else
+// Funcs
+int net_nonblock(SOCKET fd) {
+#if defined(O_NONBLOCK)
+       int f = fcntl(fd, F_GETFL);
+       if (f == -1)
+               return -1;
+       return fcntl(fd, F_SETFL, f | O_NONBLOCK);
+#else
+       u_long v = 1;
+       return ioctlsocket(fd, FIONBIO, &v);
+#endif
+}
+#endif
+
+// Funcs
+void net_perror(const char *p)
+{
+       if (p && *p) {
+               fprintf(stderr, "%s: %s\n", p, net_strerror(net_errno()));
+       } else {
+               fprintf(stderr, "%s\n", net_strerror(net_errno()));
+       }
+}
+
+// Init and shutdown
+void net_init(void) {
+       puts("[NetSock]: NetSock initializing...");
+       fflush(stdout);
+       // Initialize WSA
+#if defined(_WIN32)
+       int WStartCode = WSAStartup(MAKEWORD(2, 0), &net_wd);
+       if (WStartCode) {
+               fprintf(stderr, "Winsock API startup failed: %s\n", net_strerror(WStartCode));
+               exit(EXIT_FAILURE);
+       }
+       printf("[NetSock]: WinSock initialized V%d.%d!\n",LOBYTE(net_wd.wVersion), HIBYTE(net_wd.wVersion));
+       fflush(stdout);
+#endif
+}
+void net_cleanup(void) {
+       puts("[NetSock]: NetSock cleaning up...");
+       fflush(stdout);
+       // Initialize WSA
+#if defined(_WIN32)
+       WSACleanup();
+       puts("[NetSock]: WinSock cleaned up! (probably)");
+       fflush(stdout);
+#endif
+}
+
+// Misc
+ssize_t send_log(SOCKET socket, const char *buffer, size_t length, int flags) {
+       printf("SERVER %"PRISocket": %s", socket, (char*)buffer);
+       fflush(stdout);
+       return send(socket, buffer, length, flags);
+}
+ssize_t recv_log(SOCKET socket, char *buffer, size_t length, int flags) {
+       ssize_t bytesRead = recv(socket,buffer,length,flags);
+       if(bytesRead > 0) {
+               buffer[bytesRead] = 0;
+               printf("CLIENT %"PRISocket": %s", socket, (char*)buffer);
+               fflush(stdout);
+       }
+       return bytesRead;
+}
+void net_sleep(unsigned int sec) {
+       struct timeval sleeptime;
+       sleeptime.tv_sec = sec;
+       select(0, NULL, NULL, NULL, &sleeptime);
+}
+void net_usleep(unsigned int usec) {
+       struct timeval sleeptime;
+       sleeptime.tv_usec = usec;
+       select(0, NULL, NULL, NULL, &sleeptime);
+}
diff --git a/NetSock/netsock.h b/NetSock/netsock.h
new file mode 100644 (file)
index 0000000..ead46ed
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _netsock_h
+#define _netsock_h
+#define FD_SETSIZE 1024
+
+// Standard headers
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+// Windows
+#if defined(_WIN32)
+#pragma message("Warning: Windows detected.")
+#pragma message("IMPORTANT: COMPILE WITH -lws2_32")
+#pragma comment(lib, "ws2_32.lib")
+//#include <WinSock2.h>
+//#include <WS2tcpip.h>
+//#include <Windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+//#define PRISocket "llu" // The format string for SOCKET
+#define PRISocket "p" // The format string for SOCKET
+#define net_errno() (WSAGetLastError())
+#define net_wouldblock() (WSAGetLastError() == WSAEWOULDBLOCK)
+// Funcs
+const char *net_strerror(int e);
+// Variables
+extern struct WSAData net_wd;
+
+// POSIX
+#else
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+//typedef unsigned long long SOCKET;
+typedef int SOCKET;
+#define PRISocket "d" // The format string for SOCKET
+#define net_errno() ((int)errno)
+#define net_strerror(e) strerror((e))
+#define net_wouldblock() (errno == EAGAIN || errno == EWOULDBLOCK)
+#define closesocket close
+#define ioctlsocket ioctl
+#define INVALID_SOCKET -1
+#endif
+
+// Funcs
+int net_nonblock(SOCKET fd);
+void net_perror(const char *p);
+void net_init(void);
+void net_cleanup(void);
+ssize_t send_log(SOCKET socket, const char *buffer, size_t length, int flags);
+ssize_t recv_log(SOCKET socket, char *buffer, size_t length, int flags);
+void net_sleep(unsigned int sec);
+void net_usleep(unsigned int usec);
+#endif
diff --git a/common.h b/common.h
new file mode 100644 (file)
index 0000000..7bbd8d9
--- /dev/null
+++ b/common.h
@@ -0,0 +1,15 @@
+#ifndef _common_h
+#define _common_h
+#include "NetSock/netsock.h"
+#include "config.h"
+
+struct client_data {
+       SOCKET FD;
+       char type;
+       char nick[32];
+       size_t nickLen;
+};
+extern struct client_data *clients[CLIENTS];
+extern fd_set readfds;
+
+#endif
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..913d250
--- /dev/null
+++ b/config.h
@@ -0,0 +1,5 @@
+#define LISTENING_PORT 6667
+#define LISTENING_BACKLOG 10
+#define CLIENTS 30
+#define SUPPORT_IPV4
+#define SUPPORT_IPV6
diff --git a/irc.c b/irc.c
new file mode 100644 (file)
index 0000000..b0c7411
--- /dev/null
+++ b/irc.c
@@ -0,0 +1,101 @@
+#include "irc.h"
+
+void processPacket(struct client_data *client, char *packet, size_t packetLen) {
+       if(strncmp(packet, "PING", 4) == 0) {
+               packet[1] = 'O';
+               send_log(client->FD, packet, packetLen, 0);
+       } else if(strncmp(packet, "NICK ", 5) == 0) {
+               // User now registered
+               setNick(client, packet+5, 32);
+               printf("USER SET NICKNAME %lu %s\n", client->nickLen, client->nick);
+               fflush(stdout);
+       } else if(strncmp(packet, "USER ", 5) == 0) {
+               // Send welcome
+               newUser(client);
+       } else if(strncmp(packet, "MOTD", 4) == 0) {
+               // Send welcome
+               sendMOTD(client);
+       // Horrible join but it works and its funny
+       } else if(strncmp(packet, "JOIN ", 5) == 0) {
+               char data[256];
+               data[0] = ':';
+               strcpy(data+1, client->nick);
+               strcpy(data+1+client->nickLen, " JOIN :");
+               strcpy(data+8+client->nickLen, packet+5);
+               send_log(client->FD, data, strlen(data), 0);
+               sendall_log(client->FD, data, strlen(data), 0);
+       } else if(strncmp(packet, "PRIVMSG ", 8) == 0) {
+               char data[256];
+               data[0] = ':';
+               strcpy(data+1, client->nick);
+               data[1+client->nickLen] = ' ';
+               strcpy(data+2+client->nickLen, packet);
+               sendall_log(client->FD, data, strlen(data), 0);
+       }
+}
+
+void newUser(struct client_data *client) {
+       char data[1024];
+       // Copy in basics
+       strcpy(data, ":irc.patchysicp.xyz 001 ");
+       strcpy(data+24, client->nick);
+       strcpy(data+24+client->nickLen, " :Welcome to PatchyIRCD!!!\n");
+       //send_log(client->FD, data, (26+client->nickLen+27), 0);
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Your host is PatchyIRCD V0.0.1\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '3';
+       strcpy(data+26+client->nickLen, "This server was created when I had cybersex with your mother.\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[20] = '2';
+       data[21] = '5';
+       data[22] = '1';
+       strcpy(data+26+client->nickLen, "This server exists\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Jannies don't exist\n");
+       send_log(client->FD, data, strlen(data), 0);
+       sendMOTD(client);
+}
+
+void sendMOTD(struct client_data *client) {
+       char data[1024];
+       // Copy in basics
+       strcpy(data, ":irc.patchysicp.xyz 375 ");
+       strcpy(data+24, client->nick);
+       strcpy(data+24+client->nickLen, " :PatchySICP /MOTD\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Welcome to Montreal!\n");
+       send_log(client->FD, data, strlen(data), 0);
+       strcpy(data+26+client->nickLen, "You are retarded and I will have cybersex with your mom.\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '6';
+       strcpy(data+26+client->nickLen, "/MOTD over\n");
+       send_log(client->FD, data, strlen(data), 0);
+}
+
+void setNick(struct client_data *client, char* nickname, size_t size) {
+       // TODO: perform basic sanitization
+       strncpy(client->nick, nickname, size);
+       // Null term
+       client->nick[size-1] = 0;
+       // Remove newline
+       int i;
+       for(i=0;i<size;i++){
+               // CR/^M
+               if(client->nick[i] == 13) {
+                       client->nick[i] = 0;
+                       break;
+               }
+               // Newline
+               if(client->nick[i] == 10) {
+                       client->nick[i] = 0;
+                       break;
+               }
+       }
+       // Set length
+       client->nickLen = strlen(client->nick);
+       return;
+}
diff --git a/irc.h b/irc.h
new file mode 100644 (file)
index 0000000..b8cdb40
--- /dev/null
+++ b/irc.h
@@ -0,0 +1,12 @@
+#ifndef _irc_h
+#define _irc_h
+
+#include "common.h"
+#include "net.h"
+
+void processPacket(struct client_data *client, char *packet, size_t packetLen);
+void newUser(struct client_data *client);
+void sendMOTD(struct client_data *client);
+void setNick(struct client_data *client, char* nickname, size_t size);
+
+#endif
diff --git a/main.c b/main.c
old mode 100755 (executable)
new mode 100644 (file)
index 94e9af5..a6e39bf
--- a/main.c
+++ b/main.c
-// Some macros to control options
-#define LISTENING_PORT 6667
-#define LISTENING_BACKLOG 10
-#define CLIENT_SOCKETS 30
-#define FD_SETSIZE 1024
-#define SUPPORT_IPV4
-#define SUPPORT_IPV6
+#include "common.h"
+#include "net.h"
+#include "irc.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#if defined(_WIN32)
-#pragma message("Warning: Windows detected.")
-//#include <WinSock2.h>
-//#include <WS2tcpip.h>
-//#include <Windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-#pragma message("IMPORTANT: COMPILE WITH -lws2_32")
-#pragma comment(lib, "ws2_32.lib")
-#define PRISocket "llu"
-#else
-#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/select.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <fcntl.h>
-//typedef unsigned long long SOCKET;
-typedef int SOCKET;
-#define PRISocket "d"
-#endif
-
-struct client_data {
-       SOCKET FD;
-       char type;
-       char nick[32];
-       size_t nickLen;
-};
-
-struct client_data client_socket[CLIENT_SOCKETS];
-
-#if defined(_WIN32)
-#define net_errno() (WSAGetLastError())
-const char *net_strerror(int e) {
-       static char msg[256];
-       if (!FormatMessageA(\
-              FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
-              NULL, e, 0, msg, 256, NULL))
-               sprintf(msg, "WSA Error %d", e);
-       return msg;
-}
-int net_nonblock(SOCKET fd) {
-       u_long v = 1;
-       return ioctlsocket(fd, FIONBIO, &v);
-}
-#else
-#define net_errno() ((int)errno)
-#define net_strerror(e) strerror((e))
-#define closesocket close
-#define INVALID_SOCKET -1
-int net_nonblock(SOCKET fd) {
-       int f = fcntl(fd, F_GETFL);
-       if (f == -1)
-               return -1;
-       return fcntl(fd, F_SETFL, f | O_NONBLOCK);
-}
-#endif
-void net_perror(const char *p)
-{
-       if (p && *p)
-               fprintf(stderr, "%s: %s\n", p, net_strerror(net_errno()));
-       else
-               fprintf(stderr, "%s\n", net_strerror(net_errno()));
-}
-
-size_t send_log(int socket, const void *buffer, size_t length, int flags) {
-       printf("SERVER: %s", (char*)buffer);
-       fflush(stdout);
-       return send(socket, buffer, length, flags);
-}
-
-void sendall_log(int socket, const void *buffer, size_t length, int flags) {
-       int i;
-       for(i=0;i<CLIENT_SOCKETS;i++) {
-               if(client_socket[i].FD == socket || client_socket[i].FD == 0) {
-                       continue;
-               } else {
-                       printf("SERVER: %"PRISocket" %s", client_socket[i].FD, (char*)buffer);
-                       fflush(stdout);
-                       send(client_socket[i].FD, buffer, length, flags);
-               }
-       }
-}
-
-// IRC STUFF COPY THIS WHEN WE REFINE ALL OF THIS CODE INTO THE NEW SERVER
-
-void processPacket(struct client_data *client, char *packet, size_t packetLen);
-void newUser(struct client_data *client);
-void sendMOTD(struct client_data *client);
-void setNick(struct client_data *client, char* nickname, size_t size);
-
-// TODO: check for newlines are process each one as a different packet
-void processPacket(struct client_data *client, char *packet, size_t packetLen) {
-       if(strncmp(packet, "PING", 4) == 0) {
-               packet[1] = 'O';
-               send_log(client_socket->FD, packet, packetLen, 0);
-       } else if(strncmp(packet, "NICK ", 5) == 0) {
-               // User now registered
-               setNick(client, packet+5, 32);
-               printf("USER SET NICKNAME %lu %s\n", client->nickLen, client->nick);
-               fflush(stdout);
-       } else if(strncmp(packet, "USER ", 5) == 0) {
-               // Send welcome
-               newUser(client);
-       } else if(strncmp(packet, "MOTD", 4) == 0) {
-               // Send welcome
-               sendMOTD(client);
-       // Horrible join but it works and its funny
-       } else if(strncmp(packet, "JOIN ", 5) == 0) {
-               char data[256];
-               data[0] = ':';
-               strcpy(data+1, client->nick);
-               strcpy(data+1+client->nickLen, " JOIN :");
-               strcpy(data+8+client->nickLen, packet+5);
-               send_log(client->FD, data, strlen(data), 0);
-               sendall_log(client->FD, data, strlen(data), 0);
-       } else if(strncmp(packet, "PRIVMSG ", 8) == 0) {
-               char data[256];
-               data[0] = ':';
-               strcpy(data+1, client->nick);
-               data[1+client->nickLen] = ' ';
-               strcpy(data+2+client->nickLen, packet);
-               sendall_log(client->FD, data, strlen(data), 0);
-       }
-
-}
-
-void newUser(struct client_data *client) {
-       char data[1024];
-       // Copy in basics
-       strcpy(data, ":irc.patchysicp.xyz 001 ");
-       strcpy(data+24, client->nick);
-       strcpy(data+24+client->nickLen, " :Welcome to PatchyIRCD!!!\n");
-       //send_log(client->FD, data, (26+client->nickLen+27), 0);
-       send_log(client->FD, data, strlen(data), 0);
-       data[22] = '2';
-       strcpy(data+26+client->nickLen, "Your host is PatchyIRCD V0.0.0\n");
-       send_log(client->FD, data, strlen(data), 0);
-       data[22] = '3';
-       strcpy(data+26+client->nickLen, "This server was created when I had cybersex with your mother.\n");
-       send_log(client->FD, data, strlen(data), 0);
-       data[20] = '2';
-       data[21] = '5';
-       data[22] = '1';
-       strcpy(data+26+client->nickLen, "This server exists\n");
-       send_log(client->FD, data, strlen(data), 0);
-       data[22] = '2';
-       strcpy(data+26+client->nickLen, "Jannies don't exist\n");
-       send_log(client->FD, data, strlen(data), 0);
-       sendMOTD(client);
-}
-
-void sendMOTD(struct client_data *client) {
-       char data[1024];
-       // Copy in basics
-       strcpy(data, ":irc.patchysicp.xyz 375 ");
-       strcpy(data+24, client->nick);
-       strcpy(data+24+client->nickLen, " :PatchySICP /MOTD\n");
-       send_log(client->FD, data, strlen(data), 0);
-       data[22] = '2';
-       strcpy(data+26+client->nickLen, "Welcome to Montreal!\n");
-       send_log(client->FD, data, strlen(data), 0);
-       strcpy(data+26+client->nickLen, "You are retarded and I will have cybersex with your mom.\n");
-       send_log(client->FD, data, strlen(data), 0);
-       data[22] = '6';
-       strcpy(data+26+client->nickLen, "/MOTD over\n");
-       send_log(client->FD, data, strlen(data), 0);
-}
+// Client linked list
+struct client_data *clients[CLIENTS];
+// FDSET List
+fd_set readfds;
 
-void setNick(struct client_data *client, char* nickname, size_t size) {
-       // TODO: perform basic sanitization
-       strncpy(client->nick, nickname, size);
-       // Null term
-       client->nick[size-1] = 0;
-       // Remove newline
-       int i;
-       for(i=0;i<size;i++){
-               // CR/^M
-               if(client->nick[i] == 13) {
-                       client->nick[i] = 0;
-                       break;
-               }
-               // Newline
-               if(client->nick[i] == 10) {
-                       client->nick[i] = 0;
-                       break;
-               }
-       }
-       // Set length
-       client->nickLen = strlen(client->nick);
-       return;
-}
-
-int main(){
-       fd_set readfds;
-       SOCKET highestFD;
-       int i;
-       SOCKET SD;
+int main() {
+       int opt = 1;
        SOCKET serverSocketV4 = 0;
        SOCKET serverSocketV6 = 0;
+       SOCKET highestFD;
+       SOCKET SD;
+       int i;
        char client_addr[100];
        char *welcomeMessage = ":irc.patchysicp.xyz NOTICE * :Hello welcome to PatchyIRCD!\n";
        char buffer[1024];
        size_t bytesRead;
+       puts("[PatchyIRCD]: Starting up...");
+       fflush(stdout);
 
-#if defined(_WIN32)
-       struct WSAData wd;
-       if (WSAStartup(MAKEWORD(2, 0), &wd)) printf("Winsock API startup failed.\n");
-#endif
+       net_init();
 
-       puts("Starting");
-       fflush(stdout);
+       // Zero stuff out
+       memset(clients, 0, sizeof(clients));
 
+       // Setup structs
 #ifdef SUPPORT_IPV4
        struct sockaddr_in serverAddrV4;
        memset(&serverAddrV4, 0, sizeof(struct sockaddr_in));
@@ -243,8 +44,6 @@ int main(){
        serverAddrV6.sin6_family = AF_INET6;
        size_t serverAddrV6len = sizeof(serverAddrV6);
 #endif
-
-       int opt = 1;
 #ifdef SUPPORT_IPV4
        // Create socket
        serverSocketV4 = socket(AF_INET, SOCK_STREAM, 0);
@@ -309,32 +108,26 @@ int main(){
        }
 #endif
 
-       memset(client_socket, 0, sizeof(client_socket));
 
-       puts("Ready");
-       fflush(stdout);
+
+       // Main loop
        while(1){
-               // Clear all sockets
                FD_ZERO(&readfds); 
-               // Add main sockets
+               // Add listening SOCKETS to FDSET
 #ifdef SUPPORT_IPV4
                FD_SET(serverSocketV4, &readfds);
 #endif
 #ifdef SUPPORT_IPV6
                FD_SET(serverSocketV6, &readfds);
 #endif
+               // Set highestFD
                if(serverSocketV4 < serverSocketV6) highestFD = serverSocketV6;
                else highestFD = serverSocketV4;
-
-               // Check for new sockets
-               for(i=0;i<CLIENT_SOCKETS;i++) {
-                       SD = client_socket[i].FD;
-                       // Valid FD
-                       if(SD>0){
-                               FD_SET(SD, &readfds);
-                               // Update highest FD
-                               if(SD>highestFD){
-                                       highestFD = SD;
+               for(i=0;i<CLIENTS;i++) {
+                       if(clients[i] != 0){
+                               FD_SET(clients[i]->FD, &readfds);
+                               if(clients[i]->FD>highestFD){
+                                       highestFD = clients[i]->FD;
                                }
                        }
                }
@@ -344,6 +137,8 @@ int main(){
                        net_perror("ERROR SELECT");
                }
 
+               // Accept new connections
+               // TODO: Optimize this with goto
 #ifdef SUPPORT_IPV4
                if (FD_ISSET(serverSocketV4, &readfds)) {
                        SOCKET newSocket = accept(serverSocketV4, NULL, NULL);
@@ -356,12 +151,13 @@ int main(){
                        fflush(stdout);
                        send_log(newSocket, welcomeMessage, strlen(welcomeMessage), 0);
                        // Add to list of sockets
-                       for(i=0;i<CLIENT_SOCKETS;i++) {
-                               if(client_socket[i].FD==0){
-                                       client_socket[i].FD = newSocket;
-                                       client_socket[i].type = 4;
+                       for(i=0;i<CLIENTS;i++) {
+                               if(clients[i] == 0){
+                                       clients[i] = allocClient();
+                                       clients[i]->FD = newSocket;
+                                       clients[i]->type = 4;
                                        // Set nonblock
-                                       net_nonblock(client_socket[i].FD);
+                                       net_nonblock(clients[i]->FD);
                                        break;
                                }
                        }
@@ -379,27 +175,37 @@ int main(){
                        fflush(stdout);
                        send_log(newSocket, welcomeMessage, strlen(welcomeMessage), 0);
                        // Add to list of sockets
-                       for(i=0;i<CLIENT_SOCKETS;i++) {
-                               if(client_socket[i].FD==0){
-                                       client_socket[i].FD = newSocket;
-                                       client_socket[i].type = 6;
+                       for(i=0;i<CLIENTS;i++) {
+                               if(clients[i] == 0){
+                                       clients[i] = allocClient();
+                                       clients[i]->FD = newSocket;
+                                       clients[i]->type = 6;
                                        // Set nonblock
-                                       net_nonblock(client_socket[i].FD);
+                                       net_nonblock(clients[i]->FD);
                                        break;
                                }
                        }
                }
 #endif
                // Respond to already connected clients
-               for(i=0;i<CLIENT_SOCKETS;i++) {
-                       SD = client_socket[i].FD;
+               for(i=0;i<CLIENTS;i++) {
+                       if(clients[i] == 0) continue;
+                       SD = clients[i]->FD;
                        if(FD_ISSET(SD, &readfds)) {
                                //bytesRead = read(SD, buffer, sizeof(buffer));
-                               bytesRead = recv(SD,buffer,sizeof(buffer), 0);
+                               bytesRead = recv_log(SD,buffer,sizeof(buffer), 0);
+
+                               if(bytesRead == -1) {
+                                       if(net_wouldblock()) {
+                                               goto endOfLoop;
+                                       }
+                                       net_perror("RECV");
+                               }
+
                                // Disconnect
                                if(bytesRead == 0) {
 #ifdef SUPPORT_IPV4
-                                       if(client_socket[i].type == 4) {
+                                       if(clients[i]->type == 4) {
                                                getpeername(SD,(struct sockaddr*)&serverAddrV4,(socklen_t*)&serverAddrV4len);  
                                                inet_ntop(AF_INET, &(serverAddrV4.sin_addr), client_addr, sizeof(client_addr));
                                                printf("Client disconnected from Socket: %"PRISocket", IP: %s PORT: %d\n", SD, client_addr, ntohs(serverAddrV4.sin_port));
@@ -407,22 +213,17 @@ int main(){
                                        }
 #endif
 #ifdef SUPPORT_IPV6
-                                       if(client_socket[i].type == 6) {
+                                       if(clients[i]->type == 6) {
                                                getpeername(SD,(struct sockaddr*)&serverAddrV6,(socklen_t*)&serverAddrV6len);  
                                                inet_ntop(AF_INET6, &(serverAddrV6.sin6_addr), client_addr, sizeof(client_addr));
                                                printf("Client disconnected from Socket: %"PRISocket", IP: %s PORT: %d\n", SD, client_addr, ntohs(serverAddrV6.sin6_port));
                                                fflush(stdout);
                                        }
 #endif
-                                       closesocket(SD);
-                                       client_socket[i].FD = 0;
+                                       killConnection(clients[i]);
                                }  else {
                                        // Add null byte
                                        buffer[bytesRead] = '\0';
-                                       // Send it back
-                                       //send(SD,buffer,bytesRead,0);  
-                                       printf("CLIENT: %s", buffer);
-                                       fflush(stdout);
 
                                        int j;
                                        char *buffer2 = buffer;
@@ -432,24 +233,24 @@ int main(){
                                                        char tmp = buffer[j+1];
                                                        buffer[j+1] = 0;
                                                        //Send to processing
-                                                       processPacket(&(client_socket[i]), buffer2, strlen(buffer2));
+                                                       processPacket(clients[i], buffer2, strlen(buffer2));
                                                        buffer[j+1] = tmp;
                                                        buffer2 = &(buffer[j+1]);
                                                }
                                        }
                                }
+                               endOfLoop:;
                        }
                }
        }
 
-#if defined(_WIN32)
-       WSACleanup();
-#endif
-       for(i=0;i<CLIENT_SOCKETS;i++) {
-               if(client_socket[i].FD>0) {
-                       closesocket(client_socket[i].FD);
+       puts("[PatchyIRCD]: Cleaning up...");
+       fflush(stdout);
+       for(i=0;i<CLIENTS;i++) {
+               if(clients[i] != 0) {
+                       killConnection(clients[i]);
                }
        }
+       net_cleanup();
        return 0;
 }
-
diff --git a/net.c b/net.c
new file mode 100644 (file)
index 0000000..772cd6a
--- /dev/null
+++ b/net.c
@@ -0,0 +1,30 @@
+#include "net.h"
+
+void sendall_log(SOCKET socket, const char *buffer, size_t length, int flags) {
+       int i;
+       for(i=0;i<CLIENTS;i++) {
+               if(clients[i] == 0) continue;
+               if(clients[i]->FD == socket) {
+                       continue;
+               } else {
+                       send_log(clients[i]->FD, buffer, length, flags);
+               }
+       }
+}
+
+struct client_data *allocClient(){
+       struct client_data *NewClient = malloc(sizeof(struct client_data));
+       memset(NewClient, 0, sizeof(struct client_data));
+       return NewClient;
+};
+
+void killConnection(struct client_data *client) {
+       int i;
+       for(i=0;i<CLIENTS;i++) {
+               if(clients[i] == client) {
+                       clients[i] = 0;
+               }
+       }
+       closesocket(client->FD);
+       free(client);
+}
diff --git a/net.h b/net.h
new file mode 100644 (file)
index 0000000..5df0459
--- /dev/null
+++ b/net.h
@@ -0,0 +1,9 @@
+#ifndef _net_h
+#define _net_h
+#include "common.h"
+
+void sendall_log(SOCKET socket, const char *buffer, size_t length, int flags);
+struct client_data *allocClient();
+void killConnection(struct client_data *client);
+
+#endif
similarity index 100%
rename from client.c
rename to networking-tests/client.c
diff --git a/networking-tests/main.c b/networking-tests/main.c
new file mode 100755 (executable)
index 0000000..94e9af5
--- /dev/null
@@ -0,0 +1,455 @@
+// Some macros to control options
+#define LISTENING_PORT 6667
+#define LISTENING_BACKLOG 10
+#define CLIENT_SOCKETS 30
+#define FD_SETSIZE 1024
+#define SUPPORT_IPV4
+#define SUPPORT_IPV6
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#if defined(_WIN32)
+#pragma message("Warning: Windows detected.")
+//#include <WinSock2.h>
+//#include <WS2tcpip.h>
+//#include <Windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+#pragma message("IMPORTANT: COMPILE WITH -lws2_32")
+#pragma comment(lib, "ws2_32.lib")
+#define PRISocket "llu"
+#else
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <fcntl.h>
+//typedef unsigned long long SOCKET;
+typedef int SOCKET;
+#define PRISocket "d"
+#endif
+
+struct client_data {
+       SOCKET FD;
+       char type;
+       char nick[32];
+       size_t nickLen;
+};
+
+struct client_data client_socket[CLIENT_SOCKETS];
+
+#if defined(_WIN32)
+#define net_errno() (WSAGetLastError())
+const char *net_strerror(int e) {
+       static char msg[256];
+       if (!FormatMessageA(\
+              FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+              NULL, e, 0, msg, 256, NULL))
+               sprintf(msg, "WSA Error %d", e);
+       return msg;
+}
+int net_nonblock(SOCKET fd) {
+       u_long v = 1;
+       return ioctlsocket(fd, FIONBIO, &v);
+}
+#else
+#define net_errno() ((int)errno)
+#define net_strerror(e) strerror((e))
+#define closesocket close
+#define INVALID_SOCKET -1
+int net_nonblock(SOCKET fd) {
+       int f = fcntl(fd, F_GETFL);
+       if (f == -1)
+               return -1;
+       return fcntl(fd, F_SETFL, f | O_NONBLOCK);
+}
+#endif
+void net_perror(const char *p)
+{
+       if (p && *p)
+               fprintf(stderr, "%s: %s\n", p, net_strerror(net_errno()));
+       else
+               fprintf(stderr, "%s\n", net_strerror(net_errno()));
+}
+
+size_t send_log(int socket, const void *buffer, size_t length, int flags) {
+       printf("SERVER: %s", (char*)buffer);
+       fflush(stdout);
+       return send(socket, buffer, length, flags);
+}
+
+void sendall_log(int socket, const void *buffer, size_t length, int flags) {
+       int i;
+       for(i=0;i<CLIENT_SOCKETS;i++) {
+               if(client_socket[i].FD == socket || client_socket[i].FD == 0) {
+                       continue;
+               } else {
+                       printf("SERVER: %"PRISocket" %s", client_socket[i].FD, (char*)buffer);
+                       fflush(stdout);
+                       send(client_socket[i].FD, buffer, length, flags);
+               }
+       }
+}
+
+// IRC STUFF COPY THIS WHEN WE REFINE ALL OF THIS CODE INTO THE NEW SERVER
+
+void processPacket(struct client_data *client, char *packet, size_t packetLen);
+void newUser(struct client_data *client);
+void sendMOTD(struct client_data *client);
+void setNick(struct client_data *client, char* nickname, size_t size);
+
+// TODO: check for newlines are process each one as a different packet
+void processPacket(struct client_data *client, char *packet, size_t packetLen) {
+       if(strncmp(packet, "PING", 4) == 0) {
+               packet[1] = 'O';
+               send_log(client_socket->FD, packet, packetLen, 0);
+       } else if(strncmp(packet, "NICK ", 5) == 0) {
+               // User now registered
+               setNick(client, packet+5, 32);
+               printf("USER SET NICKNAME %lu %s\n", client->nickLen, client->nick);
+               fflush(stdout);
+       } else if(strncmp(packet, "USER ", 5) == 0) {
+               // Send welcome
+               newUser(client);
+       } else if(strncmp(packet, "MOTD", 4) == 0) {
+               // Send welcome
+               sendMOTD(client);
+       // Horrible join but it works and its funny
+       } else if(strncmp(packet, "JOIN ", 5) == 0) {
+               char data[256];
+               data[0] = ':';
+               strcpy(data+1, client->nick);
+               strcpy(data+1+client->nickLen, " JOIN :");
+               strcpy(data+8+client->nickLen, packet+5);
+               send_log(client->FD, data, strlen(data), 0);
+               sendall_log(client->FD, data, strlen(data), 0);
+       } else if(strncmp(packet, "PRIVMSG ", 8) == 0) {
+               char data[256];
+               data[0] = ':';
+               strcpy(data+1, client->nick);
+               data[1+client->nickLen] = ' ';
+               strcpy(data+2+client->nickLen, packet);
+               sendall_log(client->FD, data, strlen(data), 0);
+       }
+
+}
+
+void newUser(struct client_data *client) {
+       char data[1024];
+       // Copy in basics
+       strcpy(data, ":irc.patchysicp.xyz 001 ");
+       strcpy(data+24, client->nick);
+       strcpy(data+24+client->nickLen, " :Welcome to PatchyIRCD!!!\n");
+       //send_log(client->FD, data, (26+client->nickLen+27), 0);
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Your host is PatchyIRCD V0.0.0\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '3';
+       strcpy(data+26+client->nickLen, "This server was created when I had cybersex with your mother.\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[20] = '2';
+       data[21] = '5';
+       data[22] = '1';
+       strcpy(data+26+client->nickLen, "This server exists\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Jannies don't exist\n");
+       send_log(client->FD, data, strlen(data), 0);
+       sendMOTD(client);
+}
+
+void sendMOTD(struct client_data *client) {
+       char data[1024];
+       // Copy in basics
+       strcpy(data, ":irc.patchysicp.xyz 375 ");
+       strcpy(data+24, client->nick);
+       strcpy(data+24+client->nickLen, " :PatchySICP /MOTD\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '2';
+       strcpy(data+26+client->nickLen, "Welcome to Montreal!\n");
+       send_log(client->FD, data, strlen(data), 0);
+       strcpy(data+26+client->nickLen, "You are retarded and I will have cybersex with your mom.\n");
+       send_log(client->FD, data, strlen(data), 0);
+       data[22] = '6';
+       strcpy(data+26+client->nickLen, "/MOTD over\n");
+       send_log(client->FD, data, strlen(data), 0);
+}
+
+void setNick(struct client_data *client, char* nickname, size_t size) {
+       // TODO: perform basic sanitization
+       strncpy(client->nick, nickname, size);
+       // Null term
+       client->nick[size-1] = 0;
+       // Remove newline
+       int i;
+       for(i=0;i<size;i++){
+               // CR/^M
+               if(client->nick[i] == 13) {
+                       client->nick[i] = 0;
+                       break;
+               }
+               // Newline
+               if(client->nick[i] == 10) {
+                       client->nick[i] = 0;
+                       break;
+               }
+       }
+       // Set length
+       client->nickLen = strlen(client->nick);
+       return;
+}
+
+int main(){
+       fd_set readfds;
+       SOCKET highestFD;
+       int i;
+       SOCKET SD;
+       SOCKET serverSocketV4 = 0;
+       SOCKET serverSocketV6 = 0;
+       char client_addr[100];
+       char *welcomeMessage = ":irc.patchysicp.xyz NOTICE * :Hello welcome to PatchyIRCD!\n";
+       char buffer[1024];
+       size_t bytesRead;
+
+#if defined(_WIN32)
+       struct WSAData wd;
+       if (WSAStartup(MAKEWORD(2, 0), &wd)) printf("Winsock API startup failed.\n");
+#endif
+
+       puts("Starting");
+       fflush(stdout);
+
+#ifdef SUPPORT_IPV4
+       struct sockaddr_in serverAddrV4;
+       memset(&serverAddrV4, 0, sizeof(struct sockaddr_in));
+       serverAddrV4.sin_addr.s_addr = INADDR_ANY;
+       serverAddrV4.sin_port = htons(LISTENING_PORT);
+       serverAddrV4.sin_family = AF_INET;
+       size_t serverAddrV4len = sizeof(serverAddrV4);
+#endif
+#ifdef SUPPORT_IPV6
+       struct sockaddr_in6 serverAddrV6;
+       memset(&serverAddrV6, 0, sizeof(struct sockaddr_in6));
+       serverAddrV6.sin6_addr = in6addr_any;
+       serverAddrV6.sin6_flowinfo = 0;
+       serverAddrV6.sin6_port = htons(LISTENING_PORT);
+       serverAddrV6.sin6_family = AF_INET6;
+       size_t serverAddrV6len = sizeof(serverAddrV6);
+#endif
+
+       int opt = 1;
+#ifdef SUPPORT_IPV4
+       // Create socket
+       serverSocketV4 = socket(AF_INET, SOCK_STREAM, 0);
+       if(serverSocketV4 == (SOCKET)INVALID_SOCKET) {
+               net_perror("ERROR SOCKET IPV4");
+               exit(EXIT_FAILURE);
+       }
+       // Set socket options
+       if(setsockopt(serverSocketV4, SOL_SOCKET,\
+             SO_REUSEADDR,\
+             (void*)&opt, sizeof(opt)) == -1) {
+               net_perror("ERROR SOCKET IPV4");
+               exit(EXIT_FAILURE);
+       }
+       // Set nonblock 
+       net_nonblock(serverSocketV4);
+       // Bind to socket
+       if(bind(serverSocketV4, (struct sockaddr*)&serverAddrV4,\
+             sizeof(struct sockaddr_in)) == -1) {
+               net_perror("ERROR BIND IPV4");
+               exit(EXIT_FAILURE);
+       }
+       // Listen to socket
+       if(listen(serverSocketV4, LISTENING_BACKLOG) == -1) {
+               net_perror("ERROR LISTEN IPV4");
+               exit(EXIT_FAILURE);
+       }
+#endif
+#ifdef SUPPORT_IPV6
+       // Create socket
+       serverSocketV6 = socket(AF_INET6, SOCK_STREAM, 0);
+       if(serverSocketV6 == (SOCKET)INVALID_SOCKET) {
+               net_perror("ERROR SOCKET IPV6");
+               exit(EXIT_FAILURE);
+       }
+       // Set socket options
+       if(setsockopt(serverSocketV6, SOL_SOCKET,\
+             SO_REUSEADDR,\
+             (void*)&opt, sizeof(opt)) == -1) {
+               net_perror("ERROR SOCKET IPV6");
+               exit(EXIT_FAILURE);
+       }
+       // IPV6 Only
+       if(setsockopt(serverSocketV6, IPPROTO_IPV6,\
+             IPV6_V6ONLY,\
+             (void*)&opt, sizeof(opt)) == -1) {
+               net_perror("ERROR SOCKET IPV6");
+               exit(EXIT_FAILURE);
+       }
+       // Set nonblock 
+       net_nonblock(serverSocketV6);
+       // Bind to socket
+       if(bind(serverSocketV6, (struct sockaddr*)&serverAddrV6,\
+             sizeof(struct sockaddr_in6)) == -1) {
+               net_perror("ERROR BIND IPV6");
+               exit(EXIT_FAILURE);
+       }
+       // Listen to socket
+       if(listen(serverSocketV6, LISTENING_BACKLOG) == -1) {
+               net_perror("ERROR LISTEN IPV6");
+               exit(EXIT_FAILURE);
+       }
+#endif
+
+       memset(client_socket, 0, sizeof(client_socket));
+
+       puts("Ready");
+       fflush(stdout);
+       while(1){
+               // Clear all sockets
+               FD_ZERO(&readfds); 
+               // Add main sockets
+#ifdef SUPPORT_IPV4
+               FD_SET(serverSocketV4, &readfds);
+#endif
+#ifdef SUPPORT_IPV6
+               FD_SET(serverSocketV6, &readfds);
+#endif
+               if(serverSocketV4 < serverSocketV6) highestFD = serverSocketV6;
+               else highestFD = serverSocketV4;
+
+               // Check for new sockets
+               for(i=0;i<CLIENT_SOCKETS;i++) {
+                       SD = client_socket[i].FD;
+                       // Valid FD
+                       if(SD>0){
+                               FD_SET(SD, &readfds);
+                               // Update highest FD
+                               if(SD>highestFD){
+                                       highestFD = SD;
+                               }
+                       }
+               }
+
+               // Wait until activity on sockets
+               if(select(highestFD+1,&readfds,NULL,NULL,NULL) == -1) {
+                       net_perror("ERROR SELECT");
+               }
+
+#ifdef SUPPORT_IPV4
+               if (FD_ISSET(serverSocketV4, &readfds)) {
+                       SOCKET newSocket = accept(serverSocketV4, NULL, NULL);
+                       if(newSocket == (SOCKET)INVALID_SOCKET){
+                               net_perror("ERROR newSocket IPV4");
+                       }
+                       getpeername(newSocket,(struct sockaddr*)&serverAddrV4,(socklen_t*)&serverAddrV4len);  
+                       inet_ntop(AF_INET, &(serverAddrV4.sin_addr), client_addr, sizeof(client_addr));
+                       printf("Connection accepted from Socket: %"PRISocket", IP: %s PORT: %d\n", newSocket, client_addr, ntohs(serverAddrV4.sin_port));
+                       fflush(stdout);
+                       send_log(newSocket, welcomeMessage, strlen(welcomeMessage), 0);
+                       // Add to list of sockets
+                       for(i=0;i<CLIENT_SOCKETS;i++) {
+                               if(client_socket[i].FD==0){
+                                       client_socket[i].FD = newSocket;
+                                       client_socket[i].type = 4;
+                                       // Set nonblock
+                                       net_nonblock(client_socket[i].FD);
+                                       break;
+                               }
+                       }
+               }
+#endif
+#ifdef SUPPORT_IPV6
+               if (FD_ISSET(serverSocketV6, &readfds)) {
+                       SOCKET newSocket = accept(serverSocketV6, NULL, NULL);
+                       if(newSocket == (SOCKET)INVALID_SOCKET){
+                               net_perror("ERROR newSocket IPV6");
+                       }
+                       getpeername(newSocket,(struct sockaddr*)&serverAddrV6,(socklen_t*)&serverAddrV6len);  
+                       inet_ntop(AF_INET6, &(serverAddrV6.sin6_addr), client_addr, sizeof(client_addr));
+                       printf("Connection accepted from Socket: %"PRISocket", IP: %s PORT: %d\n", newSocket, client_addr, ntohs(serverAddrV6.sin6_port));
+                       fflush(stdout);
+                       send_log(newSocket, welcomeMessage, strlen(welcomeMessage), 0);
+                       // Add to list of sockets
+                       for(i=0;i<CLIENT_SOCKETS;i++) {
+                               if(client_socket[i].FD==0){
+                                       client_socket[i].FD = newSocket;
+                                       client_socket[i].type = 6;
+                                       // Set nonblock
+                                       net_nonblock(client_socket[i].FD);
+                                       break;
+                               }
+                       }
+               }
+#endif
+               // Respond to already connected clients
+               for(i=0;i<CLIENT_SOCKETS;i++) {
+                       SD = client_socket[i].FD;
+                       if(FD_ISSET(SD, &readfds)) {
+                               //bytesRead = read(SD, buffer, sizeof(buffer));
+                               bytesRead = recv(SD,buffer,sizeof(buffer), 0);
+                               // Disconnect
+                               if(bytesRead == 0) {
+#ifdef SUPPORT_IPV4
+                                       if(client_socket[i].type == 4) {
+                                               getpeername(SD,(struct sockaddr*)&serverAddrV4,(socklen_t*)&serverAddrV4len);  
+                                               inet_ntop(AF_INET, &(serverAddrV4.sin_addr), client_addr, sizeof(client_addr));
+                                               printf("Client disconnected from Socket: %"PRISocket", IP: %s PORT: %d\n", SD, client_addr, ntohs(serverAddrV4.sin_port));
+                                               fflush(stdout);
+                                       }
+#endif
+#ifdef SUPPORT_IPV6
+                                       if(client_socket[i].type == 6) {
+                                               getpeername(SD,(struct sockaddr*)&serverAddrV6,(socklen_t*)&serverAddrV6len);  
+                                               inet_ntop(AF_INET6, &(serverAddrV6.sin6_addr), client_addr, sizeof(client_addr));
+                                               printf("Client disconnected from Socket: %"PRISocket", IP: %s PORT: %d\n", SD, client_addr, ntohs(serverAddrV6.sin6_port));
+                                               fflush(stdout);
+                                       }
+#endif
+                                       closesocket(SD);
+                                       client_socket[i].FD = 0;
+                               }  else {
+                                       // Add null byte
+                                       buffer[bytesRead] = '\0';
+                                       // Send it back
+                                       //send(SD,buffer,bytesRead,0);  
+                                       printf("CLIENT: %s", buffer);
+                                       fflush(stdout);
+
+                                       int j;
+                                       char *buffer2 = buffer;
+                                       char tmp;
+                                       for(j=0;j<bytesRead;j++){
+                                               if(buffer[j] == '\n'){
+                                                       char tmp = buffer[j+1];
+                                                       buffer[j+1] = 0;
+                                                       //Send to processing
+                                                       processPacket(&(client_socket[i]), buffer2, strlen(buffer2));
+                                                       buffer[j+1] = tmp;
+                                                       buffer2 = &(buffer[j+1]);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+#if defined(_WIN32)
+       WSACleanup();
+#endif
+       for(i=0;i<CLIENT_SOCKETS;i++) {
+               if(client_socket[i].FD>0) {
+                       closesocket(client_socket[i].FD);
+               }
+       }
+       return 0;
+}
+