54,47 → 54,175 |
|
#include "socket_messages.h" |
|
/** Initial received packet queue size. |
*/ |
#define SOCKET_INITIAL_RECEIVED_SIZE 4 |
|
/** Maximum received packet queue size. |
*/ |
#define SOCKET_MAX_RECEIVED_SIZE 64 |
|
/** Initial waiting sockets queue size. |
*/ |
#define SOCKET_INITIAL_ACCEPTED_SIZE 1 |
|
/** Maximum waiting sockets queue size. |
*/ |
#define SOCKET_MAX_ACCEPTED_SIZE 64 |
|
/** Type definition of the socket specific data. |
* @see socket |
*/ |
typedef struct socket socket_t; |
|
/** Type definition of the socket specific data pointer. |
* @see socket |
*/ |
typedef socket_t * socket_ref; |
|
/** Socket specific data. |
*/ |
struct socket{ |
/** Socket identifier. |
*/ |
int socket_id; |
/** Parent module phone. |
*/ |
int phone; |
/** Parent module service. |
*/ |
services_t service; |
/** Underlying protocol header size. |
* Sending and receiving optimalization. |
*/ |
int header_size; |
/** Packet data fragment size. |
* Sending and receiving optimalization. |
*/ |
int data_fragment_size; |
/** Received packets queue. |
*/ |
dyn_fifo_t received; |
/** Received packets safety lock. |
*/ |
fibril_mutex_t receive_lock; |
/** Received packets signaling. |
*/ |
fibril_condvar_t receive_signal; |
/** Waiting sockets queue. |
*/ |
dyn_fifo_t accepted; |
/** Waiting sockets safety lock. |
*/ |
fibril_mutex_t accept_lock; |
/** Waiting sockets signaling. |
*/ |
fibril_condvar_t accept_signal; |
}; |
|
/** Sockets map. |
* Maps socket identifiers to the socket specific data. |
* @see int_map.h |
*/ |
INT_MAP_DECLARE( sockets, socket_t ); |
|
/** Socket client library global data. |
*/ |
static struct{ |
/** TCP module phone. |
*/ |
int tcp_phone; |
/** UDP module phone. |
*/ |
int udp_phone; |
/** Active sockets. |
*/ |
sockets_ref sockets; |
} socket_globals = { -1, -1, NULL }; |
|
INT_MAP_IMPLEMENT( sockets, socket_t ); |
|
/** Returns the TCP module phone. |
* Connects to the TCP module if necessary. |
* @returns The TCP module phone. |
*/ |
static int socket_get_tcp_phone(); |
|
/** Returns the UDP module phone. |
* Connects to the UDP module if necessary. |
* @returns The UDP module phone. |
*/ |
static int socket_get_tcp_phone(); |
|
/** Returns the active sockets. |
* @returns The active sockets. |
*/ |
static sockets_ref socket_get_sockets(); |
|
/** Default thread for new connections. |
* @param iid The initial message identifier. Input parameter. |
* @param icall The initial message call structure. Input parameter. |
*/ |
void socket_connection( ipc_callid_t iid, ipc_call_t * icall ); |
|
/** Sends message to the socket parent module with specified data. |
* @param socket_id Socket identifier. Input parameter. |
* @param message The action message. Input parameter. |
* @param arg2 The second message parameter. Input parameter. |
* @param data The data to be sent. Input parameter. |
* @param datalength The data length. Input parameter. |
* @returns EOK on success. |
* @returns ENOTSOCK if the socket is not found. |
* @returns EBADMEM if the data parameter is NULL. |
* @returns NO_DATA if the datalength parameter is zero (0). |
* @returns Other error codes as defined for the spcific message. |
*/ |
int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ); |
|
/** Initializes a new socket specific data. |
* @param socket The socket to be initialized. Input/output parameter. |
* @param socket_id The new socket identifier. Input parameter. |
* @param phone The parent module phone. Input parameter. |
* @param service The parent module service. Input parameter. |
*/ |
void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ); |
|
/** Clears and destroys the socket. |
* @param socket The socket to be destroyed. Input parameter. |
*/ |
void socket_destroy( socket_ref socket ); |
|
/** Receives data via the socket. |
* @param message The action message. Input parameter. |
* @param socket_id Socket identifier. Input parameter. |
* @param data The data buffer to be filled. Output parameter. |
* @param datalength The data length. Input parameter. |
* @param flags Various receive flags. Input parameter. |
* @param fromaddr The source address. May be NULL for connected sockets. Output parameter. |
* @param addrlen The address length. The maximum address length is read. The actual address length is set. Used only if fromaddr is not NULL. Input/output parameter. |
* @returns EOK on success. |
* @returns ENOTSOCK if the socket is not found. |
* @returns EBADMEM if the data parameter is NULL. |
* @returns NO_DATA if the datalength or addrlen parameter is zero (0). |
* @returns Other error codes as defined for the spcific message. |
*/ |
int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ); |
|
/** Sends data via the socket to the remote address. |
* Binds the socket to a free port if not already connected/bound. |
* @param message The action message. Input parameter. |
* @param socket_id Socket identifier. Input parameter. |
* @param data The data to be sent. Input parameter. |
* @param datalength The data length. Input parameter. |
* @param flags Various send flags. Input parameter. |
* @param toaddr The destination address. May be NULL for connected sockets. Input parameter. |
* @param addrlen The address length. Used only if toaddr is not NULL. Input parameter. |
* @returns EOK on success. |
* @returns ENOTSOCK if the socket is not found. |
* @returns EBADMEM if the data or toaddr parameter is NULL. |
* @returns NO_DATA if the datalength or the addrlen parameter is zero (0). |
* @returns Other error codes as defined for the NET_SOCKET_SENDTO message. |
*/ |
int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ); |
|
static int socket_get_tcp_phone(){ |
149,7 → 277,7 |
switch( IPC_GET_METHOD( call )){ |
case NET_SOCKET_RECEIVED: |
// find the socket |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
if( ! socket ){ |
ERROR_CODE = ENOTSOCK; |
break; |
156,7 → 284,7 |
} |
fibril_mutex_lock( & socket->receive_lock ); |
// push the number of received packet fragments |
if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( & call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
// signal the received packet |
fibril_condvar_signal( & socket->receive_signal ); |
} |
164,7 → 292,7 |
break; |
case NET_SOCKET_ACCEPTED: |
// find the socket |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
if( ! socket ){ |
ERROR_CODE = ENOTSOCK; |
break; |
175,7 → 303,7 |
ERROR_CODE = ENOMEM; |
break; |
} |
socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( & call ), socket->phone, socket->service ); |
socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( call ), socket->phone, socket->service ); |
ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ); |
if( ERROR_CODE < 0 ){ |
free( new_socket ); |
195,13 → 323,13 |
break; |
case NET_SOCKET_DATA_FRAGMENT_SIZE: |
// find the socket |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
if( ! socket ){ |
ERROR_CODE = ENOTSOCK; |
break; |
} |
// set the data fragment size |
socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( & call ); |
socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call ); |
ERROR_CODE = EOK; |
break; |
default: |
327,8 → 455,7 |
aid_t message_id; |
int result; |
|
if( ! cliaddr ) return EBADMEM; |
if( ! addrlen ) return NO_DATA; |
if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM; |
// find the socket |
socket = sockets_find( socket_get_sockets(), socket_id ); |
if( ! socket ) return ENOTSOCK; |
373,7 → 500,7 |
int accepted_id; |
|
// destroy all accepted sockets |
while(( accepted_id = dyn_fifo_pop( & socket->accepted ))){ |
while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){ |
socket_destroy( sockets_find( socket_get_sockets(), accepted_id )); |
} |
dyn_fifo_destroy( & socket->received ); |
454,7 → 581,7 |
|
if( ! data ) return EBADMEM; |
if( ! datalength ) return NO_DATA; |
if( fromaddr && (( ! addrlen ) || ( * addrlen < sizeof( struct sockaddr_in )))) return EINVAL; |
if( fromaddr && ( ! addrlen )) return EINVAL; |
// find the socket |
socket = sockets_find( socket_get_sockets(), socket_id ); |
if( ! socket ) return ENOTSOCK; |
500,9 → 627,9 |
// dequeue the received packet |
dyn_fifo_pop( & socket->received ); |
// return read data length |
result = SOCKET_GET_READ_DATA_LENGTH( & answer ); |
result = SOCKET_GET_READ_DATA_LENGTH( answer ); |
// set address length |
if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( & answer ); |
if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer ); |
} |
fibril_mutex_unlock( & socket->receive_lock ); |
return result; |