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
)
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.");
38 int nextClient(int serversock
, sockaddr_in
& client
)
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
));
47 Log::info("Accepted connection from %s", inet_ntoa(client
.sin_addr
));
51 int openClientSocket(std::string address
, unsigned int port
)
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
));
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
));
78 in_addr_t
resolve(const char *ip_addr
)
82 hp
= gethostbyname(ip_addr
);
86 ip
= inet_addr(ip_addr
);
87 if (ip
== INADDR_NONE
) return INADDR_NONE
;
91 // hp->h_length should equal to 4
92 memcpy(&ip
, hp
->h_addr
, 4);
97 const char *getHostByIp(in_addr ip
)
99 char *ipaddr
= inet_ntoa(ip
);
100 hostent
* host
= gethostbyaddr(ipaddr
,strlen(ipaddr
),AF_INET
);
103 Log::info("Resolved %s to host name %s", ipaddr
, host
->h_name
);
107 Log::error("Failed to resolve %s: %s", ipaddr
, hstrerror(h_errno
));
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
)
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
));
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
));
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
));
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
));
163 uint64_t ntohll(uint64_t n
) {
164 #if __BYTE_ORDER == __BIG_ENDIAN
167 return (((uint64_t)ntohl(n
)) << 32) + ntohl(n
>> 32);
171 uint64_t ntoh(uint64_t n
)
176 uint32_t ntoh(uint32_t n
)
181 uint16_t ntoh(uint16_t n
)
186 uint8_t ntoh(uint8_t n
)
191 int16_t ntoh(int16_t n
)
196 int32_t ntoh(int32_t n
)
201 uint64_t htonll(uint64_t n
) {
202 #if __BYTE_ORDER == __BIG_ENDIAN
205 return (((uint64_t)htonl(n
)) << 32) + htonl(n
>> 32);
209 uint64_t hton(uint64_t n
)
214 uint32_t hton(uint32_t n
)
219 uint16_t hton(uint16_t n
)
224 uint8_t hton(uint8_t n
)
229 int16_t hton(int16_t n
)
234 int32_t hton(int32_t n
)
240 bool recv(int fd
, T
& value
)
243 if ( recv( fd
, (char*)&netvalue
, sizeof(T
), MSG_WAITALL
) <= 0 )
247 value
= ntoh(netvalue
);
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
);