Merge changes from mcb-tcp-fixes branch.
This commit is contained in:
parent
b6def29f2b
commit
61ed298bc7
|
@ -63,5 +63,5 @@ int init_iscsidev ( struct iscsi_device *iscsidev ) {
|
||||||
* @v iscsidev iSCSI device
|
* @v iscsidev iSCSI device
|
||||||
*/
|
*/
|
||||||
void fini_iscsidev ( struct iscsi_device *iscsidev ) {
|
void fini_iscsidev ( struct iscsi_device *iscsidev ) {
|
||||||
async_wait ( iscsi_shutdown ( &iscsidev->iscsi ) );
|
iscsi_shutdown ( &iscsidev->iscsi );
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ enum ftp_state {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct ftp_request {
|
struct ftp_request {
|
||||||
/** TCP connection for this request */
|
/** Server address */
|
||||||
struct tcp_connection tcp;
|
struct sockaddr_tcpip server;
|
||||||
/** File to download */
|
/** File to download */
|
||||||
const char *filename;
|
const char *filename;
|
||||||
/** Callback function
|
/** Callback function
|
||||||
|
@ -49,10 +49,6 @@ struct ftp_request {
|
||||||
* remote server.
|
* remote server.
|
||||||
*/
|
*/
|
||||||
void ( *callback ) ( char *data, size_t len );
|
void ( *callback ) ( char *data, size_t len );
|
||||||
/** Eventual return status */
|
|
||||||
int rc;
|
|
||||||
/** Asynchronous operation for this FTP operation */
|
|
||||||
struct async_operation aop;
|
|
||||||
|
|
||||||
/** Current state */
|
/** Current state */
|
||||||
enum ftp_state state;
|
enum ftp_state state;
|
||||||
|
@ -67,8 +63,13 @@ struct ftp_request {
|
||||||
/** Passive-mode parameters, as text */
|
/** Passive-mode parameters, as text */
|
||||||
char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
|
char passive_text[24]; /* "aaa,bbb,ccc,ddd,eee,fff" */
|
||||||
|
|
||||||
/** TCP connection for the data channel */
|
/** TCP application for the control channel */
|
||||||
struct tcp_connection tcp_data;
|
struct tcp_application tcp;
|
||||||
|
/** TCP application for the data channel */
|
||||||
|
struct tcp_application tcp_data;
|
||||||
|
|
||||||
|
/** Asynchronous operation for this FTP operation */
|
||||||
|
struct async_operation aop;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct async_operation * ftp_get ( struct ftp_request *ftp );
|
struct async_operation * ftp_get ( struct ftp_request *ftp );
|
||||||
|
|
|
@ -21,14 +21,10 @@ enum hello_state {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct hello_request {
|
struct hello_request {
|
||||||
/** TCP connection for this request */
|
/** Server to connect to */
|
||||||
struct tcp_connection tcp;
|
struct sockaddr_tcpip server;
|
||||||
/** Current state */
|
|
||||||
enum hello_state state;
|
|
||||||
/** Message to be transmitted */
|
/** Message to be transmitted */
|
||||||
const char *message;
|
const char *message;
|
||||||
/** Amount of message remaining to be transmitted */
|
|
||||||
size_t remaining;
|
|
||||||
/** Callback function
|
/** Callback function
|
||||||
*
|
*
|
||||||
* @v data Received data
|
* @v data Received data
|
||||||
|
@ -38,6 +34,15 @@ struct hello_request {
|
||||||
* remote server.
|
* remote server.
|
||||||
*/
|
*/
|
||||||
void ( *callback ) ( char *data, size_t len );
|
void ( *callback ) ( char *data, size_t len );
|
||||||
|
|
||||||
|
/** Current state */
|
||||||
|
enum hello_state state;
|
||||||
|
/** Amount of message remaining to be transmitted */
|
||||||
|
size_t remaining;
|
||||||
|
|
||||||
|
/** TCP application for this request */
|
||||||
|
struct tcp_application tcp;
|
||||||
|
|
||||||
/** Asynchronous operation */
|
/** Asynchronous operation */
|
||||||
struct async_operation aop;
|
struct async_operation aop;
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,8 +29,10 @@ enum http_state {
|
||||||
struct http_request;
|
struct http_request;
|
||||||
|
|
||||||
struct http_request {
|
struct http_request {
|
||||||
/** TCP connection for this request */
|
/** Server address */
|
||||||
struct tcp_connection tcp;
|
struct sockaddr_tcpip server;
|
||||||
|
/** TCP application for this request */
|
||||||
|
struct tcp_application tcp;
|
||||||
/** Current state */
|
/** Current state */
|
||||||
enum http_state state;
|
enum http_state state;
|
||||||
/** File to download */
|
/** File to download */
|
||||||
|
|
|
@ -486,40 +486,33 @@ enum iscsi_rx_state {
|
||||||
|
|
||||||
/** An iSCSI session */
|
/** An iSCSI session */
|
||||||
struct iscsi_session {
|
struct iscsi_session {
|
||||||
/** TCP connection for this session */
|
/** Initiator IQN */
|
||||||
struct tcp_connection tcp;
|
const char *initiator_iqn;
|
||||||
|
/** Target address */
|
||||||
|
struct sockaddr_tcpip target;
|
||||||
|
/** Target IQN */
|
||||||
|
const char *target_iqn;
|
||||||
|
/** Logical Unit Number (LUN) */
|
||||||
|
uint64_t lun;
|
||||||
|
/** Username */
|
||||||
|
const char *username;
|
||||||
|
/** Password */
|
||||||
|
const char *password;
|
||||||
|
|
||||||
|
/** TCP application for this session */
|
||||||
|
struct tcp_application tcp;
|
||||||
/** Session status
|
/** Session status
|
||||||
*
|
*
|
||||||
* This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
|
* This is the bitwise-OR of zero or more ISCSI_STATUS_XXX
|
||||||
* constants.
|
* constants.
|
||||||
*/
|
*/
|
||||||
int status;
|
int status;
|
||||||
/** Asynchronous operation for the current iSCSI operation */
|
|
||||||
struct async_operation aop;
|
|
||||||
/** Retry count
|
/** Retry count
|
||||||
*
|
*
|
||||||
* Number of times that the connection has been retried.
|
* Number of times that the connection has been retried.
|
||||||
* Reset upon a successful connection.
|
* Reset upon a successful connection.
|
||||||
*/
|
*/
|
||||||
int retry_count;
|
int retry_count;
|
||||||
|
|
||||||
/** Initiator IQN */
|
|
||||||
const char *initiator_iqn;
|
|
||||||
/** Target address
|
|
||||||
*
|
|
||||||
* Kept separate from the TCP connection structure because we
|
|
||||||
* may need to handle login redirection.
|
|
||||||
*/
|
|
||||||
struct sockaddr_tcpip target;
|
|
||||||
/** Target IQN */
|
|
||||||
const char *target_iqn;
|
|
||||||
/** Logical Unit Number (LUN) */
|
|
||||||
uint64_t lun;
|
|
||||||
|
|
||||||
/** Username */
|
|
||||||
const char *username;
|
|
||||||
/** Password */
|
|
||||||
const char *password;
|
|
||||||
/** CHAP challenge/response */
|
/** CHAP challenge/response */
|
||||||
struct chap_challenge chap;
|
struct chap_challenge chap;
|
||||||
|
|
||||||
|
@ -597,6 +590,8 @@ struct iscsi_session {
|
||||||
* Set to NULL when command is complete.
|
* Set to NULL when command is complete.
|
||||||
*/
|
*/
|
||||||
struct scsi_command *command;
|
struct scsi_command *command;
|
||||||
|
/** Asynchronous operation for the current iSCSI operation */
|
||||||
|
struct async_operation aop;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** iSCSI session is currently in the security negotiation phase */
|
/** iSCSI session is currently in the security negotiation phase */
|
||||||
|
@ -632,15 +627,12 @@ struct iscsi_session {
|
||||||
/** Mask for all iSCSI "needs to send" flags */
|
/** Mask for all iSCSI "needs to send" flags */
|
||||||
#define ISCSI_STATUS_STRINGS_MASK 0xff00
|
#define ISCSI_STATUS_STRINGS_MASK 0xff00
|
||||||
|
|
||||||
/** iSCSI session is closing down */
|
|
||||||
#define ISCSI_STATUS_CLOSING 0x00010000
|
|
||||||
|
|
||||||
/** Maximum number of retries at connecting */
|
/** Maximum number of retries at connecting */
|
||||||
#define ISCSI_MAX_RETRIES 2
|
#define ISCSI_MAX_RETRIES 2
|
||||||
|
|
||||||
extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
extern struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||||
struct scsi_command *command );
|
struct scsi_command *command );
|
||||||
extern struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi );
|
extern void iscsi_shutdown ( struct iscsi_session *iscsi );
|
||||||
|
|
||||||
/** An iSCSI device */
|
/** An iSCSI device */
|
||||||
struct iscsi_device {
|
struct iscsi_device {
|
||||||
|
|
|
@ -9,13 +9,215 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include "latch.h"
|
||||||
#include <gpxe/list.h>
|
|
||||||
#include <gpxe/tcpip.h>
|
#include <gpxe/tcpip.h>
|
||||||
#include <gpxe/pkbuff.h>
|
|
||||||
#include <gpxe/retry.h>
|
|
||||||
|
|
||||||
struct tcp_connection;
|
/**
|
||||||
|
* A TCP header
|
||||||
|
*/
|
||||||
|
struct tcp_header {
|
||||||
|
uint16_t src; /* Source port */
|
||||||
|
uint16_t dest; /* Destination port */
|
||||||
|
uint32_t seq; /* Sequence number */
|
||||||
|
uint32_t ack; /* Acknowledgement number */
|
||||||
|
uint8_t hlen; /* Header length (4), Reserved (4) */
|
||||||
|
uint8_t flags; /* Reserved (2), Flags (6) */
|
||||||
|
uint16_t win; /* Advertised window */
|
||||||
|
uint16_t csum; /* Checksum */
|
||||||
|
uint16_t urg; /* Urgent pointer */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TCP flags
|
||||||
|
*/
|
||||||
|
#define TCP_CWR 0x80
|
||||||
|
#define TCP_ECE 0x40
|
||||||
|
#define TCP_URG 0x20
|
||||||
|
#define TCP_ACK 0x10
|
||||||
|
#define TCP_PSH 0x08
|
||||||
|
#define TCP_RST 0x04
|
||||||
|
#define TCP_SYN 0x02
|
||||||
|
#define TCP_FIN 0x01
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup tcpstates TCP states
|
||||||
|
*
|
||||||
|
* The TCP state is defined by a combination of the flags that are
|
||||||
|
* currently being sent in outgoing packets, the flags that have been
|
||||||
|
* sent and acknowledged by the peer, and the flags that have been
|
||||||
|
* received from the peer.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** TCP flags that are currently being sent in outgoing packets */
|
||||||
|
#define TCP_STATE_SENDING(flags) ( (flags) << 0 )
|
||||||
|
#define TCP_FLAGS_SENDING(state) ( ( (state) >> 0 ) & 0xff )
|
||||||
|
|
||||||
|
/** TCP flags that have been acknowledged by the peer
|
||||||
|
*
|
||||||
|
* Note that this applies only to SYN and FIN.
|
||||||
|
*/
|
||||||
|
#define TCP_STATE_ACKED(flags) ( (flags) << 8 )
|
||||||
|
#define TCP_FLAGS_ACKED(state) ( ( (state) >> 8 ) & 0x03 )
|
||||||
|
|
||||||
|
/** TCP flags that have been received from the peer
|
||||||
|
*
|
||||||
|
* Note that this applies only to SYN and FIN, and that once SYN has
|
||||||
|
* been received, we should always be sending ACK.
|
||||||
|
*/
|
||||||
|
#define TCP_STATE_RCVD(flags) ( (flags) << 12 )
|
||||||
|
#define TCP_FLAGS_RCVD(state) ( ( (state) >> 12 ) & 0x03 )
|
||||||
|
|
||||||
|
/** CLOSED
|
||||||
|
*
|
||||||
|
* The connection has not yet been used for anything.
|
||||||
|
*/
|
||||||
|
#define TCP_CLOSED TCP_RST
|
||||||
|
|
||||||
|
/** LISTEN
|
||||||
|
*
|
||||||
|
* Not currently used as a state; we have no support for listening
|
||||||
|
* connections. Given a unique value to avoid compiler warnings.
|
||||||
|
*/
|
||||||
|
#define TCP_LISTEN 0
|
||||||
|
|
||||||
|
/** SYN_SENT
|
||||||
|
*
|
||||||
|
* SYN has been sent, nothing has yet been received or acknowledged.
|
||||||
|
*/
|
||||||
|
#define TCP_SYN_SENT ( TCP_STATE_SENDING ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** SYN_RCVD
|
||||||
|
*
|
||||||
|
* SYN has been sent but not acknowledged, SYN has been received.
|
||||||
|
*/
|
||||||
|
#define TCP_SYN_RCVD ( TCP_STATE_SENDING ( TCP_SYN | TCP_ACK ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** ESTABLISHED
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received.
|
||||||
|
*/
|
||||||
|
#define TCP_ESTABLISHED ( TCP_STATE_SENDING ( TCP_ACK ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** FIN_WAIT_1
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
||||||
|
* been sent but not acknowledged, FIN has not been received.
|
||||||
|
*
|
||||||
|
* RFC 793 shows that we can enter FIN_WAIT_1 without have had SYN
|
||||||
|
* acknowledged, i.e. if the application closes the connection after
|
||||||
|
* sending and receiving SYN, but before having had SYN acknowledged.
|
||||||
|
* However, we have to *pretend* that SYN has been acknowledged
|
||||||
|
* anyway, otherwise we end up sending SYN and FIN in the same
|
||||||
|
* sequence number slot. Therefore, when we transition from SYN_RCVD
|
||||||
|
* to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
|
||||||
|
* and increment our sequence number.
|
||||||
|
*/
|
||||||
|
#define TCP_FIN_WAIT_1 ( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** FIN_WAIT_2
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
||||||
|
* been sent and acknowledged, FIN ha not been received.
|
||||||
|
*/
|
||||||
|
#define TCP_FIN_WAIT_2 ( TCP_STATE_SENDING ( TCP_ACK ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** CLOSING / LAST_ACK
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
||||||
|
* been sent but not acknowledged, FIN has been received.
|
||||||
|
*
|
||||||
|
* This state actually encompasses both CLOSING and LAST_ACK; they are
|
||||||
|
* identical with the definition of state that we use. I don't
|
||||||
|
* *believe* that they need to be distinguished.
|
||||||
|
*/
|
||||||
|
#define TCP_CLOSING_OR_LAST_ACK \
|
||||||
|
( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
||||||
|
|
||||||
|
/** TIME_WAIT
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
||||||
|
* been sent and acknowledged, FIN has been received.
|
||||||
|
*/
|
||||||
|
#define TCP_TIME_WAIT ( TCP_STATE_SENDING ( TCP_ACK ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
||||||
|
|
||||||
|
/** CLOSE_WAIT
|
||||||
|
*
|
||||||
|
* SYN has been sent and acknowledged, SYN has been received, FIN has
|
||||||
|
* been received.
|
||||||
|
*/
|
||||||
|
#define TCP_CLOSE_WAIT ( TCP_STATE_SENDING ( TCP_ACK ) | \
|
||||||
|
TCP_STATE_ACKED ( TCP_SYN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
|
||||||
|
|
||||||
|
/** Can send data in current state
|
||||||
|
*
|
||||||
|
* We can send data if and only if we have had our SYN acked and we
|
||||||
|
* have not yet sent our FIN.
|
||||||
|
*/
|
||||||
|
#define TCP_CAN_SEND_DATA(state) \
|
||||||
|
( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) | \
|
||||||
|
TCP_STATE_SENDING ( TCP_FIN ) ) ) \
|
||||||
|
== TCP_STATE_ACKED ( TCP_SYN ) )
|
||||||
|
|
||||||
|
/** Have closed gracefully
|
||||||
|
*
|
||||||
|
* We have closed gracefully if we have both received a FIN and had
|
||||||
|
* our own FIN acked.
|
||||||
|
*/
|
||||||
|
#define TCP_CLOSED_GRACEFULLY(state) \
|
||||||
|
( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) | \
|
||||||
|
TCP_STATE_RCVD ( TCP_FIN ) ) ) \
|
||||||
|
== ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/** Mask for TCP header length field */
|
||||||
|
#define TCP_MASK_HLEN 0xf0
|
||||||
|
|
||||||
|
/** Smallest port number on which a TCP connection can listen */
|
||||||
|
#define TCP_MIN_PORT 1
|
||||||
|
|
||||||
|
/* Some PKB constants */
|
||||||
|
#define MAX_HDR_LEN 100
|
||||||
|
#define MAX_PKB_LEN 1500
|
||||||
|
#define MIN_PKB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advertised TCP window size
|
||||||
|
*
|
||||||
|
* Our TCP window is actually limited by the amount of space available
|
||||||
|
* for RX packets in the NIC's RX ring; we tend to populate the rings
|
||||||
|
* with far fewer descriptors than a typical driver. Since we have no
|
||||||
|
* way of knowing how much of this RX ring space will be available for
|
||||||
|
* received TCP packets (consider, for example, that they may all be
|
||||||
|
* consumed by a series of unrelated ARP requests between other
|
||||||
|
* machines on the network), it is actually not even theoretically
|
||||||
|
* possible for us to specify an accurate window size. We therefore
|
||||||
|
* guess an arbitrary number that is empirically as large as possible
|
||||||
|
* while avoiding retransmissions due to dropped packets.
|
||||||
|
*/
|
||||||
|
#define TCP_WINDOW_SIZE 2048
|
||||||
|
|
||||||
|
/** TCP maximum segment lifetime
|
||||||
|
*
|
||||||
|
* Currently set to 2 minutes, as per RFC 793.
|
||||||
|
*/
|
||||||
|
#define TCP_MSL ( 2 * 60 * TICKS_PER_SEC )
|
||||||
|
|
||||||
|
struct tcp_application;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TCP operations
|
* TCP operations
|
||||||
|
@ -25,7 +227,7 @@ struct tcp_operations {
|
||||||
/*
|
/*
|
||||||
* Connection closed
|
* Connection closed
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v status Error code, if any
|
* @v status Error code, if any
|
||||||
*
|
*
|
||||||
* This is called when the connection is closed for any
|
* This is called when the connection is closed for any
|
||||||
|
@ -33,42 +235,41 @@ struct tcp_operations {
|
||||||
* contains the negative error number, if the closure is due
|
* contains the negative error number, if the closure is due
|
||||||
* to an error.
|
* to an error.
|
||||||
*
|
*
|
||||||
* Note that acked() and newdata() may be called after
|
* When closed() is called, the application no longer has a
|
||||||
* closed(), if the packet containing the FIN also
|
* valid TCP connection. Note that connected() may not have
|
||||||
* acknowledged data or contained new data. Note also that
|
* been called before closed(), if the close is due to an
|
||||||
* connected() may not have been called before closed(), if
|
* error during connection setup.
|
||||||
* the close is due to an error.
|
|
||||||
*/
|
*/
|
||||||
void ( * closed ) ( struct tcp_connection *conn, int status );
|
void ( * closed ) ( struct tcp_application *app, int status );
|
||||||
/**
|
/**
|
||||||
* Connection established (SYNACK received)
|
* Connection established
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
*/
|
*/
|
||||||
void ( * connected ) ( struct tcp_connection *conn );
|
void ( * connected ) ( struct tcp_application *app );
|
||||||
/**
|
/**
|
||||||
* Data acknowledged
|
* Data acknowledged
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v len Length of acknowledged data
|
* @v len Length of acknowledged data
|
||||||
*
|
*
|
||||||
* @c len is guaranteed to not exceed the outstanding amount
|
* @c len is guaranteed to not exceed the outstanding amount
|
||||||
* of unacknowledged data.
|
* of unacknowledged data.
|
||||||
*/
|
*/
|
||||||
void ( * acked ) ( struct tcp_connection *conn, size_t len );
|
void ( * acked ) ( struct tcp_application *app, size_t len );
|
||||||
/**
|
/**
|
||||||
* New data received
|
* New data received
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v data Data
|
* @v data Data
|
||||||
* @v len Length of data
|
* @v len Length of data
|
||||||
*/
|
*/
|
||||||
void ( * newdata ) ( struct tcp_connection *conn,
|
void ( * newdata ) ( struct tcp_application *app,
|
||||||
void *data, size_t len );
|
void *data, size_t len );
|
||||||
/**
|
/**
|
||||||
* Transmit data
|
* Transmit data
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v buf Temporary data buffer
|
* @v buf Temporary data buffer
|
||||||
* @v len Length of temporary data buffer
|
* @v len Length of temporary data buffer
|
||||||
*
|
*
|
||||||
|
@ -86,137 +287,36 @@ struct tcp_operations {
|
||||||
* the buffer is not compulsory; the application may call
|
* the buffer is not compulsory; the application may call
|
||||||
* tcp_send() on any block of data.
|
* tcp_send() on any block of data.
|
||||||
*/
|
*/
|
||||||
void ( * senddata ) ( struct tcp_connection *conn, void *buf,
|
void ( * senddata ) ( struct tcp_application *app, void *buf,
|
||||||
size_t len );
|
size_t len );
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_UIP
|
struct tcp_connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A TCP connection
|
* A TCP application
|
||||||
*
|
*
|
||||||
|
* This data structure represents an application with a TCP connection.
|
||||||
*/
|
*/
|
||||||
struct tcp_connection {
|
struct tcp_application {
|
||||||
/** Address of the remote end of the connection */
|
/** TCP connection data
|
||||||
struct sockaddr_in sin;
|
*
|
||||||
/** Operations table for this connection */
|
* 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;
|
struct tcp_operations *tcp_op;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void tcp_connect ( struct tcp_connection *conn );
|
extern int tcp_connect ( struct tcp_application *app,
|
||||||
extern void tcp_send ( struct tcp_connection *conn, const void *data,
|
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 );
|
size_t len );
|
||||||
extern void tcp_kick ( struct tcp_connection *conn );
|
|
||||||
extern void tcp_close ( struct tcp_connection *conn );
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define TCP_NOMSG ""
|
|
||||||
#define TCP_NOMSG_LEN 0
|
|
||||||
|
|
||||||
/* Smallest port number on which a TCP connection can listen */
|
|
||||||
#define TCP_MIN_PORT 1
|
|
||||||
|
|
||||||
/* Some PKB constants */
|
|
||||||
#define MAX_HDR_LEN 100
|
|
||||||
#define MAX_PKB_LEN 1500
|
|
||||||
#define MIN_PKB_LEN MAX_HDR_LEN + 100 /* To account for padding by LL */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP states
|
|
||||||
*/
|
|
||||||
#define TCP_CLOSED 0
|
|
||||||
#define TCP_LISTEN 1
|
|
||||||
#define TCP_SYN_SENT 2
|
|
||||||
#define TCP_SYN_RCVD 3
|
|
||||||
#define TCP_ESTABLISHED 4
|
|
||||||
#define TCP_FIN_WAIT_1 5
|
|
||||||
#define TCP_FIN_WAIT_2 6
|
|
||||||
#define TCP_CLOSING 7
|
|
||||||
#define TCP_TIME_WAIT 8
|
|
||||||
#define TCP_CLOSE_WAIT 9
|
|
||||||
#define TCP_LAST_ACK 10
|
|
||||||
|
|
||||||
#define TCP_INVALID 11
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A TCP connection
|
|
||||||
*/
|
|
||||||
struct tcp_connection {
|
|
||||||
struct sockaddr_tcpip peer; /* Remote socket address */
|
|
||||||
uint16_t local_port; /* Local port, in network byte order */
|
|
||||||
int tcp_state; /* TCP state */
|
|
||||||
int tcp_lstate; /* Last TCP state */
|
|
||||||
uint32_t snd_una; /* Lowest unacked byte on snd stream */
|
|
||||||
uint32_t snd_win; /* Offered by remote end */
|
|
||||||
uint32_t rcv_nxt; /* Next expected byte on rcv stream */
|
|
||||||
uint32_t rcv_win; /* Advertised to receiver */
|
|
||||||
uint8_t tcp_flags; /* TCP header flags */
|
|
||||||
struct list_head list; /* List of TCP connections */
|
|
||||||
struct pk_buff *tx_pkb; /* Transmit packet buffer */
|
|
||||||
struct retry_timer timer; /* Retransmission timer */
|
|
||||||
struct tcp_operations *tcp_op; /* Operations table for connection */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Retry timer values */
|
|
||||||
#define MAX_RETRANSMITS 3
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection closed status codes
|
|
||||||
*/
|
|
||||||
#define CONN_SNDCLOSE 0
|
|
||||||
#define CONN_RESTART 1
|
|
||||||
#define CONN_TIMEOUT 2
|
|
||||||
#define CONN_RCVCLOSE 3
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A TCP header
|
|
||||||
*/
|
|
||||||
struct tcp_header {
|
|
||||||
uint16_t src; /* Source port */
|
|
||||||
uint16_t dest; /* Destination port */
|
|
||||||
uint32_t seq; /* Sequence number */
|
|
||||||
uint32_t ack; /* Acknowledgement number */
|
|
||||||
uint8_t hlen; /* Header length (4), Reserved (4) */
|
|
||||||
uint8_t flags; /* Reserved (2), Flags (6) */
|
|
||||||
uint16_t win; /* Advertised window */
|
|
||||||
uint16_t csum; /* Checksum */
|
|
||||||
uint16_t urg; /* Urgent pointer */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP masks
|
|
||||||
*/
|
|
||||||
#define TCP_MASK_HLEN 0xf0
|
|
||||||
#define TCP_MASK_FLAGS 0x3f
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TCP flags
|
|
||||||
*/
|
|
||||||
#define TCP_URG 0x20
|
|
||||||
#define TCP_ACK 0x10
|
|
||||||
#define TCP_PSH 0x08
|
|
||||||
#define TCP_RST 0x04
|
|
||||||
#define TCP_SYN 0x02
|
|
||||||
#define TCP_FIN 0x01
|
|
||||||
|
|
||||||
extern struct tcpip_protocol tcp_protocol;
|
extern struct tcpip_protocol tcp_protocol;
|
||||||
|
|
||||||
static inline int tcp_closed ( struct tcp_connection *conn ) {
|
|
||||||
return ( conn->tcp_state == TCP_CLOSED );
|
|
||||||
}
|
|
||||||
|
|
||||||
extern void tcp_init_conn ( struct tcp_connection *conn );
|
|
||||||
extern int tcp_connect ( struct tcp_connection *conn );
|
|
||||||
extern int tcp_connectto ( struct tcp_connection *conn,
|
|
||||||
struct sockaddr_tcpip *peer );
|
|
||||||
extern int tcp_listen ( struct tcp_connection *conn, uint16_t port );
|
|
||||||
extern int tcp_senddata ( struct tcp_connection *conn );
|
|
||||||
extern int tcp_close ( struct tcp_connection *conn );
|
|
||||||
|
|
||||||
extern int tcp_send ( struct tcp_connection *conn, const void *data,
|
|
||||||
size_t len );
|
|
||||||
|
|
||||||
#endif /* USE_UIP */
|
|
||||||
|
|
||||||
#endif /* _GPXE_TCP_H */
|
#endif /* _GPXE_TCP_H */
|
||||||
|
|
1596
src/net/tcp.c
1596
src/net/tcp.c
File diff suppressed because it is too large
Load Diff
|
@ -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
|
* @ret ftp FTP request
|
||||||
*/
|
*/
|
||||||
static inline struct ftp_request * tcp_to_ftp ( struct tcp_connection *conn ) {
|
static inline struct ftp_request * tcp_to_ftp ( struct tcp_application *app ) {
|
||||||
return container_of ( conn, struct ftp_request, tcp );
|
return container_of ( app, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark FTP operation as complete
|
* Mark FTP operation as complete
|
||||||
*
|
*
|
||||||
* @v ftp FTP request
|
* @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
|
* @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 ) {
|
static void ftp_reply ( struct ftp_request *ftp ) {
|
||||||
char status_major = ftp->status_text[0];
|
char status_major = ftp->status_text[0];
|
||||||
|
@ -147,21 +129,31 @@ static void ftp_reply ( struct ftp_request *ftp ) {
|
||||||
* fatal error.
|
* fatal error.
|
||||||
*/
|
*/
|
||||||
if ( ! ( ( status_major == '2' ) ||
|
if ( ! ( ( status_major == '2' ) ||
|
||||||
( ( status_major == '3' ) && ( ftp->state == FTP_USER ) ) ) )
|
( ( status_major == '3' ) && ( ftp->state == FTP_USER ) ) ) ){
|
||||||
goto err;
|
/* Flag protocol error and close connections */
|
||||||
|
ftp_done ( ftp, -EPROTO );
|
||||||
|
}
|
||||||
|
|
||||||
/* Open passive connection when we get "PASV" response */
|
/* Open passive connection when we get "PASV" response */
|
||||||
if ( ftp->state == FTP_PASV ) {
|
if ( ftp->state == FTP_PASV ) {
|
||||||
char *ptr = ftp->passive_text;
|
char *ptr = ftp->passive_text;
|
||||||
struct sockaddr_in *sin =
|
union {
|
||||||
( struct sockaddr_in * ) &ftp->tcp_data.peer;
|
struct sockaddr_in sin;
|
||||||
|
struct sockaddr_tcpip st;
|
||||||
|
} sa;
|
||||||
|
int rc;
|
||||||
|
|
||||||
sin->sin_family = AF_INET;
|
sa.sin.sin_family = AF_INET;
|
||||||
ftp_parse_value ( &ptr, ( uint8_t * ) &sin->sin_addr,
|
ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_addr,
|
||||||
sizeof ( sin->sin_addr ) );
|
sizeof ( sa.sin.sin_addr ) );
|
||||||
ftp_parse_value ( &ptr, ( uint8_t * ) &sin->sin_port,
|
ftp_parse_value ( &ptr, ( uint8_t * ) &sa.sin.sin_port,
|
||||||
sizeof ( sin->sin_port ) );
|
sizeof ( sa.sin.sin_port ) );
|
||||||
tcp_connect ( &ftp->tcp_data );
|
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 */
|
/* Move to next state */
|
||||||
|
@ -176,26 +168,21 @@ static void ftp_reply ( struct ftp_request *ftp ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
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
|
* Handle new data arriving on FTP control channel
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v data New data
|
* @v data New data
|
||||||
* @v len Length of new data
|
* @v len Length of new data
|
||||||
*
|
*
|
||||||
* Data is collected until a complete line is received, at which point
|
* Data is collected until a complete line is received, at which point
|
||||||
* its information is passed to ftp_reply().
|
* 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 ) {
|
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;
|
char *recvbuf = ftp->recvbuf;
|
||||||
size_t recvsize = ftp->recvsize;
|
size_t recvsize = ftp->recvsize;
|
||||||
char c;
|
char c;
|
||||||
|
@ -242,10 +229,10 @@ static void ftp_newdata ( struct tcp_connection *conn,
|
||||||
/**
|
/**
|
||||||
* Handle acknowledgement of data sent on FTP control channel
|
* 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 ) {
|
static void ftp_acked ( struct tcp_application *app, size_t len ) {
|
||||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||||
|
|
||||||
/* Mark off ACKed portion of the currently-transmitted data */
|
/* Mark off ACKed portion of the currently-transmitted data */
|
||||||
ftp->already_sent += len;
|
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
|
* Construct data to send on FTP control channel
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v buf Temporary data buffer
|
* @v buf Temporary data buffer
|
||||||
* @v len Length of 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 ) {
|
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;
|
const struct ftp_string *string;
|
||||||
|
|
||||||
/* Send the as-yet-unACKed portion of the string for the
|
/* 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];
|
string = &ftp_strings[ftp->state];
|
||||||
len = snprintf ( buf, len, string->format,
|
len = snprintf ( buf, len, string->format,
|
||||||
ftp_string_data ( ftp, string->data_offset ) );
|
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
|
* 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
|
* When the control channel is closed, the data channel must also be
|
||||||
* closed, if it is currently open.
|
* closed, if it is currently open.
|
||||||
*/
|
*/
|
||||||
static void ftp_closed ( struct tcp_connection *conn, int status ) {
|
static void ftp_closed ( struct tcp_application *app, int status ) {
|
||||||
struct ftp_request *ftp = tcp_to_ftp ( conn );
|
struct ftp_request *ftp = tcp_to_ftp ( app );
|
||||||
|
|
||||||
DBG ( "FTP %p control connection closed (status %d)\n", ftp, status );
|
DBG ( "FTP %p control connection closed (status %d)\n", ftp, status );
|
||||||
|
|
||||||
/* Close data channel and record status */
|
/* Complete FTP operation */
|
||||||
ftp_set_status ( ftp, status );
|
ftp_done ( 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** FTP control channel operations */
|
/** 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
|
* @ret ftp FTP request
|
||||||
*/
|
*/
|
||||||
static inline struct ftp_request *
|
static inline struct ftp_request *
|
||||||
tcp_to_ftp_data ( struct tcp_connection *conn ) {
|
tcp_to_ftp_data ( struct tcp_application *app ) {
|
||||||
return container_of ( conn, struct ftp_request, tcp_data );
|
return container_of ( app, struct ftp_request, tcp_data );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle data channel being closed
|
* 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
|
* When the data channel is closed, the control channel should be left
|
||||||
* alone; the server will send a completion message via the control
|
* 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.
|
* 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 ) {
|
static void ftp_data_closed ( struct tcp_application *app, int status ) {
|
||||||
struct ftp_request *ftp = tcp_to_ftp_data ( conn );
|
struct ftp_request *ftp = tcp_to_ftp_data ( app );
|
||||||
|
|
||||||
DBG ( "FTP %p data connection closed (status %d)\n", ftp, status );
|
DBG ( "FTP %p data connection closed (status %d)\n", ftp, status );
|
||||||
|
|
||||||
/* If there was an error, close control channel and record status */
|
/* If there was an error, close control channel and record status */
|
||||||
if ( status ) {
|
if ( status )
|
||||||
ftp_set_status ( ftp, status );
|
ftp_done ( 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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle new data arriving on the FTP data channel
|
* Handle new data arriving on the FTP data channel
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v data New data
|
* @v data New data
|
||||||
* @v len Length of new data
|
* @v len Length of new data
|
||||||
*
|
*
|
||||||
* Data is handed off to the callback registered in the FTP request.
|
* 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 ) {
|
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 );
|
ftp->callback ( data, len );
|
||||||
}
|
}
|
||||||
|
@ -384,6 +356,7 @@ static struct tcp_operations ftp_data_tcp_operations = {
|
||||||
* @v ftp FTP request
|
* @v ftp FTP request
|
||||||
*/
|
*/
|
||||||
struct async_operation * ftp_get ( struct ftp_request *ftp ) {
|
struct async_operation * ftp_get ( struct ftp_request *ftp ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
DBG ( "FTP %p fetching %s\n", ftp, ftp->filename );
|
DBG ( "FTP %p fetching %s\n", ftp, ftp->filename );
|
||||||
|
|
||||||
|
@ -391,7 +364,8 @@ struct async_operation * ftp_get ( struct ftp_request *ftp ) {
|
||||||
ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
|
ftp->tcp_data.tcp_op = &ftp_data_tcp_operations;
|
||||||
ftp->recvbuf = ftp->status_text;
|
ftp->recvbuf = ftp->status_text;
|
||||||
ftp->recvsize = sizeof ( ftp->status_text ) - 1;
|
ftp->recvsize = sizeof ( ftp->status_text ) - 1;
|
||||||
ftp_clear_status ( ftp );
|
if ( ( rc = tcp_connect ( &ftp->tcp, &ftp->server, 0 ) ) != 0 )
|
||||||
tcp_connect ( &ftp->tcp );
|
ftp_done ( ftp, rc );
|
||||||
|
|
||||||
return &ftp->aop;
|
return &ftp->aop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
* "Hello world" TCP protocol
|
* "Hello world" TCP protocol
|
||||||
*
|
*
|
||||||
* This file implements a trivial TCP-based protocol. It connects to
|
* This file implements a trivial TCP-based protocol. It connects to
|
||||||
* the server specified in hello_request::tcp and transmits a single
|
* the server specified in hello_request::server and transmits a
|
||||||
* message (hello_request::message). Any data received from the
|
* single message (hello_request::message). Any data received from
|
||||||
* server will be passed to the callback function,
|
* the server will be passed to the callback function,
|
||||||
* hello_request::callback(), and once the connection has been closed,
|
* hello_request::callback(), and once the connection has been closed,
|
||||||
* the asynchronous operation associated with the request will be
|
* the asynchronous operation associated with the request will be
|
||||||
* marked as complete.
|
* marked as complete.
|
||||||
|
@ -26,13 +26,13 @@
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* struct hello_request hello = {
|
* struct hello_request hello = {
|
||||||
|
* .server = {
|
||||||
|
* ...
|
||||||
|
* },
|
||||||
* .message = "hello world!",
|
* .message = "hello world!",
|
||||||
* .callback = my_callback,
|
* .callback = my_callback,
|
||||||
* };
|
* };
|
||||||
*
|
*
|
||||||
* hello.sin.sin_addr.s_addr = ... server IP address ...
|
|
||||||
* hello.sin.sin_port = ... server port ...
|
|
||||||
*
|
|
||||||
* rc = async_wait ( say_hello ( &hello ) );
|
* rc = async_wait ( say_hello ( &hello ) );
|
||||||
*
|
*
|
||||||
* @endcode
|
* @endcode
|
||||||
|
@ -44,25 +44,25 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline struct hello_request *
|
static inline struct hello_request *
|
||||||
tcp_to_hello ( struct tcp_connection *conn ) {
|
tcp_to_hello ( struct tcp_application *app ) {
|
||||||
return container_of ( conn, struct hello_request, tcp );
|
return container_of ( app, struct hello_request, tcp );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hello_closed ( struct tcp_connection *conn, int status ) {
|
static void hello_closed ( struct tcp_application *app, int status ) {
|
||||||
struct hello_request *hello = tcp_to_hello ( conn );
|
struct hello_request *hello = tcp_to_hello ( app );
|
||||||
|
|
||||||
async_done ( &hello->aop, status );
|
async_done ( &hello->aop, status );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hello_connected ( struct tcp_connection *conn ) {
|
static void hello_connected ( struct tcp_application *app ) {
|
||||||
struct hello_request *hello = tcp_to_hello ( conn );
|
struct hello_request *hello = tcp_to_hello ( app );
|
||||||
|
|
||||||
hello->remaining = strlen ( hello->message );
|
hello->remaining = strlen ( hello->message );
|
||||||
hello->state = HELLO_SENDING_MESSAGE;
|
hello->state = HELLO_SENDING_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hello_acked ( struct tcp_connection *conn, size_t len ) {
|
static void hello_acked ( struct tcp_application *app, size_t len ) {
|
||||||
struct hello_request *hello = tcp_to_hello ( conn );
|
struct hello_request *hello = tcp_to_hello ( app );
|
||||||
|
|
||||||
hello->message += len;
|
hello->message += len;
|
||||||
hello->remaining -= 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 ) {
|
size_t len ) {
|
||||||
struct hello_request *hello = tcp_to_hello ( conn );
|
struct hello_request *hello = tcp_to_hello ( app );
|
||||||
|
|
||||||
hello->callback ( data, len );
|
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 ) {
|
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 = {
|
static struct tcp_operations hello_tcp_operations = {
|
||||||
|
@ -112,7 +112,11 @@ static struct tcp_operations hello_tcp_operations = {
|
||||||
* @v hello "Hello world" request
|
* @v hello "Hello world" request
|
||||||
*/
|
*/
|
||||||
struct async_operation * say_hello ( struct hello_request *hello ) {
|
struct async_operation * say_hello ( struct hello_request *hello ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
hello->tcp.tcp_op = &hello_tcp_operations;
|
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;
|
return &hello->aop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,28 +39,28 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline struct http_request *
|
static inline struct http_request *
|
||||||
tcp_to_http ( struct tcp_connection *conn ) {
|
tcp_to_http ( struct tcp_application *app ) {
|
||||||
return container_of ( conn, struct http_request, tcp );
|
return container_of ( app, struct http_request, tcp );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close an HTTP connection
|
* Close an HTTP connection
|
||||||
*
|
*
|
||||||
* @v conn a TCP Connection
|
* @v app a TCP Application
|
||||||
* @v status connection status at close
|
* @v status connection status at close
|
||||||
*/
|
*/
|
||||||
static void http_closed ( struct tcp_connection *conn, int status ) {
|
static void http_closed ( struct tcp_application *app, int status ) {
|
||||||
struct http_request *http = tcp_to_http ( conn );
|
struct http_request *http = tcp_to_http ( app );
|
||||||
async_done ( &http->aop, status );
|
async_done ( &http->aop, status );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback after a TCP connection is established
|
* 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 ) {
|
static void http_connected ( struct tcp_application *app ) {
|
||||||
struct http_request *http = tcp_to_http ( conn );
|
struct http_request *http = tcp_to_http ( app );
|
||||||
|
|
||||||
http->state = HTTP_REQUEST_FILE;
|
http->state = HTTP_REQUEST_FILE;
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,11 @@ static void http_connected ( struct tcp_connection *conn ) {
|
||||||
/**
|
/**
|
||||||
* Callback for when TCP data is acknowledged
|
* Callback for when TCP data is acknowledged
|
||||||
*
|
*
|
||||||
* @v conn a TCP Connection
|
* @v app a TCP Application
|
||||||
* @v len the length of data acked
|
* @v len the length of data acked
|
||||||
*/
|
*/
|
||||||
static void http_acked ( struct tcp_connection *conn, size_t len __attribute__ ((unused)) ) {
|
static void http_acked ( struct tcp_application *app, size_t len __attribute__ ((unused)) ) {
|
||||||
struct http_request *http = tcp_to_http ( conn );
|
struct http_request *http = tcp_to_http ( app );
|
||||||
|
|
||||||
// assume that the whole GET request was sent in on epacket
|
// 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:
|
case HTTP_RECV_FILE:
|
||||||
break;
|
break;
|
||||||
case HTTP_DONE:
|
case HTTP_DONE:
|
||||||
//tcp_close(conn);
|
//tcp_close(app);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -95,13 +95,13 @@ static void http_acked ( struct tcp_connection *conn, size_t len __attribute__ (
|
||||||
/**
|
/**
|
||||||
* Callback when new TCP data is recieved
|
* 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 data a pointer to the data recieved
|
||||||
* @v len length of data buffer
|
* @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 ) {
|
size_t len ) {
|
||||||
struct http_request *http = tcp_to_http ( conn );
|
struct http_request *http = tcp_to_http ( app );
|
||||||
char *content_length;
|
char *content_length;
|
||||||
char *start = data;
|
char *start = data;
|
||||||
char *rcp; int rc;
|
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);
|
//printf("File recv is %d\n", http->file_recv);
|
||||||
if ( http->file_recv == http->file_size ){
|
if ( http->file_recv == http->file_size ){
|
||||||
http->state = HTTP_DONE;
|
http->state = HTTP_DONE;
|
||||||
tcp_close(conn);
|
tcp_close(app);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HTTP_REQUEST_FILE:
|
case HTTP_REQUEST_FILE:
|
||||||
|
@ -155,10 +155,10 @@ static void http_newdata ( struct tcp_connection *conn, void *data,
|
||||||
/**
|
/**
|
||||||
* Callback for sending TCP 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 ) {
|
static void http_senddata ( struct tcp_application *app, void *buf, size_t len ) {
|
||||||
struct http_request *http = tcp_to_http ( conn );
|
struct http_request *http = tcp_to_http ( app );
|
||||||
|
|
||||||
switch ( http->state ){
|
switch ( http->state ){
|
||||||
case HTTP_REQUEST_FILE:
|
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);
|
printf("%s\n",(char *)buf);
|
||||||
// string is: GET <file> HTTP/1.0\r\n\r\n
|
// string is: GET <file> HTTP/1.0\r\n\r\n
|
||||||
|
|
||||||
tcp_send ( conn, buf, len);
|
tcp_send ( app, buf, len);
|
||||||
break;
|
break;
|
||||||
case HTTP_PARSE_HEADER:
|
case HTTP_PARSE_HEADER:
|
||||||
case HTTP_RECV_FILE:
|
case HTTP_RECV_FILE:
|
||||||
break;
|
break;
|
||||||
case HTTP_DONE:
|
case HTTP_DONE:
|
||||||
//tcp_close(conn)
|
//tcp_close(app)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -193,8 +193,12 @@ static struct tcp_operations http_tcp_operations = {
|
||||||
* @v http a HTTP request
|
* @v http a HTTP request
|
||||||
*/
|
*/
|
||||||
struct async_operation * get_http ( struct http_request *http ) {
|
struct async_operation * get_http ( struct http_request *http ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
http->tcp.tcp_op = &http_tcp_operations;
|
http->tcp.tcp_op = &http_tcp_operations;
|
||||||
http->state = HTTP_REQUEST_FILE;
|
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;
|
return &http->aop;
|
||||||
}
|
}
|
||||||
|
|
|
@ -720,11 +720,14 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
|
||||||
/* Check for login redirection */
|
/* Check for login redirection */
|
||||||
if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
|
if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
|
||||||
DBG ( "iSCSI %p redirecting to new server\n", iscsi );
|
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 );
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,8 +781,8 @@ static void iscsi_rx_login_response ( struct iscsi_session *iscsi, void *data,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline struct iscsi_session *
|
static inline struct iscsi_session *
|
||||||
tcp_to_iscsi ( struct tcp_connection *conn ) {
|
tcp_to_iscsi ( struct tcp_application *app ) {
|
||||||
return container_of ( conn, struct iscsi_session, tcp );
|
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
|
* Updates iscsi->tx_offset and, if applicable, transitions to the
|
||||||
* next TX state.
|
* next TX state.
|
||||||
*/
|
*/
|
||||||
static void iscsi_acked ( struct tcp_connection *conn, size_t len ) {
|
static void iscsi_acked ( struct tcp_application *app, 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;
|
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
|
||||||
enum iscsi_tx_state next_state;
|
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
|
* 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 ) {
|
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;
|
struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
|
||||||
static const char pad[] = { '\0', '\0', '\0' };
|
static const char pad[] = { '\0', '\0', '\0' };
|
||||||
|
|
||||||
|
@ -927,7 +930,7 @@ static void iscsi_senddata ( struct tcp_connection *conn,
|
||||||
/* Nothing to send */
|
/* Nothing to send */
|
||||||
break;
|
break;
|
||||||
case ISCSI_TX_BHS:
|
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 ) );
|
( sizeof ( iscsi->tx_bhs ) - iscsi->tx_offset ) );
|
||||||
break;
|
break;
|
||||||
case ISCSI_TX_AHS:
|
case ISCSI_TX_AHS:
|
||||||
|
@ -938,7 +941,7 @@ static void iscsi_senddata ( struct tcp_connection *conn,
|
||||||
iscsi_tx_data ( iscsi, buf, len );
|
iscsi_tx_data ( iscsi, buf, len );
|
||||||
break;
|
break;
|
||||||
case ISCSI_TX_DATA_PADDING:
|
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 ) );
|
- iscsi->tx_offset ) );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1029,7 +1032,7 @@ static void iscsi_rx_bhs ( struct iscsi_session *iscsi, void *data,
|
||||||
/**
|
/**
|
||||||
* Receive new data
|
* Receive new data
|
||||||
*
|
*
|
||||||
* @v tcp TCP connection
|
* @v tcp TCP application
|
||||||
* @v data Received data
|
* @v data Received data
|
||||||
* @v len Length of 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
|
* always has a full copy of the BHS available, even for portions of
|
||||||
* the data in different packets to the BHS.
|
* 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 ) {
|
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;
|
struct iscsi_bhs_common *common = &iscsi->rx_bhs.common;
|
||||||
void ( *process ) ( struct iscsi_session *iscsi, void *data,
|
void ( *process ) ( struct iscsi_session *iscsi, void *data,
|
||||||
size_t len, size_t remaining );
|
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
|
* Handle TCP connection closure
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
* @v status Error code, if any
|
* @v status Error code, if any
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void iscsi_closed ( struct tcp_connection *conn, int status ) {
|
static void iscsi_closed ( struct tcp_application *app, int status ) {
|
||||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||||
int session_status = iscsi->status;
|
int rc;
|
||||||
|
|
||||||
/* Clear session status */
|
/* Clear session status */
|
||||||
iscsi->status = 0;
|
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 */
|
/* Retry connection if within the retry limit, otherwise fail */
|
||||||
if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
|
if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
|
||||||
DBG ( "iSCSI %p retrying connection\n", iscsi );
|
DBG ( "iSCSI %p retrying connection\n", iscsi );
|
||||||
/* Re-copy address to handle redirection */
|
if ( ( rc = tcp_connect ( app, &iscsi->target, 0 ) ) != 0 ) {
|
||||||
memset ( &iscsi->tcp, 0, sizeof ( iscsi->tcp ) );
|
DBG ( "iSCSI %p could not open TCP connection\n",
|
||||||
iscsi->tcp.tcp_op = &iscsi_tcp_operations;
|
iscsi );
|
||||||
memcpy ( &iscsi->tcp.peer, &iscsi->target,
|
iscsi_done ( iscsi, rc );
|
||||||
sizeof ( iscsi->tcp.peer ) );
|
}
|
||||||
tcp_connect ( conn );
|
|
||||||
} else {
|
} else {
|
||||||
printf ( "iSCSI %p retry count exceeded\n", iscsi );
|
printf ( "iSCSI %p retry count exceeded\n", iscsi );
|
||||||
iscsi_done ( iscsi, status );
|
iscsi_done ( iscsi, status );
|
||||||
|
@ -1139,11 +1132,11 @@ static void iscsi_closed ( struct tcp_connection *conn, int status ) {
|
||||||
/**
|
/**
|
||||||
* Handle TCP connection opening
|
* Handle TCP connection opening
|
||||||
*
|
*
|
||||||
* @v conn TCP connection
|
* @v app TCP application
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void iscsi_connected ( struct tcp_connection *conn ) {
|
static void iscsi_connected ( struct tcp_application *app ) {
|
||||||
struct iscsi_session *iscsi = tcp_to_iscsi ( conn );
|
struct iscsi_session *iscsi = tcp_to_iscsi ( app );
|
||||||
|
|
||||||
/* Set connected flag and reset retry count */
|
/* Set connected flag and reset retry count */
|
||||||
iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
|
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 async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||||
struct scsi_command *command ) {
|
struct scsi_command *command ) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
assert ( iscsi->command == NULL );
|
assert ( iscsi->command == NULL );
|
||||||
iscsi->command = command;
|
iscsi->command = command;
|
||||||
|
|
||||||
|
@ -1198,9 +1193,12 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||||
} else {
|
} else {
|
||||||
/* Session not open: initiate login */
|
/* Session not open: initiate login */
|
||||||
iscsi->tcp.tcp_op = &iscsi_tcp_operations;
|
iscsi->tcp.tcp_op = &iscsi_tcp_operations;
|
||||||
memcpy ( &iscsi->tcp.peer, &iscsi->target,
|
if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
|
||||||
sizeof ( iscsi->tcp.peer ) );
|
0 ) ) != 0 ) {
|
||||||
tcp_connect ( &iscsi->tcp );
|
DBG ( "iSCSI %p could not open TCP connection\n",
|
||||||
|
iscsi );
|
||||||
|
iscsi_done ( iscsi, rc );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &iscsi->aop;
|
return &iscsi->aop;
|
||||||
|
@ -1212,10 +1210,7 @@ struct async_operation * iscsi_issue ( struct iscsi_session *iscsi,
|
||||||
* @v iscsi iSCSI session
|
* @v iscsi iSCSI session
|
||||||
* @ret aop Asynchronous operation
|
* @ret aop Asynchronous operation
|
||||||
*/
|
*/
|
||||||
struct async_operation * iscsi_shutdown ( struct iscsi_session *iscsi ) {
|
void iscsi_shutdown ( struct iscsi_session *iscsi ) {
|
||||||
if ( iscsi->status ) {
|
iscsi->status = 0;
|
||||||
iscsi->status |= ISCSI_STATUS_CLOSING;
|
|
||||||
tcp_close ( &iscsi->tcp );
|
tcp_close ( &iscsi->tcp );
|
||||||
}
|
|
||||||
return &iscsi->aop;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ void test_ftp ( struct sockaddr_tcpip *server, const char *filename ) {
|
||||||
printf ( "FTP fetching %s\n", filename );
|
printf ( "FTP fetching %s\n", filename );
|
||||||
|
|
||||||
memset ( &ftp, 0, sizeof ( ftp ) );
|
memset ( &ftp, 0, sizeof ( ftp ) );
|
||||||
memcpy ( &ftp.tcp.peer, server, sizeof ( ftp.tcp.peer ) );
|
memcpy ( &ftp.server, server, sizeof ( ftp.server ) );
|
||||||
ftp.filename = filename;
|
ftp.filename = filename;
|
||||||
ftp.callback = test_ftp_callback;
|
ftp.callback = test_ftp_callback;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ void test_hello ( struct sockaddr_tcpip *server, const char *message ) {
|
||||||
inet_ntoa ( sin->sin_addr ), ntohs ( sin->sin_port ) );
|
inet_ntoa ( sin->sin_addr ), ntohs ( sin->sin_port ) );
|
||||||
|
|
||||||
memset ( &hello, 0, sizeof ( hello ) );
|
memset ( &hello, 0, sizeof ( hello ) );
|
||||||
memcpy ( &hello.tcp.peer, server, sizeof ( hello.tcp.peer ) );
|
memcpy ( &hello.server, server, sizeof ( hello.server ) );
|
||||||
hello.message = message;
|
hello.message = message;
|
||||||
hello.callback = test_hello_callback;
|
hello.callback = test_hello_callback;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ void test_http ( struct net_device *netdev, struct sockaddr_tcpip *server, const
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
memset ( &http, 0, sizeof ( http ) );
|
memset ( &http, 0, sizeof ( http ) );
|
||||||
memcpy ( &http.tcp.peer, server, sizeof ( http.tcp.peer ) );
|
memcpy ( &http.server, server, sizeof ( http.server ) );
|
||||||
http.filename = filename;
|
http.filename = filename;
|
||||||
http.callback = test_http_callback;
|
http.callback = test_http_callback;
|
||||||
|
|
||||||
|
|
Reference in New Issue