Subversion Repositories HelenOS

Rev

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

Rev 4582 Rev 4589
Line 47... Line 47...
47
 
47
 
48
#include "../include/in.h"
48
#include "../include/in.h"
49
#include "../include/socket.h"
49
#include "../include/socket.h"
50
#include "../include/socket_errno.h"
50
#include "../include/socket_errno.h"
51
 
51
 
-
 
52
#include "../structures/dynamic_fifo.h"
52
#include "../structures/int_map.h"
53
#include "../structures/int_map.h"
53
 
54
 
54
#include "socket_messages.h"
55
#include "socket_messages.h"
55
 
56
 
-
 
57
#define SOCKET_INITIAL_RECEIVED_SIZE    4
-
 
58
#define SOCKET_MAX_RECEIVED_SIZE        64
-
 
59
 
-
 
60
#define SOCKET_INITIAL_ACCEPTED_SIZE    1
-
 
61
#define SOCKET_MAX_ACCEPTED_SIZE        64
-
 
62
 
56
typedef struct socket   socket_t;
63
typedef struct socket   socket_t;
57
typedef socket_t *      socket_ref;
64
typedef socket_t *      socket_ref;
58
 
65
 
59
struct socket{
66
struct socket{
60
    int                 socket_id;
67
    int                 socket_id;
61
    int                 phone;
68
    int                 phone;
62
    services_t          service;
69
    services_t          service;
63
    int                 max_content;
70
    int                 header_size;
-
 
71
    int                 data_fragment_size;
64
    int                 received;
72
    dyn_fifo_t          received;
65
    fibril_mutex_t      receive_lock;
73
    fibril_mutex_t      receive_lock;
66
    fibril_condvar_t    receive_signal;
74
    fibril_condvar_t    receive_signal;
67
    int                 accepted;
75
    dyn_fifo_t          accepted;
68
    fibril_mutex_t      accept_lock;
76
    fibril_mutex_t      accept_lock;
69
    fibril_condvar_t    accept_signal;
77
    fibril_condvar_t    accept_signal;
70
};
78
};
71
 
79
 
72
INT_MAP_DECLARE( sockets, socket_t );
80
INT_MAP_DECLARE( sockets, socket_t );
Line 83... Line 91...
83
static int  socket_get_tcp_phone();
91
static int  socket_get_tcp_phone();
84
static sockets_ref  socket_get_sockets();
92
static sockets_ref  socket_get_sockets();
85
void    socket_connection( ipc_callid_t iid, ipc_call_t * icall );
93
void    socket_connection( ipc_callid_t iid, ipc_call_t * icall );
86
int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength );
94
int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength );
87
void    socket_initialize( socket_ref socket, int socket_id, int phone, services_t service );
95
void    socket_initialize( socket_ref socket, int socket_id, int phone, services_t service );
-
 
96
void    socket_destroy( socket_ref socket );
-
 
97
int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen );
-
 
98
int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen );
88
 
99
 
89
static int socket_get_tcp_phone(){
100
static int socket_get_tcp_phone(){
90
    if( socket_globals.tcp_phone < 0 ){
101
    if( socket_globals.tcp_phone < 0 ){
91
        socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection );
102
        socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection );
92
    }
103
    }
Line 114... Line 125...
114
 
125
 
115
void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ){
126
void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ){
116
    socket->socket_id = socket_id;
127
    socket->socket_id = socket_id;
117
    socket->phone = phone;
128
    socket->phone = phone;
118
    socket->service = service;
129
    socket->service = service;
119
    socket->received = 0;
130
    dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE );
120
    socket->accepted = 0;
131
    dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE );
121
    fibril_mutex_initialize( & socket->receive_lock );
132
    fibril_mutex_initialize( & socket->receive_lock );
122
    fibril_condvar_initialize( & socket->receive_signal );
133
    fibril_condvar_initialize( & socket->receive_signal );
123
    fibril_mutex_initialize( & socket->accept_lock );
134
    fibril_mutex_initialize( & socket->accept_lock );
124
    fibril_condvar_initialize( & socket->accept_signal );
135
    fibril_condvar_initialize( & socket->accept_signal );
