PageRenderTime 56ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/of_v0.9.0_vs_release/addons/ofxNetwork/src/ofxUDPManager.cpp

https://gitlab.com/stillwalker1234/example-code
C++ | 559 lines | 368 code | 95 blank | 96 comment | 82 complexity | fb60fa8e1def6720908651299214848a MD5 | raw file
  1. #define _CRT_SECURE_NO_DEPRECATE
  2. #include "ofxUDPManager.h"
  3. #include "ofxNetworkUtils.h"
  4. //--------------------------------------------------------------------------------
  5. bool ofxUDPManager::m_bWinsockInit= false;
  6. //--------------------------------------------------------------------------------
  7. ofxUDPManager::ofxUDPManager()
  8. {
  9. // was winsock initialized?
  10. #ifdef TARGET_WIN32
  11. if (!m_bWinsockInit) {
  12. unsigned short vr;
  13. WSADATA wsaData;
  14. vr= MAKEWORD(2, 2);
  15. WSAStartup(vr, &wsaData);
  16. m_bWinsockInit= true;
  17. }
  18. #endif
  19. m_hSocket= INVALID_SOCKET;
  20. m_dwTimeoutReceive= OF_UDP_DEFAULT_TIMEOUT;
  21. canGetRemoteAddress = false;
  22. nonBlocking = true;
  23. };
  24. //--------------------------------------------------------------------------------
  25. /// Closes an open socket.
  26. /// NOTE: A closed socket cannot be reused again without a call to "Create()".
  27. bool ofxUDPManager::Close()
  28. {
  29. if (m_hSocket == INVALID_SOCKET)
  30. return(false);
  31. #ifdef TARGET_WIN32
  32. if(closesocket(m_hSocket) == SOCKET_ERROR)
  33. #else
  34. if(close(m_hSocket) == SOCKET_ERROR)
  35. #endif
  36. {
  37. ofxNetworkCheckError();
  38. return(false);
  39. }
  40. m_hSocket= INVALID_SOCKET;
  41. return(true);
  42. }
  43. //--------------------------------------------------------------------------------
  44. bool ofxUDPManager::Create()
  45. {
  46. if (m_hSocket != INVALID_SOCKET)
  47. return(false);
  48. m_hSocket = socket(AF_INET, SOCK_DGRAM, 0);
  49. if (m_hSocket != INVALID_SOCKET)
  50. {
  51. int unused = true;
  52. setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&unused, sizeof(unused));
  53. #ifdef __APPLE__ // MacOS/X requires an additional call
  54. setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEPORT, (char*)&unused, sizeof(unused));
  55. #endif
  56. }
  57. bool ret = m_hSocket != INVALID_SOCKET;
  58. if(!ret) ofxNetworkCheckError();
  59. return ret;
  60. }
  61. //--------------------------------------------------------------------------------
  62. ///Theo added - Choose to set nonBLocking - default mode is to block
  63. bool ofxUDPManager::SetNonBlocking(bool useNonBlocking)
  64. {
  65. nonBlocking = useNonBlocking;
  66. #ifdef TARGET_WIN32
  67. unsigned long arg = nonBlocking;
  68. int retVal = ioctlsocket(m_hSocket,FIONBIO,&arg);
  69. #else
  70. int arg = nonBlocking;
  71. int retVal = ioctl(m_hSocket,FIONBIO,&arg);
  72. #endif
  73. bool ret=(retVal >= 0);
  74. if(!ret) ofxNetworkCheckError();
  75. return ret;
  76. }
  77. //--------------------------------------------------------------------------------
  78. bool ofxUDPManager::Bind(unsigned short usPort)
  79. {
  80. saServer.sin_family = AF_INET;
  81. saServer.sin_addr.s_addr = INADDR_ANY;
  82. //Port MUST be in Network Byte Order
  83. saServer.sin_port = htons(usPort);
  84. int ret = ::bind(m_hSocket,(struct sockaddr*)&saServer,sizeof(struct sockaddr));
  85. if(ret == SOCKET_ERROR) ofxNetworkCheckError();
  86. return (ret == 0);
  87. }
  88. //--------------------------------------------------------------------------------
  89. bool ofxUDPManager::BindMcast(char *pMcast, unsigned short usPort)
  90. {
  91. // bind to port
  92. if (!Bind(usPort))
  93. {
  94. ofLogWarning("ofxUDPManager") << "BindMcast(): couldn't bind to port " << usPort;
  95. return false;
  96. }
  97. // join the multicast group
  98. struct ip_mreq mreq;
  99. mreq.imr_multiaddr.s_addr = inet_addr(pMcast);
  100. mreq.imr_interface.s_addr = INADDR_ANY;
  101. if (setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR*) &mreq, sizeof (mreq)) == SOCKET_ERROR)
  102. {
  103. ofxNetworkCheckError();
  104. return false;
  105. }
  106. // multicast bind successful
  107. return true;
  108. }
  109. //--------------------------------------------------------------------------------
  110. bool ofxUDPManager::Connect(const char *pHost, unsigned short usPort)
  111. {
  112. // sockaddr_in addr_in= {0};
  113. memset(&saClient, 0, sizeof(sockaddr_in));
  114. struct hostent *he;
  115. if (m_hSocket == INVALID_SOCKET) return(false);
  116. if ((he = gethostbyname(pHost)) == NULL)
  117. return(false);
  118. saClient.sin_family= AF_INET; // host byte order
  119. saClient.sin_port = htons(usPort); // short, network byte order
  120. // saClient.sin_addr = *((struct g_addr *)he->h_addr_list);
  121. //ofLogNotice("ofxUDPManager") << "Connect(): connected to " << inet_addr( pHost );
  122. //saClient.sin_addr.s_addr= inet_addr( pHost );
  123. //saClient.sin_addr = *((struct in_addr *)he->h_addr);
  124. memcpy((char *) &saClient.sin_addr.s_addr,
  125. he->h_addr_list[0], he->h_length);
  126. memset(&(saClient.sin_zero), '\0', 8); // zero the rest of the struct
  127. return true;
  128. }
  129. //--------------------------------------------------------------------------------
  130. bool ofxUDPManager::ConnectMcast(char* pMcast, unsigned short usPort)
  131. {
  132. // associate the source socket's address with the socket
  133. if (!Bind(usPort))
  134. {
  135. #ifdef _DEBUG
  136. ofLogError("ofxUDPManager") << "ConnectMcast(): couldn't bind to " << usPort;
  137. ofxNetworkCheckError();
  138. #endif
  139. return false;
  140. }
  141. // set ttl to default
  142. if (!SetTTL(1))
  143. {
  144. #ifdef _DEBUG
  145. ofLogWarning("ofxUDPManager") << "ConnectMcast(): couldn't set TTL; continuing anyway";
  146. ofxNetworkCheckError();
  147. #endif
  148. }
  149. if (!Connect(pMcast, usPort))
  150. {
  151. #ifdef _DEBUG
  152. ofLogError("ofxUDPManager") << " ConnectMcast(): couldn't connect to socket";
  153. ofxNetworkCheckError();
  154. #endif
  155. return false;
  156. }
  157. // multicast connect successful
  158. return true;
  159. }
  160. //--------------------------------------------------------------------------------
  161. /// Return values:
  162. /// SOCKET_TIMEOUT indicates timeout
  163. /// SOCKET_ERROR in case of a problem.
  164. int ofxUDPManager::Send(const char* pBuff, const int iSize)
  165. {
  166. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  167. /*if (m_dwTimeoutSend != NO_TIMEOUT)
  168. {
  169. fd_set fd;
  170. FD_ZERO(&fd);
  171. FD_SET(m_hSocket, &fd);
  172. timeval tv= {m_dwTimeoutSend, 0};
  173. if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
  174. {
  175. return(SOCKET_TIMEOUT);
  176. }
  177. }*/
  178. int ret = sendto(m_hSocket, (char*)pBuff, iSize, 0, (sockaddr *)&saClient, sizeof(sockaddr));
  179. if(ret==-1) ofxNetworkCheckError();
  180. return ret;
  181. // return(send(m_hSocket, pBuff, iSize, 0));
  182. }
  183. //--------------------------------------------------------------------------------
  184. /// Return values:
  185. /// SOCKET_TIMEOUT indicates timeout
  186. /// SOCKET_ERROR in case of a problem.
  187. int ofxUDPManager::SendAll(const char* pBuff, const int iSize)
  188. {
  189. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  190. if (m_dwTimeoutSend != NO_TIMEOUT)
  191. {
  192. fd_set fd;
  193. FD_ZERO(&fd);
  194. FD_SET(m_hSocket, &fd);
  195. timeval tv= {(time_t)m_dwTimeoutSend, 0};
  196. if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
  197. {
  198. ofxNetworkCheckError();
  199. return(SOCKET_TIMEOUT);
  200. }
  201. }
  202. int total= 0;
  203. int bytesleft = iSize;
  204. int n=0;
  205. while (total < iSize)
  206. {
  207. n = sendto(m_hSocket, (char*)pBuff, iSize, 0, (sockaddr *)&saClient, sizeof(sockaddr));
  208. if (n == -1)
  209. {
  210. ofxNetworkCheckError();
  211. break;
  212. }
  213. total += n;
  214. bytesleft -=n;
  215. }
  216. return n==-1?SOCKET_ERROR:total;
  217. }
  218. //--------------------------------------------------------------------------------
  219. // returns number of bytes wiating or SOCKET_ERROR if error
  220. int ofxUDPManager::PeekReceive()
  221. {
  222. if (m_hSocket == INVALID_SOCKET){
  223. ofLogError("INVALID_SOCKET");
  224. return SOCKET_ERROR;
  225. }
  226. // we can use MSG_PEEK, but we still need a large buffer (udp protocol max is 64kb even if max for this socket is less)
  227. // don't want a 64kb stack item here, so instead read how much can be read (note: not queue size, there may be more data-more packets)
  228. #ifdef TARGET_WIN32
  229. unsigned long size = 0;
  230. int retVal = ioctlsocket(m_hSocket,FIONREAD,&size);
  231. #else
  232. int size = 0;
  233. int retVal = ioctl(m_hSocket,FIONREAD,&size);
  234. #endif
  235. // error
  236. if ( retVal != 0 )
  237. {
  238. //assert( Result == SOCKET_ERROR );
  239. // report error
  240. ofxNetworkCheckError();
  241. return SOCKET_ERROR;
  242. }
  243. return size;
  244. }
  245. //--------------------------------------------------------------------------------
  246. /// Return values:
  247. /// SOCKET_TIMEOUT indicates timeout
  248. /// SOCKET_ERROR in case of a problem.
  249. int ofxUDPManager::Receive(char* pBuff, const int iSize)
  250. {
  251. if (m_hSocket == INVALID_SOCKET){
  252. ofLogError("ofxUDPManager") << "INVALID_SOCKET";
  253. return(SOCKET_ERROR);
  254. }
  255. /*if (m_dwTimeoutSend != NO_TIMEOUT)
  256. {
  257. fd_set fd;
  258. FD_ZERO(&fd);
  259. FD_SET(m_hSocket, &fd);
  260. timeval tv= {m_dwTimeoutSend, 0};
  261. if(select(m_hSocket+1,&fd,NULL,NULL,&tv)== 0)
  262. {
  263. return(SOCKET_TIMEOUT);
  264. }
  265. }*/
  266. #ifndef TARGET_WIN32
  267. socklen_t nLen= sizeof(sockaddr);
  268. #else
  269. int nLen= sizeof(sockaddr);
  270. #endif
  271. int ret=0;
  272. memset(pBuff, 0, iSize);
  273. ret= recvfrom(m_hSocket, pBuff, iSize, 0, (sockaddr *)&saClient, &nLen);
  274. if (ret > 0)
  275. {
  276. //ofLogNotice("ofxUDPManager") << "received from: " << inet_ntoa((in_addr)saClient.sin_addr);
  277. canGetRemoteAddress= true;
  278. }
  279. else
  280. {
  281. canGetRemoteAddress = false;
  282. // if the network error is WOULDBLOCK, then return 0 instead of SOCKET_ERROR as it's not really a problem, just no data.
  283. int SocketError = ofxNetworkCheckError();
  284. if ( SocketError == OFXNETWORK_ERROR(WOULDBLOCK) )
  285. return 0;
  286. }
  287. return ret;
  288. // return(recvfrom(m_hSocket, pBuff, iSize, 0));
  289. }
  290. void ofxUDPManager::SetTimeoutSend(int timeoutInSeconds)
  291. {
  292. m_dwTimeoutSend= timeoutInSeconds;
  293. }
  294. void ofxUDPManager::SetTimeoutReceive(int timeoutInSeconds)
  295. {
  296. m_dwTimeoutReceive= timeoutInSeconds;
  297. }
  298. int ofxUDPManager::GetTimeoutSend()
  299. {
  300. return m_dwTimeoutSend;
  301. }
  302. int ofxUDPManager::GetTimeoutReceive()
  303. {
  304. return m_dwTimeoutReceive;
  305. }
  306. //--------------------------------------------------------------------------------
  307. bool ofxUDPManager::GetRemoteAddr(string& address,int& port) const
  308. {
  309. if (m_hSocket == INVALID_SOCKET) return(false);
  310. if ( canGetRemoteAddress == false) return (false);
  311. // get the static-winsock-allocated address-conversion string and make a copy of it
  312. const char* AddressStr = inet_ntoa((in_addr)saClient.sin_addr);
  313. address = AddressStr;
  314. // get the port
  315. port = ntohs(saClient.sin_port);
  316. return true;
  317. }
  318. //--------------------------------------------------------------------------------
  319. bool ofxUDPManager::GetListenAddr(string& address,int& port) const
  320. {
  321. if (m_hSocket == INVALID_SOCKET) return(false);
  322. // get the static-winsock-allocated address-conversion string and make a copy of it
  323. const char* AddressStr = inet_ntoa((in_addr)saServer.sin_addr);
  324. address = AddressStr;
  325. // get the port
  326. port = ntohs(saServer.sin_port);
  327. return true;
  328. }
  329. //--------------------------------------------------------------------------------
  330. int ofxUDPManager::GetMaxMsgSize()
  331. {
  332. if (m_hSocket == INVALID_SOCKET) return(false);
  333. int sizeBuffer=0;
  334. #ifndef TARGET_WIN32
  335. socklen_t size = sizeof(int);
  336. #else
  337. int size = sizeof(int);
  338. #endif
  339. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*)&sizeBuffer, &size);
  340. if(ret==-1) ofxNetworkCheckError();
  341. return sizeBuffer;
  342. }
  343. //--------------------------------------------------------------------------------
  344. int ofxUDPManager::GetReceiveBufferSize()
  345. {
  346. if (m_hSocket == INVALID_SOCKET) return(false);
  347. int sizeBuffer=0;
  348. #ifndef TARGET_WIN32
  349. socklen_t size = sizeof(int);
  350. #else
  351. int size = sizeof(int);
  352. #endif
  353. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeBuffer, &size);
  354. if(ret==-1) ofxNetworkCheckError();
  355. return sizeBuffer;
  356. }
  357. //--------------------------------------------------------------------------------
  358. bool ofxUDPManager::SetReceiveBufferSize(int sizeInByte)
  359. {
  360. if (m_hSocket == INVALID_SOCKET) return(false);
  361. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  362. return true;
  363. }else{
  364. ofxNetworkCheckError();
  365. return false;
  366. }
  367. }
  368. //--------------------------------------------------------------------------------
  369. int ofxUDPManager::GetSendBufferSize()
  370. {
  371. if (m_hSocket == INVALID_SOCKET) return(false);
  372. int sizeBuffer=0;
  373. #ifndef TARGET_WIN32
  374. socklen_t size = sizeof(int);
  375. #else
  376. int size = sizeof(int);
  377. #endif
  378. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeBuffer, &size);
  379. if(ret==-1) ofxNetworkCheckError();
  380. return sizeBuffer;
  381. }
  382. //--------------------------------------------------------------------------------
  383. bool ofxUDPManager::SetSendBufferSize(int sizeInByte)
  384. {
  385. if (m_hSocket == INVALID_SOCKET) return(false);
  386. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  387. return true;
  388. }else{
  389. ofxNetworkCheckError();
  390. return false;
  391. }
  392. }
  393. //--------------------------------------------------------------------------------
  394. bool ofxUDPManager::SetReuseAddress(bool allowReuse)
  395. {
  396. if (m_hSocket == INVALID_SOCKET) return(false);
  397. int on;
  398. if (allowReuse) on=1;
  399. else on=0;
  400. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == 0){
  401. return true;
  402. }else{
  403. ofxNetworkCheckError();
  404. return false;
  405. }
  406. }
  407. //--------------------------------------------------------------------------------
  408. bool ofxUDPManager::SetEnableBroadcast(bool enableBroadcast)
  409. {
  410. int on;
  411. if (enableBroadcast) on=1;
  412. else on=0;
  413. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)) == 0){
  414. return true;
  415. }else{
  416. ofxNetworkCheckError();
  417. return false;
  418. }
  419. }
  420. //--------------------------------------------------------------------------------
  421. int ofxUDPManager::GetTTL()
  422. {
  423. if (m_hSocket == INVALID_SOCKET) return(false);
  424. int nTTL;
  425. #ifndef TARGET_WIN32
  426. socklen_t nSize = sizeof(int);
  427. #else
  428. int nSize = sizeof(int);
  429. #endif
  430. if (getsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *) &nTTL, &nSize) == SOCKET_ERROR)
  431. {
  432. #ifdef _DEBUG
  433. ofLogError("ofxUDPManager") << "GetTTL(): getsockopt failed";
  434. #endif
  435. ofxNetworkCheckError();
  436. return -1;
  437. }
  438. return nTTL;
  439. }
  440. //--------------------------------------------------------------------------------
  441. bool ofxUDPManager::SetTTL(int nTTL)
  442. {
  443. if (m_hSocket == INVALID_SOCKET) return(false);
  444. // Set the Time-to-Live of the multicast.
  445. if (setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *)&nTTL, sizeof (int)) == SOCKET_ERROR)
  446. {
  447. #ifdef _DEBUG
  448. ofLogError("ofxUDPManager") << "SetTTL(): setsockopt failed";
  449. #endif
  450. ofxNetworkCheckError();
  451. return false;
  452. }
  453. return true;
  454. }
  455. /*
  456. //--------------------------------------------------------------------------------
  457. bool ofxUDPManager::GetInetAddr(LPINETADDR pInetAddr)
  458. {
  459. if (m_hSocket == INVALID_SOCKET) return(false);
  460. int iSize= sizeof(sockaddr);
  461. return(getsockname(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  462. }
  463. */