network.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #include "network.h"
  17. #include "string.h"
  18. #include "mutex.h"
  19. ////////////////////////////////////////////////////////////////////////////////
  20. /// Platforms supporting Socket interface
  21. ////////////////////////////////////////////////////////////////////////////////
  22. #if defined(__WIN32__)
  23. #define _WINSOCK_DEPRECATED_NO_WARNINGS
  24. //#include <winsock2.h>
  25. //#include <io.h>
  26. typedef int socklen_t;
  27. #define SHUT_RDWR 0x2
  28. #else
  29. #include <unistd.h>
  30. #include <fcntl.h>
  31. #include <sys/types.h>
  32. #include <sys/socket.h>
  33. #include <netinet/in.h>
  34. #include <netinet/tcp.h>
  35. #include <netdb.h>
  36. #define SOCKET int
  37. #define INVALID_SOCKET -1
  38. #define closesocket ::close
  39. #endif
  40. /*! ignore if not supported */
  41. #ifndef MSG_NOSIGNAL
  42. #define MSG_NOSIGNAL 0
  43. #endif
  44. #define BUFFERING 1
  45. namespace embree
  46. {
  47. namespace network
  48. {
  49. __forceinline void initialize() {
  50. #ifdef __WIN32__
  51. static bool initialized = false;
  52. static MutexSys initMutex;
  53. Lock<MutexSys> lock(initMutex);
  54. WSADATA wsaData;
  55. short version = MAKEWORD(1,1);
  56. if (WSAStartup(version,&wsaData) != 0)
  57. THROW_RUNTIME_ERROR("Winsock initialization failed");
  58. initialized = true;
  59. #endif
  60. }
  61. struct buffered_socket_t
  62. {
  63. buffered_socket_t (SOCKET fd, size_t isize = 64*1024, size_t osize = 64*1024)
  64. : fd(fd),
  65. ibuf(new char[isize]), isize(isize), istart(0), iend(0),
  66. obuf(new char[osize]), osize(osize), oend(0) {
  67. }
  68. ~buffered_socket_t () {
  69. delete[] ibuf; ibuf = nullptr;
  70. delete[] obuf; obuf = nullptr;
  71. }
  72. private:
  73. buffered_socket_t (const buffered_socket_t& other) DELETED; // do not implement
  74. buffered_socket_t& operator= (const buffered_socket_t& other) DELETED; // do not implement
  75. public:
  76. SOCKET fd; //!< file descriptor of the socket
  77. char* ibuf;
  78. size_t isize;
  79. size_t istart,iend;
  80. char* obuf;
  81. size_t osize;
  82. size_t oend;
  83. };
  84. struct AutoCloseSocket
  85. {
  86. SOCKET sock;
  87. AutoCloseSocket (SOCKET sock) : sock(sock) {}
  88. ~AutoCloseSocket () {
  89. if (sock != INVALID_SOCKET) {
  90. closesocket(sock);
  91. }
  92. }
  93. };
  94. socket_t connect(const char* host, unsigned short port)
  95. {
  96. initialize();
  97. /*! create a new socket */
  98. SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
  99. if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");
  100. AutoCloseSocket auto_close(sockfd);
  101. /*! perform DNS lookup */
  102. struct hostent* server = ::gethostbyname(host);
  103. if (!server) THROW_RUNTIME_ERROR("server "+std::string(host)+" not found");
  104. /*! perform connection */
  105. struct sockaddr_in serv_addr;
  106. memset((char*)&serv_addr, 0, sizeof(serv_addr));
  107. serv_addr.sin_family = AF_INET;
  108. serv_addr.sin_port = (unsigned short) htons(port);
  109. memcpy((char*)&serv_addr.sin_addr.s_addr, (char*)server->h_addr, server->h_length);
  110. if (::connect(sockfd,(struct sockaddr*) &serv_addr,sizeof(serv_addr)) < 0)
  111. THROW_RUNTIME_ERROR("connection to "+std::string(host)+":"+toString(port)+" failed");
  112. /*! enable TCP_NODELAY */
  113. #ifdef TCP_NODELAY
  114. { int flag = 1; ::setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (const char*)&flag, sizeof(int)); }
  115. #endif
  116. /*! we do not want SIGPIPE to be thrown */
  117. #ifdef SO_NOSIGPIPE
  118. { int flag = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (const char*) &flag, sizeof(int)); }
  119. #endif
  120. auto_close.sock = INVALID_SOCKET;
  121. return (socket_t) new buffered_socket_t(sockfd);
  122. }
  123. socket_t bind(unsigned short port)
  124. {
  125. initialize();
  126. /*! create a new socket */
  127. SOCKET sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
  128. if (sockfd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot create socket");
  129. AutoCloseSocket auto_close(sockfd);
  130. /* When the server completes, the server socket enters a time-wait state during which the local
  131. address and port used by the socket are believed to be in use by the OS. The wait state may
  132. last several minutes. This socket option allows bind() to reuse the port immediately. */
  133. #ifdef SO_REUSEADDR
  134. { int flag = true; ::setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&flag, sizeof(int)); }
  135. #endif
  136. /*! bind socket to port */
  137. struct sockaddr_in serv_addr;
  138. memset((char *) &serv_addr, 0, sizeof(serv_addr));
  139. serv_addr.sin_family = AF_INET;
  140. serv_addr.sin_port = (unsigned short) htons(port);
  141. serv_addr.sin_addr.s_addr = INADDR_ANY;
  142. if (::bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0)
  143. THROW_RUNTIME_ERROR("binding to port "+toString(port)+" failed");
  144. /*! listen to port, up to 5 pending connections */
  145. if (::listen(sockfd,5) < 0)
  146. THROW_RUNTIME_ERROR("listening on socket failed");
  147. auto_close.sock = INVALID_SOCKET;
  148. return (socket_t) new buffered_socket_t(sockfd);
  149. }
  150. socket_t listen(socket_t hsock)
  151. {
  152. SOCKET sockfd = ((buffered_socket_t*) hsock)->fd;
  153. /*! accept incoming connection */
  154. struct sockaddr_in addr;
  155. socklen_t len = sizeof(addr);
  156. SOCKET fd = ::accept(sockfd, (struct sockaddr *) &addr, &len);
  157. if (fd == INVALID_SOCKET) THROW_RUNTIME_ERROR("cannot accept connection");
  158. /*! enable TCP_NODELAY */
  159. #ifdef TCP_NODELAY
  160. { int flag = 1; ::setsockopt(fd,IPPROTO_TCP,TCP_NODELAY,(char*)&flag,sizeof(int)); }
  161. #endif
  162. /*! we do not want SIGPIPE to be thrown */
  163. #ifdef SO_NOSIGPIPE
  164. { int flag = 1; setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&flag, sizeof(int)); }
  165. #endif
  166. return (socket_t) new buffered_socket_t(fd);
  167. }
  168. void read(socket_t hsock_i, void* data_i, size_t bytes)
  169. {
  170. #if BUFFERING
  171. char* data = (char*)data_i;
  172. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  173. while (bytes) {
  174. if (hsock->istart == hsock->iend) {
  175. ssize_t n = ::recv(hsock->fd,hsock->ibuf,int(hsock->isize),MSG_NOSIGNAL);
  176. if (n == 0) throw Disconnect();
  177. else if (n < 0) THROW_RUNTIME_ERROR("error reading from socket");
  178. hsock->istart = 0;
  179. hsock->iend = n;
  180. }
  181. size_t bsize = hsock->iend-hsock->istart;
  182. if (bytes < bsize) bsize = bytes;
  183. memcpy(data,hsock->ibuf+hsock->istart,bsize);
  184. data += bsize;
  185. hsock->istart += bsize;
  186. bytes -= bsize;
  187. }
  188. #else
  189. char* data = (char*) data_i;
  190. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  191. while (bytes) {
  192. ssize_t n = ::read(hsock->fd,data,bytes);
  193. if (n == 0) throw Disconnect();
  194. else if (n < 0) THROW_RUNTIME_ERROR("error reading from socket");
  195. data+=n;
  196. bytes-=n;
  197. }
  198. #endif
  199. }
  200. void write(socket_t hsock_i, const void* data_i, size_t bytes)
  201. {
  202. #if BUFFERING
  203. const char* data = (const char*) data_i;
  204. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  205. while (bytes) {
  206. if (hsock->oend == hsock->osize) flush(hsock_i);
  207. size_t bsize = hsock->osize-hsock->oend;
  208. if (bytes < bsize) bsize = bytes;
  209. memcpy(hsock->obuf+hsock->oend,data,bsize);
  210. data += bsize;
  211. hsock->oend += bsize;
  212. bytes -= bsize;
  213. }
  214. #else
  215. const char* data = (const char*) data_i;
  216. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  217. while (bytes) {
  218. ssize_t n = ::write(hsock->fd,data,bytes);
  219. if (n < 0) THROW_RUNTIME_ERROR("error writing to socket");
  220. data+=n;
  221. bytes-=n;
  222. }
  223. #endif
  224. }
  225. void flush(socket_t hsock_i)
  226. {
  227. #if BUFFERING
  228. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  229. char* data = hsock->obuf;
  230. size_t bytes = hsock->oend;
  231. while (bytes > 0) {
  232. ssize_t n = ::send(hsock->fd,data,(int)bytes,MSG_NOSIGNAL);
  233. if (n < 0) THROW_RUNTIME_ERROR("error writing to socket");
  234. bytes -= n;
  235. data += n;
  236. }
  237. hsock->oend = 0;
  238. #endif
  239. }
  240. void close(socket_t hsock_i) {
  241. buffered_socket_t* hsock = (buffered_socket_t*) hsock_i;
  242. ::shutdown(hsock->fd,SHUT_RDWR);
  243. closesocket(hsock->fd);
  244. delete hsock;
  245. }
  246. }
  247. }
  248. ////////////////////////////////////////////////////////////////////////////////
  249. /// All Platforms
  250. ////////////////////////////////////////////////////////////////////////////////
  251. namespace embree
  252. {
  253. namespace network
  254. {
  255. bool read_bool(socket_t socket)
  256. {
  257. bool value = 0;
  258. read(socket,&value,sizeof(bool));
  259. return value;
  260. }
  261. char read_char(socket_t socket)
  262. {
  263. char value = 0;
  264. read(socket,&value,sizeof(char));
  265. return value;
  266. }
  267. int read_int(socket_t socket)
  268. {
  269. int value = 0;
  270. read(socket,&value,sizeof(int));
  271. return value;
  272. }
  273. float read_float(socket_t socket)
  274. {
  275. float value = 0.0f;
  276. read(socket,&value,sizeof(float));
  277. return value;
  278. }
  279. std::string read_string(socket_t socket)
  280. {
  281. int bytes = read_int(socket);
  282. char* str = new char[bytes+1];
  283. read(socket,str,bytes);
  284. str[bytes] = 0x00;
  285. std::string s(str);
  286. delete[] str;
  287. return s;
  288. }
  289. void write(socket_t socket, bool value) {
  290. write(socket,&value,sizeof(bool));
  291. }
  292. void write(socket_t socket, char value) {
  293. write(socket,&value,sizeof(char));
  294. }
  295. void write(socket_t socket, int value) {
  296. write(socket,&value,sizeof(int));
  297. }
  298. void write(socket_t socket, float value) {
  299. write(socket,&value,sizeof(float));
  300. }
  301. void write(socket_t socket, const std::string& str) {
  302. write(socket,(int)str.size());
  303. write(socket,str.c_str(),str.size());
  304. }
  305. }
  306. }