125
}
136
}
Line 135... Line 146...
135
    while( true ){
146
    while( true ){
136
 
147
 
137
        callid = async_get_call( & call );
148
        callid = async_get_call( & call );
138
        switch( IPC_GET_METHOD( call )){
149
        switch( IPC_GET_METHOD( call )){
139
            case NET_SOCKET_RECEIVED:
150
            case NET_SOCKET_RECEIVED:
-
 
151
                // find the socket
140
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
152
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
141
                if( ! socket ){
153
                if( ! socket ){
142
                    ERROR_CODE = ENOTSOCK;
154
                    ERROR_CODE = ENOTSOCK;
143
                    break;
155
                    break;
144
                }
156
                }
145
                fibril_mutex_lock( & socket->receive_lock );
157
                fibril_mutex_lock( & socket->receive_lock );
-
 
158
                // 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 ))){
146
                ++ socket->received;
160
                    // signal the received packet
147
                fibril_condvar_signal( & socket->receive_signal );
161
                    fibril_condvar_signal( & socket->receive_signal );
-
 
162
                }
148
                fibril_mutex_unlock( & socket->receive_lock );
163
                fibril_mutex_unlock( & socket->receive_lock );
149
                ERROR_CODE = EOK;
-
 
150
                break;
164
                break;
151
            case NET_SOCKET_ACCEPTED:
165
            case NET_SOCKET_ACCEPTED:
-
 
166
                // find the socket
152
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
167
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
153
                if( ! socket ){
168
                if( ! socket ){
154
                    ERROR_CODE = ENOTSOCK;
169
                    ERROR_CODE = ENOTSOCK;
155
                    break;
170
                    break;
156
                }
171
                }
157
                fibril_mutex_lock( & socket->accept_lock );
172
                // create a new scoket
158
                new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
173
                new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
159
                if( ! new_socket ){
174
                if( ! new_socket ){
160
                    ERROR_CODE = ENOMEM;
175
                    ERROR_CODE = ENOMEM;
161
                    break;
176
                    break;
162
                }
177
                }
163
                socket_initialize( new_socket, SOCKET_GET_NEW_SOCKET_ID( & call ), socket->phone, socket->service );
178
                socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( & call ), socket->phone, socket->service );
164
                if( ERROR_OCCURRED( sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ))){
179
                ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
-
 
180
                if( ERROR_CODE < 0 ){
-
 
181
                    free( new_socket );
-
 
182
                }else{
-
 
183
                    // push the new socket identifier
-
 
184
                    fibril_mutex_lock( & socket->accept_lock );
-
 
185
                    if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, new_socket->socket_id, SOCKET_MAX_ACCEPTED_SIZE ))){
-
 
186
                        sockets_exclude( socket_get_sockets(), new_socket->socket_id );
-
 
187
                        free( new_socket );
165
                    break;
188
                    }else{
-
 
189
                        // signal the accepted socket
-
 
190
                        fibril_condvar_signal( & socket->accept_signal );
-
 
191
                    }
-
 
192
                    fibril_mutex_unlock( & socket->accept_lock );
-
 
193
                    ERROR_CODE = EOK;
166
                }
194
                }
167
                ++ socket->accepted;
-
 
168
                fibril_condvar_signal( & socket->accept_signal );
-
 
169
                fibril_mutex_unlock( & socket->accept_lock );
-
 
170
                break;
195
                break;
171
/*          case NET_SOCKET_MTU:
196
            case NET_SOCKET_DATA_FRAGMENT_SIZE:
-
 
197
                // find the socket
172
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
198
                socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( & call ));
173
                if( ! socket ){
199
                if( ! socket ){
174
                    ERROR_CODE = ENOTSOCK;
200
                    ERROR_CODE = ENOTSOCK;
175
                    break;
201
                    break;
176
                }
202
                }
177
                socket->mtu =
203
                // set the data fragment size
-
 
204
                socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( & call );
178
                ERROR_CODE = EOK;
205
                ERROR_CODE = EOK;
179
                break;
206
                break;
180
*/          default:
207
            default:
181
                ERROR_CODE = ENOTSUP;
208
                ERROR_CODE = ENOTSUP;
182
        }
209
        }
183
        ipc_answer_0( callid, ERROR_CODE );
