Subversion Repositories HelenOS

Rev

Rev 4603 | Rev 4701 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4603 Rev 4700
Line 32... Line 32...
32
 
32
 
33
/** @file
33
/** @file
34
 */
34
 */
35
 
35
 
36
#include <async.h>
36
#include <async.h>
-
 
37
#include <fibril_sync.h>
37
#include <malloc.h>
38
#include <malloc.h>
38
#include <stdio.h>
39
#include <stdio.h>
39
 
40
 
40
#include <ipc/ipc.h>
41
#include <ipc/ipc.h>
41
#include <ipc/services.h>
42
#include <ipc/services.h>
Line 64... Line 65...
64
#include "udp_header.h"
65
#include "udp_header.h"
65
#include "udp_module.h"
66
#include "udp_module.h"
66
 
67
 
67
#define MAX_UDP_FRAGMENT_SIZE   65535
68
#define MAX_UDP_FRAGMENT_SIZE   65535
68
 
69
 
-
 
70
#define UDP_FREE_PORTS_START    1025
-
 
71
#define UDP_FREE_PORTS_END      65535
-
 
72
 
69
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver );
73
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver );
70
int udp_process_packet( packet_t packet );
74
int udp_process_packet( packet_t packet );
71
int process_client_messages( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
75
int process_client_messages( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
72
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags );
76
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags );
73
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags );
77
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags );
Line 80... Line 84...
80
/** Initializes the module.
84
/** Initializes the module.
81
 */
85
 */
82
int udp_initialize( async_client_conn_t client_connection ){
86
int udp_initialize( async_client_conn_t client_connection ){
83
    ERROR_DECLARE;
87
    ERROR_DECLARE;
84
 
88
 
-
 
89
    fibril_rwlock_initialize( & udp_globals.lock );
-
 
90
    fibril_rwlock_write_lock( & udp_globals.lock );
85
    udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg );
91
    udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg );
86
    if( udp_globals.ip_phone < 0 ){
92
    if( udp_globals.ip_phone < 0 ){
87
        return udp_globals.ip_phone;
93
        return udp_globals.ip_phone;
88
    }
94
    }
89
    ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
95
    ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
90
    ERROR_PROPAGATE( socket_ports_initialize( & udp_globals.sockets ));
96
    ERROR_PROPAGATE( socket_ports_initialize( & udp_globals.sockets ));
91
    udp_globals.prefix += sizeof( udp_header_t );
97
    udp_globals.prefix += sizeof( udp_header_t );
92
    udp_globals.content -= sizeof( udp_header_t );
98
    udp_globals.content -= sizeof( udp_header_t );
-
 
99
    udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
-
 
100
    fibril_rwlock_write_unlock( & udp_globals.lock );
93
    return EOK;
101
    return EOK;
94
}
102
}
95
 
103
 
96
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver ){
104
int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver ){
97
    ERROR_DECLARE;
105
    ERROR_DECLARE;
Line 181... Line 189...
181
    packet_t    packet;
189
    packet_t    packet;
182
 
190
 
183
    * answer_count = 0;
191
    * answer_count = 0;
184
    switch( IPC_GET_METHOD( * call )){
192
    switch( IPC_GET_METHOD( * call )){
185
        case NET_TL_RECEIVED:
193
        case NET_TL_RECEIVED:
-
 
194
            fibril_rwlock_read_lock( & udp_globals.lock );
186
            ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )));
195
            if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
187
            return udp_received_msg( IPC_GET_DEVICE( call ), packet, 0 );
196
                ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, 0 );
-
 
197
            }
-
 
198
            fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
199
            return ERROR_CODE;
188
        case IPC_M_CONNECT_TO_ME:
200
        case IPC_M_CONNECT_TO_ME:
189
            return process_client_messages( callid, call, answer, answer_count );
201
            return process_client_messages( callid, call, answer, answer_count );
190
    }
202
    }
191
    return ENOTSUP;
203
    return ENOTSUP;
192
}
204
}
Line 198... Line 210...
198
    bool                    keep_on_going = true;
210
    bool                    keep_on_going = true;
199
    socket_cores_t          local_sockets;
211
    socket_cores_t          local_sockets;
200
    int                     app_phone = IPC_GET_PHONE( call );
212
    int                     app_phone = IPC_GET_PHONE( call );
201
    void *                  addr;
213
    void *                  addr;
202
    size_t                  addrlen;
214
    size_t                  addrlen;
-
 
215
    fibril_rwlock_t         lock;
203
 
216
 
204
    /*
217
    /*
205
     * Accept the connection
218
     * Accept the connection
206
     *  - Answer the first IPC_M_CONNECT_ME_TO call.
219
     *  - Answer the first IPC_M_CONNECT_ME_TO call.
207
     */
220
     */
208
    ipc_answer_0( callid, EOK );
221
    ipc_answer_0( callid, EOK );
209
 
222
 
210
    socket_cores_initialize( & local_sockets );
223
    socket_cores_initialize( & local_sockets );
-
 
224
    fibril_rwlock_initialize( & lock );
211
 
225
 
