PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/socket.cxx

https://bitbucket.org/wildcarde/conquest-dicom-server
C++ | 694 lines | 448 code | 89 blank | 157 comment | 47 complexity | 229f0add2d4b215b8e60128f6849fbc6 MD5 | raw file
  1. /*
  2. 20010426 ljz Added 'setsockopt' in 'Listen' and 'Open'
  3. Call 'shutdown' before closing a socket
  4. 20010720 ljz Changed 'print' to 'fprint(stderr,...)'
  5. 20050116 mvh Adapted for LINUX compile
  6. 20050119 mvh Blocked out SOCKET END ERROR message
  7. 20070406 mvh Use reentrant gethostbyname_r when available
  8. 20070415 mvh Small fix there for windows
  9. 20090620 jf Added unistd.h for UNIX
  10. 20090824 mvh Debug output of adress connecting to socket
  11. 20091231 bcb Changed char* to const char* for gcc4.2 warnings
  12. 20100111 mvh Merged
  13. 20100122 mvh Gethostbyname: fixed bug reported by Arash 2station would not be found
  14. 20100122 mvh Added Poll() method: returns TRUE if data available
  15. 20100125 mvh Linux warning
  16. 20100309 bcb Commented out or inited to fix unused variable warning (gcc4.2 Warnings)
  17. 20100619 bcb Fix gcc4 warnings, improve speed and made TimeOut local.
  18. 20100707 mvh Merged
  19. */
  20. /****************************************************************************
  21. Copyright (C) 1995, University of California, Davis
  22. THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND THE UNIVERSITY
  23. OF CALIFORNIA DOES NOT MAKE ANY WARRANTY ABOUT THE SOFTWARE, ITS
  24. PERFORMANCE, ITS MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR
  25. USE, FREEDOM FROM ANY COMPUTER DISEASES OR ITS CONFORMITY TO ANY
  26. SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND PERFORMANCE OF
  27. THE SOFTWARE IS WITH THE USER.
  28. Copyright of the software and supporting documentation is
  29. owned by the University of California, and free access
  30. is hereby granted as a license to use this software, copy this
  31. software and prepare derivative works based upon this software.
  32. However, any distribution of this software source code or
  33. supporting documentation or derivative works (source code and
  34. supporting documentation) must include this copyright notice.
  35. ****************************************************************************/
  36. /***************************************************************************
  37. *
  38. * University of California, Davis
  39. * UCDMC DICOM Network Transport Libraries
  40. * Version 0.1 Beta
  41. *
  42. * Technical Contact: mhoskin@ucdavis.edu
  43. *
  44. ***************************************************************************/
  45. /*******************************************************************************
  46. *
  47. * socket.C
  48. *
  49. *******************************************************************************/
  50. # include "dicom.hpp"
  51. # include <stdlib.h>
  52. #ifdef UNIX
  53. # include <unistd.h> //DUCKHEAD92
  54. #endif
  55. #ifdef WINDOWS
  56. #define SD_BOTH 0x02 /* From winsock2.h */
  57. static WORD WinSockUsed = 0;
  58. static WSADATA wsaData;
  59. Socket :: Socket ()
  60. {
  61. WORD VersionNeeded;
  62. FARPROC FarProc;
  63. TimeOut = 60 * 5; // 5 minutes
  64. UDP = 0;
  65. if(! WinSockUsed )
  66. {
  67. /* WinSock.dll not WSAStartup(), so call it and init the library */
  68. VersionNeeded = 0x0101;
  69. Error = WSAStartup( VersionNeeded, &wsaData);
  70. if( Error )
  71. {
  72. /* no socket library */
  73. return;
  74. }
  75. /*FarProc = (FARPROC) SocketBlockingHook;
  76. if(!WSASetBlockingHook(FarProc))
  77. {
  78. OutputDebugString("Failed to Install Blocking Hook\n");
  79. }*/
  80. }
  81. ++WinSockUsed;
  82. Socketfd = 0;
  83. ListenSocketfd = 0;
  84. Connected = 0;
  85. Listened = 0;
  86. }
  87. Socket :: ~Socket ()
  88. {
  89. if( ! WinSockUsed )
  90. return; // must have failed installation
  91. if ( Socketfd )
  92. {
  93. shutdown(Socketfd, SD_BOTH);
  94. closesocket(Socketfd);
  95. }
  96. if ( ListenSocketfd )
  97. {
  98. shutdown(ListenSocketfd, SD_BOTH);
  99. closesocket(ListenSocketfd);
  100. }
  101. --WinSockUsed;
  102. if(! WinSockUsed )
  103. {
  104. //WSAUnhookBlockingHook();
  105. WSACleanup();
  106. }
  107. }
  108. #else
  109. #define SYSV_SOCKET
  110. # define closesocket(xxx) close(xxx)
  111. /*
  112. int closesocket(int sock)
  113. {
  114. int flags;
  115. struct linger sl;
  116. sl.l_onoff=1;
  117. sl.l_linger=30;
  118. errno=0;
  119. setsockopt(sock, SOL_SOCKET, SO_LINGER, &sl, sizeof(linger));
  120. fprintf(stderr, "%d\n", errno);
  121. errno = 0;
  122. fprintf(stderr, "CloseSocket(%d) : %d ", sock, close(sock));
  123. fprintf(stderr, "%d\n", errno);
  124. return(0);
  125. }
  126. */
  127. Socket :: Socket()
  128. #ifdef __GNUC__ //Faster with member initialization.
  129. :Error(0),
  130. tulong(0),
  131. tulongptr(NULL),
  132. Socketfd(0),
  133. ListenSocketfd(0),
  134. UDP(0),
  135. Connected(0),
  136. Listened(0),
  137. sa(),
  138. hes(),
  139. servs(),
  140. TimeOut(300) {} // 5 minutes
  141. #else
  142. {
  143. Socketfd = 0;
  144. Connected = 0;
  145. Listened = 0;
  146. ListenSocketfd = 0;
  147. TimeOut = 60 * 5; // 5 minutes
  148. UDP = 0;
  149. }
  150. #endif
  151. Socket :: ~Socket()
  152. {
  153. if ( Socketfd )
  154. {
  155. closesocket(Socketfd);
  156. }
  157. if ( ListenSocketfd )
  158. {
  159. closesocket(ListenSocketfd);
  160. }
  161. }
  162. #endif
  163. #ifndef gethostbyname_r
  164. #define gethostbyname_r(name, a, b, c, d, e) *d=gethostbyname(name)
  165. #endif
  166. struct hostent * Socket :: Gethostbyname(char *name1)
  167. {
  168. struct hostent *he;
  169. struct hostent he2;
  170. unsigned long ip;
  171. // unsigned long i1,i2,i3,i4;
  172. // char *dot2, *dot3, *dot4;
  173. char *name;
  174. char ndat[128], buf[64];
  175. int dum;
  176. he2.h_length = 0;//Added for compiler unused warning. bcb
  177. buf[63] = 0;//Added for compiler unused warning. bcb
  178. dum = 0;//Added for compiler unused warning. bcb
  179. strcpy(ndat, name1);
  180. name = &ndat[0];
  181. if(!atoi(name1) || strchr(name1, '.')==NULL) // fix for name like 2station
  182. gethostbyname_r(name, &he2, buf, 64, &he, &dum);
  183. else
  184. he = NULL; // has . and starts with number
  185. if(he)
  186. {
  187. memcpy ((void *) &hes, (void *) he, sizeof(struct hostent));
  188. return(&hes);
  189. }
  190. #ifdef MAC
  191. struct in_addr ipa = inet_addr(name);
  192. ip = ipa.s_addr;
  193. #else
  194. ip = inet_addr(name);
  195. #endif
  196. /******************************
  197. dot2 = strchr(name, '.');
  198. if(!dot2)
  199. return ( NULL );
  200. (*dot2) = '\0';
  201. ++dot2;
  202. dot3 = strchr(dot2, '.');
  203. if(!dot3)
  204. return ( NULL );
  205. (*dot3) = '\0';
  206. ++dot3;
  207. dot4 = strchr(dot3, '.');
  208. if(!dot4)
  209. return ( NULL );
  210. (*dot4) = '\0';
  211. ++dot4;
  212. i1 = atoi(name);
  213. i2 = atoi(dot2);
  214. i3 = atoi(dot3);
  215. i4 = atoi(dot4);
  216. #if NATIVE_ENDIAN == BIG_ENDIAN
  217. i1 = i4 << 24;
  218. i2 = i3 << 16;
  219. i3 = i2 << 8;
  220. #else
  221. i4 = i4 << 24;
  222. i3 = i3 << 16;
  223. i2 = i2 << 8;
  224. #endif
  225. ip = i1 | i2 | i3 | i4;
  226. ********************************/
  227. hes.h_addr_list = (char **) &tulongptr;
  228. tulongptr = &tulong;
  229. tulong = ip;
  230. return ( &hes );
  231. }
  232. struct servent * Socket :: Getservbyname(const char *name, char *prot)
  233. {
  234. unsigned short s;
  235. // unsigned short s1;
  236. struct servent *se;
  237. s = atoi(name);
  238. if(!s)
  239. {
  240. se = getservbyname(name, prot);
  241. if(!se)
  242. return(se);
  243. memcpy ((void *) &servs, (void *) se, sizeof(struct servent));
  244. return(&servs);
  245. }
  246. #ifdef MAC
  247. servs.s_port = s;
  248. #else
  249. servs.s_port = htons(s);
  250. #endif
  251. /****************************
  252. s1 = s & 0x00ff;
  253. s1 = s1 << 8;
  254. s = s >> 8;
  255. s1 = s1 | s;
  256. servs.s_port = s1;
  257. *******************************/
  258. // fprintf(stderr, "returning: %d\n", servs.s_port);
  259. return ( &servs );
  260. }
  261. BOOL Socket :: Listen ( char *port )
  262. {
  263. UINT32 tuint32;
  264. // struct hostent *he;
  265. // struct hostent hecopy;
  266. struct servent *se;
  267. struct servent secopy;
  268. struct linger Linger;
  269. Connected = 0;
  270. Listened = 0;
  271. if ( Socketfd )
  272. closesocket(Socketfd);
  273. // fprintf(stderr, "[Listen: %s]\n", port); fflush(stderr);
  274. /*he = Gethostbyname("hampson");
  275. if ( !he )
  276. {
  277. return ( FALSE ); // could not resolve host name
  278. }
  279. */
  280. //memcpy ((void *) &hecopy, (void *) he, sizeof(struct hostent));
  281. se = Getservbyname(port, NULL);
  282. if ( !se )
  283. return ( FALSE ); // could not resolv port
  284. memcpy ((void *) &secopy, (void *) se, sizeof(struct servent));
  285. Socketfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  286. if(!Socketfd)
  287. return ( FALSE ); // could not create socket
  288. Linger.l_onoff = 1;
  289. Linger.l_linger = 0;
  290. setsockopt(Socketfd, SOL_SOCKET, SO_LINGER, (char*)&Linger, sizeof(struct linger));
  291. //memcpy((void *) &sa.sin_addr.S_un.S_addr , (void *) hecopy.h_addr_list[0], 4); // adddress
  292. // should bind to the default address
  293. tuint32 = 0;
  294. #ifdef SYSV_SOCKET
  295. sa.sin_addr.s_addr = tuint32;
  296. #else
  297. memcpy((void *) &sa.sin_addr.S_un.S_addr, (void *) &tuint32, 4);
  298. #endif
  299. memcpy((void *) &sa.sin_port , (void *) &secopy.s_port, 2); // port
  300. sa.sin_port = secopy.s_port;
  301. sa.sin_family = AF_INET;
  302. if(bind(Socketfd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)))
  303. {
  304. // fprintf(stderr, "Erro (bind) : %d\n", GetLinkError());
  305. #ifdef FORCEDIO
  306. /* while(errno==125)
  307. {
  308. errno=0;
  309. bind(Socketfd, (struct sockaddr *) &sa, sizeof(struct
  310. sockaddr_in));
  311. }*/
  312. #endif
  313. if(GetLinkError())
  314. {
  315. closesocket(Socketfd);
  316. Error = GetLinkError();
  317. Socketfd = 0;
  318. return ( FALSE );
  319. }
  320. }
  321. if(listen(Socketfd, 5))
  322. {
  323. //fprintf(stderr, "Erro (bind): %d\n", GetLinkError());fflush(stderr);
  324. closesocket(Socketfd);
  325. Socketfd = 0;
  326. return ( FALSE );
  327. }
  328. Listened = 1;
  329. ListenSocketfd = Socketfd;
  330. Socketfd = 0;
  331. Connected = 0;
  332. return ( TRUE );
  333. }
  334. BOOL Socket :: Accept()
  335. {
  336. #ifdef SYSV_SOCKET
  337. socklen_t Size;
  338. #else
  339. int Size;
  340. #endif
  341. //fprintf(stderr, "Accept()\n");fflush(stderr);
  342. if(!Listened)
  343. return ( FALSE );
  344. if(!ListenSocketfd)
  345. return ( FALSE );
  346. Size = sizeof(struct sockaddr_in);
  347. Socketfd = accept(ListenSocketfd, (struct sockaddr *) &sa, &Size);
  348. if(Socketfd>0)
  349. {
  350. Connected = TRUE;
  351. DicomError(DCM_ERROR_DEBUG, "Connected by address: %08x", sa.sin_addr.s_addr);
  352. return ( TRUE );
  353. }
  354. //fprintf(stderr, "Error (accept) : %d\n", errno);
  355. closesocket(ListenSocketfd);
  356. Listened = 0;
  357. ListenSocketfd = 0;
  358. Socketfd = 0;
  359. Connected = FALSE;
  360. return ( FALSE );
  361. }
  362. BOOL Socket :: Open ( char *ip, char *port)
  363. {
  364. struct hostent *he;
  365. struct hostent hecopy;
  366. struct servent *se;
  367. struct servent secopy;
  368. struct linger Linger;
  369. if ( Socketfd )
  370. closesocket(Socketfd);
  371. Connected = 0;
  372. he = Gethostbyname(ip);
  373. if ( !he )
  374. {
  375. // fprintf(stderr, "Could not resolve host\n");
  376. return ( FALSE ); // could not resolve host name
  377. }
  378. memcpy ((void *) &hecopy, (void *) he, sizeof(struct hostent));
  379. se = Getservbyname(port, NULL);
  380. if ( !se )
  381. {
  382. // fprintf(stderr, "Could not resolve port\n");
  383. return ( FALSE ); // could not resolv port
  384. }
  385. memcpy ((void *) &secopy, (void *) se, sizeof(struct servent));
  386. if(!hecopy.h_addr_list)
  387. return ( FALSE );
  388. Socketfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  389. if(Socketfd<0)
  390. return ( FALSE ); // could not create socket
  391. Linger.l_onoff = 1;
  392. Linger.l_linger = 0;
  393. setsockopt(Socketfd, SOL_SOCKET, SO_LINGER, (char*)&Linger, sizeof(struct linger));
  394. #ifdef SYSV_SOCKET
  395. memcpy((void *) &sa.sin_addr.s_addr , (void *) hecopy.h_addr_list[0], 4); // adddress
  396. #else
  397. memcpy((void *) &sa.sin_addr.S_un.S_addr , (void *) hecopy.h_addr_list[0], 4); // adddress
  398. #endif
  399. memcpy((void *) &sa.sin_port , (void *) &secopy.s_port, 2); // port
  400. sa.sin_family = AF_INET;
  401. sa.sin_port = secopy.s_port;
  402. Error = connect(Socketfd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
  403. if( ! Error )
  404. {
  405. Connected = TRUE;
  406. return ( TRUE );
  407. }
  408. closesocket(Socketfd);
  409. Socketfd = 0;
  410. return ( FALSE );
  411. }
  412. BOOL Socket :: Close()
  413. {
  414. if(ListenSocketfd)
  415. {
  416. closesocket(ListenSocketfd);
  417. }
  418. if(Socketfd)
  419. {
  420. closesocket(Socketfd);
  421. }
  422. ListenSocketfd = 0;
  423. Socketfd = 0;
  424. Connected = 0;
  425. Listened = 0;
  426. UDP = 0;
  427. return ( TRUE );
  428. }
  429. BOOL Socket :: Poll(void)
  430. {
  431. #ifdef SYSV_SOCKET
  432. fd_set fds;
  433. #else
  434. struct fd_set fds;
  435. #endif
  436. struct timeval tv = {0, 0}; // return immediately
  437. if ( ! Connected )
  438. return ( FALSE );
  439. #ifdef MAC
  440. memset((void*)&fds, 0, sizeof(struct fd_set));
  441. #else
  442. FD_ZERO(&fds);
  443. #endif
  444. FD_SET(Socketfd, &fds);
  445. return (select(Socketfd + 1, &fds, NULL, NULL, &tv)==1);
  446. }
  447. BOOL Socket :: SendBinary(BYTE *s, UINT count)
  448. {
  449. if ( !Connected)
  450. return ( 0 );
  451. if(send ( Socketfd, (char *) s, count, 0)<0)
  452. {
  453. // fprintf(stderr, "SOCKET END ERROR: %d\n", GetLastError());
  454. }
  455. return ( TRUE );
  456. }
  457. INT Socket :: ReadBinary(BYTE *s, UINT count)
  458. {
  459. #ifdef SYSV_SOCKET
  460. fd_set fds;
  461. #else
  462. struct fd_set fds;
  463. #endif
  464. struct timeval tv = {TimeOut, 0}; // poll
  465. if ( ! Connected )
  466. return ( -1 );
  467. #ifdef MAC
  468. memset((void*)&fds, 0, sizeof(struct fd_set));
  469. #else
  470. FD_ZERO(&fds);
  471. #endif
  472. FD_SET(Socketfd, &fds);
  473. if(select(Socketfd + 1, &fds, NULL, NULL, &tv)==1)
  474. {
  475. if((count = recv(Socketfd, (char *) s, count, 0))==0)
  476. {
  477. /*#ifdef WINDOWS
  478. if(WSAGetLastError()==WSAEDISCON)
  479. return(-1);
  480. else
  481. return(0);
  482. #else
  483. return ( -1 );
  484. #endif
  485. */
  486. Close ();
  487. return ( -1 );
  488. }
  489. return ( count );
  490. }
  491. if ( TimeOut )
  492. return ( -1 );
  493. return ( 0 );
  494. }
  495. int Socket :: GetLinkError()
  496. {
  497. #ifdef WINDOWS
  498. return ( WSAGetLastError() );
  499. #else
  500. return ( errno );
  501. #endif
  502. }
  503. BOOL Socket :: SetTimeOut(int lTimeOut)
  504. {
  505. this->TimeOut = lTimeOut;
  506. return ( TRUE );
  507. }
  508. BOOL
  509. Socket :: BindUDPServer (
  510. char *port)
  511. {
  512. Close();
  513. struct servent *se;
  514. struct servent secopy;
  515. se = Getservbyname(port, NULL);
  516. if ( !se )
  517. {
  518. return ( FALSE ); // could not resolv port
  519. }
  520. memcpy ((void *) &secopy, (void *) se, sizeof(struct servent));
  521. Socketfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  522. if(Socketfd<0)
  523. return ( FALSE ); // could not create socket
  524. #ifdef SYSV_SOCKET
  525. memset((void *) &sa.sin_addr.s_addr , 0, 4);
  526. #else
  527. memset((void *) &sa.sin_addr.S_un.S_addr , 0, 4);
  528. #endif
  529. memcpy((void *) &sa.sin_port , (void *) &secopy.s_port, 2); // port
  530. sa.sin_family = AF_INET;
  531. sa.sin_port = secopy.s_port;
  532. if(bind(Socketfd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in)))
  533. {
  534. closesocket(Socketfd);
  535. Error = GetLinkError();
  536. Socketfd = 0;
  537. return ( FALSE );
  538. }
  539. Connected = 1;
  540. UDP = 1;
  541. return ( TRUE );
  542. }
  543. BOOL
  544. Socket :: BindUDPClient (
  545. char *ip,
  546. const char *port)
  547. {
  548. struct hostent *he;
  549. struct hostent hecopy;
  550. struct servent *se;
  551. struct servent secopy;
  552. if ( Socketfd )
  553. closesocket(Socketfd);
  554. if ( ListenSocketfd )
  555. closesocket(ListenSocketfd);
  556. Listened = 0;
  557. Connected = 0;
  558. Socketfd = 0;
  559. ListenSocketfd = 0;
  560. he = Gethostbyname(ip);
  561. if ( !he )
  562. {
  563. fprintf(stderr, "Could not resolve host\n");
  564. return ( FALSE ); // could not resolve host name
  565. }
  566. memcpy ((void *) &hecopy, (void *) he, sizeof(struct hostent));
  567. se = Getservbyname(port, NULL);
  568. if ( !se )
  569. {
  570. fprintf(stderr, "Could not resolve port\n");
  571. return ( FALSE ); // could not resolv port
  572. }
  573. memcpy ((void *) &secopy, (void *) se, sizeof(struct servent));
  574. if(!hecopy.h_addr_list)
  575. return ( FALSE );
  576. Socketfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  577. if(Socketfd<0)
  578. return ( FALSE ); // could not create socket
  579. #ifdef SYSV_SOCKET
  580. memcpy((void *) &sa.sin_addr.s_addr , (void *) hecopy.h_addr_list[0], 4); // adddress
  581. #else
  582. memcpy((void *) &sa.sin_addr.S_un.S_addr , (void *) hecopy.h_addr_list[0], 4); // adddress
  583. #endif
  584. memcpy((void *) &sa.sin_port , (void *) &secopy.s_port, 2); // port
  585. sa.sin_family = AF_INET;
  586. sa.sin_port = secopy.s_port;
  587. Error = connect(Socketfd, (struct sockaddr *) &sa, sizeof(struct sockaddr_in));
  588. if( ! Error )
  589. {
  590. Connected = TRUE;
  591. UDP = 1;
  592. return ( TRUE );
  593. }
  594. closesocket(Socketfd);
  595. Socketfd = 0;
  596. return ( FALSE );
  597. }
  598. /*#endif*/