diff nnchat.c @ 168:2e4850ece456

Partially re-factor connection handling.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 14 Nov 2010 22:08:08 +0200
parents f2f0b6f9281b
children 8d4cdbeae606
line wrap: on
line diff
--- a/nnchat.c	Sat Nov 06 18:00:22 2010 +0200
+++ b/nnchat.c	Sun Nov 14 22:08:08 2010 +0200
@@ -29,7 +29,6 @@
 #define SET_MIN_BACKBUF (1024)      /* Backbuffer size (in lines) */
 #define SET_MAX_HISTORY (16)        /* Command history length */
 #define SET_DELAY       (15)
-#define SET_DELAY_USEC  (SET_DELAY * 250)
 #define SET_KEEPALIVE   (15*60)     /* Ping/keepalive period in seconds */
 
 
@@ -360,12 +359,12 @@
 }
 
 
-int handleUser(int sock, const char *str)
+int handleUser(nn_conn_t *conn, const char *str)
 {
     const char *msg = "</USER><MESSAGE>", *p = str;
     char *q, *s, *t, *h, *p2;
     
-    (void) sock;
+    (void) conn;
     
     s = strstr(str, msg);
     if (!s) return 1;
@@ -428,7 +427,7 @@
 }
 
 
-int handleLogin(int sock, const char *str)
+int handleLogin(nn_conn_t *conn, const char *str)
 {
     char tmpStr[256];
     
@@ -439,18 +438,18 @@
         return -2;
     } else if (!strncmp(str, "SUCCESS", 7)) {
         printMsg("½2½Login success½0½ - ½3½%s½0½\n", tmpStr);
-        nn_send_msg(sock, optUserName2, "%%2FRequestUserList");
+        nn_conn_send_msg(conn, optUserName2, "%%2FRequestUserList");
         return 0;
     } else
         return 1;
 }
 
 
-int handleAddUser(int sock, const char *str)
+int handleAddUser(nn_conn_t *conn, const char *str)
 {
     char *p, *s = strstr(str, "</ADD_USER>");
 
-    (void) sock;
+    (void) conn;
 
     if (!s) return 1;
     *s = 0;
@@ -466,11 +465,11 @@
 }
 
 
-int handleDeleteUser(int sock, const char *str)
+int handleDeleteUser(nn_conn_t *conn, const char *str)
 {
     char *p, *s = strstr(str, "</DELETE_USER>");
 
-    (void) sock;
+    (void) conn;
 
     if (!s) return 1;
     *s = 0;
@@ -486,17 +485,17 @@
 }
 
 
-int handleFoo(int sock, const char *str)
+int handleFoo(nn_conn_t *conn, const char *str)
 {
-    (void) sock; (void) str;
+    (void) conn; (void) str;
     
     return 0;
 }
 
 
-int handleBoot(int sock, const char *str)
+int handleBoot(nn_conn_t *conn, const char *str)
 {
-    (void) sock; (void) str;
+    (void) conn; (void) str;
     errorMsg("Booted by server.\n");
     return -1;
 }
@@ -505,7 +504,7 @@
 typedef struct {
     char *cmd;
     ssize_t len;
-    int (*handler)(int, const char *);
+    int (*handler)(nn_conn_t *, const char *);
 } protocmd_t;
 
 
@@ -521,7 +520,7 @@
 static const int nprotoCmds = sizeof(protoCmds) / sizeof(protoCmds[0]);
 
 
