Use offsetof macro where possible to defined header size;
authorteodor <teodor>
Fri, 30 Nov 2007 18:07:44 +0000 (18:07 +0000)
committerteodor <teodor>
Fri, 30 Nov 2007 18:07:44 +0000 (18:07 +0000)
Use network byteorder for messages
Use standart message type for tcp connection.

connection.h
regis.h
tcp.c
tmalloc.h
udp.c

index 6ccd725..572e357 100644 (file)
@@ -6,13 +6,13 @@
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
- *        notice, this list of conditions and the following disclaimer.
+ *     notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
- *        notice, this list of conditions and the following disclaimer in the
- *        documentation and/or other materials provided with the distribution.
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the author nor the names of any co-contributors
- *        may be used to endorse or promote products derived from this software
- *        without specific prior written permission.
+ *     may be used to endorse or promote products derived from this software
+ *     without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-
+#include "tools.h"
 
 #define CS_OK          0
 #define CS_INPROCESS    1
 #define CS_CONNECTED    2
-#define CS_READ         3
-#define CS_SEND         4
-#define CS_WAIT         5
-#define CS_ERROR        6
+#define CS_READ         3
+#define CS_SEND         4
+#define CS_WAIT         5
+#define CS_ERROR       6
 #define CS_FINISHSEND   7
 #define CS_FINISHREAD   8
 #define CS_TIMEOUT     9
 
 #define READ_INCRIMENT_BUFSIZ 1024
 
+/*
+ * any message shoulbe compatible with TCMsg struct
+ */
+typedef struct {
+               /* len and type should be transferred in network byte order */
+       u_int32_t       len; 
+       u_int32_t       type;
+       char        data[1];
+} TCMsg;
+
+#define TCMSGHDRSZ      offsetof(TCMsg, data)
+
+/* tcp */
 typedef struct {
        /* I/O buffer */
-        u_int32_t  len;
-        char    *buf;
-        char    *ptr;
+       u_int32_t  len;
+       char    *ptr;
+       TCMsg   *buf; /* send buf */
 
        /* internal fields */
-        int     fd;
-        u_int32_t
+       int     fd;
+       u_int32_t
                readyio:1,  
                state:29;
-        struct sockaddr_in serv_addr;
+       struct sockaddr_in serv_addr;
 
        /* external link */
        void*           data;
 } TC_Connection;
 
-#define TCCONNHDRSZ   ( sizeof(TC_Connection) - sizeof(void*) )
+#define TCCONNHDRSZ  offsetof(TC_Connection, data)
 
 TC_Connection *TC_fillConnection( TC_Connection *cs, char *name, u_int32_t port );
 TC_Connection* TC_AcceptTcp(TC_Connection *cs);
 u_int32_t TC_ClientInitConnection(TC_Connection *cs, char *name, u_int32_t port);
 u_int32_t TC_ServerInitConnect( TC_Connection *cs );
 u_int32_t TC_ServerConnect( TC_Connection *cs, int timeout );
+/*
+ * TC_Send doesn't promise to keep TC_Connection->buf unchanged
+ */
 u_int32_t TC_Send( TC_Connection *cs );
 u_int32_t TC_Read( TC_Connection *cs, size_t maxsize );
 u_int32_t TC_Talk( TC_Connection *cs, size_t maxsize );
 void TC_FreeConnection( TC_Connection *cs );
 int TC_ReadyIO( TC_Connection **cs, int number, int timeout );
 
