Rev 4603 | Rev 4708 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4603 | Rev 4701 | ||
|---|---|---|---|
| Line 52... | Line 52... | ||
| 52 | #include "../structures/dynamic_fifo.h" |
52 | #include "../structures/dynamic_fifo.h" |
| 53 | #include "../structures/int_map.h" |
53 | #include "../structures/int_map.h" |
| 54 | 54 | ||
| 55 | #include "socket_messages.h" |
55 | #include "socket_messages.h" |
| 56 | 56 | ||
| - | 57 | /** Initial received packet queue size. |
|
| - | 58 | */ |
|
| 57 | #define SOCKET_INITIAL_RECEIVED_SIZE 4 |
59 | #define SOCKET_INITIAL_RECEIVED_SIZE 4 |
| - | 60 | ||
| - | 61 | /** Maximum received packet queue size. |
|
| - | 62 | */ |
|
| 58 | #define SOCKET_MAX_RECEIVED_SIZE 64 |
63 | #define SOCKET_MAX_RECEIVED_SIZE 64 |
| 59 | 64 | ||
| - | 65 | /** Initial waiting sockets queue size. |
|
| - | 66 | */ |
|
| 60 | #define SOCKET_INITIAL_ACCEPTED_SIZE 1 |
67 | #define SOCKET_INITIAL_ACCEPTED_SIZE 1 |
| - | 68 | ||
| - | 69 | /** Maximum waiting sockets queue size. |
|
| - | 70 | */ |
|
| 61 | #define SOCKET_MAX_ACCEPTED_SIZE 64 |
71 | #define SOCKET_MAX_ACCEPTED_SIZE 64 |
| 62 | 72 | ||
| - | 73 | /** Type definition of the socket specific data. |
|
| - | 74 | * @see socket |
|
| - | 75 | */ |
|
| 63 | typedef struct socket socket_t; |
76 | typedef struct socket socket_t; |
| 64 | typedef socket_t * socket_ref; |
- | |
| 65 | 77 | ||
| - | 78 | /** Type definition of the socket specific data pointer. |
|
| - | 79 | * @see socket |
|
| - | 80 | */ |
|
| - | 81 | typedef socket_t * socket_ref; |
|
| - | 82 | ||
| - | 83 | /** Socket specific data. |
|
| - | 84 | */ |
|
| 66 | struct socket{ |
85 | struct socket{ |
| - | 86 | /** Socket identifier. |
|
| - | 87 | */ |
|
| 67 | int socket_id; |
88 | int socket_id; |
| - | 89 | /** Parent module phone. |
|
| - | 90 | */ |
|
| 68 | int phone; |
91 | int phone; |
| - | 92 | /** Parent module service. |
|
| - | 93 | */ |
|
| 69 | services_t service; |
94 | services_t service; |
| - | 95 | /** Underlying protocol header size. |
|
| - | 96 | * Sending and receiving optimalization. |
|
| - | 97 | */ |
|
| 70 | int header_size; |
98 | int header_size; |
| - | 99 | /** Packet data fragment size. |
|
| - | 100 | * Sending and receiving optimalization. |
|
| - | 101 | */ |
|
| 71 | int data_fragment_size; |
102 | int data_fragment_size; |
| - | 103 | /** Received packets queue. |
|
| - | 104 | */ |
|
| 72 | dyn_fifo_t received; |
105 | dyn_fifo_t received; |
| - | 106 | /** Received packets safety lock. |
|
| - | 107 | */ |
|
| 73 | fibril_mutex_t receive_lock; |
108 | fibril_mutex_t receive_lock; |
| - | 109 | /** Received packets signaling. |
|
| - | 110 | */ |
|
| 74 | fibril_condvar_t receive_signal; |
111 | fibril_condvar_t receive_signal; |
| - | 112 | /** Waiting sockets queue. |
|
| - | 113 | */ |
|
| 75 | dyn_fifo_t accepted; |
114 | dyn_fifo_t accepted; |
| - | 115 | /** Waiting sockets safety lock. |
|
| - | 116 | */ |
|
| 76 | fibril_mutex_t accept_lock; |
117 | fibril_mutex_t accept_lock; |
| - | 118 | /** Waiting sockets signaling. |
|
| - | 119 | */ |
|
| 77 | fibril_condvar_t accept_signal; |
120 | fibril_condvar_t accept_signal; |
| 78 | }; |
121 | }; |
| 79 | 122 | ||
| - | 123 | /** Sockets map. |
|
| - | 124 | * Maps socket identifiers to the socket specific data. |
|
| - | 125 | * @see int_map.h |
|
| - | 126 | */ |
|
| 80 | INT_MAP_DECLARE( sockets, socket_t ); |
127 | INT_MAP_DECLARE( sockets, socket_t ); |
| 81 | 128 | ||
| - | 129 | /** Socket client library global data. |
|
| - | 130 | */ |
|
| 82 | static struct{ |
131 | static struct{ |
| - | 132 | /** TCP module phone. |
|
| - | 133 | */ |
|
| 83 | int tcp_phone; |
134 | int tcp_phone; |
| - | 135 | /** UDP module phone. |
|
| - | 136 | */ |
|
| 84 | int udp_phone; |
137 | int udp_phone; |
| - | 138 | /** Active sockets. |
|
| - | 139 | */ |
|
| 85 | sockets_ref sockets; |
140 | sockets_ref sockets; |
| 86 | } socket_globals = { -1, -1, NULL }; |
141 | } socket_globals = { -1, -1, NULL }; |
| 87 | 142 | ||
| 88 | INT_MAP_IMPLEMENT( sockets, socket_t ); |
143 | INT_MAP_IMPLEMENT( sockets, socket_t ); |
| 89 | 144 | ||
| - | 145 | /** Returns the TCP module phone. |
|
| - | 146 | * Connects to the TCP module if necessary. |
|
| - | 147 | * @returns The TCP module phone. |
|
| - | 148 | */ |
|
| 90 | static int socket_get_tcp_phone(); |
149 | static int socket_get_tcp_phone(); |
| - | 150 | ||
| - | 151 | /** Returns the UDP module phone. |
|
| - | 152 | * Connects to the UDP module if necessary. |
|
| - | 153 | * @returns The UDP module phone. |
|
| - | 154 | */ |
|
| 91 | static int socket_get_tcp_phone(); |
155 | static int socket_get_tcp_phone(); |
| - | 156 | ||
| - | 157 | /** Returns the active sockets. |
|
| - | 158 | * @returns The active sockets. |
|
| - | 159 | */ |
|
| 92 | static sockets_ref socket_get_sockets(); |
160 | static sockets_ref socket_get_sockets(); |
| - | 161 | ||
| - | 162 | /** Default thread for new connections. |
|
| - | 163 | * @param iid The initial message identifier. Input parameter. |
|
| - | 164 | * @param icall The initial message call structure. Input parameter. |
|
| - | 165 | */ |
|
| 93 | void socket_connection( ipc_callid_t iid, ipc_call_t * icall ); |
166 | void socket_connection( ipc_callid_t iid, ipc_call_t * icall ); |
| - | 167 | ||
| - | 168 | /** Sends message to the socket parent module with specified data. |
|
| - | 169 | * @param socket_id Socket identifier. Input parameter. |
|
| - | 170 | * @param message The action message. Input parameter. |
|
| - | 171 | * @param arg2 The second message parameter. Input parameter. |
|
| - | 172 | * @param data The data to be sent. Input parameter. |
|
| - | 173 | * @param datalength The data length. Input parameter. |
|
| - | 174 | * @returns EOK on success. |
|
| - | 175 | * @returns ENOTSOCK if the socket is not found. |
|
| - | 176 | * @returns EBADMEM if the data parameter is NULL. |
|
| - | 177 | * @returns NO_DATA if the datalength parameter is zero (0). |
|
| - | 178 | * @returns Other error codes as defined for the spcific message. |
|
| - | 179 | */ |
|
| 94 | int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ); |
180 | int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ); |
| - | 181 | ||
| - | 182 | /** Initializes a new socket specific data. |
|
| - | 183 | * @param socket The socket to be initialized. Input/output parameter. |
|
| - | 184 | * @param socket_id The new socket identifier. Input parameter. |
|
| - | 185 | * @param phone The parent module phone. Input parameter. |
|
| - | 186 | * @param service The parent module service. Input parameter. |
|
| - | 187 | */ |
|
| 95 | void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ); |
188 | void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ); |
| - | 189 | ||
| - | 190 | /** Clears and destroys the socket. |
|
| - | 191 | * @param socket The socket to be destroyed. Input parameter. |
|
| - | 192 | */ |
|
| 96 | void socket_destroy( socket_ref socket ); |
193 | void socket_destroy( socket_ref socket ); |
| - | 194 | ||
| - | 195 | /** Receives data via the socket. |
|
| - | 196 | * @param message The action message. Input parameter. |
|
| - | 197 | * @param socket_id Socket identifier. Input parameter. |
|
| - | 198 | * @param data The data buffer to be filled. Output parameter. |
|
| - | 199 | * @param datalength The data length. Input parameter. |
|
| - | 200 | * @param flags Various receive flags. Input parameter. |
|
| - | 201 | * @param fromaddr The source address. May be NULL for connected sockets. Output parameter. |
|
| - | 202 | * @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. |
|
| - | 203 | * @returns EOK on success. |
|
| - | 204 | * @returns ENOTSOCK if the socket is not found. |
|
| - | 205 | * @returns EBADMEM if the data parameter is NULL. |
|
| - | 206 | * @returns NO_DATA if the datalength or addrlen parameter is zero (0). |
|
| - | 207 | * @returns Other error codes as defined for the spcific message. |
|
| - | 208 | */ |
|
| 97 | int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ); |
209 | int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ); |
| - | 210 | ||
| - | 211 | /** Sends data via the socket to the remote address. |
|
| - | 212 | * Binds the socket to a free port if not already connected/bound. |
|
| - | 213 | * @param message The action message. Input parameter. |
|
| - | 214 | * @param socket_id Socket identifier. Input parameter. |
|
| - | 215 | * @param data The data to be sent. Input parameter. |
|
| - | 216 | * @param datalength The data length. Input parameter. |
|
| - | 217 | * @param flags Various send flags. Input parameter. |
|
| - | 218 | * @param toaddr The destination address. May be NULL for connected sockets. Input parameter. |
|
| - | 219 | * @param addrlen The address length. Used only if toaddr is not NULL. Input parameter. |
|
| - | 220 | * @returns EOK on success. |
|
| - | 221 | * @returns ENOTSOCK if the socket is not found. |
|
| - | 222 | * @returns EBADMEM if the data or toaddr parameter is NULL. |
|
| - | 223 | * @returns NO_DATA if the datalength or the addrlen parameter is zero (0). |
|
| - | 224 | * @returns Other error codes as defined for the NET_SOCKET_SENDTO message. |
|
| - | 225 | */ |
|
| 98 | int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ); |
226 | int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ); |
| 99 | 227 | ||
| 100 | static int socket_get_tcp_phone(){ |
228 | static int socket_get_tcp_phone(){ |
| 101 | if( socket_globals.tcp_phone < 0 ){ |
229 | if( socket_globals.tcp_phone < 0 ){ |
| 102 | socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection ); |
230 | socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection ); |
| Line 147... | Line 275... | ||
| 147 | 275 | ||
| 148 | callid = async_get_call( & call ); |
276 | callid = async_get_call( & call ); |
| 149 | switch( IPC_GET_METHOD( call )){ |
277 | switch( IPC_GET_METHOD( call )){ |
| 150 | case NET_SOCKET_RECEIVED: |
278 | case NET_SOCKET_RECEIVED: |
| 151 | // find the socket |
279 | // find the socket |
| 152 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
280 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 153 | if( ! socket ){ |
281 | if( ! socket ){ |
| 154 | ERROR_CODE = ENOTSOCK; |
282 | ERROR_CODE = ENOTSOCK; |
| 155 | break; |
283 | break; |
| 156 | } |
284 | } |
| 157 | fibril_mutex_lock( & socket->receive_lock ); |
285 | fibril_mutex_lock( & socket->receive_lock ); |
| 158 | // push the number of received packet fragments |
286 | // push the number of received packet fragments |
| 159 | if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( & call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
287 | if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
| 160 | // signal the received packet |
288 | // signal the received packet |
| 161 | fibril_condvar_signal( & socket->receive_signal ); |
289 | fibril_condvar_signal( & socket->receive_signal ); |
| 162 | } |
290 | } |
| 163 | fibril_mutex_unlock( & socket->receive_lock ); |
291 | fibril_mutex_unlock( & socket->receive_lock ); |
| 164 | break; |
292 | break; |
| 165 | case NET_SOCKET_ACCEPTED: |
293 | case NET_SOCKET_ACCEPTED: |
| 166 | // find the socket |
294 | // find the socket |
| 167 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
295 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 168 | if( ! socket ){ |
296 | if( ! socket ){ |
| 169 | ERROR_CODE = ENOTSOCK; |
297 | ERROR_CODE = ENOTSOCK; |
| 170 | break; |
298 | break; |
| 171 | } |
299 | } |
| 172 | // create a new scoket |
300 | // create a new scoket |
| 173 | new_socket = ( socket_ref ) malloc( sizeof( socket_t )); |
301 | new_socket = ( socket_ref ) malloc( sizeof( socket_t )); |
| 174 | if( ! new_socket ){ |
302 | if( ! new_socket ){ |
| 175 | ERROR_CODE = ENOMEM; |
303 | ERROR_CODE = ENOMEM; |
| 176 | break; |
304 | break; |
| 177 | } |
305 | } |
| 178 | socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( & call ), socket->phone, socket->service ); |
306 | socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( call ), socket->phone, socket->service ); |
| 179 | ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ); |
307 | ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ); |
| 180 | if( ERROR_CODE < 0 ){ |
308 | if( ERROR_CODE < 0 ){ |
| 181 | free( new_socket ); |
309 | free( new_socket ); |
| 182 | }else{ |
310 | }else{ |
| 183 | // push the new socket identifier |
311 | // push the new socket identifier |
| Line 193... | Line 321... | ||
| 193 | ERROR_CODE = EOK; |
321 | ERROR_CODE = EOK; |
| 194 | } |
322 | } |
| 195 | break; |
323 | break; |
| 196 | case NET_SOCKET_DATA_FRAGMENT_SIZE: |
324 | case NET_SOCKET_DATA_FRAGMENT_SIZE: |
| 197 | // find the socket |
325 | // find the socket |
| 198 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call )); |
326 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 199 | if( ! socket ){ |
327 | if( ! socket ){ |
| 200 | ERROR_CODE = ENOTSOCK; |
328 | ERROR_CODE = ENOTSOCK; |
| 201 | break; |
329 | break; |
| 202 | } |
330 | } |
| 203 | // set the data fragment size |
331 | // set the data fragment size |
| 204 | socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( & call ); |
332 | socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call ); |
| 205 | ERROR_CODE = EOK; |
333 | ERROR_CODE = EOK; |
| 206 | break; |
334 | break; |
| 207 | default: |
335 | default: |
| 208 | ERROR_CODE = ENOTSUP; |
336 | ERROR_CODE = ENOTSUP; |
| 209 | } |
337 | } |
| Line 325... | Line 453... | ||
| 325 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
453 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
| 326 | socket_ref socket; |
454 | socket_ref socket; |
| 327 | aid_t message_id; |
455 | aid_t message_id; |
| 328 | int result; |
456 | int result; |
| 329 | 457 | ||
| 330 | if( ! cliaddr ) return EBADMEM; |
458 | if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM; |
| 331 | if( ! addrlen ) return NO_DATA; |
- | |
| 332 | // find the socket |
459 | // find the socket |
| 333 | socket = sockets_find( socket_get_sockets(), socket_id ); |
460 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 334 | if( ! socket ) return ENOTSOCK; |
461 | if( ! socket ) return ENOTSOCK; |
| 335 | fibril_mutex_lock( & socket->accept_lock ); |
462 | fibril_mutex_lock( & socket->accept_lock ); |
| 336 | // wait for an accepted socket |
463 | // wait for an accepted socket |
| Line 371... | Line 498... | ||
| 371 | 498 | ||
| 372 | void socket_destroy( socket_ref socket ){ |
499 | void socket_destroy( socket_ref socket ){ |
| 373 | int accepted_id; |
500 | int accepted_id; |
| 374 | 501 | ||
| 375 | // destroy all accepted sockets |
502 | // destroy all accepted sockets |
| 376 | while(( accepted_id = dyn_fifo_pop( & socket->accepted ))){ |
503 | while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){ |
| 377 | socket_destroy( sockets_find( socket_get_sockets(), accepted_id )); |
504 | socket_destroy( sockets_find( socket_get_sockets(), accepted_id )); |
| 378 | } |
505 | } |
| 379 | dyn_fifo_destroy( & socket->received ); |
506 | dyn_fifo_destroy( & socket->received ); |
| 380 | dyn_fifo_destroy( & socket->accepted ); |
507 | dyn_fifo_destroy( & socket->accepted ); |
| 381 | sockets_exclude( socket_get_sockets(), socket->socket_id ); |
508 | sockets_exclude( socket_get_sockets(), socket->socket_id ); |
| Line 452... | Line 579... | ||
| 452 | int index; |
579 | int index; |
| 453 | ipc_call_t answer; |
580 | ipc_call_t answer; |
| 454 | 581 | ||
| 455 | if( ! data ) return EBADMEM; |
582 | if( ! data ) return EBADMEM; |
| 456 | if( ! datalength ) return NO_DATA; |
583 | if( ! datalength ) return NO_DATA; |
| 457 | if( fromaddr && (( ! addrlen ) || ( * addrlen < sizeof( struct sockaddr_in )))) return EINVAL; |
584 | if( fromaddr && ( ! addrlen )) return EINVAL; |
| 458 | // find the socket |
585 | // find the socket |
| 459 | socket = sockets_find( socket_get_sockets(), socket_id ); |
586 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 460 | if( ! socket ) return ENOTSOCK; |
587 | if( ! socket ) return ENOTSOCK; |
| 461 | fibril_mutex_lock( & socket->receive_lock ); |
588 | fibril_mutex_lock( & socket->receive_lock ); |
| 462 | // wait for a received packet |
589 | // wait for a received packet |
| Line 498... | Line 625... | ||
| 498 | // if successful |
625 | // if successful |
| 499 | if( result == EOK ){ |
626 | if( result == EOK ){ |
| 500 | // dequeue the received packet |
627 | // dequeue the received packet |
| 501 | dyn_fifo_pop( & socket->received ); |
628 | dyn_fifo_pop( & socket->received ); |
| 502 | // return read data length |
629 | // return read data length |
| 503 | result = SOCKET_GET_READ_DATA_LENGTH( & answer ); |
630 | result = SOCKET_GET_READ_DATA_LENGTH( answer ); |
| 504 | // set address length |
631 | // set address length |
| 505 | if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( & answer ); |
632 | if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer ); |
| 506 | } |
633 | } |
| 507 | fibril_mutex_unlock( & socket->receive_lock ); |
634 | fibril_mutex_unlock( & socket->receive_lock ); |
| 508 | return result; |
635 | return result; |
| 509 | } |
636 | } |
| 510 | 637 | ||