PageRenderTime 32ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/of/of_v0.9.3_vs_release/addons/ofxNetwork/src/ofxTCPManager.cpp

https://gitlab.com/cocoroac/walkingartists
C++ | 605 lines | 471 code | 85 blank | 49 comment | 131 complexity | 95541463256a70c3ab8b5db04fc52280 MD5 | raw file
  1. #include "ofxTCPManager.h"
  2. #include <stdio.h>
  3. #include "ofxNetworkUtils.h"
  4. //--------------------------------------------------------------------------------
  5. bool ofxTCPManager::m_bWinsockInit= false;
  6. //--------------------------------------------------------------------------------
  7. ofxTCPManager::ofxTCPManager()
  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. #else
  19. //this disables the other apps from shutting down if the client
  20. //or server disconnects.
  21. signal(SIGPIPE,SIG_IGN);
  22. signal(EPIPE,SIG_IGN);
  23. #endif
  24. nonBlocking = false;
  25. m_hSocket= INVALID_SOCKET;
  26. m_dwTimeoutSend= OF_TCP_DEFAULT_TIMEOUT;
  27. m_dwTimeoutReceive= OF_TCP_DEFAULT_TIMEOUT;
  28. m_dwTimeoutAccept= OF_TCP_DEFAULT_TIMEOUT;
  29. m_dwTimeoutConnect= 5;//OF_TCP_DEFAULT_TIMEOUT;
  30. m_iListenPort= -1;
  31. m_closing = false;
  32. m_iMaxConnections = 100;
  33. };
  34. //--------------------------------------------------------------------------------
  35. /// Closes an open socket.
  36. /// NOTE: A closed socket cannot be reused again without a call to "Create()".
  37. bool ofxTCPManager::Close()
  38. {
  39. if (m_hSocket == INVALID_SOCKET) return(true);
  40. #ifdef TARGET_WIN32
  41. if(closesocket(m_hSocket) == SOCKET_ERROR)
  42. #else
  43. m_closing = true;
  44. shutdown(m_hSocket,SHUT_RDWR);
  45. if(close(m_hSocket) == SOCKET_ERROR)
  46. #endif
  47. {
  48. // if it's reported we're not/no longer a socket, let it fall through and be invalidated
  49. int Error = ofxNetworkCheckError();
  50. if ( Error != OFXNETWORK_ERROR(NOTSOCK) )
  51. {
  52. return(false);
  53. }
  54. }
  55. m_hSocket= INVALID_SOCKET;
  56. #ifdef TARGET_WIN32
  57. //This was commented out in the original
  58. //WSACleanup();
  59. #endif
  60. return(true);
  61. }
  62. //--------------------------------------------------------------------------------
  63. void ofxTCPManager::CleanUp() {
  64. #ifdef TARGET_WIN32
  65. WSACleanup();
  66. #endif
  67. m_bWinsockInit = false;
  68. }
  69. //--------------------------------------------------------------------------------
  70. bool ofxTCPManager::CheckIsConnected(){
  71. #ifdef TARGET_WIN32
  72. fd_set fd;
  73. FD_ZERO(&fd);
  74. FD_SET(m_hSocket, &fd);
  75. timeval tv = { (time_t)0, 1 };
  76. if (select(0, &fd, NULL, NULL, &tv) == 1) {
  77. int so_error;
  78. socklen_t len = sizeof so_error;
  79. getsockopt(m_hSocket, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len);
  80. if (so_error == 0) {
  81. u_long toread;
  82. #ifdef TARGET_WIN32
  83. ioctlsocket(m_hSocket, FIONREAD, &toread);
  84. #else
  85. ioctl(m_hSocket, FIONREAD, &toread);
  86. #endif
  87. if (toread == 0) {
  88. return false;
  89. }
  90. }
  91. }
  92. return true;
  93. #else
  94. bool wasBlocking = nonBlocking;
  95. SetNonBlocking(false);
  96. struct timeval timeout;
  97. timeout.tv_sec = 0;
  98. timeout.tv_usec = 1;
  99. if(setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout))<0){
  100. return true;
  101. }
  102. char buffer;
  103. int ret = recv(m_hSocket, &buffer, 1, MSG_PEEK);
  104. SetNonBlocking(wasBlocking);
  105. timeout.tv_sec = 0;
  106. timeout.tv_usec = 0;
  107. setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
  108. return ret!=0;
  109. #endif
  110. }
  111. //--------------------------------------------------------------------------------
  112. bool ofxTCPManager::Create()
  113. {
  114. if (m_hSocket != INVALID_SOCKET) return(false);
  115. m_closing = false;
  116. m_hSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_IP);
  117. bool ret = (m_hSocket != INVALID_SOCKET);
  118. if(!ret) ofxNetworkCheckError();
  119. return ret;
  120. }
  121. //--------------------------------------------------------------------------------
  122. bool ofxTCPManager::Listen(int iMaxConnections)
  123. {
  124. if (m_hSocket == INVALID_SOCKET) return(false);
  125. m_iMaxConnections = iMaxConnections;
  126. bool ret = (listen(m_hSocket, iMaxConnections)!= SOCKET_ERROR);
  127. if(!ret) ofxNetworkCheckError();
  128. return ret;
  129. }
  130. bool ofxTCPManager::Bind(unsigned short usPort)
  131. {
  132. struct sockaddr_in local;
  133. memset(&local, 0, sizeof(sockaddr_in));
  134. local.sin_family = AF_INET;
  135. local.sin_addr.s_addr = INADDR_ANY;
  136. //Port MUST be in Network Byte Order
  137. local.sin_port = htons(usPort);
  138. if (::bind(m_hSocket,(struct sockaddr*)&local,sizeof(local))){
  139. ofxNetworkCheckError();
  140. return false;
  141. }
  142. return true;
  143. }
  144. //--------------------------------------------------------------------------------
  145. bool ofxTCPManager::Accept(ofxTCPManager& sConnect)
  146. {
  147. sockaddr_in addr;
  148. #ifndef TARGET_WIN32
  149. socklen_t iSize;
  150. #else
  151. int iSize;
  152. #endif
  153. if (m_hSocket == INVALID_SOCKET) return(false);
  154. if (m_dwTimeoutAccept != NO_TIMEOUT) {
  155. fd_set fd;
  156. FD_ZERO(&fd);
  157. FD_SET(m_hSocket, &fd);
  158. timeval tv= {(time_t)m_dwTimeoutAccept, 0};
  159. if(select(0, &fd, NULL, NULL, &tv) == 0) {
  160. ofxNetworkCheckError();
  161. return(false);
  162. }
  163. }
  164. iSize= sizeof(sockaddr_in);
  165. sConnect.m_hSocket = accept(m_hSocket, (sockaddr*)&addr, &iSize);
  166. bool ret = (sConnect.m_hSocket != INVALID_SOCKET);
  167. if(!ret && !m_closing) ofxNetworkCheckError();
  168. return ret;
  169. }
  170. //--------------------------------------------------------------------------------
  171. bool ofxTCPManager::Connect(const char *pAddrStr, unsigned short usPort)
  172. {
  173. sockaddr_in addr_in= {0};
  174. struct hostent *he;
  175. if (m_hSocket == INVALID_SOCKET){
  176. return(false);
  177. }
  178. if ((he = gethostbyname(pAddrStr)) == NULL)
  179. return(false);
  180. addr_in.sin_family= AF_INET; // host byte order
  181. addr_in.sin_port = htons(usPort); // short, network byte order
  182. addr_in.sin_addr = *((struct in_addr *)he->h_addr);
  183. // set to non-blocking before connect
  184. bool wasBlocking = nonBlocking;
  185. if(m_dwTimeoutConnect != NO_TIMEOUT){
  186. SetNonBlocking(true);
  187. }
  188. int ret = connect(m_hSocket, (sockaddr *)&addr_in, sizeof(sockaddr));
  189. int err = 0;
  190. if(ret<0) err = ofxNetworkCheckError();
  191. // set a timeout
  192. if (ret < 0 && (err == OFXNETWORK_ERROR(INPROGRESS) || err == OFXNETWORK_ERROR(WOULDBLOCK)) && m_dwTimeoutConnect != NO_TIMEOUT) {
  193. ret = WaitSend(m_dwTimeoutConnect, 0);
  194. if(ret == 0) {
  195. socklen_t len = sizeof err;
  196. if (getsockopt(m_hSocket, SOL_SOCKET, SO_ERROR, (char*)&err, &len)<0){
  197. ret = SOCKET_ERROR;
  198. }else if(err != 0) {
  199. ret = SOCKET_ERROR;
  200. }
  201. }
  202. }
  203. if(m_dwTimeoutConnect != NO_TIMEOUT){
  204. SetNonBlocking(wasBlocking);
  205. }
  206. return ret>=0;
  207. }
  208. //--------------------------------------------------------------------------------
  209. int ofxTCPManager::WaitReceive(time_t timeoutSeconds, time_t timeoutMicros){
  210. if (m_hSocket == INVALID_SOCKET) return SOCKET_ERROR;
  211. fd_set fd;
  212. FD_ZERO(&fd);
  213. FD_SET(m_hSocket, &fd);
  214. timeval tv;
  215. tv.tv_sec = timeoutSeconds;
  216. tv.tv_usec = timeoutMicros;
  217. auto ret = select(m_hSocket+1,&fd,NULL,NULL,&tv);
  218. if(ret == 0){
  219. return SOCKET_TIMEOUT;
  220. }else if(ret < 0){
  221. return SOCKET_ERROR;
  222. }else{
  223. return 0;
  224. }
  225. }
  226. //--------------------------------------------------------------------------------
  227. int ofxTCPManager::WaitSend(time_t timeoutSeconds, time_t timeoutMicros){
  228. if (m_hSocket == INVALID_SOCKET) return SOCKET_ERROR;
  229. fd_set fd;
  230. FD_ZERO(&fd);
  231. FD_SET(m_hSocket, &fd);
  232. timeval tv;
  233. tv.tv_sec = timeoutSeconds;
  234. tv.tv_usec = timeoutMicros;
  235. auto ret = select(m_hSocket+1,NULL,&fd,NULL,&tv);
  236. if(ret == 0){
  237. return SOCKET_TIMEOUT;
  238. }else if(ret < 0){
  239. return SOCKET_ERROR;
  240. }else{
  241. return 0;
  242. }
  243. }
  244. //--------------------------------------------------------------------------------
  245. bool ofxTCPManager::SetNonBlocking(bool useNonBlocking)
  246. {
  247. if(useNonBlocking==nonBlocking){
  248. return true;
  249. }
  250. auto prevNonBlocking = nonBlocking;
  251. nonBlocking = useNonBlocking;
  252. #ifdef TARGET_WIN32
  253. unsigned long arg = nonBlocking;
  254. int retVal = ioctlsocket(m_hSocket,FIONBIO,&arg);
  255. #else
  256. int flags = fcntl(m_hSocket, F_GETFL, 0);
  257. int retVal;
  258. if(useNonBlocking){
  259. retVal = fcntl(m_hSocket, F_SETFL, flags | O_NONBLOCK);
  260. }else{
  261. retVal = fcntl(m_hSocket, F_SETFL, flags & ~O_NONBLOCK);
  262. }
  263. #endif
  264. bool ret = (retVal >= 0);
  265. if(!ret){
  266. ofxNetworkCheckError();
  267. nonBlocking = prevNonBlocking;
  268. }
  269. return ret;
  270. }
  271. bool ofxTCPManager::IsNonBlocking(){
  272. return nonBlocking;
  273. }
  274. //--------------------------------------------------------------------------------
  275. int ofxTCPManager::Write(const char* pBuff, const int iSize)
  276. {
  277. int iBytesSent= 0;
  278. int iBytesTemp;
  279. const char* pTemp= pBuff;
  280. do {
  281. iBytesTemp= Send(pTemp, iSize - iBytesSent);
  282. // error occured?
  283. if (iBytesTemp == SOCKET_ERROR) return(SOCKET_ERROR);
  284. if (iBytesTemp == SOCKET_TIMEOUT) return(SOCKET_TIMEOUT);
  285. iBytesSent+= iBytesTemp;
  286. pTemp+= iBytesTemp;
  287. } while(iBytesSent < iSize);
  288. return(iBytesSent);
  289. }
  290. //--------------------------------------------------------------------------------
  291. /// Return values:
  292. /// SOCKET_TIMEOUT indicates timeout
  293. /// SOCKET_ERROR in case of a problem.
  294. int ofxTCPManager::Send(const char* pBuff, const int iSize)
  295. {
  296. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  297. if (m_dwTimeoutSend != NO_TIMEOUT){
  298. auto ret = WaitSend(m_dwTimeoutSend,0);
  299. if(ret!=0){
  300. return ret;
  301. }
  302. }
  303. return send(m_hSocket, pBuff, iSize, 0);
  304. }
  305. //--------------------------------------------------------------------------------
  306. /// Return values:
  307. /// SOCKET_TIMEOUT indicates timeout
  308. /// SOCKET_ERROR in case of a problem.
  309. int ofxTCPManager::SendAll(const char* pBuff, const int iSize)
  310. {
  311. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  312. auto timestamp = ofGetElapsedTimeMicros();
  313. auto timeleftSecs = m_dwTimeoutSend;
  314. auto timeleftMicros = 0;
  315. int total= 0;
  316. int bytesleft = iSize;
  317. int ret=-1;
  318. while (total < iSize) {
  319. if (m_dwTimeoutSend != NO_TIMEOUT){
  320. auto ret = WaitSend(timeleftSecs,timeleftMicros);
  321. if(ret!=0){
  322. return ret;
  323. }
  324. }
  325. ret = send(m_hSocket, pBuff + total, bytesleft, 0);
  326. if (ret == SOCKET_ERROR) {
  327. return SOCKET_ERROR;
  328. }
  329. total += ret;
  330. bytesleft -=ret;
  331. if (m_dwTimeoutSend != NO_TIMEOUT){
  332. auto now = ofGetElapsedTimeMicros();
  333. auto diff = now - timestamp;
  334. if (diff > m_dwTimeoutSend * 1000000){
  335. return SOCKET_TIMEOUT;
  336. }
  337. float timeFloat = m_dwTimeoutSend - diff/1000000.;
  338. timeleftSecs = timeFloat;
  339. timeleftMicros = (timeFloat - timeleftSecs) * 1000000;
  340. }
  341. }
  342. return total;
  343. }
  344. //--------------------------------------------------------------------------------
  345. /// Return values:
  346. /// SOCKET_TIMEOUT indicates timeout
  347. /// SOCKET_ERROR in case of a problem.
  348. ///
  349. int ofxTCPManager::Receive(char* pBuff, const int iSize)
  350. {
  351. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  352. if (m_dwTimeoutReceive != NO_TIMEOUT){
  353. auto ret = WaitReceive(m_dwTimeoutReceive,0);
  354. if(ret!=0){
  355. return ret;
  356. }
  357. }
  358. return recv(m_hSocket, pBuff, iSize, 0);
  359. }
  360. //--------------------------------------------------------------------------------
  361. /// Return values:
  362. /// SOCKET_TIMEOUT indicates timeout
  363. /// SOCKET_ERROR in case of a problem.
  364. ///
  365. int ofxTCPManager::PeekReceive(char* pBuff, const int iSize)
  366. {
  367. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  368. if (m_dwTimeoutReceive != NO_TIMEOUT){
  369. auto ret = WaitReceive(m_dwTimeoutReceive,0);
  370. if(ret!=0){
  371. return ret;
  372. }
  373. }
  374. return recv(m_hSocket, pBuff, iSize, MSG_PEEK);
  375. }
  376. //--------------------------------------------------------------------------------
  377. /// Return values:
  378. /// SOCKET_TIMEOUT indicates timeout
  379. /// SOCKET_ERROR in case of a problem.
  380. int ofxTCPManager::ReceiveAll(char* pBuff, const int iSize)
  381. {
  382. if (m_hSocket == INVALID_SOCKET) return(SOCKET_ERROR);
  383. auto timestamp = ofGetElapsedTimeMicros();
  384. auto timeleftSecs = m_dwTimeoutReceive;
  385. auto timeleftMicros = 0;
  386. int totalBytes=0;
  387. do {
  388. if (m_dwTimeoutReceive != NO_TIMEOUT){
  389. auto ret = WaitReceive(timeleftSecs, timeleftMicros);
  390. if(ret!=0){
  391. return ret;
  392. }
  393. }
  394. int ret = recv(m_hSocket, pBuff+totalBytes, iSize-totalBytes, 0);
  395. if (ret==0 && totalBytes != iSize){
  396. return SOCKET_ERROR;
  397. }
  398. if (ret < 0){
  399. return SOCKET_ERROR;
  400. }
  401. totalBytes += ret;
  402. if (m_dwTimeoutReceive != NO_TIMEOUT){
  403. auto now = ofGetElapsedTimeMicros();
  404. auto diff = now - timestamp;
  405. if(diff > m_dwTimeoutReceive){
  406. return SOCKET_TIMEOUT;
  407. }
  408. float timeFloat = m_dwTimeoutSend - diff/1000000.;
  409. timeleftSecs = timeFloat;
  410. timeleftMicros = (timeFloat - timeleftSecs) * 1000000;
  411. }
  412. }while(totalBytes < iSize);
  413. return totalBytes;
  414. }
  415. //--------------------------------------------------------------------------------
  416. bool ofxTCPManager::GetRemoteAddr(LPINETADDR pInetAddr)
  417. {
  418. if (m_hSocket == INVALID_SOCKET) return(false);
  419. #ifndef TARGET_WIN32
  420. socklen_t iSize;
  421. #else
  422. int iSize;
  423. #endif
  424. iSize= sizeof(sockaddr);
  425. bool ret = (getpeername(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  426. if(!ret) ofxNetworkCheckError();
  427. return ret;
  428. }
  429. //--------------------------------------------------------------------------------
  430. bool ofxTCPManager::GetInetAddr(LPINETADDR pInetAddr)
  431. {
  432. if (m_hSocket == INVALID_SOCKET) return(false);
  433. #ifndef TARGET_WIN32
  434. socklen_t iSize;
  435. #else
  436. int iSize;
  437. #endif
  438. iSize= sizeof(sockaddr);
  439. bool ret = (getsockname(m_hSocket, (sockaddr *)pInetAddr, &iSize) != SOCKET_ERROR);
  440. if(!ret) ofxNetworkCheckError();
  441. return ret;
  442. }
  443. void ofxTCPManager::SetTimeoutConnect(int timeoutInSeconds) {
  444. m_dwTimeoutConnect= timeoutInSeconds;
  445. }
  446. void ofxTCPManager::SetTimeoutSend(int timeoutInSeconds) {
  447. m_dwTimeoutSend= timeoutInSeconds;
  448. }
  449. void ofxTCPManager::SetTimeoutReceive(int timeoutInSeconds) {
  450. m_dwTimeoutReceive= timeoutInSeconds;
  451. }
  452. void ofxTCPManager::SetTimeoutAccept(int timeoutInSeconds) {
  453. m_dwTimeoutAccept= timeoutInSeconds;
  454. }
  455. int ofxTCPManager::GetTimeoutConnect() {
  456. return m_dwTimeoutConnect;
  457. }
  458. int ofxTCPManager::GetTimeoutSend() {
  459. return m_dwTimeoutSend;
  460. }
  461. int ofxTCPManager::GetTimeoutReceive() {
  462. return m_dwTimeoutReceive;
  463. }
  464. int ofxTCPManager::GetTimeoutAccept() {
  465. return m_dwTimeoutAccept;
  466. }
  467. int ofxTCPManager::GetReceiveBufferSize() {
  468. if (m_hSocket == INVALID_SOCKET) return(false);
  469. #ifndef TARGET_WIN32
  470. socklen_t size;
  471. #else
  472. int size;
  473. #endif
  474. int sizeBuffer=0;
  475. size = sizeof(int);
  476. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeBuffer, &size);
  477. if(ret==-1) ofxNetworkCheckError();
  478. return sizeBuffer;
  479. }
  480. bool ofxTCPManager::SetReceiveBufferSize(int sizeInByte) {
  481. if (m_hSocket == INVALID_SOCKET) return(false);
  482. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_RCVBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  483. return true;
  484. }else{
  485. ofxNetworkCheckError();
  486. return false;
  487. }
  488. }
  489. int ofxTCPManager::GetSendBufferSize() {
  490. if (m_hSocket == INVALID_SOCKET) return(false);
  491. #ifndef TARGET_WIN32
  492. socklen_t size;
  493. #else
  494. int size;
  495. #endif
  496. int sizeBuffer=0;
  497. size = sizeof(int);
  498. int ret = getsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeBuffer, &size);
  499. if(ret==-1) ofxNetworkCheckError();
  500. return sizeBuffer;
  501. }
  502. bool ofxTCPManager::SetSendBufferSize(int sizeInByte) {
  503. if (m_hSocket == INVALID_SOCKET) return(false);
  504. if ( setsockopt(m_hSocket, SOL_SOCKET, SO_SNDBUF, (char*)&sizeInByte, sizeof(sizeInByte)) == 0){
  505. return true;
  506. }else{
  507. ofxNetworkCheckError();
  508. return false;
  509. }
  510. }
  511. int ofxTCPManager::GetMaxConnections() {
  512. return m_iMaxConnections;
  513. }
  514. bool ofxTCPManager::CheckHost(const char *pAddrStr) {
  515. hostent * hostEntry;
  516. in_addr iaHost;
  517. iaHost.s_addr = inet_addr(pAddrStr);
  518. hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);
  519. return ((!hostEntry) ? false : true);
  520. }