mirror of
https://github.com/ipxe/ipxe
synced 2025-12-22 13:00:39 +03:00
Merge changes from mcb-tcp-fixes branch.
This commit is contained in:
@@ -58,49 +58,31 @@ static inline const void * ftp_string_data ( struct ftp_request *ftp,
|
||||
}
|
||||
|
||||
/**
|
||||
* Get FTP request from control TCP connection
|
||||
* Get FTP request from control TCP application
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
* @ret ftp FTP request
|
||||
*/
|
||||
static inline struct ftp_request * tcp_to_ftp ( struct tcp_connection *conn ) {
|
||||
return container_of ( conn, struct ftp_request, tcp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set overall FTP operation status
|
||||
*
|
||||
* @v ftp FTP request
|
||||
* @v rc Return status code
|
||||
*
|
||||
* Set the return status that will eventually be returned via
|
||||
* ftp_done(). If multiple errors are flagged, only the first will be
|
||||
* returned.
|
||||
*/
|
||||
static void ftp_set_status ( struct ftp_request *ftp, int rc ) {
|
||||
if ( ! ftp->rc )
|
||||
ftp->rc = rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear overall FTP operation status
|
||||
*
|
||||
* @v ftp FTP request
|
||||
*/
|
||||
static void ftp_clear_status ( struct ftp_request *ftp ) {
|
||||
ftp->rc = 0;
|
||||
static inline struct ftp_request * tcp_to_ftp ( struct tcp_application *app ) {
|
||||
return container_of ( app, struct ftp_request, tcp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark FTP operation as complete
|
||||
*
|
||||
* @v ftp FTP request
|
||||
* @v rc Return status code
|
||||
*/
|
||||
static void ftp_done ( struct ftp_request *ftp ) {
|
||||
static void ftp_done ( struct ftp_request *ftp, int rc ) {
|
||||
|
||||
DBG ( "FTP %p completed with status %d\n", ftp, ftp->rc );
|
||||
DBG ( "FTP %p completed with status %d\n", ftp, rc );
|
||||
|
||||
async_done ( &ftp->aop, ftp->rc );
|
||||
/* Close both TCP connections */
|
||||
tcp_close ( &ftp->tcp );
|
||||
tcp_close ( &ftp->tcp_data );
|
||||
|
||||
/* Mark asynchronous operation as complete */
|
||||
async_done ( &ftp->aop, rc );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +113,7 @@ static void ftp_parse_value ( char **text, uint8_t *value, size_t len ) {
|
||||
*
|
||||
* @v ftp FTP request
|
||||
*
|
||||
* This is called once we have received a complete repsonse line.
|
||||
* This is called once we have received a complete response line.
|
||||
*/
|
||||
static void ftp_reply ( struct ftp_request *ftp ) {
|
||||
char status_major = ftp->status_text[0];
|
||||
@@ -147,21 +129,31 @@ static void ftp_reply ( struct ftp_request *ftp ) {
|
||||
* fatal error.
|
||||
*/
|
||||
if ( ! ( ( status_major == '2' ) ||
|
||||
( ( status_major == '3' ) && ( ftp->state == FTP_USER ) ) ) )
|
||||
goto err;
|
||||
( ( status_major == '3' ) && ( ftp->state == FTP_USER ) ) ) ){
|
||||
/* Flag protocol error and close connections */
|
||||
ftp_done ( ftp, -EPROTO );
|
||||
}
|
||||
|
||||
/* Open passive connection when we get "PASV" response */
|
||||
if ( ftp->state == FTP_PASV ) {
|
||||
char *ptr = ftp->passive_text;
|
||||
struct sockaddr_in *sin =
|
||||
( struct sockaddr_in * ) &ftp->tcp_data.peer;
|
||||
union {
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_tcpip st;
|
||||
} sa;
|
||||
int rc;
|
||||
|
||||
sin->sin_family = AF_INET;
|
||||
ftp_parse_value ( &ptr, ( uint8_t * ) &sin->sin_addr,
|
||||
sizeof ( sin->sin_addr ) );
|
||||
ftp_parse_value ( &ptr, ( uint8_t * ) &sin->sin_port,
|
||||
sizeof ( sin->sin_port ) );
|
||||
tcp_connect ( &ftp->tcp_data );
|
||||
sa.sin.sin_family = AF_INET;
|
||||
ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_addr,
|
||||
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 ){
|
||||
DBG ( "FTP %p could not create data connection\n",
|
||||
ftp );
|
||||
ftp_done ( ftp, rc );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to next state */
|
||||
@@ -176,26 +168,21 @@ static void ftp_reply ( struct ftp_request *ftp ) {
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
/* Flag protocol error and close connections */
|
||||
ftp_set_status ( ftp, -EPROTO );
|
||||
tcp_close ( &ftp->tcp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle new data arriving on FTP control channel
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP 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_connection *conn,
|
||||
static void ftp_newdata ( struct tcp_application *app,
|
||||
void *data, size_t len ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
||||
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||
char *recvbuf = ftp->recvbuf;
|
||||
size_t recvsize = ftp->recvsize;
|
||||
char c;
|
||||
@@ -242,10 +229,10 @@ static void ftp_newdata ( struct tcp_connection *conn,
|
||||
/**
|
||||
* Handle acknowledgement of data sent on FTP control channel
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
*/
|
||||
static void ftp_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
||||
static void ftp_acked ( struct tcp_application *app, size_t len ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||
|
||||
/* Mark off ACKed portion of the currently-transmitted data */
|
||||
ftp->already_sent += len;
|
||||
@@ -254,13 +241,13 @@ static void ftp_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
/**
|
||||
* Construct data to send on FTP control channel
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
* @v buf Temporary data buffer
|
||||
* @v len Length of temporary data buffer
|
||||
*/
|
||||
static void ftp_senddata ( struct tcp_connection *conn,
|
||||
static void ftp_senddata ( struct tcp_application *app,
|
||||
void *buf, size_t len ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
||||
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||
const struct ftp_string *string;
|
||||
|
||||
/* Send the as-yet-unACKed portion of the string for the
|
||||
@@ -269,31 +256,24 @@ static void ftp_senddata ( struct tcp_connection *conn,
|
||||
string = &ftp_strings[ftp->state];
|
||||
len = snprintf ( buf, len, string->format,
|
||||
ftp_string_data ( ftp, string->data_offset ) );
|
||||
tcp_send ( conn, buf + ftp->already_sent, len - ftp->already_sent );
|
||||
tcp_send ( app, buf + ftp->already_sent, len - ftp->already_sent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle control channel being closed
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP 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_connection *conn, int status ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
||||
static void ftp_closed ( struct tcp_application *app, int status ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||
|
||||
DBG ( "FTP %p control connection closed (status %d)\n", ftp, status );
|
||||
|
||||
/* Close data channel and record status */
|
||||
ftp_set_status ( ftp, status );
|
||||
tcp_close ( &ftp->tcp_data );
|
||||
|
||||
/* Mark FTP operation as complete if we are the last
|
||||
* connection to close
|
||||
*/
|
||||
if ( tcp_closed ( &ftp->tcp_data ) )
|
||||
ftp_done ( ftp );
|
||||
/* Complete FTP operation */
|
||||
ftp_done ( ftp, status );
|
||||
}
|
||||
|
||||
/** FTP control channel operations */
|
||||
@@ -311,20 +291,20 @@ static struct tcp_operations ftp_tcp_operations = {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get FTP request from data TCP connection
|
||||
* Get FTP request from data TCP application
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
* @ret ftp FTP request
|
||||
*/
|
||||
static inline struct ftp_request *
|
||||
tcp_to_ftp_data ( struct tcp_connection *conn ) {
|
||||
return container_of ( conn, struct ftp_request, tcp_data );
|
||||
tcp_to_ftp_data ( struct tcp_application *app ) {
|
||||
return container_of ( app, struct ftp_request, tcp_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle data channel being closed
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
*
|
||||
* When the data channel is closed, the control channel should be left
|
||||
* alone; the server will send a completion message via the control
|
||||
@@ -332,36 +312,28 @@ tcp_to_ftp_data ( struct tcp_connection *conn ) {
|
||||
*
|
||||
* If the data channel is closed due to an error, we abort the request.
|
||||
*/
|
||||
static void ftp_data_closed ( struct tcp_connection *conn, int status ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp_data ( conn );
|
||||
static void ftp_data_closed ( struct tcp_application *app, int status ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp_data ( app );
|
||||
|
||||
DBG ( "FTP %p data connection closed (status %d)\n", ftp, status );
|
||||
|
||||
/* If there was an error, close control channel and record status */
|
||||
if ( status ) {
|
||||
ftp_set_status ( ftp, status );
|
||||
tcp_close ( &ftp->tcp );
|
||||
}
|
||||
|
||||
/* Mark FTP operation as complete if we are the last
|
||||
* connection to close
|
||||
*/
|
||||
if ( tcp_closed ( &ftp->tcp ) )
|
||||
ftp_done ( ftp );
|
||||
if ( status )
|
||||
ftp_done ( ftp, status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle new data arriving on the FTP data channel
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
* @v data New data
|
||||
* @v len Length of new data
|
||||
*
|
||||
* Data is handed off to the callback registered in the FTP request.
|
||||
*/
|
||||
static void ftp_data_newdata ( struct tcp_connection *conn,
|
||||
static void ftp_data_newdata ( struct tcp_application *app,
|
||||
void *data, size_t len ) {
|
||||
struct ftp_request *ftp = tcp_to_ftp_data ( conn );
|
||||
struct ftp_request *ftp = tcp_to_ftp_data ( app );
|
||||
|
||||
ftp->callback ( data, len );
|
||||
}
|
||||
@@ -384,14 +356,16 @@ static struct tcp_operations ftp_data_tcp_operations = {
|
||||
* @v ftp FTP request
|
||||
*/
|
||||
struct async_operation * ftp_get ( struct ftp_request *ftp ) {
|
||||
|
||||
int rc;
|
||||
|
||||
DBG ( "FTP %p fetching %s\n", ftp, ftp->filename );
|
||||
|
||||
ftp->tcp.tcp_op = &ftp_tcp_operations;
|
||||
ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
|
||||
ftp->recvbuf = ftp->status_text;
|
||||
ftp->recvsize = sizeof ( ftp->status_text ) - 1;
|
||||
ftp_clear_status ( ftp );
|
||||
tcp_connect ( &ftp->tcp );
|
||||
if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
|
||||
ftp_done ( ftp, rc );
|
||||
|
||||
return &ftp->aop;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
* "Hello world" TCP protocol
|
||||
*
|
||||
* This file implements a trivial TCP-based protocol. It connects to
|
||||
* the server specified in hello_request::tcp and transmits a single
|
||||
* message (hello_request::message). Any data received from the
|
||||
* server will be passed to the callback function,
|
||||
* the server specified in hello_request::server and transmits a
|
||||
* single message (hello_request::message). Any data received from
|
||||
* the server will be passed to the callback function,
|
||||
* hello_request::callback(), and once the connection has been closed,
|
||||
* the asynchronous operation associated with the request will be
|
||||
* marked as complete.
|
||||
@@ -26,13 +26,13 @@
|
||||
* }
|
||||
*
|
||||
* struct hello_request hello = {
|
||||
* .server = {
|
||||
* ...
|
||||
* },
|
||||
* .message = "hello world!",
|
||||
* .callback = my_callback,
|
||||
* };
|
||||
*
|
||||
* hello.sin.sin_addr.s_addr = ... server IP address ...
|
||||
* hello.sin.sin_port = ... server port ...
|
||||
*
|
||||
* rc = async_wait ( say_hello ( &hello ) );
|
||||
*
|
||||
* @endcode
|
||||
@@ -44,25 +44,25 @@
|
||||
*/
|
||||
|
||||
static inline struct hello_request *
|
||||
tcp_to_hello ( struct tcp_connection *conn ) {
|
||||
return container_of ( conn, struct hello_request, tcp );
|
||||
tcp_to_hello ( struct tcp_application *app ) {
|
||||
return container_of ( app, struct hello_request, tcp );
|
||||
}
|
||||
|
||||
static void hello_closed ( struct tcp_connection *conn, int status ) {
|
||||
struct hello_request *hello = tcp_to_hello ( conn );
|
||||
static void hello_closed ( struct tcp_application *app, int status ) {
|
||||
struct hello_request *hello = tcp_to_hello ( app );
|
||||
|
||||
async_done ( &hello->aop, status );
|
||||
}
|
||||
|
||||
static void hello_connected ( struct tcp_connection *conn ) {
|
||||
struct hello_request *hello = tcp_to_hello ( conn );
|
||||
static void hello_connected ( struct tcp_application *app ) {
|
||||
struct hello_request *hello = tcp_to_hello ( app );
|
||||
|
||||
hello->remaining = strlen ( hello->message );
|
||||
hello->state = HELLO_SENDING_MESSAGE;
|
||||
}
|
||||
|
||||
static void hello_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
struct hello_request *hello = tcp_to_hello ( conn );
|
||||
static void hello_acked ( struct tcp_application *app, size_t len ) {
|
||||
struct hello_request *hello = tcp_to_hello ( app );
|
||||
|
||||
hello->message += len;
|
||||
hello->remaining -= len;
|
||||
@@ -84,18 +84,18 @@ static void hello_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
}
|
||||
}
|
||||
|
||||
static void hello_newdata ( struct tcp_connection *conn, void *data,
|
||||
static void hello_newdata ( struct tcp_application *app, void *data,
|
||||
size_t len ) {
|
||||
struct hello_request *hello = tcp_to_hello ( conn );
|
||||
struct hello_request *hello = tcp_to_hello ( app );
|
||||
|
||||
hello->callback ( data, len );
|
||||
}
|
||||
|
||||
static void hello_senddata ( struct tcp_connection *conn,
|
||||
static void hello_senddata ( struct tcp_application *app,
|
||||
void *buf __unused, size_t len __unused ) {
|
||||
struct hello_request *hello = tcp_to_hello ( conn );
|
||||
struct hello_request *hello = tcp_to_hello ( app );
|
||||
|
||||
tcp_send ( conn, hello->message, hello->remaining );
|
||||
tcp_send ( app, hello->message, hello->remaining );
|
||||
}
|
||||
|
||||
static struct tcp_operations hello_tcp_operations = {
|
||||
@@ -112,7 +112,11 @@ static struct tcp_operations hello_tcp_operations = {
|
||||
* @v hello "Hello world" request
|
||||
*/
|
||||
struct async_operation * say_hello ( struct hello_request *hello ) {
|
||||
int rc;
|
||||
|
||||
hello->tcp.tcp_op = &hello_tcp_operations;
|
||||
tcp_connect ( &hello->tcp );
|
||||
if ( ( rc = tcp_connect ( &hello->tcp, &hello->server, 0 ) ) != 0 )
|
||||
async_done ( &hello->aop, rc );
|
||||
|
||||
return &hello->aop;
|
||||
}
|
||||
|
||||
@@ -39,28 +39,28 @@
|
||||
*/
|
||||
|
||||
static inline struct http_request *
|
||||
tcp_to_http ( struct tcp_connection *conn ) {
|
||||
return container_of ( conn, struct http_request, tcp );
|
||||
tcp_to_http ( struct tcp_application *app ) {
|
||||
return container_of ( app, struct http_request, tcp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an HTTP connection
|
||||
*
|
||||
* @v conn a TCP Connection
|
||||
* @v app a TCP Application
|
||||
* @v status connection status at close
|
||||
*/
|
||||
static void http_closed ( struct tcp_connection *conn, int status ) {
|
||||
struct http_request *http = tcp_to_http ( conn );
|
||||
static void http_closed ( struct tcp_application *app, int status ) {
|
||||
struct http_request *http = tcp_to_http ( app );
|
||||
async_done ( &http->aop, status );
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback after a TCP connection is established
|
||||
*
|
||||
* @v conn a TCP Connection
|
||||
* @v app a TCP Application
|
||||
*/
|
||||
static void http_connected ( struct tcp_connection *conn ) {
|
||||
struct http_request *http = tcp_to_http ( conn );
|
||||
static void http_connected ( struct tcp_application *app ) {
|
||||
struct http_request *http = tcp_to_http ( app );
|
||||
|
||||
http->state = HTTP_REQUEST_FILE;
|
||||
}
|
||||
@@ -68,11 +68,11 @@ static void http_connected ( struct tcp_connection *conn ) {
|
||||
/**
|
||||
* Callback for when TCP data is acknowledged
|
||||
*
|
||||
* @v conn a TCP Connection
|
||||
* @v app a TCP Application
|
||||
* @v len the length of data acked
|
||||
*/
|
||||
static void http_acked ( struct tcp_connection *conn, size_t len __attribute__ ((unused)) ) {
|
||||
struct http_request *http = tcp_to_http ( conn );
|
||||
static void http_acked ( struct tcp_application *app, size_t len __attribute__ ((unused)) ) {
|
||||
struct http_request *http = tcp_to_http ( app );
|
||||
|
||||
// assume that the whole GET request was sent in on epacket
|
||||
|
||||
@@ -84,7 +84,7 @@ static void http_acked ( struct tcp_connection *conn, size_t len __attribute__ (
|
||||
case HTTP_RECV_FILE:
|
||||
break;
|
||||
case HTTP_DONE:
|
||||
//tcp_close(conn);
|
||||
//tcp_close(app);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -95,13 +95,13 @@ static void http_acked ( struct tcp_connection *conn, size_t len __attribute__ (
|
||||
/**
|
||||
* Callback when new TCP data is recieved
|
||||
*
|
||||
* @v conn a TCP Connection
|
||||
* @v app a TCP Application
|
||||
* @v data a pointer to the data recieved
|
||||
* @v len length of data buffer
|
||||
*/
|
||||
static void http_newdata ( struct tcp_connection *conn, void *data,
|
||||
static void http_newdata ( struct tcp_application *app, void *data,
|
||||
size_t len ) {
|
||||
struct http_request *http = tcp_to_http ( conn );
|
||||
struct http_request *http = tcp_to_http ( app );
|
||||
char *content_length;
|
||||
char *start = data;
|
||||
char *rcp; int rc;
|
||||
@@ -142,7 +142,7 @@ static void http_newdata ( struct tcp_connection *conn, void *data,
|
||||
//printf("File recv is %d\n", http->file_recv);
|
||||
if ( http->file_recv == http->file_size ){
|
||||
http->state = HTTP_DONE;
|
||||
tcp_close(conn);
|
||||
tcp_close(app);
|
||||
}
|
||||
break;
|
||||
case HTTP_REQUEST_FILE:
|
||||
@@ -155,10 +155,10 @@ static void http_newdata ( struct tcp_connection *conn, void *data,
|
||||
/**
|
||||
* Callback for sending TCP data
|
||||
*
|
||||
* @v conn a TCP Connection
|
||||
* @v app a TCP Application
|
||||
*/
|
||||
static void http_senddata ( struct tcp_connection *conn, void *buf, size_t len ) {
|
||||
struct http_request *http = tcp_to_http ( conn );
|
||||
static void http_senddata ( struct tcp_application *app, void *buf, size_t len ) {
|
||||
struct http_request *http = tcp_to_http ( app );
|
||||
|
||||
switch ( http->state ){
|
||||
case HTTP_REQUEST_FILE:
|
||||
@@ -166,13 +166,13 @@ static void http_senddata ( struct tcp_connection *conn, void *buf, size_t len )
|
||||
printf("%s\n",(char *)buf);
|
||||
// string is: GET <file> HTTP/1.0\r\n\r\n
|
||||
|
||||
tcp_send ( conn, buf, len);
|
||||
tcp_send ( app, buf, len);
|
||||
break;
|
||||
case HTTP_PARSE_HEADER:
|
||||
case HTTP_RECV_FILE:
|
||||
break;
|
||||
case HTTP_DONE:
|
||||
//tcp_close(conn)
|
||||
//tcp_close(app)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -193,8 +193,12 @@ static struct tcp_operations http_tcp_operations = {
|
||||
* @v http a HTTP request
|
||||
*/
|
||||
struct async_operation * get_http ( struct http_request *http ) {
|
||||
int rc;
|
||||
|
||||
http->tcp.tcp_op = &http_tcp_operations;
|
||||
http->state = HTTP_REQUEST_FILE;
|
||||
tcp_connect ( &http->tcp );
|
||||
if ( ( rc = tcp_connect ( &http->tcp, &http->server, 0 ) ) != 0 )
|
||||
async_done ( &http->aop, rc );
|
||||
|
||||
return &http->aop;
|
||||
}
|
||||
|
||||
@@ -720,11 +720,14 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
|
||||
/* Check for login redirection */
|
||||
if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
|
||||
DBG ( "iSCSI %p redirecting to new server\n", iscsi );
|
||||
/* Close the TCP connection; our TCP closed() method
|
||||
* will take care of the reconnection once this
|
||||
* connection has been cleanly terminated.
|
||||
*/
|
||||
tcp_close ( &iscsi->tcp );
|
||||
iscsi->status = 0;
|
||||
if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
|
||||
0 ) ) != 0 ) {
|
||||
DBG ( "iSCSI %p could not open TCP connection\n",
|
||||
iscsi );
|
||||
iscsi_done ( iscsi, rc );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -778,8 +781,8 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
|
||||
*/
|
||||
|
||||
static inline struct iscsi_session *
|
||||
tcp_to_iscsi ( struct tcp_connection *conn ) {
|
||||
return container_of ( conn, struct iscsi_session, tcp );
|
||||
tcp_to_iscsi ( struct tcp_application *app ) {
|
||||
return container_of ( app, struct iscsi_session, tcp );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -859,8 +862,8 @@ static void iscsi_tx_done ( struct iscsi_session *iscsi ) {
|
||||
* Updates iscsi->tx_offset and, if applicable, transitions to the
|
||||
* next TX state.
|
||||
*/
|
||||
static void iscsi_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
||||
static void iscsi_acked ( struct tcp_application *app, size_t len ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
|
||||
enum iscsi_tx_state next_state;
|
||||
|
||||
@@ -916,9 +919,9 @@ static void iscsi_acked ( struct tcp_connection *conn, size_t len ) {
|
||||
*
|
||||
* Constructs data to be sent for the current TX state
|
||||
*/
|
||||
static void iscsi_senddata ( struct tcp_connection *conn,
|
||||
static void iscsi_senddata ( struct tcp_application *app,
|
||||
void *buf, size_t len ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
|
||||
static const char pad[] = { '\0', '\0', '\0' };
|
||||
|
||||
@@ -927,7 +930,7 @@ static void iscsi_senddata ( struct tcp_connection *conn,
|
||||
/* Nothing to send */
|
||||
break;
|
||||
case ISCSI_TX_BHS:
|
||||
tcp_send ( conn, &iscsi->tx_bhs.bytes[iscsi->tx_offset],
|
||||
tcp_send ( app, &iscsi->tx_bhs.bytes[iscsi->tx_offset],
|
||||
( sizeof ( iscsi->tx_bhs ) - iscsi->tx_offset ) );
|
||||
break;
|
||||
case ISCSI_TX_AHS:
|
||||
@@ -938,7 +941,7 @@ static void iscsi_senddata ( struct tcp_connection *conn,
|
||||
iscsi_tx_data ( iscsi, buf, len );
|
||||
break;
|
||||
case ISCSI_TX_DATA_PADDING:
|
||||
tcp_send ( conn, pad, ( ISCSI_DATA_PAD_LEN ( common->lengths )
|
||||
tcp_send ( app, pad, ( ISCSI_DATA_PAD_LEN ( common->lengths )
|
||||
- iscsi->tx_offset ) );
|
||||
break;
|
||||
default:
|
||||
@@ -1029,7 +1032,7 @@ static void iscsi_rx_bhs ( struct iscsi_session *iscsi, void *data,
|
||||
/**
|
||||
* Receive new data
|
||||
*
|
||||
* @v tcp TCP connection
|
||||
* @v tcp TCP application
|
||||
* @v data Received data
|
||||
* @v len Length of received data
|
||||
*
|
||||
@@ -1040,9 +1043,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_connection *conn, void *data,
|
||||
static void iscsi_newdata ( struct tcp_application *app, void *data,
|
||||
size_t len ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
||||
struct iscsi_session *iscsi = tcp_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 );
|
||||
@@ -1098,38 +1101,28 @@ static void iscsi_newdata ( struct tcp_connection *conn, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
#warning "Remove me soon"
|
||||
static struct tcp_operations iscsi_tcp_operations;
|
||||
|
||||
/**
|
||||
* Handle TCP connection closure
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
* @v status Error code, if any
|
||||
*
|
||||
*/
|
||||
static void iscsi_closed ( struct tcp_connection *conn, int status ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
||||
int session_status = iscsi->status;
|
||||
static void iscsi_closed ( struct tcp_application *app, int status ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||
int rc;
|
||||
|
||||
/* Clear session status */
|
||||
iscsi->status = 0;
|
||||
|
||||
/* If we are deliberately closing down, exit cleanly */
|
||||
if ( session_status & ISCSI_STATUS_CLOSING ) {
|
||||
iscsi_done ( iscsi, status );
|
||||
return;
|
||||
}
|
||||
|
||||
/* Retry connection if within the retry limit, otherwise fail */
|
||||
if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
|
||||
DBG ( "iSCSI %p retrying connection\n", iscsi );
|
||||
/* Re-copy address to handle redirection */
|
||||
memset ( &iscsi->tcp, 0, sizeof ( iscsi->tcp ) );
|
||||
iscsi->tcp.tcp_op = &iscsi_tcp_operations;
|
||||
memcpy ( &iscsi->tcp.peer, &iscsi->target,
|
||||
sizeof ( iscsi->tcp.peer ) );
|
||||
tcp_connect ( conn );
|
||||
if ( ( rc = tcp_connect ( app, &iscsi->target, 0 ) ) != 0 ) {
|
||||
DBG ( "iSCSI %p could not open TCP connection\n",
|
||||
iscsi );
|
||||
iscsi_done ( iscsi, rc );
|
||||
}
|
||||
} else {
|
||||
printf ( "iSCSI %p retry count exceeded\n", iscsi );
|
||||
iscsi_done ( iscsi, status );
|
||||
@@ -1139,11 +1132,11 @@ static void iscsi_closed ( struct tcp_connection *conn, int status ) {
|
||||
/**
|
||||
* Handle TCP connection opening
|
||||
*
|
||||
* @v conn TCP connection
|
||||
* @v app TCP application
|
||||
*
|
||||
*/
|
||||
static void iscsi_connected ( struct tcp_connection *conn ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
||||
static void iscsi_connected ( struct tcp_application *app ) {
|
||||
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||
|
||||
/* Set connected flag and reset retry count */
|
||||
iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
|
||||
@@ -1179,6 +1172,8 @@ static struct tcp_operations iscsi_tcp_operations = {
|
||||
*/
|
||||
struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||
struct scsi_command *command ) {
|
||||
int rc;
|
||||
|
||||
assert ( iscsi->command == NULL );
|
||||
iscsi->command = command;
|
||||
|
||||
@@ -1198,9 +1193,12 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||
} else {
|
||||
/* Session not open: initiate login */
|
||||
iscsi->tcp.tcp_op = &iscsi_tcp_operations;
|
||||
memcpy ( &iscsi->tcp.peer, &iscsi->target,
|
||||
sizeof ( iscsi->tcp.peer ) );
|
||||
tcp_connect ( &iscsi->tcp );
|
||||
if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
|
||||
0 ) ) != 0 ) {
|
||||
DBG ( "iSCSI %p could not open TCP connection\n",
|
||||
iscsi );
|
||||
iscsi_done ( iscsi, rc );
|
||||
}
|
||||
}
|
||||
|
||||
return &iscsi->aop;
|
||||
@@ -1212,10 +1210,7 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||
* @v iscsi iSCSI session
|
||||
* @ret aop Asynchronous operation
|
||||
*/
|
||||
struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi ) {
|
||||
if ( iscsi->status ) {
|
||||
iscsi->status |= ISCSI_STATUS_CLOSING;
|
||||
tcp_close ( &iscsi->tcp );
|
||||
}
|
||||
return &iscsi->aop;
|
||||
void iscsi_shutdown ( struct iscsi_session *iscsi ) {
|
||||
iscsi->status = 0;
|
||||
tcp_close ( &iscsi->tcp );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user