-int handleProtocol(const int sock, const char *buf, const ssize_t bufLen)
+int handleProtocol(nn_conn_t *conn, const char *buf, const ssize_t bufLen)
 {
     static BOOL protoCmdsInit = FALSE;
     int i;
@@ -535,7 +534,7 @@
     for (i = 0; i < nprotoCmds; i++) {
         ssize_t cmdLen = protoCmds[i].len;
         if (cmdLen < bufLen && !strncmp(buf, protoCmds[i].cmd, cmdLen))
-            return protoCmds[i].handler(sock, buf + cmdLen);
+            return protoCmds[i].handler(conn, buf + cmdLen);
     }
 
     if (optDebug) {
@@ -556,7 +555,7 @@
     return strcasecmp((char *) s1, (char *) s2);
 }
 
-int handleUserInput(const int sock, char *buf, size_t bufLen)
+int handleUserInput(nn_conn_t *conn, char *buf, size_t bufLen)
 {
     char *tmpStr, tmpBuf[4096];
     BOOL result;
@@ -579,7 +578,7 @@
         }
         optUserColor = tmpInt;
         printMsg("Setting color to #%06x\n", optUserColor);
-        nn_send_msg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
+        nn_conn_send_msg(conn, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
         return 0;
     } else if (!strncasecmp(buf, "/ignore", 7)) {
         char *name = trimLeft(buf + 7);
@@ -675,7 +674,7 @@
     /* Send double-encoded */
     tmpStr = nn_dblencode_str(buf);
     if (tmpStr == 0) return -2;
-    result = nn_send_msg(sock, optUserName2, "%s", tmpStr);
+    result = nn_conn_send_msg(conn, optUserName2, "%s", tmpStr);
     th_free(tmpStr);
     
     return result ? 0 : -1;
@@ -804,9 +803,11 @@
     return FALSE;
 }
 
+
 int main(int argc, char *argv[])
 {
-    int tmpSocket = -1, curVis = ERR, updateCount = 0;
+    nn_conn_t *conn = NULL;
+    int curVis = ERR, updateCount = 0;
     struct hostent *tmpHost;
     BOOL argsOK, isError = FALSE,
         exitProg = FALSE,
@@ -815,10 +816,8 @@
         networkInit = FALSE,
         insertMode = TRUE;
     time_t prevTime;
-    struct timeval socktv;
-    fd_set sockfds;
     char *tmpStr;
-    nn_editbuf_t *editBuf = nn_editbuf_new(SET_BUFSIZE);
+    nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE);
     nn_editbuf_t *histBuf[SET_MAX_HISTORY+2];
     int histPos = 0, histMax = 0;
 
@@ -926,34 +925,39 @@
     /* To emulate the official client, we first make a request for
      * policy file, even though we don't use it for anything...
      */
-    if ((tmpSocket = nn_open_connection((struct in_addr *) tmpHost->h_addr, 843)) < 0) {
+    if ((conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, 843)) == NULL) {
         THERR("Policy file request connection setup failed!\n");
         goto err_exit;
     }
-    
+    if (!nn_conn_check(conn))
+        goto err_exit;
+
     tmpStr = "<policy-file-request/>";
-    if (nn_send_to_socket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) {
+    if (nn_conn_send_buf(conn, tmpStr, strlen(tmpStr) + 1) == FALSE) {
         THERR("Failed to send policy file request.\n");
         goto err_exit;
     } else {
-        ssize_t gotBuf;
-        char tmpBuf[SET_BUFSIZE];
-        gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0);
-        tmpBuf[gotBuf-1] = 0;
-        THMSG(2, "Probe got: %s\n", tmpBuf);
-        nn_close_connection(tmpSocket);
+        int cres = nn_conn_pull(conn);
+        if (cres == 0) {
+            THMSG(2, "Probe got: %s\n", conn->buf);
+        } else {
+            THMSG(2, "Could not get policy probe.\n");
+        }
     }
+    nn_conn_close(conn);
 
     /* Okay, now do the proper connection ... */
-    if ((tmpSocket = nn_open_connection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) {
+    if ((conn = nn_conn_open((struct in_addr *) tmpHost->h_addr, optPort)) == NULL) {
         THERR("Main connection setup failed!\n");
         goto err_exit;
     }
+    if (!nn_conn_check(conn))
+        goto err_exit;
     
     THMSG(1, "Connected, logging in as '%s', site '%s'.\n", optUserName, optSite);
     optUserName2 = nn_dblencode_str(optUserName);
     tmpStr = nn_dblencode_str(optSite);
-    nn_send_msg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword);
+    nn_conn_send_msg(conn, optUserName2, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword);
     th_free(tmpStr);
     
     /* Initialize NCurses */
@@ -1001,60 +1005,30 @@
 
     /* Enter mainloop */
     prevTime = time(NULL);
-    FD_ZERO(&sockfds);
-    FD_SET(tmpSocket, &sockfds);
 
     while (!isError && !exitProg) {
-        int result;
-        fd_set tmpfds;
-        
-        /* Check for incoming data from the server */
-        socktv.tv_sec = 0;
-        socktv.tv_usec = SET_DELAY_USEC;
-        tmpfds = sockfds;
-        if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &socktv)) == -1) {
-            int res = nn_get_socket_errno();
-            if (res != EINTR) {
-                errorMsg("Error occured in select(sockfds): %d, %s\n",
-                    res, nn_get_socket_errstr(res));
-                isError = TRUE;
-            }
-        } else if (FD_ISSET(tmpSocket, &tmpfds)) {
-            ssize_t gotBuf;
-            char tmpBuf[8192];
-            char *bufPtr = tmpBuf;
-            gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0);
-            
-            if (gotBuf < 0) {
-                int res = nn_get_socket_errno();
-                errorMsg("Error in recv: %d, %s\n", res, nn_get_socket_errstr(res));
-                isError = TRUE;
-            } else if (gotBuf == 0) {
-                errorMsg("Server closed connection.\n");
-                isError = TRUE;
-            } else {
-                /* Handle protocol data */
-                tmpBuf[gotBuf] = 0;
-                do {
-                    size_t bufLen = strlen(bufPtr) + 1;
-                    result = handleProtocol(tmpSocket, bufPtr, bufLen);
-                
-                    if (result > 0) {
-                        /* Couldn't handle the message for some reason */
-                        printMsg("Could not handle: %s\n", tmpBuf);
-                    } else if (result < 0) {
-                        /* Fatal error, quit */
-                        errorMsg("Fatal error with message: %s\n", tmpBuf);
-                        isError = TRUE;
-                    }
-                    
-                    gotBuf -= bufLen;
-                    bufPtr += bufLen;
-                } while (gotBuf > 0 && !isError);
-                updateStatus(insertMode);
-            }
+        int cres = nn_conn_pull(conn);
+        if (cres == 0) {
+            do {
+                size_t bufLen = strlen(conn->ptr) + 1;
+                int result = handleProtocol(conn, conn->ptr, bufLen);
+
+                if (result > 0) {
+                    /* Couldn't handle the message for some reason */
+                    printMsg("Could not handle: %s\n", conn->ptr);
+                } else if (result < 0) {
+                    /* Fatal error, quit */
+                    errorMsg("Fatal error with message: %s\n", conn->ptr);
+                    isError = TRUE;
+                }
+
+                conn->got -= bufLen;
+                conn->ptr += bufLen;
+            } while (conn->got > 0 && !isError);
         }