210
        ipc_answer_0( callid, ERROR_CODE );
184
    }
211
    }
185
}
212
}
186
 
213
 
187
int socket( int domain, int type, int protocol ){
214
int socket( int domain, int type, int protocol ){
-
 
215
    ERROR_DECLARE;
-
 
216
 
188
    socket_ref  socket;
217
    socket_ref  socket;
189
    int         phone;
218
    int         phone;
190
    int         socket_id;
219
    int         socket_id;
191
    services_t  service;
220
    services_t  service;
192
 
221
 
-
 
222
    // find the appropriate service
193
    switch( domain ){
223
    switch( domain ){
194
        case PF_INET:
224
        case PF_INET:
195
            switch( type ){
225
            switch( type ){
196
                case SOCK_STREAM:
226
                case SOCK_STREAM:
197
                    if( ! protocol ) protocol = IPPROTO_TCP;
227
                    if( ! protocol ) protocol = IPPROTO_TCP;
Line 222... Line 252...
222
            break;
252
            break;
223
        // TODO IPv6
253
        // TODO IPv6
224
        default:
254
        default:
225
            return EPFNOSUPPORT;
255
            return EPFNOSUPPORT;
226
    }
256
    }
227
    assert( phone );
257
    // create a new socket structure
228
    socket = ( socket_ref ) malloc( sizeof( socket_t ));
258
    socket = ( socket_ref ) malloc( sizeof( socket_t ));
229
    if( ! socket ) return ENOMEM;
259
    if( ! socket ) return ENOMEM;
230
    socket_id = async_req_3_0( phone, NET_SOCKET, 0, 0, service );
260
    if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE ))){
231
    if( socket_id > 0 ){
261
        free( socket );
-
 
262
        return ERROR_CODE;
-
 
263
    }
232
        socket_initialize( socket, socket_id, phone, service );
264
    if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE ))){
233
        if( sockets_add( socket_get_sockets(), socket_id, socket ) != EOK ){
265
        dyn_fifo_destroy( & socket->received );
234
            free( socket );
266
        free( socket );
-
 
267
        return ERROR_CODE;
-
 
268
    }
-
 
269
    // request a new socket
-
 
270
    if( ERROR_OCCURRED( async_req_3_3( phone, NET_SOCKET, 0, 0, service, ( ipcarg_t * ) & socket_id, ( ipcarg_t * ) & socket->header_size, ( ipcarg_t * ) & socket->data_fragment_size ))){
235
            async_msg_3( phone, NET_SOCKET_CLOSE, socket_id, 0, service );
271
        dyn_fifo_destroy( & socket->received );
-
 
272
        dyn_fifo_destroy( & socket->accepted );
-
 
273
        free( socket );
-
 
274
        return ERROR_CODE;
236
        }
275
    }
-
 
276
    // finish the new socket initialization
-
 
277
    socket_initialize( socket, socket_id, phone, service );
237
    }else{
278
    // store the new socket
-
 
279
    ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket );
-
 
280
    if( ERROR_CODE < 0 ){
-
 
281
        dyn_fifo_destroy( & socket->received );
-
 
282
        dyn_fifo_destroy( & socket->accepted );
238
        free( socket );
283
        free( socket );
-
 
284
        async_msg_3( phone, NET_SOCKET_CLOSE, socket_id, 0, service );
-
 
285
        return ERROR_CODE;
239
    }
286
    }
-
 
287
 
240
    return socket_id;
288
    return socket_id;
241
}
289
}
242
 
290
 
243
int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ){
291
int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ){
244
    socket_ref      socket;
292
    socket_ref      socket;
245
    aid_t           message_id;
293
    aid_t           message_id;
246
    ipcarg_t        result;
294
    ipcarg_t        result;
247
 
295
 
248
    if( ! data ) return EBADMEM;
296
    if( ! data ) return EBADMEM;
249
    if( ! datalength ) return NO_DATA;
297
    if( ! datalength ) return NO_DATA;
-
 
298
    // find the socket
250
    socket = sockets_find( socket_get_sockets(), socket_id );
299
    socket = sockets_find( socket_get_sockets(), socket_id );
251
    if( ! socket ) return ENOTSOCK;
300
    if( ! socket ) return ENOTSOCK;
-
 
301
    // request the message
252
    message_id = async_send_3( socket->phone, message, socket->socket_id, arg2, socket->service, NULL );
302
    message_id = async_send_3( socket->phone, message, socket->socket_id, arg2, socket->service, NULL );
-
 
303
    // send the address
253
    ipc_data_write_start( socket->phone, data, datalength );
304
    ipc_data_write_start( socket->phone, data, datalength );
254
    async_wait_for( message_id, & result );
305
    async_wait_for( message_id, & result );
255
    return ( int ) result;
306
    return ( int ) result;
256
}
307
}
257
 
