PageRenderTime 61ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/addons/ofxNetwork/src/ofxUDPManager.cpp

https://github.com/brolin/openFrameworks
C++ | 500 lines | 332 code | 84 blank | 84 comment | 73 complexity | 8a4fef4fc0bd5a2fb0a6529c09c95bbc 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. m_iListenPort= -1;
  22. canGetRemoteAddress = false;
  23. nonBlocking = true;
  24. };
  25. //--------------------------------------------------------------------------------
  26. /// Closes an open socket.
  27. /// NOTE: A closed socket cannot be reused again without a call to "Create()".
  28. bool ofxUDPManager::Close()
  29. {
  30. if (m_hSocket == INVALID_SOCKET)
  31. return(false);
  32. #ifdef TARGET_WIN32
  33. if(closesocket(m_hSocket) == SOCKET_ERROR)
  34. #else
  35. if(close(m_hSocket) == SOCKET_ERROR)
  36. #endif
  37. {
  38. ofxNetworkCheckError();
  39. return(false);
  40. }
  41. m_hSocket= INVALID_SOCKET;
  42. return(true);
  43. }
  44. //--------------------------------------------------------------------------------
  45. bool ofxUDPManager::Create()
  46. {
  47. if (m_hSocket != INVALID_SOCKET)
  48. return(false);
  49. m_hSocket = socket(AF_INET, SOCK_DGRAM, 0);
  50. if (m_hSocket != INVALID_SOCKET)
  51. {
  52. int unused = true;
  53. setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&unused, sizeof(unused));
  54. }
  55. bool ret = m_hSocket != INVALID_SOCKET;
  56. if(!ret) ofxNetworkCheckError();
  57. return ret;
  58. }
  59. //--------------------------------------------------------------------------------
  60. ///Theo added - Choose to set nonBLocking - default mode is to block
  61. bool ofxUDPManager::SetNonBlocking(bool useNonBlocking)
  62. {
  63. nonBlocking = useNonBlocking;
  64. #ifdef TARGET_WIN32
  65. unsigned long arg = nonBlocking;
  66. int retVal = ioctlsocket(m_hSocket,FIONBIO,&arg);
  67. #else
  68. int arg = nonBlocking;
  69. int retVal = ioctl(m_hSocket,FIONBIO,&arg);
  70. #endif
  71. bool ret=(retVal >= 0);
  72. if(!ret) ofxNetworkCheckError();
  73. return ret;
  74. }
  75. //--------------------------------------------------------------------------------
  76. bool ofxUDPManager::Bind(unsigned short usPort)
  77. {
  78. saServer.sin_family = AF_INET;
  79. saServer.sin_addr.s_addr = INADDR_ANY;
  80. //Port MUST be in Network Byte Order
  81. saServer.sin_port = htons(usPort);
  82. int ret = bind(m_hSocket,(struct sockaddr*)&saServer,sizeof(struct sockaddr));
  83. if(ret==-1) ofxNetworkCheckError();
  84. return (ret == 0);
  85. }
  86. //--------------------------------------------------------------------------------
  87. bool ofxUDPManager::BindMcast(char *pMcast, unsigned short usPort)
  88. {
  89. // bind to port
  90. if (!Bind(usPort))
  91. {
  92. printf("can't bind to port \n");
  93. return false;
  94. }
  95. // join the multicast group
  96. struct ip_mreq mreq;
  97. mreq.imr_multiaddr.s_addr = inet_addr(pMcast);
  98. mreq.imr_interface.s_addr = INADDR_ANY;
  99. if (setsockopt(m_hSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR*) &mreq, sizeof (mreq)) == SOCKET_ERROR)
  100. {
  101. ofxNetworkCheckError();
  102. return false;
  103. }
  104. printf("here ? \n");
  105. // multicast bind successful
  106. return true;
  107. }
  108. //--------------------------------------------------------------------------------
  109. bool ofxUDPManager::Connect(const char *pHost, unsigned short usPort)
  110. {
  111. // sockaddr_in addr_in= {0};
  112. memset(&saClient, 0, sizeof(sockaddr_in));
  113. struct hostent *he;
  114. if (m_hSocket == INVALID_SOCKET) return(false);
  115. if ((he = gethostbyname(pHost)) == NULL)
  116. return(false);
  117. saClient.sin_family= AF_INET; // host byte order
  118. saClient.sin_port = htons(usPort); // short, network byte order
  119. // saClient.sin_addr = *((struct g_addr *)he->h_addr_list);
  120. //cout << inet_addr( pHost ) << endl;
  121. //saClient.sin_addr.s_addr= inet_addr( pHost );
  122. //saClient.sin_addr = *((struct in_addr *)he->h_addr);
  123. memcpy((char *) &saClient.sin_addr.s_addr,
  124. he->h_addr_list[0], he->h_length);
  125. memset(&(saClient.sin_zero), '\0', 8); // zero the rest of the struct
  126. return true;
  127. }
  128. //--------------------------------------------------------------------------------
  129. bool ofxUDPManager::ConnectMcast(char* pMcast, unsigned short usPort)
  130. {
  131. // associate the source socket's address with the socket
  132. if (!Bind(usPort))
  133. {
  134. #ifdef _DEBUG
  135. printf("Binding socket failed! Error: %d", WSAGetLastError());
  136. #endif
  137. return false;
  138. }
  139. // set ttl to default
  140. if (!SetTTL(1))
  141. {
  142. #ifdef _DEBUG
  143. printf("SetTTL failed. Continue anyway. Error: %d", WSAGetLastError());
  144. #endif
  145. }
  146. if (!Connect(pMcast, usPort))
  147. {
  148. #ifdef _DEBUG
  149. printf("Connecting socket failed! Error: %d", WSAGetLastError ());
  150. #endif
  151. return false;
  152. }
  153. // multicast connect successful
  154. return true;
  155. }
  156. //--------------------------------------------------------------------------------
  157. /// Return values:
  158. /// SOCKET_TIMEOUT indicates timeout
  159. /// SOCKET_ERROR in case of a problem.
  160. int ofxUDPManager::Send(const char* pBuff, const int iSize)
  161. {
  162. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  163. /*if (m_dwTimeoutSend != NO_TIMEOUT)
  164. {
  165. fd_set fd;
  166. FD_ZERO(&fd);
  167. FD_SET(m_hSocket, &fd);
  168. timeval tv= {m_dwTimeoutSend, 0};
  169. if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
  170. {
  171. return(SOCKET_TIMEOUT);
  172. }
  173. }*/
  174. int ret = sendto(m_hSocket, (char*)pBuff, iSize, 0, (sockaddr *)&saClient, sizeof(sockaddr));
  175. if(ret==-1) ofxNetworkCheckError();
  176. return ret;
  177. // return(send(m_hSocket, pBuff, iSize, 0));
  178. }
  179. //--------------------------------------------------------------------------------
  180. /// Return values:
  181. /// SOCKET_TIMEOUT indicates timeout
  182. /// SOCKET_ERROR in case of a problem.
  183. int ofxUDPManager::SendAll(const char* pBuff, const int iSize)
  184. {
  185. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  186. if (m_dwTimeoutSend != NO_TIMEOUT)
  187. {
  188. fd_set fd;
  189. FD_ZERO(&fd);
  190. FD_SET(m_hSocket, &fd);
  191. timeval tv= {m_dwTimeoutSend, 0};
  192. if(select(m_hSocket+1,NULL,&fd,NULL,&tv)== 0)
  193. {
  194. ofxNetworkCheckError();
  195. return(SOCKET_TIMEOUT);
  196. }
  197. }
  198. int total= 0;
  199. int bytesleft = iSize;
  200. int n=0;
  201. while (total < iSize)
  202. {
  203. n = sendto(m_hSocket, (char*)pBuff, iSize, 0, (sockaddr *)&saClient, sizeof(sockaddr));
  204. if (n == -1)
  205. {
  206. ofxNetworkCheckError();
  207. break;
  208. }
  209. total += n;
  210. bytesleft -=n;
  211. }
  212. return n==-1?SOCKET_ERROR:total;
  213. }
  214. //--------------------------------------------------------------------------------
  215. /// Return values:
  216. /// SOCKET_TIMEOUT indicates timeout
  217. /// SOCKET_ERROR in case of a problem.
  218. int ofxUDPManager::Receive(char* pBuff, const int iSize)
  219. {
  220. if (m_hSocket == INVALID_SOCKET){
  221. printf("INVALID_SOCKET");
  222. return(SOCKET_ERROR);
  223. }
  224. /*if (m_dwTimeoutSend != NO_TIMEOUT)
  225. {
  226. fd_set fd;
  227. FD_ZERO(&fd);
  228. FD_SET(m_hSocket, &fd);
  229. timeval tv= {m_dwTimeoutSend, 0};
  230. if(select(m_hSocket+1,&fd,NULL,NULL,&tv)== 0)
  231. {
  232. return(SOCKET_TIMEOUT);
  233. }
  234. }*/
  235. #ifndef TARGET_WIN32
  236. socklen_t nLen= sizeof(sockaddr);
  237. #else
  238. int nLen= sizeof(sockaddr);
  239. #endif
  240. int ret=0;
  241. memset(pBuff, 0, iSize);
  242. ret= recvfrom(m_hSocket, pBuff, iSize, 0, (sockaddr *)&saClient, &nLen);
  243. if (ret > 0)
  244. {
  245. //printf("\nreceived from: %s\n", inet_ntoa((in_addr)saClient.sin_addr));
  246. canGetRemoteAddress= true;
  247. }
  248. else
  249. {
  250. ofxNetworkCheckError();
  251. //printf("\nreceived from: ????\n");
  252. canGetRemoteAddress= false;
  253. }
  254. return ret;
  255. // return(recvfrom(m_hSocket, pBuff, iSize, 0));
  256. }
  257. void ofxUDPManager::SetTimeoutSend(int timeoutInSeconds)
  258. {
  259. m_dwTimeoutSend= timeoutInSeconds;
  260. }
  261. void ofxUDPManager::SetTimeoutReceive(int timeoutInSeconds)
  262. {
  263. m_dwTimeoutReceive= timeoutInSeconds;
  264. }
  265. int ofxUDPManager::GetTimeoutSend()
  266. {
  267. return m_dwTimeoutSend;
  268. }
  269. int ofxUDPManager::GetTimeoutReceive()
  270. {
  271. return m_dwTimeoutReceive;
  272. }
  273. //--------------------------------------------------------------------------------
  274. bool ofxUDPManager::GetRemoteAddr(char* address)
  275. {
  276. if (m_hSocket == INVALID_SOCKET) return(false);
  277. if ( canGetRemoteAddress == false) return (false);
  278. strcpy(address, inet_ntoa((in_addr)saClient.sin_addr));
  279. return true;
  280. }
  281. //--------------------------------------------------------------------------------
  282. int ofxUDPManager::GetMaxMsgSize()
  283. {
  284. if (m_hSocket == INVALID_SOCKET) return(false);
  285. int sizeBuffer=0;
  286. #ifndef TARGET_WIN32
  287. socklen_t size = sizeof(int);
  288. #else
  289. int size = sizeof(int);
  290. #endif
  291. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_MAX_MSG_SIZE, (char*)&sizeBuffer, &size);
  292. if(ret==-1) ofxNetworkCheckError();
  293. return sizeBuffer;
  294. }
  295. //--------------------------------------------------------------------------------
  296. int ofxUDPManager::GetReceiveBufferSize()
  297. {
  298. if (m_hSocket == INVALID_SOCKET) return(false);
  299. int sizeBuffer=0;
  300. #ifndef TARGET_WIN32
  301. socklen_t size = sizeof(int);
  302. #else
  303. int size = sizeof(int);
  304. #endif
  305. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeBuffer, &size);
  306. if(ret==-1) ofxNetworkCheckError();
  307. return sizeBuffer;
  308. }
  309. //--------------------------------------------------------------------------------
  310. bool ofxUDPManager::SetReceiveBufferSize(int sizeInByte)
  311. {
  312. if (m_hSocket == INVALID_SOCKET) return(false);
  313. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  314. return true;
  315. }else{
  316. ofxNetworkCheckError();
  317. return false;
  318. }
  319. }
  320. //--------------------------------------------------------------------------------
  321. int ofxUDPManager::GetSendBufferSize()
  322. {
  323. if (m_hSocket == INVALID_SOCKET) return(false);
  324. int sizeBuffer=0;
  325. #ifndef TARGET_WIN32
  326. socklen_t size = sizeof(int);
  327. #else
  328. int size = sizeof(int);
  329. #endif
  330. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeBuffer, &size);
  331. if(ret==-1) ofxNetworkCheckError();
  332. return sizeBuffer;
  333. }
  334. //--------------------------------------------------------------------------------
  335. bool ofxUDPManager::SetSendBufferSize(int sizeInByte)
  336. {
  337. if (m_hSocket == INVALID_SOCKET) return(false);
  338. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  339. return true;
  340. }else{
  341. ofxNetworkCheckError();
  342. return false;
  343. }
  344. }
  345. //--------------------------------------------------------------------------------
  346. bool ofxUDPManager::SetReuseAddress(bool allowReuse)
  347. {
  348. if (m_hSocket == INVALID_SOCKET) return(false);
  349. int on;
  350. if (allowReuse) on=1;
  351. else on=0;
  352. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on)) == 0){
  353. return true;
  354. }else{
  355. ofxNetworkCheckError();
  356. return false;
  357. }
  358. }
  359. //--------------------------------------------------------------------------------
  360. bool ofxUDPManager::SetEnableBroadcast(bool enableBroadcast)
  361. {
  362. int on;
  363. if (enableBroadcast) on=1;
  364. else on=0;
  365. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on)) == 0){
  366. return true;
  367. }else{
  368. ofxNetworkCheckError();
  369. return false;
  370. }
  371. }
  372. //--------------------------------------------------------------------------------
  373. int ofxUDPManager::GetTTL()
  374. {
  375. if (m_hSocket == INVALID_SOCKET) return(false);
  376. int nTTL;
  377. #ifndef TARGET_WIN32
  378. socklen_t nSize = sizeof(int);
  379. #else
  380. int nSize = sizeof(int);
  381. #endif
  382. if (getsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *) &nTTL, &nSize) == SOCKET_ERROR)
  383. {
  384. #ifdef _DEBUG
  385. printf("getsockopt failed! Error: %d", WSAGetLastError());
  386. #endif
  387. ofxNetworkCheckError();
  388. return -1;
  389. }
  390. return nTTL;
  391. }
  392. //--------------------------------------------------------------------------------
  393. bool ofxUDPManager::SetTTL(int nTTL)
  394. {
  395. if (m_hSocket == INVALID_SOCKET) return(false);
  396. // Set the Time-to-Live of the multicast.
  397. if (setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL, (char FAR *)&nTTL, sizeof (int)) == SOCKET_ERROR)
  398. {
  399. #ifdef _DEBUG
  400. printf("setsockopt failed! Error: %d", WSAGetLastError());
  401. #endif
  402. ofxNetworkCheckError();
  403. return false;
  404. }
  405. return true;
  406. }
  407. /*
  408. //--------------------------------------------------------------------------------
  409. bool ofxUDPManager::GetInetAddr(LPINETADDR pInetAddr)
  410. {
  411. if (m_hSocket == INVALID_SOCKET) return(false);
  412. int iSize= sizeof(sockaddr);
  413. return(getsockname(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  414. }
  415. */