Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

tcp.c 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #include <string.h>
  2. #include <assert.h>
  3. #include <byteswap.h>
  4. #include <gpxe/tcp.h>
  5. #include "uip/uip.h"
  6. /** @file
  7. *
  8. * TCP protocol
  9. *
  10. * The gPXE TCP stack is currently implemented on top of the uIP
  11. * protocol stack. This file provides wrappers around uIP so that
  12. * higher-level protocol implementations do not need to talk directly
  13. * to uIP (which has a somewhat baroque API).
  14. *
  15. * Basic operation is to create a #tcp_connection structure, call
  16. * tcp_connect() and then call run_tcpip() in a loop until the
  17. * operation has completed. The TCP stack will call the various
  18. * methods defined in the #tcp_operations structure in order to send
  19. * and receive data.
  20. *
  21. * See hello.c for a trivial example of a TCP protocol using this
  22. * API.
  23. *
  24. */
  25. /**
  26. * TCP transmit buffer
  27. *
  28. * When a tcp_operations::senddata() method is called, it is
  29. * guaranteed to be able to use this buffer as temporary space for
  30. * constructing the data to be sent. For example, code such as
  31. *
  32. * @code
  33. *
  34. * static void my_senddata ( struct tcp_connection *conn ) {
  35. * int len;
  36. *
  37. * len = snprintf ( tcp_buffer, tcp_buflen, "FETCH %s\r\n", filename );
  38. * tcp_send ( conn, tcp_buffer + already_sent, len - already_sent );
  39. * }
  40. *
  41. * @endcode
  42. *
  43. * is allowed, and is probably the best way to deal with
  44. * variably-sized data.
  45. *
  46. * Note that you cannot use this simple mechanism if you want to be
  47. * able to construct single data blocks of more than #tcp_buflen
  48. * bytes.
  49. */
  50. void *tcp_buffer = uip_buf + ( 40 + UIP_LLH_LEN );
  51. /** Size of #tcp_buffer */
  52. size_t tcp_buflen = UIP_BUFSIZE - ( 40 + UIP_LLH_LEN );
  53. /**
  54. * Open a TCP connection
  55. *
  56. * @v conn TCP connection
  57. * @ret 0 Success
  58. * @ret <0 Failure
  59. *
  60. * This sets up a new TCP connection to the remote host specified in
  61. * tcp_connection::sin. The actual SYN packet will not be sent out
  62. * until run_tcpip() is called for the first time.
  63. *
  64. * @todo Use linked lists instead of a static buffer, and thereby
  65. * remove the only potential failure case, giving this function
  66. * a void return type.
  67. */
  68. int tcp_connect ( struct tcp_connection *conn ) {
  69. struct uip_conn *uip_conn;
  70. u16_t ipaddr[2];
  71. assert ( conn->sin.sin_addr.s_addr != 0 );
  72. assert ( conn->sin.sin_port != 0 );
  73. assert ( conn->tcp_op != NULL );
  74. assert ( sizeof ( uip_conn->appstate ) == sizeof ( conn ) );
  75. * ( ( uint32_t * ) ipaddr ) = conn->sin.sin_addr.s_addr;
  76. uip_conn = uip_connect ( ipaddr, conn->sin.sin_port );
  77. if ( ! uip_conn )
  78. return -1;
  79. *( ( void ** ) uip_conn->appstate ) = conn;
  80. return 0;
  81. }
  82. /**
  83. * Send data via a TCP connection
  84. *
  85. * @v conn TCP connection
  86. * @v data Data to send
  87. * @v len Length of data
  88. *
  89. * Data will be automatically limited to the current TCP window size.
  90. *
  91. * If retransmission is required, the connection's
  92. * tcp_operations::senddata() method will be called again in order to
  93. * regenerate the data.
  94. */
  95. void tcp_send ( struct tcp_connection *conn __unused,
  96. const void *data, size_t len ) {
  97. assert ( conn = *( ( void ** ) uip_conn->appstate ) );
  98. if ( len > tcp_buflen )
  99. len = tcp_buflen;
  100. memmove ( tcp_buffer, data, len );
  101. uip_send ( tcp_buffer, len );
  102. }
  103. /**
  104. * Close a TCP connection
  105. *
  106. * @v conn TCP connection
  107. */
  108. void tcp_close ( struct tcp_connection *conn __unused ) {
  109. assert ( conn = *( ( void ** ) uip_conn->appstate ) );
  110. uip_close();
  111. }
  112. /**
  113. * uIP TCP application call interface
  114. *
  115. * This is the entry point of gPXE from the point of view of the uIP
  116. * protocol stack. This function calls the appropriate methods from
  117. * the connection's @tcp_operations table in order to process received
  118. * data, transmit new data etc.
  119. */
  120. void uip_tcp_appcall ( void ) {
  121. struct tcp_connection *conn = *( ( void ** ) uip_conn->appstate );
  122. struct tcp_operations *op = conn->tcp_op;
  123. assert ( conn->tcp_op->closed != NULL );
  124. assert ( conn->tcp_op->connected != NULL );
  125. assert ( conn->tcp_op->acked != NULL );
  126. assert ( conn->tcp_op->newdata != NULL );
  127. assert ( conn->tcp_op->senddata != NULL );
  128. if ( uip_aborted() && op->aborted ) /* optional method */
  129. op->aborted ( conn );
  130. if ( uip_timedout() && op->timedout ) /* optional method */
  131. op->timedout ( conn );
  132. if ( uip_closed() && op->closed ) /* optional method */
  133. op->closed ( conn );
  134. if ( uip_connected() )
  135. op->connected ( conn );
  136. if ( uip_acked() )
  137. op->acked ( conn, uip_conn->len );
  138. if ( uip_newdata() )
  139. op->newdata ( conn, ( void * ) uip_appdata, uip_len );
  140. if ( uip_rexmit() || uip_newdata() || uip_acked() ||
  141. uip_connected() || uip_poll() )
  142. op->senddata ( conn );
  143. }
  144. /* Present here to allow everything to link. Will go into separate
  145. * udp.c file
  146. */
  147. void uip_udp_appcall ( void ) {
  148. }