-        
+        if (!nn_conn_check(conn))
+            isError = TRUE;
+
         /* Handle user input */
         if (!optDaemon) {
             int c, cnt = 0;
@@ -1103,6 +1077,7 @@
             case '\r':
                 /* Call the user input handler */
                 if (editBuf->len > 0) {
+                    int result;
                     
                     if (histMax > 0) {
                         nn_editbuf_free(histBuf[SET_MAX_HISTORY+1]);
@@ -1115,7 +1090,7 @@
                     if (histMax < SET_MAX_HISTORY) histMax++;
                     
                     nn_editbuf_insert(editBuf, editBuf->len, 0);
-                    result = handleUserInput(tmpSocket, editBuf->data, editBuf->len);
+                    result = handleUserInput(conn, editBuf->data, editBuf->len);
                     
                     nn_editbuf_clear(editBuf);
                     
@@ -1261,7 +1236,7 @@
         if (++updateCount > 10) {
             time_t tmpTime = time(NULL);
             if (tmpTime - prevTime > SET_KEEPALIVE) {
-                nn_send_msg(tmpSocket, optUserName2, "/listallusers"); 
+                nn_conn_send_msg(conn, optUserName2, "/listallusers"); 
                 prevTime = tmpTime;
             }
             
@@ -1270,7 +1245,7 @@
                 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);
-                nn_send_msg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
+                nn_conn_send_msg(conn, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
             }
             
             updateStatus(insertMode);
@@ -1301,7 +1276,7 @@
     
     th_free(optUserName2);
 
-    nn_close_connection(tmpSocket);
+    nn_conn_close(conn);
     
     if (networkInit)
         nn_network_close();