-typedef struct {
-        u_int32_t       len;
-        u_int32_t       type;
-        char            data[1];
-} TCMsg;
-
-#define TCMSGHDRSZ      (2*sizeof(u_int32_t))
+/* udp */
 
 
-/* udp */
 typedef struct {
        char    *host;
        u_int32_t       port;
@@ -124,16 +133,16 @@ typedef struct {
  *
  * Udp client send:
  * Msg msg;
- * msg.host        = "127.0.0.1";
- * msg.port        = 5432;
+ * msg.host    = "127.0.0.1";
+ * msg.port    = 5432;
  * msg.sockfd =-1;
  * msg.msg = GOTFILLEDPMSG();
  * if ( TC_sendMsg(&msg)!=CS_OK ) {
- *        //Very bad
+ *     //Very bad
  * }
  * msg.msg = GOTFILLEDPMSG();
  * if ( TC_sendMsg(&msg)!=CS_OK ) {
- *        //Very bad
+ *     //Very bad
  * }
  * TC_closefd(&msg);
  */ 
@@ -143,10 +152,14 @@ u_int32_t TC_getMsg( int sockfd, Msg *msg );
 u_int32_t TC_sendMsg( Msg *msg );
 void     TC_closefd( Msg *msg );
 
+/*
+ * Connection pool
+ */
+
 typedef struct {
-        u_int32_t       len;
-        u_int32_t       number;
-        TC_Connection   **conn;
+       u_int32_t       len;
+       u_int32_t       number;
+       TC_Connection   **conn;
 } PoolConnection;
 
 void TC_addConnection(PoolConnection *pool, TC_Connection *c);
diff --git a/regis.h b/regis.h
index c28c619..bed78fd 100644 (file)
--- a/regis.h
+++ b/regis.h
@@ -31,6 +31,7 @@
 #define __REGIS_H__
 
 #include <sys/types.h>
+#include "tools.h"
 
 typedef struct RegisNode {
        u_int32_t       
@@ -41,7 +42,7 @@ typedef struct RegisNode {
        unsigned char   data[1];
 } RegisNode;
 
-#define  RNHDRSZ       (sizeof(u_int32_t)+sizeof(void*))
+#define  RNHDRSZ       offsetof(RegisNode, data)
 
 #define        RSF_ONEOF       1
 #define        RSF_NONEOF      2
diff --git a/tcp.c b/tcp.c
index 7183b42..112e98a 100644 (file)
--- a/tcp.c
+++ b/tcp.c
@@ -343,17 +343,22 @@ TC_Send( TC_Connection *cs ) {
        if ( cs->state == CS_ERROR )
                return CS_ERROR;
 
-       if ( cs->state != CS_SEND ) {
+       if ( cs->state != CS_SEND || cs->ptr == NULL ) {
                cs->state = CS_SEND;
-               cs->ptr = cs->buf;
+               cs->ptr = (char*)cs->buf;
+               cs->len = cs->buf->len;
+
+               /* convert fields to network byteorder */
+               cs->buf->len = htonl(cs->buf->len);
+               cs->buf->type = htonl(cs->buf->type);
        }
 
-       if ( cs->ptr - cs->buf >= cs->len ) {
+       if ( cs->ptr - (char*)cs->buf >= cs->len ) {
                cs->state = CS_FINISHSEND;
                return CS_FINISHSEND;
        }
 
-       if ((sz=write(cs->fd, cs->ptr, cs->len - (cs->ptr - cs->buf)))==0 ||
+       if ((sz=write(cs->fd, cs->ptr, cs->len - (cs->ptr - (char*)cs->buf)))==0 ||
                (sz < 0 && (errno == EWOULDBLOCK || errno == EAGAIN))) {
 
                /* SunOS 4.1.x, are broken and select() says that
@@ -375,8 +380,11 @@ TC_Send( TC_Connection *cs ) {
 
        cs->ptr += sz;
 
-       if ( cs->ptr - cs->buf >= cs->len ) {
+       if ( cs->ptr - (char*)cs->buf >= cs->len ) {
                cs->state = CS_FINISHSEND;
+               /* revert byteorder conversion */
+               cs->buf->len = ntohl(cs->buf->len);
+               cs->buf->type = ntohl(cs->buf->type);
                return CS_FINISHSEND;
        }
        
@@ -385,12 +393,13 @@ TC_Send( TC_Connection *cs ) {
 
 static void 
 resizeCS( TC_Connection *cs, int sz ) {
-       int diff = cs->ptr - cs->buf;
+       int diff = cs->ptr - (char*)cs->buf;
+
        if ( cs->len >= sz )
                return; 
        cs->len = sz;
-       cs->buf = (char*)trealloc( (void*)cs->buf, cs->len );
-       cs->ptr = cs->buf + diff;
+       cs->buf = (TCMsg*)trealloc( (void*)cs->buf, cs->len );
+       cs->ptr = ((char*)cs->buf) + diff;
 }
 
 u_int32_t
@@ -400,17 +409,18 @@ TC_Read( TC_Connection *cs, size_t maxsize ) {
        if ( cs->state == CS_ERROR )
                return CS_ERROR;
 
-       if (cs->state != CS_READ ) {
+       if (cs->state != CS_READ || cs->ptr == NULL ) {
                cs->state = CS_READ;
-               cs->ptr = cs->buf;
+               cs->ptr = (char*)cs->buf;
+               cs->len = 0;
        }
 
-       alreadyread = cs->ptr - cs->buf;
-       if ( alreadyread < sizeof(u_int32_t) ) {
-               toread = sizeof(u_int32_t) - alreadyread;
-               resizeCS(cs, sizeof(u_int32_t));
+       alreadyread = cs->ptr - (char*)cs->buf;
+       if ( alreadyread < TCMSGHDRSZ ) {
+               toread = TCMSGHDRSZ - alreadyread;
+               resizeCS(cs, TCMSGHDRSZ);
        } else {
-               totalread = *(u_int32_t*)(cs->buf);
+               totalread = ntohl(cs->buf->len);
                if ( maxsize > 0 && totalread > maxsize )
                {
                        tlog(TL_ALARM,"TC_Read: message size (%d b) is greater than max allowed (%d b)", totalread, maxsize);
@@ -435,7 +445,13 @@ TC_Read( TC_Connection *cs, size_t maxsize ) {
                return CS_ERROR;
        }
        
-
+       if ( alreadyread < TCMSGHDRSZ  && alreadyread + sz >= TCMSGHDRSZ ) {
+               /* 
+                * we just read header - we can get totalread value. 
+                */
+               totalread = ntohl(cs->buf->len);
+       }
+       
        cs->ptr += sz;
        alreadyread += sz;
        if ( sz == 0 && alreadyread != totalread ) {
@@ -443,7 +459,13 @@ TC_Read( TC_Connection *cs, size_t maxsize ) {
                cs->state = CS_ERROR;
                return CS_ERROR;
        }
-       cs->state = ( alreadyread == totalread ) ? CS_FINISHREAD : CS_READ;
+
+       if ( alreadyread == totalread ) {
+               cs->buf->len = ntohl(cs->buf->len);
+               cs->buf->type = ntohl(cs->buf->type);
+               cs->state = CS_FINISHREAD;
+       }
+
        return cs->state;
 }
 
@@ -475,14 +497,14 @@ TC_Talk( TC_Connection *cs, size_t maxsize  ) {
                return cs->state;
        
        cs->state = CS_SEND;
-       cs->ptr = cs->buf;
+       cs->ptr = NULL;
        while( cs->state != CS_FINISHSEND ) {
                while( !TC_ReadyIO( &cs, 1, 100) );
                if ( TC_Send(cs) == CS_ERROR ) return CS_ERROR;
        }
 
        cs->state = CS_READ;
-       cs->ptr = cs->buf;
+       cs->ptr = NULL;
        while( cs->state != CS_FINISHREAD ) {
                while( !TC_ReadyIO( &cs, 1, 100) );
                if ( TC_Read(cs, maxsize) == CS_ERROR ) return CS_ERROR;
index a39a3ff..67069eb 100644 (file)
--- a/tmalloc.h
+++ b/tmalloc.h
@@ -55,7 +55,7 @@ typedef struct MemoryChunk {
        char data[1];
 } MemoryChunk;
 
-#define MEMCHNKHDRSZ   ( sizeof(u_int32_t)*2 + sizeof(MemoryChunk*) )
+#define MEMCHNKHDRSZ   offsetof(MemoryChunk, data)
 
 typedef struct MemoryContext {
        u_int32_t       flags;
diff --git a/udp.c b/udp.c
index 6e127da..9c212af 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -110,6 +110,12 @@ TC_getMsg( int sockfd, Msg *msg ) {
                tlog(TL_ALARM, "Got message %d bytes (should be al least %d)", n, TCMSGHDRSZ );
                return CS_AGAIN;
        }
+       
+       /*
+        * convert from network byteorder
+        */
+       pmsg->len = ntohl(pmsg->len);
+       pmsg->type = ntohl(pmsg->type);
 
        if ( pmsg->len > MSGMAXSIZE  ) {
                tlog(TL_ALARM, "Messages (%d bytes) is too big", pmsg->len);
@@ -130,6 +136,8 @@ TC_getMsg( int sockfd, Msg *msg ) {
 /* send */
 u_int32_t 
 TC_sendMsg( Msg *msg ) {
+       int msglen;
+
        if ( msg->msg == NULL || msg->msg->len <=0  )
                return CS_OK;
 
@@ -182,7 +190,14 @@ TC_sendMsg( Msg *msg ) {
                msg->host_addr.sin_port = htons(msg->port);
        }
 
-       if (sendto(msg->sockfd, (void*)msg->msg, msg->msg->len, 0, (struct sockaddr *) &(msg->host_addr), sizeof(msg->host_addr)) != msg->msg->len) {
+       /*
+        * convert to network byteorder
+        */
+       msglen = msg->msg->len;
+       msg->msg->len = htonl(msg->msg->len);
+       msg->msg->type = htonl(msg->msg->type);
+
+       if (sendto(msg->sockfd, (void*)msg->msg, msglen, 0, (struct sockaddr *) &(msg->host_addr), sizeof(msg->host_addr)) != msglen) {
                tlog(TL_CRIT,"Can't send message to %s:%d : %s", msg->host, msg->port, strerror(errno));
                close(msg->sockfd);
                msg->sockfd=-1;