]> git.rm.cloudns.org Git - xonotic/darkplaces.git/commitdiff
IRC: flesh out
authorJānis Rūcis <parasti@gmail.com>
Mon, 29 Mar 2010 14:19:51 +0000 (17:19 +0300)
committerJānis Rūcis <parasti@gmail.com>
Sun, 27 Jun 2010 12:23:20 +0000 (15:23 +0300)
console.h
host.c
irc.c [new file with mode: 0644]
irc.h [new file with mode: 0644]
makefile.inc

index f86ae155f052a8991fef595c5b541136f566e056..97cec60eb16fb80583783350431bf61e07f441c2 100644 (file)
--- 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 3c77a0e356ce13c439cd0160946f0e2f74e809c0..605852b625bf6f3e031aaa90f9259135fe078c80 100644 (file)
--- 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 (file)
index 0000000..672e5b6
--- /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 <address> : 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 <raw IRC message>\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 (file)
index 0000000..e49e3f2
--- /dev/null
+++ b/irc.h
@@ -0,0 +1,7 @@
+#ifndef IRC_H
+#define IRC_H
+
+void IRC_Init(void);
+void IRC_Frame(void);
+
+#endif
index aeac6e313e8549f22e2b46965b738e70625d73e0..6b9d14b5ecd8ecb6d926738ed19a476ed39b3f37 100644 (file)
@@ -141,6 +141,7 @@ OBJ_COMMON= \
        model_sprite.o \
        mvm_cmds.o \
        netconn.o \
+       irc.o \
        palette.o \
        polygon.o \
        portals.o \