From c8a7133e9f7b5fcbedbcdf0a451010b7cd86eed8 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 5 Apr 2006 11:43:01 +0000 Subject: [PATCH] Added tcp_buffer, to give applications a zero-cost place to build data to be transmitted. --- src/include/gpxe/tcp.h | 2 ++ src/proto/tcp.c | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/include/gpxe/tcp.h b/src/include/gpxe/tcp.h index cb275f81..bcb15365 100644 --- a/src/include/gpxe/tcp.h +++ b/src/include/gpxe/tcp.h @@ -92,6 +92,8 @@ struct tcp_connection { struct tcp_operations *tcp_op; }; +extern void *tcp_buffer; +extern size_t tcp_buflen; extern int tcp_connect ( struct tcp_connection *conn ); extern void tcp_send ( struct tcp_connection *conn, const void *data, size_t len ); diff --git a/src/proto/tcp.c b/src/proto/tcp.c index 0010f64f..69fe95f5 100644 --- a/src/proto/tcp.c +++ b/src/proto/tcp.c @@ -24,6 +24,36 @@ * */ +/** + * TCP transmit buffer + * + * When a tcp_operations::senddata() method is called, it is + * guaranteed to be able to use this buffer as temporary space for + * constructing the data to be sent. For example, code such as + * + * @code + * + * static void my_senddata ( struct tcp_connection *conn ) { + * int len; + * + * len = snprintf ( tcp_buffer, tcp_buflen, "FETCH %s\r\n", filename ); + * tcp_send ( conn, tcp_buffer + already_sent, len - already_sent ); + * } + * + * @endcode + * + * is allowed, and is probably the best way to deal with + * variably-sized data. + * + * Note that you cannot use this simple mechanism if you want to be + * able to construct single data blocks of more than #tcp_buflen + * bytes. + */ +void *tcp_buffer = uip_buf + ( 40 + UIP_LLH_LEN ); + +/** Size of #tcp_buffer */ +size_t tcp_buflen = UIP_BUFSIZE - ( 40 + UIP_LLH_LEN ); + /** * Open a TCP connection * @@ -67,13 +97,19 @@ int tcp_connect ( struct tcp_connection *conn ) { * Data will be automatically limited to the current TCP window size. * * If retransmission is required, the connection's - * tcp_operations::newdata() method will be called again in order to + * tcp_operations::senddata() method will be called again in order to * regenerate the data. */ void tcp_send ( struct tcp_connection *conn __unused, const void *data, size_t len ) { + assert ( conn = *( ( void ** ) uip_conn->appstate ) ); - uip_send ( ( void * ) data, len ); + + if ( len > tcp_buflen ) + len = tcp_buflen; + memmove ( tcp_buffer, data, len ); + + uip_send ( tcp_buffer, len ); } /**