From 578145c49406947676c66432ed7e60e1e197c2b8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C4=81nis=20R=C5=ABcis?= Date: Mon, 29 Mar 2010 17:19:51 +0300 Subject: [PATCH] IRC: flesh out --- console.h | 1 + host.c | 4 + irc.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++ irc.h | 7 ++ makefile.inc | 1 + 5 files changed, 236 insertions(+) create mode 100644 irc.c create mode 100644 irc.h diff --git a/console.h b/console.h index f86ae155..97cec60e 100644 --- a/console.h +++ b/console.h @@ -75,6 +75,7 @@ void Con_CompleteCommandLine(void); /// formatted in columns on the console void Con_DisplayList(const char **list); +void SanitizeString(char *in, char *out); /*! \name log * @{ diff --git a/host.c b/host.c index 3c77a0e3..605852b6 100644 --- a/host.c +++ b/host.c @@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "csprogs.h" #include "sv_demo.h" #include "snd_main.h" +#include "irc.h" /* @@ -696,6 +697,8 @@ void Host_Main(void) Curl_Run(); + IRC_Frame(); + // check for commands typed to the host Host_GetConsoleCommands(); @@ -1115,6 +1118,7 @@ static void Host_Init (void) FS_Init(); NetConn_Init(); + IRC_Init(); Curl_Init(); //PR_Init(); //PR_Cmd_Init(); diff --git a/irc.c b/irc.c new file mode 100644 index 00000000..672e5b65 --- /dev/null +++ b/irc.c @@ -0,0 +1,223 @@ +#include "quakedef.h" +#include "lhnet.h" +#include "console.h" + +static lhnetsocket_t *irc_socket; +static char irc_incoming[1024]; +static char irc_outgoing[1024]; +static int irc_incoming_len; +static int irc_outgoing_len; + +static void IRC_Disconnect(void) +{ + if (irc_socket) + { + Con_Print("[IRC] Disconnected.\n"); + LHNET_CloseSocket(irc_socket); + irc_socket = NULL; + } + + irc_incoming_len = 0; + irc_outgoing_len = 0; +} + +static int IRC_Connect(const char *addr) +{ + lhnetaddress_t address; + + IRC_Disconnect(); + + if (!LHNETADDRESS_FromString(&address, addr, 6667)) + { + Con_Printf("[IRC] Bad server address given: %s.\n", addr); + return 0; + } + + if (!(irc_socket = LHNET_AllocSocket(&address))) + { + Con_Printf("[IRC] Couldn't allocate a socket.\n"); + return 0; + } + + LHNET_OpenSocket_Connected(irc_socket); + + if (irc_socket->constatus == LHNETCONSTATUS_ERROR) + { + /* LHNET prints an error, so we don't have to. */ + Z_Free((void *) irc_socket); + return 0; + } + + Con_Print("[IRC] Connecting to the server...\n"); + return 1; +} + +static void IRC_AddMessage(const char *message) +{ + size_t len = strlen(message); + + memcpy(irc_outgoing + irc_outgoing_len, message, sizeof (irc_outgoing) - irc_outgoing_len - 2); + memcpy(irc_outgoing + min(irc_outgoing_len + len, sizeof (irc_outgoing) - 2), "\r\n", 2); + + irc_outgoing_len = min(irc_outgoing_len + len + 2, sizeof (irc_outgoing)); + + Con_Printf("[IRC] %d bytes waiting to be written\n", irc_outgoing_len); +} + +static const char *IRC_NickFromPlayerName(void) +{ + const char prefix[] = "[DP]"; + const int prefix_len = sizeof (prefix) - 1; + char *nick; + + nick = Z_Malloc(prefix_len + strlen(cl_name.string) + 1); + memcpy(nick, prefix, prefix_len + 1); + SanitizeString(cl_name.string, nick + prefix_len); + + return nick; +} + +static void IRC_Connect_f(void) +{ + if (Cmd_Argc() != 2) + { + Con_Print("ircconnect
: connect to an IRC server\n"); + return; + } + + if (IRC_Connect(Cmd_Argv(1))) + { + const char *nick = IRC_NickFromPlayerName(); + + IRC_AddMessage(va("NICK %s", nick)); + IRC_AddMessage(va("USER %s localhost localhost :%s", nick, nick)); + + Z_Free((void *) nick); + } +} + +static void IRC_Disconnect_f(void) +{ + IRC_Disconnect(); +} + +static void IRC_IRC_f(void) +{ + if (Cmd_Argc() < 2) + { + Con_Print("irc \n"); + return; + } + + if (irc_socket) + IRC_AddMessage(Cmd_Args()); + else + Con_Print("[IRC] Not connected to a server.\n"); +} + +static void IRC_ProcessMessages(void) +{ + char *remaining = irc_incoming; + int remaining_len = irc_incoming_len; + + while (remaining_len > 0) + { + char *cr; + + cr = memchr((void *) remaining, '\r', remaining_len); + + if (!cr || cr == remaining + remaining_len - 1) + { + /* Probably incomplete message. */ + memmove(irc_incoming, remaining, remaining_len); + break; + } + + if (cr[1] == '\n') + { + int len = (cr - remaining) + 2; + + cr[0] = 0; + cr[1] = 0; + + Con_Printf("[IRC] %s\n", remaining); + + remaining += len; + remaining_len -= len; + } + else + { + /* Garbage or embedded CR? Discard it and retry. */ + cr[0] = '.'; + } + } + + irc_incoming_len = remaining_len; +} + +static void IRC_ReadMessages(void) +{ + lhnetaddress_t dummyaddress; + int read; + + read = LHNET_Read(irc_socket, irc_incoming + irc_incoming_len, sizeof (irc_incoming) - irc_incoming_len, &dummyaddress); + + if (read > 0) + { + Con_Printf("[IRC] Read %d bytes\n", read); + irc_incoming_len += read; + IRC_ProcessMessages(); + } +} + +static void IRC_WriteMessages(void) +{ + lhnetaddress_t dummyaddress = irc_socket->address; + int written; + + written = LHNET_Write(irc_socket, irc_outgoing, irc_outgoing_len, &dummyaddress); + + if (written > 0) + { + Con_Printf("[IRC] Wrote %d bytes\n", written); + memmove(irc_outgoing, irc_outgoing + written, irc_outgoing_len - written); + irc_outgoing_len -= written; + } +} + +void IRC_Frame(void) +{ + if (irc_socket) + { + if (irc_socket->constatus == LHNETCONSTATUS_INPROGRESS) + LHNET_OpenSocket_Connected(irc_socket); + + switch (irc_socket->constatus) + { + case LHNETCONSTATUS_INPROGRESS: + case LHNETCONSTATUS_DISCONNECTED: + break; + + case LHNETCONSTATUS_ERROR: + Con_Print("[IRC] Failed to connect to the server.\n"); + IRC_Disconnect(); + break; + + case LHNETCONSTATUS_CONNECTED: + IRC_WriteMessages(); + IRC_ReadMessages(); + + if (irc_socket->constatus == LHNETCONSTATUS_DISCONNECTED) + IRC_Disconnect(); + + break; + } + } +} + +void IRC_Init(void) +{ + Cmd_AddCommand("ircconnect", IRC_Connect_f, "connect to an IRC server"); + Cmd_AddCommand("ircdisconnect", IRC_Disconnect_f, "disconnect from an IRC server"); + Cmd_AddCommand("irc", IRC_IRC_f, "send raw messages to a connected IRC server"); +} diff --git a/irc.h b/irc.h new file mode 100644 index 00000000..e49e3f25 --- /dev/null +++ b/irc.h @@ -0,0 +1,7 @@ +#ifndef IRC_H +#define IRC_H + +void IRC_Init(void); +void IRC_Frame(void); + +#endif diff --git a/makefile.inc b/makefile.inc index aeac6e31..6b9d14b5 100644 --- a/makefile.inc +++ b/makefile.inc @@ -141,6 +141,7 @@ OBJ_COMMON= \ model_sprite.o \ mvm_cmds.o \ netconn.o \ + irc.o \ palette.o \ polygon.o \ portals.o \ -- 2.39.2