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

/libretroshare/src/tcponudp/tou.cc

https://gitlab.com/cave/RetroShare
C++ | 664 lines | 466 code | 103 blank | 95 comment | 66 complexity | 4929c6c3bf46a5f54a6daa8c41827e89 MD5 | raw file
Possible License(s): 0BSD, GPL-2.0
  1. /*
  2. * "$Id: tou.cc,v 1.7 2007-02-18 21:46:50 rmf24 Exp $"
  3. *
  4. * TCP-on-UDP (tou) network interface for RetroShare.
  5. *
  6. * Copyright 2004-2006 by Robert Fernie.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Library General Public
  10. * License Version 2 as published by the Free Software Foundation.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  20. * USA.
  21. *
  22. * Please report all bugs and problems to "retroshare@lunamutt.com".
  23. *
  24. */
  25. #include "tou.h"
  26. static const int kInitStreamTable = 5;
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <time.h>
  30. #include "udp/udpstack.h"
  31. #include "tcpstream.h"
  32. #include <vector>
  33. #include <iostream>
  34. #include <errno.h>
  35. #define DEBUG_TOU_INTERFACE 1
  36. struct TcpOnUdp_t
  37. {
  38. int tou_fd;
  39. int lasterrno;
  40. TcpStream *tcp;
  41. UdpSubReceiver *udpsr;
  42. int udptype;
  43. bool idle;
  44. };
  45. typedef struct TcpOnUdp_t TcpOnUdp;
  46. static RsMutex touMutex("touMutex");
  47. // Mutex is used to control addition / removals from tou_streams.
  48. // Lookup should be okay - as long as you stick to your allocated ID!
  49. static std::vector<TcpOnUdp *> tou_streams;
  50. static int tou_inited = 0;
  51. #include "tcponudp/udppeer.h"
  52. #include "tcponudp/udprelay.h"
  53. static UdpSubReceiver *udpSR[MAX_TOU_RECEIVERS] = {NULL};
  54. static uint32_t udpType[MAX_TOU_RECEIVERS] = { 0 };
  55. static uint32_t noUdpSR = 0;
  56. /* tou_init
  57. *
  58. * Modified to accept a number of UdpSubRecievers!
  59. * these can be linked to arbitary UdpStacks.
  60. * (removed all UdpStack references here!)
  61. *
  62. * Unfortunately, the UdpSubReceivers have different initialisation for starting a connection.
  63. * So the TOU interface has to accomodate this.
  64. *
  65. */
  66. /* tou_init - opens the udp port (universal bind) */
  67. int tou_init(void **in_udpsubrecvs, int *type, int number)
  68. {
  69. RsStackMutex stack(touMutex); /***** LOCKED ******/
  70. UdpSubReceiver **usrArray = (UdpSubReceiver **) in_udpsubrecvs;
  71. if (number > MAX_TOU_RECEIVERS)
  72. {
  73. std::cerr << "tou_init() Invalid number of receivers";
  74. std::cerr << std::endl;
  75. return 0;
  76. }
  77. if (tou_inited)
  78. {
  79. return 1;
  80. }
  81. noUdpSR = number;
  82. uint32_t i;
  83. for(i = 0; i < noUdpSR; i++)
  84. {
  85. udpSR[i] = usrArray[i];
  86. udpType[i] = type[i];
  87. }
  88. tou_streams.resize(kInitStreamTable);
  89. tou_inited = 1;
  90. return 1;
  91. }
  92. /* open - allocates a sockfd, and checks that the type is okay */
  93. int tou_socket(uint32_t recvIdx, uint32_t type, int /*protocol*/)
  94. {
  95. RsStackMutex stack(touMutex); /***** LOCKED ******/
  96. if (!tou_inited)
  97. {
  98. return -1;
  99. }
  100. if (recvIdx >= noUdpSR)
  101. {
  102. std::cerr << "tou_socket() ERROR recvIdx greater than #receivers";
  103. std::cerr << std::endl;
  104. return -1;
  105. }
  106. /* check that the index matches the type */
  107. UdpSubReceiver *recver = udpSR[recvIdx];
  108. uint32_t recverType = udpType[recvIdx];
  109. if (recverType != type)
  110. {
  111. std::cerr << "tou_socket() ERROR type doesn't match expected type";
  112. std::cerr << std::endl;
  113. return -1;
  114. }
  115. for(unsigned int i = 1; i < tou_streams.size(); i++)
  116. {
  117. if (tou_streams[i] == NULL)
  118. {
  119. tou_streams[i] = new TcpOnUdp();
  120. tou_streams[i] -> tou_fd = i;
  121. tou_streams[i] -> tcp = NULL;
  122. tou_streams[i] -> udpsr = recver;
  123. tou_streams[i] -> udptype = recverType;
  124. return i;
  125. }
  126. }
  127. TcpOnUdp *tou = new TcpOnUdp();
  128. tou_streams.push_back(tou);
  129. if (tou == tou_streams[tou_streams.size() -1])
  130. {
  131. tou -> tou_fd = tou_streams.size() -1;
  132. tou -> tcp = NULL;
  133. tou -> udpsr = recver;
  134. tou -> udptype = recverType;
  135. return tou->tou_fd;
  136. }
  137. tou -> lasterrno = EUSERS;
  138. return -1;
  139. }
  140. bool tou_stream_check(int sockfd)
  141. {
  142. if (sockfd < 0)
  143. {
  144. std::cerr << "tou_stream_check() ERROR sockfd < 0";
  145. std::cerr << std::endl;
  146. return false;
  147. }
  148. if (tou_streams[sockfd] == NULL)
  149. {
  150. std::cerr << "tou_stream_check() ERROR tou_streams[sockfd] == NULL";
  151. std::cerr << std::endl;
  152. return false;
  153. }
  154. return true;
  155. }
  156. /* bind - opens the udp port */
  157. int tou_bind(int sockfd, const struct sockaddr * /* my_addr */, socklen_t /* addrlen */ )
  158. {
  159. if (!tou_stream_check(sockfd))
  160. {
  161. return -1;
  162. }
  163. TcpOnUdp *tous = tou_streams[sockfd];
  164. /* this now always returns an error! */
  165. tous -> lasterrno = EADDRINUSE;
  166. return -1;
  167. }
  168. /* records peers address, and sends syn pkt
  169. * the timeout is very slow initially - to give
  170. * the peer a chance to startup
  171. *
  172. * - like a tcp/ip connection, the connect
  173. * will return -1 EAGAIN, until connection complete.
  174. * - always non blocking.
  175. */
  176. int tou_connect(int sockfd, const struct sockaddr *serv_addr,
  177. socklen_t addrlen, uint32_t conn_period)
  178. {
  179. if (!tou_stream_check(sockfd))
  180. {
  181. return -1;
  182. }
  183. TcpOnUdp *tous = tou_streams[sockfd];
  184. if (addrlen < sizeof(struct sockaddr_in))
  185. {
  186. std::cerr << "tou_connect() ERROR invalid size of sockaddr";
  187. std::cerr << std::endl;
  188. tous -> lasterrno = EINVAL;
  189. return -1;
  190. }
  191. // only IPv4 for the moment.
  192. const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr;
  193. if (ss_addr->ss_family != AF_INET)
  194. {
  195. std::cerr << "tou_connect() ERROR not ipv4";
  196. std::cerr << std::endl;
  197. tous -> lasterrno = EINVAL;
  198. return -1;
  199. }
  200. /* enforce that the udptype is correct */
  201. if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER)
  202. {
  203. std::cerr << "tou_connect() ERROR connect method invalid for udptype";
  204. std::cerr << std::endl;
  205. tous -> lasterrno = EINVAL;
  206. return -1;
  207. }
  208. #ifdef TOU_DYNAMIC_CAST_CHECK
  209. /* extra checking -> for testing purposes (dynamic cast) */
  210. UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
  211. if (!upr)
  212. {
  213. std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver";
  214. std::cerr << std::endl;
  215. tous -> lasterrno = EINVAL;
  216. return -1;
  217. }
  218. #else
  219. UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
  220. #endif
  221. /* create a TCP stream to connect with. */
  222. if (!tous->tcp)
  223. {
  224. tous->tcp = new TcpStream(tous->udpsr);
  225. upr->addUdpPeer(tous->tcp,
  226. *((const struct sockaddr_in *) serv_addr));
  227. }
  228. tous->tcp->connect(*(const struct sockaddr_in *) serv_addr, conn_period);
  229. tous->tcp->tick();
  230. if (tous->tcp->isConnected())
  231. {
  232. return 0;
  233. }
  234. tous -> lasterrno = EINPROGRESS;
  235. return -1;
  236. }
  237. /* is this ever used? should it be depreciated? */
  238. int tou_listenfor(int sockfd, const struct sockaddr *serv_addr,
  239. socklen_t addrlen)
  240. {
  241. if (!tou_stream_check(sockfd))
  242. {
  243. return -1;
  244. }
  245. TcpOnUdp *tous = tou_streams[sockfd];
  246. if (addrlen < sizeof(struct sockaddr_in))
  247. {
  248. std::cerr << "tou_listenfor() ERROR invalid size of sockaddr";
  249. std::cerr << std::endl;
  250. tous -> lasterrno = EINVAL;
  251. return -1;
  252. }
  253. // only IPv4 for the moment.
  254. const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) serv_addr;
  255. if (ss_addr->ss_family != AF_INET)
  256. {
  257. std::cerr << "tou_listenfor() ERROR not ipv4";
  258. std::cerr << std::endl;
  259. tous -> lasterrno = EINVAL;
  260. return -1;
  261. }
  262. /* enforce that the udptype is correct */
  263. if (tous -> udptype != TOU_RECEIVER_TYPE_UDPPEER)
  264. {
  265. std::cerr << "tou_connect() ERROR connect method invalid for udptype";
  266. std::cerr << std::endl;
  267. tous -> lasterrno = EINVAL;
  268. return -1;
  269. }
  270. #ifdef TOU_DYNAMIC_CAST_CHECK
  271. /* extra checking -> for testing purposes (dynamic cast) */
  272. UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
  273. if (!upr)
  274. {
  275. std::cerr << "tou_connect() ERROR cannot convert type to UdpPeerReceiver";
  276. std::cerr << std::endl;
  277. tous -> lasterrno = EINVAL;
  278. return -1;
  279. }
  280. #else
  281. UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
  282. #endif
  283. /* create a TCP stream to connect with. */
  284. if (!tous->tcp)
  285. {
  286. tous->tcp = new TcpStream(tous->udpsr);
  287. upr->addUdpPeer(tous->tcp,
  288. *((const struct sockaddr_in *) serv_addr));
  289. }
  290. tous->tcp->listenfor(*((struct sockaddr_in *) serv_addr));
  291. tous->tcp->tick();
  292. return 0;
  293. }
  294. int tou_listen(int /* sockfd */ , int /* backlog */ )
  295. {
  296. return 1;
  297. }
  298. /*
  299. * This is the alternative RELAY connection.
  300. *
  301. * User needs to provide 3 ip addresses.
  302. * These addresses should have been provided by the RELAY negogiation
  303. * a) own ip:port
  304. * b) proxy ip:port
  305. * c) dest ip:port
  306. *
  307. * The reset of the startup is similar to other TOU connections.
  308. * As this is likely to be run over an established UDP connection,
  309. * there is little need for a big connection period.
  310. *
  311. * - like a tcp/ip connection, the connect
  312. * will return -1 EAGAIN, until connection complete.
  313. * - always non blocking.
  314. */
  315. #define DEFAULT_RELAY_CONN_PERIOD 1
  316. int tou_connect_via_relay(int sockfd,
  317. const struct sockaddr_in *own_addr,
  318. const struct sockaddr_in *proxy_addr,
  319. const struct sockaddr_in *dest_addr)
  320. {
  321. if (!tou_stream_check(sockfd))
  322. {
  323. return -1;
  324. }
  325. TcpOnUdp *tous = tou_streams[sockfd];
  326. /* enforce that the udptype is correct */
  327. if (tous -> udptype != TOU_RECEIVER_TYPE_UDPRELAY)
  328. {
  329. std::cerr << "tou_connect() ERROR connect method invalid for udptype";
  330. std::cerr << std::endl;
  331. tous -> lasterrno = EINVAL;
  332. return -1;
  333. }
  334. #ifdef TOU_DYNAMIC_CAST_CHECK
  335. /* extra checking -> for testing purposes (dynamic cast) */
  336. UdpRelayReceiver *urr = dynamic_cast<UdpRelayReceiver *>(tous->udpsr);
  337. if (!urr)
  338. {
  339. std::cerr << "tou_connect() ERROR cannot convert type to UdpRelayReceiver";
  340. std::cerr << std::endl;
  341. tous -> lasterrno = EINVAL;
  342. return -1;
  343. }
  344. #else
  345. UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr);
  346. #endif
  347. /* create a TCP stream to connect with. */
  348. if (!tous->tcp)
  349. {
  350. tous->tcp = new TcpStream(tous->udpsr);
  351. UdpRelayAddrSet addrSet(own_addr, dest_addr);
  352. urr->addUdpPeer(tous->tcp, &addrSet, proxy_addr);
  353. }
  354. /* We Point it at the Destination Address.
  355. * The UdpRelayReceiver wraps and re-directs the packets to the proxy
  356. */
  357. tous->tcp->connect(*dest_addr, DEFAULT_RELAY_CONN_PERIOD);
  358. tous->tcp->tick();
  359. if (tous->tcp->isConnected())
  360. {
  361. return 0;
  362. }
  363. tous -> lasterrno = EINPROGRESS;
  364. return -1;
  365. }
  366. /* slightly different - returns sockfd on connection */
  367. int tou_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
  368. {
  369. if (!tou_stream_check(sockfd))
  370. {
  371. return -1;
  372. }
  373. TcpOnUdp *tous = tou_streams[sockfd];
  374. if (*addrlen < sizeof(struct sockaddr_in))
  375. {
  376. std::cerr << "tou_accept() ERROR invalid size of sockaddr";
  377. std::cerr << std::endl;
  378. tous -> lasterrno = EINVAL;
  379. return -1;
  380. }
  381. // only IPv4 for the moment.
  382. const struct sockaddr_storage *ss_addr = (struct sockaddr_storage *) addr;
  383. if (ss_addr->ss_family != AF_INET)
  384. {
  385. std::cerr << "tou_accept() ERROR not ipv4";
  386. std::cerr << std::endl;
  387. tous -> lasterrno = EINVAL;
  388. return -1;
  389. }
  390. //tous->tcp->connect();
  391. tous->tcp->tick();
  392. if (tous->tcp->isConnected())
  393. {
  394. // should get remote address
  395. tous->tcp->getRemoteAddress(*((struct sockaddr_in *) addr));
  396. return sockfd;
  397. }
  398. tous -> lasterrno = EAGAIN;
  399. return -1;
  400. }
  401. int tou_connected(int sockfd)
  402. {
  403. if (!tou_stream_check(sockfd))
  404. {
  405. return -1;
  406. }
  407. TcpOnUdp *tous = tou_streams[sockfd];
  408. tous->tcp->tick();
  409. return (tous->tcp->TcpState() == 4);
  410. }
  411. /* standard stream read/write non-blocking of course
  412. */
  413. ssize_t tou_read(int sockfd, void *buf, size_t count)
  414. {
  415. if (!tou_stream_check(sockfd))
  416. {
  417. return -1;
  418. }
  419. TcpOnUdp *tous = tou_streams[sockfd];
  420. tous->tcp->tick();
  421. int err = tous->tcp->read((char *) buf, count);
  422. if (err < 0)
  423. {
  424. tous->lasterrno = tous->tcp->TcpErrorState();
  425. return -1;
  426. }
  427. return err;
  428. }
  429. ssize_t tou_write(int sockfd, const void *buf, size_t count)
  430. {
  431. if (!tou_stream_check(sockfd))
  432. {
  433. return -1;
  434. }
  435. TcpOnUdp *tous = tou_streams[sockfd];
  436. int err = tous->tcp->write((char *) buf, count);
  437. if (err < 0)
  438. {
  439. tous->lasterrno = tous->tcp->TcpErrorState();
  440. tous->tcp->tick();
  441. return -1;
  442. }
  443. tous->tcp->tick();
  444. return err;
  445. }
  446. /* check stream */
  447. int tou_maxread(int sockfd)
  448. {
  449. if (!tou_stream_check(sockfd))
  450. {
  451. return -1;
  452. }
  453. TcpOnUdp *tous = tou_streams[sockfd];
  454. tous->tcp->tick();
  455. int ret = tous->tcp->read_pending();
  456. if (ret < 0)
  457. {
  458. tous->lasterrno = tous->tcp->TcpErrorState();
  459. return 0; // error detected next time.
  460. }
  461. return ret;
  462. }
  463. int tou_maxwrite(int sockfd)
  464. {
  465. if (!tou_stream_check(sockfd))
  466. {
  467. return -1;
  468. }
  469. TcpOnUdp *tous = tou_streams[sockfd];
  470. tous->tcp->tick();
  471. int ret = tous->tcp->write_allowed();
  472. if (ret < 0)
  473. {
  474. tous->lasterrno = tous->tcp->TcpErrorState();
  475. return 0; // error detected next time?
  476. }
  477. return ret;
  478. }
  479. /* close down the tcp over udp connection */
  480. int tou_close(int sockfd)
  481. {
  482. TcpOnUdp *tous = NULL;
  483. {
  484. RsStackMutex stack(touMutex); /***** LOCKED ******/
  485. if (!tou_stream_check(sockfd))
  486. {
  487. return -1;
  488. }
  489. tous = tou_streams[sockfd];
  490. tou_streams[sockfd] = NULL;
  491. }
  492. if (tous->tcp)
  493. {
  494. tous->tcp->tick();
  495. /* shut it down */
  496. tous->tcp->close();
  497. /* now we need to work out which type of receiver we have */
  498. #ifdef TOU_DYNAMIC_CAST_CHECK
  499. /* extra checking -> for testing purposes (dynamic cast) */
  500. UdpRelayReceiver *urr = dynamic_cast<UdpRelayReceiver *>(tous->udpsr);
  501. UdpPeerReceiver *upr = dynamic_cast<UdpPeerReceiver *>(tous->udpsr);
  502. if (urr)
  503. {
  504. urr->removeUdpPeer(tous->tcp);
  505. }
  506. else if (upr)
  507. {
  508. upr->removeUdpPeer(tous->tcp);
  509. }
  510. else
  511. {
  512. /* error */
  513. std::cerr << "tou_close() ERROR unknown udptype";
  514. std::cerr << std::endl;
  515. tous -> lasterrno = EINVAL;
  516. }
  517. #else
  518. if (tous -> udptype == TOU_RECEIVER_TYPE_UDPRELAY)
  519. {
  520. UdpRelayReceiver *urr = (UdpRelayReceiver *) (tous->udpsr);
  521. urr->removeUdpPeer(tous->tcp);
  522. }
  523. else if (tous -> udptype == TOU_RECEIVER_TYPE_UDPPEER)
  524. {
  525. UdpPeerReceiver *upr = (UdpPeerReceiver *) (tous->udpsr);
  526. upr->removeUdpPeer(tous->tcp);
  527. }
  528. else
  529. {
  530. /* error */
  531. std::cerr << "tou_close() ERROR unknown udptype";
  532. std::cerr << std::endl;
  533. tous -> lasterrno = EINVAL;
  534. }
  535. #endif
  536. delete tous->tcp;
  537. tous->tcp = NULL ; // prevents calling
  538. }
  539. delete tous;
  540. return 1;
  541. }
  542. /* get an error number */
  543. int tou_errno(int sockfd)
  544. {
  545. if (!tou_stream_check(sockfd))
  546. {
  547. return ENOTSOCK;
  548. }
  549. TcpOnUdp *tous = tou_streams[sockfd];
  550. return tous->lasterrno;
  551. }
  552. int tou_clear_error(int sockfd)
  553. {
  554. if (!tou_stream_check(sockfd))
  555. {
  556. return -1;
  557. }
  558. TcpOnUdp *tous = tou_streams[sockfd];
  559. tous->lasterrno = 0;
  560. return 0;
  561. }