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 |