Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

tcp.c 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include <string.h>
  2. #include <assert.h>
  3. #include <byteswap.h>
  4. #include <latch.h>
  5. #include <gpxe/process.h>
  6. #include <gpxe/init.h>
  7. #include <gpxe/netdevice.h>
  8. #include <gpxe/pkbuff.h>
  9. #include <gpxe/ip.h>
  10. #include <gpxe/tcp.h>
  11. #include "uip/uip.h"
  12. /** @file
  13. *
  14. * TCP protocol
  15. *
  16. * The gPXE TCP stack is currently implemented on top of the uIP
  17. * protocol stack. This file provides wrappers around uIP so that
  18. * higher-level protocol implementations do not need to talk directly
  19. * to uIP (which has a somewhat baroque API).
  20. *
  21. * Basic operation is to create a #tcp_connection structure, call
  22. * tcp_connect() and then call run_tcpip() in a loop until the
  23. * operation has completed. The TCP stack will call the various
  24. * methods defined in the #tcp_operations structure in order to send
  25. * and receive data.
  26. *
  27. * See hello.c for a trivial example of a TCP protocol using this
  28. * API.
  29. *
  30. */
  31. /**
  32. * TCP transmit buffer
  33. *
  34. * When a tcp_operations::senddata() method is called, it is
  35. * guaranteed to be able to use this buffer as temporary space for
  36. * constructing the data to be sent. For example, code such as
  37. *
  38. * @code
  39. *
  40. * static void my_senddata ( struct tcp_connection *conn ) {
  41. * int len;
  42. *
  43. * len = snprintf ( tcp_buffer, tcp_buflen, "FETCH %s\r\n", filename );
  44. * tcp_send ( conn, tcp_buffer + already_sent, len - already_sent );
  45. * }
  46. *
  47. * @endcode
  48. *
  49. * is allowed, and is probably the best way to deal with
  50. * variably-sized data.
  51. *
  52. * Note that you cannot use this simple mechanism if you want to be
  53. * able to construct single data blocks of more than #tcp_buflen
  54. * bytes.
  55. */
  56. void *tcp_buffer = uip_buf + ( 40 + UIP_LLH_LEN );
  57. /** Size of #tcp_buffer */
  58. size_t tcp_buflen = UIP_BUFSIZE - ( 40 + UIP_LLH_LEN );
  59. /**
  60. * Open a TCP connection
  61. *
  62. * @v conn TCP connection
  63. *
  64. * This sets up a new TCP connection to the remote host specified in
  65. * tcp_connection::sin.
  66. */
  67. void tcp_connect ( struct tcp_connection *conn ) {
  68. struct uip_conn *uip_conn;
  69. u16_t ipaddr[2];
  70. assert ( conn->sin.sin_addr.s_addr != 0 );
  71. assert ( conn->sin.sin_port != 0 );
  72. assert ( conn->tcp_op != NULL );
  73. assert ( sizeof ( uip_conn->appstate ) == sizeof ( conn ) );
  74. * ( ( uint32_t * ) ipaddr ) = conn->sin.sin_addr.s_addr;
  75. uip_conn = uip_connect ( ipaddr, conn->sin.sin_port );
  76. #warning "Use linked lists so that uip_connect() cannot fail"
  77. assert ( uip_conn != NULL );
  78. *( ( void ** ) uip_conn->appstate ) = conn;
  79. }
  80. /**
  81. * Send data via a TCP connection
  82. *
  83. * @v conn TCP connection
  84. * @v data Data to send
  85. * @v len Length of data
  86. *
  87. * Data will be automatically limited to the current TCP window size.
  88. *
  89. * If retransmission is required, the connection's
  90. * tcp_operations::senddata() method will be called again in order to
  91. * regenerate the data.
  92. */
  93. void tcp_send ( struct tcp_connection *conn __unused,
  94. const void *data, size_t len ) {
  95. assert ( conn = *( ( void ** ) uip_conn->appstate ) );
  96. if ( len > tcp_buflen )
  97. len = tcp_buflen;
  98. memmove ( tcp_buffer, data, len );
  99. uip_send ( tcp_buffer, len );
  100. }
  101. /**
  102. * Close a TCP connection
  103. *
  104. * @v conn TCP connection
  105. */
  106. void tcp_close ( struct tcp_connection *conn __unused ) {
  107. assert ( conn = *( ( void ** ) uip_conn->appstate ) );
  108. uip_close();
  109. }
  110. /**
  111. * uIP TCP application call interface
  112. *
  113. * This is the entry point of gPXE from the point of view of the uIP
  114. * protocol stack. This function calls the appropriate methods from
  115. * the connection's @tcp_operations table in order to process received
  116. * data, transmit new data etc.
  117. */
  118. void uip_tcp_appcall ( void ) {
  119. struct tcp_connection *conn = *( ( void ** ) uip_conn->appstate );
  120. struct tcp_operations *op = conn->tcp_op;
  121. assert ( conn->tcp_op->closed != NULL );
  122. assert ( conn->tcp_op->connected != NULL );
  123. assert ( conn->tcp_op->acked != NULL );
  124. assert ( conn->tcp_op->newdata != NULL );
  125. assert ( conn->tcp_op->senddata != NULL );
  126. if ( uip_aborted() && op->aborted ) /* optional method */
  127. op->aborted ( conn );
  128. if ( uip_timedout() && op->timedout ) /* optional method */
  129. op->timedout ( conn );
  130. if ( uip_closed() && op->closed ) /* optional method */
  131. op->closed ( conn );
  132. if ( uip_connected() )
  133. op->connected ( conn );
  134. if ( uip_acked() )
  135. op->acked ( conn, uip_conn->len );
  136. if ( uip_newdata() )
  137. op->newdata ( conn, ( void * ) uip_appdata, uip_len );
  138. if ( uip_rexmit() || uip_newdata() || uip_acked() ||
  139. uip_connected() || uip_poll() )
  140. op->senddata ( conn );
  141. }
  142. /* Present here to allow everything to link. Will go into separate
  143. * udp.c file
  144. */
  145. void uip_udp_appcall ( void ) {
  146. }
  147. /**
  148. * Perform periodic processing of all TCP connections
  149. *
  150. * This allows TCP connections to retransmit data if necessary.
  151. */
  152. static void tcp_periodic ( void ) {
  153. struct pk_buff *pkb;
  154. int i;
  155. for ( i = 0 ; i < UIP_CONNS ; i++ ) {
  156. uip_periodic ( i );
  157. if ( uip_len > 0 ) {
  158. pkb = alloc_pkb ( uip_len + MAX_LL_HEADER_LEN);
  159. if ( ! pkb )
  160. continue;
  161. pkb_reserve ( pkb, MAX_LL_HEADER_LEN );
  162. pkb_put ( pkb, uip_len );
  163. memcpy ( pkb->data, uip_buf, uip_len );
  164. pkb->net_protocol = &ipv4_protocol;
  165. net_transmit ( pkb );
  166. }
  167. }
  168. }
  169. /**
  170. * Single-step the TCP stack
  171. *
  172. * @v process TCP process
  173. *
  174. * This calls tcp_periodic() at regular intervals.
  175. */
  176. static void tcp_step ( struct process *process ) {
  177. static long timeout = 0;
  178. if ( currticks() > timeout ) {
  179. timeout = currticks() + ( TICKS_PER_SEC / 10 );
  180. tcp_periodic ();
  181. }
  182. schedule ( process );
  183. }
  184. /** TCP stack process */
  185. static struct process tcp_process = {
  186. .step = tcp_step,
  187. };
  188. /** Initialise the TCP stack */
  189. static void init_tcp ( void ) {
  190. schedule ( &tcp_process );
  191. }
  192. INIT_FN ( INIT_PROCESS, init_tcp, NULL, NULL );