aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown <mcb30@etherboot.org>2007-01-31 02:09:13 +0000
committerMichael Brown <mcb30@etherboot.org>2007-01-31 02:09:13 +0000
commit6d32f0e6e2179afa4e78ab94d3fbfb691a6f99de (patch)
tree9ba9ac5ba0a755bdb6f10a563b22dac61ef4045d
parent02f18565dafa4462584ad89ee284d1cbcfad4b6a (diff)
downloadipxe-6d32f0e6e2179afa4e78ab94d3fbfb691a6f99de.tar.gz
Changed to use the generic stream API.
-rw-r--r--src/include/gpxe/ftp.h10
-rw-r--r--src/include/gpxe/http.h6
-rw-r--r--src/include/gpxe/iscsi.h8
-rw-r--r--src/include/gpxe/stream.h7
-rw-r--r--src/include/gpxe/tcp.h101
-rw-r--r--src/net/stream.c54
-rw-r--r--src/net/tcp.c571
-rw-r--r--src/net/tcp/ftp.c111
-rw-r--r--src/net/tcp/http.c50
-rw-r--r--src/net/tcp/iscsi.c103
10 files changed, 490 insertions, 531 deletions
diff --git a/src/include/gpxe/ftp.h b/src/include/gpxe/ftp.h
index 64e8d4e4..41eca8ca 100644
--- a/src/include/gpxe/ftp.h
+++ b/src/include/gpxe/ftp.h
@@ -9,7 +9,7 @@
#include <stdint.h>
#include <gpxe/async.h>
-#include <gpxe/tcp.h>
+#include <gpxe/stream.h>
struct buffer;
@@ -57,10 +57,10 @@ struct ftp_request {
char status_text[4];
/** Passive-mode parameters, as text */
char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
- /** TCP application for the control channel */
- struct tcp_application tcp;
- /** TCP application for the data channel */
- struct tcp_application tcp_data;
+ /** Stream application for the control channel */
+ struct stream_application stream;
+ /** Stream application for the data channel */
+ struct stream_application stream_data;
};
extern int ftp_get ( struct uri *uri, struct buffer *buffer,
diff --git a/src/include/gpxe/http.h b/src/include/gpxe/http.h
index 3cfc888a..911a7485 100644
--- a/src/include/gpxe/http.h
+++ b/src/include/gpxe/http.h
@@ -8,7 +8,7 @@
*/
#include <stdint.h>
-#include <gpxe/tcp.h>
+#include <gpxe/stream.h>
#include <gpxe/async.h>
#include <gpxe/linebuf.h>
#include <gpxe/uri.h>
@@ -43,8 +43,8 @@ struct http_request {
/** Server address */
struct sockaddr server;
- /** TCP application for this request */
- struct tcp_application tcp;
+ /** Stream application for this request */
+ struct stream_application stream;
/** Number of bytes already sent */
size_t tx_offset;
/** RX state */
diff --git a/src/include/gpxe/iscsi.h b/src/include/gpxe/iscsi.h
index 74560649..62b789c2 100644
--- a/src/include/gpxe/iscsi.h
+++ b/src/include/gpxe/iscsi.h
@@ -8,7 +8,7 @@
*/
#include <stdint.h>
-#include <gpxe/tcp.h>
+#include <gpxe/stream.h>
#include <gpxe/async.h>
#include <gpxe/scsi.h>
#include <gpxe/chap.h>
@@ -489,7 +489,7 @@ struct iscsi_session {
/** Initiator IQN */
const char *initiator_iqn;
/** Target address */
- struct sockaddr_tcpip target;
+ struct sockaddr target;
/** Target IQN */
const char *target_iqn;
/** Logical Unit Number (LUN) */
@@ -499,8 +499,8 @@ struct iscsi_session {
/** Password */
const char *password;
- /** TCP application for this session */
- struct tcp_application tcp;
+ /** Stream application for this session */
+ struct stream_application stream;
/** Session status
*
* This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
diff --git a/src/include/gpxe/stream.h b/src/include/gpxe/stream.h
index 8d1c5f5d..545bfae7 100644
--- a/src/include/gpxe/stream.h
+++ b/src/include/gpxe/stream.h
@@ -125,7 +125,7 @@ struct stream_connection_operations {
* application's senddata() method.
*/
int ( * send ) ( struct stream_connection *conn,
- void *data, size_t len );
+ const void *data, size_t len );
/**
* Notify connection that data is available to send
*
@@ -167,6 +167,9 @@ struct stream_connection {
struct stream_connection_operations *op;
};
+extern void stream_associate ( struct stream_application *app,
+ struct stream_connection *conn );
+
extern void stream_connected ( struct stream_connection *conn );
extern void stream_closed ( struct stream_connection *conn, int rc );
extern void stream_senddata ( struct stream_connection *conn,
@@ -181,7 +184,7 @@ extern int stream_connect ( struct stream_application *app,
struct sockaddr *peer );
extern void stream_close ( struct stream_application *app );
extern int stream_send ( struct stream_application *app,
- void *data, size_t len );
+ const void *data, size_t len );
extern int stream_kick ( struct stream_application *app );
#endif /* _GPXE_STREAM_H */
diff --git a/src/include/gpxe/tcp.h b/src/include/gpxe/tcp.h
index f618ae32..576898e8 100644
--- a/src/include/gpxe/tcp.h
+++ b/src/include/gpxe/tcp.h
@@ -11,6 +11,7 @@
#include "latch.h"
#include <gpxe/tcpip.h>
+#include <gpxe/stream.h>
/**
* A TCP header
@@ -252,105 +253,7 @@ struct tcp_mss_option {
*/
#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
-struct tcp_application;
-
-/**
- * TCP operations
- *
- */
-struct tcp_operations {
- /*
- * Connection closed
- *
- * @v app TCP application
- * @v status Error code, if any
- *
- * This is called when the connection is closed for any
- * reason, including timeouts or aborts. The status code
- * contains the negative error number, if the closure is due
- * to an error.
- *
- * When closed() is called, the application no longer has a
- * valid TCP connection. Note that connected() may not have
- * been called before closed(), if the close is due to an
- * error during connection setup.
- */
- void ( * closed ) ( struct tcp_application *app, int status );
- /**
- * Connection established
- *
- * @v app TCP application
- */
- void ( * connected ) ( struct tcp_application *app );
- /**
- * Data acknowledged
- *
- * @v app TCP application
- * @v len Length of acknowledged data
- *
- * @c len is guaranteed to not exceed the outstanding amount
- * of unacknowledged data.
- */
- void ( * acked ) ( struct tcp_application *app, size_t len );
- /**
- * New data received
- *
- * @v app TCP application
- * @v data Data
- * @v len Length of data
- */
- void ( * newdata ) ( struct tcp_application *app,
- void *data, size_t len );
- /**
- * Transmit data
- *
- * @v app TCP application
- * @v buf Temporary data buffer
- * @v len Length of temporary data buffer
- *
- * The application should transmit whatever it currently wants
- * to send using tcp_send(). If retransmissions are required,
- * senddata() will be called again and the application must
- * regenerate the data. The easiest way to implement this is
- * to ensure that senddata() never changes the application's
- * state.
- *
- * The application may use the temporary data buffer to
- * construct the data to be sent. Note that merely filling
- * the buffer will do nothing; the application must call
- * tcp_send() in order to actually transmit the data. Use of
- * the buffer is not compulsory; the application may call
- * tcp_send() on any block of data.
- */
- void ( * senddata ) ( struct tcp_application *app, void *buf,
- size_t len );
-};
-
-struct tcp_connection;
-
-/**
- * A TCP application
- *
- * This data structure represents an application with a TCP connection.
- */
-struct tcp_application {
- /** TCP connection data
- *
- * This is filled in by TCP calls that initiate a connection,
- * and reset to NULL when the connection is closed.
- */
- struct tcp_connection *conn;
- /** TCP connection operations table */
- struct tcp_operations *tcp_op;
-};
-
-extern int tcp_connect ( struct tcp_application *app,
- struct sockaddr_tcpip *peer,
- uint16_t local_port );
-extern void tcp_close ( struct tcp_application *app );
-extern int tcp_senddata ( struct tcp_application *app );
-extern int tcp_send ( struct tcp_application *app, const void *data,
- size_t len );
+extern int tcp_open ( struct stream_application *app );
extern struct tcpip_protocol tcp_protocol;
diff --git a/src/net/stream.c b/src/net/stream.c
index 92e00d73..e255d850 100644
--- a/src/net/stream.c
+++ b/src/net/stream.c
@@ -25,9 +25,27 @@
#include <stdint.h>
#include <string.h>
#include <errno.h>
+#include <assert.h>
#include <gpxe/stream.h>
/**
+ * Associate application with connection
+ *
+ * @v app Stream application
+ * @v conn Stream connection
+ */
+void stream_associate ( struct stream_application *app,
+ struct stream_connection *conn ) {
+
+ DBGC ( app, "Stream %p associating with connection %p\n", app, conn );
+
+ assert ( conn->app == NULL );
+ assert ( app->conn == NULL );
+ conn->app = app;
+ app->conn = conn;
+}
+
+/**
* Connection established
*
* @v conn Stream connection
@@ -45,7 +63,8 @@ void stream_connected ( struct stream_connection *conn ) {
}
/* Hand off to application */
- app->op->connected ( app );
+ if ( app->op->connected )
+ app->op->connected ( app );
}
/**
@@ -66,8 +85,13 @@ void stream_closed ( struct stream_connection *conn, int rc ) {
return;
}
+ /* Disassociate application from connection */
+ app->conn = NULL;
+ conn->app = NULL;
+
/* Hand off to application */
- app->op->closed ( app, rc );
+ if ( app->op->closed )
+ app->op->closed ( app, rc );
}
/**
@@ -91,7 +115,8 @@ void stream_senddata ( struct stream_connection *conn,
}
/* Hand off to application */
- app->op->senddata ( app, data, len );
+ if ( app->op->senddata )
+ app->op->senddata ( app, data, len );
}
/**
@@ -116,7 +141,8 @@ void stream_acked ( struct stream_connection *conn, size_t len ) {
}
/* Hand off to application */
- app->op->acked ( app, len );
+ if ( app->op->acked )
+ app->op->acked ( app, len );
}
/**
@@ -140,7 +166,8 @@ void stream_newdata ( struct stream_connection *conn,
}
/* Hand off to application */
- app->op->newdata ( app, data, len );
+ if ( app->op->newdata )
+ app->op->newdata ( app, data, len );
}
/**
@@ -163,6 +190,8 @@ int stream_bind ( struct stream_application *app, struct sockaddr *local ) {
}
/* Hand off to connection */
+ if ( ! conn->op->bind )
+ return -ENOTSUP;
if ( ( rc = conn->op->bind ( conn, local ) ) != 0 ) {
DBGC ( app, "Stream %p failed to bind: %s\n",
app, strerror ( rc ) );
@@ -192,6 +221,8 @@ int stream_connect ( struct stream_application *app, struct sockaddr *peer ) {
}
/* Hand off to connection */
+ if ( ! conn->op->connect )
+ return -ENOTSUP;
if ( ( rc = conn->op->connect ( conn, peer ) ) != 0 ) {
DBGC ( app, "Stream %p failed to connect: %s\n",
app, strerror ( rc ) );
@@ -217,7 +248,13 @@ void stream_close ( struct stream_application *app ) {
return;
}
+ /* Disassociate application from connection */
+ app->conn = NULL;
+ conn->app = NULL;
+
/* Hand off to connection */
+ if ( ! conn->op->close )
+ return;
conn->op->close ( conn );
}
@@ -232,7 +269,8 @@ void stream_close ( struct stream_application *app ) {
* This method should be called only in the context of an
* application's senddata() method.
*/
-int stream_send ( struct stream_application *app, void *data, size_t len ) {
+int stream_send ( struct stream_application *app,
+ const void *data, size_t len ) {
struct stream_connection *conn = app->conn;
int rc;
@@ -245,6 +283,8 @@ int stream_send ( struct stream_application *app, void *data, size_t len ) {
}
/* Hand off to connection */
+ if ( ! conn->op->send )
+ return -ENOTSUP;
if ( ( rc = conn->op->send ( conn, data, len ) ) != 0 ) {
DBGC ( app, "Stream %p failed to send %zd bytes: %s\n",
app, len, strerror ( rc ) );
@@ -273,6 +313,8 @@ int stream_kick ( struct stream_application *app ) {
}
/* Hand off to connection */
+ if ( ! conn->op->send )
+ return -ENOTSUP;
if ( ( rc = conn->op->kick ( conn ) ) != 0 ) {
DBGC ( app, "Stream %p failed to kick connection: %s\n",
app, strerror ( rc ) );
diff --git a/src/net/tcp.c b/src/net/tcp.c
index 2c2f0b33..056c3e3c 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -8,6 +8,7 @@
#include <gpxe/pkbuff.h>
#include <gpxe/malloc.h>
#include <gpxe/retry.h>
+#include <gpxe/stream.h>
#include <gpxe/tcpip.h>
#include <gpxe/tcp.h>
@@ -17,22 +18,22 @@
*
*/
+struct tcp_connection;
static void tcp_expired ( struct retry_timer *timer, int over );
-static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send );
+static int tcp_senddata_conn ( struct tcp_connection *tcp, int force_send );
+static struct stream_connection_operations tcp_op;
/**
* A TCP connection
*
* This data structure represents the internal state of a TCP
- * connection. It is kept separate from @c struct @c tcp_application
- * because the internal state is still required for some time after
- * the application closes the connection.
+ * connection.
*/
struct tcp_connection {
+ /** The stream connection */
+ struct stream_connection stream;
/** List of TCP connections */
struct list_head list;
- /** The associated TCP application, if any */
- struct tcp_application *app;
/** Remote socket address */
struct sockaddr_tcpip peer;
@@ -108,17 +109,17 @@ tcp_state ( int state ) {
/**
* Dump TCP state transition
*
- * @v conn TCP connection
+ * @v tcp TCP connection
*/
static inline __attribute__ (( always_inline )) void
-tcp_dump_state ( struct tcp_connection *conn ) {
+tcp_dump_state ( struct tcp_connection *tcp ) {
- if ( conn->tcp_state != conn->prev_tcp_state ) {
- DBGC ( conn, "TCP %p transitioned from %s to %s\n", conn,
- tcp_state ( conn->prev_tcp_state ),
- tcp_state ( conn->tcp_state ) );
+ if ( tcp->tcp_state != tcp->prev_tcp_state ) {
+ DBGC ( tcp, "TCP %p transitioned from %s to %s\n", tcp,
+ tcp_state ( tcp->prev_tcp_state ),
+ tcp_state ( tcp->tcp_state ) );
}
- conn->prev_tcp_state = conn->tcp_state;
+ tcp->prev_tcp_state = tcp->tcp_state;
}
/**
@@ -127,17 +128,17 @@ tcp_dump_state ( struct tcp_connection *conn ) {
* @v flags TCP flags
*/
static inline __attribute__ (( always_inline )) void
-tcp_dump_flags ( struct tcp_connection *conn, unsigned int flags ) {
+tcp_dump_flags ( struct tcp_connection *tcp, unsigned int flags ) {
if ( flags & TCP_RST )
- DBGC ( conn, " RST" );
+ DBGC ( tcp, " RST" );
if ( flags & TCP_SYN )
- DBGC ( conn, " SYN" );
+ DBGC ( tcp, " SYN" );
if ( flags & TCP_PSH )
- DBGC ( conn, " PSH" );
+ DBGC ( tcp, " PSH" );
if ( flags & TCP_FIN )
- DBGC ( conn, " FIN" );
+ DBGC ( tcp, " FIN" );
if ( flags & TCP_ACK )
- DBGC ( conn, " ACK" );
+ DBGC ( tcp, " ACK" );
}
/**
@@ -148,105 +149,68 @@ tcp_dump_flags ( struct tcp_connection *conn, unsigned int flags ) {
* Allocates TCP connection and adds it to the TCP connection list.
*/
static struct tcp_connection * alloc_tcp ( void ) {
- struct tcp_connection *conn;
-
- conn = malloc ( sizeof ( *conn ) );
- if ( conn ) {
- DBGC ( conn, "TCP %p allocated\n", conn );
- memset ( conn, 0, sizeof ( *conn ) );
- conn->tcp_state = conn->prev_tcp_state = TCP_CLOSED;
- conn->snd_seq = random();
- conn->timer.expired = tcp_expired;
- list_add ( &conn->list, &tcp_conns );
- }
- return conn;
+ struct tcp_connection *tcp;
+
+ tcp = malloc ( sizeof ( *tcp ) );
+ if ( tcp ) {
+ DBGC ( tcp, "TCP %p allocated\n", tcp );
+ memset ( tcp, 0, sizeof ( *tcp ) );
+ tcp->tcp_state = tcp->prev_tcp_state = TCP_CLOSED;
+ tcp->snd_seq = random();
+ tcp->timer.expired = tcp_expired;
+ tcp->stream.op = &tcp_op;
+ list_add ( &tcp->list, &tcp_conns );
+ }
+ return tcp;
}
/**
* Free TCP connection
*
- * @v conn TCP connection
+ * @v tcp TCP connection
*
* Removes connection from TCP connection list and frees the data
* structure.
*/
-static void free_tcp ( struct tcp_connection *conn ) {
+static void free_tcp ( struct tcp_connection *tcp ) {
- assert ( conn );
- assert ( conn->tcp_state == TCP_CLOSED );
- assert ( conn->app == NULL );
+ assert ( tcp );
+ assert ( tcp->tcp_state == TCP_CLOSED );
- stop_timer ( &conn->timer );
- list_del ( &conn->list );
- free ( conn );
- DBGC ( conn, "TCP %p freed\n", conn );
-}
-
-/**
- * Associate TCP connection with application
- *
- * @v conn TCP connection
- * @v app TCP application
- */
-static void tcp_associate ( struct tcp_connection *conn,
- struct tcp_application *app ) {
- assert ( conn->app == NULL );
- assert ( app->conn == NULL );
- conn->app = app;
- app->conn = conn;
- DBGC ( conn, "TCP %p associated with application %p\n", conn, app );
-}
-
-/**
- * Disassociate TCP connection from application
- *
- * @v conn TCP connection
- */
-static void tcp_disassociate ( struct tcp_connection *conn ) {
- struct tcp_application *app = conn->app;
-
- if ( app ) {
- assert ( app->conn == conn );
- conn->app = NULL;
- app->conn = NULL;
- DBGC ( conn, "TCP %p disassociated from application %p\n",
- conn, app );
- }
+ stop_timer ( &tcp->timer );
+ list_del ( &tcp->list );
+ free ( tcp );
+ DBGC ( tcp, "TCP %p freed\n", tcp );
}
/**
* Abort TCP connection
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v send_rst Send a RST after closing
* @v rc Reason code
*/
-static void tcp_abort ( struct tcp_connection *conn, int send_rst, int rc ) {
- struct tcp_application *app = conn->app;
+static void tcp_abort ( struct tcp_connection *tcp, int send_rst, int rc ) {
/* Transition to CLOSED */
- conn->tcp_state = TCP_CLOSED;
- tcp_dump_state ( conn );
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
/* Send RST if requested to do so */
if ( send_rst )
- tcp_senddata_conn ( conn, 1 );
+ tcp_senddata_conn ( tcp, 1 );
- /* Break association between application and connection */
- tcp_disassociate ( conn );
+ /* Close stream */
+ stream_closed ( &tcp->stream, rc );
/* Free the connection */
- free_tcp ( conn );
-
- /* Notify application */
- if ( app && app->tcp_op->closed )
- app->tcp_op->closed ( app, rc );
+ free_tcp ( tcp );
}
/**
* Transmit any outstanding data
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v force_send Force sending of packet
*
* Transmits any outstanding data on the connection. If the
@@ -257,8 +221,7 @@ static void tcp_abort ( struct tcp_connection *conn, int send_rst, int rc ) {
* will have been started if necessary, and so the stack will
* eventually attempt to retransmit the failed packet.
*/
-static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
- struct tcp_application *app = conn->app;
+static int tcp_senddata_conn ( struct tcp_connection *tcp, int force_send ) {
struct pk_buff *pkb;
struct tcp_header *tcphdr;
struct tcp_mss_option *mssopt;
@@ -272,7 +235,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
/* Allocate space to the TX buffer */
pkb = alloc_pkb ( MAX_PKB_LEN );
if ( ! pkb ) {
- DBGC ( conn, "TCP %p could not allocate data buffer\n", conn );
+ DBGC ( tcp, "TCP %p could not allocate data buffer\n", tcp );
/* Start the retry timer so that we attempt to
* retransmit this packet later. (Start it
* unconditionally, since without a packet buffer we
@@ -280,7 +243,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
* be able to tell whether or not we have something
* that actually needs to be retransmitted).
*/
- start_timer ( &conn->timer );
+ start_timer ( &tcp->timer );
return -ENOMEM;
}
pkb_reserve ( pkb, MAX_HDR_LEN );
@@ -288,28 +251,28 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
/* If we are connected, call the senddata() method, which may
* call tcp_send() to queue up a data payload.
*/
- if ( TCP_CAN_SEND_DATA ( conn->tcp_state ) &&
- app && app->tcp_op->senddata ) {
- conn->tx_pkb = pkb;
- app->tcp_op->senddata ( app, pkb->data, pkb_tailroom ( pkb ) );
- conn->tx_pkb = NULL;
+ if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
+ tcp->tx_pkb = pkb;
+ stream_senddata ( &tcp->stream, pkb->data,
+ pkb_tailroom ( pkb ) );
+ tcp->tx_pkb = NULL;
}
/* Truncate payload length to fit transmit window */
len = pkb_len ( pkb );
- if ( len > conn->snd_win )
- len = conn->snd_win;
+ if ( len > tcp->snd_win )
+ len = tcp->snd_win;
/* Calculate amount of sequence space that this transmission
* consumes. (SYN or FIN consume one byte, and we can never
* send both at once).
*/
seq_len = len;
- flags = TCP_FLAGS_SENDING ( conn->tcp_state );
+ flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
if ( flags & ( TCP_SYN | TCP_FIN ) )
seq_len++;
- conn->snd_sent = seq_len;
+ tcp->snd_sent = seq_len;
/* If we have nothing to transmit, drop the packet */
if ( ( seq_len == 0 ) && ! force_send ) {
@@ -322,7 +285,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
* retransmission timer.
*/
if ( seq_len )
- start_timer ( &conn->timer );
+ start_timer ( &tcp->timer );
/* Estimate window size */
window = freemem;
@@ -340,25 +303,25 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
}
tcphdr = pkb_push ( pkb, sizeof ( *tcphdr ) );
memset ( tcphdr, 0, sizeof ( *tcphdr ) );
- tcphdr->src = conn->local_port;
- tcphdr->dest = conn->peer.st_port;
- tcphdr->seq = htonl ( conn->snd_seq );
- tcphdr->ack = htonl ( conn->rcv_ack );
+ tcphdr->src = tcp->local_port;
+ tcphdr->dest = tcp->peer.st_port;
+ tcphdr->seq = htonl ( tcp->snd_seq );
+ tcphdr->ack = htonl ( tcp->rcv_ack );
tcphdr->hlen = ( ( payload - pkb->data ) << 2 );
tcphdr->flags = flags;
tcphdr->win = htons ( window );
tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
/* Dump header */
- DBGC ( conn, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
- conn, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ DBGC ( tcp, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) + seq_len ),
ntohl ( tcphdr->ack ), len );
- tcp_dump_flags ( conn, tcphdr->flags );
- DBGC ( conn, "\n" );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC ( tcp, "\n" );
/* Transmit packet */
- rc = tcpip_tx ( pkb, &tcp_protocol, &conn->peer, NULL, &tcphdr->csum );
+ rc = tcpip_tx ( pkb, &tcp_protocol, &tcp->peer, NULL, &tcphdr->csum );
/* If we got -ENETUNREACH, kill the connection immediately
* because there is no point retrying. This isn't strictly
@@ -367,11 +330,11 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
* RST packets transmitted on connection abort, to avoid a
* potential infinite loop.
*/
- if ( ( ! ( conn->tcp_state & TCP_STATE_SENT ( TCP_RST ) ) ) &&
+ if ( ( ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_RST ) ) ) &&
( rc == -ENETUNREACH ) ) {
- DBGC ( conn, "TCP %p aborting after TX failed: %s\n",
- conn, strerror ( rc ) );
- tcp_abort ( conn, 0, rc );
+ DBGC ( tcp, "TCP %p aborting after TX failed: %s\n",
+ tcp, strerror ( rc ) );
+ tcp_abort ( tcp, 0, rc );
}
return rc;
@@ -380,28 +343,23 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
/**
* Transmit any outstanding data
*
- * @v conn TCP connection
+ * @v stream TCP stream
*
* This function allocates space to the transmit buffer and invokes
* the senddata() callback function, to allow the application to
* transmit new data.
*/
-int tcp_senddata ( struct tcp_application *app ) {
- struct tcp_connection *conn = app->conn;
-
- /* Check connection actually exists */
- if ( ! conn ) {
- DBG ( "TCP app %p has no connection\n", app );
- return -ENOTCONN;
- }
+static int tcp_kick ( struct stream_connection *stream ) {
+ struct tcp_connection *tcp =
+ container_of ( stream, struct tcp_connection, stream );
- return tcp_senddata_conn ( conn, 0 );
+ return tcp_senddata_conn ( tcp, 0 );
}
/**
* Transmit data
*
- * @v app TCP application
+ * @v stream TCP stream
* @v data Data to be sent
* @v len Length of the data
* @ret rc Return status code
@@ -410,21 +368,17 @@ int tcp_senddata ( struct tcp_application *app ) {
* can be called only in the context of an application's senddata()
* method.
*/
-int tcp_send ( struct tcp_application *app, const void *data, size_t len ) {
- struct tcp_connection *conn = app->conn;
+static int tcp_send ( struct stream_connection *stream,
+ const void *data, size_t len ) {
+ struct tcp_connection *tcp =
+ container_of ( stream, struct tcp_connection, stream );
struct pk_buff *pkb;
- /* Check connection actually exists */
- if ( ! conn ) {
- DBG ( "TCP app %p has no connection\n", app );
- return -ENOTCONN;
- }
-
/* Check that we have a packet buffer to fill */
- pkb = conn->tx_pkb;
+ pkb = tcp->tx_pkb;
if ( ! pkb ) {
- DBG ( "TCP app %p tried to send data outside of the "
- "senddata() method\n", app );
+ DBGC ( tcp, "TCP %p tried to send data outside of the "
+ "senddata() method\n", tcp );
return -EINVAL;
}
@@ -445,30 +399,30 @@ int tcp_send ( struct tcp_application *app, const void *data, size_t len ) {
* @v over Failure indicator
*/
static void tcp_expired ( struct retry_timer *timer, int over ) {
- struct tcp_connection *conn =
+ struct tcp_connection *tcp =
container_of ( timer, struct tcp_connection, timer );
- int graceful_close = TCP_CLOSED_GRACEFULLY ( conn->tcp_state );
+ int graceful_close = TCP_CLOSED_GRACEFULLY ( tcp->tcp_state );
- DBGC ( conn, "TCP %p timer %s in %s\n", conn,
- ( over ? "expired" : "fired" ), tcp_state ( conn->tcp_state ) );
+ DBGC ( tcp, "TCP %p timer %s in %s\n", tcp,
+ ( over ? "expired" : "fired" ), tcp_state ( tcp->tcp_state ) );
- assert ( ( conn->tcp_state == TCP_SYN_SENT ) ||
- ( conn->tcp_state == TCP_SYN_RCVD ) ||
- ( conn->tcp_state == TCP_ESTABLISHED ) ||
- ( conn->tcp_state == TCP_FIN_WAIT_1 ) ||
- ( conn->tcp_state == TCP_TIME_WAIT ) ||
- ( conn->tcp_state == TCP_CLOSE_WAIT ) ||
- ( conn->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
+ assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
+ ( tcp->tcp_state == TCP_SYN_RCVD ) ||
+ ( tcp->tcp_state == TCP_ESTABLISHED ) ||
+ ( tcp->tcp_state == TCP_FIN_WAIT_1 ) ||
+ ( tcp->tcp_state == TCP_TIME_WAIT ) ||
+ ( tcp->tcp_state == TCP_CLOSE_WAIT ) ||
+ ( tcp->tcp_state == TCP_CLOSING_OR_LAST_ACK ) );
if ( over || graceful_close ) {
/* If we have finally timed out and given up, or if
* this is the result of a graceful close, terminate
* the connection
*/
- tcp_abort ( conn, 1, -ETIMEDOUT );
+ tcp_abort ( tcp, 1, -ETIMEDOUT );
} else {
/* Otherwise, retransmit the packet */
- tcp_senddata_conn ( conn, 0 );
+ tcp_senddata_conn ( tcp, 0 );
}
}
@@ -478,7 +432,7 @@ static void tcp_expired ( struct retry_timer *timer, int over ) {
* @v in_tcphdr TCP header of incoming packet
* @ret rc Return status code
*/
-static int tcp_send_reset ( struct tcp_connection *conn,
+static int tcp_send_reset ( struct tcp_connection *tcp,
struct tcp_header *in_tcphdr ) {
struct pk_buff *pkb;
struct tcp_header *tcphdr;
@@ -486,7 +440,7 @@ static int tcp_send_reset ( struct tcp_connection *conn,
/* Allocate space for dataless TX buffer */
pkb = alloc_pkb ( MAX_HDR_LEN );
if ( ! pkb ) {
- DBGC ( conn, "TCP %p could not allocate data buffer\n", conn );
+ DBGC ( tcp, "TCP %p could not allocate data buffer\n", tcp );
return -ENOMEM;
}
pkb_reserve ( pkb, MAX_HDR_LEN );
@@ -504,15 +458,15 @@ static int tcp_send_reset ( struct tcp_connection *conn,
tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
/* Dump header */
- DBGC ( conn, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
- conn, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
+ DBGC ( tcp, "TCP %p TX %d->%d %08lx..%08lx %08lx %4zd",
+ tcp, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ),
ntohl ( tcphdr->seq ), ( ntohl ( tcphdr->seq ) ),
ntohl ( tcphdr->ack ), 0 );
- tcp_dump_flags ( conn, tcphdr->flags );
- DBGC ( conn, "\n" );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC ( tcp, "\n" );
/* Transmit packet */
- return tcpip_tx ( pkb, &tcp_protocol, &conn->peer,
+ return tcpip_tx ( pkb, &tcp_protocol, &tcp->peer,
NULL, &tcphdr->csum );
}
@@ -520,14 +474,14 @@ static int tcp_send_reset ( struct tcp_connection *conn,
* Identify TCP connection by local port number
*
* @v local_port Local port (in network-endian order)
- * @ret conn TCP connection, or NULL
+ * @ret tcp TCP connection, or NULL
*/
static struct tcp_connection * tcp_demux ( uint16_t local_port ) {
- struct tcp_connection *conn;
+ struct tcp_connection *tcp;
- list_for_each_entry ( conn, &tcp_conns, list ) {
- if ( conn->local_port == local_port )
- return conn;
+ list_for_each_entry ( tcp, &tcp_conns, list ) {
+ if ( tcp->local_port == local_port )
+ return tcp;
}
return NULL;
}
@@ -535,32 +489,30 @@ static struct tcp_connection * tcp_demux ( uint16_t local_port ) {
/**
* Handle TCP received SYN
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v seq SEQ value (in host-endian order)
* @ret rc Return status code
*/
-static int tcp_rx_syn ( struct tcp_connection *conn, uint32_t seq ) {
- struct tcp_application *app = conn->app;
+static int tcp_rx_syn ( struct tcp_connection *tcp, uint32_t seq ) {
/* Synchronise sequence numbers on first SYN */
- if ( ! ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) )
- conn->rcv_ack = seq;
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) )
+ tcp->rcv_ack = seq;
/* Ignore duplicate SYN */
- if ( ( conn->rcv_ack - seq ) > 0 )
+ if ( ( tcp->rcv_ack - seq ) > 0 )
return 0;
/* Mark SYN as received and start sending ACKs with each packet */
- conn->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
+ tcp->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
TCP_STATE_RCVD ( TCP_SYN ) );
/* Acknowledge SYN */
- conn->rcv_ack++;
+ tcp->rcv_ack++;
/* Notify application of established connection, if applicable */
- if ( ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) &&
- app && app->tcp_op->connected )
- app->tcp_op->connected ( app );
+ if ( ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ stream_connected ( &tcp->stream );
return 0;
}
@@ -568,24 +520,23 @@ static int tcp_rx_syn ( struct tcp_connection *conn, uint32_t seq ) {
/**
* Handle TCP received ACK
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v ack ACK value (in host-endian order)
* @v win WIN value (in host-endian order)
* @ret rc Return status code
*/
-static int tcp_rx_ack ( struct tcp_connection *conn, uint32_t ack,
+static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
uint32_t win ) {
- struct tcp_application *app = conn->app;
- size_t ack_len = ( ack - conn->snd_seq );
+ size_t ack_len = ( ack - tcp->snd_seq );
size_t len;
unsigned int acked_flags = 0;
/* Ignore duplicate or out-of-range ACK */
- if ( ack_len > conn->snd_sent ) {
- DBGC ( conn, "TCP %p received ACK for [%08lx,%08lx), "
- "sent only [%08lx,%08lx)\n", conn, conn->snd_seq,
- ( conn->snd_seq + ack_len ), conn->snd_seq,
- ( conn->snd_seq + conn->snd_sent ) );
+ if ( ack_len > tcp->snd_sent ) {
+ DBGC ( tcp, "TCP %p received ACK for [%08lx,%08lx), "
+ "sent only [%08lx,%08lx)\n", tcp, tcp->snd_seq,
+ ( tcp->snd_seq + ack_len ), tcp->snd_seq,
+ ( tcp->snd_seq + tcp->snd_sent ) );
return -EINVAL;
}
@@ -595,34 +546,34 @@ static int tcp_rx_ack ( struct tcp_connection *conn, uint32_t ack,
* the last outstanding sequence point.)
*/
len = ack_len;
- if ( ack_len == conn->snd_sent ) {
- acked_flags = ( TCP_FLAGS_SENDING ( conn->tcp_state ) &
+ if ( ack_len == tcp->snd_sent ) {
+ acked_flags = ( TCP_FLAGS_SENDING ( tcp->tcp_state ) &
( TCP_SYN | TCP_FIN ) );
if ( acked_flags )
len--;
}
/* Update SEQ and sent counters, and window size */
- conn->snd_seq = ack;
- conn->snd_sent = 0;
- conn->snd_win = win;
+ tcp->snd_seq = ack;
+ tcp->snd_sent = 0;
+ tcp->snd_win = win;
/* Stop the retransmission timer */
- stop_timer ( &conn->timer );
+ stop_timer ( &tcp->timer );
/* Notify application of acknowledged data, if any */
- if ( len && app && app->tcp_op->acked )
- app->tcp_op->acked ( app, len );
+ if ( len )
+ stream_acked ( &tcp->stream, len );
/* Mark SYN/FIN as acknowledged if applicable. */
if ( acked_flags )
- conn->tcp_state |= TCP_STATE_ACKED ( acked_flags );
+ tcp->tcp_state |= TCP_STATE_ACKED ( acked_flags );
/* Notify application of established connection, if applicable */
if ( ( acked_flags & TCP_SYN ) &&
- ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) &&
- app && app->tcp_op->connected )
- app->tcp_op->connected ( app );
+ ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+ stream_connected ( &tcp->stream );
+ }
return 0;
}
@@ -630,30 +581,28 @@ static int tcp_rx_ack ( struct tcp_connection *conn, uint32_t ack,
/**
* Handle TCP received data
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v seq SEQ value (in host-endian order)
* @v data Data buffer
* @v len Length of data buffer
* @ret rc Return status code
*/
-static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
+static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
void *data, size_t len ) {
- struct tcp_application *app = conn->app;
size_t already_rcvd;
/* Ignore duplicate data */
- already_rcvd = ( conn->rcv_ack - seq );
+ already_rcvd = ( tcp->rcv_ack - seq );
if ( already_rcvd >= len )
return 0;
data += already_rcvd;
len -= already_rcvd;
/* Acknowledge new data */
- conn->rcv_ack += len;
+ tcp->rcv_ack += len;
/* Notify application */
- if ( app && app->tcp_op->newdata )
- app->tcp_op->newdata ( app, data, len );
+ stream_newdata ( &tcp->stream, data, len );
return 0;
}
@@ -661,28 +610,23 @@ static int tcp_rx_data ( struct tcp_connection *conn, uint32_t seq,
/**
* Handle TCP received FIN
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v seq SEQ value (in host-endian order)
* @ret rc Return status code
*/
-static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
- struct tcp_application *app = conn->app;
+static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
/* Ignore duplicate FIN */
- if ( ( conn->rcv_ack - seq ) > 0 )
+ if ( ( tcp->rcv_ack - seq ) > 0 )
return 0;
/* Mark FIN as received, acknowledge it, and send our own FIN */
- conn->tcp_state |= ( TCP_STATE_RCVD ( TCP_FIN ) |
+ tcp->tcp_state |= ( TCP_STATE_RCVD ( TCP_FIN ) |
TCP_STATE_SENT ( TCP_FIN ) );
- conn->rcv_ack++;
-
- /* Break association with application */
- tcp_disassociate ( conn );
+ tcp->rcv_ack++;
- /* Notify application */
- if ( app && app->tcp_op->closed )
- app->tcp_op->closed ( app, 0 );
+ /* Close stream */
+ stream_closed ( &tcp->stream, 0 );
return 0;
}
@@ -690,27 +634,27 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
/**
* Handle TCP received RST
*
- * @v conn TCP connection
+ * @v tcp TCP connection
* @v seq SEQ value (in host-endian order)
* @ret rc Return status code
*/
-static int tcp_rx_rst ( struct tcp_connection *conn, uint32_t seq ) {
+static int tcp_rx_rst ( struct tcp_connection *tcp, uint32_t seq ) {
/* Accept RST only if it falls within the window. If we have
* not yet received a SYN, then we have no window to test
* against, so fall back to checking that our SYN has been
* ACKed.
*/
- if ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
- if ( ( conn->rcv_ack - seq ) > 0 )
+ if ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) {
+ if ( ( tcp->rcv_ack - seq ) > 0 )
return 0;
} else {
- if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
return 0;
}
/* Abort connection without sending a RST */
- tcp_abort ( conn, 0, -ECONNRESET );
+ tcp_abort ( tcp, 0, -ECONNRESET );
return -ECONNRESET;
}
@@ -729,7 +673,7 @@ static int tcp_rx ( struct pk_buff *pkb,
struct sockaddr_tcpip *st_dest __unused,
uint16_t pshdr_csum ) {
struct tcp_header *tcphdr = pkb->data;
- struct tcp_connection *conn;
+ struct tcp_connection *tcp;
unsigned int hlen;
uint16_t csum;
uint32_t start_seq;
@@ -770,7 +714,7 @@ static int tcp_rx ( struct pk_buff *pkb,
}
/* Parse parameters from header and strip header */
- conn = tcp_demux ( tcphdr->dest );
+ tcp = tcp_demux ( tcphdr->dest );
start_seq = seq = ntohl ( tcphdr->seq );
ack = ntohl ( tcphdr->ack );
win = ntohs ( tcphdr->win );
@@ -779,65 +723,65 @@ static int tcp_rx ( struct pk_buff *pkb,
len = pkb_len ( pkb );
/* Dump header */
- DBGC ( conn, "TCP %p RX %d<-%d %08lx %08lx..%08lx %4zd",
- conn, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
+ DBGC ( tcp, "TCP %p RX %d<-%d %08lx %08lx..%08lx %4zd",
+ tcp, ntohs ( tcphdr->dest ), ntohs ( tcphdr->src ),
ntohl ( tcphdr->ack ), ntohl ( tcphdr->seq ),
( ntohl ( tcphdr->seq ) + len +
( ( tcphdr->flags & ( TCP_SYN | TCP_FIN ) ) ? 1 : 0 ) ), len);
- tcp_dump_flags ( conn, tcphdr->flags );
- DBGC ( conn, "\n" );
+ tcp_dump_flags ( tcp, tcphdr->flags );
+ DBGC ( tcp, "\n" );
/* If no connection was found, send RST */
- if ( ! conn ) {
- tcp_send_reset ( conn, tcphdr );
+ if ( ! tcp ) {
+ tcp_send_reset ( tcp, tcphdr );
rc = -ENOTCONN;
goto done;
}
/* Handle ACK, if present */
if ( flags & TCP_ACK ) {
- if ( ( rc = tcp_rx_ack ( conn, ack, win ) ) != 0 ) {
- tcp_send_reset ( conn, tcphdr );
+ if ( ( rc = tcp_rx_ack ( tcp, ack, win ) ) != 0 ) {
+ tcp_send_reset ( tcp, tcphdr );
goto done;
}
}
/* Handle SYN, if present */
if ( flags & TCP_SYN ) {
- tcp_rx_syn ( conn, seq );
+ tcp_rx_syn ( tcp, seq );
seq++;
}
/* Handle RST, if present */
if ( flags & TCP_RST ) {
- if ( ( rc = tcp_rx_rst ( conn, seq ) ) != 0 )
+ if ( ( rc = tcp_rx_rst ( tcp, seq ) ) != 0 )
goto done;
}
/* Handle new data, if any */
- tcp_rx_data ( conn, seq, data, len );
+ tcp_rx_data ( tcp, seq, data, len );
seq += len;
/* Handle FIN, if present */
if ( flags & TCP_FIN ) {
- tcp_rx_fin ( conn, seq );
+ tcp_rx_fin ( tcp, seq );
seq++;
}
/* Dump out any state change as a result of the received packet */
- tcp_dump_state ( conn );
+ tcp_dump_state ( tcp );
/* Send out any pending data. If peer is expecting an ACK for
* this packet then force sending a reply.
*/
- tcp_senddata_conn ( conn, ( start_seq != seq ) );
+ tcp_senddata_conn ( tcp, ( start_seq != seq ) );
/* If this packet was the last we expect to receive, set up
* timer to expire and cause the connection to be freed.
*/
- if ( TCP_CLOSED_GRACEFULLY ( conn->tcp_state ) ) {
- conn->timer.timeout = ( 2 * TCP_MSL );
- start_timer ( &conn->timer );
+ if ( TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) {
+ tcp->timer.timeout = ( 2 * TCP_MSL );
+ start_timer ( &tcp->timer );
}
rc = 0;
@@ -850,88 +794,88 @@ static int tcp_rx ( struct pk_buff *pkb,
/**
* Bind TCP connection to local port
*
- * @v conn TCP connection
- * @v local_port Local port (in network byte order), or 0
+ * @v stream TCP stream
+ * @v local Local address
* @ret rc Return status code
*
- * This function adds the connection to the list of registered TCP
- * connections. If the local port is 0, the connection is assigned an
- * available port between 1024 and 65535.
+ * Only the port portion of the local address is used. If the local
+ * port is 0, the connection is assigned an available port between
+ * 1024 and 65535.
*/
-static int tcp_bind ( struct tcp_connection *conn, uint16_t local_port ) {
+static int tcp_bind ( struct stream_connection *stream,
+ struct sockaddr *local ) {
+ struct tcp_connection *tcp =
+ container_of ( stream, struct tcp_connection, stream );
+ struct sockaddr_tcpip *st = ( ( struct sockaddr_tcpip * ) local );
struct tcp_connection *existing;
+ struct sockaddr_tcpip try;
static uint16_t try_port = 1024;
+ uint16_t local_port = st->st_port;
/* If no port specified, find the first available port */
if ( ! local_port ) {
for ( ; try_port ; try_port++ ) {
if ( try_port < 1024 )
continue;
- if ( tcp_bind ( conn, htons ( try_port ) ) == 0 )
+ try.st_port = htons ( try_port );
+ if ( tcp_bind ( stream,
+ ( struct sockaddr * ) &try ) == 0 ) {
return 0;
+ }
}
- DBGC ( conn, "TCP %p could not bind: no free ports\n", conn );
+ DBGC ( tcp, "TCP %p could not bind: no free ports\n", tcp );
return -EADDRINUSE;
}
/* Attempt bind to local port */
list_for_each_entry ( existing, &tcp_conns, list ) {
if ( existing->local_port == local_port ) {
- DBGC ( conn, "TCP %p could not bind: port %d in use\n",
- conn, ntohs ( local_port ) );
+ DBGC ( tcp, "TCP %p could not bind: port %d in use\n",
+ tcp, ntohs ( local_port ) );
return -EADDRINUSE;
}
}
- conn->local_port = local_port;
+ tcp->local_port = local_port;
- DBGC ( conn, "TCP %p bound to port %d\n", conn, ntohs ( local_port ) );
+ DBGC ( tcp, "TCP %p bound to port %d\n", tcp, ntohs ( local_port ) );
return 0;
}
/**
* Connect to a remote server
*
- * @v app TCP application
+ * @v stream TCP stream
* @v peer Remote socket address
- * @v local_port Local port number (in network byte order), or 0
* @ret rc Return status code
*
* This function initiates a TCP connection to the socket address specified in
* peer. It sends a SYN packet to peer. When the connection is established, the
* TCP stack calls the connected() callback function.
*/
-int tcp_connect ( struct tcp_application *app, struct sockaddr_tcpip *peer,
- uint16_t local_port ) {
- struct tcp_connection *conn;
+static int tcp_connect ( struct stream_connection *stream,
+ struct sockaddr *peer ) {
+ struct tcp_connection *tcp =
+ container_of ( stream, struct tcp_connection, stream );
+ struct sockaddr_tcpip *st = ( ( struct sockaddr_tcpip * ) peer );
+ struct sockaddr_tcpip local;
int rc;
- /* Application must not already have an open connection */
- if ( app->conn ) {
- DBG ( "TCP app %p already open on %p\n", app, app->conn );
- return -EISCONN;
- }
-
- /* Allocate connection state storage and add to connection list */
- conn = alloc_tcp();
- if ( ! conn ) {
- DBG ( "TCP app %p could not allocate connection\n", app );
- return -ENOMEM;
- }
-
- /* Bind to peer and to local port */
- memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
- if ( ( rc = tcp_bind ( conn, local_port ) ) != 0 ) {
- free_tcp ( conn );
- return rc;
+ /* Bind to local port if not already bound */
+ if ( ! tcp->local_port ) {
+ local.st_port = 0;
+ if ( ( rc = tcp_bind ( stream,
+ ( struct sockaddr * ) &local ) ) != 0 ){
+ return rc;
+ }
}
- /* Associate with application */
- tcp_associate ( conn, app );
+ /* Bind to peer */
+ memcpy ( &tcp->peer, st, sizeof ( tcp->peer ) );
/* Transition to TCP_SYN_SENT and send the SYN */
- conn->tcp_state = TCP_SYN_SENT;
- tcp_dump_state ( conn );
- tcp_senddata_conn ( conn, 0 );
+ tcp->tcp_state = TCP_SYN_SENT;
+ tcp_dump_state ( tcp );
+ tcp_senddata_conn ( tcp, 0 );
return 0;
}
@@ -939,30 +883,22 @@ int tcp_connect ( struct tcp_application *app, struct sockaddr_tcpip *peer,
/**
* Close the connection
*
- * @v app TCP application
+ * @v stream TCP stream
*
- * The association between the application and the TCP connection is
- * immediately severed, and the TCP application data structure can be
- * reused or freed immediately. The TCP connection will persist until
- * the state machine has returned to the TCP_CLOSED state.
+ * The TCP connection will persist until the state machine has
+ * returned to the TCP_CLOSED state.
*/
-void tcp_close ( struct tcp_application *app ) {
- struct tcp_connection *conn = app->conn;
-
- /* If no connection exists, do nothing */
- if ( ! conn )
- return;
-
- /* Break association between application and connection */
- tcp_disassociate ( conn );
+static void tcp_close ( struct stream_connection *stream ) {
+ struct tcp_connection *tcp =
+ container_of ( stream, struct tcp_connection, stream );
/* If we have not yet received a SYN (i.e. we are in CLOSED,
* LISTEN or SYN_SENT), just delete the connection
*/
- if ( ! ( conn->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
- conn->tcp_state = TCP_CLOSED;
- tcp_dump_state ( conn );
- free_tcp ( conn );
+ if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
+ free_tcp ( tcp );
return;
}
@@ -970,15 +906,52 @@ void tcp_close ( struct tcp_application *app ) {
* SYN_RCVD), pretend that it has been acknowledged so that we
* can send a FIN without breaking things.
*/
- if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
- tcp_rx_ack ( conn, ( conn->snd_seq + 1 ), 0 );
+ if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
+ tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 );
/* Send a FIN to initiate the close */
- conn->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
- tcp_dump_state ( conn );
- tcp_senddata_conn ( conn, 0 );
+ tcp->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
+ tcp_dump_state ( tcp );
+ tcp_senddata_conn ( tcp, 0 );
}
+/**
+ * Open TCP connection
+ *
+ * @v app Stream application
+ * @ret rc Return status code
+ */
+int tcp_open ( struct stream_application *app ) {
+ struct tcp_connection *tcp;
+
+ /* Application must not already have an open connection */
+ if ( app->conn ) {
+ DBG ( "TCP app %p already open on %p\n", app, app->conn );
+ return -EISCONN;
+ }
+
+ /* Allocate connection state storage and add to connection list */
+ tcp = alloc_tcp();
+ if ( ! tcp ) {
+ DBG ( "TCP app %p could not allocate connection\n", app );
+ return -ENOMEM;
+ }
+
+ /* Associate application with connection */
+ stream_associate ( app, &tcp->stream );
+
+ return 0;
+}
+
+/** TCP stream operations */
+static struct stream_connection_operations tcp_op = {
+ .bind = tcp_bind,
+ .connect = tcp_connect,
+ .close = tcp_close,
+ .send = tcp_send,
+ .kick = tcp_kick,
+};
+
/** TCP protocol */
struct tcpip_protocol tcp_protocol __tcpip_protocol = {
.name = "TCP",
diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c
index 78567884..061240c3 100644
--- a/src/net/tcp/ftp.c
+++ b/src/net/tcp/ftp.c
@@ -4,10 +4,12 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
+#include <byteswap.h>
#include <gpxe/async.h>
#include <gpxe/buffer.h>
#include <gpxe/uri.h>
#include <gpxe/download.h>
+#include <gpxe/tcp.h>
#include <gpxe/ftp.h>
/** @file
@@ -40,13 +42,14 @@ static const char * ftp_strings[] = {
};
/**
- * Get FTP request from control TCP application
+ * Get FTP request from control stream application
*
- * @v app TCP application
+ * @v app Stream application
* @ret ftp FTP request
*/
-static inline struct ftp_request * tcp_to_ftp ( struct tcp_application *app ) {
- return container_of ( app, struct ftp_request, tcp );
+static inline struct ftp_request *
+stream_to_ftp ( struct stream_application *app ) {
+ return container_of ( app, struct ftp_request, stream );
}
/**
@@ -59,9 +62,9 @@ static void ftp_done ( struct ftp_request *ftp, int rc ) {
DBGC ( ftp, "FTP %p completed with status %d\n", ftp, rc );
- /* Close both TCP connections */
- tcp_close ( &ftp->tcp );
- tcp_close ( &ftp->tcp_data );
+ /* Close both stream connections */
+ stream_close ( &ftp->stream );
+ stream_close ( &ftp->stream_data );
/* Mark asynchronous operation as complete */
async_done ( &ftp->async, rc );
@@ -70,9 +73,9 @@ static void ftp_done ( struct ftp_request *ftp, int rc ) {
/**
* Parse FTP byte sequence value
*
- * @v text Text string
- * @v value Value buffer
- * @v len Length of value buffer
+ * @v text Text string
+ * @v value Value buffer
+ * @v len Length of value buffer
*
* This parses an FTP byte sequence value (e.g. the "aaa,bbb,ccc,ddd"
* form for IP addresses in PORT commands) into a byte sequence. @c
@@ -93,7 +96,7 @@ static void ftp_parse_value ( char **text, uint8_t *value, size_t len ) {
/**
* Handle an FTP control channel response
*
- * @v ftp FTP request
+ * @v ftp FTP request
*
* This is called once we have received a complete response line.
*/
@@ -121,7 +124,7 @@ static void ftp_reply ( struct ftp_request *ftp ) {
char *ptr = ftp->passive_text;
union {
struct sockaddr_in sin;
- struct sockaddr_tcpip st;
+ struct sockaddr sa;
} sa;
int rc;
@@ -130,7 +133,14 @@ static void ftp_reply ( struct ftp_request *ftp ) {
sizeof ( sa.sin.sin_addr ) );
ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_port,
sizeof ( sa.sin.sin_port ) );
- if ( ( rc = tcp_connect ( &ftp->tcp_data, &sa.st, 0 ) ) != 0 ){
+ if ( ( rc = tcp_open ( &ftp->stream_data ) ) != 0 ) {
+ DBGC ( ftp, "FTP %p could not open data connection\n",
+ ftp );
+ ftp_done ( ftp, rc );
+ return;
+ }
+ if ( ( rc = stream_connect ( &ftp->stream_data,
+ &sa.sa ) ) != 0 ){
DBGC ( ftp, "FTP %p could not make data connection\n",
ftp );
ftp_done ( ftp, rc );
@@ -154,16 +164,16 @@ static void ftp_reply ( struct ftp_request *ftp ) {
/**
* Handle new data arriving on FTP control channel
*
- * @v app TCP application
- * @v data New data
- * @v len Length of new data
+ * @v app Stream application
+ * @v data New data
+ * @v len Length of new data
*
* Data is collected until a complete line is received, at which point
* its information is passed to ftp_reply().
*/
-static void ftp_newdata ( struct tcp_application *app,
+static void ftp_newdata ( struct stream_application *app,
void *data, size_t len ) {
- struct ftp_request *ftp = tcp_to_ftp ( app );
+ struct ftp_request *ftp = stream_to_ftp ( app );
char *recvbuf = ftp->recvbuf;
size_t recvsize = ftp->recvsize;
char c;
@@ -210,10 +220,10 @@ static void ftp_newdata ( struct tcp_application *app,
/**
* Handle acknowledgement of data sent on FTP control channel
*
- * @v app TCP application
+ * @v app Stream application
*/
-static void ftp_acked ( struct tcp_application *app, size_t len ) {
- struct ftp_request *ftp = tcp_to_ftp ( app );
+static void ftp_acked ( struct stream_application *app, size_t len ) {
+ struct ftp_request *ftp = stream_to_ftp ( app );
/* Mark off ACKed portion of the currently-transmitted data */
ftp->already_sent += len;
@@ -222,31 +232,31 @@ static void ftp_acked ( struct tcp_application *app, size_t len ) {
/**
* Construct data to send on FTP control channel
*
- * @v app TCP application
- * @v buf Temporary data buffer
- * @v len Length of temporary data buffer
+ * @v app Stream application
+ * @v buf Temporary data buffer
+ * @v len Length of temporary data buffer
*/
-static void ftp_senddata ( struct tcp_application *app,
+static void ftp_senddata ( struct stream_application *app,
void *buf, size_t len ) {
- struct ftp_request *ftp = tcp_to_ftp ( app );
+ struct ftp_request *ftp = stream_to_ftp ( app );
/* Send the as-yet-unACKed portion of the string for the
* current state.
*/
len = snprintf ( buf, len, ftp_strings[ftp->state], ftp->uri->path );
- tcp_send ( app, buf + ftp->already_sent, len - ftp->already_sent );
+ stream_send ( app, buf + ftp->already_sent, len - ftp->already_sent );
}
/**
* Handle control channel being closed
*
- * @v app TCP application
+ * @v app Stream application
*
* When the control channel is closed, the data channel must also be
* closed, if it is currently open.
*/
-static void ftp_closed ( struct tcp_application *app, int rc ) {
- struct ftp_request *ftp = tcp_to_ftp ( app );
+static void ftp_closed ( struct stream_application *app, int rc ) {
+ struct ftp_request *ftp = stream_to_ftp ( app );
DBGC ( ftp, "FTP %p control connection closed: %s\n",
ftp, strerror ( rc ) );
@@ -256,7 +266,7 @@ static void ftp_closed ( struct tcp_application *app, int rc ) {
}
/** FTP control channel operations */
-static struct tcp_operations ftp_tcp_operations = {
+static struct stream_application_operations ftp_stream_operations = {
.closed = ftp_closed,
.acked = ftp_acked,
.newdata = ftp_newdata,
@@ -270,20 +280,20 @@ static struct tcp_operations ftp_tcp_operations = {
*/
/**
- * Get FTP request from data TCP application
+ * Get FTP request from data stream application
*
- * @v app TCP application
+ * @v app Stream application
* @ret ftp FTP request
*/
static inline struct ftp_request *
-tcp_to_ftp_data ( struct tcp_application *app ) {
- return container_of ( app, struct ftp_request, tcp_data );
+stream_to_ftp_data ( struct stream_application *app ) {
+ return container_of ( app, struct ftp_request, stream_data );
}
/**
* Handle data channel being closed
*
- * @v app TCP application
+ * @v app Stream application
*
* When the data channel is closed, the control channel should be left
* alone; the server will send a completion message via the control
@@ -291,8 +301,8 @@ tcp_to_ftp_data ( struct tcp_application *app ) {
*
* If the data channel is closed due to an error, we abort the request.
*/
-static void ftp_data_closed ( struct tcp_application *app, int rc ) {
- struct ftp_request *ftp = tcp_to_ftp_data ( app );
+static void ftp_data_closed ( struct stream_application *app, int rc ) {
+ struct ftp_request *ftp = stream_to_ftp_data ( app );
DBGC ( ftp, "FTP %p data connection closed: %s\n",
ftp, strerror ( rc ) );
@@ -305,13 +315,13 @@ static void ftp_data_closed ( struct tcp_application *app, int rc ) {
/**
* Handle new data arriving on the FTP data channel
*
- * @v app TCP application
- * @v data New data
- * @v len Length of new data
+ * @v app Stream application
+ * @v data New data
+ * @v len Length of new data
*/
-static void ftp_data_newdata ( struct tcp_application *app,
+static void ftp_data_newdata ( struct stream_application *app,
void *data, size_t len ) {
- struct ftp_request *ftp = tcp_to_ftp_data ( app );
+ struct ftp_request *ftp = stream_to_ftp_data ( app );
int rc;
/* Fill data buffer */
@@ -325,7 +335,7 @@ static void ftp_data_newdata ( struct tcp_application *app,
}
/** FTP data channel operations */
-static struct tcp_operations ftp_data_tcp_operations = {
+static struct stream_application_operations ftp_data_stream_operations = {
.closed = ftp_data_closed,
.newdata = ftp_data_newdata,
};
@@ -353,9 +363,6 @@ static struct async_operations ftp_async_operations = {
.reap = ftp_reap,
};
-#warning "Quick name resolution hack"
-#include <byteswap.h>
-
/**
* Initiate an FTP connection
*
@@ -387,12 +394,12 @@ int ftp_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
ftp->already_sent = 0;
ftp->recvbuf = ftp->status_text;
ftp->recvsize = sizeof ( ftp->status_text ) - 1;
- ftp->tcp.tcp_op = &ftp_tcp_operations;
- ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
+ ftp->stream.op = &ftp_stream_operations;
+ ftp->stream_data.op = &ftp_data_stream_operations;
#warning "Quick name resolution hack"
union {
- struct sockaddr_tcpip st;
+ struct sockaddr sa;
struct sockaddr_in sin;
} server;
server.sin.sin_port = htons ( FTP_PORT );
@@ -404,7 +411,9 @@ int ftp_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
DBGC ( ftp, "FTP %p fetching %s\n", ftp, ftp->uri->path );
- if ( ( rc = tcp_connect ( &ftp->tcp, &server.st, 0 ) ) != 0 )
+ if ( ( rc = tcp_open ( &ftp->stream ) ) != 0 )
+ goto err;
+ if ( ( rc = stream_connect ( &ftp->stream, &server.sa ) ) != 0 )
goto err;
async_init ( &ftp->async, &ftp_async_operations, parent );
diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c
index 18030fe6..381ab1f4 100644
--- a/src/net/tcp/http.c
+++ b/src/net/tcp/http.c
@@ -36,13 +36,14 @@
#include <gpxe/buffer.h>
#include <gpxe/download.h>
#include <gpxe/resolv.h>
+#include <gpxe/tcp.h>
#include <gpxe/http.h>
static struct async_operations http_async_operations;
static inline struct http_request *
-tcp_to_http ( struct tcp_application *app ) {
- return container_of ( app, struct http_request, tcp );
+stream_to_http ( struct stream_application *app ) {
+ return container_of ( app, struct http_request, stream );
}
/**
@@ -54,8 +55,8 @@ tcp_to_http ( struct tcp_application *app ) {
*/
static void http_done ( struct http_request *http, int rc ) {
- /* Close TCP connection */
- tcp_close ( &http->tcp );
+ /* Close stream connection */
+ stream_close ( &http->stream );
/* Prevent further processing of any current packet */
http->rx_state = HTTP_RX_DEAD;
@@ -271,9 +272,9 @@ static void http_rx_data ( struct http_request *http,
* @v data New data
* @v len Length of new data
*/
-static void http_newdata ( struct tcp_application *app,
+static void http_newdata ( struct stream_application *app,
void *data, size_t len ) {
- struct http_request *http = tcp_to_http ( app );
+ struct http_request *http = stream_to_http ( app );
const char *buf = data;
char *line;
int rc;
@@ -319,13 +320,13 @@ static void http_newdata ( struct tcp_application *app,
/**
* Send HTTP data
*
- * @v app TCP application
+ * @v app Stream application
* @v buf Temporary data buffer
* @v len Length of temporary data buffer
*/
-static void http_senddata ( struct tcp_application *app,
+static void http_senddata ( struct stream_application *app,
void *buf, size_t len ) {
- struct http_request *http = tcp_to_http ( app );
+ struct http_request *http = stream_to_http ( app );
const char *path = http->uri->path;
const char *host = http->uri->host;
@@ -338,17 +339,18 @@ static void http_senddata ( struct tcp_application *app,
"Host: %s\r\n"
"\r\n", path, host );
- tcp_send ( app, ( buf + http->tx_offset ), ( len - http->tx_offset ) );
+ stream_send ( app, ( buf + http->tx_offset ),
+ ( len - http->tx_offset ) );
}
/**
* HTTP data acknowledged
*
- * @v app TCP application
+ * @v app Stream application
* @v len Length of acknowledged data
*/
-static void http_acked ( struct tcp_application *app, size_t len ) {
- struct http_request *http = tcp_to_http ( app );
+static void http_acked ( struct stream_application *app, size_t len ) {
+ struct http_request *http = stream_to_http ( app );
http->tx_offset += len;
}
@@ -356,10 +358,10 @@ static void http_acked ( struct tcp_application *app, size_t len ) {
/**
* HTTP connection closed by network stack
*
- * @v app TCP application
+ * @v app Stream application
*/
-static void http_closed ( struct tcp_application *app, int rc ) {
- struct http_request *http = tcp_to_http ( app );
+static void http_closed ( struct stream_application *app, int rc ) {
+ struct http_request *http = stream_to_http ( app );
DBGC ( http, "HTTP %p connection closed: %s\n",
http, strerror ( rc ) );
@@ -367,8 +369,8 @@ static void http_closed ( struct tcp_application *app, int rc ) {
http_done ( http, rc );
}
-/** HTTP TCP operations */
-static struct tcp_operations http_tcp_operations = {
+/** HTTP stream operations */
+static struct stream_application_operations http_stream_operations = {
.closed = http_closed,
.acked = http_acked,
.newdata = http_newdata,
@@ -395,6 +397,7 @@ int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
http->uri = uri;
http->buffer = buffer;
async_init ( &http->async, &http_async_operations, parent );
+ http->stream.op = &http_stream_operations;
/* Start name resolution. The download proper will start when
* name resolution completes.
@@ -432,10 +435,15 @@ static void http_sigchld ( struct async *async, enum signal signal __unused ) {
}
/* Otherwise, start the HTTP connection */
- http->tcp.tcp_op = &http_tcp_operations;
+ if ( ( rc = tcp_open ( &http->stream ) ) != 0 ) {
+ DBGC ( http, "HTTP %p could not open stream connection: %s\n",
+ http, strerror ( rc ) );
+ http_done ( http, rc );
+ return;
+ }
st->st_port = htons ( uri_port ( http->uri, HTTP_PORT ) );
- if ( ( rc = tcp_connect ( &http->tcp, st, 0 ) ) != 0 ) {
- DBGC ( http, "HTTP %p could not open TCP connection: %s\n",
+ if ( ( rc = stream_connect ( &http->stream, &http->server ) ) != 0 ) {
+ DBGC ( http, "HTTP %p could not connect stream: %s\n",
http, strerror ( rc ) );
http_done ( http, rc );
return;
diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c
index 4d95c0b9..56567976 100644
--- a/src/net/tcp/iscsi.c
+++ b/src/net/tcp/iscsi.c
@@ -26,6 +26,7 @@
#include <gpxe/scsi.h>
#include <gpxe/process.h>
#include <gpxe/uaccess.h>
+#include <gpxe/tcp.h>
#include <gpxe/iscsi.h>
/** @file
@@ -85,8 +86,8 @@ static void iscsi_rx_buffered_data_done ( struct iscsi_session *iscsi ) {
*/
static void iscsi_close ( struct iscsi_session *iscsi ) {
- /* Close TCP connection */
- tcp_close ( &iscsi->tcp );
+ /* Close stream connection */
+ stream_close ( &iscsi->stream );
/* Clear connection status */
iscsi->status = 0;
@@ -338,7 +339,7 @@ static void iscsi_tx_data_out ( struct iscsi_session *iscsi,
len = remaining;
copy_from_user ( buf, iscsi->command->data_out, offset, len );
- tcp_send ( &iscsi->tcp, buf, len );
+ stream_send ( &iscsi->stream, buf, len );
}
/****************************************************************************
@@ -507,7 +508,7 @@ static void iscsi_login_request_done ( struct iscsi_session *iscsi ) {
static void iscsi_tx_login_request ( struct iscsi_session *iscsi,
void *buf, size_t len ) {
len = iscsi_build_login_request_strings ( iscsi, buf, len );
- tcp_send ( &iscsi->tcp, buf + iscsi->tx_offset,
+ stream_send ( &iscsi->stream, buf + iscsi->tx_offset,
len - iscsi->tx_offset );
}
@@ -750,11 +751,18 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
DBGC ( iscsi, "iSCSI %p redirecting to new server\n", iscsi );
iscsi_close ( iscsi );
- if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
- 0 ) ) != 0 ) {
- DBGC ( iscsi, "iSCSI %p could not open TCP "
- "connection: %s\n", iscsi, strerror ( rc ) );
+ if ( ( rc = tcp_open ( &iscsi->stream ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not open stream: %s\n ",
+ iscsi, strerror ( rc ) );
iscsi_done ( iscsi, rc );
+ return;
+ }
+ if ( ( rc = stream_connect ( &iscsi->stream,
+ &iscsi->target ) != 0 ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not connect: %s\n ",
+ iscsi, strerror ( rc ) );
+ iscsi_done ( iscsi, rc );
+ return;
}
return;
}
@@ -810,13 +818,13 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
/****************************************************************************
*
- * iSCSI to TCP interface
+ * iSCSI to stream interface
*
*/
static inline struct iscsi_session *
-tcp_to_iscsi ( struct tcp_application *app ) {
- return container_of ( app, struct iscsi_session, tcp );
+stream_to_iscsi ( struct stream_application *app ) {
+ return container_of ( app, struct iscsi_session, stream );
}
/**
@@ -889,15 +897,15 @@ static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
}
/**
- * Handle TCP ACKs
+ * Handle stream ACKs
*
* @v iscsi iSCSI session
*
* Updates iscsi->tx_offset and, if applicable, transitions to the
* next TX state.
*/
-static void iscsi_acked ( struct tcp_application *app, size_t len ) {
- struct iscsi_session *iscsi = tcp_to_iscsi ( app );
+static void iscsi_acked ( struct stream_application *app, size_t len ) {
+ struct iscsi_session *iscsi = stream_to_iscsi ( app );
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
enum iscsi_tx_state next_state;
@@ -953,9 +961,9 @@ static void iscsi_acked ( struct tcp_application *app, size_t len ) {
*
* Constructs data to be sent for the current TX state
*/
-static void iscsi_senddata ( struct tcp_application *app,
+static void iscsi_senddata ( struct stream_application *app,
void *buf, size_t len ) {
- struct iscsi_session *iscsi = tcp_to_iscsi ( app );
+ struct iscsi_session *iscsi = stream_to_iscsi ( app );
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
static const char pad[] = { '\0', '\0', '\0' };
@@ -964,7 +972,7 @@ static void iscsi_senddata ( struct tcp_application *app,
/* Nothing to send */
break;
case ISCSI_TX_BHS:
- tcp_send ( app, &iscsi->tx_bhs.bytes[iscsi->tx_offset],
+ stream_send ( app, &iscsi->tx_bhs.bytes[iscsi->tx_offset],
( sizeof ( iscsi->tx_bhs ) - iscsi->tx_offset ) );
break;
case ISCSI_TX_AHS:
@@ -975,8 +983,8 @@ static void iscsi_senddata ( struct tcp_application *app,
iscsi_tx_data ( iscsi, buf, len );
break;
case ISCSI_TX_DATA_PADDING:
- tcp_send ( app, pad, ( ISCSI_DATA_PAD_LEN ( common->lengths )
- - iscsi->tx_offset ) );
+ stream_send ( app, pad, ( ISCSI_DATA_PAD_LEN( common->lengths )
+ - iscsi->tx_offset ) );
break;
default:
assert ( 0 );
@@ -1068,7 +1076,7 @@ static void iscsi_rx_bhs ( struct iscsi_session *iscsi, void *data,
/**
* Receive new data
*
- * @v tcp TCP application
+ * @v stream Stream application
* @v data Received data
* @v len Length of received data
*
@@ -1079,9 +1087,9 @@ static void iscsi_rx_bhs ( struct iscsi_session *iscsi, void *data,
* always has a full copy of the BHS available, even for portions of
* the data in different packets to the BHS.
*/
-static void iscsi_newdata ( struct tcp_application *app, void *data,
+static void iscsi_newdata ( struct stream_application *app, void *data,
size_t len ) {
- struct iscsi_session *iscsi = tcp_to_iscsi ( app );
+ struct iscsi_session *iscsi = stream_to_iscsi ( app );
struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
void ( *process ) ( struct iscsi_session *iscsi, void *data,
size_t len, size_t remaining );
@@ -1138,14 +1146,14 @@ static void iscsi_newdata ( struct tcp_application *app, void *data,
}
/**
- * Handle TCP connection closure
+ * Handle stream connection closure
*
- * @v app TCP application
+ * @v app Stream application
* @v status Error code, if any
*
*/
-static void iscsi_closed ( struct tcp_application *app, int status ) {
- struct iscsi_session *iscsi = tcp_to_iscsi ( app );
+static void iscsi_closed ( struct stream_application *app, int status ) {
+ struct iscsi_session *iscsi = stream_to_iscsi ( app );
int rc;
/* Even a graceful close counts as an error for iSCSI */
@@ -1159,26 +1167,34 @@ static void iscsi_closed ( struct tcp_application *app, int status ) {
if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
DBGC ( iscsi, "iSCSI %p retrying connection (retry #%d)\n",
iscsi, iscsi->retry_count );
- if ( ( rc = tcp_connect ( app, &iscsi->target, 0 ) ) != 0 ) {
- DBGC ( iscsi, "iSCSI %p could not open TCP "
- "connection: %s\n", iscsi, strerror ( rc ) );
+ if ( ( rc = tcp_open ( app ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not open stream: %s\n ",
+ iscsi, strerror ( rc ) );
iscsi_done ( iscsi, rc );
+ return;
+ }
+ if ( ( rc = stream_connect ( app, &iscsi->target ) ) != 0 ){
+ DBGC ( iscsi, "iSCSI %p could not connect: %s\n",
+ iscsi, strerror ( rc ) );
+ iscsi_done ( iscsi, rc );
+ return;
}
} else {
DBGC ( iscsi, "iSCSI %p retry count exceeded\n", iscsi );
iscsi->instant_rc = status;
iscsi_done ( iscsi, status );
+ return;
}
}
/**
- * Handle TCP connection opening
+ * Handle stream connection opening
*
- * @v app TCP application
+ * @v app Stream application
*
*/
-static void iscsi_connected ( struct tcp_application *app ) {
- struct iscsi_session *iscsi = tcp_to_iscsi ( app );
+static void iscsi_connected ( struct stream_application *app ) {
+ struct iscsi_session *iscsi = stream_to_iscsi ( app );
assert ( iscsi->rx_state == ISCSI_RX_BHS );
assert ( iscsi->rx_offset == 0 );
@@ -1194,8 +1210,8 @@ static void iscsi_connected ( struct tcp_application *app ) {
iscsi_start_login ( iscsi );
}
-/** iSCSI TCP operations */
-static struct tcp_operations iscsi_tcp_operations = {
+/** iSCSI stream operations */
+static struct stream_application_operations iscsi_stream_operations = {
.closed = iscsi_closed,
.connected = iscsi_connected,
.acked = iscsi_acked,
@@ -1224,14 +1240,19 @@ int iscsi_issue ( struct iscsi_session *iscsi, struct scsi_command *command,
} else if ( iscsi->status ) {
/* Session already open: issue command */
iscsi_start_command ( iscsi );
- tcp_senddata ( &iscsi->tcp );
+ stream_kick ( &iscsi->stream );
} else {
/* Session not open: initiate login */
- iscsi->tcp.tcp_op = &iscsi_tcp_operations;
- if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
- 0 ) ) != 0 ) {
- DBGC ( iscsi, "iSCSI %p could not open TCP "
- "connection: %s\n", iscsi, strerror ( rc ) );
+ iscsi->stream.op = &iscsi_stream_operations;
+ if ( ( rc = tcp_open ( &iscsi->stream ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not open stream: %s\n ",
+ iscsi, strerror ( rc ) );
+ return rc;
+ }
+ if ( ( rc = stream_connect ( &iscsi->stream,
+ &iscsi->target ) ) != 0 ) {
+ DBGC ( iscsi, "iSCSI %p could not connect: %s\n",
+ iscsi, strerror ( rc ) );
return rc;
}
}