struct dynarr databuf;
+const char *hostname = "irc.patchysicp.xyz";
int processPacket(struct client_data *client) {
- char *packet = client->buf;
- //size_t packetLen = client->bufLen;
+ char *source = NULL;
+ char *command = NULL;
+ char *args[16] = {0};
+ int argc = 0;
+ {
+ char *p = client->buf;
+ { // remove \r
+ char *end = strchr(p, '\n');
+ if (!end) {
+ killConnection(client, false);
+ return 1; // null detected
+ }
+ if (end > p && end[-1] == '\r')
+ end[-1] = '\n';
+ if (strchr(p, '\r')) {
+ killConnection(client, false);
+ return 1; // internal \r detected
+ }
+ }
+ if (*p == ':') {
+ source = p;
+ while (*p != ' ' && *p != '\n')
+ p++;
+ if (*p++ == '\n') {
+ killConnection(client, true);
+ return 1; // no command
+ }
+ p[-1] = '\0';
+ }
+ command = p;
+ while (*p != ' ' && *p != '\n')
+ p++;
+ int more_args = *p++ != '\n';
+ p[-1] = '\0';
+ stringupper(command);
+ while (more_args) {
+ if (argc == 15) // too many arguments
+ break;
+ while (*p == ' ')
+ p++;
+ if (*p == '\n')
+ break;
+ int is_colon = *p == ':';
+ args[argc++] = p += is_colon;
+ if (is_colon) {
+ if (*p == '\n')
+ argc--; // empty trailing argument
+ while (*p != '\n')
+ p++;
+ *p = '\0';
+ break;
+ } else {
+ while (*p != ' ' && *p != '\n')
+ p++;
+ more_args = *p++ != '\n';
+ p[-1] = '\0';
+ }
+ }
+ args[argc] = NULL;
+ }
+ printf("parsed message: %s", command);
+ for (int i = 0; i < argc; i++){
+ printf(" %d:%s", i, args[i]);
+ if (i == argc-1)
+ printf("\n");
+ }
databuf.len = 0;
- if(strncmp(packet, "PING", 4) == 0) {
- append_str(&databuf, ":irc.patchysicp.xyz PONG irc.patchysicp.xyz :");
- append_str(&databuf, packet+5);
+ if(strcmp(command, "PING") == 0) {
+ if (!args[0]) // FIXME: error message
+ return 0;
+ append_strf(&databuf, ":%s PONG %s :%s", hostname, hostname, args[0]);
send_log(client->FD, databuf.buf, databuf.len, 0);
- } else if(strncmp(packet, "NICK ", 5) == 0) {
+ } else if(strcmp(command, "NICK") == 0) {
// User now registered
- setNick(client, packet+5, 32);
+ if (!args[0]) // FIXME: error message
+ return 0;
+ setNick(client, args[0], 32);
printf("USER SET NICKNAME %s\n", client->nick);
fflush(stdout);
- } else if(strncmp(packet, "USER ", 5) == 0) {
+ } else if(strcmp(command, "USER") == 0) {
// Send welcome
newUser(client);
- } else if(strncmp(packet, "MOTD", 4) == 0) {
+ } else if(strcmp(command, "MOTD") == 0) {
// Send welcome
sendMOTD(client);
- // Horrible join but it works and its funny
- } else if(strncmp(packet, "JOIN ", 5) == 0) {
- char *i;
- append_str(&databuf, ":");
- append_str(&databuf, client->nick);
- append_str(&databuf, " JOIN :");
- // Start GitHub Copilot
- if(packet[5] == ':') {
- i = packet+6;
- } else {
- i = packet+5;
- }
- append_str(&databuf, i);
- i = databuf.buf+8+client->nickLen;
- while(*i != '\0') {
- // Fuck you and multiple channels at once
- // TODO: actually implement multiple channels
- if(*i == ' ' || *i == ',') {
- *i = '\n';
- *(i+1) = 0;
+ } else if(strcmp(command, "JOIN") == 0) {
+ if (!args[0]) // FIXME: error message
+ return 0;
+ for (char *p = args[0]; *p; p++) // TODO: multiple channels
+ if (*p == ',') {
+ *p = '\0';
break;
}
- i++;
- }
- databuf.len = strlen(databuf.buf);
+ append_strf(&databuf, ":%s JOIN :%s\n", client->nick, args[0]);
// End GitHub Copilot
send_log(client->FD, databuf.buf, databuf.len, 0);
sendall_log(client->FD, databuf.buf, databuf.len, 0);
- *strchr(packet, '\n') = '\0';
for(int i=0; i<CLIENTS; i++)
if(clients[i] && clients[i]->nick[0]) {
databuf.len = 0;
- append_strf(&databuf, ":irc.patchysicp.xyz 353 %s = %s :%s\n", client->nick, packet+5+(packet[5]==':'), clients[i]->nick);
+ append_strf(&databuf, ":%s 353 %s = %s :%s\n", hostname, client->nick, args[0], clients[i]->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
}
databuf.len = 0;
- append_strf(&databuf, ":irc.patchysicp.xyz 366 %s :End of /NAMES list\n", client->nick);
+ append_strf(&databuf, ":%s 366 %s :End of /NAMES list\n", hostname, client->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
- } else if(strncmp(packet, "PRIVMSG ", 8) == 0) {
- append_str(&databuf, ":");
- append_str(&databuf, client->nick);
- append_str(&databuf, " ");
- append_str(&databuf, packet);
+ } else if(strcmp(command, "PRIVMSG") == 0) {
+ if (argc < 2) // FIXME: error message
+ return 0;
+ append_strf(&databuf, ":%s PRIVMSG %s :%s\n", client->nick, args[0], args[1]);
sendall_log(client->FD, databuf.buf, databuf.len, 0);
// Start GitHub Copilot - this shit actually be copy pasting my code lmao
- } else if(strncmp(packet, "QUIT", 4) == 0) {
- append_str(&databuf, ":");
- append_str(&databuf, client->nick);
- append_str(&databuf, " QUIT :");
- if(packet[4] == ' ') {
- if(packet[5] == ':') {
- append_str(&databuf, packet+6);
- } else {
- append_str(&databuf, packet+5);
- }
- } else {
- append_str(&databuf, "Client Quit\n");
- }
+ } else if(strcmp(command, "QUIT") == 0) {
+ append_strf(&databuf, ":%s QUIT :%s\n", client->nick, args[0] ? args[0] : "Client Quit");
sendall_log(client->FD, databuf.buf, databuf.len, 0);
killConnection(client, true);
return 1;
- } else if(strncmp(packet, "PONG", 4) == 0) {
+ } else if(strcmp(command, "PONG") == 0) {
// Do nothing
- } else if(strncmp(packet, "MODE ", 5) == 0) {
- char *p = packet+5;
- char *start_nick = p;
- while (*p != ' ' && *p != '\n')
- p++;
- char *end_nick = p;
- if (*end_nick == '\n') { // get mode
- *end_nick = '\0';
- if (*start_nick != '#') {
- struct client_data *cl = findClient(start_nick);
+ } else if(strcmp(command, "MODE") == 0) {
+ if (argc == 0) // FIXME: error message
+ return 0;
+ char *nick = args[0];
+ if (argc == 1) { // get mode
+ if (*nick != '#') {
+ struct client_data *cl = findClient(nick);
if (!cl) {
- append_strf(&databuf, ":irc.patchysicp.xyz 401 %s %s :No such nick/channel\n", client->nick, start_nick-1);
+ append_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
return 0;
}
- append_strf(&databuf, ":irc.patchysicp.xyz 221 %s +", client->nick);
+ append_strf(&databuf, ":%s 221 %s +", hostname, client->nick);
if (cl->umode & UMODE_INVISIBLE) append_str(&databuf, "i");
if (cl->umode & UMODE_OPER) append_str(&databuf, "o");
if (cl->umode & UMODE_LOPER) append_str(&databuf, "O");
append_str(&databuf, "\n");
send_log(client->FD, databuf.buf, databuf.len, 0);
} else {
- append_strf(&databuf, ":irc.patchysicp.xyz 324 %s %s +nt\n", client->nick, start_nick);
+ append_strf(&databuf, ":%s 324 %s %s +nt\n", hostname, client->nick, nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
}
} else { // set mode
- *end_nick = '\0';
- if (*start_nick != '#') {
- struct client_data *cl = findClient(start_nick);
+ if (*nick != '#') {
+ struct client_data *cl = findClient(nick);
if (!cl) {
- append_strf(&databuf, ":irc.patchysicp.xyz 401 %s %s :No such nick/channel\n", client->nick, start_nick-1);
+ append_strf(&databuf, ":%s 401 %s %s :No such nick/channel\n", hostname, client->nick, nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
return 0;
}
if (client->FD != cl->FD) {
- append_strf(&databuf, ":irc.patchysicp.xyz 502 %s :Can't change mode for other users\n", client->nick);
+ append_strf(&databuf, ":%s 502 %s :Can't change mode for other users\n", hostname, client->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
return 0;
}
- if (*++p == ':')
- p++;
int off;
+ char *p = args[1];
switch (*p++) {
case '+': off = 0; break;
case '-': off = 1; break;
- default:
- *end_nick = ' ';
- goto unknown;
+ default: goto unknown;
}
- while (*p != ' ' && *p != '\n') {
+ while (*p) {
databuf.len = 0;
switch (*p) {
case 'i':
if (off) {
- append_strf(&databuf, ":irc.patchysicp.xyz MODE %s -i\n", client->nick);
+ append_strf(&databuf, ":%s MODE %s -i\n", hostname, client->nick);
cl->umode &= ~UMODE_INVISIBLE;
} else {
- append_strf(&databuf, ":irc.patchysicp.xyz MODE %s +i\n", client->nick);
+ append_strf(&databuf, ":%s MODE %s +i\n", hostname, client->nick);
cl->umode |= UMODE_INVISIBLE;
}
send_log(client->FD, databuf.buf, databuf.len, 0);
break;
default:
- append_strf(&databuf, ":irc.patchysicp.xyz 501 %s :Unknown MODE flag\n", client->nick);
+ append_strf(&databuf, ":%s 501 %s :Unknown MODE flag\n", hostname, client->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
}
p++;
}
} else {
- *end_nick = ' ';
goto unknown;
}
}
- } else if(strncmp(packet, "NAMES ", 6) == 0) {
+ } else if(strcmp(command, "NAMES") == 0) {
// TODO: actual channel support
- char *p = strchr(packet+6, '\n');
- *p = '\0';
+ if (argc == 0) // FIXME: error message
+ return 0;
for(int i=0; i<CLIENTS; i++)
if(clients[i] && clients[i]->nick[0]) {
databuf.len = 0;
- append_strf(&databuf, ":irc.patchysicp.xyz 353 %s = %s :%s\n", client->nick, packet+6, clients[i]->nick);
+ append_strf(&databuf, ":%s 353 %s = %s :%s\n", hostname, client->nick, args[0], clients[i]->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
}
databuf.len = 0;
- append_strf(&databuf, ":irc.patchysicp.xyz 366 %s :End of /NAMES list\n", client->nick);
+ append_strf(&databuf, ":%s 366 %s :End of /NAMES list\n", hostname, client->nick);
send_log(client->FD, databuf.buf, databuf.len, 0);
} else {
unknown:
- printf("Unknown packet: %s", packet);
// Inform user of error
- append_str(&databuf, ":irc.patchysicp.xyz 421 ");
- append_str(&databuf, client->nick);
- append_str(&databuf, " :Unknown command, ");
- append_str(&databuf, packet);
+ append_strf(&databuf, ":%s 421 %s :Unknown command %s\n", hostname, client->nick, command);
send_log(client->FD, databuf.buf, databuf.len, 0);
fflush(stdout);
}
}
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);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 001 %s :Welcome to PatchyIRCD!!!\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 002 %s :Your host is PatchyIRCD V0.0.1\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 003 %s :This server was created when I had cybersex with your mother.\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 251 %s :This server exists\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 252 %s :Jannies don't exist\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 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);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 375 %s :PatchySICP /MOTD\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 372 %s :Welcome to Montreal!\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 372 %s :You are retarded and I will have cybersex with your mom.\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
+ databuf.len = 0;
+ append_strf(&databuf, ":%s 376 %s :/MOTD over\n", hostname, client->nick);
+ send_log(client->FD, databuf.buf, databuf.len, 0);
}
void setNick(struct client_data *client, char* nickname, size_t size) {
// Remove newline
for(i=0;i<size;i++){
- // CR/^M
- if(nickname[i] == 13) {
- nickname[i] = 0;
- break;
- }
- // Newline
- if(nickname[i] == 10) {
- nickname[i] = 0;
- break;
- }
// Space
if(nickname[i] == ' ') {
nickname[i] = 0;
break;
}
- // NULL
- if(nickname[i] == 0) {
- nickname[i] = 0;
- break;
- }
}
// Start GitHub Copilot
if(strncmp(clients[i]->nick, nickname, size) == 0) {
// Nickname is already taken
databuf.len = 0;
- append_str(&databuf, ":irc.patchysicp.xyz 443 * ");
- append_str(&databuf, nickname);
- append_str(&databuf, " :Nickname is already in use\n");
+ append_strf(&databuf, ":%s 443 * %s :Nickname is already in use\n", hostname, nickname);
send_log(client->FD, databuf.buf, databuf.len, 0);
return;
}
// Update nickname
if(client->nickLen) {
databuf.len = 0;
- append_str(&databuf, ":");
- append_str(&databuf, client->nick);
- append_str(&databuf, " NICK ");
- append_str(&databuf, nickname);
- append_str(&databuf, "\n");
+ append_strf(&databuf, ":%s NICK %s\n", client->nick, nickname);
send_log(client->FD, databuf.buf, databuf.len, 0);
sendall_log(client->FD, databuf.buf, databuf.len, 0);
}