Remove TODO file
[remote/remote-mci.git] / protocols / tcputil.cc
blob0f648e8411fcfb73118bec3b79267ed0ae048045
1 #include "tcputil.h"
2 #include "macros.h"
3 namespace remote { namespace protocols {
5 int openServerSocket(struct sockaddr_in& server, unsigned int port, int max_pending, int retryinterval)
7 int serversock = -1 ;
9 do {
10 /* Create the TCP socket */
11 if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
13 log("Could not create server socket, waiting to try again\n");
14 usleep(retryinterval * 1000000);
16 } while ( serversock < 0 );
19 /* Construct the server sockaddr_in structure */
20 memset(&server, 0, sizeof(server)); /* Clear struct */
21 server.sin_family = AF_INET; /* Internet/IP */
22 server.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
23 server.sin_port = htons(port); /* server port */
24 /* Bind the server socket */
25 while (bind(serversock, (struct sockaddr *) &server, sizeof(server)) < 0)
27 log("Could not bind server socket, waiting to try again \n");
28 usleep(retryinterval * 1000000);
31 /* Listen on the server socket */
32 if (listen(serversock, max_pending) < 0)
34 log("Could not listen on server socket.\n");
35 return -1;
38 return serversock;
41 int nextClient( int serversock, sockaddr_in& client )
43 int clientsock;
44 unsigned int clientlen = sizeof(client);
45 /* Wait for client connection */
46 if ((clientsock = accept(serversock, (struct sockaddr *) &client, &clientlen)) < 0)
48 log("Could not accept client connection.\n");
50 log("Accepted connection from %s\n",inet_ntoa(client.sin_addr));
51 return clientsock;
54 int openClientSocket(std::string address, unsigned int port)
56 int sock;
57 struct sockaddr_in server;
59 // Create the TCP control socket
60 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
61 log("Failed to create client socket.\n");
62 return sock;
65 memset(&server, 0, sizeof(server));
66 server.sin_family = AF_INET;
67 server.sin_addr.s_addr = resolve(address.c_str());
68 server.sin_port = htons(port);
70 // Establish connection
71 if (connect(sock,(struct sockaddr *) &server,sizeof(server)) < 0)
73 log("Failed to connect with server %s on port %u.\n", address.c_str(),port);
74 close(sock);
75 return -1;
79 return sock;
82 in_addr_t resolve(const char *ip_addr)
84 struct hostent *hp;
85 in_addr_t ip;
86 hp = gethostbyname(ip_addr);
88 if (!hp)
90 ip = inet_addr(ip_addr);
91 if (ip == INADDR_NONE) return INADDR_NONE;
92 else return ip;
95 // hp->h_length should equal to 4
96 memcpy(&ip, hp->h_addr, 4);
97 return ip;
101 char* getHostByIp(in_addr ip)
103 char* ipaddr = inet_ntoa(ip);
104 log("Looking up ip %s with len %u\n",ipaddr,strlen(ipaddr));
105 hostent* host = gethostbyaddr(ipaddr,strlen(ipaddr),AF_INET);
107 if (host)
109 log("Host name %s\n",host->h_name);
110 return host->h_name;
112 else
115 log("No host name found!\n");
117 switch (h_errno)
119 case HOST_NOT_FOUND:
120 log("HOST_NOT_FOUND\n");
121 break;
122 case NO_ADDRESS:
123 log("NO_ADDRESS\n");
124 break;
125 case NO_RECOVERY:
126 log("NO_RECOVERY\n");
127 break;
128 case TRY_AGAIN:
129 printf("TRY_AGAIN\n");
130 break;
131 default:
132 log("Unknown error %u\n",h_errno);
135 return "";
139 void setSendTimeout(int fd, long seconds, long microseconds )
141 struct timeval timeOut;
142 timeOut.tv_sec = seconds;
143 timeOut.tv_usec = microseconds;
144 if ( setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeOut,sizeof(timeOut)) != 0 )
146 log("Failed to set SO_SNDTIMEO to %i\n",fd);
147 return;
151 void setSendBuffer( int fd, int byteSize)
153 if ( setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &byteSize,sizeof(byteSize)) != 0 )
155 log("Failed to set SO_SNDBUF to %i on %i\n",byteSize,fd);
156 return;
160 void setKeepAlive( int fd, int numProbes, int idleTime, int interval)
162 // set keepalive on
163 int optval = 1;
165 if ( setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval,sizeof(optval)) != 0 )
167 log("Failed to set SO_KEEPALIVE on %i\n",fd);
168 return;
171 // The maximum number of keepalive probes TCP should send before dropping the connection.
172 if ( setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &numProbes, sizeof(numProbes)) != 0)
174 log("Failed to set TCP_KEEPCNT to %i on %i\n",numProbes,fd);
175 return;
178 // The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes.
179 if ( setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &idleTime, sizeof(idleTime)) != 0)
181 log("Failed to set TCP_KEEPIDLE to %i on %i\n",idleTime,fd);
182 return;
185 // The time (in seconds) between individual keepalive probes.
186 if ( setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)) != 0)
188 log("Failed to set TCP_KEEPINTVL to %i on %i\n",interval,fd);
189 return;
193 uint64_t ntohll(uint64_t n) {
194 #if __BYTE_ORDER == __BIG_ENDIAN
195 return n;
196 #else
197 return (((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32);
198 #endif
201 uint64_t ntoh(uint64_t n)
203 return ntohll(n);
206 uint32_t ntoh(uint32_t n)
208 return ntohl(n);
211 uint16_t ntoh(uint16_t n)
213 return ntohs(n);
216 uint8_t ntoh(uint8_t n)
218 return n;
221 int16_t ntoh(int16_t n)
223 return ntohs(n);
226 int32_t ntoh(int32_t n)
228 return ntohl(n);
231 uint64_t htonll(uint64_t n) {
232 #if __BYTE_ORDER == __BIG_ENDIAN
233 return n;
234 #else
235 return (((uint64_t)htonl(n)) << 32) + htonl(n >> 32);
236 #endif
239 uint64_t hton(uint64_t n)
241 return htonll(n);
244 uint32_t hton(uint32_t n)
246 return htonl(n);
249 uint16_t hton(uint16_t n)
251 return htons(n);
254 uint8_t hton(uint8_t n)
256 return n;
259 int16_t hton(int16_t n)
261 return htons(n);
264 int32_t hton(int32_t n)
266 return htonl(n);
269 template<class T>
270 bool recv(int fd, T& value)
272 T netvalue;
273 if ( recv( fd, (char*)&netvalue, sizeof(T), MSG_WAITALL) <= 0 )
275 return false;
277 value = ntoh(netvalue);
278 return true;
281 template<class T>
282 bool send(int fd, T value)
284 T netvalue = hton(value);
285 return ( ::send(fd, (char*)&netvalue, sizeof(T), 0) == sizeof(T) );
288 template bool recv<uint8_t>(int fd, uint8_t& value);
289 template bool recv<uint16_t>(int fd, uint16_t& value);
290 template bool recv<uint32_t>(int fd, uint32_t& value);
291 template bool recv<uint64_t>(int fd, uint64_t& value);
292 template bool send<uint8_t>(int fd, uint8_t value);
293 template bool send<uint16_t>(int fd, uint16_t value);
294 template bool send<uint32_t>(int fd, uint32_t value);
295 template bool send<uint64_t>(int fd, uint64_t value);
297 template<class T> uint8_t* readvalue(T& value,uint8_t* buffer, uint32_t& buflen)
299 if (buflen < sizeof(value)) __THROW__ ("Cannot read value from buffer - buffer too short!");
300 value = ntoh(*((T*)buffer));
301 buflen = buflen - sizeof(value);
302 return buffer+sizeof(value);
305 template uint8_t* readvalue<uint8_t>(uint8_t& value,uint8_t* buffer, uint32_t& buflen);
306 template uint8_t* readvalue<uint16_t>(uint16_t& value,uint8_t* buffer, uint32_t& buflen);
307 template uint8_t* readvalue<uint32_t>(uint32_t& value,uint8_t* buffer, uint32_t& buflen);
308 template uint8_t* readvalue<uint64_t>(uint64_t& value,uint8_t* buffer, uint32_t& buflen);
310 template<class T> uint8_t* writevalue(T value,uint8_t* buffer, uint32_t& buflen)
312 if (buflen < sizeof(value)) __THROW__ ("Cannot write value to buffer - buffer too short!");
313 *((T*)buffer) = hton(value);
314 buflen = buflen - sizeof(value);
315 return buffer+sizeof(value);
318 template uint8_t* writevalue<uint8_t>(uint8_t value,uint8_t* buffer, uint32_t& buflen);
319 template uint8_t* writevalue<uint16_t>(uint16_t value,uint8_t* buffer, uint32_t& buflen);
320 template uint8_t* writevalue<uint32_t>(uint32_t value,uint8_t* buffer, uint32_t& buflen);
321 template uint8_t* writevalue<uint64_t>(uint64_t value,uint8_t* buffer, uint32_t& buflen);