first commit, unfinished wip

This commit is contained in:
thorium1256
2026-05-11 15:14:22 +03:00
commit 8f4162305f
16 changed files with 651 additions and 0 deletions

92
src/IRC.c Normal file
View File

@@ -0,0 +1,92 @@
#include "IRC.h"
#include "defines.h"
#include "netcode.h"
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
int IRC_ParseMessage(char *line, irc_message_t *msg)
{
strncpy(msg->line, line, sizeof(msg->line) - 1);
char *ptr = msg->line;
ptr[sizeof(msg->line)] = NUL;
char *source = NULL;
char *command = NULL;
// get the source, if it exists (the : at the beginning of an IRC message)
if(*ptr == ':')
{
ptr++;
source = ptr;
while (*ptr && *ptr != ' ') ptr++;
if (*ptr) *ptr++ = NUL;
while (*ptr == ' ') ptr++; // skip any extra spaces
}
msg->source = source;
// read the command
command = ptr;
while(*ptr && *ptr != ' ') ptr++;
if (*ptr) *ptr++ = NUL;
msg->command = command;
while (*ptr == ' ') ptr++;
// read its arguments (until we encounter a colon/nullbyte)
msg->argc = 0;
while(*ptr && msg->argc <= 15)
{
if(*ptr == ':') // if it's a trailing arg
{
ptr++;
msg->argv[msg->argc] = ptr;
msg->argc++;
break;
}
msg->argv[msg->argc] = ptr;
while(*ptr && *ptr != ' ') ptr++;
if (*ptr)
{
*ptr++ = NUL;
while (*ptr == ' ') ptr++; // skip spaces for next arg
}
msg->argc++;
}
return 0;
}
static void handlePing(irc_message_t *msg, irc_client_t *irc)
{
char buf[128];
snprintf(buf, sizeof buf, "PONG :%s", msg->argv[0]);
NET_Send(irc->sockfd, buf);
}
void IRC_ProcessMessage(irc_message_t *msg, irc_client_t *irc)
{
command_t commands[] =
{
{"PING", handlePing},
{NULL, NULL}
};
for(int i = 0; commands[i].name; i++)
{
if(strcmp(msg->command, commands[i].name) == 0)
{
commands[i].handler(msg, irc);
}
}
}

105
src/main.c Normal file
View File

@@ -0,0 +1,105 @@
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <stdbool.h>
#include "IRC.h"
#include "defines.h"
#include "netcode.h"
int main(int argc, char **argv)
{
int sockfd = NET_Connect("irc.libera.chat", 6667);
fd_set readfds;
static char linebuf[1026];
static size_t lineLen = 0;
char recvline[513];
char sendline[513];
irc_client_t irc;
irc.sockfd = sockfd;
if(sockfd >= 0)
{
NET_Send(sockfd, "NICK BareBonesDude\r\n");
NET_Send(sockfd, "USER BareBonesDude 0 * :The Postal Dudesksleton\r\n");
}
else
{
return 1;
}
while(1)
{
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO, &readfds);
FD_SET(sockfd, &readfds);
int maxfd = (sockfd > 0) ? sockfd + 1 : 1;
select(maxfd, &readfds, NULL, NULL, NULL);
if(FD_ISSET(STDIN_FILENO, &readfds))
{
fgets(sendline, sizeof(sendline), stdin);
NET_Send(sockfd, sendline);
}
if(FD_ISSET(sockfd, &readfds))
{
ssize_t n = recv(sockfd, recvline, sizeof(recvline), 0);
if(n <= 0) break;
recvline[n] = NUL;
for(ssize_t i = 0; i < n; i++)
{
linebuf[lineLen++] = recvline[i];
if(lineLen >= 2 && linebuf[lineLen - 2] == '\r' && linebuf[lineLen - 1] == '\n')
{
// we found a complete line
linebuf[lineLen] = NUL;
// parse the message
irc_message_t msg;
IRC_ParseMessage(linebuf, &msg);
// try to print it
if(msg.source != NULL)
{
printf("%s: %s ", msg.source, msg.command);
}
else
{
printf("Server: %s ", msg.command);
}
for(int i = 0; i < msg.argc; i++)
{
printf("%s ", msg.argv[i]);
}
lineLen = 0;
}
if(lineLen >= sizeof(linebuf) - 1)
{
lineLen = 0;
}
}
}
}
printf("Connection closed by foreign host.\n");
return 0;
}

123
src/netcode.c Normal file
View File

@@ -0,0 +1,123 @@
#include "netcode.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int NET_Connect(const char *host, int port)
{
int status;
struct addrinfo hints, *res;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// save us from user or programmer stupidity
if(!host)
{
return -1;
}
char portNumber[6];
snprintf(portNumber, 6, "%d", port);
printf("Looking up %s...\n", host);
if ((status = getaddrinfo(host, portNumber, &hints, &res)) == -1)
{
fprintf(stderr, "Unable to lookup %s: %s\n", host, gai_strerror(status));
return -1;
}
char ipstr[INET6_ADDRSTRLEN];
int sockfd = -1;
for(struct addrinfo *p = res; p != NULL; p = p->ai_next)
{
void *addr;
struct sockaddr_in *ipv4;
struct sockaddr_in6 *ipv6;
if(p->ai_family == AF_INET)
{
ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
}
else
{
ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
}
inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
printf("Connecting to %s (%s)...\n", host, ipstr);
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
{
char perrorMsg[sizeof("Failed to connect to ") + sizeof ipstr];
snprintf(perrorMsg, sizeof perrorMsg, "Failed to connect to %s", ipstr);
perror(perrorMsg);
continue;
}
if((connect(sockfd, p->ai_addr, p->ai_addrlen)) == -1)
{
close(sockfd);
char perrorMsg[sizeof("Failed to connect to ") + sizeof ipstr];
snprintf(perrorMsg, sizeof perrorMsg, "Failed to connect to %s", ipstr);
perror(perrorMsg);
continue;
}
printf("Connected!\n");
break;
}
if(sockfd >= 0)
{
return sockfd;
}
else
{
return -1;
}
}
void NET_Send(int sockfd, const char *toSend)
{
size_t bytesSent = 0;
size_t sendLen = strlen(toSend);
while(bytesSent < sendLen)
{
ssize_t sent = send(sockfd, toSend, sendLen - bytesSent, 0);
if(sent == -1)
{
perror("NET_Send");
return;
}
if(sent == 0)
{
fprintf(stderr, "NET_Send: connection closed");
return;
}
bytesSent += sent;
}
}
void NET_Close(int sockfd)
{
if(sockfd >= 0)
{
shutdown(sockfd, SHUT_RDWR);
close(sockfd);
}
}