Protocols: Fix includes to use the explicit path of the header files
[remote/remote-mci.git] / protocols / tcputil.cc
blob66d95730dbf2d3f6a85f5d199985dfe41e2ca8c0
1 #include "protocols/tcputil.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) {
12 Log::warn("Could not create server socket, waiting to try again");
13 usleep(retryinterval * 1000000);
15 } while (serversock < 0);
18 /* Construct the server sockaddr_in structure */
19 memset(&server, 0, sizeof(server)); /* Clear struct */
20 server.sin_family = AF_INET; /* Internet/IP */
21 server.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
22 server.sin_port = htons(port); /* server port */
23 /* Bind the server socket */
24 while (bind(serversock, (struct sockaddr *) &server, sizeof(server)) < 0) {
25 Log::warn("Could not bind server socket, waiting to try again");
26 usleep(retryinterval * 1000000);
29 /* Listen on the server socket */
30 if (listen(serversock, max_pending) < 0) {
31 Log::error("Could not listen on server socket.");
32 return -1;
35 return serversock;
38 int nextClient(int serversock, sockaddr_in& client)
40 int clientsock;
41 unsigned int clientlen = sizeof(client);
43 /* Wait for client connection */
44 if ((clientsock = accept(serversock, (struct sockaddr *) &client, &clientlen)) < 0)
45 Log::error("Could not accept client connection: %s", strerror(errno));
46 else
47 Log::info("Accepted connection from %s", inet_ntoa(client.sin_addr));
48 return clientsock;
51 int openClientSocket(std::string address, unsigned int port)
53 int sock;
54 struct sockaddr_in server;
56 // Create the TCP control socket
57 if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
58 Log::error("Failed to create client socket: %s", strerror(errno));
59 return -1;
62 memset(&server, 0, sizeof(server));
63 server.sin_family = AF_INET;
64 server.sin_addr.s_addr = resolve(address.c_str());
65 server.sin_port = htons(port);
67 // Establish connection
68 if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
69 Log::error("Failed to connect to %s on port %u: %s",
70 address.c_str(), port, strerror(errno));
71 close(sock);
72 return -1;
75 return sock;
78 in_addr_t resolve(const char *ip_addr)
80 struct hostent *hp;
81 in_addr_t ip;
82 hp = gethostbyname(ip_addr);
84 if (!hp)
86 ip = inet_addr(ip_addr);
87 if (ip == INADDR_NONE) return INADDR_NONE;
88 else return ip;
91 // hp->h_length should equal to 4
92 memcpy(&ip, hp->h_addr, 4);
93 return ip;
97 const char *getHostByIp(in_addr ip)
99 char *ipaddr = inet_ntoa(ip);
100 hostent* host = gethostbyaddr(ipaddr,strlen(ipaddr),AF_INET);
102 if (host) {
103 Log::info("Resolved %s to host name %s", ipaddr, host->h_name);
104 return host->h_name;
107 Log::error("Failed to resolve %s: %s", ipaddr, hstrerror(h_errno));
108 return "";
111 void setSendTimeout(int fd, long seconds, long microseconds )
113 struct timeval timeOut;
115 timeOut.tv_sec = seconds;
116 timeOut.tv_usec = microseconds;
117 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeOut, sizeof(timeOut)) != 0) {
118 Log::error("Failed to set SO_SNDTIMEO to %i: %s",
119 fd, strerror(errno));
123 void setSendBuffer( int fd, int byteSize)
125 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &byteSize, sizeof(byteSize)) != 0) {
126 Log::error("Failed to set SO_SNDBUF to %i on %i: %s",
127 byteSize, fd, strerror(errno));
131 void setKeepAlive( int fd, int numProbes, int idleTime, int interval)
133 // set keepalive on
134 int optval = 1;
136 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval,sizeof(optval)) != 0) {
137 Log::error("Failed to set SO_KEEPALIVE on %i: %s", fd, strerror(errno));
138 return;
141 // The maximum number of keepalive probes TCP should send before dropping the connection.
142 if (setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &numProbes, sizeof(numProbes)) != 0) {
143 Log::error("Failed to set TCP_KEEPCNT to %i on %i: %s",
144 numProbes, fd, strerror(errno));
145 return;
148 // The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes.
149 if (setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &idleTime, sizeof(idleTime)) != 0) {
150 Log::error("Failed to set TCP_KEEPIDLE to %i on %i: %s",
151 idleTime, fd, strerror(errno));
152 return;
155 // The time (in seconds) between individual keepalive probes.
156 if (setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &interval, sizeof(interval)) != 0) {
157 Log::error("Failed to set TCP_KEEPINTVL to %i on %i: %s",
158 interval, fd, strerror(errno));
159 return;
163 uint64_t ntohll(uint64_t n) {
164 #if __BYTE_ORDER == __BIG_ENDIAN
165 return n;
166 #else
167 return (((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32);
168 #endif
171 uint64_t ntoh(uint64_t n)
173 return ntohll(n);
176 uint32_t ntoh(uint32_t n)
178 return ntohl(n);
181 uint16_t ntoh(uint16_t n)
183 return ntohs(n);
186 uint8_t ntoh(uint8_t n)
188 return n;
191 int16_t ntoh(int16_t n)
193 return ntohs(n);
196 int32_t ntoh(int32_t n)
198 return ntohl(n);
201 uint64_t htonll(uint64_t n) {
202 #if __BYTE_ORDER == __BIG_ENDIAN
203 return n;
204 #else
205 return (((uint64_t)htonl(n)) << 32) + htonl(n >> 32);
206 #endif
209 uint64_t hton(uint64_t n)
211 return htonll(n);
214 uint32_t hton(uint32_t n)
216 return htonl(n);
219 uint16_t hton(uint16_t n)
221 return htons(n);
224 uint8_t hton(uint8_t n)
226 return n;
229 int16_t hton(int16_t n)
231 return htons(n);
234 int32_t hton(int32_t n)
236 return htonl(n);
239 template<class T>
240 bool recv(int fd, T& value)
242 T netvalue;
243 if ( recv( fd, (char*)&netvalue, sizeof(T), MSG_WAITALL) <= 0 )
245 return false;
247 value = ntoh(netvalue);
248 return true;
251 template<class T>
252 bool send(int fd, T value)
254 T netvalue = hton(value);
255 return ( ::send(fd, (char*)&netvalue, sizeof(T), 0) == sizeof(T) );
258 template bool recv<uint8_t>(int fd, uint8_t& value);
259 template bool recv<uint16_t>(int fd, uint16_t& value);
260 template bool recv<uint32_t>(int fd, uint32_t& value);
261 template bool recv<uint64_t>(int fd, uint64_t& value);
262 template bool send<uint8_t>(int fd, uint8_t value);
263 template bool send<uint16_t>(int fd, uint16_t value);
264 template bool send<uint32_t>(int fd, uint32_t value);
265 template bool send<uint64_t>(int fd, uint64_t value);
267 template<class T> uint8_t* readvalue(T& value,uint8_t* buffer, uint32_t& buflen)
269 if (buflen < sizeof(value)) __THROW__ ("Cannot read value from buffer - buffer too short!");
270 value = ntoh(*((T*)buffer));
271 buflen = buflen - sizeof(value);
272 return buffer+sizeof(value);
275 template uint8_t* readvalue<uint8_t>(uint8_t& value,uint8_t* buffer, uint32_t& buflen);
276 template uint8_t* readvalue<uint16_t>(uint16_t& value,uint8_t* buffer, uint32_t& buflen);
277 template uint8_t* readvalue<uint32_t>(uint32_t& value,uint8_t* buffer, uint32_t& buflen);
278 template uint8_t* readvalue<uint64_t>(uint64_t& value,uint8_t* buffer, uint32_t& buflen);
280 template<class T> uint8_t* writevalue(T value,uint8_t* buffer, uint32_t& buflen)
282 if (buflen < sizeof(value)) __THROW__ ("Cannot write value to buffer - buffer too short!");
283 *((T*)buffer) = hton(value);
284 buflen = buflen - sizeof(value);
285 return buffer+sizeof(value);
288 template uint8_t* writevalue<uint8_t>(uint8_t value,uint8_t* buffer, uint32_t& buflen);
289 template uint8_t* writevalue<uint16_t>(uint16_t value,uint8_t* buffer, uint32_t& buflen);
290 template uint8_t* writevalue<uint32_t>(uint32_t value,uint8_t* buffer, uint32_t& buflen);
291 template uint8_t* writevalue<uint64_t>(uint64_t value,uint8_t* buffer, uint32_t& buflen);