308
 
258
int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){
309
int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){
-
 
310
    // send the address
259
    return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, addrlen );
311
    return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, addrlen );
260
}
312
}
261
 
313
 
262
int listen( int socket_id, int backlog ){
314
int listen( int socket_id, int backlog ){
263
    socket_ref      socket;
315
    socket_ref      socket;
264
 
316
 
265
    if( backlog <= 0 ) return EINVAL;
317
    if( backlog <= 0 ) return EINVAL;
-
 
318
    // find the socket
266
    socket = sockets_find( socket_get_sockets(), socket_id );
319
    socket = sockets_find( socket_get_sockets(), socket_id );
267
    if( ! socket ) return ENOTSOCK;
320
    if( ! socket ) return ENOTSOCK;
-
 
321
    // request listen backlog change
268
    return async_req_3_0( socket->phone, NET_SOCKET_LISTEN, socket->socket_id, backlog, socket->service );
322
    return async_req_3_0( socket->phone, NET_SOCKET_LISTEN, socket->socket_id, backlog, socket->service );
269
}
323
}
270
 
324
 
271
int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){
325
int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){
272
    socket_ref      socket;
326
    socket_ref      socket;
273
    aid_t           message_id;
327
    aid_t           message_id;
274
    ipcarg_t        result;
328
    int             result;
275
 
329
 
276
    if( ! cliaddr ) return EBADMEM;
330
    if( ! cliaddr ) return EBADMEM;
277
    if( ! addrlen ) return NO_DATA;
331
    if( ! addrlen ) return NO_DATA;
-
 
332
    // find the socket
278
    socket = sockets_find( socket_get_sockets(), socket_id );
333
    socket = sockets_find( socket_get_sockets(), socket_id );
279
    if( ! socket ) return ENOTSOCK;
334
    if( ! socket ) return ENOTSOCK;
280
    fibril_mutex_lock( & socket->accept_lock );
335
    fibril_mutex_lock( & socket->accept_lock );
-
 
336
    // wait for an accepted socket
281
    while( socket->accepted <= 0 ){
337
    while( dyn_fifo_value( & socket->accepted ) <= 0 ){
282
        fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock );
338
        fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock );
283
    }
339
    }
-
 
340
    // request accept
284
    message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, socket->socket_id, 0, socket->service, NULL );
341
    message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, socket->socket_id, dyn_fifo_value( & socket->accepted ), socket->service, NULL );
-
 
342
    // read address
285
    ipc_data_read_start( socket->phone, cliaddr, * addrlen );
343
    ipc_data_read_start( socket->phone, cliaddr, * addrlen );
286
    async_wait_for( message_id, & result );
344
    async_wait_for( message_id, ( ipcarg_t * ) & result );
287
    if( result > 0 ){
345
    if( result > 0 ){
-
 
346
        // dequeue the accepted apcket if successful
288
        -- socket->accepted;
347
        dyn_fifo_pop( & socket->accepted );
289
    }
348
    }
290
    fibril_mutex_unlock( & socket->accept_lock );
349
    fibril_mutex_unlock( & socket->accept_lock );
291
    return ( int ) result;
350
    return result;
292
}
351
}
293
 
352
 
294
int connect( int socket_id, const struct sockaddr * serv_addr, socklen_t addrlen ){
353
int connect( int socket_id, const struct sockaddr * serv_addr, socklen_t addrlen ){
-
 
354
    // send the address
295
    return socket_send_data( socket_id, NET_SOCKET_CONNECT, 0, serv_addr, addrlen );
355
    return socket_send_data( socket_id, NET_SOCKET_CONNECT, 0, serv_addr, addrlen );
296
}
356
}
297
 
