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
00024
00025
00026
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