tcp.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /****************************************************************************\
  19. TCP Neal Kettler [email protected]
  20. ******************************************************************************
  21. A general purpose TCP class that can be used in either CLIENT or
  22. SERVER mode. Note that this uses non-blocking sockets.
  23. The FD_* macros:
  24. FD_CLR(int fd, fd_set *set); // clear a single FD
  25. FD_ISSET(int fd, fd_set *set); // check whether a single FD is set
  26. FD_SET(int fd, fd_set *set); // set a single FD
  27. FD_ZERO(fd_set * set); // clear the entire set
  28. NOTE: The fd_set returned by 'Wait' is static, don't call delete
  29. on it!
  30. If you are writing a CLIENT:
  31. The last argument to many functions is an integer whichFD, this is used
  32. only by SERVER mode, so you can omit this argument. Sample Code:
  33. fd_set *fdSet;
  34. uint8 *buff=new uint8[1024];
  35. int retval;
  36. TCP tcp(CLIENT);
  37. tcp.Bind((uint32)0,(uint16)0); // let system pick local IP and a Port for you
  38. tcp.Connect("tango",13); // can connect by name or "10.1.1.10"
  39. // or the integerßin host byte order
  40. fdSet=tcp.Wait(10,0); // wait for UP TO 10 sec and 0 microseconds
  41. if (FD_ISSET(tcp.GetFD(),fdSet)) // Is there something to read?
  42. {
  43. retval=tcp.Read(buff,1024); // Read something
  44. // Retval will contain the number of
  45. // bytes read, or...
  46. // 0 = remote end closed connection
  47. // -1 = nothing to read
  48. fprintf(stderr,"%s",buff);
  49. }
  50. else
  51. fprintf(stderr,"Nothing was read!\n");
  52. If you are writing a SERVER:
  53. The structure called 'clientList' contains all the File Descriptors
  54. that have connected to the server. Make sure you look at the FD_*
  55. functions so you can use this sort of structure. When you are writing
  56. a server, you need to specify the 'whichFD' arguments to all the
  57. functions. Sample Code:
  58. fd_set *fdSet;
  59. uint8 *buff=new uint8[1024];
  60. int retval;
  61. TCP tcp(SERVER);
  62. tcp.Bind((uint32)0,(uint16)2121); // You need to bind to a well defined
  63. // port number or nobody will know where
  64. // to connect to.
  65. while (1)
  66. {
  67. fdSet=tcp.Wait(-1,-1); // Wait until there is something on the socket
  68. if (FD_ISSET(tcp.GetFD(),fdSet)) // somebody must want a connection
  69. {
  70. retval=tcp.GetConnection(); // Get a connection if somebody's trying
  71. if (retval!=-1)
  72. {
  73. tcp.Write("Hello World!\n",strlen("Hello World!\n"),retval);
  74. tcp.Close(retval);
  75. }
  76. }
  77. }
  78. \****************************************************************************/
  79. #include "tcp.h"
  80. #include <stdarg.h>
  81. #ifndef _WINDOWS
  82. #include <errno.h>
  83. #define closesocket close
  84. #endif
  85. // newMode should be either CLIENT or SERVER
  86. TCP::TCP(int new_mode)
  87. {
  88. mode=CLIENT;
  89. maxFD=0;
  90. fd = -1;
  91. clientCount=0;
  92. if ((new_mode==CLIENT)||(new_mode==SERVER))
  93. mode=new_mode;
  94. FD_ZERO(&clientList);
  95. connectionState=CLOSED;
  96. inputDelay=5;
  97. outputDelay=5;
  98. }
  99. // Create a TCP object on a pre-existing socket
  100. TCP::TCP(int new_mode,sint16 socket)
  101. {
  102. sint32 retval;
  103. mode=CLIENT;
  104. maxFD= socket;
  105. fd = socket;
  106. clientCount=0;
  107. if ((new_mode==CLIENT)||(new_mode==SERVER))
  108. mode=new_mode;
  109. FD_ZERO(&clientList);
  110. inputDelay=5;
  111. outputDelay=5;
  112. retval=SetBlocking(FALSE,socket); // set to NB mode
  113. //DBGMSG("Setblocking: "<<retval);
  114. connectionState=CLOSED;
  115. if (mode==CLIENT) // determine what state the socket is in
  116. {
  117. connectionState=CONNECTING; // this is used when state is unsure
  118. if (IsConnected(socket))
  119. connectionState=CONNECTED;
  120. else
  121. connectionState=CLOSED;
  122. }
  123. //DBGMSG("Connstate = "<<connectionState);
  124. }
  125. TCP::~TCP()
  126. {
  127. CloseAll();
  128. }
  129. int TCP::GetFD()
  130. {
  131. return(fd);
  132. }
  133. // private function
  134. sint32 TCP::SetBlocking(bit8 block,sint32 whichFD)
  135. {
  136. if (whichFD==0)
  137. whichFD=fd;
  138. #ifdef _WINDOWS
  139. unsigned long flag=1;
  140. if (block)
  141. flag=0;
  142. int retval;
  143. retval=ioctlsocket(whichFD,FIONBIO,&flag);
  144. if (retval==SOCKET_ERROR)
  145. return(-1);
  146. else
  147. return(0);
  148. #else
  149. int flags = fcntl(whichFD, F_GETFL, 0);
  150. if (block==FALSE) // set nonblocking
  151. flags |= O_NONBLOCK;
  152. else // set blocking
  153. flags &= ~(O_NONBLOCK);
  154. if (fcntl(whichFD, F_SETFL, flags) < 0)
  155. {
  156. return(-1);
  157. }
  158. return(0);
  159. #endif
  160. }
  161. sint32 TCP::GetMaxFD(void)
  162. {
  163. if (mode==CLIENT)
  164. return(fd);
  165. else if (mode==SERVER)
  166. return(maxFD);
  167. else
  168. return(-1);
  169. }
  170. // Only specify whichFD if this is a server application
  171. sint32 TCP::Write(const uint8 *msg,uint32 len,sint32 whichFD)
  172. {
  173. sint32 retval;
  174. if (whichFD==0)
  175. {
  176. if (mode==SERVER)
  177. assert(FALSE);
  178. whichFD=fd;
  179. }
  180. SetBlocking(TRUE,whichFD);
  181. retval=send(whichFD,(const char *)msg,len,0);
  182. #ifdef _WINDOWS
  183. if (retval==SOCKET_ERROR)
  184. retval=-1;
  185. #endif
  186. SetBlocking(FALSE,whichFD);
  187. return(retval);
  188. }
  189. // Only specify whichFD if this is a server application
  190. // NON BLOCKING WRITE
  191. sint32 TCP::WriteNB(uint8 *msg,uint32 len,sint32 whichFD)
  192. {
  193. sint32 retval;
  194. if (whichFD==0)
  195. {
  196. if (mode==SERVER)
  197. assert(FALSE);
  198. whichFD=fd;
  199. }
  200. retval=send(whichFD,(const char *)msg,len,0);
  201. #ifdef _WINDOWS
  202. if (retval==SOCKET_ERROR)
  203. retval=-1;
  204. #endif
  205. return(retval);
  206. }
  207. // Encapsulate data for lame ass proxys that won't pass 0's or 255's through
  208. // 0 goes to 1,1
  209. // 1 goes to 1,2
  210. // 255 goes to 1,3
  211. // everything else is the same
  212. sint32 TCP::EncapsulatedWrite(uint8 *msg,uint32 len,sint32 whichFD)
  213. {
  214. sint32 retval;
  215. uint32 i,bytesSent=0;
  216. uint8 data,one=1;
  217. if (mode==CLIENT)
  218. whichFD=fd;
  219. SetBlocking(TRUE,whichFD);
  220. for (i=0; i<len; i++)
  221. {
  222. data=msg[i];
  223. if ((data>1)&&(data<255))
  224. {
  225. retval=send(whichFD,(char *)&data,1,0);
  226. if (retval<1)
  227. {
  228. SetBlocking(FALSE,whichFD);
  229. return(i);
  230. }
  231. bytesSent++;
  232. }
  233. else
  234. {
  235. retval=send(whichFD,(char *)&one,1,0);
  236. if (retval<1)
  237. {
  238. SetBlocking(FALSE,whichFD);
  239. return(i);
  240. }
  241. if (data==0)
  242. data=1;
  243. else if (data==1)
  244. data=2;
  245. else if (data==255)
  246. data=3;
  247. retval=send(whichFD,(char *)&data,1,0);
  248. if (retval<1)
  249. {
  250. SetBlocking(FALSE,whichFD);
  251. return(i);
  252. }
  253. bytesSent+=2;
  254. }
  255. }
  256. SetBlocking(FALSE,whichFD);
  257. ///fprintf(stderr,"\n\nENCAP SENT %d\n\n",bytesSent);
  258. return(len);
  259. }
  260. // Make sure string is '\0' terminated
  261. sint32 TCP::WriteString(char *msg,sint32 whichFD)
  262. {
  263. if (mode==CLIENT)
  264. whichFD=fd;
  265. WaitWrite(whichFD);
  266. sint32 retval;
  267. if (mode==CLIENT)
  268. {
  269. SetBlocking(TRUE,fd);
  270. retval=send(fd,msg,strlen(msg),0);
  271. SetBlocking(FALSE,fd);
  272. return(retval);
  273. }
  274. else if (mode==SERVER)
  275. {
  276. if ((whichFD<=maxFD) && (FD_ISSET(whichFD,&clientList)))
  277. {
  278. SetBlocking(TRUE,whichFD);
  279. retval=send(whichFD,msg,strlen(msg),0);
  280. SetBlocking(FALSE,whichFD);
  281. return(retval);
  282. }
  283. }
  284. return(-1);
  285. }
  286. // only use for strings up to 1024 chars!
  287. sint32 TCP::Printf(sint32 whichFD,const char *format,...)
  288. {
  289. va_list arg;
  290. char string[1024];
  291. sint32 retval;
  292. va_start(arg,format);
  293. vsprintf(string,format,arg);
  294. va_end(arg);
  295. if (mode==CLIENT)
  296. whichFD=fd;
  297. WaitWrite(fd);
  298. if (mode==CLIENT)
  299. {
  300. SetBlocking(TRUE,whichFD);
  301. retval=send(fd,string,strlen(string),0);
  302. SetBlocking(FALSE,whichFD);
  303. return(retval);
  304. }
  305. else if (mode==SERVER)
  306. {
  307. if ((whichFD<=maxFD) && (FD_ISSET(whichFD,&clientList)))
  308. {
  309. SetBlocking(TRUE,whichFD);
  310. retval=send(whichFD,string,strlen(string),0);
  311. SetBlocking(FALSE,whichFD);
  312. return(retval);
  313. }
  314. }
  315. return(-1);
  316. }
  317. // Returns 0 on failure
  318. // Returns IP in host byte order!
  319. uint32 TCP::GetRemoteIP(sint32 whichFD)
  320. {
  321. struct sockaddr_in sin;
  322. int sinSize=sizeof(sin);
  323. if (mode==CLIENT)
  324. {
  325. if(getpeername(fd,(sockaddr *)&sin,&sinSize)==0)
  326. return(ntohl(sin.sin_addr.s_addr));
  327. }
  328. else if (mode==SERVER)
  329. {
  330. if(getpeername(whichFD,(sockaddr *)&sin,&sinSize)==0)
  331. return(ntohl(sin.sin_addr.s_addr));
  332. }
  333. return(0);
  334. }
  335. // Returns 0 on failure
  336. // Returns Port in host byte order!
  337. uint16 TCP::GetRemotePort(sint32 whichFD)
  338. {
  339. struct sockaddr_in sin;
  340. int sinSize=sizeof(sin);
  341. if (mode==CLIENT)
  342. {
  343. if(getpeername(fd,(sockaddr *)&sin,&sinSize)==0)
  344. return(ntohs(sin.sin_port));
  345. }
  346. else if (mode==SERVER)
  347. {
  348. if(getpeername(whichFD,(sockaddr *)&sin,&sinSize)==0)
  349. return(ntohs(sin.sin_port));
  350. }
  351. return(0);
  352. }
  353. // Is the FD connected?
  354. bit8 TCP::IsConnected(sint32 whichFD)
  355. {
  356. struct sockaddr_in sin;
  357. int sinSize=sizeof(sin);
  358. if (mode==CLIENT)
  359. whichFD=fd;
  360. if (mode==CLIENT)
  361. {
  362. if (connectionState==CONNECTED)
  363. return(TRUE);
  364. if (connectionState==CLOSED)
  365. return(FALSE);
  366. }
  367. // only get here if state==CONNECTING
  368. if(getpeername(whichFD,(sockaddr *)&sin,&sinSize)==0)
  369. if ( (sin.sin_addr.s_addr!=htonl(0)) && (CanWrite(whichFD)) )
  370. {
  371. connectionState=CONNECTED;
  372. return(TRUE);
  373. }
  374. return(FALSE);
  375. }
  376. // Not portable?
  377. /**************
  378. sint32 TCP::GetSockStatus(sint32 whichFD)
  379. {
  380. sint32 retval;
  381. int status,size=sizeof(int);
  382. if (whichFD==0)
  383. whichFD=fd;
  384. retval=getsockopt(whichFD,SOL_SOCKET,SO_ERROR,(char *)&status,&size);
  385. if (retval==-1)
  386. return(-1);
  387. return(status);
  388. }
  389. *******************/
  390. // The TCP equivalent of fgets()
  391. char *TCP::Gets(char *string,int n,int whichFD)
  392. {
  393. char c;
  394. int retval,i=0;
  395. fd_set fdSet;
  396. if (whichFD==0)
  397. whichFD=GetFD();
  398. if (whichFD <= 0)
  399. return(NULL);
  400. memset(string,0,n);
  401. while(1)
  402. {
  403. if (i==n)
  404. return(string);
  405. Wait(inputDelay,0,fdSet,whichFD); // inputDelay = 5 sec or so
  406. if (! FD_ISSET(whichFD,&fdSet))
  407. {
  408. DBGMSG("Gets timeout: " << inputDelay);
  409. return(NULL);
  410. }
  411. retval=Read((unsigned char *)&c,1,whichFD);
  412. if ((retval>0)&&(c!=0))
  413. {
  414. string[i]=c;
  415. if (c=='\n')
  416. return(string);
  417. i++;
  418. }
  419. else if ((retval==0)&&(i==0))
  420. {
  421. DBGMSG("Remote endpoint closed (1)");
  422. return(NULL);
  423. }
  424. else if (retval==0)
  425. return(string);
  426. }
  427. return(string);
  428. }
  429. // only specify whichFD if this is a server
  430. sint32 TCP::Read(uint8 *msg,uint32 len,sint32 whichFD)
  431. {
  432. sint32 retval;
  433. //DBGMSG("In read, mode: "<<mode<<" FD: "<<fd);
  434. if (mode==CLIENT)
  435. {
  436. retval=recv(fd,(char *)msg,len,0);
  437. ////////DBGMSG("READ: "<<retval << " ON FD: " << fd << " LEN: "<< len);
  438. if (retval==0)
  439. Close();
  440. return(retval);
  441. }
  442. else if (mode==SERVER)
  443. {
  444. if ((whichFD<=maxFD) && (FD_ISSET(whichFD,&clientList)))
  445. {
  446. retval=recv(whichFD,(char *)msg,len,0);
  447. if (retval==0)
  448. {
  449. Close(whichFD);
  450. }
  451. return(retval);
  452. }
  453. else
  454. {
  455. return(0); // closed
  456. }
  457. }
  458. return(-1);
  459. }
  460. // only specify whichFD if this is a server
  461. // Try and read 'len' bytes until the timer goes out.
  462. // This is effectively a blocking call, but it's still useful
  463. // in threaded environments.
  464. sint32 TCP::TimedRead(uint8 *msg,uint32 len,int seconds,sint32 whichFD)
  465. {
  466. fd_set set;
  467. sint32 bytes_read=0;
  468. sint32 retval;
  469. time_t stop_time=time(NULL)+seconds;
  470. while ((time(NULL)<=stop_time)&&((uint32)bytes_read<len))
  471. {
  472. Wait(1,0,set,whichFD);
  473. //DBGMSG("Calling read");
  474. retval=Read(msg+bytes_read,len-bytes_read,whichFD);
  475. if (retval==0) // they closed
  476. {
  477. DBGMSG("Remote close!\n");
  478. return(bytes_read);
  479. }
  480. else if (retval>0)
  481. bytes_read+=retval;
  482. // otherwise some error
  483. }
  484. return(bytes_read);
  485. }
  486. // only specify whichFD if this is a server
  487. // Peek at data in system buffer
  488. sint32 TCP::Peek(uint8 *msg,uint32 len,sint32 whichFD)
  489. {
  490. sint32 retval;
  491. if (mode==CLIENT)
  492. {
  493. retval=recv(fd,(char *)msg,len,MSG_PEEK);
  494. if (retval==0)
  495. Close();
  496. return(retval);
  497. }
  498. else if (mode==SERVER)
  499. {
  500. if ((whichFD<=maxFD) && (FD_ISSET(whichFD,&clientList)))
  501. {
  502. retval=recv(whichFD,(char *)msg,len,MSG_PEEK);
  503. if (retval==0)
  504. Close(whichFD);
  505. return(retval);
  506. }
  507. else
  508. return(0); // closed
  509. }
  510. return(-1);
  511. }
  512. // only specify whichFD if this is a server
  513. // (this is used for non-8 bit clean pipes, you probably don't
  514. // want to use it!)
  515. sint32 TCP::EncapsulatedRead(uint8 *msg,uint32 len,sint32 whichFD)
  516. {
  517. sint32 retval,bytesRead=0;
  518. uint32 i;
  519. char data;
  520. if (mode==CLIENT)
  521. whichFD=fd;
  522. else if (mode==SERVER)
  523. {
  524. if ((whichFD>maxFD) || (!FD_ISSET(whichFD,&clientList)))
  525. return(0);
  526. }
  527. else
  528. return(-1);
  529. for (i=0; i<len; i++)
  530. {
  531. retval=recv(fd,&data,1,0);
  532. if (retval==0)
  533. {
  534. Close();
  535. return(bytesRead);
  536. }
  537. if (retval==1)
  538. {
  539. bytesRead++;
  540. if (data==1)
  541. {
  542. retval=0;
  543. while(retval!=1)
  544. {
  545. retval=recv(fd,&data,1,0);
  546. if (retval==0)
  547. {
  548. Close();
  549. return(bytesRead);
  550. }
  551. }
  552. if (data==1)
  553. data=0;
  554. else if (data==2)
  555. data=1;
  556. else if (data==3)
  557. data=(char)255;
  558. }
  559. msg[i]=data;
  560. }
  561. if (retval==-1)
  562. return(bytesRead);
  563. }
  564. return(bytesRead);
  565. }
  566. sint32 TCP::CloseAll(void)
  567. {
  568. int i;
  569. if (mode==CLIENT)
  570. return(Close());
  571. for(i=0; i<=maxFD; i++)
  572. {
  573. if ((i!=fd)&&(FD_ISSET(i,&clientList)))
  574. Close(i);
  575. }
  576. return(Close(fd)); // close the master fd last
  577. }
  578. //
  579. // For clients this is used to give up ownership of a socket.
  580. // Often used so the destructor won't call close on a socket.
  581. //
  582. void TCP::DisownSocket(void)
  583. {
  584. if (mode==CLIENT)
  585. {
  586. fd=-1;
  587. connectionState=CLOSED;
  588. }
  589. }
  590. // for a server 0 = master FD, or a client FD can be passed in
  591. // for a client the whichFD argument is ignored completely
  592. sint32 TCP::Close(sint32 whichFD)
  593. {
  594. int i;
  595. if (mode==CLIENT)
  596. {
  597. connectionState=CLOSED;
  598. if(fd != -1)
  599. {
  600. sint32 retval = closesocket(fd);
  601. fd = -1;
  602. return retval;
  603. }
  604. }
  605. else if (mode==SERVER)
  606. {
  607. if (whichFD==0)
  608. {
  609. if (shutdown(fd,2)==0)
  610. return(closesocket(fd));
  611. else
  612. return(-1);
  613. }
  614. else if ((whichFD<=maxFD) && (FD_ISSET(whichFD,&clientList)))
  615. {
  616. if (whichFD==maxFD) // make sure maxFD is still correct
  617. {
  618. for (i=maxFD; i>=0; i--)
  619. if (FD_ISSET(i,&clientList))
  620. {
  621. maxFD=i;
  622. break;
  623. }
  624. }
  625. FD_CLR((uint32)whichFD,&clientList);
  626. clientCount--;
  627. return(closesocket(whichFD));
  628. }
  629. }
  630. return(-1);
  631. }
  632. // if 'sec' AND 'usec' are -1 then this will sleep until
  633. // there is socket activity
  634. int TCP::Wait(sint32 sec,sint32 usec,fd_set &returnSet,sint32 whichFD)
  635. {
  636. fd_set inputSet;
  637. FD_ZERO(&inputSet);
  638. if (mode==SERVER)
  639. {
  640. if (whichFD==0)
  641. {
  642. inputSet=clientList;
  643. if (fd > 0)
  644. FD_SET(fd,&inputSet);
  645. }
  646. else if (whichFD > 0)
  647. FD_SET(whichFD,&inputSet);
  648. }
  649. else if (mode==CLIENT)
  650. {
  651. if (whichFD==0)
  652. whichFD=fd;
  653. if (whichFD > 0)
  654. FD_SET(whichFD,&inputSet);
  655. }
  656. return(Wait(sec,usec,inputSet,returnSet));
  657. }
  658. int TCP::Wait(sint32 sec,sint32 usec,fd_set &givenSet,fd_set &returnSet)
  659. {
  660. Wtime timeout;
  661. Wtime timenow;
  662. Wtime timethen;
  663. fd_set backupSet;
  664. int retval=0,done,givenMax;
  665. bit8 noTimeout=FALSE;
  666. timeval tv;
  667. returnSet=givenSet;
  668. backupSet=returnSet;
  669. if ((sec==-1)&&(usec==-1))
  670. noTimeout=TRUE;
  671. timeout.SetSec(sec);
  672. timeout.SetUsec(usec);
  673. timethen+=timeout;
  674. givenMax=maxFD;
  675. for (uint32 i=0; i<(sizeof(fd_set)*8); i++) // i=maxFD+1
  676. {
  677. if (FD_ISSET(i,&givenSet))
  678. givenMax=i;
  679. }
  680. done=0;
  681. while( ! done)
  682. {
  683. if (noTimeout)
  684. retval=select(givenMax+1,&returnSet,0,0,NULL);
  685. else
  686. {
  687. timeout.GetTimevalMT(tv);
  688. retval=select(givenMax+1,&returnSet,0,0,&tv);
  689. }
  690. if (retval>=0)
  691. done=1;
  692. else if ((retval==-1)&&(errno==EINTR)) // in case of signal
  693. {
  694. if (noTimeout==FALSE)
  695. {
  696. timenow.Update();
  697. timeout=timethen-timenow;
  698. }
  699. if ((noTimeout==FALSE)&&(timenow.GetSec()==0)&&(timenow.GetUsec()==0))
  700. done=1;
  701. else
  702. returnSet=backupSet;
  703. }
  704. else // maybe out of memory?
  705. {
  706. done=1;
  707. }
  708. }
  709. return(retval);
  710. }
  711. void TCP::WaitWrite(sint32 whichFD)
  712. {
  713. fd_set backupSet;
  714. int retval=0,done;
  715. fd_set outputSet;
  716. if (whichFD==0)
  717. whichFD=fd;
  718. if (whichFD==-1)
  719. return;
  720. FD_ZERO(&outputSet);
  721. FD_SET(whichFD,&outputSet);
  722. backupSet=outputSet;
  723. done=0;
  724. while( ! done)
  725. {
  726. retval=select(maxFD+1,0,&outputSet,0,NULL);
  727. if (retval>=0)
  728. done=1;
  729. else if ((retval==-1)&&(errno==EINTR)) // in case of signal
  730. outputSet=backupSet;
  731. else // maybe out of memory?
  732. done=1;
  733. }
  734. }
  735. // Can a FD be written to?
  736. bit8 TCP::CanWrite(sint32 whichFD)
  737. {
  738. int retval=0;
  739. fd_set outputSet;
  740. Wtime timeout;
  741. timeval tv;
  742. timeout.SetSec(0);
  743. timeout.SetUsec(0);
  744. if (whichFD==0)
  745. whichFD=fd;
  746. FD_ZERO(&outputSet);
  747. FD_SET(whichFD,&outputSet);
  748. timeout.GetTimevalMT(tv);
  749. retval=select(whichFD+1,0,&outputSet,0,&tv);
  750. if (retval>0)
  751. return(TRUE);
  752. else
  753. return(FALSE);
  754. }
  755. bit8 TCP::Bind(char *Host,uint16 port,bit8 reuseAddr)
  756. {
  757. char hostName[100];
  758. struct hostent *hostStruct;
  759. struct in_addr *hostNode;
  760. if (isdigit(Host[0]))
  761. return ( Bind( ntohl(inet_addr(Host)), port,reuseAddr) );
  762. strcpy(hostName, Host);
  763. hostStruct = gethostbyname(Host);
  764. if (hostStruct == NULL)
  765. return (0);
  766. hostNode = (struct in_addr *) hostStruct->h_addr;
  767. return ( Bind(ntohl(hostNode->s_addr),port,reuseAddr) );
  768. }
  769. // You must call bind, implicit binding is for sissies
  770. // Well... you can get implicit binding if you pass 0 for either arg
  771. bit8 TCP::Bind(uint32 IP,uint16 Port,bit8 reuseAddr)
  772. {
  773. int retval;
  774. int status;
  775. IP=htonl(IP);
  776. Port=htons(Port);
  777. addr.sin_family=AF_INET;
  778. addr.sin_port=Port;
  779. addr.sin_addr.s_addr=IP;
  780. fd=socket(AF_INET,SOCK_STREAM,DEFAULT_PROTOCOL);
  781. if (fd==-1)
  782. return(FALSE);
  783. retval=SetBlocking(FALSE,fd);
  784. if (retval==-1)
  785. ERRMSG("Couldn't set nonblocking mode!");
  786. if (reuseAddr==TRUE)
  787. {
  788. uint32 opval;
  789. #ifdef SO_REUSEPORT
  790. /****************** this may make the socket get garbage data??
  791. opval=1;
  792. retval=setsockopt(fd,SOL_SOCKET,SO_REUSEPORT,(char *)&opval,sizeof(opval));
  793. if (retval!=0)
  794. fprintf(stderr,"Could not set socket to SO_REUSEPORT\n");
  795. **********************/
  796. #endif
  797. #ifdef SO_REUSEADDR
  798. opval=1;
  799. retval=setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char *)&opval,sizeof(opval));
  800. if (retval!=0)
  801. fprintf(stderr,"Could not set socket to SO_REUSEADDR\n");
  802. #endif
  803. }
  804. retval=bind(fd,(struct sockaddr *)&addr,sizeof(addr));
  805. #ifdef _WINDOWS
  806. if (retval==SOCKET_ERROR)
  807. retval=-1;
  808. #endif
  809. if (retval==-1)
  810. {
  811. status=GetStatus();
  812. DBGMSG("Bind failure (" << status << ") IP "<< IP <<" PORT "<< ntohs(Port));
  813. return(FALSE);
  814. }
  815. myIP=IP;
  816. myPort=Port;
  817. maxFD=fd;
  818. if (mode==SERVER)
  819. listen(fd,64); //Solaris needs lots of listen slots for some reason
  820. return(TRUE);
  821. }
  822. // This is only for clients
  823. bit8 TCP::Connect(char *Host,uint16 port)
  824. {
  825. char hostName[100];
  826. struct hostent *hostStruct;
  827. struct in_addr *hostNode;
  828. if (isdigit(Host[0]))
  829. return ( Connect( ntohl(inet_addr(Host)), port) );
  830. strcpy(hostName, Host);
  831. hostStruct = gethostbyname(Host);
  832. if (hostStruct == NULL)
  833. {ERRMSG("Can't resolve host");return (0);}
  834. hostNode = (struct in_addr *) hostStruct->h_addr;
  835. return ( Connect(ntohl(hostNode->s_addr),port) );
  836. }
  837. bit8 TCP::Connect(uint32 IP,uint16 Port)
  838. {
  839. int tries,result;
  840. struct timeval sleep_time;
  841. struct sockaddr_in serverAddr;
  842. int status;
  843. IP=htonl(IP);
  844. Port=htons(Port);
  845. serverAddr.sin_family=AF_INET;
  846. serverAddr.sin_port=Port;
  847. serverAddr.sin_addr.s_addr=IP;
  848. if (mode!=CLIENT)
  849. {ERRMSG("Can't connect in server mode");return(FALSE);}
  850. tries=0;
  851. result=-1;
  852. // try 10 connects with a greater and greater sleep time after each one
  853. // this can go on for upto 5.4 seconds
  854. while ((tries < 10) && (result == -1))
  855. {
  856. ClearStatus();
  857. result = connect(fd,(struct sockaddr *)&serverAddr, sizeof(serverAddr));
  858. status=GetStatus();
  859. #ifdef _WINDOWS
  860. if (result==SOCKET_ERROR)
  861. result=-1;
  862. #endif
  863. if ((status == ISCONN) && (result == -1))
  864. {
  865. result = 0;
  866. }
  867. if (result == -1)
  868. {
  869. if ((status!=INPROGRESS)&&(status!=ALREADY)&&(status!=AGAIN)&&
  870. (status!=WOULDBLOCK))
  871. {
  872. Close();
  873. Bind(myIP,myPort);
  874. }
  875. tries++;
  876. sleep_time.tv_sec = 0;
  877. sleep_time.tv_usec = (100000*(tries+1));
  878. #ifdef WIN32
  879. Sleep((sleep_time.tv_usec)/1000);
  880. #else
  881. select(0, 0, 0, 0, &sleep_time);
  882. #endif
  883. }
  884. }
  885. if (result == -1)
  886. {
  887. return(FALSE);
  888. }
  889. connectionState=CONNECTED;
  890. return (TRUE);
  891. }
  892. // Asynchronous Connection
  893. bit8 TCP::ConnectAsync(char *Host,uint16 port)
  894. {
  895. char hostName[100];
  896. struct hostent *hostStruct;
  897. struct in_addr *hostNode;
  898. if (isdigit(Host[0]))
  899. return ( ConnectAsync( ntohl(inet_addr(Host)), port) );
  900. strcpy(hostName, Host);
  901. hostStruct = gethostbyname(Host);
  902. if (hostStruct == NULL)
  903. return (0);
  904. hostNode = (struct in_addr *) hostStruct->h_addr;
  905. return ( ConnectAsync(ntohl(hostNode->s_addr),port) );
  906. }
  907. // Asynchronous Connection
  908. bit8 TCP::ConnectAsync(uint32 IP,uint16 Port)
  909. {
  910. int result;
  911. struct sockaddr_in serverAddr;
  912. int status,connectErrno;
  913. int retval;
  914. IP=htonl(IP);
  915. Port=htons(Port);
  916. serverAddr.sin_family=AF_INET;
  917. serverAddr.sin_port=Port;
  918. serverAddr.sin_addr.s_addr=IP;
  919. if (mode!=CLIENT)
  920. return(FALSE);
  921. result=-1;
  922. if (connectionState==CONNECTING)
  923. {
  924. if (IsConnected(fd))
  925. {
  926. DBGMSG("CONNECTION COMPLETE at point 1");
  927. connectionState=CONNECTED;
  928. return(TRUE);
  929. }
  930. else
  931. return(TRUE); // Still trying
  932. }
  933. ClearStatus();
  934. result = connect(fd,(struct sockaddr *)&serverAddr, sizeof(serverAddr));
  935. connectErrno=errno;
  936. status=GetStatus();
  937. #ifdef _WINDOWS
  938. if (result==SOCKET_ERROR)
  939. {
  940. DBGMSG("Socket error 1 " << status);
  941. result=-1;
  942. }
  943. #endif
  944. // If we have a bogus FD, try again after closing and re-binding
  945. if ((result==-1)&&((status==BADF)||(status==NOTSOCK)||(status==INVAL)))
  946. {
  947. Close();
  948. retval=Bind(myIP,myPort);
  949. DBGMSG("BIND = "<<retval);
  950. ClearStatus();
  951. result = connect(fd,(struct sockaddr *)&serverAddr, sizeof(serverAddr));
  952. status=GetStatus();
  953. #ifdef _WINDOWS
  954. if (result==SOCKET_ERROR)
  955. {
  956. DBGMSG("Socket error 2 " << status);
  957. result=-1;
  958. }
  959. #endif
  960. }
  961. if (result==-1)
  962. {
  963. if ((status==ISCONN)||(status==INPROGRESS)||(status==ALREADY)||
  964. (status==WOULDBLOCK))
  965. {
  966. connectionState=CONNECTING;
  967. return(TRUE); // The socket's trying to connect
  968. }
  969. else // Must be a "real" problem
  970. {
  971. Close();
  972. DBGMSG("Fail " << connectErrno << " " << status);
  973. connectionState=CLOSED;
  974. return(FALSE);
  975. }
  976. }
  977. //printf("Connected for real\n");
  978. connectionState=CONNECTED;
  979. return(TRUE);
  980. }
  981. void TCP::ClearStatus(void)
  982. {
  983. #ifndef _WINDOWS
  984. errno=0;
  985. #endif
  986. }
  987. int TCP::GetStatus(void)
  988. {
  989. #ifdef _WINDOWS
  990. int status=WSAGetLastError();
  991. if (status==0) return(OK);
  992. else if (status==WSAEINTR) return(INTR);
  993. else if (status==WSAEINPROGRESS) return(INPROGRESS);
  994. else if (status==WSAECONNREFUSED) return(CONNREFUSED);
  995. else if (status==WSAEINVAL) return(INVAL);
  996. else if (status==WSAEISCONN) return(ISCONN);
  997. else if (status==WSAENOTSOCK) return(NOTSOCK);
  998. else if (status==WSAETIMEDOUT) return(TIMEDOUT);
  999. else if (status==WSAEALREADY) return(ALREADY);
  1000. else if (status==WSAEWOULDBLOCK) return(WOULDBLOCK);
  1001. else if (status==WSAEBADF) return(BADF);
  1002. else return(UNKNOWN);
  1003. #else
  1004. int status=errno;
  1005. if (status==0) return(OK);
  1006. else if (status==EINTR) return(INTR);
  1007. else if (status==EINPROGRESS) return(INPROGRESS);
  1008. else if (status==ECONNREFUSED) return(CONNREFUSED);
  1009. else if (status==EINVAL) return(INVAL);
  1010. else if (status==EISCONN) return(ISCONN);
  1011. else if (status==ENOTSOCK) return(NOTSOCK);
  1012. else if (status==ETIMEDOUT) return(TIMEDOUT);
  1013. else if (status==EALREADY) return(ALREADY);
  1014. else if (status==EAGAIN) return(AGAIN);
  1015. else if (status==EWOULDBLOCK) return(WOULDBLOCK);
  1016. else if (status==EBADF) return(BADF);
  1017. else return(UNKNOWN);
  1018. #endif
  1019. }
  1020. // this is only for servers
  1021. sint32 TCP::GetConnection(void)
  1022. {
  1023. if (mode!=SERVER)
  1024. return(-1);
  1025. sint32 clientFD;
  1026. struct sockaddr_in clientAddr;
  1027. int addrlen=sizeof(clientAddr);
  1028. clientFD=accept(fd,(struct sockaddr *)&clientAddr,&addrlen);
  1029. if (clientFD!=-1)
  1030. {
  1031. if (clientFD>maxFD)
  1032. maxFD=clientFD;
  1033. FD_SET(clientFD,&clientList);
  1034. clientCount++;
  1035. }
  1036. return(clientFD);
  1037. }
  1038. sint32 TCP::GetConnection(struct sockaddr *clientAddr)
  1039. {
  1040. if (mode!=SERVER)
  1041. return(-1);
  1042. sint32 clientFD;
  1043. int addrlen=sizeof(struct sockaddr);
  1044. clientFD=accept(fd,(struct sockaddr *)clientAddr,&addrlen);
  1045. if (clientFD!=-1)
  1046. {
  1047. if (clientFD>maxFD)
  1048. maxFD=clientFD;
  1049. FD_SET(clientFD,&clientList);
  1050. clientCount++;
  1051. }
  1052. return(clientFD);
  1053. }