357
 
298
int closesocket( int socket_id ){
358
int closesocket( int socket_id ){
-
 
359
    ERROR_DECLARE;
-
 
360
 
299
    socket_ref      socket;
361
    socket_ref      socket;
300
 
362
 
301
    socket = sockets_find( socket_get_sockets(), socket_id );
363
    socket = sockets_find( socket_get_sockets(), socket_id );
302
    if( ! socket ) return ENOTSOCK;
364
    if( ! socket ) return ENOTSOCK;
-
 
365
    // request close
303
    return async_req_3_0( socket->phone, NET_SOCKET_CLOSE, socket->socket_id, 0, socket->service );
366
    ERROR_PROPAGATE( async_req_3_0( socket->phone, NET_SOCKET_CLOSE, socket->socket_id, 0, socket->service ));
-
 
367
    // free the socket structure
-
 
368
    socket_destroy( socket );
-
 
369
    return EOK;
-
 
370
}
-
 
371
 
-
 
372
void socket_destroy( socket_ref socket ){
-
 
373
    int accepted_id;
-
 
374
 
-
 
375
    // destroy all accepted sockets
-
 
376
    while(( accepted_id = dyn_fifo_pop( & socket->accepted ))){
-
 
377
        socket_destroy( sockets_find( socket_get_sockets(), accepted_id ));
-
 
378
    }
-
 
379
    dyn_fifo_destroy( & socket->received );
-
 
380
    dyn_fifo_destroy( & socket->accepted );
-
 
381
    sockets_exclude( socket_get_sockets(), socket->socket_id );
304
}
382
}
305
 
383
 
306
int send( int socket_id, void * data, size_t datalength, int flags ){
384
int send( int socket_id, void * data, size_t datalength, int flags ){
-
 
385
    // without the address
307
    return socket_send_data( socket_id, NET_SOCKET_SEND, flags, data, datalength );
386
    return sendto_core( NET_SOCKET_SEND, socket_id, data, datalength, flags, NULL, 0 );
308
}
387
}
309
 
388
 
310
int sendto( int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){
389
int sendto( int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){
311
    socket_ref      socket;
-
 
312
    aid_t           message_id;
-
 
313
    ipcarg_t        result;
-
 
314
 
-
 
315
    if( ! toaddr ) return EBADMEM;
390
    if( ! toaddr ) return EBADMEM;
316
    if( ! addrlen ) return NO_DATA;
391
    if( ! addrlen ) return NO_DATA;
317
    if( ! data ) return EBADMEM;
392
    // with the address
318
    if( ! datalength ) return NO_DATA;
-
 
319
    socket = sockets_find( socket_get_sockets(), socket_id );
-
 
320
    if( ! socket ) return ENOTSOCK;
-
 
321
    message_id = async_send_3( socket->phone, NET_SOCKET_SENDTO, socket->socket_id, flags, socket->service, NULL );
393
    return sendto_core( NET_SOCKET_SENDTO, socket_id, data, datalength, flags, toaddr, addrlen );
322
    if( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK ){
-
 
323
        ipc_data_write_start( socket->phone, data, datalength );
-
 
324
    }
-
 
325
    async_wait_for( message_id, & result );
-
 
326
    return ( int ) result;
-
 
327
}
394
}
328
 
395
 
