lux/dist/util.h

00001 
00004 #ifndef LUX_SERVER_UTIL_H
00005 #define LUX_SERVER_UTIL_H
00006 
00007 #include "lux/lux.h"
00008 #include "common.h"
00009 #include <errno.h>
00010 #include <cstdio>
00011 #include <cstring>
00012 #include <sys/types.h>
00013 #include <sys/socket.h>
00014 #include <netinet/in.h>
00015 #include <netinet/tcp.h>
00016 #include <arpa/inet.h>
00017 #include <sys/uio.h>
00018 #include <netdb.h>
00019 
00020 #include <time.h>
00021 #include <sys/time.h>
00022 
00023 // System call wrapper used in gauche.
00024 // (macro names are changed.)
00025 // thanks to shirok and kzk.
00026 // http://kzk9.net/column/write.html
00027 #define SAFE_SYSCALL3(result, expr, check) \
00028   do { \
00029     (result) = (expr); \
00030     if ((check) && errno == EINTR) { \
00031       errno = 0; \
00032     } else { \
00033       break; \
00034     } \
00035   } while (1)
00036 
00037 #define SAFE_SYSCALL(result, expr) \
00038   SAFE_SYSCALL3(result, expr, (result < 0))
00039 
00040 namespace Lux {
00041 
00042   static inline
00043   double gettimeofday_sec()
00044   {
00045     struct timeval tv;
00046     gettimeofday(&tv, NULL);
00047     return tv.tv_sec + (double)tv.tv_usec*1e-6;
00048   }
00049 
00050   static inline
00051   int lut_connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
00052   {
00053     int ret;
00054     SAFE_SYSCALL(ret, connect(s, serv_addr, addrlen));
00055     return ret;
00056   }
00057 
00058   static inline
00059   int lut_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
00060   {
00061     int ret;
00062     SAFE_SYSCALL(ret, accept(s, addr, addrlen));
00063     return ret;
00064   }
00065 
00066   static inline
00067   ssize_t lut_recv(int s, void *buf, size_t len, int flags)
00068   {
00069     char *p = reinterpret_cast<char *>(buf);
00070     const char * const end_p = p + len;
00071 
00072     while (p < end_p) {
00073       ssize_t num_bytes;
00074       SAFE_SYSCALL(num_bytes, recv(s, p, end_p - p, flags));
00075       if (num_bytes < 0) {
00076         return num_bytes;
00077       } else if (num_bytes == 0) {
00078         return num_bytes;
00079       }
00080       p += num_bytes;
00081     }
00082 
00083     if (p != end_p) {
00084       return -1;
00085     }
00086     return len;
00087   }
00088 
00089   static inline
00090   ssize_t lut_send(int s, const void *buf, size_t len, int flags)
00091   {
00092     const char *p = reinterpret_cast<const char *>(buf);
00093     const char * const end_p = p + len;
00094 
00095     while (p < end_p) {
00096       ssize_t num_bytes;
00097       SAFE_SYSCALL(num_bytes, send(s, p, end_p - p, flags));
00098       if (num_bytes < 0) {
00099         perror("send failed");
00100         break;
00101       }
00102       p += num_bytes;
00103     }
00104 
00105     if (p != end_p) {
00106       return -1;
00107     }
00108     return len;
00109   }
00110 
00111   static inline
00112   ssize_t lut_writev(int fd, struct iovec *vector, int count)
00113   {
00114     size_t total = 0;
00115     for (int i = 0; i < count; ++i) {
00116       total += vector[i].iov_len;
00117     }
00118 
00119     size_t remain = total;
00120     while (1) {
00121       ssize_t num_bytes;
00122       SAFE_SYSCALL(num_bytes, writev(fd, vector, count));
00123       if (num_bytes < 0) {
00124         perror("writev failed");
00125         break;
00126       }
00127       remain -= num_bytes;
00128       if (!remain) { break; }
00129 
00130       for (int i = 0; i < count; ++i) {
00131         if (num_bytes >= vector[i].iov_len) {
00132           num_bytes -= vector[i].iov_len;
00133         } else {
00134           vector[i].iov_len -= num_bytes;
00135           char *p = (char *) vector[i].iov_base;
00136           p += num_bytes;
00137           vector[i].iov_base = p;
00138           int j = 0;
00139           for (; i < count && j < count; ++i, ++j) {
00140             vector[j] = vector[i];
00141           }
00142           count = j;
00143         }
00144       }
00145     }
00146     if (remain > 0) {
00147       return -1;
00148     }
00149     return total;
00150   }
00151 
00152   static inline
00153   bool sock_connect(int &s, in_addr_t ip, uint16_t port)
00154   {
00155     struct sockaddr_in server;
00156     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00157       perror("socket");
00158       return false;
00159     }
00160     int on = 1;
00161     setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
00162 
00163     memset((char *) &server, 0, sizeof(server));
00164     server.sin_family = AF_INET;
00165     server.sin_addr.s_addr = ip;
00166     server.sin_port = htons(port);
00167 
00168     if (lut_connect(s, (struct sockaddr *) &server, sizeof(server)) < 0) {
00169       perror("connect");
00170       return false;
00171     }
00172     return true;
00173   }
00174 
00175   static inline
00176   in_addr_t get_ip_by_str(const char *str)
00177   {
00178     in_addr_t ip;
00179     if ((ip = inet_addr(str)) == INADDR_NONE) {
00180       struct hostent *he;
00181       if ((he = gethostbyname(str)) == NULL) {
00182         return 0;
00183       }   
00184       memcpy((char *) &ip, (char *) he->h_addr, he->h_length);
00185     }
00186     return ip;
00187   }
00188 }
00189 
00190 #endif

Generated on Fri Feb 5 15:50:30 2010 for Lux by  doxygen 1.4.7