PageRenderTime 39ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/platform/FNET/fnet_stack/stack/fnet_tcp.c

https://gitlab.com/fuggles/ucos
C | 4121 lines | 2565 code | 678 blank | 878 comment | 471 complexity | bc5ed71aa75ec5379df171b086c22f30 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /**************************************************************************
  2. *
  3. * Copyright 2011-2015 by Andrey Butok. FNET Community.
  4. * Copyright 2008-2010 by Andrey Butok. Freescale Semiconductor, Inc.
  5. * Copyright 2003 by Alexey Shervashidze, Andrey Butok. Motorola SPS.
  6. *
  7. ***************************************************************************
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License Version 3
  10. * or later (the "LGPL").
  11. *
  12. * This program 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.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * and the GNU Lesser General Public License along with this program.
  18. * If not, see <http://www.gnu.org/licenses/>.
  19. *
  20. **********************************************************************/ /*!
  21. *
  22. * @file fnet_tcp.c
  23. *
  24. * @author Olexandr Servasidze, Andrey Butok.
  25. *
  26. * @brief TCP protocol implementation.
  27. *
  28. ***************************************************************************/
  29. #include "fnet.h"
  30. #if FNET_CFG_TCP
  31. #include "fnet_socket_prv.h"
  32. #include "fnet_timer_prv.h"
  33. #include "fnet_tcp.h"
  34. #include "fnet_checksum.h"
  35. #include "fnet_prot.h"
  36. /************************************************************************
  37. * Definitions
  38. *************************************************************************/
  39. struct fnet_tcp_segment
  40. {
  41. fnet_socket_option_t *sockoption;
  42. struct sockaddr src_addr;
  43. struct sockaddr dest_addr;
  44. unsigned long seq;
  45. unsigned long ack;
  46. unsigned char flags;
  47. unsigned short wnd;
  48. unsigned short urgpointer;
  49. void *options;
  50. char optlen;
  51. fnet_netbuf_t *data;
  52. };
  53. /************************************************************************
  54. * Function Prototypes
  55. *************************************************************************/
  56. static void fnet_tcp_slowtimo( void *cookie );
  57. static void fnet_tcp_fasttimo( void *cookie );
  58. static void fnet_tcp_slowtimosk( fnet_socket_t *sk );
  59. static void fnet_tcp_fasttimosk( fnet_socket_t *sk );
  60. static int fnet_tcp_inputsk( fnet_socket_t *sk, fnet_netbuf_t *insegment, struct sockaddr *src_addr, struct sockaddr *dest_addr);
  61. static void fnet_tcp_initconnection( fnet_socket_t *sk );
  62. static int fnet_tcp_dataprocess( fnet_socket_t *sk, fnet_netbuf_t *insegment, int *ackparam );
  63. static int fnet_tcp_sendheadseg( fnet_socket_t *sk, unsigned char flags, void *options, char optlen );
  64. static int fnet_tcp_senddataseg( fnet_socket_t *sk, void *options, char optlen, unsigned long datasize );
  65. static unsigned long fnet_tcp_getrcvwnd( fnet_socket_t *sk );
  66. static int fnet_tcp_sendseg( struct fnet_tcp_segment *segment);
  67. static void fnet_tcp_sendrst( fnet_socket_option_t *sockoption, fnet_netbuf_t *insegment, struct sockaddr *src_addr, struct sockaddr *dest_addr);
  68. static void fnet_tcp_sendrstsk( fnet_socket_t *sk );
  69. static void fnet_tcp_sendack( fnet_socket_t *sk );
  70. static void fnet_tcp_abortsk( fnet_socket_t *sk );
  71. static void fnet_tcp_setsynopt( fnet_socket_t *sk, char *options, char *optionlen );
  72. static void fnet_tcp_getsynopt( fnet_socket_t *sk );
  73. static int fnet_tcp_addopt( fnet_netbuf_t *segment, unsigned char len, void *data );
  74. static void fnet_tcp_getopt( fnet_socket_t *sk, fnet_netbuf_t *segment );
  75. static unsigned long fnet_tcp_getsize( unsigned long pos1, unsigned long pos2 );
  76. static void fnet_tcp_rtimeo( fnet_socket_t *sk );
  77. static void fnet_tcp_ktimeo( fnet_socket_t *sk );
  78. static void fnet_tcp_ptimeo( fnet_socket_t *sk );
  79. static int fnet_tcp_hit( unsigned long startpos, unsigned long endpos, unsigned long pos );
  80. static int fnet_tcp_addinpbuf( fnet_socket_t *sk, fnet_netbuf_t *insegment, int *ackparam );
  81. static fnet_socket_t *fnet_tcp_findsk( struct sockaddr *src_addr, struct sockaddr *dest_addr );
  82. static void fnet_tcp_addpartialsk( fnet_socket_t *mainsk, fnet_socket_t *partialsk );
  83. static void fnet_tcp_movesk2incominglist( fnet_socket_t *sk );
  84. static void fnet_tcp_closesk( fnet_socket_t *sk );
  85. static void fnet_tcp_delpartialsk( fnet_socket_t *sk );
  86. static void fnet_tcp_delincomingsk( fnet_socket_t *sk );
  87. static void fnet_tcp_delcb( fnet_tcp_control_t *cb );
  88. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  89. static void fnet_tcp_deletetmpbuf( fnet_tcp_control_t *cb );
  90. #endif
  91. static void fnet_tcp_delsk( fnet_socket_t ** head, fnet_socket_t *sk );
  92. static int fnet_tcp_sendanydata( fnet_socket_t *sk, int oneexec );
  93. #if FNET_CFG_TCP_URGENT
  94. static void fnet_tcp_urgprocessing( fnet_socket_t *sk, fnet_netbuf_t ** segment, unsigned long repdatasize, int *ackparam );
  95. #endif
  96. static void fnet_tcp_finprocessing( fnet_socket_t *sk, unsigned long ack );
  97. static int fnet_tcp_init( void );
  98. static void fnet_tcp_release( void );
  99. static void fnet_tcp_input(fnet_netif_t *netif, struct sockaddr *src_addr, struct sockaddr *dest_addr, fnet_netbuf_t *nb, fnet_netbuf_t *ip_nb);
  100. static void fnet_tcp_control_input(fnet_prot_notify_t command, struct sockaddr *src_addr, struct sockaddr *dest_addr, fnet_netbuf_t *nb);
  101. static int fnet_tcp_attach( fnet_socket_t *sk );
  102. static int fnet_tcp_close( fnet_socket_t *sk );
  103. static int fnet_tcp_connect( fnet_socket_t *sk, struct sockaddr *foreign_addr);
  104. static fnet_socket_t *fnet_tcp_accept( fnet_socket_t *listensk );
  105. static int fnet_tcp_rcv( fnet_socket_t *sk, char *buf, int len, int flags, struct sockaddr *foreign_addr);
  106. static int fnet_tcp_snd( fnet_socket_t *sk, char *buf, int len, int flags, const struct sockaddr *foreign_addr);
  107. static int fnet_tcp_shutdown( fnet_socket_t *sk, int how );
  108. static int fnet_tcp_setsockopt( fnet_socket_t *sk, int level, int optname, char *optval, unsigned int optlen );
  109. static int fnet_tcp_getsockopt( fnet_socket_t *sk, int level, int optname, char *optval, unsigned int *optlen );
  110. static int fnet_tcp_listen( fnet_socket_t *sk, int backlog );
  111. static void fnet_tcp_drain( void );
  112. #if FNET_CFG_DEBUG_TRACE_TCP
  113. void fnet_tcp_trace(char *str, fnet_tcp_header_t *tcp_hdr);
  114. #else
  115. #define fnet_tcp_trace(str, tcp_hdr)
  116. #endif
  117. #if 0 /* For Debug needs.*/
  118. int FNET_DEBUG_check_send_buffer(fnet_socket_t *sk);
  119. #endif
  120. /************************************************************************
  121. * Global Variables
  122. *************************************************************************/
  123. /* Initial Sequence Number
  124. * tcpcb_isntime is changed by STEPISN every 0.5 sec.
  125. * Additionaly, each time a connection is established,
  126. * tcpcb_isntime is also incremented by FNET_TCP_STEPISN */
  127. static unsigned long fnet_tcp_isntime = 1;
  128. /* Timers.*/
  129. static fnet_timer_desc_t fnet_tcp_fasttimer;
  130. static fnet_timer_desc_t fnet_tcp_slowtimer;
  131. /*****************************************************************************
  132. * Protocol API structure.
  133. ******************************************************************************/
  134. static const fnet_socket_prot_if_t fnet_tcp_socket_api =
  135. {
  136. 1, /* TRUE = connection required by protocol.*/
  137. fnet_tcp_attach, /* A new socket has been created.*/
  138. fnet_tcp_close,
  139. fnet_tcp_connect,
  140. fnet_tcp_accept,
  141. fnet_tcp_rcv,
  142. fnet_tcp_snd,
  143. fnet_tcp_shutdown,
  144. fnet_tcp_setsockopt,
  145. fnet_tcp_getsockopt,
  146. fnet_tcp_listen
  147. };
  148. /* Protocol structure.*/
  149. fnet_prot_if_t fnet_tcp_prot_if =
  150. {
  151. 0,
  152. AF_SUPPORTED, /* Protocol domain.*/
  153. SOCK_STREAM, /* Socket type.*/
  154. FNET_IP_PROTOCOL_TCP, /* Protocol number.*/
  155. fnet_tcp_init,
  156. fnet_tcp_release,
  157. fnet_tcp_input,
  158. fnet_tcp_control_input, /* Control input (from below).*/
  159. fnet_tcp_drain,
  160. &fnet_tcp_socket_api /* Socket API */
  161. };
  162. /************************************************************************
  163. * NAME: fnet_tcp_init
  164. *
  165. * DESCRIPTION: This function performs a protocol initialization.
  166. *
  167. * RETURNS: If no error occurs, this function returns ERR_OK. Otherwise
  168. * it returns FNET_ERR.
  169. *************************************************************************/
  170. static int fnet_tcp_init( void )
  171. {
  172. /* Create the slow timer.*/
  173. fnet_tcp_fasttimer = fnet_timer_new(FNET_TCP_FASTTIMO / FNET_TIMER_PERIOD_MS, fnet_tcp_fasttimo, 0);
  174. if(!fnet_tcp_fasttimer)
  175. return FNET_ERR;
  176. /* Create the fast timer.*/
  177. fnet_tcp_slowtimer = fnet_timer_new(FNET_TCP_SLOWTIMO / FNET_TIMER_PERIOD_MS, fnet_tcp_slowtimo, 0);
  178. if(!fnet_tcp_slowtimer)
  179. {
  180. fnet_timer_free(fnet_tcp_fasttimer);
  181. fnet_tcp_fasttimer = 0;
  182. return FNET_ERR;
  183. }
  184. return FNET_OK;
  185. }
  186. /************************************************************************
  187. * NAME: fnet_tcp_release
  188. *
  189. * DESCRIPTION: This function resets and deletes sockets and releases timers.
  190. *
  191. * RETURNS: None.
  192. *************************************************************************/
  193. static void fnet_tcp_release( void )
  194. {
  195. fnet_tcp_control_t *cb;
  196. fnet_isr_lock();
  197. /* Release sockets.*/
  198. while(fnet_tcp_prot_if.head)
  199. {
  200. cb = (fnet_tcp_control_t *)fnet_tcp_prot_if.head->protocol_control;
  201. cb->tcpcb_flags |= FNET_TCP_CBF_CLOSE;
  202. fnet_tcp_abortsk(fnet_tcp_prot_if.head);
  203. }
  204. /* Free timers.*/
  205. fnet_timer_free(fnet_tcp_fasttimer);
  206. fnet_timer_free(fnet_tcp_slowtimer);
  207. fnet_tcp_fasttimer = 0;
  208. fnet_tcp_slowtimer = 0;
  209. fnet_isr_unlock();
  210. }
  211. /************************************************************************
  212. * NAME: fnet_tcp_input
  213. *
  214. * DESCRIPTION: This function receives, checks and routes input segments.
  215. *
  216. * RETURNS: FNET_OK.
  217. *************************************************************************/
  218. static void fnet_tcp_input(fnet_netif_t *netif, struct sockaddr *src_addr, struct sockaddr *dest_addr, fnet_netbuf_t *nb, fnet_netbuf_t *ip_nb)
  219. {
  220. fnet_socket_t *sk;
  221. fnet_netbuf_t *buf;
  222. unsigned short checksum;
  223. unsigned long tcp_length;
  224. tcp_length = (unsigned long)FNET_TCP_LENGTH(nb);
  225. fnet_netbuf_free_chain(ip_nb);
  226. /* The header must reside in contiguous area of the memory.*/
  227. buf = fnet_netbuf_pullup(nb, (int)tcp_length);
  228. if(!buf)
  229. {
  230. goto DROP;
  231. }
  232. nb = buf;
  233. /*Checksum.*/
  234. #if FNET_CFG_CPU_ETH_HW_RX_PROTOCOL_CHECKSUM || FNET_CFG_CPU_ETH_HW_TX_PROTOCOL_CHECKSUM
  235. if(nb->flags & FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM)
  236. {
  237. checksum = 0;
  238. }
  239. else
  240. #endif
  241. {
  242. checksum = fnet_checksum_pseudo_start( nb, FNET_HTONS((unsigned short)FNET_IP_PROTOCOL_TCP), (unsigned short)nb->total_length );
  243. checksum = fnet_checksum_pseudo_end( checksum, (char *)src_addr->sa_data, (char *)dest_addr->sa_data,
  244. (dest_addr->sa_family == AF_INET) ? sizeof(fnet_ip4_addr_t) : sizeof(fnet_ip6_addr_t) );
  245. }
  246. if(checksum
  247. || (fnet_socket_addr_is_broadcast(src_addr, netif)
  248. || fnet_socket_addr_is_multicast(src_addr))
  249. || (nb->total_length < tcp_length) /* Check the length.*/)
  250. {
  251. goto DROP;
  252. }
  253. /* Set port numbers.*/
  254. src_addr->sa_port = FNET_TCP_SPORT(nb);
  255. dest_addr->sa_port = FNET_TCP_DPORT(nb);
  256. if(fnet_socket_addr_is_broadcast(dest_addr, netif) || fnet_socket_addr_is_multicast(dest_addr))
  257. {
  258. /* Send RST.*/
  259. fnet_tcp_sendrst(0, nb, dest_addr, src_addr);
  260. goto DROP;
  261. }
  262. fnet_tcp_trace("RX", buf->data_ptr); /* TCP trace.*/
  263. sk = fnet_tcp_findsk(src_addr, dest_addr);
  264. if(sk)
  265. {
  266. if(sk->state == SS_LISTENING)
  267. {
  268. sk->foreign_addr = *src_addr;
  269. }
  270. nb->next_chain = 0;
  271. /* Process the segment.*/
  272. if(fnet_tcp_inputsk(sk, nb, src_addr, dest_addr) == FNET_TRUE)
  273. goto DROP;
  274. }
  275. else
  276. {
  277. if(!(FNET_TCP_FLAGS(nb) & FNET_TCP_SGT_RST))
  278. fnet_tcp_sendrst(0, nb, dest_addr, src_addr);
  279. goto DROP;
  280. }
  281. /* Wake-up user application.*/
  282. fnet_os_event_raise();
  283. return;
  284. DROP:
  285. /* Wake-up user application.*/
  286. fnet_os_event_raise();
  287. /* Delete the segment.*/
  288. fnet_netbuf_free_chain(nb);
  289. }
  290. /************************************************************************
  291. * NAME: fnet_tcp_control_input
  292. *
  293. * DESCRIPTION: This function process ICMP errors.
  294. *
  295. * RETURNS: None.
  296. *************************************************************************/
  297. static void fnet_tcp_control_input(fnet_prot_notify_t command, struct sockaddr *src_addr, struct sockaddr *dest_addr, fnet_netbuf_t *nb)
  298. {
  299. fnet_tcp_header_t *tcp_header; /* Pointer to the TCP header.*/
  300. fnet_socket_t *sk; /* Pointer to the socket.*/
  301. fnet_tcp_control_t *cb;
  302. if(src_addr && dest_addr && nb)
  303. {
  304. tcp_header = nb->data_ptr;
  305. /* Find the corresponding socket.*/
  306. dest_addr->sa_port = tcp_header->destination_port;
  307. src_addr->sa_port = tcp_header->source_port;
  308. sk = fnet_tcp_findsk(dest_addr, src_addr);
  309. if(sk)
  310. {
  311. /* Initialize the pointer of the control block.*/
  312. cb = sk->protocol_control;
  313. switch(command)
  314. {
  315. case FNET_PROT_NOTIFY_QUENCH: /* Someone said to slow down.*/
  316. /* Begin the Slow Start algorithm.*/
  317. cb->tcpcb_cwnd = cb->tcpcb_sndmss;
  318. break;
  319. case FNET_PROT_NOTIFY_MSGSIZE: /* Message size forced drop.*/
  320. sk->options.local_error = FNET_ERR_MSGSIZE;
  321. break;
  322. case FNET_PROT_NOTIFY_UNREACH_HOST: /* No route to host.*/
  323. case FNET_PROT_NOTIFY_UNREACH_NET: /* No route to network.*/
  324. case FNET_PROT_NOTIFY_UNREACH_SRCFAIL: /* Source route failed.*/
  325. sk->options.local_error = FNET_ERR_HOSTUNREACH;
  326. break;
  327. case FNET_PROT_NOTIFY_PARAMPROB: /* Header incorrect.*/
  328. sk->options.local_error = FNET_ERR_NOPROTOOPT; /* Bad protocol option.*/
  329. break;
  330. case FNET_PROT_NOTIFY_UNREACH_PORT: /* bad port #.*/
  331. case FNET_PROT_NOTIFY_UNREACH_PROTOCOL:
  332. if(sk->state != SS_LISTENING) /* Avoid listening sockets.*/
  333. {
  334. sk->options.local_error = FNET_ERR_CONNRESET;
  335. fnet_tcp_closesk(sk);
  336. }
  337. break;
  338. default:
  339. break;
  340. }
  341. }
  342. }
  343. }
  344. /************************************************************************
  345. * NAME: fnet_tcp_attach
  346. *
  347. * DESCRIPTION: This function performs the initialization of the
  348. * socket's options and creates the structure of the control blok.
  349. *
  350. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  351. * it returns FNET_ERR.
  352. *************************************************************************/
  353. static int fnet_tcp_attach( fnet_socket_t *sk )
  354. {
  355. struct tcpcb *cb;
  356. /* Create the control block.*/
  357. cb = (struct tcpcb *)fnet_malloc_zero(sizeof(fnet_tcp_control_t));
  358. /* Check the memory allocation.*/
  359. if(!cb)
  360. {
  361. fnet_socket_set_error(sk, FNET_ERR_NOMEM);
  362. return FNET_ERR;
  363. }
  364. sk->protocol_control = (void *)cb;
  365. /* Set the maximal segment size option.*/
  366. sk->options.tcp_opt.mss = FNET_CFG_SOCKET_TCP_MSS;
  367. /* Default setting of the flags.*/
  368. sk->options.tcp_opt.flags =
  369. #if FNET_CFG_TCP_URGENT
  370. TCP_BSD |
  371. #endif
  372. TCP_NODELAY;
  373. sk->options.tcp_opt.keep_idle = FNET_TCP_KEEPIDLE_DEFAULT; /* TCP_KEEPIDLE option. */
  374. sk->options.tcp_opt.keep_intvl = FNET_TCP_KEEPINTVL_DEFAULT; /* TCP_KEEPINTVL option. */
  375. sk->options.tcp_opt.keep_cnt = FNET_TCP_KEEPCNT_DEFAULT; /* TCP_KEEPCNT option. */
  376. sk->options.flags = SO_KEEPALIVE;
  377. /* Set the IP options.*/
  378. #if FNET_CFG_IP4
  379. sk->options.ip_opt.ttl = FNET_TCP_TTL_DEFAULT;
  380. sk->options.ip_opt.tos = 0;
  381. #endif
  382. #if FNET_CFG_IP6
  383. sk->options.ip6_opt.hops_unicast = 0; /* Defined by ND.*/
  384. #endif
  385. /* Set the buffer sizes.*/
  386. sk->send_buffer.count_max = FNET_TCP_TX_BUF_MAX;
  387. sk->receive_buffer.count_max = FNET_TCP_RX_BUF_MAX;
  388. return FNET_OK;
  389. }
  390. /************************************************************************
  391. * NAME: fnet_tcp_close
  392. *
  393. * DESCRIPTION: This function performs the connection termination.
  394. *
  395. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  396. * it returns FNET_ERR.
  397. *************************************************************************/
  398. static int fnet_tcp_close( fnet_socket_t *sk )
  399. {
  400. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  401. /* If the connection is closed, free the memory.*/
  402. if(sk->state == SS_UNCONNECTED)
  403. {
  404. cb->tcpcb_flags |= FNET_TCP_CBF_CLOSE;
  405. fnet_tcp_closesk(sk);
  406. return FNET_OK;
  407. }
  408. /* If SO_LINGER option is present.*/
  409. if(sk->options.flags & SO_LINGER)
  410. {
  411. if(sk->options.linger_ticks == 0)
  412. /* Linger is 0 so close the socket immediately. */
  413. {
  414. /* Hard reset.*/
  415. fnet_isr_lock();
  416. cb->tcpcb_flags |= FNET_TCP_CBF_CLOSE;
  417. fnet_tcp_abortsk(sk);
  418. fnet_isr_unlock();
  419. return FNET_OK;
  420. }
  421. }
  422. fnet_isr_lock();
  423. if(sk->state != SS_CONNECTED)
  424. {
  425. cb->tcpcb_flags |= FNET_TCP_CBF_CLOSE;
  426. fnet_tcp_abortsk(sk);
  427. /* Unlock interrupts.*/
  428. fnet_isr_unlock();
  429. return FNET_OK;
  430. }
  431. /* If the socket is not unlocked, try to send the data.*/
  432. if(!sk->send_buffer.is_shutdown)
  433. {
  434. sk->send_buffer.is_shutdown = 1;
  435. fnet_tcp_sendanydata(sk, 1);
  436. }
  437. fnet_isr_unlock();
  438. fnet_isr_lock();
  439. /* After this moment the unconnecetd socket must be deleted.*/
  440. cb->tcpcb_flags |= FNET_TCP_CBF_CLOSE;
  441. /* If the socket is already unconnected, close the socket.*/
  442. if(sk->state == SS_UNCONNECTED)
  443. {
  444. fnet_tcp_closesk(sk);
  445. }
  446. else
  447. {
  448. if(cb->tcpcb_connection_state != FNET_TCP_CS_TIME_WAIT)
  449. {
  450. if((sk->options.flags & SO_LINGER) && sk->options.linger_ticks)
  451. cb->tcpcb_timers.connection = ((sk->options.linger_ticks * FNET_TIMER_PERIOD_MS)
  452. / FNET_TCP_SLOWTIMO);
  453. else
  454. cb->tcpcb_timers.connection = FNET_TCP_ABORT_INTERVAL;
  455. sk->receive_buffer.is_shutdown = 1;
  456. }
  457. if(sk->receive_buffer.count)
  458. fnet_socket_buffer_release(&sk->receive_buffer);
  459. }
  460. fnet_isr_unlock();
  461. return FNET_OK;
  462. }
  463. /************************************************************************
  464. * NAME: fnet_tcp_connect
  465. *
  466. * DESCRIPTION: This function performs the connection establishment.
  467. *
  468. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  469. * it returns FNET_ERR.
  470. *************************************************************************/
  471. static int fnet_tcp_connect( fnet_socket_t *sk, struct sockaddr *foreign_addr)
  472. {
  473. fnet_tcp_control_t *cb;
  474. char options[FNET_TCP_MAX_OPT_SIZE];
  475. char optionlen;
  476. int error;
  477. fnet_netif_t *netif;
  478. if((netif = fnet_socket_addr_route(foreign_addr)) == FNET_NULL)
  479. {
  480. error = FNET_ERR_NETUNREACH;
  481. goto ERROR;
  482. }
  483. /* TCP doesn't support broadcasting and multicasting.*/
  484. if(fnet_socket_addr_is_broadcast(foreign_addr, netif) || fnet_socket_addr_is_multicast(foreign_addr))
  485. {
  486. error = FNET_ERR_ADDRNOTAVAIL;
  487. goto ERROR;
  488. }
  489. /* Initialize the pointer to the control block.*/
  490. cb = (fnet_tcp_control_t *)sk->protocol_control;
  491. /* Initialize the control block.*/
  492. fnet_tcp_initconnection(sk);
  493. /* Set synchronized options.*/
  494. fnet_tcp_setsynopt(sk, options, &optionlen);
  495. /* Initialize sequnece number parameters.*/
  496. cb->tcpcb_sndseq = fnet_tcp_isntime;
  497. cb->tcpcb_maxrcvack = fnet_tcp_isntime + 1;
  498. #if FNET_CFG_TCP_URGENT
  499. cb->tcpcb_sndurgseq = cb->tcpcb_sndseq - 1;
  500. #endif /* FNET_CFG_TCP_URGENT */
  501. /* Set the foreign address.*/
  502. sk->foreign_addr = *foreign_addr;
  503. fnet_isr_lock();
  504. /* Send SYN segment.*/
  505. error = fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_SYN, options, optionlen);
  506. /* Check the result.*/
  507. if(error)
  508. {
  509. fnet_isr_unlock();
  510. goto ERROR;
  511. }
  512. /* Change the states.*/
  513. cb->tcpcb_connection_state = FNET_TCP_CS_SYN_SENT;
  514. sk->state = SS_CONNECTING;
  515. /* Increase Initial Sequence Number.*/
  516. fnet_tcp_isntime += FNET_TCP_STEPISN;
  517. /* Initialize Abort Timer.*/
  518. cb->tcpcb_timers.retransmission = cb->tcpcb_rto;
  519. cb->tcpcb_timers.connection = FNET_TCP_ABORT_INTERVAL_CON;
  520. fnet_isr_unlock();
  521. return FNET_OK;
  522. ERROR:
  523. fnet_socket_set_error(sk, error);
  524. return FNET_ERR;
  525. }
  526. /************************************************************************
  527. * NAME: fnet_tcp_accept
  528. *
  529. * DESCRIPTION: This function removes the created socket
  530. * from the incoming queue of the listening socket,
  531. * and adds this socket to the main list.
  532. *
  533. * RETURNS: If the incoming socket is present, this function returns
  534. * the first created incoming socket. Otherwise, it returns 0.
  535. *************************************************************************/
  536. static fnet_socket_t *fnet_tcp_accept( fnet_socket_t *listensk )
  537. {
  538. fnet_socket_t *sk= FNET_NULL;
  539. /* If the incoming socket is not present, return.*/
  540. if(listensk->incoming_con)
  541. {
  542. fnet_isr_lock();
  543. /* Find the first incoming socket.*/
  544. sk = listensk->incoming_con;
  545. while(sk->next)
  546. sk = sk->next;
  547. /* Delete the incoming socket from the list.*/
  548. sk->head_con->incoming_con_len--;
  549. fnet_socket_list_del(&sk->head_con->incoming_con, sk);
  550. fnet_isr_unlock();
  551. sk->head_con = 0;
  552. }
  553. return sk;
  554. }
  555. /************************************************************************
  556. * NAME: fnet_tcp_rcv
  557. *
  558. * DESCRIPTION: This function receives the data and sends the acknowledgment
  559. * (This acknowledgment segment informs about the new free size
  560. * in the input buffer).
  561. *
  562. * RETURNS: If no error occurs, this function returns the length
  563. * of the received data. Otherwise, it returns FNET_ERR.
  564. *************************************************************************/
  565. static int fnet_tcp_rcv( fnet_socket_t *sk, char *buf, int len, int flags, struct sockaddr *foreign_addr)
  566. {
  567. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  568. int remove; /* Remove flag. 1 means that the data must be deleted
  569. * from the input buffer after the reading.*/
  570. int error_code;
  571. /* Receive the flags.*/
  572. remove = !(flags & MSG_PEEK);
  573. #if FNET_CFG_TCP_URGENT
  574. /* Reading of the OOB data.*/
  575. if(flags & MSG_OOB)
  576. {
  577. /* If the OOB data can't be read, return.*/
  578. if(sk->options.flags & SO_OOBINLINE)
  579. {
  580. error_code = FNET_ERR_INVAL;
  581. goto ERROR;
  582. }
  583. /* If the OOB data is present, read */
  584. if(cb->tcpcb_flags & FNET_TCP_CBF_RCVURGENT)
  585. {
  586. fnet_isr_lock();
  587. if(remove)
  588. {
  589. cb->tcpcb_rcvurgmark = FNET_TCP_NOT_USED;
  590. cb->tcpcb_flags &= ~FNET_TCP_CBF_RCVURGENT;
  591. }
  592. *buf = cb->tcpcb_iobc;
  593. fnet_isr_unlock();
  594. return FNET_TCP_URGENT_DATA_SIZE;
  595. }
  596. else
  597. {
  598. /* If the socket is not connected , return with the error. */
  599. if(sk->state != SS_CONNECTED)
  600. {
  601. error_code = FNET_ERR_NOTCONN;
  602. goto ERROR;
  603. }
  604. return 0;
  605. }
  606. }
  607. #endif /* FNET_CFG_TCP_URGENT */
  608. fnet_isr_lock();
  609. #if FNET_CFG_TCP_URGENT
  610. /* Calculate the length of the data that can be received.*/
  611. if(cb->tcpcb_rcvurgmark > 0 && len >= cb->tcpcb_rcvurgmark)
  612. {
  613. len = cb->tcpcb_rcvurgmark;
  614. if(remove)
  615. cb->tcpcb_rcvurgmark = FNET_TCP_NOT_USED;
  616. }
  617. else
  618. #endif /* FNET_CFG_TCP_URGENT */
  619. if(sk->receive_buffer.count < len)
  620. {
  621. len = (int)sk->receive_buffer.count;
  622. }
  623. /* Copy the data to the buffer.*/
  624. len = fnet_socket_buffer_read_record(&sk->receive_buffer, buf, len, remove);
  625. /* Remove the data from input buffer.*/
  626. if(remove)
  627. {
  628. /* Recalculate the new free size in the input buffer.*/
  629. cb->tcpcb_newfreercvsize += len;
  630. /* If the window is opened, send acknowledgment.*/
  631. if((cb->tcpcb_newfreercvsize >= (cb->tcpcb_rcvmss << 1)
  632. || cb->tcpcb_newfreercvsize >= (cb->tcpcb_rcvcountmax >> 1) /* More than half of RX buffer.*/
  633. || (!cb->tcpcb_rcvwnd && cb->tcpcb_newfreercvsize)) && (sk->state == SS_CONNECTED))
  634. fnet_tcp_sendack(sk);
  635. }
  636. /* If the socket is not connected and the data are not received, return with error.*/
  637. if(len == 0 && sk->state != SS_CONNECTED)
  638. {
  639. error_code = FNET_ERR_NOTCONN;
  640. goto ERROR_UNLOCK;
  641. }
  642. else
  643. {
  644. /* Set the foreign address and port.*/
  645. if(foreign_addr)
  646. *foreign_addr = sk->foreign_addr;
  647. /* If the socket is closed by peer and no data.*/
  648. if((len == 0) && (cb->tcpcb_flags & FNET_TCP_CBF_FIN_RCVD))
  649. {
  650. error_code = FNET_ERR_CONNCLOSED;
  651. goto ERROR_UNLOCK;
  652. }
  653. }
  654. fnet_isr_unlock();
  655. return len;
  656. ERROR_UNLOCK:
  657. fnet_isr_unlock();
  658. #if FNET_CFG_TCP_URGENT
  659. ERROR:
  660. #endif
  661. fnet_socket_set_error(sk, error_code);
  662. return FNET_ERR;
  663. }
  664. /************************************************************************
  665. * NAME: fnet_tcp_snd
  666. *
  667. * DESCRIPTION: This function adds the data to the output buffer and
  668. * sends the data that can be sent.
  669. *
  670. * RETURNS: If no error occurs, this function returns the length
  671. * of the data that is added to the output buffer.
  672. * Otherwise, it returns FNET_ERR.
  673. *************************************************************************/
  674. static int fnet_tcp_snd( fnet_socket_t *sk, char *buf, int len, int flags, const struct sockaddr *foreign_addr)
  675. {
  676. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  677. fnet_netbuf_t *netbuf;
  678. long sendlength = len; /* Size of the data that must be sent.*/
  679. long sentlength = 0; /* Length of the sent data.*/
  680. long freespace; /* Free space in the output buffer.*/
  681. long currentlen; /* Current length.*/
  682. int dontroute = 0; /* Routing flag.*/
  683. unsigned long malloc_max;
  684. int error_code;
  685. FNET_COMP_UNUSED_ARG(foreign_addr);
  686. /* If the size of the data greater than the maximal size of the output buffer, return*/
  687. if(sendlength > FNET_TCP_MAX_BUFFER)
  688. {
  689. error_code = FNET_ERR_INVAL;
  690. goto ERROR;
  691. }
  692. /* If the socket is not connected, return*/
  693. if(sk->state != SS_CONNECTED)
  694. {
  695. error_code = FNET_ERR_NOTCONN;
  696. goto ERROR;
  697. }
  698. if(sendlength)
  699. {
  700. fnet_isr_lock();
  701. /* Caclulate a free space in the output buffer.*/
  702. freespace = (long)(sk->send_buffer.count_max - sk->send_buffer.count);
  703. /* Check maximum allocated memory chunck */
  704. malloc_max = fnet_malloc_max_netbuf();
  705. if(malloc_max < (long)(FNET_CFG_CPU_ETH0_MTU*1.5)) /* TBD I do not like it ????*/
  706. {
  707. freespace = 0;
  708. }
  709. else if(freespace > malloc_max)
  710. {
  711. freespace = (long)malloc_max;
  712. }
  713. /* If the function is nonblocking and the data length greater than the freespace, recalculate the size of the data*/
  714. if(freespace < sendlength)
  715. {
  716. /* If the data can't be added to the output buffer, return*/
  717. if(freespace <= 0)
  718. {
  719. fnet_isr_unlock();
  720. return 0;
  721. }
  722. else
  723. {
  724. /* Recalculate the data size.*/
  725. sendlength = freespace;
  726. #if FNET_CFG_TCP_URGENT
  727. flags &= ~MSG_OOB;
  728. #endif /* FNET_CFG_TCP_URGENT */
  729. }
  730. }
  731. #if FNET_CFG_TCP_URGENT
  732. /* Process the OOB data.*/
  733. if(flags & MSG_OOB)
  734. {
  735. /* If the urgent data are already present, the urgent byte will not be added.*/
  736. if(FNET_TCP_COMP_GE(cb->tcpcb_sndurgseq, cb->tcpcb_rcvack))
  737. {
  738. sendlength -= 1;
  739. /* If the data size is 0, return.*/
  740. if(!sendlength)
  741. {
  742. fnet_isr_unlock();
  743. return 0;
  744. }
  745. }
  746. else
  747. {
  748. /* Calculate the new sequence number of the urgent data.*/
  749. cb->tcpcb_sndurgseq = cb->tcpcb_rcvack + sk->send_buffer.count + sendlength - 1;
  750. }
  751. }
  752. #endif /* FNET_CFG_TCP_URGENT */
  753. /* If the routing tables should be bypassed for this message only, set dontroute flag.*/
  754. if((flags & MSG_DONTROUTE) && !(sk->options.flags & SO_DONTROUTE))
  755. {
  756. dontroute = 1;
  757. sk->options.flags |= SO_DONTROUTE;
  758. }
  759. /* Receive the freespace value.*/
  760. /* TBD*/
  761. #if 0
  762. freespace = (long)(sk->send_buffer.count_max - sk->send_buffer.count);
  763. #endif
  764. /* Try to add the data.*/
  765. if(freespace > 0)
  766. {
  767. cb->tcpcb_flags |= FNET_TCP_CBF_INSND;
  768. /* Calculate the data size that can be added.*/
  769. if(sendlength > freespace)
  770. currentlen = freespace;
  771. else
  772. currentlen = sendlength;
  773. netbuf = fnet_netbuf_from_buf(&buf[sentlength], currentlen, FNET_TRUE);
  774. /* Check the memory allocation.*/
  775. if(netbuf)
  776. {
  777. sentlength += currentlen;
  778. if(fnet_socket_buffer_append_record(&sk->send_buffer, netbuf) == FNET_OK)
  779. {
  780. /* If the window of another side is closed, set the persist timer.*/
  781. if(!cb->tcpcb_sndwnd)
  782. {
  783. if(cb->tcpcb_timers.persist == FNET_TCP_TIMER_OFF)
  784. {
  785. cb->tcpcb_cprto = cb->tcpcb_rto;
  786. cb->tcpcb_timers.persist = cb->tcpcb_cprto;
  787. }
  788. }
  789. else
  790. {
  791. /* Try to send the data.*/
  792. while(1)
  793. {
  794. /* If the connection is not established, delete the data. Otherwise try to send the data*/
  795. if(sk->state == SS_CONNECTED)
  796. {
  797. if(!fnet_tcp_sendanydata(sk, 1))
  798. {
  799. cb->tcpcb_flags &= ~FNET_TCP_CBF_INSND;
  800. break;
  801. }
  802. }
  803. else
  804. {
  805. /* If socket is not connected, delete the output buffer.*/
  806. fnet_socket_buffer_release(&sk->send_buffer);
  807. cb->tcpcb_flags &= ~FNET_TCP_CBF_INSND;
  808. break;
  809. }
  810. }
  811. }
  812. }
  813. else /* Not able to add to the socket send buffer.*/
  814. {
  815. fnet_netbuf_free( netbuf );
  816. fnet_isr_unlock();
  817. return 0;
  818. }
  819. }
  820. }
  821. /* Receive the freespace value.*/
  822. freespace = (long)(sk->send_buffer.count_max - sk->send_buffer.count);
  823. #if FNET_CFG_TCP_URGENT
  824. if(FNET_TCP_COMP_GE(cb->tcpcb_sndurgseq, cb->tcpcb_rcvack + sk->send_buffer.count))
  825. cb->tcpcb_sndurgseq = cb->tcpcb_rcvack - 1;
  826. #endif /* FNET_CFG_TCP_URGENT */
  827. /* Remove the dontroute flag.*/
  828. if(dontroute)
  829. sk->options.flags &= ~SO_DONTROUTE;
  830. fnet_isr_unlock();
  831. }
  832. return sentlength;
  833. ERROR:
  834. fnet_socket_set_error(sk, error_code);
  835. return FNET_ERR;
  836. }
  837. /************************************************************************
  838. * NAME: fnet_tcp_shutdown
  839. *
  840. * DESCRIPTION: This function closes a write-half, read-half, or
  841. * both halves of the connection.
  842. *
  843. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  844. * it returns FNET_ERR.
  845. *************************************************************************/
  846. static int fnet_tcp_shutdown( fnet_socket_t *sk, int how )
  847. {
  848. /* If the socket is not connected, return.*/
  849. if(sk->state != SS_CONNECTED)
  850. {
  851. fnet_socket_set_error(sk, FNET_ERR_NOTCONN);
  852. return FNET_ERR;
  853. }
  854. else
  855. {
  856. fnet_isr_lock();
  857. /* Shutdown the writing.*/
  858. if(how & SD_WRITE && !sk->send_buffer.is_shutdown)
  859. {
  860. /* Set the flag of the buffer.*/
  861. sk->send_buffer.is_shutdown = 1;
  862. /* Send the data that is in the output buffer.*/
  863. fnet_tcp_sendanydata(sk, 1);
  864. }
  865. /* Shutdown the reading.*/
  866. if(how & SD_READ && !sk->receive_buffer.is_shutdown)
  867. {
  868. fnet_socket_buffer_release(&sk->receive_buffer);
  869. /* Set the flag of the buffer (Data can't be read).*/
  870. sk->receive_buffer.is_shutdown = 1;
  871. }
  872. fnet_isr_unlock();
  873. return FNET_OK;
  874. }
  875. }
  876. /************************************************************************
  877. * NAME: fnet_tcp_setsockopt
  878. *
  879. * DESCRIPTION: This function sets a TCP option.
  880. *
  881. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  882. * it returns FNET_ERR.
  883. *************************************************************************/
  884. static int fnet_tcp_setsockopt( fnet_socket_t *sk, int level, int optname, char *optval, unsigned int optlen )
  885. {
  886. int error_code;
  887. /* If the level is not IPPROTO_TCP, go to IP processing.*/
  888. if(level == IPPROTO_TCP)
  889. {
  890. /* Check the option size.*/
  891. switch(optname)
  892. {
  893. case TCP_MSS:
  894. if(optlen != sizeof(unsigned short))
  895. {
  896. error_code = FNET_ERR_INVAL;
  897. goto ERROR;
  898. }
  899. break;
  900. case TCP_KEEPCNT:
  901. case TCP_KEEPINTVL:
  902. case TCP_KEEPIDLE:
  903. case TCP_NODELAY:
  904. #if FNET_CFG_TCP_URGENT
  905. case TCP_BSD:
  906. #endif
  907. if(optlen != sizeof(int))
  908. {
  909. error_code = FNET_ERR_INVAL;
  910. goto ERROR;
  911. }
  912. break;
  913. default:
  914. /* The option is not supported.*/
  915. error_code = FNET_ERR_NOPROTOOPT;
  916. goto ERROR;
  917. }
  918. /* Process the option.*/
  919. switch(optname)
  920. {
  921. /* Maximal segment size option.*/
  922. case TCP_MSS:
  923. if(!(*((unsigned short *)(optval))))
  924. {
  925. error_code = FNET_ERR_INVAL;
  926. goto ERROR;
  927. }
  928. sk->options.tcp_opt.mss = *((unsigned short *)(optval));
  929. break;
  930. /* Keepalive probe retransmit limit.*/
  931. case TCP_KEEPCNT:
  932. if(!(*((unsigned int *)(optval))))
  933. {
  934. error_code = FNET_ERR_INVAL;
  935. goto ERROR;
  936. }
  937. sk->options.tcp_opt.keep_cnt = *((int *)(optval));
  938. break;
  939. /* Keepalive retransmit interval.*/
  940. case TCP_KEEPINTVL:
  941. if(!(*((unsigned int *)(optval))))
  942. {
  943. error_code = FNET_ERR_INVAL;
  944. goto ERROR;
  945. }
  946. sk->options.tcp_opt.keep_intvl = *((int *)(optval))*(1000/FNET_TCP_SLOWTIMO);
  947. break;
  948. /* Time between keepalive probes.*/
  949. case TCP_KEEPIDLE:
  950. if(!(*((unsigned int *)(optval))))
  951. {
  952. error_code = FNET_ERR_INVAL;
  953. goto ERROR;
  954. }
  955. sk->options.tcp_opt.keep_idle = *((int *)(optval))*(1000/FNET_TCP_SLOWTIMO);
  956. break;
  957. #if FNET_CFG_TCP_URGENT
  958. /* BSD interpretation of the urgent pointer.*/
  959. case TCP_BSD:
  960. #endif
  961. /* TCP_NO_DELAY option.*/
  962. case TCP_NODELAY:
  963. if(*((int *)(optval)))
  964. sk->options.tcp_opt.flags |= optname;
  965. else
  966. sk->options.tcp_opt.flags &= ~optname;
  967. break;
  968. }
  969. return FNET_OK;
  970. }
  971. else
  972. {
  973. /* IP level option processing.*/
  974. return fnet_ip_setsockopt(sk, level, optname, optval, optlen);
  975. }
  976. ERROR:
  977. fnet_socket_set_error(sk, error_code);
  978. return FNET_ERR;
  979. }
  980. /************************************************************************
  981. * NAME: fnet_tcp_getsockopt
  982. *
  983. * DESCRIPTION: This function receives a TCP option.
  984. *
  985. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise
  986. * it returns FNET_ERR.
  987. *************************************************************************/
  988. static int fnet_tcp_getsockopt( fnet_socket_t *sk, int level, int optname, char *optval, unsigned int *optlen )
  989. {
  990. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  991. if(level == IPPROTO_TCP)
  992. {
  993. switch(optname)
  994. {
  995. case TCP_KEEPCNT:
  996. *((int *)(optval)) = sk->options.tcp_opt.keep_cnt;
  997. break;
  998. case TCP_KEEPINTVL:
  999. *((int *)(optval)) = sk->options.tcp_opt.keep_intvl/(1000/FNET_TCP_SLOWTIMO);
  1000. break;
  1001. case TCP_KEEPIDLE:
  1002. *((int *)(optval)) = sk->options.tcp_opt.keep_idle/(1000/FNET_TCP_SLOWTIMO);
  1003. break;
  1004. #if FNET_CFG_TCP_URGENT
  1005. case TCP_BSD:
  1006. #endif
  1007. case TCP_NODELAY:
  1008. if(sk->options.tcp_opt.flags & optname)
  1009. *((int *)(optval)) = 1;
  1010. else
  1011. *((int *)(optval)) = 0;
  1012. break;
  1013. case TCP_FINRCVD:
  1014. if(cb->tcpcb_flags & FNET_TCP_CBF_FIN_RCVD)
  1015. *((int *)(optval)) = 1;
  1016. else
  1017. *((int *)(optval)) = 0;
  1018. break;
  1019. #if FNET_CFG_TCP_URGENT
  1020. case TCP_URGRCVD:
  1021. if(cb->tcpcb_flags & FNET_TCP_CBF_RCVURGENT)
  1022. *((int *)(optval)) = 1;
  1023. else
  1024. *((int *)(optval)) = 0;
  1025. break;
  1026. #endif
  1027. case TCP_MSS:
  1028. *((unsigned short *)(optval)) = sk->options.tcp_opt.mss;
  1029. *optlen = sizeof(unsigned short);
  1030. return FNET_OK;
  1031. default:
  1032. fnet_socket_set_error(sk, FNET_ERR_NOPROTOOPT);
  1033. return FNET_ERR;
  1034. }
  1035. *optlen = sizeof(int);
  1036. return FNET_OK;
  1037. }
  1038. else
  1039. {
  1040. /* IP level option processing.*/
  1041. return fnet_ip_getsockopt(sk, level, optname, optval, optlen);
  1042. }
  1043. }
  1044. /************************************************************************
  1045. * NAME: fnet_tcp_listen
  1046. *
  1047. * DESCRIPTION: This function changes
  1048. * the state of the socket to the listening state.
  1049. *
  1050. * RETURNS: FNET_OK.
  1051. *************************************************************************/
  1052. static int fnet_tcp_listen( fnet_socket_t *sk, int backlog )
  1053. {
  1054. /* Initializen the pointer to the control block.*/
  1055. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  1056. if(sk->state == SS_LISTENING)
  1057. {
  1058. /* If the socket number of the listening socket is greater than the new backlog,
  1059. * delete the sockets.*/
  1060. fnet_isr_lock();
  1061. while(backlog < sk->partial_con_len + sk->incoming_con_len && sk->partial_con_len)
  1062. fnet_tcp_abortsk(sk->partial_con);
  1063. while(backlog < sk->incoming_con_len)
  1064. fnet_tcp_abortsk(sk->incoming_con);
  1065. sk->con_limit = backlog;
  1066. fnet_isr_unlock();
  1067. }
  1068. else
  1069. {
  1070. fnet_tcp_initconnection(sk);
  1071. /* Foreign address must be any.*/
  1072. ((struct sockaddr_in *)(&sk->foreign_addr))->sin_addr.s_addr = INADDR_ANY;
  1073. sk->foreign_addr.sa_port = 0;
  1074. sk->foreign_addr.sa_family = AF_INET;
  1075. sk->con_limit = backlog;
  1076. /* Change the state.*/
  1077. cb->tcpcb_connection_state = FNET_TCP_CS_LISTENING;
  1078. sk->state = SS_LISTENING;
  1079. }
  1080. return FNET_OK;
  1081. }
  1082. /************************************************************************
  1083. * NAME: fnet_tcp_drain
  1084. *
  1085. * DESCRIPTION: fnet_tcp_drain removes the temporary data.
  1086. *
  1087. * RETURNS: None.
  1088. *************************************************************************/
  1089. static void fnet_tcp_drain( void )
  1090. {
  1091. fnet_socket_t *sk;
  1092. fnet_socket_t *delsk;
  1093. fnet_tcp_control_t *cb;
  1094. fnet_isr_lock();
  1095. /* Receive the pointer to the first socket.*/
  1096. sk = fnet_tcp_prot_if.head;
  1097. while(sk)
  1098. {
  1099. cb = (fnet_tcp_control_t *)sk->protocol_control;
  1100. delsk = sk;
  1101. sk = sk->next;
  1102. /* if((cb->tcpcb_connection_state == FNET_TCP_CS_TIME_WAIT) && (cb->tcpcb_flags & FNET_TCP_CBF_CLOSE))*/
  1103. if((cb->tcpcb_flags & FNET_TCP_CBF_CLOSE))
  1104. {
  1105. /* Remove the socket that to be closed. */
  1106. fnet_tcp_closesk(delsk);
  1107. }
  1108. /* Delete all partial and incoming connections */
  1109. else if(delsk->state == SS_LISTENING)
  1110. {
  1111. while(delsk->partial_con)
  1112. fnet_tcp_abortsk(delsk->partial_con);
  1113. #if 0
  1114. while (delsk->incoming_con)
  1115. fnet_tcp_abortsk(delsk->incoming_con);
  1116. #endif
  1117. }
  1118. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  1119. else
  1120. /* Remove the temporary data.*/
  1121. fnet_tcp_deletetmpbuf(cb);
  1122. #endif
  1123. }
  1124. fnet_isr_unlock();
  1125. }
  1126. /************************************************************************
  1127. * NAME: fnet_tcp_initconnection
  1128. *
  1129. * DESCRIPTION: This function creates and initializes the control block,
  1130. * and initializes the socket.
  1131. *
  1132. * RETURNS: None.
  1133. *************************************************************************/
  1134. static void fnet_tcp_initconnection( fnet_socket_t *sk )
  1135. {
  1136. fnet_tcp_control_t *cb;
  1137. cb = sk->protocol_control;
  1138. fnet_memset_zero(cb, sizeof(fnet_tcp_control_t));
  1139. /* Set the default maximal segment size value.*/
  1140. cb->tcpcb_sndmss = FNET_TCP_DEFAULT_MSS;
  1141. cb->tcpcb_rcvmss = sk->options.tcp_opt.mss;
  1142. /* Set the length of the socket buffers.*/
  1143. cb->tcpcb_rcvcountmax = sk->receive_buffer.count_max;
  1144. /* The input buffer can't be greater than the FNET_TCP_MAX_BUFFER value.*/
  1145. if(cb->tcpcb_rcvcountmax > FNET_TCP_MAX_BUFFER)
  1146. cb->tcpcb_rcvcountmax = FNET_TCP_MAX_BUFFER;
  1147. /* If a segment size greater than the buffer length, recalculate the segment size.*/
  1148. if(cb->tcpcb_rcvcountmax < cb->tcpcb_rcvmss)
  1149. cb->tcpcb_rcvmss = (unsigned short)cb->tcpcb_rcvcountmax;
  1150. /* Receive a scale of the input window.*/
  1151. while(FNET_TCP_MAXWIN << cb->tcpcb_recvscale < cb->tcpcb_rcvcountmax)
  1152. cb->tcpcb_recvscale++;
  1153. /* Stop all timers.*/
  1154. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  1155. cb->tcpcb_timers.connection = FNET_TCP_TIMER_OFF;
  1156. cb->tcpcb_timers.abort = FNET_TCP_TIMER_OFF;
  1157. cb->tcpcb_timers.round_trip = FNET_TCP_TIMER_OFF;
  1158. cb->tcpcb_timers.persist = FNET_TCP_TIMER_OFF;
  1159. cb->tcpcb_timers.keepalive = FNET_TCP_TIMER_OFF;
  1160. cb->tcpcb_timers.delayed_ack = FNET_TCP_TIMER_OFF;
  1161. /* Initialize the retransmission timeout.*/
  1162. cb->tcpcb_rto = cb->tcpcb_crto = FNET_TCP_TIMERS_INIT;
  1163. #if FNET_CFG_TCP_URGENT
  1164. /* Initialize the receive urgent mark.*/
  1165. cb->tcpcb_rcvurgmark = FNET_TCP_NOT_USED;
  1166. #endif /* FNET_CFG_TCP_URGENT */
  1167. /* Initialize Slow Start Threshold.*/
  1168. cb->tcpcb_ssthresh = FNET_TCP_MAX_BUFFER;
  1169. /* Clear the input buffer.*/
  1170. if(sk->receive_buffer.count)
  1171. fnet_socket_buffer_release(&sk->receive_buffer);
  1172. }
  1173. /************************************************************************
  1174. * NAME: fnet_tcp_inputsk
  1175. *
  1176. * DESCRIPTION: This function processes the input segments of
  1177. * the corresponding socket.
  1178. *
  1179. * RETURNS: TRUE if the input segment must be deleted. Otherwise
  1180. * this function returns FALSE.
  1181. *************************************************************************/
  1182. static int fnet_tcp_inputsk( fnet_socket_t *sk, fnet_netbuf_t *insegment, struct sockaddr *src_addr, struct sockaddr *dest_addr)
  1183. {
  1184. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  1185. fnet_tcp_control_t *pcb; /* Pointer to the partial control block.*/
  1186. unsigned char sgmtype; /* Flags of the segment.*/
  1187. fnet_socket_t *psk; /* Pointer to the partial socket.*/
  1188. int result = FNET_TRUE;
  1189. char options[FNET_TCP_MAX_OPT_SIZE];
  1190. char optionlen;
  1191. unsigned long repsize; /* Size of repeated data.*/
  1192. int ackparam = 0; /* Acknowledgment parameter.*/
  1193. unsigned long tcp_seq = fnet_ntohl(FNET_TCP_SEQ(insegment));
  1194. unsigned long tcp_length = (unsigned long)FNET_TCP_LENGTH(insegment);
  1195. unsigned long tcp_ack = fnet_ntohl(FNET_TCP_ACK(insegment));
  1196. /* Get the flags.*/
  1197. sgmtype = (unsigned char)(FNET_TCP_FLAGS(insegment));
  1198. /* Check the sequence number.*/
  1199. switch(cb->tcpcb_connection_state)
  1200. {
  1201. case FNET_TCP_CS_SYN_SENT:
  1202. case FNET_TCP_CS_LISTENING:
  1203. break;
  1204. case FNET_TCP_CS_SYN_RCVD:
  1205. if(cb->tcpcb_prev_connection_state == FNET_TCP_CS_SYN_SENT && (sgmtype & FNET_TCP_SGT_SYN))
  1206. {
  1207. /* Check the sequence number for simultaneouos open.*/
  1208. if(tcp_seq == cb->tcpcb_sndack - 1)
  1209. break;
  1210. }
  1211. default:
  1212. if(FNET_TCP_COMP_G(cb->tcpcb_sndack, tcp_seq))
  1213. {
  1214. if(FNET_TCP_COMP_G(tcp_seq + insegment->total_length - tcp_length, cb->tcpcb_sndack))
  1215. {
  1216. /* Delete the left repeated part.*/
  1217. repsize = fnet_tcp_getsize(tcp_seq, cb->tcpcb_sndack);
  1218. fnet_netbuf_cut_center(&insegment, (int)tcp_length, (int)repsize);
  1219. /* If urgent flag is present, recalculate of the urgent pointer.*/
  1220. if(sgmtype & FNET_TCP_SGT_URG)
  1221. {
  1222. if((int)fnet_ntohs(FNET_TCP_URG(insegment)) - (int)repsize >= 0)
  1223. {
  1224. FNET_TCP_URG(insegment) = fnet_htons((unsigned short)(fnet_ntohs(FNET_TCP_URG(insegment)) - repsize));
  1225. }
  1226. else
  1227. {
  1228. sgmtype &= ~FNET_TCP_SGT_URG;
  1229. FNET_TCP_SET_FLAGS(insegment) = sgmtype;
  1230. }
  1231. }
  1232. /* Set the sequence number.*/
  1233. tcp_seq = cb->tcpcb_sndack;
  1234. FNET_TCP_SEQ(insegment) = fnet_htonl(tcp_seq);
  1235. /* Acknowledgment must be sent immediatelly.*/
  1236. ackparam |= FNET_TCP_AP_SEND_IMMEDIATELLY;
  1237. }
  1238. else
  1239. {
  1240. /* Segment is repeated */
  1241. /* Send the acknowledgment */
  1242. fnet_tcp_sendack(sk);
  1243. return FNET_TRUE;
  1244. }
  1245. }
  1246. if(FNET_TCP_COMP_G(tcp_seq, cb->tcpcb_sndack + cb->tcpcb_rcvwnd))
  1247. {
  1248. /* Segment is not in the window*/
  1249. /* Send the acknowledgment */
  1250. fnet_tcp_sendack(sk);
  1251. return FNET_TRUE;
  1252. }
  1253. else
  1254. {
  1255. if(FNET_TCP_COMP_G(tcp_seq + insegment->total_length - tcp_length, cb->tcpcb_sndack + cb->tcpcb_rcvwnd))
  1256. {
  1257. /* Delete the right part that is not in the window.*/
  1258. fnet_netbuf_trim(&insegment, -(int)fnet_tcp_getsize(cb->tcpcb_sndack + cb->tcpcb_rcvwnd,
  1259. (unsigned long)(tcp_seq + insegment->total_length - tcp_length)));
  1260. /* Acknowledgment must be sent immediatelly.*/
  1261. ackparam |= FNET_TCP_AP_SEND_IMMEDIATELLY;
  1262. }
  1263. }
  1264. }
  1265. /* Process the reset segment with acknowledgment.*/
  1266. if((sgmtype &(FNET_TCP_SGT_RST | FNET_TCP_SGT_ACK)) == (FNET_TCP_SGT_RST | FNET_TCP_SGT_ACK))
  1267. {
  1268. if(cb->tcpcb_connection_state == FNET_TCP_CS_SYN_SENT)
  1269. {
  1270. if(tcp_ack == cb->tcpcb_sndseq)
  1271. /* Close the socket (connecting is failed).*/
  1272. sk->options.local_error = FNET_ERR_CONNRESET;
  1273. fnet_tcp_closesk(sk);
  1274. return FNET_TRUE;
  1275. }
  1276. }
  1277. /* Process the reset segment without acknowledgment.*/
  1278. if(sgmtype & FNET_TCP_SGT_RST)
  1279. {
  1280. switch(cb->tcpcb_connection_state)
  1281. {
  1282. case FNET_TCP_CS_LISTENING:
  1283. case FNET_TCP_CS_SYN_SENT:
  1284. return FNET_TRUE;
  1285. default:
  1286. /* Close the socket.*/
  1287. sk->options.local_error = FNET_ERR_CONNRESET;
  1288. fnet_tcp_closesk(sk);
  1289. }
  1290. return FNET_TRUE;
  1291. }
  1292. /* Process the SYN segment.*/
  1293. if(sgmtype & FNET_TCP_SGT_SYN)
  1294. {
  1295. switch(cb->tcpcb_connection_state)
  1296. {
  1297. case FNET_TCP_CS_SYN_SENT:
  1298. case FNET_TCP_CS_LISTENING:
  1299. break;
  1300. case FNET_TCP_CS_SYN_RCVD:
  1301. if((cb->tcpcb_prev_connection_state == FNET_TCP_CS_SYN_SENT) && (tcp_seq == (cb->tcpcb_sndack - 1)))
  1302. break;
  1303. default:
  1304. /* Close the socket and send the reset segment.*/
  1305. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1306. fnet_tcp_closesk(sk);
  1307. return FNET_TRUE;
  1308. }
  1309. }
  1310. else
  1311. {
  1312. /* Process the segment without SYN flag.*/
  1313. switch(cb->tcpcb_connection_state)
  1314. {
  1315. case FNET_TCP_CS_LISTENING:
  1316. if(sgmtype & FNET_TCP_SGT_ACK)
  1317. /* Send the reset segment.*/
  1318. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1319. return FNET_TRUE;
  1320. case FNET_TCP_CS_SYN_SENT:
  1321. if(sgmtype & FNET_TCP_SGT_ACK)
  1322. /* Send the reset segment.*/
  1323. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1324. return FNET_TRUE;
  1325. default:
  1326. break; /* do nothing, avoid compiler warning "enumeration value not handled in switch" */
  1327. }
  1328. }
  1329. /* Process the segment with acknowledgment.*/
  1330. if(sgmtype & FNET_TCP_SGT_ACK)
  1331. {
  1332. switch(cb->tcpcb_connection_state)
  1333. {
  1334. case FNET_TCP_CS_SYN_SENT:
  1335. case FNET_TCP_CS_SYN_RCVD:
  1336. if(tcp_ack != cb->tcpcb_sndseq)
  1337. {
  1338. /* Send the reset segment.*/
  1339. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1340. return FNET_TRUE;
  1341. }
  1342. break;
  1343. case FNET_TCP_CS_LISTENING:
  1344. /* Send the reset segment.*/
  1345. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1346. return FNET_TRUE;
  1347. default:
  1348. if(!fnet_tcp_hit(cb->tcpcb_rcvack, cb->tcpcb_maxrcvack, tcp_ack))
  1349. {
  1350. if(FNET_TCP_COMP_G(tcp_ack, cb->tcpcb_maxrcvack))
  1351. /* Send the acknowledgment.*/
  1352. fnet_tcp_sendack(sk);
  1353. return FNET_TRUE;
  1354. }
  1355. }
  1356. }
  1357. else
  1358. {
  1359. /* Process the segment without acknowledgment.*/
  1360. switch(cb->tcpcb_connection_state)
  1361. {
  1362. case FNET_TCP_CS_SYN_SENT:
  1363. case FNET_TCP_CS_LISTENING:
  1364. break;
  1365. case FNET_TCP_CS_SYN_RCVD:
  1366. fnet_tcp_sendack(sk);
  1367. default:
  1368. return FNET_TRUE;
  1369. }
  1370. }
  1371. /* Set the window size (of another side).*/
  1372. if(sgmtype & FNET_TCP_SGT_SYN)
  1373. cb->tcpcb_sndwnd = fnet_ntohs(FNET_TCP_WND(insegment));
  1374. else
  1375. cb->tcpcb_sndwnd = (unsigned long)(fnet_ntohs(FNET_TCP_WND(insegment)) << cb->tcpcb_sendscale);
  1376. if(cb->tcpcb_maxwnd < cb->tcpcb_sndwnd)
  1377. cb->tcpcb_maxwnd = cb->tcpcb_sndwnd;
  1378. /* Main processing.*/
  1379. switch(cb->tcpcb_connection_state)
  1380. {
  1381. case FNET_TCP_CS_SYN_SENT:
  1382. cb->tcpcb_sndack = tcp_seq + 1;
  1383. /* Process the second segment of the open.*/
  1384. if(sgmtype & FNET_TCP_SGT_ACK)
  1385. {
  1386. cb->tcpcb_rcvack = tcp_ack;
  1387. #if FNET_CFG_TCP_URGENT
  1388. /* Initialize the urgent sequence number.*/
  1389. cb->tcpcb_rcvurgseq = tcp_seq;
  1390. #endif /* FNET_CFG_TCP_URGENT */
  1391. /* Receive the options.*/
  1392. fnet_tcp_getopt(sk, insegment);
  1393. fnet_tcp_getsynopt(sk);
  1394. /* If MSS of another side 0, return.*/
  1395. if(!cb->tcpcb_sndmss)
  1396. {
  1397. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1398. fnet_tcp_closesk(sk);
  1399. return FNET_TRUE;
  1400. }
  1401. /* Stop the timers.*/
  1402. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  1403. cb->tcpcb_timers.connection = FNET_TCP_TIMER_OFF;
  1404. /* Send the acknowledgment (third segment of the open).*/
  1405. fnet_tcp_sendack(sk);
  1406. /* Change the states.*/
  1407. cb->tcpcb_connection_state = FNET_TCP_CS_ESTABLISHED;
  1408. sk->state = SS_CONNECTED;
  1409. /* Initialize the keepalive timer.*/
  1410. if(sk->options.flags & SO_KEEPALIVE)
  1411. cb->tcpcb_timers.keepalive = sk->options.tcp_opt.keep_idle;
  1412. break;
  1413. }
  1414. else
  1415. /* Process the simultaneous open.*/
  1416. {
  1417. /* Reinitialize the retrasmission timer.*/
  1418. cb->tcpcb_timers.retransmission = cb->tcpcb_rto;
  1419. /* Receive the options.*/
  1420. fnet_tcp_getopt(sk, insegment);
  1421. fnet_tcp_getsynopt(sk);
  1422. /* If MSS of another side 0, return.*/
  1423. if(!cb->tcpcb_sndmss)
  1424. {
  1425. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1426. fnet_tcp_closesk(sk);
  1427. return FNET_TRUE;
  1428. }
  1429. #if FNET_CFG_TCP_URGENT
  1430. /* Initialize the urgent sequence number.*/
  1431. cb->tcpcb_rcvurgseq = tcp_seq;
  1432. #endif /* FNET_CFG_TCP_URGENT */
  1433. /* Change the states.*/
  1434. cb->tcpcb_connection_state = FNET_TCP_CS_SYN_RCVD;
  1435. cb->tcpcb_prev_connection_state = FNET_TCP_CS_SYN_SENT;
  1436. /* Send acknowledgment.*/
  1437. fnet_tcp_sendack(sk);
  1438. break;
  1439. }
  1440. /* Process the first segment.*/
  1441. case FNET_TCP_CS_LISTENING:
  1442. /* If socket can't be created, return.*/
  1443. if(sk->partial_con_len + sk->incoming_con_len >= sk->con_limit)
  1444. {
  1445. fnet_memset_zero(&sk->foreign_addr, sizeof(sk->foreign_addr));
  1446. cb->tcpcb_sndwnd = 0;
  1447. cb->tcpcb_maxwnd = 0;
  1448. break;
  1449. }
  1450. /* Create the socket.*/
  1451. psk = fnet_socket_copy(sk);
  1452. fnet_memset_zero(&sk->foreign_addr, sizeof(sk->foreign_addr));
  1453. /* Check the memory allocation.*/
  1454. if(!psk)
  1455. {
  1456. cb->tcpcb_sndwnd = 0;
  1457. cb->tcpcb_maxwnd = 0;
  1458. break;
  1459. }
  1460. /* Set the local address.*/
  1461. psk->local_addr = *dest_addr;
  1462. /* Create the control block.*/
  1463. pcb = (fnet_tcp_control_t *)fnet_malloc_zero(sizeof(fnet_tcp_control_t));
  1464. /* Check the memory allocation.*/
  1465. if(!pcb)
  1466. {
  1467. fnet_free(psk);
  1468. cb->tcpcb_sndwnd = 0;
  1469. cb->tcpcb_maxwnd = 0;
  1470. break;
  1471. }
  1472. /* Initialize the pointer.*/
  1473. psk->protocol_control = (void *)pcb;
  1474. fnet_tcp_initconnection(psk);
  1475. /* Copy the control block parameters.*/
  1476. pcb->tcpcb_sndwnd = cb->tcpcb_sndwnd;
  1477. pcb->tcpcb_maxwnd = cb->tcpcb_maxwnd;
  1478. cb->tcpcb_sndwnd = 0;
  1479. cb->tcpcb_maxwnd = 0;
  1480. /* Add the new socket to the partial list.*/
  1481. fnet_tcp_addpartialsk(sk, psk);
  1482. /* Initialize the parameters of the control block.*/
  1483. pcb->tcpcb_sndack = tcp_seq + 1;
  1484. pcb->tcpcb_sndseq = fnet_tcp_isntime;
  1485. pcb->tcpcb_maxrcvack = fnet_tcp_isntime + 1;
  1486. #if FNET_CFG_TCP_URGENT
  1487. pcb->tcpcb_sndurgseq = pcb->tcpcb_sndseq;
  1488. pcb->tcpcb_rcvurgseq = tcp_seq;
  1489. #endif /* FNET_CFG_TCP_URGENT */
  1490. /* Change the states.*/
  1491. psk->state = SS_CONNECTING;
  1492. pcb->tcpcb_prev_connection_state = FNET_TCP_CS_LISTENING;
  1493. pcb->tcpcb_connection_state = FNET_TCP_CS_SYN_RCVD;
  1494. /* Receive the options.*/
  1495. fnet_tcp_getopt(psk, insegment);
  1496. fnet_tcp_getsynopt(psk);
  1497. /* If MSS of another side 0, return.*/
  1498. if(!pcb->tcpcb_sndmss)
  1499. {
  1500. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1501. fnet_tcp_closesk(psk);
  1502. break;
  1503. }
  1504. /* Set the options.*/
  1505. fnet_tcp_setsynopt(psk, options, &optionlen);
  1506. /* Send SYN segment.*/
  1507. fnet_tcp_sendheadseg(psk, FNET_TCP_SGT_SYN | FNET_TCP_SGT_ACK, options, optionlen);
  1508. /* Increase ISN (Initial Sequence Number).*/
  1509. fnet_tcp_isntime += FNET_TCP_STEPISN;
  1510. /* Initialization the connection timer.*/
  1511. pcb->tcpcb_timers.connection = FNET_TCP_ABORT_INTERVAL_CON;
  1512. pcb->tcpcb_timers.retransmission = pcb->tcpcb_rto;
  1513. break;
  1514. case FNET_TCP_CS_SYN_RCVD:
  1515. /* Change the states.*/
  1516. cb->tcpcb_connection_state = FNET_TCP_CS_ESTABLISHED;
  1517. sk->state = SS_CONNECTED;
  1518. /* Stop the connection and retransmission timers.*/
  1519. cb->tcpcb_timers.connection = FNET_TCP_TIMER_OFF;
  1520. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  1521. cb->tcpcb_rcvack = tcp_ack;
  1522. /* If previous state is FNET_TCP_CS_LISTENING, process the acknowledgment (third segment of the open)
  1523. * Otherwise, process the SYN segment.*/
  1524. if(cb->tcpcb_prev_connection_state == FNET_TCP_CS_LISTENING)
  1525. {
  1526. /* Add the partial socket to the list of incoming socket.*/
  1527. fnet_tcp_movesk2incominglist(sk);
  1528. /* Proceed the processing.*/
  1529. result = fnet_tcp_dataprocess(sk, insegment, &ackparam);
  1530. break;
  1531. }
  1532. else
  1533. {
  1534. if(!(sgmtype & FNET_TCP_SGT_SYN))
  1535. {
  1536. /* Proseed the processing.*/
  1537. result = fnet_tcp_dataprocess(sk, insegment, &ackparam);
  1538. }
  1539. else
  1540. {
  1541. /* Initialize the keepalive timer.*/
  1542. if(sk->options.flags & SO_KEEPALIVE)
  1543. cb->tcpcb_timers.keepalive = sk->options.tcp_opt.keep_idle;
  1544. }
  1545. break;
  1546. }
  1547. case FNET_TCP_CS_FIN_WAIT_2:
  1548. case FNET_TCP_CS_CLOSE_WAIT:
  1549. case FNET_TCP_CS_ESTABLISHED:
  1550. /* Proseed the processing.*/
  1551. result = fnet_tcp_dataprocess(sk, insegment, &ackparam);
  1552. break;
  1553. case FNET_TCP_CS_FIN_WAIT_1:
  1554. /* Proseed the processing.*/
  1555. result = fnet_tcp_dataprocess(sk, insegment, &ackparam);
  1556. if(cb->tcpcb_sndseq == cb->tcpcb_rcvack && cb->tcpcb_connection_state == FNET_TCP_CS_FIN_WAIT_1)
  1557. /* Change the state.*/
  1558. cb->tcpcb_connection_state = FNET_TCP_CS_FIN_WAIT_2;
  1559. break;
  1560. case FNET_TCP_CS_LAST_ACK:
  1561. if(tcp_ack == cb->tcpcb_sndseq)
  1562. /* Close the socket.*/
  1563. fnet_tcp_closesk(sk);
  1564. return FNET_TRUE;
  1565. case FNET_TCP_CS_CLOSING:
  1566. if(tcp_ack == cb->tcpcb_sndseq)
  1567. {
  1568. cb->tcpcb_connection_state = FNET_TCP_CS_TIME_WAIT;
  1569. /* Set the timeout of the TIME_WAIT state.*/
  1570. cb->tcpcb_timers.connection = FNET_TCP_TIME_WAIT;
  1571. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  1572. cb->tcpcb_timers.keepalive = FNET_TCP_TIMER_OFF;
  1573. }
  1574. break;
  1575. case FNET_TCP_CS_TIME_WAIT:
  1576. fnet_tcp_sendrst(&sk->options, insegment, dest_addr, src_addr);
  1577. break;
  1578. default:
  1579. break; /* do nothing, avoid compiler warning "enumeration value not handled in switch" */
  1580. }
  1581. /* If the input buffer is closed, delete the input data.*/
  1582. if(sk->receive_buffer.is_shutdown && sk->receive_buffer.count)
  1583. fnet_socket_buffer_release(&sk->receive_buffer);
  1584. return result;
  1585. }
  1586. /************************************************************************
  1587. * NAME: fnet_tcp_dataprocess
  1588. *
  1589. * DESCRIPTION: This function proceeds the processing of the input segemnt.
  1590. *
  1591. * RETURNS: TRUE if the input segment must be deleted. Otherwise
  1592. * this function returns FALSE.
  1593. *************************************************************************/
  1594. static int fnet_tcp_dataprocess( fnet_socket_t *sk, fnet_netbuf_t *insegment, int *ackparam )
  1595. {
  1596. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  1597. long size;
  1598. int err;
  1599. int delflag = 1;
  1600. unsigned long seq;
  1601. unsigned long tcp_ack = fnet_ntohl(FNET_TCP_ACK(insegment));
  1602. /* Reinitialize the keepalive timer.*/
  1603. if(sk->options.flags & SO_KEEPALIVE)
  1604. cb->tcpcb_timers.keepalive = sk->options.tcp_opt.keep_idle;
  1605. else
  1606. cb->tcpcb_timers.keepalive = FNET_TCP_TIMER_OFF;
  1607. /* Reset the abort timer.*/
  1608. cb->tcpcb_timers.abort = FNET_TCP_TIMER_OFF;
  1609. /* If acknowledgment is repeated.*/
  1610. if(cb->tcpcb_rcvack == tcp_ack)
  1611. {
  1612. /* If unacknowledged data is present.*/
  1613. if(cb->tcpcb_sndseq != cb->tcpcb_rcvack && sk->send_buffer.count)
  1614. {
  1615. /* Increase the timer of rpeated acknowledgments.*/
  1616. cb->tcpcb_fastretrcounter++;
  1617. /* If the number of repeated acknowledgments is FNET_TCP_NUMBER_FOR_FAST_RET,
  1618. * process the fast retransmission.*/
  1619. if(cb->tcpcb_fastretrcounter == FNET_TCP_NUMBER_FOR_FAST_RET)
  1620. {
  1621. /* Increase the timer of rpeated acknowledgments.*/
  1622. cb->tcpcb_fastretrcounter++;
  1623. /* Recalculate the congestion window and slow start threshold values.*/
  1624. if(cb->tcpcb_cwnd > cb->tcpcb_sndwnd)
  1625. cb->tcpcb_ssthresh = cb->tcpcb_sndwnd >> 1;
  1626. else
  1627. cb->tcpcb_ssthresh = cb->tcpcb_cwnd >> 1;
  1628. if(cb->tcpcb_ssthresh < (cb->tcpcb_sndmss << 1))
  1629. cb->tcpcb_ssthresh = (unsigned long)(cb->tcpcb_sndmss << 1);
  1630. cb->tcpcb_cwnd = cb->tcpcb_ssthresh;
  1631. /* Retransmit the segment.*/
  1632. seq = cb->tcpcb_sndseq;
  1633. cb->tcpcb_sndseq = cb->tcpcb_rcvack;
  1634. fnet_tcp_senddataseg(sk, 0, 0, cb->tcpcb_sndmss);
  1635. cb->tcpcb_sndseq = seq;
  1636. /* Acknowledgment is sent in retransmited segment.*/
  1637. *ackparam |= FNET_TCP_AP_NO_SENDING;
  1638. /* Round trip time can't be measured in this case.*/
  1639. cb->tcpcb_timers.round_trip = FNET_TCP_TIMER_OFF;
  1640. cb->tcpcb_timing_state = TCP_TS_SEGMENT_LOST;
  1641. }
  1642. }
  1643. }
  1644. else
  1645. {
  1646. /* Reset the counter of repeated acknowledgments.*/
  1647. cb->tcpcb_fastretrcounter = 0;
  1648. /* Recalculate the congestion window and slow start threshold values.*/
  1649. size = (long)fnet_tcp_getsize(cb->tcpcb_rcvack, tcp_ack);
  1650. if(size > sk->send_buffer.count)
  1651. size = (long)sk->send_buffer.count;
  1652. if(cb->tcpcb_cwnd < FNET_TCP_MAX_BUFFER)
  1653. {
  1654. if(cb->tcpcb_cwnd > cb->tcpcb_ssthresh)
  1655. {
  1656. /* Congestion avoidance mode.*/
  1657. cb->tcpcb_pcount += size;
  1658. }
  1659. else
  1660. {
  1661. /* Slow start mode.*/
  1662. if(cb->tcpcb_cwnd + size > cb->tcpcb_ssthresh)
  1663. {
  1664. cb->tcpcb_pcount = cb->tcpcb_pcount + cb->tcpcb_cwnd + size - cb->tcpcb_ssthresh;
  1665. cb->tcpcb_cwnd = cb->tcpcb_ssthresh;
  1666. }
  1667. else
  1668. {
  1669. cb->tcpcb_cwnd += size;
  1670. }
  1671. }
  1672. if(cb->tcpcb_pcount >= cb->tcpcb_cwnd)
  1673. {
  1674. cb->tcpcb_pcount -= cb->tcpcb_cwnd;
  1675. cb->tcpcb_cwnd += cb->tcpcb_sndmss;
  1676. }
  1677. }
  1678. /* Delete the acknowledged data.*/
  1679. fnet_netbuf_trim(&sk->send_buffer.net_buf_chain, size);
  1680. sk->send_buffer.count -= size;
  1681. /* Save the acknowledgment number.*/
  1682. cb->tcpcb_rcvack = tcp_ack;
  1683. if(FNET_TCP_COMP_G(cb->tcpcb_rcvack, cb->tcpcb_sndseq))
  1684. cb->tcpcb_sndseq = cb->tcpcb_rcvack;
  1685. /* Calculate the retransmission timeout ( using Jacobson method ).*/
  1686. if(FNET_TCP_COMP_GE(cb->tcpcb_rcvack, cb->tcpcb_timingack) && cb->tcpcb_timing_state == TCP_TS_SEGMENT_SENT)
  1687. {
  1688. if(cb->tcpcb_srtt)
  1689. {
  1690. err = /*(short)*/(cb->tcpcb_timers.round_trip - (cb->tcpcb_srtt >> FNET_TCP_RTT_SHIFT));
  1691. if((cb->tcpcb_srtt += err) <= 0)
  1692. cb->tcpcb_srtt = 1;
  1693. if(err < 0)
  1694. err = -err;
  1695. err -= (cb->tcpcb_rttvar >> FNET_TCP_RTTVAR_SHIFT);
  1696. if((cb->tcpcb_rttvar += err) <= 0)
  1697. cb->tcpcb_rttvar = 1;
  1698. }
  1699. else
  1700. {
  1701. /* Initial calculation of the retransmission variables.*/
  1702. cb->tcpcb_srtt = (cb->tcpcb_timers.round_trip + 1) << FNET_TCP_RTT_SHIFT;
  1703. cb->tcpcb_rttvar = (cb->tcpcb_timers.round_trip + 1)
  1704. << (FNET_TCP_RTTVAR_SHIFT - 1);
  1705. }
  1706. cb->tcpcb_timing_state = TCP_TS_ACK_RECEIVED;
  1707. cb->tcpcb_rto = (cb->tcpcb_srtt >> FNET_TCP_RTT_SHIFT) + cb->tcpcb_rttvar;
  1708. cb->tcpcb_timers.round_trip = FNET_TCP_TIMER_OFF;
  1709. }
  1710. }
  1711. /* If the final segment is not received, add the data to the input buffer.*/
  1712. if(!(cb->tcpcb_flags & FNET_TCP_CBF_FIN_RCVD))
  1713. {
  1714. delflag = !fnet_tcp_addinpbuf(sk, insegment, ackparam);
  1715. }
  1716. else if((insegment->total_length - FNET_TCP_LENGTH(insegment)) > 0)
  1717. *ackparam |= FNET_TCP_AP_SEND_IMMEDIATELLY;
  1718. /* Acknowledgment of the final segment must be send immediatelly.*/
  1719. if((*ackparam & FNET_TCP_AP_FIN_ACK)
  1720. ||(FNET_TCP_FLAGS(insegment) & FNET_TCP_SGT_PSH))
  1721. {
  1722. fnet_tcp_sendack(sk);
  1723. }
  1724. /* Try to sent the data.*/
  1725. if(fnet_tcp_sendanydata(sk, (int)(cb->tcpcb_flags & FNET_TCP_CBF_INSND)))
  1726. *ackparam |= FNET_TCP_AP_NO_SENDING;
  1727. /* If the window of another side is closed, turn on the persist timer.*/
  1728. if(!cb->tcpcb_sndwnd && sk->send_buffer.count)
  1729. {
  1730. if(cb->tcpcb_timers.persist == FNET_TCP_TIMER_OFF)
  1731. cb->tcpcb_cprto = cb->tcpcb_rto;
  1732. cb->tcpcb_timers.persist = cb->tcpcb_cprto;
  1733. }
  1734. else
  1735. {
  1736. if(!(cb->tcpcb_flags & FNET_TCP_CBF_SEND_TIMEOUT))
  1737. cb->tcpcb_timers.persist = FNET_TCP_TIMER_OFF;
  1738. }
  1739. /* If the sent data is acknowledged, turn of the retransmission timer.*/
  1740. if(cb->tcpcb_rcvack == cb->tcpcb_sndseq)
  1741. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  1742. else
  1743. cb->tcpcb_timers.retransmission = cb->tcpcb_rto;
  1744. /* If the acknowledgment is sent, return
  1745. * If the acnkowledgment must be sent immediatelly, send it
  1746. * If the acnkowledgment must be sent after delay, turn on the acknowledgment timer.*/
  1747. if((*ackparam & FNET_TCP_AP_NO_SENDING) || (*ackparam & FNET_TCP_AP_FIN_ACK))
  1748. return delflag;
  1749. if(*ackparam & FNET_TCP_AP_SEND_IMMEDIATELLY)
  1750. {
  1751. fnet_tcp_sendack(sk);
  1752. return delflag;
  1753. }
  1754. if(*ackparam & FNET_TCP_AP_SEND_WITH_DELAY)
  1755. cb->tcpcb_timers.delayed_ack = 1; /* Delay 200 ms*/
  1756. return delflag;
  1757. }
  1758. /***********************************************************************
  1759. * NAME: fnet_tcp_addinpbuf
  1760. *
  1761. * DESCRIPTION: This function adds the data to the input buffer and
  1762. * returns the acknowledgement parameter.
  1763. *
  1764. * RETURNS: TRUE if the input segment is added to the buffer. Otherwise
  1765. * this function returns FALSE.
  1766. *************************************************************************/
  1767. static int fnet_tcp_addinpbuf( fnet_socket_t *sk, fnet_netbuf_t *insegment, int *ackparam )
  1768. {
  1769. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  1770. unsigned long tcp_length = (unsigned long)FNET_TCP_LENGTH(insegment);
  1771. unsigned long tcp_flags = (unsigned long)FNET_TCP_FLAGS(insegment);
  1772. int result;
  1773. /* If segment doesn't include the data and the FIN or URG flag,
  1774. * return from the function.*/
  1775. if(!(insegment->total_length - tcp_length)
  1776. && !(tcp_flags & (FNET_TCP_SGT_URG | FNET_TCP_SGT_FIN)))
  1777. return 0; /* The data isn't added.*/
  1778. /* Process the segment that came in order.*/
  1779. if(fnet_ntohl(FNET_TCP_SEQ(insegment)) == cb->tcpcb_sndack
  1780. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  1781. && !cb->tcpcb_count
  1782. #endif
  1783. )
  1784. {
  1785. #if FNET_CFG_TCP_URGENT
  1786. if(tcp_flags & FNET_TCP_SGT_URG)
  1787. {
  1788. /* Process the urgent data.*/
  1789. fnet_tcp_urgprocessing(sk, &insegment, 0, ackparam);
  1790. }
  1791. else
  1792. {
  1793. /* Pull the receive urgent pointer
  1794. * along with the receive window */
  1795. cb->tcpcb_rcvurgseq = cb->tcpcb_sndack - 1;
  1796. }
  1797. #endif /* FNET_CFG_TCP_URGENT */
  1798. /* Process the final segment. */
  1799. if(tcp_flags & FNET_TCP_SGT_FIN)
  1800. {
  1801. fnet_tcp_finprocessing(sk, fnet_ntohl(FNET_TCP_ACK(insegment)));
  1802. cb->tcpcb_sndack++;
  1803. *ackparam |= FNET_TCP_AP_FIN_ACK;
  1804. }
  1805. /* Delete the header.*/
  1806. fnet_netbuf_trim(&insegment, (int)tcp_length);
  1807. /* Add the data.*/
  1808. if(insegment)
  1809. {
  1810. cb->tcpcb_sndack += insegment->total_length;
  1811. sk->receive_buffer.net_buf_chain = fnet_netbuf_concat(sk->receive_buffer.net_buf_chain,
  1812. insegment);
  1813. sk->receive_buffer.count += insegment->total_length;
  1814. *ackparam |= FNET_TCP_AP_SEND_WITH_DELAY;
  1815. }
  1816. return FNET_TRUE;
  1817. }
  1818. result = 0; /* The data is not added to the buffer.*/
  1819. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  1820. {
  1821. fnet_netbuf_t *buf, *prevbuf;
  1822. unsigned long seq, size;
  1823. /* Add to the temporary input buffer.*/
  1824. if(cb->tcpcb_count + insegment->total_length <= cb->tcpcb_rcvcountmax
  1825. || fnet_ntohl(FNET_TCP_SEQ(insegment)) == cb->tcpcb_sndack)
  1826. {
  1827. /* Acknowledgement must be sent immediately.*/
  1828. *ackparam |= FNET_TCP_AP_SEND_IMMEDIATELLY;
  1829. /* Data is added to the buffer.*/
  1830. result = 1;
  1831. /* Add the segment to the temporary buffer (with sorting).*/
  1832. if(cb->tcpcb_rcvchain)
  1833. {
  1834. buf = cb->tcpcb_rcvchain;
  1835. prevbuf = 0;
  1836. while(1)
  1837. {
  1838. if(FNET_TCP_COMP_G(fnet_ntohl(FNET_TCP_SEQ(buf)), fnet_ntohl(FNET_TCP_SEQ(insegment))))
  1839. {
  1840. if(prevbuf)
  1841. prevbuf->next_chain = insegment;
  1842. else
  1843. cb->tcpcb_rcvchain = insegment;
  1844. insegment->next_chain = buf;
  1845. break;
  1846. }
  1847. if(!buf->next_chain)
  1848. {
  1849. buf->next_chain = insegment;
  1850. break;
  1851. }
  1852. prevbuf = buf;
  1853. buf = buf->next_chain;
  1854. }
  1855. }
  1856. else
  1857. {
  1858. cb->tcpcb_rcvchain = insegment;
  1859. }
  1860. cb->tcpcb_count += insegment->total_length;
  1861. }
  1862. /* If the temporary buffer received the lost segment
  1863. * move the data from the temporary buffer to the input buffer of the socket.*/
  1864. if(fnet_ntohl(FNET_TCP_SEQ(insegment)) == cb->tcpcb_sndack)
  1865. {
  1866. seq = cb->tcpcb_sndack;
  1867. while(cb->tcpcb_rcvchain)
  1868. {
  1869. if(FNET_TCP_COMP_GE(seq, fnet_ntohl(FNET_TCP_SEQ(cb->tcpcb_rcvchain))))
  1870. {
  1871. if(FNET_TCP_COMP_GE(fnet_ntohl(FNET_TCP_SEQ(cb->tcpcb_rcvchain)) + cb->tcpcb_rcvchain->total_length
  1872. - FNET_TCP_LENGTH(cb->tcpcb_rcvchain),
  1873. seq))
  1874. {
  1875. /* Receive the size of the repeated segment.*/
  1876. size = fnet_tcp_getsize(fnet_ntohl(FNET_TCP_SEQ(cb->tcpcb_rcvchain)), seq);
  1877. /* Receive the new sequnce number.*/
  1878. seq = fnet_ntohl(FNET_TCP_SEQ(cb->tcpcb_rcvchain)) + cb->tcpcb_rcvchain->total_length
  1879. - FNET_TCP_LENGTH(cb->tcpcb_rcvchain);
  1880. /* Set the size of the temporary buffer.*/
  1881. cb->tcpcb_count -= cb->tcpcb_rcvchain->total_length;
  1882. buf = cb->tcpcb_rcvchain;
  1883. cb->tcpcb_rcvchain = cb->tcpcb_rcvchain->next_chain;
  1884. buf->next_chain = 0;
  1885. #if FNET_CFG_TCP_URGENT
  1886. if(FNET_TCP_FLAGS(buf) & FNET_TCP_SGT_URG)
  1887. {
  1888. /* Process the urgent data.*/
  1889. fnet_tcp_urgprocessing(sk, &buf, size, ackparam);
  1890. }
  1891. else
  1892. {
  1893. /* Pull the receive urgent pointer
  1894. * along with the receive window */
  1895. cb->tcpcb_rcvurgseq = cb->tcpcb_sndack - 1;
  1896. }
  1897. #endif
  1898. /* Process the final segment.*/
  1899. if(FNET_TCP_FLAGS(buf) & FNET_TCP_SGT_FIN)
  1900. {
  1901. fnet_tcp_finprocessing(sk, fnet_ntohl(FNET_TCP_ACK(buf)));
  1902. *ackparam |= FNET_TCP_AP_FIN_ACK;
  1903. seq++;
  1904. }
  1905. /* Delete the header and repeated part.*/
  1906. fnet_netbuf_trim(&buf, (int)(FNET_TCP_LENGTH(buf) + size));
  1907. /* Add the data.*/
  1908. if(buf)
  1909. {
  1910. sk->receive_buffer.count += buf->total_length;
  1911. sk->receive_buffer.net_buf_chain =
  1912. fnet_netbuf_concat(sk->receive_buffer.net_buf_chain,
  1913. buf);
  1914. }
  1915. /* Set the new acknowledgment number.*/
  1916. cb->tcpcb_sndack = seq;
  1917. }
  1918. else
  1919. {
  1920. /* Delete the repeated segment.*/
  1921. buf = cb->tcpcb_rcvchain;
  1922. cb->tcpcb_rcvchain = cb->tcpcb_rcvchain->next_chain;
  1923. /* Set the new size of the temporary buffer.*/
  1924. cb->tcpcb_count -= cb->tcpcb_rcvchain->total_length;
  1925. fnet_netbuf_free_chain(buf);
  1926. }
  1927. }
  1928. else
  1929. {
  1930. break;
  1931. }
  1932. }
  1933. }
  1934. }
  1935. #endif
  1936. return result;
  1937. }
  1938. /***********************************************************************
  1939. * NAME: fnet_tcp_sendanydata
  1940. *
  1941. * DESCRIPTION: This function sends the data that is allowed by the windows
  1942. * (The congestion window and the window of another side).
  1943. *
  1944. * RETURNS: TRUE if some data are sent. Otherwise
  1945. * this function returns FALSE.
  1946. *************************************************************************/
  1947. static int fnet_tcp_sendanydata( fnet_socket_t *sk, int oneexec )
  1948. {
  1949. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  1950. long sndwnd; /* Size of the data that can be sent.*/
  1951. unsigned long cwnd; /* Congestion window.*/
  1952. unsigned long sntdata; /* Size of data that is sent.*/
  1953. long wnd; /* Windows */
  1954. long datasize; /* Size of the data that can be sent from the output buffer.*/
  1955. int result = 0;
  1956. /* Reset the silly window avoidance flag.*/
  1957. cb->tcpcb_flags &= ~FNET_TCP_CBF_SEND_TIMEOUT;
  1958. /* Receive the size of the data that is sent.*/
  1959. sntdata = fnet_tcp_getsize(cb->tcpcb_rcvack, cb->tcpcb_sndseq);
  1960. /* Receive the size of the data that is allowed by the window.*/
  1961. wnd = (long)(cb->tcpcb_sndwnd - sntdata);
  1962. if(wnd < 0)
  1963. {
  1964. /* The window is shrinked.*/
  1965. cb->tcpcb_timing_state = TCP_TS_SEGMENT_LOST;
  1966. cb->tcpcb_sndseq += wnd;
  1967. sntdata += wnd;
  1968. wnd = 0;
  1969. }
  1970. /* The size of the data in the output buffer that can be sent.*/
  1971. datasize = (long)(sk->send_buffer.count - sntdata);
  1972. /* Congestion window.*/
  1973. cwnd = cb->tcpcb_cwnd - sntdata;
  1974. cwnd = ((unsigned long)(cwnd / cb->tcpcb_sndmss)) * cb->tcpcb_sndmss;
  1975. /* Calculate sndwnd (size of the data that will be sent).*/
  1976. if(wnd > cwnd)
  1977. sndwnd = (long)cwnd;
  1978. else
  1979. sndwnd = wnd;
  1980. if(sndwnd > datasize)
  1981. sndwnd = datasize;
  1982. /* If the data can't be sent.*/
  1983. if(sndwnd <= 0)
  1984. {
  1985. /* Send the final segment without data.*/
  1986. if(sk->send_buffer.is_shutdown && !datasize && !(cb->tcpcb_flags & FNET_TCP_CBF_FIN_SENT))
  1987. {
  1988. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_FIN | FNET_TCP_SGT_ACK, 0, 0);
  1989. /* Reinitialize the retransmission timer.*/
  1990. if(cb->tcpcb_timers.retransmission == FNET_TCP_TIMER_OFF)
  1991. cb->tcpcb_timers.retransmission = cb->tcpcb_rto;
  1992. result = 1;
  1993. }
  1994. return result;
  1995. }
  1996. /* The sntdata variable will include the size of the data that is sent.*/
  1997. sntdata = 0;
  1998. while(sndwnd > 0)
  1999. {
  2000. /* Sending of the maximal size segment.*/
  2001. if(cb->tcpcb_sndmss <= sndwnd)
  2002. {
  2003. /* Send the full sized segment.*/
  2004. fnet_tcp_senddataseg(sk, 0, 0, cb->tcpcb_sndmss);
  2005. sndwnd -= cb->tcpcb_sndmss;
  2006. sntdata += cb->tcpcb_sndmss;
  2007. }
  2008. else
  2009. {
  2010. /*The sending of the partial segments is occured in cases:
  2011. * If the data must be sent in any cases
  2012. * If the urgent data is present
  2013. * If the size of the input buffer of another side greater than the half of its maximal size
  2014. * If the Nagle algorithm is blocked and all data can be sent in this segment
  2015. * If all sent data is acknowledged and all data can be sent in this segment.*/
  2016. if(sndwnd > (cb->tcpcb_maxwnd >> 1)
  2017. || (cb->tcpcb_flags & FNET_TCP_CBF_FORCE_SEND)
  2018. #if FNET_CFG_TCP_URGENT
  2019. || FNET_TCP_COMP_GE(cb->tcpcb_sndurgseq, cb->tcpcb_sndseq)
  2020. #endif /* FNET_CFG_TCP_URGENT */
  2021. )
  2022. {
  2023. /* Send the partial segment.*/
  2024. fnet_tcp_senddataseg(sk, 0, 0, (unsigned long)sndwnd);
  2025. sntdata += sndwnd;
  2026. }
  2027. else
  2028. {
  2029. if(cb->tcpcb_rcvack == cb->tcpcb_sndseq || (sk->options.tcp_opt.flags & TCP_NODELAY))
  2030. {
  2031. if(sntdata + sndwnd == datasize)
  2032. {
  2033. /* Send the partial segment.*/
  2034. fnet_tcp_senddataseg(sk, 0, 0, (unsigned long)sndwnd);
  2035. sntdata += sndwnd;
  2036. }
  2037. else
  2038. {
  2039. /* Set the silly window avoidance flag.*/
  2040. if(cb->tcpcb_timers.persist == FNET_TCP_TIMER_OFF
  2041. || cb->tcpcb_timers.persist > cb->tcpcb_rto)
  2042. {
  2043. cb->tcpcb_cprto = cb->tcpcb_rto;
  2044. cb->tcpcb_timers.persist = cb->tcpcb_cprto;
  2045. }
  2046. cb->tcpcb_flags |= FNET_TCP_CBF_SEND_TIMEOUT;
  2047. }
  2048. }
  2049. }
  2050. sndwnd = 0;
  2051. }
  2052. /* If the execution of the function must be without delay, return.*/
  2053. if(oneexec)
  2054. break;
  2055. }
  2056. /* If the data is sent.*/
  2057. if(sntdata > 0)
  2058. {
  2059. /* Process the states of round trip time measurement.*/
  2060. if(cb->tcpcb_timing_state == TCP_TS_ACK_RECEIVED || (cb->tcpcb_timing_state == TCP_TS_SEGMENT_LOST
  2061. && FNET_TCP_COMP_G(cb->tcpcb_sndseq, cb->tcpcb_timingack)))
  2062. {
  2063. cb->tcpcb_timingack = cb->tcpcb_sndseq;
  2064. cb->tcpcb_timers.round_trip = FNET_TCP_TIMER_ON_INCREMENT;
  2065. cb->tcpcb_timing_state = TCP_TS_SEGMENT_SENT;
  2066. }
  2067. result = 1;
  2068. cb->tcpcb_timers.persist = FNET_TCP_TIMER_OFF;
  2069. }
  2070. /* Reinitialize the retransmission timer.*/
  2071. if(sntdata > 0 && cb->tcpcb_timers.retransmission == FNET_TCP_TIMER_OFF)
  2072. cb->tcpcb_timers.retransmission = cb->tcpcb_rto;
  2073. return result;
  2074. }
  2075. #if FNET_CFG_TCP_URGENT
  2076. /***********************************************************************
  2077. * NAME: fnet_tcp_urgprocessing
  2078. *
  2079. * DESCRIPTION: This function processes the urgent data.
  2080. *
  2081. * RETURNS: None.
  2082. *************************************************************************/
  2083. static void fnet_tcp_urgprocessing( fnet_socket_t *sk, fnet_netbuf_t ** segment, unsigned long repdatasize,
  2084. int *ackparam )
  2085. {
  2086. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2087. unsigned short upointer;
  2088. unsigned short uoffset;
  2089. fnet_netbuf_t *buf;
  2090. unsigned long tcp_seq;
  2091. buf = (fnet_netbuf_t *) *segment;
  2092. /* Receive the urgent pointer.*/
  2093. upointer = fnet_ntohs(FNET_TCP_URG(buf));
  2094. /* Different interpretation of the urgent pointer in the TCP header.*/
  2095. if(sk->options.tcp_opt.flags & TCP_BSD)
  2096. {
  2097. /* BSD interpretation.*/
  2098. if(!upointer)
  2099. return;
  2100. upointer--;
  2101. }
  2102. /* Only the new data must be processed.*/
  2103. if(upointer < repdatasize || (repdatasize && (buf->total_length - FNET_TCP_LENGTH(buf) <= repdatasize)))
  2104. return;
  2105. tcp_seq = fnet_ntohl(FNET_TCP_SEQ(buf));
  2106. /* Receive the new urgent pointer.*/
  2107. if(FNET_TCP_COMP_G(tcp_seq + upointer, cb->tcpcb_rcvurgseq))
  2108. cb->tcpcb_rcvurgseq = tcp_seq + upointer;
  2109. else
  2110. upointer = (unsigned short)(cb->tcpcb_rcvurgseq - tcp_seq);
  2111. /* If the urgent byte is not in this segment.*/
  2112. if(upointer >= buf->total_length - FNET_TCP_LENGTH(buf))
  2113. return;
  2114. /* Set the number of bytes before the urgent character.*/
  2115. cb->tcpcb_rcvurgmark = (long)(sk->receive_buffer.count + upointer);
  2116. /* If the urgent data must be in the stream, return from this function. */
  2117. if(sk->options.flags & SO_OOBINLINE)
  2118. return;
  2119. /* Find and read the urgent byte.*/
  2120. uoffset = (unsigned short)(upointer + FNET_TCP_LENGTH(buf));
  2121. while(uoffset >= buf->length)
  2122. {
  2123. uoffset -= buf->length;
  2124. buf = buf->next;
  2125. }
  2126. cb->tcpcb_flags |= FNET_TCP_CBF_RCVURGENT;
  2127. cb->tcpcb_iobc = (char)FNET_TCP_GETUCHAR(buf->data_ptr, uoffset);
  2128. cb->tcpcb_sndack++;
  2129. /* Delete the urgent byte from the stream.*/
  2130. fnet_netbuf_cut_center(segment, upointer + FNET_TCP_LENGTH((fnet_netbuf_t *)(*segment)), FNET_TRUE );
  2131. /* Acknowledgment must be sent immediately.*/
  2132. *ackparam |= FNET_TCP_AP_SEND_IMMEDIATELLY;
  2133. }
  2134. #endif /* FNET_CFG_TCP_URGENT */
  2135. /***********************************************************************
  2136. * NAME: fnet_tcp_finprocessing
  2137. *
  2138. * DESCRIPTION: This function processes the final segment.
  2139. *
  2140. * RETURNS: None.
  2141. *************************************************************************/
  2142. static void fnet_tcp_finprocessing( fnet_socket_t *sk, unsigned long ack )
  2143. {
  2144. /* Initialize the pointer to the control block.*/
  2145. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2146. /* Process the final segment depend on state.*/
  2147. switch(cb->tcpcb_connection_state)
  2148. {
  2149. case FNET_TCP_CS_ESTABLISHED:
  2150. cb->tcpcb_connection_state = FNET_TCP_CS_CLOSE_WAIT;
  2151. /*RStevens: The connection can remain in this state forever.
  2152. * The other end is still in the CLOSE_WAIT state, and can remain
  2153. * there forever, until the application decides to issue its close.*/
  2154. break;
  2155. case FNET_TCP_CS_FIN_WAIT_1:
  2156. if(ack != cb->tcpcb_sndseq)
  2157. {
  2158. /* Simultaneous close.*/
  2159. cb->tcpcb_connection_state = FNET_TCP_CS_CLOSING;
  2160. break;
  2161. }
  2162. case FNET_TCP_CS_FIN_WAIT_2:
  2163. cb->tcpcb_connection_state = FNET_TCP_CS_TIME_WAIT;
  2164. /* Set timewait timeout.*/
  2165. if(cb->tcpcb_timers.connection <= 0) /* If it was already set before by other state. */
  2166. cb->tcpcb_timers.connection = FNET_TCP_TIME_WAIT;
  2167. cb->tcpcb_timers.keepalive = FNET_TCP_TIMER_OFF;
  2168. break;
  2169. default:
  2170. return;
  2171. }
  2172. cb->tcpcb_flags |= FNET_TCP_CBF_FIN_RCVD;
  2173. }
  2174. /***********************************************************************
  2175. * NAME: tcp_rcvwnd
  2176. *
  2177. * DESCRIPTION: This function receives a new window size.
  2178. *
  2179. * RETURNS: The new window.
  2180. *************************************************************************/
  2181. static unsigned long fnet_tcp_getrcvwnd( fnet_socket_t *sk )
  2182. {
  2183. long wnd;
  2184. unsigned long rcvwnd;
  2185. /* Initialize the pointer to the control block.*/
  2186. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2187. rcvwnd = cb->tcpcb_rcvwnd;
  2188. /* Set the receive window size.*/
  2189. wnd = (long)(cb->tcpcb_rcvcountmax - sk->receive_buffer.count);
  2190. if(wnd < 0)
  2191. wnd = 0;
  2192. if(rcvwnd < wnd)
  2193. {
  2194. /* Window can be opened only on condition that*/
  2195. if(wnd - rcvwnd >= cb->tcpcb_rcvmss || wnd - rcvwnd >= (cb->tcpcb_rcvcountmax >> 1) || !rcvwnd)
  2196. rcvwnd = (unsigned long)wnd;
  2197. }
  2198. else
  2199. {
  2200. rcvwnd = (unsigned long)wnd;
  2201. }
  2202. return rcvwnd;
  2203. }
  2204. /************************************************************************
  2205. * NAME: fnet_tcp_slowtimo
  2206. *
  2207. * DESCRIPTION: This function processes the timeouts.
  2208. * (fnet_tcp_slowtimo is performed every 500 ms).
  2209. *
  2210. * RETURNS: None.
  2211. *************************************************************************/
  2212. static void fnet_tcp_slowtimo(void *cookie)
  2213. {
  2214. fnet_socket_t *sk;
  2215. fnet_socket_t *addedsk;
  2216. fnet_socket_t *nextsk;
  2217. FNET_COMP_UNUSED_ARG(cookie);
  2218. fnet_isr_lock();
  2219. sk = fnet_tcp_prot_if.head;
  2220. while(sk)
  2221. {
  2222. addedsk = sk->partial_con;
  2223. while(addedsk)
  2224. {
  2225. nextsk = addedsk->next;
  2226. /* Process the partial sockets.*/
  2227. fnet_tcp_slowtimosk(addedsk);
  2228. addedsk = nextsk;
  2229. }
  2230. addedsk = sk->incoming_con;
  2231. while(addedsk)
  2232. {
  2233. nextsk = addedsk->next;
  2234. /* Process the incoming sockets.*/
  2235. fnet_tcp_slowtimosk(addedsk);
  2236. addedsk = nextsk;
  2237. }
  2238. /* Processg the main socket.*/
  2239. nextsk = sk->next;
  2240. fnet_tcp_slowtimosk(sk);
  2241. sk = nextsk;
  2242. }
  2243. fnet_tcp_isntime += FNET_TCP_STEPISN;
  2244. fnet_isr_unlock();
  2245. }
  2246. /************************************************************************
  2247. * NAME: fnet_tcp_fasttimo
  2248. *
  2249. * DESCRIPTION: This function processes the timeouts
  2250. * (fnet_tcp_fasttimo is performed every 200 ms).
  2251. *
  2252. * RETURNS: None.
  2253. *************************************************************************/
  2254. static void fnet_tcp_fasttimo( void *cookie )
  2255. {
  2256. fnet_socket_t *sk;
  2257. fnet_socket_t *addedsk;
  2258. FNET_COMP_UNUSED_ARG(cookie);
  2259. fnet_isr_lock();
  2260. sk = fnet_tcp_prot_if.head;
  2261. while(sk)
  2262. {
  2263. fnet_tcp_fasttimosk(sk);
  2264. addedsk = sk->incoming_con;
  2265. while(addedsk)
  2266. {
  2267. fnet_tcp_fasttimosk(addedsk);
  2268. addedsk = addedsk->next;
  2269. }
  2270. sk = sk->next;
  2271. }
  2272. fnet_isr_unlock();
  2273. }
  2274. /************************************************************************
  2275. * NAME: fnet_tcp_slowtimosk
  2276. *
  2277. * DESCRIPTION: This function processes the timers of the socket
  2278. * (fnet_tcp_slowtimosk is performed every 500 ms).
  2279. *
  2280. * RETURNS: None.
  2281. *************************************************************************/
  2282. static void fnet_tcp_slowtimosk( fnet_socket_t *sk )
  2283. {
  2284. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2285. /* If the socket is not connected, return.*/
  2286. if(sk->state != SS_UNCONNECTED)
  2287. {
  2288. /* Check the abort timer.*/
  2289. if(cb->tcpcb_timers.abort != FNET_TCP_TIMER_OFF)
  2290. {
  2291. cb->tcpcb_timers.abort--;
  2292. if(!cb->tcpcb_timers.abort)
  2293. {
  2294. cb->tcpcb_timers.abort = FNET_TCP_TIMER_OFF;
  2295. if(sk->options.local_error != FNET_ERR_HOSTUNREACH)
  2296. sk->options.local_error = FNET_ERR_CONNABORTED;
  2297. fnet_tcp_closesk(sk);
  2298. return;
  2299. }
  2300. }
  2301. /* Check the connection timer.*/
  2302. if(cb->tcpcb_timers.connection != FNET_TCP_TIMER_OFF)
  2303. {
  2304. cb->tcpcb_timers.connection--;
  2305. if(!cb->tcpcb_timers.connection)
  2306. {
  2307. cb->tcpcb_timers.connection = FNET_TCP_TIMER_OFF;
  2308. if(cb->tcpcb_flags & FNET_TCP_CBF_CLOSE)
  2309. {
  2310. if(cb->tcpcb_connection_state == FNET_TCP_CS_TIME_WAIT)
  2311. fnet_tcp_closesk(sk);
  2312. else
  2313. fnet_tcp_abortsk(sk);
  2314. }
  2315. else
  2316. {
  2317. if(sk->options.local_error != FNET_ERR_HOSTUNREACH
  2318. && sk->options.local_error != FNET_ERR_NOPROTOOPT)
  2319. sk->options.local_error = FNET_ERR_TIMEDOUT;
  2320. fnet_tcp_closesk(sk);
  2321. }
  2322. return;
  2323. }
  2324. }
  2325. /* Check the retransmission timer.*/
  2326. if(cb->tcpcb_timers.retransmission != FNET_TCP_TIMER_OFF)
  2327. {
  2328. cb->tcpcb_timers.retransmission--;
  2329. if(!cb->tcpcb_timers.retransmission)
  2330. {
  2331. cb->tcpcb_timers.retransmission = FNET_TCP_TIMER_OFF;
  2332. fnet_tcp_rtimeo(sk);
  2333. }
  2334. }
  2335. /* Check the keepalive timer.*/
  2336. if(cb->tcpcb_timers.keepalive != FNET_TCP_TIMER_OFF)
  2337. {
  2338. cb->tcpcb_timers.keepalive--;
  2339. if(!cb->tcpcb_timers.keepalive)
  2340. {
  2341. cb->tcpcb_timers.keepalive = FNET_TCP_TIMER_OFF;
  2342. fnet_tcp_ktimeo(sk);
  2343. }
  2344. }
  2345. /* Check the persist timer.*/
  2346. if(cb->tcpcb_timers.persist != FNET_TCP_TIMER_OFF)
  2347. {
  2348. cb->tcpcb_timers.persist--;
  2349. if(!cb->tcpcb_timers.persist)
  2350. {
  2351. cb->tcpcb_timers.persist = FNET_TCP_TIMER_OFF;
  2352. fnet_tcp_ptimeo(sk);
  2353. }
  2354. }
  2355. /* If the round trip timer is turned on, recalculate it.*/
  2356. if(cb->tcpcb_timers.round_trip != FNET_TCP_TIMER_OFF)
  2357. cb->tcpcb_timers.round_trip++;
  2358. }
  2359. }
  2360. /************************************************************************
  2361. * NAME: fnet_tcp_fasttimosk
  2362. *
  2363. * DESCRIPTION: This function processes the delayed acknowledgment timer
  2364. * of the socket (fnet_tcp_fasttimo is performed every 200 ms).
  2365. *
  2366. * RETURNS: None.
  2367. *************************************************************************/
  2368. static void fnet_tcp_fasttimosk( fnet_socket_t *sk )
  2369. {
  2370. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2371. if(sk->state != SS_UNCONNECTED)
  2372. {
  2373. /* Check the delayed acknowledgment timer.*/
  2374. if(cb->tcpcb_timers.delayed_ack != FNET_TCP_TIMER_OFF)
  2375. {
  2376. cb->tcpcb_timers.delayed_ack--;
  2377. if(!cb->tcpcb_timers.delayed_ack)
  2378. {
  2379. cb->tcpcb_timers.delayed_ack = FNET_TCP_TIMER_OFF;
  2380. fnet_tcp_sendack(sk);
  2381. return;
  2382. }
  2383. }
  2384. }
  2385. }
  2386. /************************************************************************
  2387. * NAME: fnet_tcp_rtimeo
  2388. *
  2389. * DESCRIPTION: This function processes the timeout of the retransmission
  2390. * timer.
  2391. *
  2392. * RETURNS: None.
  2393. *************************************************************************/
  2394. static void fnet_tcp_rtimeo( fnet_socket_t *sk )
  2395. {
  2396. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2397. char options[FNET_TCP_MAX_OPT_SIZE];
  2398. char optionlen;
  2399. switch(cb->tcpcb_connection_state)
  2400. {
  2401. case FNET_TCP_CS_SYN_RCVD:
  2402. /* Reinitialize of the sequnce number.*/
  2403. cb->tcpcb_sndseq--;
  2404. fnet_tcp_setsynopt(sk, options, &optionlen);
  2405. /* Create and send the SYN segment.*/
  2406. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_SYN | FNET_TCP_SGT_ACK, options, optionlen);
  2407. break;
  2408. case FNET_TCP_CS_SYN_SENT:
  2409. /* Retransmission of the first segment.*/
  2410. /* Recalculate the sequence number.*/
  2411. cb->tcpcb_sndseq--;
  2412. fnet_tcp_setsynopt(sk, options, &optionlen);
  2413. /* Send the SYN segment.*/
  2414. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_SYN, options, optionlen);
  2415. break;
  2416. default:
  2417. /* If FIN segment is sent, it must be retransmited.*/
  2418. cb->tcpcb_flags &= ~FNET_TCP_CBF_FIN_SENT;
  2419. /* Initialize of the abort timer.*/
  2420. if(cb->tcpcb_timers.abort == FNET_TCP_TIMER_OFF)
  2421. cb->tcpcb_timers.abort = FNET_TCP_ABORT_INTERVAL;
  2422. /* Recalculate the sequence number.*/
  2423. cb->tcpcb_sndseq = cb->tcpcb_rcvack;
  2424. /* Recalculate the congestion window and slow start threshold values (for case of retransmission).*/
  2425. if(cb->tcpcb_cwnd > cb->tcpcb_sndwnd)
  2426. cb->tcpcb_ssthresh = cb->tcpcb_sndwnd >> 1;
  2427. else
  2428. cb->tcpcb_ssthresh = cb->tcpcb_cwnd >> 1;
  2429. if(cb->tcpcb_ssthresh < (cb->tcpcb_sndmss << 1))
  2430. cb->tcpcb_ssthresh = (unsigned long)(cb->tcpcb_sndmss << 1);
  2431. cb->tcpcb_cwnd = cb->tcpcb_sndmss;
  2432. /* Round trip time can't be measured in this case.*/
  2433. cb->tcpcb_timers.round_trip = FNET_TCP_TIMER_OFF;
  2434. cb->tcpcb_timing_state = TCP_TS_SEGMENT_LOST;
  2435. cb->tcpcb_flags |= FNET_TCP_CBF_FORCE_SEND;
  2436. fnet_tcp_sendanydata(sk, 0);
  2437. cb->tcpcb_flags &= ~FNET_TCP_CBF_FORCE_SEND;
  2438. }
  2439. /* If the first timeout is occured, initialize the retransmission timer.*/
  2440. if(cb->tcpcb_retrseq != cb->tcpcb_rcvack)
  2441. {
  2442. cb->tcpcb_crto = cb->tcpcb_rto;
  2443. cb->tcpcb_retrseq = cb->tcpcb_rcvack;
  2444. }
  2445. /* Recalculate the retransission timer.*/
  2446. if(cb->tcpcb_crto != FNET_TCP_TIMERS_LIMIT)
  2447. {
  2448. if((cb->tcpcb_crto << 1) > FNET_TCP_TIMERS_LIMIT)
  2449. /* Timeout must be less or equal than TIMER_LIMIT.*/
  2450. cb->tcpcb_crto = FNET_TCP_TIMERS_LIMIT;
  2451. else
  2452. /* Increase the timeout (*2).*/
  2453. cb->tcpcb_crto <<= 1;
  2454. }
  2455. cb->tcpcb_timers.retransmission = cb->tcpcb_crto;
  2456. }
  2457. /************************************************************************
  2458. * NAME: fnet_tcp_ktimeo
  2459. *
  2460. * DESCRIPTION: This function processes the timeout of the keepalive
  2461. * timer.
  2462. *
  2463. * RETURNS: None.
  2464. *************************************************************************/
  2465. static void fnet_tcp_ktimeo( fnet_socket_t *sk )
  2466. {
  2467. fnet_netbuf_t *data;
  2468. unsigned short rcvwnd;
  2469. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2470. struct fnet_tcp_segment segment;
  2471. /* Create the keepalive segment.*/
  2472. data = fnet_netbuf_new(1, FNET_FALSE);
  2473. /* Check the memory allocation.*/
  2474. if(!data)
  2475. return;
  2476. /* Receive the window size.*/
  2477. rcvwnd = (unsigned short)(fnet_tcp_getrcvwnd(sk) >> cb->tcpcb_recvscale);
  2478. /* Send the segment.*/
  2479. segment.sockoption = &sk->options;
  2480. segment.src_addr = sk->local_addr;
  2481. segment.dest_addr = sk->foreign_addr;
  2482. segment.seq = cb->tcpcb_rcvack - 1;
  2483. segment.ack = cb->tcpcb_sndack;
  2484. segment.flags = FNET_TCP_SGT_ACK;
  2485. segment.wnd = rcvwnd;
  2486. segment.urgpointer = 0;
  2487. segment.options = 0;
  2488. segment.optlen = 0;
  2489. segment.data = data;
  2490. fnet_tcp_sendseg(&segment); /* TBD res check */
  2491. /* Set the timers.*/
  2492. cb->tcpcb_timers.keepalive = sk->options.tcp_opt.keep_intvl;
  2493. if((cb->tcpcb_timers.abort == FNET_TCP_TIMER_OFF) || (cb->tcpcb_timers.abort > (sk->options.tcp_opt.keep_cnt * sk->options.tcp_opt.keep_intvl) ))
  2494. {
  2495. cb->tcpcb_timers.abort = sk->options.tcp_opt.keep_cnt * sk->options.tcp_opt.keep_intvl;
  2496. }
  2497. }
  2498. /************************************************************************
  2499. * NAME: fnet_tcp_ptimeo
  2500. *
  2501. * DESCRIPTION: This function processes the timeout of the persist
  2502. * timer.
  2503. *
  2504. * RETURNS: None.
  2505. *************************************************************************/
  2506. static void fnet_tcp_ptimeo( fnet_socket_t *sk )
  2507. {
  2508. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2509. /* If the window is closed, send the probe segment
  2510. * Otherwise, try to send any data.*/
  2511. if(!cb->tcpcb_sndwnd)
  2512. {
  2513. fnet_tcp_senddataseg(sk, 0, 0, 1);
  2514. cb->tcpcb_sndseq--;
  2515. }
  2516. else
  2517. {
  2518. cb->tcpcb_flags |= FNET_TCP_CBF_FORCE_SEND;
  2519. fnet_tcp_sendanydata(sk, 0);
  2520. cb->tcpcb_flags &= ~FNET_TCP_CBF_FORCE_SEND;
  2521. return;
  2522. }
  2523. /* Reinitialize the persist timer.*/
  2524. if(cb->tcpcb_cprto != FNET_TCP_TIMERS_LIMIT)
  2525. {
  2526. if((cb->tcpcb_cprto << 1) > FNET_TCP_TIMERS_LIMIT)
  2527. /* Timeout must be less or equal than TIMER_LIMIT.*/
  2528. cb->tcpcb_cprto = FNET_TCP_TIMERS_LIMIT;
  2529. else
  2530. /* Increase the timeout (*2).*/
  2531. cb->tcpcb_cprto <<= 1;
  2532. }
  2533. cb->tcpcb_timers.persist = cb->tcpcb_cprto;
  2534. /* Initialize the abort timer.*/
  2535. if(cb->tcpcb_timers.abort == FNET_TCP_TIMER_OFF)
  2536. cb->tcpcb_timers.abort = FNET_TCP_ABORT_INTERVAL;
  2537. }
  2538. /************************************************************************
  2539. * NAME: fnet_tcp_sendseg
  2540. *
  2541. * DESCRIPTION: This function sends the segment.
  2542. *
  2543. * RETURNS: FNET_OK if the segment is sent. Otherwise
  2544. * this function returns the error code.
  2545. *************************************************************************/
  2546. static int fnet_tcp_sendseg(struct fnet_tcp_segment *segment)
  2547. {
  2548. fnet_netbuf_t *nb;
  2549. int error = FNET_OK;
  2550. fnet_netif_t *netif;
  2551. FNET_COMP_PACKED_VAR unsigned short *checksum_p;
  2552. #if FNET_CFG_IP6
  2553. if(segment->dest_addr.sa_family == AF_INET6)
  2554. {
  2555. /* Check Scope ID.*/
  2556. netif = fnet_netif_get_by_scope_id( ((struct sockaddr_in6 *)(&segment->dest_addr))->sin6_scope_id );
  2557. }
  2558. else
  2559. #endif
  2560. netif = FNET_NULL;
  2561. /* Create the header.*/
  2562. nb = fnet_netbuf_new(FNET_TCP_SIZE_HEADER, FNET_FALSE);
  2563. if(!nb)
  2564. {
  2565. if(segment->data)
  2566. fnet_netbuf_free_chain(segment->data);
  2567. return FNET_ERR_NOMEM;
  2568. }
  2569. fnet_memset_zero(nb->data_ptr, FNET_TCP_SIZE_HEADER);
  2570. /* Add TCP options.*/
  2571. if(segment->options && segment->optlen)
  2572. {
  2573. error = (unsigned char)fnet_tcp_addopt(nb, (unsigned char)segment->optlen, segment->options);
  2574. if(error)
  2575. {
  2576. fnet_netbuf_free_chain(nb);
  2577. if(segment->data)
  2578. fnet_netbuf_free_chain(segment->data);
  2579. return error;
  2580. }
  2581. }
  2582. else
  2583. {
  2584. FNET_TCP_SET_LENGTH(nb) = FNET_TCP_SIZE_HEADER << 2; /* (FNET_TCP_SIZE_HEADER/4 + opt_len/4) */
  2585. }
  2586. /* Initialization of the header.*/
  2587. FNET_TCP_SPORT(nb) = segment->src_addr.sa_port;
  2588. FNET_TCP_DPORT(nb) = segment->dest_addr.sa_port;
  2589. FNET_TCP_SEQ(nb) = fnet_htonl(segment->seq);
  2590. FNET_TCP_ACK(nb) = fnet_htonl(segment->ack);
  2591. FNET_TCP_SET_FLAGS(nb) = segment->flags;
  2592. FNET_TCP_WND(nb) = fnet_htons(segment->wnd);
  2593. /* Add the data.*/
  2594. nb = fnet_netbuf_concat(nb, segment->data);
  2595. /* Set the pointer to the urgent data.*/
  2596. FNET_TCP_URG(nb) = fnet_htons(segment->urgpointer);
  2597. /* Checksum calculation.*/
  2598. FNET_TCP_CHECKSUM(nb) = 0;
  2599. #if FNET_CFG_UDP_CHECKSUM
  2600. #if FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM
  2601. if( 0
  2602. #if FNET_CFG_IP4
  2603. ||( (segment->dest_addr.sa_family == AF_INET)
  2604. && ((netif = fnet_ip_route(((struct sockaddr_in *)(&segment->dest_addr))->sin_addr.s_addr))!= FNET_NULL)
  2605. && (netif->features & FNET_NETIF_FEATURE_HW_TX_PROTOCOL_CHECKSUM)
  2606. && (fnet_ip_will_fragment(netif, nb->total_length) == FNET_FALSE) /* Fragmented packets are not inspected.*/ )
  2607. #endif
  2608. #if FNET_CFG_IP6
  2609. ||( (segment->dest_addr.sa_family == AF_INET6)
  2610. && (netif || ((netif = fnet_ip6_route(&((struct sockaddr_in6 *)(&segment->src_addr))->sin6_addr.s6_addr, &((struct sockaddr_in6 *)(&segment->dest_addr))->sin6_addr.s6_addr))!= FNET_NULL ) )
  2611. && (netif->features & FNET_NETIF_FEATURE_HW_TX_PROTOCOL_CHECKSUM)
  2612. && (fnet_ip6_will_fragment(netif, nb->total_length) == FNET_FALSE) /* Fragmented packets are not inspected.*/ )
  2613. #endif
  2614. )
  2615. {
  2616. nb->flags |= FNET_NETBUF_FLAG_HW_PROTOCOL_CHECKSUM;
  2617. checksum_p = 0;
  2618. }
  2619. else
  2620. #endif /* FNET_CFG_CPU_ETH_HW_TX_IP_CHECKSUM */
  2621. {
  2622. FNET_TCP_CHECKSUM(nb) = fnet_checksum_pseudo_start(nb, FNET_HTONS((unsigned short)FNET_IP_PROTOCOL_TCP), (unsigned short)nb->total_length);
  2623. checksum_p = &FNET_TCP_CHECKSUM(nb);
  2624. }
  2625. #endif /* FNET_CFG_UDP_CHECKSUM */
  2626. #if FNET_CFG_IP4
  2627. if(segment->dest_addr.sa_family == AF_INET)
  2628. {
  2629. error = fnet_ip_output(netif, ((struct sockaddr_in *)(&segment->src_addr))->sin_addr.s_addr,
  2630. ((struct sockaddr_in *)(&segment->dest_addr))->sin_addr.s_addr,
  2631. FNET_IP_PROTOCOL_TCP,
  2632. (unsigned char)(segment->sockoption ? segment->sockoption->ip_opt.tos : 0),
  2633. (unsigned char)(segment->sockoption ? segment->sockoption->ip_opt.ttl : FNET_TCP_TTL_DEFAULT),
  2634. nb, 0,
  2635. (segment->sockoption ? ((segment->sockoption->flags & SO_DONTROUTE) > 0) : 0),
  2636. checksum_p);
  2637. }
  2638. else
  2639. #endif
  2640. #if FNET_CFG_IP6
  2641. if(segment->dest_addr.sa_family == AF_INET6)
  2642. {
  2643. error = fnet_ip6_output( netif,
  2644. &((struct sockaddr_in6 *)(&segment->src_addr))->sin6_addr.s6_addr,
  2645. &((struct sockaddr_in6 *)(&segment->dest_addr))->sin6_addr.s6_addr,
  2646. FNET_IP_PROTOCOL_TCP,
  2647. (unsigned char)(segment->sockoption ? segment->sockoption->ip6_opt.hops_unicast : 0 /*default*/),
  2648. nb,
  2649. checksum_p );
  2650. }
  2651. else
  2652. #endif
  2653. {};
  2654. return error;
  2655. }
  2656. /************************************************************************
  2657. * NAME: fnet_tcp_sendheadseg
  2658. *
  2659. * DESCRIPTION: This function sends the segment wihout data.
  2660. *
  2661. * RETURNS: TRUE if no error occurs. Otherwise
  2662. * this function returns the error code.
  2663. *************************************************************************/
  2664. static int fnet_tcp_sendheadseg( fnet_socket_t *sk, unsigned char flags, void *options, char optlen )
  2665. {
  2666. unsigned long seq;
  2667. unsigned short wnd;
  2668. int error = FNET_OK;
  2669. unsigned long ack = 0;
  2670. unsigned short urgpointer = 0;
  2671. struct fnet_tcp_segment segment;
  2672. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2673. /* Get the sequence number.*/
  2674. seq = cb->tcpcb_sndseq;
  2675. /* Get the window.*/
  2676. cb->tcpcb_rcvwnd = fnet_tcp_getrcvwnd(sk);
  2677. /* Process the SYN flag.*/
  2678. if(flags & FNET_TCP_SGT_SYN)
  2679. {
  2680. seq++;
  2681. if(cb->tcpcb_rcvwnd > FNET_TCP_MAXWIN)
  2682. wnd = FNET_TCP_MAXWIN;
  2683. else
  2684. wnd = (unsigned short)cb->tcpcb_rcvwnd;
  2685. }
  2686. else
  2687. {
  2688. wnd = (unsigned short)(cb->tcpcb_rcvwnd >> cb->tcpcb_recvscale);
  2689. }
  2690. /* Process the FIN flag.*/
  2691. if(flags & FNET_TCP_SGT_FIN)
  2692. {
  2693. seq++;
  2694. /* Change the state after sending of the final segment*/
  2695. if(cb->tcpcb_connection_state == FNET_TCP_CS_ESTABLISHED)
  2696. cb->tcpcb_connection_state = FNET_TCP_CS_FIN_WAIT_1;
  2697. else if(cb->tcpcb_connection_state == FNET_TCP_CS_CLOSE_WAIT)
  2698. cb->tcpcb_connection_state = FNET_TCP_CS_LAST_ACK;
  2699. cb->tcpcb_flags |= FNET_TCP_CBF_FIN_SENT;
  2700. }
  2701. #if FNET_CFG_TCP_URGENT
  2702. /* Process the URG flag.*/
  2703. if((flags & FNET_TCP_SGT_URG)
  2704. && fnet_tcp_getsize(cb->tcpcb_sndseq, cb->tcpcb_sndurgseq) < FNET_TCP_MAXWIN)
  2705. {
  2706. urgpointer = (unsigned short)fnet_tcp_getsize(cb->tcpcb_sndseq, cb->tcpcb_sndurgseq);
  2707. if(sk->options.tcp_opt.flags & TCP_BSD)
  2708. urgpointer++;
  2709. }
  2710. #endif /* FNET_CFG_TCP_URGENT */
  2711. /* Process the ACK flag.*/
  2712. if(flags & FNET_TCP_SGT_ACK)
  2713. ack = cb->tcpcb_sndack;
  2714. /* Send the segment.*/
  2715. segment.sockoption = &sk->options;
  2716. segment.src_addr = sk->local_addr;
  2717. segment.dest_addr = sk->foreign_addr;
  2718. segment.seq = cb->tcpcb_sndseq;
  2719. segment.ack = ack;
  2720. segment.flags = flags;
  2721. segment.wnd = wnd;
  2722. segment.urgpointer = urgpointer;
  2723. segment.options = options;
  2724. segment.optlen = optlen;
  2725. segment.data = 0;
  2726. error = fnet_tcp_sendseg(&segment);
  2727. /* Turn off the delayed acknowledgment timer.*/
  2728. cb->tcpcb_timers.delayed_ack = FNET_TCP_TIMER_OFF;
  2729. cb->tcpcb_newfreercvsize = 0;
  2730. /* Set the new sequence number.*/
  2731. cb->tcpcb_sndseq = seq;
  2732. if(FNET_TCP_COMP_G(cb->tcpcb_sndseq, cb->tcpcb_maxrcvack))
  2733. cb->tcpcb_maxrcvack = cb->tcpcb_sndseq;
  2734. return error;
  2735. }
  2736. /************************************************************************
  2737. * NAME: fnet_tcp_senddataseg
  2738. *
  2739. * DESCRIPTION: This function sends the data segment.
  2740. *
  2741. * RETURNS: TRUE if no error occurs. Otherwise
  2742. * this function returns the error code.
  2743. *************************************************************************/
  2744. static int fnet_tcp_senddataseg( fnet_socket_t *sk, void *options, char optlen, unsigned long datasize )
  2745. {
  2746. unsigned char flags;
  2747. long newdatasize; /* Datasize that can be sent.*/
  2748. unsigned long urgpointer = 0; /* Pointer of the urgent data.*/
  2749. fnet_netbuf_t *data = 0; /* Data pointer.*/
  2750. unsigned long seq; /* Sequence number.*/
  2751. int error;
  2752. unsigned long tmp;
  2753. struct fnet_tcp_segment segment;
  2754. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2755. /* Receive the sequence number.*/
  2756. seq = cb->tcpcb_sndseq;
  2757. /* Reset the flags.*/
  2758. flags = 0;
  2759. /* Data that can be sent.*/
  2760. newdatasize = (long)(sk->send_buffer.count - fnet_tcp_getsize(cb->tcpcb_rcvack, cb->tcpcb_sndseq));
  2761. /* Check the data size.*/
  2762. if(datasize > newdatasize)
  2763. datasize = (unsigned long)newdatasize;
  2764. #if FNET_CFG_IP4
  2765. tmp = fnet_ip_maximum_packet(((struct sockaddr_in *)(&sk->foreign_addr))->sin_addr.s_addr);
  2766. #else /* TBD */
  2767. tmp = 0;
  2768. #endif
  2769. if((datasize + FNET_TCP_SIZE_HEADER) > tmp)
  2770. datasize = (tmp - FNET_TCP_SIZE_HEADER);
  2771. /* Create the flags.*/
  2772. flags |= FNET_TCP_SGT_ACK;
  2773. /* If the data of the segment is the last in the output buffer,*/
  2774. /* Set PSH flag.*/
  2775. if(newdatasize == datasize && datasize)
  2776. flags |= FNET_TCP_SGT_PSH;
  2777. #if FNET_CFG_TCP_URGENT
  2778. /* Process the urgent request.*/
  2779. if(FNET_TCP_COMP_GE(cb->tcpcb_sndurgseq, cb->tcpcb_sndseq))
  2780. {
  2781. if(fnet_tcp_getsize(cb->tcpcb_sndseq, cb->tcpcb_sndurgseq) < FNET_TCP_MAX_URG_POINTER)
  2782. {
  2783. /* Set the urgent pointer.*/
  2784. urgpointer = fnet_tcp_getsize(cb->tcpcb_sndseq, cb->tcpcb_sndurgseq);
  2785. flags |= FNET_TCP_SGT_URG;
  2786. /* If the BSD interpretation, increase the urgent pointer.*/
  2787. if(sk->options.tcp_opt.flags & TCP_BSD)
  2788. urgpointer++;
  2789. }
  2790. }
  2791. else
  2792. {
  2793. /* Pull the send urgent pointer along with the send window.*/
  2794. if(FNET_TCP_COMP_G(cb->tcpcb_rcvack - 1, cb->tcpcb_sndurgseq))
  2795. cb->tcpcb_sndurgseq = cb->tcpcb_rcvack - 1;
  2796. }
  2797. #endif /* FNET_CFG_TCP_URGENT */
  2798. /* If final segment must be sent.*/
  2799. if(sk->send_buffer.is_shutdown)
  2800. {
  2801. if(newdatasize == datasize)
  2802. {
  2803. /* End of the data sending.*/
  2804. flags |= FNET_TCP_SGT_FIN;
  2805. seq++;
  2806. /* Change the state after the sending of the final segment.*/
  2807. if(cb->tcpcb_connection_state == FNET_TCP_CS_ESTABLISHED)
  2808. cb->tcpcb_connection_state = FNET_TCP_CS_FIN_WAIT_1;
  2809. else if(cb->tcpcb_connection_state == FNET_TCP_CS_CLOSE_WAIT)
  2810. cb->tcpcb_connection_state = FNET_TCP_CS_LAST_ACK;
  2811. cb->tcpcb_flags |= FNET_TCP_CBF_FIN_SENT;
  2812. }
  2813. }
  2814. /* Receive the window size.*/
  2815. cb->tcpcb_rcvwnd = fnet_tcp_getrcvwnd(sk);
  2816. /* If the data is present, add it.*/
  2817. if(datasize)
  2818. {
  2819. data = fnet_netbuf_copy(sk->send_buffer.net_buf_chain, (int)(sk->send_buffer.count - newdatasize),
  2820. (int)datasize, 0);
  2821. /* Check the memory allocation.*/
  2822. if(!data)
  2823. {
  2824. cb->tcpcb_sndseq = seq + datasize;
  2825. return FNET_ERR_NOMEM;
  2826. }
  2827. }
  2828. /* Send the segment.*/
  2829. segment.sockoption = &sk->options;
  2830. segment.src_addr = sk->local_addr;
  2831. segment.dest_addr = sk->foreign_addr;
  2832. segment.seq = cb->tcpcb_sndseq;
  2833. segment.ack = cb->tcpcb_sndack;
  2834. segment.flags = flags;
  2835. segment.wnd = (unsigned short)(cb->tcpcb_rcvwnd >> cb->tcpcb_recvscale);
  2836. segment.urgpointer = (unsigned short)urgpointer;
  2837. segment.options = options;
  2838. segment.optlen = optlen;
  2839. segment.data = data;
  2840. error = fnet_tcp_sendseg(&segment);
  2841. /* Turn off the delayed acknowledgment timer.*/
  2842. cb->tcpcb_timers.delayed_ack = FNET_TCP_TIMER_OFF;
  2843. cb->tcpcb_newfreercvsize = 0;
  2844. /* Set the new sequence number.*/
  2845. cb->tcpcb_sndseq = seq + datasize;
  2846. if(FNET_TCP_COMP_G(cb->tcpcb_sndseq, cb->tcpcb_maxrcvack))
  2847. cb->tcpcb_maxrcvack = cb->tcpcb_sndseq;
  2848. return error;
  2849. }
  2850. /************************************************************************
  2851. * NAME: fnet_tcp_sendack
  2852. *
  2853. * DESCRIPTION: This function sends the acknowledgement segment.
  2854. *
  2855. * RETURNS: None.
  2856. *************************************************************************/
  2857. static void fnet_tcp_sendack( fnet_socket_t *sk )
  2858. {
  2859. char options[FNET_TCP_MAX_OPT_SIZE];
  2860. char optionlen;
  2861. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2862. switch(cb->tcpcb_connection_state)
  2863. {
  2864. /* In the SYN_RCVD state acknowledgement must be with the SYN flag.*/
  2865. case FNET_TCP_CS_SYN_RCVD:
  2866. /* Reinitialize of the sequnce number.*/
  2867. cb->tcpcb_sndseq--;
  2868. fnet_tcp_setsynopt(sk, options, &optionlen);
  2869. /* Create and send the SYN segment.*/
  2870. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_SYN | FNET_TCP_SGT_ACK, options, optionlen);
  2871. break;
  2872. /* In the FIN_WAIT_1 and LAST_ACK states acknowledgement must be with the FIN flag.*/
  2873. case FNET_TCP_CS_FIN_WAIT_1:
  2874. case FNET_TCP_CS_LAST_ACK:
  2875. /* Reinitialize the sequnce number.*/
  2876. cb->tcpcb_sndseq--;
  2877. /* Create and send the FIN segment.*/
  2878. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_FIN | FNET_TCP_SGT_ACK, 0, 0);
  2879. break;
  2880. default:
  2881. #if FNET_CFG_TCP_URGENT
  2882. /* If the urgent data is present, set the urgent flag.*/
  2883. if(FNET_TCP_COMP_GE(cb->tcpcb_sndurgseq, cb->tcpcb_sndseq))
  2884. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_ACK | FNET_TCP_SGT_URG, 0, 0);
  2885. else
  2886. #endif /* FNET_CFG_TCP_URGENT */
  2887. fnet_tcp_sendheadseg(sk, FNET_TCP_SGT_ACK, 0, 0);
  2888. break;
  2889. }
  2890. /* Turn of the delayed acknowledgment timer.*/
  2891. cb->tcpcb_timers.delayed_ack = FNET_TCP_TIMER_OFF;
  2892. }
  2893. /************************************************************************
  2894. * NAME: fnet_tcp_sendrst
  2895. *
  2896. * DESCRIPTION: This function sends the reset segment.
  2897. *
  2898. * RETURNS: None.
  2899. *************************************************************************/
  2900. static void fnet_tcp_sendrst( fnet_socket_option_t *sockoption, fnet_netbuf_t *insegment,
  2901. struct sockaddr *src_addr, struct sockaddr *dest_addr)
  2902. {
  2903. struct fnet_tcp_segment segment;
  2904. if(FNET_TCP_FLAGS(insegment) & FNET_TCP_SGT_ACK)
  2905. {
  2906. /* Send the reset segment without acknowledgment*/
  2907. segment.seq = fnet_ntohl(FNET_TCP_ACK(insegment));
  2908. segment.ack = 0;
  2909. segment.flags = FNET_TCP_SGT_RST;
  2910. }
  2911. else
  2912. {
  2913. /* Send the reset segment with acknowledgment*/
  2914. segment.seq = 0;
  2915. segment.ack = fnet_ntohl(FNET_TCP_SEQ(insegment)) + insegment->total_length - FNET_TCP_LENGTH(insegment)
  2916. + (FNET_TCP_SGT_FIN & FNET_TCP_FLAGS(insegment)) + ((FNET_TCP_SGT_SYN
  2917. & FNET_TCP_FLAGS(insegment)) >> 1);
  2918. segment.flags = FNET_TCP_SGT_RST | FNET_TCP_SGT_ACK;
  2919. }
  2920. segment.sockoption = sockoption;
  2921. segment.src_addr = *src_addr;
  2922. segment.dest_addr = *dest_addr;
  2923. segment.wnd = 0;
  2924. segment.urgpointer = 0;
  2925. segment.options = 0;
  2926. segment.optlen = 0;
  2927. segment.data = 0;
  2928. fnet_tcp_sendseg(&segment);
  2929. }
  2930. /************************************************************************
  2931. * NAME: fnet_tcp_sendrstsk
  2932. *
  2933. * DESCRIPTION: This function sends the reset segment.
  2934. *
  2935. * RETURNS: None.
  2936. *************************************************************************/
  2937. static void fnet_tcp_sendrstsk( fnet_socket_t *sk )
  2938. {
  2939. struct fnet_tcp_segment segment;
  2940. /* Initialize the pointer to the control block.*/
  2941. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  2942. if(sk->state != SS_UNCONNECTED && cb->tcpcb_connection_state != FNET_TCP_CS_SYN_SENT
  2943. && cb->tcpcb_connection_state != FNET_TCP_CS_TIME_WAIT)
  2944. {
  2945. if(cb->tcpcb_connection_state == FNET_TCP_CS_SYN_RCVD)
  2946. {
  2947. /* Send the reset segment with acknowledgment.*/
  2948. segment.seq = 0;
  2949. segment.ack = cb->tcpcb_sndack;
  2950. segment.flags = FNET_TCP_SGT_RST | FNET_TCP_SGT_ACK;
  2951. }
  2952. else
  2953. {
  2954. /* Send the reset segment without acknowledgment.*/
  2955. segment.seq = cb->tcpcb_rcvack;
  2956. segment.ack = 0;
  2957. segment.flags = FNET_TCP_SGT_RST;
  2958. }
  2959. segment.sockoption = &sk->options;
  2960. segment.src_addr = sk->local_addr;
  2961. segment.dest_addr = sk->foreign_addr;
  2962. segment.wnd = 0;
  2963. segment.urgpointer = 0;
  2964. segment.options = 0;
  2965. segment.optlen = 0;
  2966. segment.data = 0;
  2967. fnet_tcp_sendseg(&segment);
  2968. }
  2969. }
  2970. /************************************************************************
  2971. * NAME: fnet_tcp_abortsk
  2972. *
  2973. * DESCRIPTION: This function sends the reset segment and closes the socket.
  2974. *
  2975. * RETURNS: None.
  2976. *************************************************************************/
  2977. static void fnet_tcp_abortsk( fnet_socket_t *sk )
  2978. {
  2979. /* If the incoming or the partial socket is present, abort it.*/
  2980. if(sk->state == SS_LISTENING)
  2981. {
  2982. while(sk->partial_con)
  2983. fnet_tcp_abortsk(sk->partial_con);
  2984. while(sk->incoming_con)
  2985. fnet_tcp_abortsk(sk->incoming_con);
  2986. }
  2987. else
  2988. fnet_tcp_sendrstsk(sk);
  2989. /* Close the socket.*/
  2990. fnet_tcp_closesk(sk);
  2991. }
  2992. /************************************************************************
  2993. * NAME: fnet_tcp_addopt
  2994. *
  2995. * DESCRIPTION: This function adds the options in the segment.
  2996. * fnet_tcp_addopt can be used only before the data adding and only after
  2997. * the creating of the main header.
  2998. *
  2999. * RETURNS: If no error occurs, this function returns FNET_OK. Otherwise,
  3000. * it returns FNET_ERR.
  3001. *************************************************************************/
  3002. static int fnet_tcp_addopt( fnet_netbuf_t *segment, unsigned char len, void *data )
  3003. {
  3004. fnet_netbuf_t *buf;
  3005. int i;
  3006. char size; /* Size of options.*/
  3007. /* Create the buffer of the options.*/
  3008. buf = fnet_netbuf_new(FNET_TCP_SIZE_OPTIONS, FNET_FALSE);
  3009. /* Check the memory allocatio.*/
  3010. if(!buf)
  3011. return FNET_ERR_NOMEM;
  3012. /* Reset the buffer and add it to the header.*/
  3013. fnet_memset_zero(buf->data_ptr, FNET_TCP_SIZE_OPTIONS); /* Set to FNET_TCP_OTYPES_END.*/
  3014. segment = fnet_netbuf_concat(segment, buf);
  3015. buf = segment->next;
  3016. /* Copy the options.*/
  3017. for (i = 0; i < len; ++i)
  3018. FNET_TCP_GETUCHAR(buf->data_ptr, i) = FNET_TCP_GETUCHAR(data, i);
  3019. /* Set the length (this value is saved in 4-byte words format).*/
  3020. if(len & 0x3)
  3021. size = (char)((len & 0xfffc) + 4);
  3022. else
  3023. size = (char)len;
  3024. /* Trim the buffer of the options.*/
  3025. fnet_netbuf_trim(&segment, size - FNET_TCP_SIZE_OPTIONS);
  3026. /* Recalculate the header length.*/
  3027. FNET_TCP_SET_LENGTH(segment) = (unsigned char)((buf->length + FNET_TCP_SIZE_HEADER) << 2);
  3028. return FNET_OK;
  3029. }
  3030. /************************************************************************
  3031. * NAME: fnet_tcp_getopt
  3032. *
  3033. * DESCRIPTION: This function processes the received options.
  3034. *
  3035. * RETURNS: None.
  3036. *************************************************************************/
  3037. static void fnet_tcp_getopt( fnet_socket_t *sk, fnet_netbuf_t *segment )
  3038. {
  3039. int i; /* index variable.*/
  3040. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  3041. if(!segment)
  3042. return;
  3043. /* Start position of the options.*/
  3044. i = FNET_TCP_SIZE_HEADER;
  3045. /* Receive the of the options.*/
  3046. while(i < FNET_TCP_LENGTH(segment) && FNET_TCP_GETUCHAR(segment->data_ptr, i) != FNET_TCP_OTYPES_END)
  3047. {
  3048. if(FNET_TCP_GETUCHAR(segment->data_ptr, i) == FNET_TCP_OTYPES_NOP)
  3049. {
  3050. ++i;
  3051. }
  3052. else
  3053. {
  3054. if(i + 1 >= FNET_TCP_LENGTH(segment)
  3055. || i + FNET_TCP_GETUCHAR(segment->data_ptr, i + 1) - 1 >= FNET_TCP_LENGTH(segment))
  3056. break;
  3057. /* Process the options.*/
  3058. switch(FNET_TCP_GETUCHAR(segment->data_ptr, i))
  3059. {
  3060. case FNET_TCP_OTYPES_MSS:
  3061. cb->tcpcb_sndmss = fnet_ntohs(FNET_TCP_GETUSHORT(segment->data_ptr, i + 2));
  3062. break;
  3063. case FNET_TCP_OTYPES_WINDOW:
  3064. cb->tcpcb_sendscale = FNET_TCP_GETUCHAR(segment->data_ptr, i + 2);
  3065. if(cb->tcpcb_sendscale > FNET_TCP_MAX_WINSHIFT)
  3066. cb->tcpcb_sendscale = FNET_TCP_MAX_WINSHIFT;
  3067. cb->tcpcb_flags |= FNET_TCP_CBF_RCVD_SCALE;
  3068. break;
  3069. }
  3070. i += FNET_TCP_GETUCHAR(segment->data_ptr, i + 1);
  3071. }
  3072. }
  3073. }
  3074. /************************************************************************
  3075. * NAME: fnet_tcp_setsynopt
  3076. *
  3077. * DESCRIPTION: This function sets the options of the synchronized (SYN )
  3078. * segment.
  3079. * RETURNS: None.
  3080. *************************************************************************/
  3081. static void fnet_tcp_setsynopt( fnet_socket_t *sk, char *options, char *optionlen )
  3082. {
  3083. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  3084. *optionlen = 0;
  3085. /* If 0, detect MSS based on interface MTU minus "TCP,IP header size".*/
  3086. if(cb->tcpcb_rcvmss == 0)
  3087. {
  3088. #if FNET_CFG_IP4 /* TBD*/
  3089. fnet_netif_t *netif;
  3090. if((netif = fnet_ip_route(((struct sockaddr_in *)(&sk->foreign_addr))->sin_addr.s_addr)) != 0)
  3091. {
  3092. cb->tcpcb_rcvmss = (unsigned short) (netif->mtu - 40); /* MTU - [TCP,IP header size].*/
  3093. }
  3094. #else
  3095. cb->tcpcb_rcvmss = 0; /* TBD create FNET*/
  3096. #endif /* FNET_CFG_IP4 */ /* TBD */
  3097. }
  3098. /* Set the MSS option.*/
  3099. *((unsigned long *)(options + *optionlen)) = fnet_htonl((unsigned long)(cb->tcpcb_rcvmss | FNET_TCP_MSS_HEADER));
  3100. *optionlen += FNET_TCP_MSS_SIZE;
  3101. /* Set the window scale option.*/
  3102. *((unsigned long *)(options + *optionlen))
  3103. = fnet_htonl((unsigned long)((cb->tcpcb_recvscale | FNET_TCP_WINDOW_HEADER) << 8));
  3104. *optionlen += FNET_TCP_WINDOW_SIZE;
  3105. }
  3106. /************************************************************************
  3107. * NAME: fnet_tcp_getsynopt
  3108. *
  3109. * DESCRIPTION: This function performs the initialization depend on
  3110. * options of the synchronized (SYN) segment.
  3111. *
  3112. * RETURNS: None.
  3113. *************************************************************************/
  3114. static void fnet_tcp_getsynopt( fnet_socket_t *sk )
  3115. {
  3116. /* Pointer to the control block.*/
  3117. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  3118. if(!(cb->tcpcb_flags & FNET_TCP_CBF_RCVD_SCALE))
  3119. {
  3120. /* Reset the scale variable if the scale option is not received.*/
  3121. cb->tcpcb_recvscale = 0;
  3122. /* If the size of the input buffer greater than
  3123. * the maximal size of the window , reinitialze the buffer size.*/
  3124. if(cb->tcpcb_rcvcountmax > FNET_TCP_MAXWIN)
  3125. cb->tcpcb_rcvcountmax = FNET_TCP_MAXWIN;
  3126. }
  3127. /* Initialize the congestion window.*/
  3128. cb->tcpcb_cwnd = cb->tcpcb_sndmss;
  3129. }
  3130. /************************************************************************
  3131. * NAME: fnet_tcp_findsk
  3132. *
  3133. * DESCRIPTION: This function finds the socket with parameters that allow
  3134. * to receive and process the segment.
  3135. *
  3136. * RETURNS: If the socket is found this function returns the pointer to the
  3137. * socket. Otherwise, this function returns 0.
  3138. *************************************************************************/
  3139. static fnet_socket_t *fnet_tcp_findsk( struct sockaddr *src_addr, struct sockaddr *dest_addr )
  3140. {
  3141. fnet_socket_t *listensk = 0;
  3142. fnet_socket_t *sk;
  3143. fnet_isr_lock();
  3144. sk = fnet_tcp_prot_if.head;
  3145. while(sk)
  3146. {
  3147. if(sk->local_addr.sa_port == dest_addr->sa_port)
  3148. {
  3149. /* Listening socket.*/
  3150. if(sk->state == SS_LISTENING)
  3151. {
  3152. if(!listensk && (fnet_socket_addr_is_unspecified(&sk->local_addr) || fnet_socket_addr_are_equal(&sk->local_addr, dest_addr) ))
  3153. listensk = sk;
  3154. }
  3155. else
  3156. {
  3157. /* Not listening socket.*/
  3158. if(fnet_socket_addr_are_equal(&sk->local_addr, dest_addr) && sk->state != SS_UNCONNECTED &&
  3159. fnet_socket_addr_are_equal(&sk->foreign_addr, src_addr) && sk->foreign_addr.sa_port == src_addr->sa_port)
  3160. break;
  3161. }
  3162. }
  3163. sk = sk->next;
  3164. }
  3165. /* If the listening socket with the same local parameters (address and port) is present.*/
  3166. if(!sk && listensk)
  3167. {
  3168. /* Search the partial socket with the same foreign parameters (address and port).*/
  3169. sk = listensk->partial_con;
  3170. while(sk)
  3171. {
  3172. if(fnet_socket_addr_are_equal(&sk->foreign_addr, src_addr) && sk->foreign_addr.sa_port == src_addr->sa_port)
  3173. break;
  3174. sk = sk->next;
  3175. }
  3176. if(!sk)
  3177. {
  3178. /* Search the incoming socket with the same foreign parameters (address and port).*/
  3179. sk = listensk->incoming_con;
  3180. while(sk)
  3181. {
  3182. if(fnet_socket_addr_are_equal(&sk->foreign_addr, src_addr) && sk->foreign_addr.sa_port == src_addr->sa_port)
  3183. break;
  3184. sk = sk->next;
  3185. }
  3186. }
  3187. /* Listening socket is unique (with the same local parameters).*/
  3188. if(!sk)
  3189. sk = listensk;
  3190. }
  3191. fnet_isr_unlock();
  3192. return sk;
  3193. }
  3194. /***********************************************************************
  3195. * NAME: fnet_tcp_addpartialsk
  3196. *
  3197. * DESCRIPTION: This function adds the socket to the partial sockets list.
  3198. *
  3199. * RETURNS: None.
  3200. *************************************************************************/
  3201. static void fnet_tcp_addpartialsk( fnet_socket_t *mainsk, fnet_socket_t *partialsk )
  3202. {
  3203. mainsk->partial_con_len++;
  3204. partialsk->head_con = mainsk;
  3205. fnet_socket_list_add(&mainsk->partial_con, partialsk);
  3206. }
  3207. /***********************************************************************
  3208. * NAME: fnet_tcp_movesk2incominglist
  3209. *
  3210. * DESCRIPTION: This function moves socket from the partial list
  3211. * to the incoming list.
  3212. *
  3213. * RETURNS: None.
  3214. *************************************************************************/
  3215. static void fnet_tcp_movesk2incominglist( fnet_socket_t *sk )
  3216. {
  3217. fnet_socket_t *mainsk;
  3218. mainsk = sk->head_con;
  3219. mainsk->partial_con_len--;
  3220. mainsk->incoming_con_len++;
  3221. fnet_socket_list_del(&mainsk->partial_con, sk);
  3222. fnet_socket_list_add(&mainsk->incoming_con, sk);
  3223. }
  3224. /***********************************************************************
  3225. * NAME: fnet_tcp_closesk
  3226. *
  3227. * DESCRIPTION: This function closes the socket.
  3228. *
  3229. * RETURNS: None.
  3230. *************************************************************************/
  3231. static void fnet_tcp_closesk( fnet_socket_t *sk )
  3232. {
  3233. /* Initialize the pointer to the control block.*/
  3234. fnet_tcp_control_t *cb = (fnet_tcp_control_t *)sk->protocol_control;
  3235. if(sk->head_con)
  3236. {
  3237. /* If the socket is partial or incoming.*/
  3238. if(sk->state == SS_CONNECTING)
  3239. /* Delete from the partial list.*/
  3240. fnet_tcp_delpartialsk(sk);
  3241. else
  3242. /* Delete from the incoming list.*/
  3243. fnet_tcp_delincomingsk(sk);
  3244. }
  3245. else
  3246. {
  3247. /* If the socket must be deleted, free the structures
  3248. * Otherwise, change the state and free the unused data.*/
  3249. if(cb->tcpcb_flags & FNET_TCP_CBF_CLOSE)
  3250. {
  3251. fnet_tcp_delsk(&fnet_tcp_prot_if.head, sk);
  3252. }
  3253. else
  3254. {
  3255. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  3256. fnet_tcp_deletetmpbuf(cb);
  3257. #endif
  3258. fnet_socket_buffer_release(&sk->send_buffer);
  3259. sk->state = SS_UNCONNECTED;
  3260. fnet_memset_zero(&sk->foreign_addr, sizeof(sk->foreign_addr));
  3261. }
  3262. }
  3263. }
  3264. /***********************************************************************
  3265. * NAME: fnet_tcp_delpartialsk
  3266. *
  3267. * DESCRIPTION: This function deletes the socket from
  3268. * the partial list.
  3269. *
  3270. * RETURNS: None.
  3271. *************************************************************************/
  3272. static void fnet_tcp_delpartialsk( fnet_socket_t *sk )
  3273. {
  3274. sk->head_con->partial_con_len--;
  3275. fnet_tcp_delsk(&sk->head_con->partial_con, sk);
  3276. }
  3277. /***********************************************************************
  3278. * NAME: fnet_tcp_delincomingsk
  3279. *
  3280. * DESCRIPTION: This function deletes the socket from the incoming list.
  3281. *
  3282. * RETURNS: None.
  3283. *************************************************************************/
  3284. static void fnet_tcp_delincomingsk( fnet_socket_t *sk )
  3285. {
  3286. sk->head_con->incoming_con_len--;
  3287. fnet_tcp_delsk(&sk->head_con->incoming_con, sk);
  3288. }
  3289. /***********************************************************************
  3290. * NAME: fnet_tcp_delcb
  3291. *
  3292. * DESCRIPTION: This function deletes the control block.
  3293. *
  3294. * RETURNS: None.
  3295. *************************************************************************/
  3296. static void fnet_tcp_delcb( fnet_tcp_control_t *cb )
  3297. {
  3298. if(!cb)
  3299. return;
  3300. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  3301. fnet_tcp_deletetmpbuf(cb);
  3302. #endif
  3303. fnet_free(cb);
  3304. }
  3305. /***********************************************************************
  3306. * NAME: fnet_tcp_delcb
  3307. *
  3308. * DESCRIPTION: This function deletes the temporary buffer.
  3309. *
  3310. * RETURNS: None.
  3311. *************************************************************************/
  3312. #if !FNET_CFG_TCP_DISCARD_OUT_OF_ORDER
  3313. static void fnet_tcp_deletetmpbuf( fnet_tcp_control_t *cb )
  3314. {
  3315. fnet_netbuf_t *buf, *delbuf;
  3316. buf = cb->tcpcb_rcvchain;
  3317. while(buf)
  3318. {
  3319. delbuf = buf;
  3320. buf = buf->next_chain;
  3321. fnet_netbuf_free_chain(delbuf);
  3322. }
  3323. cb->tcpcb_count = 0;
  3324. cb->tcpcb_rcvchain = 0;
  3325. }
  3326. #endif
  3327. /***********************************************************************
  3328. * NAME: fnet_tcp_delsk
  3329. *
  3330. * DESCRIPTION: This function deletes the socket.
  3331. *
  3332. * RETURNS: None.
  3333. *************************************************************************/
  3334. static void fnet_tcp_delsk( fnet_socket_t ** head, fnet_socket_t *sk )
  3335. {
  3336. fnet_tcp_delcb((fnet_tcp_control_t *)sk->protocol_control);
  3337. fnet_socket_release(head, sk);
  3338. }
  3339. /***********************************************************************
  3340. * NAME: fnet_tcp_hit
  3341. *
  3342. * DESCRIPTION:
  3343. *
  3344. * RETURNS: This function returns TRUE if position (pos) is located
  3345. * in the interval between startpos and endpos. Otherwise
  3346. * this function returns FALSE.
  3347. *************************************************************************/
  3348. static int fnet_tcp_hit( unsigned long startpos, unsigned long endpos, unsigned long pos )
  3349. {
  3350. if(endpos >= startpos)
  3351. {
  3352. if(pos < startpos || pos > endpos)
  3353. return 0;
  3354. }
  3355. else
  3356. {
  3357. if(pos < startpos && pos > endpos)
  3358. return 0;
  3359. }
  3360. return 1;
  3361. }
  3362. /***********************************************************************
  3363. * NAME: fnet_tcp_getsize
  3364. *
  3365. * DESCRIPTION:
  3366. *
  3367. * RETURNS: This function returns the length of the interval
  3368. * (from pos1 to pos2 ).
  3369. *************************************************************************/
  3370. static unsigned long fnet_tcp_getsize( unsigned long pos1, unsigned long pos2 )
  3371. {
  3372. unsigned long size;
  3373. if(pos1 <= pos2)
  3374. {
  3375. size = pos2 - pos1;
  3376. }
  3377. else
  3378. {
  3379. size = FNET_TCP_MAX_SEQ - pos1 + pos2 + 1;
  3380. }
  3381. return size;
  3382. }
  3383. /************************************************************************
  3384. * NAME: fnet_tcp_trace
  3385. *
  3386. * DESCRIPTION: Prints TCP header. For debugging purposes.
  3387. *************************************************************************/
  3388. #if FNET_CFG_DEBUG_TRACE_TCP
  3389. void fnet_tcp_trace(char *str, fnet_tcp_header_t *tcp_hdr)
  3390. {
  3391. fnet_printf(FNET_SERIAL_ESC_FG_GREEN"%s", str); /* Print app-specific header.*/
  3392. fnet_println("[TCP header]"FNET_SERIAL_ESC_FG_BLACK);
  3393. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3394. fnet_println("|(SrcPort) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |(DestPort) "FNET_SERIAL_ESC_FG_BLUE"%3u"FNET_SERIAL_ESC_FG_BLACK" |",
  3395. fnet_ntohs(tcp_hdr->source_port),
  3396. fnet_ntohs(tcp_hdr->destination_port));
  3397. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3398. fnet_println("|(Sequence number) 0x%010u |",
  3399. fnet_ntohl(tcp_hdr->sequence_number));
  3400. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3401. fnet_println("|(ACK number) 0x%010u |",
  3402. fnet_ntohl(tcp_hdr->ack_number));
  3403. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3404. fnet_println("|(HL)%2u | |(F) %u%u%u%u%u%u|(Window) %5u |",
  3405. FNET_TCP_HEADER_GET_HDRLENGTH(tcp_hdr),
  3406. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) >> 5 & 1,
  3407. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) >> 4 & 1,
  3408. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) >> 3 & 1,
  3409. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) >> 2 & 1,
  3410. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) >> 1 & 1,
  3411. FNET_TCP_HEADER_GET_FLAGS(tcp_hdr) & 1,
  3412. fnet_ntohs(tcp_hdr->window) );
  3413. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3414. fnet_println("|(Checksum) 0x%04u |(Urgent ptr) %5u |",
  3415. fnet_ntohs(tcp_hdr->checksum),
  3416. fnet_ntohs(tcp_hdr->urgent_ptr));
  3417. fnet_println("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+");
  3418. }
  3419. #endif /* FNET_CFG_DEBUG_TRACE_TCP */
  3420. #if 0 /* For Debug needs.*/
  3421. /*************************************************************************/
  3422. int FNET_DEBUG_check_send_buffer( fnet_socket_t *sk)
  3423. {
  3424. fnet_netbuf_t *head_nb;
  3425. fnet_netbuf_t *nb = (sk->send_buffer.net_buf_chain);
  3426. int i = 0;
  3427. if(nb == 0)
  3428. return FNET_OK;
  3429. head_nb = nb;
  3430. while(nb->next != 0)
  3431. {
  3432. i++;
  3433. nb = nb->next;
  3434. if(i > 100)
  3435. {
  3436. fnet_println("!!!SEND BUF CHAIN CRASH!!!");
  3437. return FNET_ERR;
  3438. }
  3439. }
  3440. return FNET_OK;
  3441. }
  3442. #endif
  3443. #endif