# HG changeset patch # User Matti Hamalainen # Date 1289765288 -7200 # Node ID 2e4850ece45688ea33b618420ef70814c3656f17 # Parent b0b63d164702360f1de3233580518a5af5571609 Partially re-factor connection handling. diff -r b0b63d164702 -r 2e4850ece456 libnnchat.c --- a/libnnchat.c Sat Nov 06 18:00:22 2010 +0200 +++ b/libnnchat.c Sun Nov 14 22:08:08 2010 +0200 @@ -6,20 +6,6 @@ #include "libnnchat.h" -typedef struct { - char c; - char *ent; -} html_entity_t; - - -static const html_entity_t HTMLEntities[] = { - { '<', "<" }, - { '>', ">" }, -}; - -static const int numHTMLEntities = sizeof(HTMLEntities) / sizeof(HTMLEntities[0]); - - #ifdef __WIN32 const char *hstrerror(int err) { @@ -36,8 +22,21 @@ const char *nn_get_socket_errstr(int err) { static char buf[64]; - snprintf(buf, sizeof(buf), "Error #%d", err); - return buf; + switch (err) { + case WSAEADDRINUSE: return "Address already in use"; + case WSAECONNABORTED: return "Software caused connection abort"; + case WSAECONNREFUSED: return "Connection refused"; + case WSAECONNRESET: return "Connection reset by peer"; + case WSAEHOSTUNREACH: return "No route to host"; + case WSAENETDOWN: return "Network is down"; + case WSAETIMEDOUT: return "Connection timed out"; + case WSAHOST_NOT_FOUND: return "Host not found"; + case WSAVERNOTSUPPORTED: return "Wrong WinSock DLL version"; + default: + snprintf(buf, sizeof(buf), "Error #%d", err); + return buf; + break; + } } #else int nn_get_socket_errno(void) @@ -52,46 +51,164 @@ #endif -int nn_open_connection(struct in_addr *addr, const int port) +void nn_conn_err(nn_conn_t *conn, const char *fmt, ...) { - struct sockaddr_in tmpAddr; - int sock = -1; + conn->err = TRUE; + + if (conn->errfunc) { + va_list ap; + va_start(ap, fmt); + conn->errfunc(conn, fmt, ap); + va_end(ap); + } +} + + +static void nn_conn_msg(nn_conn_t *conn, const char *fmt, ...) +{ + if (conn->msgfunc) { + va_list ap; + va_start(ap, fmt); + conn->msgfunc(conn, fmt, ap); + va_end(ap); + } +} + + +nn_conn_t *nn_conn_open(struct in_addr *addr, const int port) +{ + nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t)); + struct sockaddr_in dest; - tmpAddr.sin_family = AF_INET; - tmpAddr.sin_port = htons(port); - tmpAddr.sin_addr = *addr; + if (conn == NULL) + return NULL; + + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + dest.sin_addr = *addr; - THMSG(1, "Connecting to %s:%d ...\n", - inet_ntoa(tmpAddr.sin_addr), port); + nn_conn_msg(conn, "Connecting to %s:%d ...\n", + inet_ntoa(dest.sin_addr), port); - if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { - THERR("Could not open socket: %s\n", strerror(errno)); - return -2; + if ((conn->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + nn_conn_err(conn, "Could not open socket: %s\n", strerror(errno)); + conn->status = NN_CONN_CLOSED; + return conn; } - THMSG(2, "Using socket %d.\n", sock); + nn_conn_msg(conn, "Using socket %d.\n", conn->socket); - if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { - THERR("Could not connect: %s\n", strerror(errno)); - return -5; + if (connect(conn->socket, (struct sockaddr *) &dest, sizeof(dest)) == -1) { + nn_conn_err(conn, "Could not connect: %s\n", strerror(errno)); + conn->status = NN_CONN_CLOSED; + return conn; } + + conn->port = port; + conn->address = *addr; + FD_ZERO(&(conn->sockfds)); + FD_SET(conn->socket, &(conn->sockfds)); + conn->status = NN_CONN_OPEN; - return sock; + return conn; } -void nn_close_connection(const int sock) +void nn_conn_close(nn_conn_t *conn) { - if (sock >= 0) { + if (conn == NULL) + return; + + if (conn->socket >= 0) { #ifdef __WIN32 - closesocket(sock); + closesocket(conn->socket); #else - close(sock); + close(conn->socket); #endif + conn->socket = -1; } + + conn->status = NN_CONN_CLOSED; + + th_free(conn); } +BOOL nn_conn_send_buf(nn_conn_t *conn, const char *buf, const size_t len) +{ + size_t bufLeft = len; + const char *bufPtr = buf; + + while (bufLeft > 0) { + ssize_t bufSent; + bufSent = send(conn->socket, bufPtr, bufLeft, 0); + if (bufSent < 0) { + nn_conn_err(conn, "nn_conn_send_buf() failed: %s", strerror(errno)); + return FALSE; + } + bufLeft -= bufSent; + bufPtr += bufSent; + } + + return TRUE; +} + + +BOOL nn_conn_pull(nn_conn_t *conn) +{ + int result; + struct timeval socktv; + fd_set tmpfds; + + if (conn == NULL) + return -1; + + conn->ptr = conn->buf; + + /* Check for incoming data */ + socktv.tv_sec = 0; + socktv.tv_usec = NN_DELAY_USEC; + tmpfds = conn->sockfds; + + if ((result = select(conn->socket + 1, &tmpfds, NULL, NULL, &socktv)) == -1) { + int err = nn_get_socket_errno(); + if (err != EINTR) { + nn_conn_err(conn, "Error occured in select(%d, sockfds): %d, %s\n", + socket, err, nn_get_socket_errstr(err)); + return -1; + } + } else + if (FD_ISSET(conn->socket, &tmpfds)) { + conn->got = recv(conn->socket, conn->ptr, NN_CONNBUF_SIZE, 0); + + if (conn->got < 0) { + int res = nn_get_socket_errno(); + nn_conn_err(conn, "Error in recv: %d, %s\n", res, nn_get_socket_errstr(res)); + return -2; + } else if (conn->got == 0) { + nn_conn_err(conn, "Server closed connection.\n"); + conn->status = NN_CONN_CLOSED; + return -3; + } else { + /* Handle protocol data */ + conn->buf[conn->got] = 0; + return 0; + } + } + + return 1; +} + +BOOL nn_conn_check(nn_conn_t *conn) +{ + if (conn == NULL) + return FALSE; + + return conn->err == 0 && conn->status == NN_CONN_OPEN; +} + + + BOOL nn_network_init(void) { #ifdef __WIN32 @@ -115,31 +232,15 @@ } -BOOL nn_send_to_socket(const int sock, char *buf, const size_t bufLen) -{ - size_t bufLeft = bufLen; - char *bufPtr = buf; - - while (bufLeft > 0) { - ssize_t bufSent; - bufSent = send(sock, bufPtr, bufLeft, 0); - if (bufSent < 0) return FALSE; - bufLeft -= bufSent; - bufPtr += bufSent; - } - return TRUE; -} - - -BOOL bufRealloc(char **buf, size_t *size, size_t add) +static BOOL bufRealloc(char **buf, size_t *size, size_t add) { return ((*buf = th_realloc(*buf, *size + add)) != NULL); } #define PUSHCHAR(x) bufPushChar(&result, &resSize, &resPos, x) -BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch) +static BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch) { - if (*pos >= *size && !bufRealloc(buf, size, SET_ALLOC_SIZE)) + if (*pos >= *size && !bufRealloc(buf, size, NN_ALLOC_SIZE)) return FALSE; (*buf)[*pos] = ch; @@ -148,14 +249,14 @@ } #define PUSHSTR(x) bufPushStr(&result, &resSize, &resPos, x) -BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str) +static BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str) { size_t tmpLen; if (str == NULL) return FALSE; tmpLen = strlen(str); - if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + SET_ALLOC_SIZE)) + if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + NN_ALLOC_SIZE)) return FALSE; strcpy(*buf + *pos, str); @@ -172,7 +273,7 @@ if (str == NULL) return NULL; - resSize = strlen(str) + SET_ALLOC_SIZE; + resSize = strlen(str) + NN_ALLOC_SIZE; if ((result = th_malloc(resSize)) == NULL) return NULL; @@ -227,7 +328,7 @@ if (str == NULL) return NULL; - resSize = strlen(str) + SET_ALLOC_SIZE; + resSize = strlen(str) + NN_ALLOC_SIZE; if ((result = th_malloc(resSize)) == NULL) return NULL; @@ -288,7 +389,7 @@ if (str == NULL) return NULL; - resSize = strlen(str) + SET_ALLOC_SIZE; + resSize = strlen(str) + NN_ALLOC_SIZE; if ((result = th_malloc(resSize)) == NULL) return NULL; @@ -305,6 +406,20 @@ } +typedef struct { + char c; + char *ent; +} html_entity_t; + + +static const html_entity_t HTMLEntities[] = { + { '<', "<" }, + { '>', ">" }, +}; + +static const int numHTMLEntities = sizeof(HTMLEntities) / sizeof(HTMLEntities[0]); + + char *nn_encode_str2(const char *str) { const char *s = str; @@ -313,7 +428,7 @@ if (str == NULL) return NULL; - resSize = strlen(str) + SET_ALLOC_SIZE; + resSize = strlen(str) + NN_ALLOC_SIZE; if ((result = th_malloc(resSize)) == NULL) return NULL; @@ -400,23 +515,27 @@ } -BOOL nn_send_msg(const int sock, const char *user, const char *fmt, ...) +BOOL nn_conn_send_msg(nn_conn_t *conn, const char *user, const char *fmt, ...) { - char tmpBuf[SET_BUFSIZE], tmpBuf2[SET_BUFSIZE + 256]; - int n; + char *tmp, *msg; va_list ap; va_start(ap, fmt); - n = vsnprintf(tmpBuf, sizeof(tmpBuf), fmt, ap); + tmp = th_strdup_vprintf(fmt, ap); va_end(ap); - if (n < 0) return FALSE; + if (tmp == NULL) + return FALSE; + + msg = th_strdup_printf("%s%s", user, tmp); + th_free(tmp); - snprintf(tmpBuf2, sizeof(tmpBuf2), - "%s%s", - user, tmpBuf); - - return nn_send_to_socket(sock, tmpBuf2, strlen(tmpBuf2) + 1); + if (msg != NULL) { + BOOL ret = nn_conn_send_buf(conn, msg, strlen(msg) + 1); + th_free(msg); + return ret; + } else + return FALSE; } @@ -459,7 +578,6 @@ int nn_editbuf_write(nn_editbuf_t *buf, ssize_t pos, int ch) { - /* Check arguments */ if (buf->len+1 >= buf->size) return -3; if (pos < 0) @@ -475,7 +593,6 @@ int nn_editbuf_insert(nn_editbuf_t *buf, ssize_t pos, int ch) { - /* Check arguments */ if (buf->len+1 >= buf->size) return -3; if (pos < 0) @@ -493,7 +610,6 @@ int nn_editbuf_delete(nn_editbuf_t *buf, ssize_t pos) { - /* Check arguments */ if (pos < 0) return -1; else if (pos < buf->len) { @@ -568,9 +684,12 @@ } else return NULL; - str = th_malloc(siz + 1); + if ((str = th_malloc(siz + 1)) == NULL) + return NULL; + memcpy(str, buf->data + start, siz); str[siz] = 0; + return str; } diff -r b0b63d164702 -r 2e4850ece456 libnnchat.h --- a/libnnchat.h Sat Nov 06 18:00:22 2010 +0200 +++ b/libnnchat.h Sun Nov 14 22:08:08 2010 +0200 @@ -21,9 +21,11 @@ #include #include "th_string.h" -#define SET_BUFSIZE (4096) -#define SET_ALLOC_SIZE (128) - +#define NN_TMPBUF_SIZE (4096) +#define NN_ALLOC_SIZE (128) +#define NN_CONNBUF_SIZE (64 * 1024) +#define NN_NUM_BUCKETS (256) +#define NN_DELAY_USEC (15 * 250) typedef struct { char **data; @@ -44,25 +46,46 @@ } nn_user_t; -#define NN_NUM_BUCKETS (256) typedef struct { nn_user_t *buckets[NN_NUM_BUCKETS]; } nn_userhash_t; +enum { + NN_CONN_UNINIT = 0, + NN_CONN_OPEN, + NN_CONN_CLOSED +}; -#ifdef __WIN32 -const char *hstrerror(int err); -#endif -int nn_get_socket_errno(void); -const char *nn_get_socket_errstr(int err); +typedef struct _nn_conn_t { + int socket; + int port; + struct in_addr address; + fd_set sockfds; + + void (*errfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap); + void (*msgfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap); + + int err; + int status; + + char buf[NN_CONNBUF_SIZE + 16]; + char *ptr; + ssize_t got; +} nn_conn_t; + + +const char *nn_get_errstr(int err); BOOL nn_network_init(void); void nn_network_close(void); -int nn_open_connection(struct in_addr *addr, const int port); -void nn_close_connection(const int sock); -BOOL nn_send_to_socket(const int sock, char *buf, const size_t bufLen); -BOOL nn_send_msg(const int sock, const char *user, const char *fmt, ...); +nn_conn_t * nn_conn_open(struct in_addr *addr, const int port); +void nn_conn_close(nn_conn_t *); +BOOL nn_conn_pull(nn_conn_t *); +BOOL nn_conn_send_buf(nn_conn_t *, const char *buf, const size_t len); +BOOL nn_conn_send_msg(nn_conn_t *, const char *user, const char *fmt, ...); +BOOL nn_conn_check(nn_conn_t *); + nn_userhash_t *nn_userhash_new(void); nn_user_t * nn_userhash_foreach(const nn_userhash_t *, int (*func)(const nn_user_t *)); @@ -75,6 +98,7 @@ nn_user_t * nn_user_copy(const nn_user_t *src); nn_user_t * nn_user_find(const nn_userhash_t *list, const char *name); + char * nn_encode_str1(const char *str); char * nn_decode_str1(const char *str); char * nn_encode_str2(const char *str); @@ -88,6 +112,7 @@ void nn_ringbuf_free(nn_ringbuf_t *buf); void nn_ringbuf_add(nn_ringbuf_t *buf, const char *str); + int nn_editbuf_write(nn_editbuf_t *buf, ssize_t pos, int ch); int nn_editbuf_insert(nn_editbuf_t *buf, ssize_t pos, int ch); int nn_editbuf_delete(nn_editbuf_t *buf, ssize_t pos); diff -r b0b63d164702 -r 2e4850ece456 nnchat.c --- 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 = "", *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, ""); - (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, ""); - (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 = ""; - 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();