tcpsock.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH
  3. * Copyright (c) 1993 by Digital Equipment Corporation
  4. * Copyright (c) 1983, 1993 by The Regents of the University of California
  5. *
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. Neither the name of the copyright holders nor the names of
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  30. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  31. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. *
  34. * For additional information see http://www.ethernut.de/
  35. */
  36. /*!
  37. * \file net/tcpsock.c
  38. * \brief TCP socket interface.
  39. *
  40. * \verbatim
  41. * $Id: tcpsock.c 5542 2014-01-10 17:35:18Z olereinhardt $
  42. * \endverbatim
  43. */
  44. #include <cfg/os.h>
  45. #include <cfg/crt.h>
  46. #include <sys/types.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49. #include <errno.h>
  50. #include <sys/atom.h>
  51. #include <sys/heap.h>
  52. #include <sys/thread.h>
  53. #include <sys/event.h>
  54. #include <sys/timer.h>
  55. #include <net/route.h>
  56. #include <netinet/in.h>
  57. #include <netinet/ip.h>
  58. #include <netinet/icmp.h>
  59. #include <netinet/ip_icmp.h>
  60. #include <netinet/ipcsum.h>
  61. #include <sys/socket.h>
  62. #include <netinet/tcp.h>
  63. #include <stdio.h>
  64. #include <io.h>
  65. #include <memdebug.h>
  66. #ifdef NUTDEBUG
  67. #include <net/netdebug.h>
  68. #endif
  69. /*!
  70. * \addtogroup xgTcpSocket
  71. */
  72. /*@{*/
  73. TCPSOCKET *tcpSocketList = 0; /*!< Global linked list of all TCP sockets. */
  74. static uint16_t last_local_port; /* Unassigned local port. */
  75. static uint_fast8_t registered;
  76. void NutTcpDiscardBuffers(TCPSOCKET * sock)
  77. {
  78. NETBUF *nb;
  79. while ((nb = sock->so_rx_buf) != 0) {
  80. sock->so_rx_buf = nb->nb_next;
  81. NutNetBufFree(nb);
  82. }
  83. while ((nb = sock->so_tx_nbq) != 0) {
  84. sock->so_tx_nbq = nb->nb_next;
  85. NutNetBufFree(nb);
  86. }
  87. while ((nb = sock->so_rx_nbq) != 0) {
  88. sock->so_rx_nbq = nb->nb_next;
  89. NutNetBufFree(nb);
  90. }
  91. }
  92. /*!
  93. * \brief Destroy a previously allocated socket.
  94. *
  95. * Release occupied socket memory.
  96. *
  97. * Applications must not call this function. It is automatically called
  98. * by a timer after the socket has been closed by NutTcpCloseSocket().
  99. *
  100. * \param sock Socket descriptor. This pointer must have been
  101. * retrieved by calling NutTcpCreateSocket().
  102. */
  103. void NutTcpDestroySocket(TCPSOCKET * sock)
  104. {
  105. //@@@printf ("[%04X] Calling destroy.\n", (u_short) sock);
  106. /*
  107. * Free all memory occupied by the socket.
  108. */
  109. NutTcpDiscardBuffers(sock);
  110. if (sock->so_devocnt)
  111. {
  112. free(sock->so_devobuf);
  113. sock->so_devocnt = 0;
  114. }
  115. memset(sock, 0, sizeof(TCPSOCKET));
  116. free(sock);
  117. }
  118. /*!
  119. * \brief Find a matching socket.
  120. *
  121. * Loop through all sockets and find a matching connection (preferred)
  122. * or a listening socket.
  123. *
  124. * Applications typically do not call this function.
  125. *
  126. * \param lport Local port number.
  127. * \param rport Remote port number.
  128. * \param raddr Remote IP address in network byte order.
  129. *
  130. * \return Socket descriptor.
  131. */
  132. TCPSOCKET *NutTcpFindSocket(uint16_t lport, uint16_t rport, uint32_t raddr)
  133. {
  134. TCPSOCKET *sp;
  135. TCPSOCKET *sock = 0;
  136. /*
  137. * Try to find an exact match for the remote
  138. * address and port first.
  139. */
  140. for (sp = tcpSocketList; sp; sp = sp->so_next) {
  141. if (sp->so_local_port == lport) {
  142. if (sp->so_remote_addr == raddr && sp->so_remote_port == rport && sp->so_state != TCPS_CLOSED && sp->so_state != TCPS_DESTROY) {
  143. sock = sp;
  144. break;
  145. }
  146. }
  147. }
  148. /*
  149. * If no exact match exists, try a listening socket.
  150. * This part had been totally wrong, because it
  151. * didn't check the local port number and accepted
  152. * incoming requests on any port. Thanks to
  153. * Alejandro Lopez, who pointed this out.
  154. */
  155. if (sock == 0) {
  156. for (sp = tcpSocketList; sp; sp = sp->so_next) {
  157. if (sp->so_state == TCPS_LISTEN && sp->so_local_port == lport) {
  158. sock = sp;
  159. break;
  160. }
  161. }
  162. }
  163. return sock;
  164. }
  165. /*!
  166. * \brief Create a TCP socket.
  167. *
  168. * Allocates a TCPSOCKET structure from heap memory, initializes
  169. * it and returns a pointer to that structure.
  170. *
  171. * The very first call will also start the TCP state machine,
  172. * which is running in a separate thread.
  173. *
  174. * \return Socket descriptor of the newly created TCP socket or
  175. * 0 if there is not enough memory left.
  176. */
  177. TCPSOCKET *NutTcpCreateSocket(void)
  178. {
  179. TCPSOCKET *sock = 0;
  180. if (!registered) {
  181. if (NutRegisterIpHandler(IPPROTO_TCP, NutTcpInput) || NutTcpInitStateMachine()) {
  182. return NULL;
  183. }
  184. registered = 1;
  185. }
  186. if ((sock = calloc(1, sizeof(TCPSOCKET))) != 0) {
  187. sock->so_state = TCPS_CLOSED;
  188. /*
  189. * Initialize the virtual device interface.
  190. */
  191. sock->so_devtype = IFTYP_TCPSOCK;
  192. sock->so_devread = NutTcpDeviceRead;
  193. sock->so_devwrite = NutTcpDeviceWrite;
  194. #ifdef __HARVARD_ARCH__
  195. sock->so_devwrite_P = NutTcpDeviceWrite_P;
  196. #endif
  197. sock->so_devioctl = NutTcpDeviceIOCtl;
  198. sock->so_devselect = NutTcpDeviceSelect;
  199. sock->so_tx_isn = NutGetTickCount(); /* Generate the ISN from the nut_ticks counter */
  200. sock->so_tx_una = sock->so_tx_isn;
  201. sock->so_tx_nxt = sock->so_tx_isn;
  202. sock->so_rx_bsz = sock->so_rx_win = TCP_WINSIZE;
  203. sock->so_mss = TCP_MSS;
  204. sock->so_rtto = 1000; /* Initial retransmission time out */
  205. sock->so_next = tcpSocketList;
  206. sock->so_devobsz = TCP_MSS; /* Default output buffer size is TCP_MSS bytes */
  207. tcpSocketList = sock;
  208. }
  209. return sock;
  210. }
  211. /*!
  212. * \brief Set value of a TCP socket option.
  213. *
  214. * The following values can be set:
  215. *
  216. * - #TCP_MAXSEG Maximum segment size (#uint16_t). Can only be set if
  217. socket is not yet connected.
  218. * - #SO_SNDTIMEO Socket send timeout (#uint32_t).
  219. * - #SO_RCVTIMEO Socket receive timeout (#uint32_t).
  220. * - #SO_SNDBUF Socket output buffer size (#uint16_t).
  221. *
  222. * \param sock Socket descriptor. This pointer must have been
  223. * retrieved by calling NutTcpCreateSocket().
  224. * \param optname Option to set.
  225. * \param optval Pointer to the value.
  226. * \param optlen Length of the value.
  227. * \return 0 on success, -1 otherwise. The specific error code
  228. * can be retrieved by calling NutTcpError().
  229. */
  230. int NutTcpSetSockOpt(TCPSOCKET * sock, int optname, const void *optval, int optlen)
  231. {
  232. int rc = -1;
  233. if (sock == 0)
  234. return -1;
  235. switch (optname) {
  236. case TCP_MAXSEG:
  237. if (optval == 0 || optlen != sizeof(uint16_t))
  238. sock->so_last_error = EINVAL;
  239. else if (sock->so_state != TCPS_CLOSED)
  240. sock->so_last_error = EISCONN;
  241. else {
  242. sock->so_mss = *((uint16_t *) optval);
  243. rc = 0;
  244. }
  245. break;
  246. case SO_RCVBUF:
  247. if (optval == 0 || optlen != sizeof(uint16_t))
  248. sock->so_last_error = EINVAL;
  249. else {
  250. sock->so_rx_bsz = *((uint16_t *) optval);
  251. sock->so_rx_win = sock->so_rx_bsz;
  252. rc = 0;
  253. }
  254. break;
  255. case SO_SNDTIMEO:
  256. if (optval == 0 || optlen != sizeof(uint32_t))
  257. sock->so_last_error = EINVAL;
  258. else {
  259. sock->so_write_to = *((uint32_t *) optval);
  260. rc = 0;
  261. }
  262. break;
  263. case SO_RCVTIMEO:
  264. if (optval == 0 || optlen != sizeof(uint32_t))
  265. sock->so_last_error = EINVAL;
  266. else {
  267. sock->so_read_to = *((uint32_t *) optval);
  268. rc = 0;
  269. }
  270. break;
  271. case SO_SNDBUF:
  272. if (optval == 0 || optlen != sizeof(uint16_t))
  273. sock->so_last_error = EINVAL;
  274. else {
  275. NutTcpDeviceWrite(sock, 0, 0);
  276. sock->so_devobsz = *((uint16_t *) optval);
  277. rc = 0;
  278. }
  279. break;
  280. default:
  281. sock->so_last_error = ENOPROTOOPT;
  282. break;
  283. }
  284. return rc;
  285. }
  286. /*!
  287. * \brief Get a TCP socket option value.
  288. *
  289. * The following values can be set:
  290. *
  291. * - #TCP_MAXSEG Maximum segment size (#uint16_t).
  292. * - #SO_SNDTIMEO Socket send timeout (#uint32_t).
  293. * - #SO_RCVTIMEO Socket receive timeout (#uint32_t).
  294. * - #SO_SNDBUF Socket output buffer size (#uint16_t).
  295. *
  296. * \param sock Socket descriptor. This pointer must have been
  297. * retrieved by calling NutTcpCreateSocket().
  298. * \param optname Option to get.
  299. * \param optval Points to a buffer receiving the value.
  300. * \param optlen Length of the value buffer.
  301. *
  302. * \return 0 on success, -1 otherwise. The specific error code
  303. * can be retrieved by calling NutTcpError().
  304. */
  305. int NutTcpGetSockOpt(TCPSOCKET * sock, int optname, void *optval, int optlen)
  306. {
  307. int rc = -1;
  308. if (sock == 0)
  309. return -1;
  310. switch (optname) {
  311. case TCP_MAXSEG:
  312. if (optval == 0 || optlen != sizeof(uint16_t))
  313. sock->so_last_error = EINVAL;
  314. else {
  315. *((uint16_t *) optval) = sock->so_mss;
  316. rc = 0;
  317. }
  318. break;
  319. case SO_RCVBUF:
  320. if (optval == 0 || optlen != sizeof(uint16_t))
  321. sock->so_last_error = EINVAL;
  322. else {
  323. *((uint16_t *) optval) = sock->so_rx_bsz;
  324. rc = 0;
  325. }
  326. break;
  327. case SO_SNDTIMEO:
  328. if (optval == 0 || optlen != sizeof(uint32_t))
  329. sock->so_last_error = EINVAL;
  330. else {
  331. *((uint32_t *) optval) = sock->so_write_to;
  332. rc = 0;
  333. }
  334. break;
  335. case SO_RCVTIMEO:
  336. if (optval == 0 || optlen != sizeof(uint32_t))
  337. sock->so_last_error = EINVAL;
  338. else {
  339. *((uint32_t *) optval) = sock->so_read_to;
  340. rc = 0;
  341. }
  342. break;
  343. case SO_SNDBUF:
  344. if (optval == 0 || optlen != sizeof(uint16_t))
  345. sock->so_last_error = EINVAL;
  346. else {
  347. *((uint16_t *) optval) = sock->so_devobsz;
  348. rc = 0;
  349. }
  350. break;
  351. default:
  352. sock->so_last_error = ENOPROTOOPT;
  353. break;
  354. }
  355. return rc;
  356. }
  357. /*!
  358. * \brief Connect to a remote socket.
  359. *
  360. * This function tries to establish a connection to the specified
  361. * remote port of the specified remote server. The calling thread
  362. * will be suspended until a connection is successfully established
  363. * or an error occurs.
  364. *
  365. * If a write timeout is set for this socket, the function will return
  366. * an error, if the connection could not be established before the
  367. * timeout. In this case the last error is set to ETIMEOUT.
  368. *
  369. * This function is typically used by TCP client applications.
  370. *
  371. * \param sock Socket descriptor. This pointer must have been
  372. * retrieved by calling NutTcpCreateSocket().
  373. * \param addr IP address of the host to connect (network byte order).
  374. * \param port Port number to connect (host byte order).
  375. *
  376. * \return 0 on success, -1 otherwise. The specific error code
  377. * can be retrieved by calling NutTcpError().
  378. */
  379. int NutTcpConnect(TCPSOCKET * sock, uint32_t addr, uint16_t port)
  380. {
  381. TCPSOCKET *sp;
  382. NUTDEVICE *dev;
  383. uint16_t ticks;
  384. if (sock == 0)
  385. return -1;
  386. /*
  387. * Despite RFC793 we do not allow a passive
  388. * open to become active.
  389. */
  390. if (sock->so_state == TCPS_LISTEN) {
  391. sock->so_last_error = EOPNOTSUPP;
  392. return -1;
  393. } else if (sock->so_state != TCPS_CLOSED) {
  394. sock->so_last_error = EISCONN;
  395. return -1;
  396. }
  397. /*
  398. * Find an unused local port.
  399. */
  400. do {
  401. /* Each time a new socket is created the local port number in incremented
  402. by a more or less randomized value between 1 and 15 (the lowest 4 bit of
  403. NutGetMillis() | 1). The highest two bits are always set to 1.
  404. This way a port range of 49152 to 65535 is used according to the IANA
  405. suggestions for ephemeral port usage.
  406. */
  407. ticks = (uint16_t) NutGetMillis();
  408. if (last_local_port) {
  409. last_local_port += (uint16_t) ((ticks & 0x000F) | 1);
  410. } else {
  411. last_local_port = ticks;
  412. }
  413. last_local_port |= 0xC000;
  414. sp = tcpSocketList;
  415. while (sp) {
  416. /* Thanks to Ralph Mason for fixing the byte order bug. */
  417. if (sp->so_local_port == htons(last_local_port))
  418. break;
  419. sp = sp->so_next;
  420. }
  421. } while (sp);
  422. /*
  423. * OK - we've got a new port. Now fill
  424. * remaining parts of the socket structure.
  425. */
  426. sock->so_local_port = htons(last_local_port);
  427. sock->so_remote_port = htons(port);
  428. sock->so_remote_addr = addr;
  429. /*
  430. * Get local address for this destination.
  431. */
  432. if ((dev = NutIpRouteQuery(addr, 0)) != 0) {
  433. IFNET *nif = dev->dev_icb;
  434. sock->so_local_addr = nif->if_local_ip;
  435. } else {
  436. sock->so_last_error = EHOSTUNREACH;
  437. return -1;
  438. }
  439. /*
  440. * Trigger active open event for the state machine.
  441. * This will suspend the thread until synchronized.
  442. */
  443. return NutTcpStateActiveOpenEvent(sock);
  444. }
  445. /*!
  446. * \brief Wait for incoming connect from a remote socket.
  447. *
  448. * The calling thread will be suspended until until an
  449. * incoming connection request is received.
  450. *
  451. * This function is typically used by TCP server applications.
  452. *
  453. * \param sock Socket descriptor. This pointer must have been
  454. * retrieved by calling NutTcpCreateSocket().
  455. * \param port Port number to listen to (host byte order).
  456. *
  457. * \return 0 on success, -1 otherwise. The specific error code
  458. * can be retrieved by calling NutTcpError().
  459. */
  460. int NutTcpAccept(TCPSOCKET * sock, uint16_t port)
  461. {
  462. sock->so_local_port = htons(port);
  463. return NutTcpStatePassiveOpenEvent(sock);
  464. }
  465. /*!
  466. * \brief Send data on a connected TCP socket.
  467. *
  468. * \param sock Socket descriptor. This pointer must have been
  469. * retrieved by calling NutTcpCreateSocket(). In
  470. * addition a connection must have been established
  471. * by calling NutTcpConnect or NutTcpAccept.
  472. * \param data Pointer to a buffer containing the data to send.
  473. * \param len Number of bytes to be sent.
  474. *
  475. * \return If successful, the number of bytes added to the socket transmit
  476. * buffer. This is limited to the maximum segment size of the
  477. * connection and thus may be less than the specified number of
  478. * bytes to send. The return value -1 indicates a fatal error.
  479. * On time out, a value of 0 is returned.
  480. */
  481. int NutTcpSend(TCPSOCKET * sock, const void *data, int len)
  482. {
  483. uint16_t unacked;
  484. /*
  485. * Check parameters.
  486. */
  487. NutThreadYield();
  488. if (sock == 0)
  489. return -1;
  490. if (data == 0 || len == 0)
  491. return 0;
  492. /*
  493. * Limit the transmission size to our maximum segment size.
  494. */
  495. if (len > sock->so_mss)
  496. len = sock->so_mss;
  497. for (;;) {
  498. /*
  499. * We can only send on an established connection.
  500. */
  501. if (sock->so_state != TCPS_ESTABLISHED) {
  502. sock->so_last_error = ENOTCONN;
  503. return -1;
  504. }
  505. /*
  506. * Limit the size of unacknowledged data to four full segments.
  507. * Also wait for peer's window open wide enough to take all our
  508. * data. This also avoids silly window syndrome on our side.
  509. */
  510. unacked = sock->so_tx_nxt - sock->so_tx_una;
  511. if ((unacked >> 2) < sock->so_mss && len <= sock->so_tx_win - unacked) {
  512. break;
  513. }
  514. if (NutEventWait(&sock->so_tx_tq, sock->so_write_to)) {
  515. return 0;
  516. }
  517. }
  518. /*
  519. * The segment will be automatically retransmitted if not
  520. * acknowledged in time. If this returns an error, it's a
  521. * fatal one.
  522. */
  523. sock->so_tx_flags |= SO_ACK;
  524. if (NutTcpOutput(sock, data, len))
  525. return -1;
  526. return len;
  527. }
  528. /*!
  529. * \brief Receive data on a connected TCP socket.
  530. *
  531. * \param sock Socket descriptor. This pointer must have been
  532. * retrieved by calling NutTcpCreateSocket(). In
  533. * addition a connection must have been established
  534. * by calling NutTcpConnect or NutTcpAccept.
  535. * \param data Pointer to the buffer that receives the data.
  536. * \param size Size of the buffer.
  537. *
  538. * \return If successful, the number of received data bytes
  539. * is returned. This may be less than the specified
  540. * size of the buffer. The return value 0 indicates
  541. * a timeout, while -1 is returned in case of an error
  542. * or broken connection. Call NutTcpError() to determine
  543. * the specific error code.
  544. */
  545. int NutTcpReceive(TCPSOCKET * sock, void *data, int size)
  546. {
  547. int i;
  548. NutThreadYield();
  549. /*
  550. * Check parameters.
  551. */
  552. if (sock == 0)
  553. return -1;
  554. if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT) {
  555. sock->so_last_error = ENOTCONN;
  556. return -1;
  557. }
  558. if (data == 0 || size == 0)
  559. return 0;
  560. /*
  561. * Wait until any data arrived, a timeout occurs
  562. * or the connection terminates.
  563. */
  564. while (sock->so_rx_cnt - sock->so_rd_cnt == 0) {
  565. if (sock->so_state != TCPS_ESTABLISHED) {
  566. sock->so_last_error = ENOTCONN;
  567. return -1;
  568. }
  569. if (NutEventWait(&sock->so_rx_tq, sock->so_read_to))
  570. return 0;
  571. }
  572. if (size > sock->so_rx_cnt - sock->so_rd_cnt)
  573. size = sock->so_rx_cnt - sock->so_rd_cnt;
  574. if (size) {
  575. NETBUF *nb;
  576. uint16_t rd_cnt; /* Bytes read from NETBUF. */
  577. uint16_t nb_cnt; /* Bytes left in NETBUF. */
  578. uint16_t ab_cnt; /* Total bytes in app buffer. */
  579. uint16_t mv_cnt; /* Bytes to move to app buffer. */
  580. rd_cnt = sock->so_rd_cnt;
  581. ab_cnt = 0;
  582. while (ab_cnt < size) {
  583. nb = sock->so_rx_buf;
  584. nb_cnt = nb->nb_ap.sz - rd_cnt;
  585. mv_cnt = size - ab_cnt;
  586. if (mv_cnt > nb_cnt)
  587. mv_cnt = nb_cnt;
  588. memcpy((char *) data + ab_cnt, (char *) (nb->nb_ap.vp) + rd_cnt, mv_cnt);
  589. ab_cnt += mv_cnt;
  590. rd_cnt += mv_cnt;
  591. if (mv_cnt >= nb_cnt) {
  592. sock->so_rx_buf = nb->nb_next;
  593. sock->so_rx_cnt -= rd_cnt;
  594. NutNetBufFree(nb);
  595. sock->so_rx_apc--;
  596. nb = sock->so_rx_buf;
  597. rd_cnt = 0;
  598. }
  599. }
  600. sock->so_rd_cnt = rd_cnt;
  601. /*
  602. * Update our receive window.
  603. */
  604. if (sock->so_state == TCPS_ESTABLISHED) {
  605. i = sock->so_rx_win;
  606. if ((i += size) > sock->so_rx_bsz)
  607. i = sock->so_rx_bsz;
  608. if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
  609. sock->so_rx_win = i;
  610. NutTcpStateWindowEvent(sock);
  611. } else {
  612. sock->so_rx_win = i;
  613. }
  614. }
  615. }
  616. return size;
  617. }
  618. /*!
  619. * \brief Close TCP socket.
  620. *
  621. * Note, that the socket may not be immediately destroyed
  622. * after calling this function. However, the application
  623. * must not use the socket after this call.
  624. *
  625. * \param sock Socket descriptor. This pointer must have been
  626. * retrieved by calling NutTcpCreateSocket().
  627. *
  628. * \return 0 on success, -1 otherwise.
  629. */
  630. int NutTcpCloseSocket(TCPSOCKET * sock)
  631. {
  632. /* Flush buffer first */
  633. //@@@printf ("[%04X] Calling close\n", (u_short) sock);
  634. NutTcpDeviceWrite(sock, 0, 0);
  635. return NutTcpStateCloseEvent(sock);
  636. }
  637. /*!
  638. * \brief Return specific code of the last error.
  639. *
  640. * Possible error codes (net/errno.h) are:
  641. *
  642. * - EWOULDBLOCK: Operation would block
  643. * - EINPROGRESS: Operation now in progress
  644. * - EALREADY: Operation already in progress
  645. * - ENOTSOCK: Socket operation on non-socket
  646. * - EDESTADDRREQ: Destination address required
  647. * - EMSGSIZE: Message too long
  648. * - EPROTOTYPE: Protocol wrong type for socket
  649. * - ENOPROTOOPT: Protocol not available
  650. * - EPROTONOSUPPORT: Protocol not supported
  651. * - ESOCKTNOSUPPORT: Socket type not supported
  652. * - EOPNOTSUPP: Operation not supported on socket
  653. * - EPFNOSUPPORT: Protocol family not supported
  654. * - EAFNOSUPPORT: Address family not supported by protocol family
  655. * - EADDRINUSE: Address already in use
  656. * - EADDRNOTAVAIL: Can't assign requested address
  657. * - ENETDOWN: Network is down
  658. * - ENETUNREACH: Network is unreachable
  659. * - ENETRESET: Network dropped connection on reset
  660. * - ECONNABORTED: Software caused connection abort
  661. * - ECONNRESET: Connection reset by peer
  662. * - ENOBUFS: No buffer space available
  663. * - EISCONN: Socket is already connected
  664. * - ENOTCONN: Socket is not connected
  665. * - ESHUTDOWN: Can't send after socket shutdown
  666. * - ETOOMANYREFS: Too many references: can't splice
  667. * - ETIMEDOUT: Connection timed out
  668. * - ECONNREFUSED: Connection refused
  669. * - ELOOP: Too many levels of symbolic links
  670. * - ENAMETOOLONG: File name too long
  671. * - EHOSTDOWN: Host is down
  672. * - EHOSTUNREACH: No route to host
  673. * - ENOTEMPTY: Directory not empty
  674. *
  675. * \param sock Socket descriptor. This pointer must have been
  676. * retrieved by calling NutTcpCreateSocket().
  677. *
  678. * \note Applications must not call this function to retrieve the
  679. * error code if NutTcpCloseSocket() or NutTcpDestroySocket()
  680. * failed.
  681. *
  682. * \todo Not all error codes are properly set right now. Some socket
  683. * functions return an error without setting an error code.
  684. */
  685. int NutTcpError(TCPSOCKET * sock)
  686. {
  687. if (sock == 0)
  688. return ENOTSOCK;
  689. return sock->so_last_error;
  690. }
  691. /*!
  692. * \brief Read from virtual socket device.
  693. *
  694. * TCP sockets can be used like other Nut/OS devices. This routine
  695. * is part of the virtual socket device driver.
  696. *
  697. * This function is called by the low level input routines of the
  698. * \ref xrCrtLowio "C runtime library", using the _NUTDEVICE::dev_read
  699. * entry.
  700. *
  701. * \param sock Socket descriptor. This pointer must have been
  702. * retrieved by calling NutTcpCreateSocket().
  703. * \param buffer Pointer to the buffer that receives the data.
  704. * \param size Maximum number of bytes to read.
  705. *
  706. * \return The number of bytes read, which may be less than the number
  707. * of bytes specified. A return value of -1 indicates an error,
  708. * while zero is returned in case of a timeout.
  709. */
  710. int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
  711. {
  712. return NutTcpReceive(sock, buffer, size);
  713. }
  714. static int SendBuffer(TCPSOCKET * sock, const void *buffer, int size)
  715. {
  716. int rc;
  717. int bite;
  718. for (rc = 0; rc < size; rc += bite) {
  719. if ((bite = NutTcpSend(sock, (uint8_t *) buffer + rc, size - rc)) <= 0) {
  720. return -1;
  721. }
  722. }
  723. return rc;
  724. }
  725. /*!
  726. * \brief Write to a socket.
  727. *
  728. * TCP sockets can be used like other Nut/OS devices. This routine
  729. * is part of the virtual socket device driver.
  730. *
  731. * This function is called by the low level output routines of the
  732. * \ref xrCrtLowio "C runtime library", using the
  733. * \ref _NUTDEVICE::dev_write entry.
  734. *
  735. * In contrast to NutTcpSend() this routine provides some buffering.
  736. *
  737. * \param sock Socket descriptor. This pointer must have been
  738. * retrieved by calling NutTcpCreateSocket().
  739. * \param buf Pointer to the data to be written.
  740. * \param size Number of bytes to write. If zero, then the output buffer
  741. * will be flushed.
  742. *
  743. * \return The number of bytes written. A return value of -1 indicates
  744. * an error.
  745. *
  746. */
  747. int NutTcpDeviceWrite(TCPSOCKET * sock, const void *buf, int size)
  748. {
  749. int rc;
  750. uint16_t sz;
  751. /* hack alert for ICCAVR */
  752. uint8_t *buffer = (uint8_t*) buf;
  753. /*
  754. * Check parameters.
  755. */
  756. if (sock == 0)
  757. return -1;
  758. if (sock->so_state != TCPS_ESTABLISHED) {
  759. sock->so_last_error = ENOTCONN;
  760. return -1;
  761. }
  762. /* Flush buffer? */
  763. if (size == 0) {
  764. if (sock->so_devocnt) {
  765. if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
  766. free(sock->so_devobuf);
  767. sock->so_devocnt = 0;
  768. return -1;
  769. }
  770. free(sock->so_devobuf);
  771. sock->so_devocnt = 0;
  772. }
  773. return 0;
  774. }
  775. /* If we don't have a buffer so far... */
  776. if (sock->so_devocnt == 0) {
  777. /* If new data block is bigger or equal than buffer size
  778. * send first part of data to NIC and store remaining
  779. * bytes in buffer
  780. */
  781. if ((uint16_t) size >= sock->so_devobsz) {
  782. rc = size % sock->so_devobsz;
  783. if (SendBuffer(sock, buffer, size - rc) < 0)
  784. return -1;
  785. buffer += size - rc;
  786. } else
  787. rc = size;
  788. /* If there are some remainings bytes, allocate buffer
  789. * and store them
  790. */
  791. if (rc) {
  792. if (!(sock->so_devobuf = malloc(sock->so_devobsz)))
  793. return -1;
  794. memcpy(sock->so_devobuf, buffer, rc);
  795. sock->so_devocnt = rc;
  796. }
  797. return size;
  798. }
  799. /* Check if new data fully fits in output buffer */
  800. if (sock->so_devocnt + size < sock->so_devobsz) {
  801. memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
  802. sock->so_devocnt += size;
  803. return size;
  804. }
  805. /* Otherwise store first bytes of new data in buffer and flush
  806. * the buffer
  807. */
  808. sz = sock->so_devobsz - sock->so_devocnt;
  809. memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
  810. buffer += sz;
  811. if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
  812. free(sock->so_devobuf);
  813. sock->so_devocnt = 0;
  814. return -1;
  815. }
  816. /* If remaining data is bigger or equal than buffer size
  817. * send first part of data to NIC and later store remaining
  818. * bytes in buffer
  819. */
  820. sz = size - sz;
  821. if (sz >= sock->so_devobsz) {
  822. rc = sz % sock->so_devobsz;
  823. if (SendBuffer(sock, buffer, sz - rc) < 0) {
  824. free(sock->so_devobuf);
  825. sock->so_devocnt = 0;
  826. return -1;
  827. }
  828. buffer += sz - rc;
  829. } else
  830. rc = sz;
  831. /* If there are some remaining bytes, store them in buffer
  832. */
  833. if (rc)
  834. memcpy(sock->so_devobuf, buffer, rc);
  835. else /* Otherwise free buffer */
  836. free(sock->so_devobuf);
  837. sock->so_devocnt = rc;
  838. return size;
  839. }
  840. /*!
  841. * \brief Write to device.
  842. *
  843. * This function is implemented for CPUs with Harvard Architecture
  844. * only.
  845. *
  846. * TCP sockets can be used like other Nut/OS devices. This routine
  847. * is part of the virtual socket device driver and similar to
  848. * NutTcpDeviceWrite() except that the data is located in program
  849. * memory.
  850. *
  851. * This function is called by the low level output routines of the
  852. * \ref xrCrtLowio "C runtime library", using the
  853. * \ref _NUTDEVICE::dev_write_P entry.
  854. *
  855. * \param sock Socket descriptor. This pointer must have been
  856. * retrieved by calling NutTcpCreateSocket().
  857. * \param buffer Pointer to the data in program space to be written.
  858. * \param size Number of bytes to write.
  859. *
  860. * \warning Inefficient implementation. No buffering has been
  861. * implemented. Thus, each call will result in a separate
  862. * TCP segment.
  863. */
  864. #ifdef __HARVARD_ARCH__
  865. int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
  866. {
  867. int rc;
  868. char *rp = 0;
  869. /*
  870. * Hack alert. Neither do we handle out of memory correctly
  871. * nor do we pass the PGM pointer to lower levels.
  872. */
  873. if (size && (rp = NutHeapAlloc(size)) != 0)
  874. memcpy_P(rp, buffer, size);
  875. rc = NutTcpDeviceWrite(sock, rp, size);
  876. if (rp)
  877. NutHeapFree(rp);
  878. return rc;
  879. }
  880. #endif
  881. /*!
  882. * \brief Driver control function.
  883. *
  884. * Used by the virtual device driver to modify or query device specific
  885. * settings.
  886. *
  887. * \param sock Socket descriptor. This pointer must have been
  888. * retrieved by calling NutTcpCreateSocket().
  889. * \param cmd Requested control function. May be set to one of the
  890. * following constants:
  891. * - \ref IOCTL_GETFILESIZE
  892. * - \ref IOCTL_GETINBUFCOUNT
  893. * - \ref IOCTL_GETOUTBUFCOUNT
  894. *
  895. * \param param Points to a buffer that contains any data required for
  896. * the given control function or receives data from that
  897. * function.
  898. * \return 0 on success, -1 otherwise.
  899. */
  900. int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
  901. {
  902. uint32_t *lvp = (uint32_t *) param;
  903. int rc = 0;
  904. switch (cmd) {
  905. case IOCTL_GETFILESIZE:
  906. case IOCTL_GETINBUFCOUNT:
  907. *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
  908. break;
  909. case IOCTL_GETOUTBUFCOUNT:
  910. *lvp = (sock->so_devocnt);
  911. break;
  912. default:
  913. rc = -1;
  914. }
  915. return rc;
  916. }
  917. #ifndef CRT_DISABLE_SELECT_POLL
  918. /*!
  919. * \brief Callback function called by select routine to check, if read
  920. * or write to this socket would block
  921. * \internal
  922. *
  923. * This function is called by select_scan routine of the C runtime library
  924. * as part of the select() implementation. If select if currently waiting
  925. * on a waitqueue, this function will be called to check the current state
  926. * as soon as the select waitqueues got signalled by the tcp statemachine
  927. *
  928. * \param sock Socket descriptor. This pointer must have been
  929. * retrieved by calling NutTcpCreateSocket().
  930. * \param flags Flags representing what we are waiting for (read / write / exception)
  931. * \param wq Waitqueue, which should be added to the drivers waitqueue list. The
  932. * thread that called select is waiting on this waitqueue
  933. * \param cmd Internal command, that is passed to NutSelectManageWq
  934. *
  935. * \return Flags representing the current filedescriptor state
  936. */
  937. int NutTcpDeviceSelect (TCPSOCKET * sock, int flags, HANDLE *wq, select_cmd_t cmd)
  938. {
  939. int rflags = 0;
  940. /* Manage the wait queue lists for the select call */
  941. NutSelectManageWq(&sock->so_rx_wq_list, wq, flags & WQ_FLAG_READ, cmd);
  942. NutSelectManageWq(&sock->so_tx_wq_list, wq, flags & WQ_FLAG_WRITE, cmd);
  943. if (sock->so_state == TCPS_ESTABLISHED) {
  944. /* Check if there is some data available for reading (compare to NutTcpReceive) */
  945. if (sock->so_rx_cnt - sock->so_rd_cnt > 0) {
  946. rflags |= WQ_FLAG_READ;
  947. }
  948. /* Check if there is some free space in the output buffer. */
  949. if (sock->so_devocnt < sock->so_devobsz) {
  950. rflags |= WQ_FLAG_WRITE;
  951. }
  952. }
  953. if ((sock->so_state == TCPS_CLOSED) || (sock->so_state == TCPS_CLOSE_WAIT) || (sock->so_state == TCPS_DESTROY)) {
  954. /* The socket has been closed. Signal for read and write.
  955. Send and receive routines will then return EOF.
  956. */
  957. rflags |= WQ_FLAG_READ | WQ_FLAG_WRITE;
  958. }
  959. rflags &= flags;
  960. return rflags;
  961. }
  962. #endif
  963. /*@}*/