changeset 96:7c9538e71c89

Add connection keepalive by sending /listallusers every 15 minutes, due to NN server booting after about 30 minutes of inactivity; Improve handling of error messages; Add handling for "<BOOT />" protocol token.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 05 Jul 2009 16:55:40 +0300
parents 69f9c46e4a94
children 218efd2f0641
files nnchat.c
diffstat 1 files changed, 56 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- a/nnchat.c	Sat Jun 20 01:45:09 2009 +0300
+++ b/nnchat.c	Sun Jul 05 16:55:40 2009 +0300
@@ -1,7 +1,7 @@
 /*
  * NNChat - Custom chat client for NewbieNudes.com chatrooms
  * Written by Matti 'ccr' Hämäläinen
- * (C) Copyright 2008 Tecnic Software productions (TNSP)
+ * (C) Copyright 2008-2009 Tecnic Software productions (TNSP)
  */
 #include "libnnchat.h"
 #include <stdlib.h>
@@ -20,13 +20,14 @@
 #define SET_MAX_HISTORY (16)
 #define SET_DELAY       (15)
 #define SET_DELAY_USEC  (SET_DELAY * 1000)
+#define SET_KEEPALIVE   (15*60)     /* Ping/keepalive period in seconds */
 
 
 /* Options
  */
 int     optPort = 8005;
 int     optUserColor = 0x006080;
-char    *optServer = "www11.servemedata.com",
+char    *optServer = "chat.newbienudes.com",
         *optUserName = NULL,
         *optUserName2 = NULL,
         *optPassword = NULL,
@@ -311,6 +312,20 @@
 }
 
 
+void errorMsg(char *fmt, ...)
+{
+    char buf[8192];
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+    va_end(ap);
+
+    printMsg(buf);
+    THERR(buf);
+}
+
+
 int handleUser(int sock, char *str)
 {
     const char *msg = "</USER><MESSAGE>";
@@ -430,6 +445,14 @@
 }
 
 
+int handleBoot(int sock, char *str)
+{
+    (void) sock; (void) str;
+    errorMsg("Booted by server.\n");
+    return -1;
+}
+
+
 typedef struct {
     char *cmd;
     int (*handler)(int, char *);
@@ -442,6 +465,7 @@
     { "<DELETE_USER>", handleDeleteUser },
     { "<ADD_USER>", handleAddUser },
     { "<NUMCLIENTS>", handleFoo },
+    { "<BOOT />", handleBoot },
 };
 
 const int nprotoCmds = (sizeof(protoCmds) / sizeof(protoCmds[0]));
@@ -565,7 +589,8 @@
         cursesInit = FALSE,
         networkInit = FALSE,
         insertMode = TRUE;
-    struct timeval tv;
+    time_t prevTime;
+    struct timeval socktv;
     fd_set sockfds;
     char *tmpStr;
     nn_editbuf_t *editBuf = newBuf(SET_BUFSIZE);
@@ -575,7 +600,7 @@
     memset(histBuf, 0, sizeof(histBuf));
     
     /* Initialize */
-    th_init("NNChat", "Newbie Nudes chat client", "0.7.1",
+    th_init("NNChat", "Newbie Nudes chat client", "0.7.2",
         "Written and designed by Anonymous Finnish Guy (C) 2008-2009",
         "This software is freeware, use and distribute as you wish.");
     th_verbosityLevel = 0;
@@ -621,18 +646,18 @@
     THMSG(2, "True hostname: %s\n", tmpHost->h_name);
 
 
-#if 0
+#if 1
     /* To emulate the official client, we first make a request for
      * policy file, even though we don't use it for anything...
      */
-    if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) {
+    if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, 843)) < 0) {
         THERR("Policy file request connection setup failed!\n");
         goto err_exit;
     }
     
     tmpStr = "<policy-file-request/>";
     if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) {
-        THERR("Failed to send fakeprobe.\n");
+        THERR("Failed to send policy file request.\n");
         goto err_exit;
     } else {
         ssize_t gotBuf;
@@ -701,6 +726,7 @@
     }
     
     /* Enter mainloop */
+    prevTime = time(NULL);
     FD_ZERO(&sockfds);
     FD_SET(tmpSocket, &sockfds);
 
@@ -709,13 +735,13 @@
         fd_set tmpfds;
         
         /* Check for incoming data from the server */
-        tv.tv_sec = 0;
-        tv.tv_usec = SET_DELAY_USEC;
+        socktv.tv_sec = 0;
+        socktv.tv_usec = SET_DELAY_USEC;
         tmpfds = sockfds;
-        if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &tv)) == -1) {
+        if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &socktv)) == -1) {
             int res = getSocketErrno();
             if (res != EINTR) {
-                printMsg("Error occured in select(sockfds): %d, %s\n",
+                errorMsg("Error occured in select(sockfds): %d, %s\n",
                     res, getSocketErrStr(res));
                 isError = TRUE;
             }
@@ -727,10 +753,10 @@
             
             if (gotBuf < 0) {
                 int res = getSocketErrno();
-                printMsg("Error in recv: %d, %s\n", res, getSocketErrStr(res));
+                errorMsg("Error in recv: %d, %s\n", res, getSocketErrStr(res));
                 isError = TRUE;
             } else if (gotBuf == 0) {
-                printMsg("Server closed connection.\n");
+                errorMsg("Server closed connection.\n");
                 isError = TRUE;
             } else {
                 /* Handle protocol data */
@@ -744,7 +770,7 @@
                         printMsg("Could not handle: %s\n", tmpBuf);
                     } else if (result < 0) {
                         /* Fatal error, quit */
-                        printMsg("Fatal error with message: %s\n", tmpBuf);
+                        errorMsg("Fatal error with message: %s\n", tmpBuf);
                         isError = TRUE;
                     }
                     
@@ -785,7 +811,7 @@
 #ifdef KEY_RESIZE
             case KEY_RESIZE:
                 if (!initializeWindows()) {
-                    THERR("Error resizing ncurses windows\n");
+                    errorMsg("Error resizing ncurses windows\n");
                     isError = TRUE;
                 }
                 break;
@@ -813,7 +839,7 @@
                     clearBuf(editBuf);
                     
                     if (result < 0) {
-                        printMsg("Fatal error handling user input: %s\n", editBuf->data);
+                        errorMsg("Fatal error handling user input: %s\n", editBuf->data);
                         isError = TRUE;
                     }
                     
@@ -938,17 +964,24 @@
         } /* !optDaemon */
         
         if (++updateCount > 10) {
+            time_t tmpTime = time(NULL);
+            if (tmpTime - prevTime > SET_KEEPALIVE) {
+                sendUserMsg(tmpSocket, optUserName2, "/listallusers"); 
+                prevTime = tmpTime;
+            }
+            
+            if (!colorSet) {
+                colorSet = TRUE;
+                printMsg("%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
+                printMsg("%s\n", th_prog_author);
+                printMsg("%s\n", th_prog_license);
+                sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
+            }
+            
             updateStatus(insertMode);
             updateCount = 0;
         }
         
-        if (!colorSet) {
-            colorSet = TRUE;
-            printMsg("%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
-            printMsg("%s\n", th_prog_author);
-            printMsg("%s\n", th_prog_license);
-            sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
-        }
     }
     
     /* Shutdown */