329
int recv( int socket_id, void * data, size_t datalength, int flags ){
396
int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){
330
    socket_ref      socket;
397
    socket_ref      socket;
331
    aid_t           message_id;
398
    aid_t           message_id;
332
    ipcarg_t        result;
399
    ipcarg_t        result;
-
 
400
    int             fragments;
333
 
401
 
334
    if( ! data ) return EBADMEM;
402
    if( ! data ) return EBADMEM;
335
    if( ! datalength ) return NO_DATA;
403
    if( ! datalength ) return NO_DATA;
-
 
404
    // find socket
336
    socket = sockets_find( socket_get_sockets(), socket_id );
405
    socket = sockets_find( socket_get_sockets(), socket_id );
337
    if( ! socket ) return ENOTSOCK;
406
    if( ! socket ) return ENOTSOCK;
-
 
407
    // compute data fragment count
-
 
408
    fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
-
 
409
    if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
-
 
410
    // request send
-
 
411
    message_id = async_send_4( socket->phone, message, socket->socket_id, fragments, socket->service, flags, NULL );
-
 
412
    // send the address if given
-
 
413
    if(( ! toaddr ) || ( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){
-
 
414
        if( fragments == 1 ){
-
 
415
            // send all if only one fragment
338
    fibril_mutex_lock( & socket->receive_lock );
416
            ipc_data_write_start( socket->phone, data, datalength );
-
 
417
        }else{
-
 
418
            // send the first fragment
-
 
419
            ipc_data_write_start( socket->phone, data, socket->data_fragment_size - socket->header_size );
-
 
420
            data += socket->data_fragment_size - socket->header_size;
-
 
421
            // send the middle fragments
339
    while( socket->received <= 0 ){
422
            while(( -- fragments ) > 1 ){
340
        fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock );
423
                ipc_data_write_start( socket->phone, data, socket->data_fragment_size );
-
 
424
                data += socket->data_fragment_size;
-
 
425
            }
-
 
426
            // send the last fragment
-
 
427
            ipc_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size );
-
 
428
        }
341
    }
429
    }
342
    message_id = async_send_3( socket->phone, NET_SOCKET_RECV, socket->socket_id, flags, socket->service, NULL );
-
 
343
    ipc_data_read_start( socket->phone, data, datalength );
-
 
344
    async_wait_for( message_id, & result );
430
    async_wait_for( message_id, & result );
345
    if( result > 0 ){
-
 
346
        -- socket->received;
-
 
347
    }
-
 
348
    fibril_mutex_unlock( & socket->receive_lock );
-
 
349
    return ( int ) result;
431
    return ( int ) result;
350
}
432
}
351
 
433
 
-
 
434
int recv( int socket_id, void * data, size_t datalength, int flags ){
-
 
435
    // without the address
-
 
436
    return recvfrom_core( NET_SOCKET_RECV, socket_id, data, datalength, flags, NULL, NULL );
-
 
437
}
-
 
438
 
352
int recvfrom( int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){
439
int recvfrom( int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){
-
 
440
    if( ! fromaddr ) return EBADMEM;
-
 
441
    if( ! addrlen ) return NO_DATA;
-
 
442
    // with the address
-
 
443
    return recvfrom_core( NET_SOCKET_RECVFROM, socket_id, data, datalength, flags, fromaddr, addrlen );
-
 
444
}
-
 
445
 
-
 
446
int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){
353
    socket_ref      socket;
447
    socket_ref      socket;
354
    aid_t           message_id;
448
    aid_t           message_id;
355
    ipcarg_t        result;
449
    int             result;
-
 
450
    int             fragments;
-
 
451
    int *           lengths;
-
 
452
    int             index;
-
 
453
    ipc_call_t      answer;
356
 
454
 
357
    if( ! fromaddr ) return EBADMEM;
-
 
358
    if( ! addrlen ) return NO_DATA;
-
 
359
    if( ! data ) return EBADMEM;
455
    if( ! data ) return EBADMEM;
360
    if( ! datalength ) return NO_DATA;
456
    if( ! datalength ) return NO_DATA;
-
 
457
    // find the socket
361
    socket = sockets_find( socket_get_sockets(), socket_id );
458
    socket = sockets_find( socket_get_sockets(), socket_id );
362
    if( ! socket ) return ENOTSOCK;
459
    if( ! socket ) return ENOTSOCK;
363
    fibril_mutex_lock( & socket->receive_lock );
460
    fibril_mutex_lock( & socket->receive_lock );
364
    while( socket->received <= 0 ){
461
    // wait for a received packet
-
 
462
    while(( fragments = dyn_fifo_value( & socket->received )) <= 0 ){
365
        fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock );
463
        fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock );
366
    }
464
    }
367
    message_id = async_send_3( socket->phone, NET_SOCKET_RECVFROM, socket->socket_id, flags, socket->service, NULL );
465
    // prepare lengths if more fragments
-
 