212
    while( keep_on_going ){
226
    while( keep_on_going ){
213
        // refresh data
227
        // refresh data
214
        * answer_count = 0;
228
        * answer_count = 0;
215
        IPC_SET_RETVAL( * answer, 0 );
229
        IPC_SET_RETVAL( * answer, 0 );
Line 228... Line 242...
228
            case IPC_M_PHONE_HUNGUP:
242
            case IPC_M_PHONE_HUNGUP:
229
                keep_on_going = false;
243
                keep_on_going = false;
230
                res = EOK;
244
                res = EOK;
231
                break;
245
                break;
232
            case NET_SOCKET:
246
            case NET_SOCKET:
-
 
247
                fibril_rwlock_write_lock( & lock );
233
                res = socket_create( & local_sockets, app_phone, SOCKET_SET_SOCKET_ID( answer ));
248
                res = socket_create( & local_sockets, app_phone, SOCKET_SET_SOCKET_ID( answer ));
-
 
249
                fibril_rwlock_write_unlock( & lock );
234
                * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
250
                * SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
235
                * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
251
                * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
236
                * answer_count = 3;
252
                * answer_count = 3;
237
                break;
253
                break;
238
            case NET_SOCKET_BIND:
254
            case NET_SOCKET_BIND:
239
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
255
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
240
                    res = ERROR_CODE;
256
                    res = ERROR_CODE;
241
                    break;
257
                    break;
242
                }
258
                }
-
 
259
                fibril_rwlock_write_lock( & lock );
-
 
260
                fibril_rwlock_write_lock( & udp_globals.lock );
243
                res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen );
261
                res = socket_bind( & local_sockets, & udp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port );
-
 
262
                fibril_rwlock_write_unlock( & udp_globals.lock );
-
 
263
                fibril_rwlock_write_unlock( & lock );
244
                free( addr );
264
                free( addr );
245
                break;
265
                break;
246
            case NET_SOCKET_SENDTO:
266
            case NET_SOCKET_SENDTO:
247
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
267
                if( ERROR_OCCURRED( socket_read_data( & addr, & addrlen ))){
248
                    res = ERROR_CODE;
268
                    res = ERROR_CODE;
249
                    break;
269
                    break;
250
                }
270
                }
-
 
271
                fibril_rwlock_read_lock( & lock );
-
 
272
                fibril_rwlock_read_lock( & udp_globals.lock );
251
                res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
273
                res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_FLAGS( call ));
-
 
274
                fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
275
                fibril_rwlock_read_unlock( & lock );
252
                free( addr );
276
                free( addr );
253
                break;
277
                break;
254
            case NET_SOCKET_RECVFROM:
278
            case NET_SOCKET_RECVFROM:
-
 
279
                fibril_rwlock_read_lock( & lock );
-
 
280
                fibril_rwlock_read_lock( & udp_globals.lock );
255
                res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ));
281
                res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ));
-
 
282
                fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
283
                fibril_rwlock_read_unlock( & lock );
256
                if( res > 0 ){
284
                if( res > 0 ){
257
                    * SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
285
                    * SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
258
                    * SOCKET_SET_ADDRESS_LENGTH( answer ) = sizeof( struct sockaddr_in );
286
                    * SOCKET_SET_ADDRESS_LENGTH( answer ) = sizeof( struct sockaddr_in );
259
                    * answer_count = 2;
287
                    * answer_count = 2;
260
                    res = EOK;
288
                    res = EOK;
261
                }
289
                }
262
                break;
290
                break;
263
            case NET_SOCKET_CLOSE:
291
            case NET_SOCKET_CLOSE:
-
 
292
                fibril_rwlock_write_lock( & lock );
-
 
293
                fibril_rwlock_write_lock( & udp_globals.lock );
264
                res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets );
294
                res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets );
-
 
295
                fibril_rwlock_write_unlock( & udp_globals.lock );
-
 
296
                fibril_rwlock_write_unlock( & lock );
265
                break;
297
                break;
266
            case NET_SOCKET_GETSOCKOPT:
298
            case NET_SOCKET_GETSOCKOPT:
267
            case NET_SOCKET_SETSOCKOPT:
299
            case NET_SOCKET_SETSOCKOPT:
268
            default:
300
            default:
269
                res = ENOTSUP;
301
                res = ENOTSUP;
Line 313... Line 345...
313
            if( addrlen != sizeof( struct sockaddr_in )) return EINVAL;
345
            if( addrlen != sizeof( struct sockaddr_in )) return EINVAL;
314
            address_in = ( struct sockaddr_in * ) addr;
346
            address_in = ( struct sockaddr_in * ) addr;
315
            socket = socket_cores_find( local_sockets, socket_id );
347
            socket = socket_cores_find( local_sockets, socket_id );
316
            if( ! socket ) return ENOTSOCK;
348
            if( ! socket ) return ENOTSOCK;
317
 
349
 
-
 
350
            // bind the socket to a random free port if not bound
-
 
351
            if( socket->port <= 0 ){
-
 
352
                // try to find a free port
-
 
353
                fibril_rwlock_read_unlock( & udp_globals.lock );
-
 
354
                fibril_rwlock_write_lock( & udp_globals.lock );
-
 
355
                ERROR_PROPAGATE( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ));
-
 
356
                fibril_rwlock_write_unlock( & udp_globals.lock );
-
 
357
                fibril_rwlock_read_lock( & udp_globals.lock );
-
 
358
                // set the next port as the search starting port number
-
 
359
                udp_globals.last_used_port = socket->port;
-
 
360
            }
318
            // TODO do not ask all the time
361
            // TODO do not ask all the time
319
            ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
362
            ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix ));
320
 
363
 
321
            // read the first packet fragment
364
            // read the first packet fragment
322
            total_length = socket_read_packet_data( & packet, sizeof( udp_header_t ), address_in );
365
            total_length = socket_read_packet_data( & packet, sizeof( udp_header_t ), address_in );