466
    if( fragments > 1 ){
368
    if( ipc_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK ){
467
        lengths = ( int * ) malloc( sizeof( int ) * ( fragments + 1 ));
-
 
468
        if( ! lengths ){
369
        ipc_data_read_start( socket->phone, data, datalength );
469
            fibril_mutex_unlock( & socket->receive_lock );
-
 
470
            return ENOMEM;
-
 
471
        }
370
    }
472
    }
-
 
473
    // request packet data
-
 
474
    message_id = async_send_4( socket->phone, message, socket->socket_id, 0, socket->service, flags, & answer );
-
 
475
    // read the address if desired
-
 
476
    if( fromaddr ){
-
 
477
        * addrlen = sizeof( struct sockaddr_in );
-
 
478
    }
-
 
479
    if(( ! fromaddr ) || ( ipc_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){
-
 
480
        if( fragments == 1 ){
-
 
481
            // read all if only one fragment
-
 
482
            ipc_data_read_start( socket->phone, data, datalength );
-
 
483
        }else{
-
 
484
        // read the fragment lengths
-
 
485
            if( ipc_data_read_start( socket->phone, lengths, sizeof( int ) * ( fragments + 1 )) == EOK ){
-
 
486
                if( lengths[ fragments ] <= datalength ){
-
 
487
                // read all fragments if long enough
-
 
488
                    for( index = 0; index < fragments; ++ index ){
-
 
489
                        ipc_data_read_start( socket->phone, data, lengths[ index ] );
-
 
490
                        data += lengths[ index ];
-
 
491
                    }
-
 
492
                }
-
 
493
            }
-
 
494
            free( lengths );
-
 
495
        }
-
 
496
    }else if( fragments > 1 ){
-
 
497
        free( lengths );
-
 
498
    }
371
    async_wait_for( message_id, & result );
499
    async_wait_for( message_id, ( ipcarg_t * ) & result );
-
 
500
    // if successful
372
    if( result > 0 ){
501
    if( result == EOK ){
-
 
502
        // dequeue the received packet
373
        -- socket->received;
503
        dyn_fifo_pop( & socket->received );
-
 
504
        // return read data length
-
 
505
        result = SOCKET_GET_READ_DATA_LENGTH( & answer );
374
    }
506
    }
375
    fibril_mutex_unlock( & socket->receive_lock );
507
    fibril_mutex_unlock( & socket->receive_lock );
376
    return ( int ) result;
508
    return result;
377
}
509
}
378
 
510
 
379
int getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen ){
511
int getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen ){
380
    socket_ref      socket;
512
    socket_ref      socket;
381
    aid_t           message_id;
513
    aid_t           message_id;
382
    ipcarg_t        result;
514
    ipcarg_t        result;
383
 
515
 
384
    if( ! value ) return EBADMEM;
516
    if( !( value && optlen )) return EBADMEM;
385
    if( ! optlen ) return NO_DATA;
517
    if( !( * optlen )) return NO_DATA;
-
 
518
    // find the socket
386
    socket = sockets_find( socket_get_sockets(), socket_id );
519
    socket = sockets_find( socket_get_sockets(), socket_id );
387
    if( ! socket ) return ENOTSOCK;
520
    if( ! socket ) return ENOTSOCK;
-
 
521
    // request option value
388
    message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, socket->socket_id, optname, socket->service, NULL );
522
    message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, socket->socket_id, optname, socket->service, NULL );
-
 
523
    // read the length
-
 
524
    if( ipc_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){
-
 
525
        // read the value
389
    ipc_data_read_start( socket->phone, value, * optlen );
526
        ipc_data_read_start( socket->phone, value, * optlen );
-
 
527
    }
390
    async_wait_for( message_id, & result );
528
    async_wait_for( message_id, & result );
391
    return ( int ) result;
529
    return ( int ) result;
392
}
530
}
393
 
531
 
394
int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){
532
int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){
-
 
533
    // send the value
395
    return socket_send_data( socket_id, NET_SOCKET_SETSOCKOPT, optname, value, optlen );
534
    return socket_send_data( socket_id, NET_SOCKET_SETSOCKOPT, optname, value, optlen );
-
 
535
 
396
}
536
}
397
 
537
 
398
/** @}
538
/** @}
399
 */
539
 */