Rev 4603 | Rev 4701 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4603 | Rev 4700 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2008 Lukas Mejdrech |
2 | * Copyright (c) 2008 Lukas Mejdrech |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
13 | * documentation and/or other materials provided with the distribution. |
14 | * - The name of the author may not be used to endorse or promote products |
14 | * - The name of the author may not be used to endorse or promote products |
15 | * derived from this software without specific prior written permission. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /** @addtogroup udp |
29 | /** @addtogroup udp |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
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> |
42 | 43 | ||
43 | #include "../../err.h" |
44 | #include "../../err.h" |
44 | #include "../../messages.h" |
45 | #include "../../messages.h" |
45 | #include "../../modules.h" |
46 | #include "../../modules.h" |
46 | 47 | ||
47 | #include "../../structures/dynamic_fifo.h" |
48 | #include "../../structures/dynamic_fifo.h" |
48 | #include "../../structures/packet/packet_client.h" |
49 | #include "../../structures/packet/packet_client.h" |
49 | 50 | ||
50 | #include "../../include/in.h" |
51 | #include "../../include/in.h" |
51 | #include "../../include/inet.h" |
52 | #include "../../include/inet.h" |
52 | #include "../../include/ip_client.h" |
53 | #include "../../include/ip_client.h" |
53 | #include "../../include/ip_interface.h" |
54 | #include "../../include/ip_interface.h" |
54 | #include "../../include/ip_protocols.h" |
55 | #include "../../include/ip_protocols.h" |
55 | #include "../../include/socket.h" |
56 | #include "../../include/socket.h" |
56 | #include "../../include/socket_errno.h" |
57 | #include "../../include/socket_errno.h" |
57 | 58 | ||
58 | #include "../../socket/socket_core.h" |
59 | #include "../../socket/socket_core.h" |
59 | #include "../../socket/socket_messages.h" |
60 | #include "../../socket/socket_messages.h" |
60 | 61 | ||
61 | #include "../tl_messages.h" |
62 | #include "../tl_messages.h" |
62 | 63 | ||
63 | #include "udp.h" |
64 | #include "udp.h" |
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 ); |
74 | int socket_read_data( void ** data, size_t * length ); |
78 | int socket_read_data( void ** data, size_t * length ); |
75 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ); |
79 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ); |
76 | int socket_write_data( void * data, size_t data_length ); |
80 | int socket_write_data( void * data, size_t data_length ); |
77 | 81 | ||
78 | udp_globals_t udp_globals; |
82 | udp_globals_t udp_globals; |
79 | 83 | ||
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; |
98 | 106 | ||
99 | if( ERROR_OCCURRED( udp_process_packet( packet ))){ |
107 | if( ERROR_OCCURRED( udp_process_packet( packet ))){ |
100 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
108 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
101 | return ERROR_CODE; |
109 | return ERROR_CODE; |
102 | } |
110 | } |
103 | 111 | ||
104 | return EOK; |
112 | return EOK; |
105 | } |
113 | } |
106 | 114 | ||
107 | int udp_process_packet( packet_t packet ){ |
115 | int udp_process_packet( packet_t packet ){ |
108 | ERROR_DECLARE; |
116 | ERROR_DECLARE; |
109 | 117 | ||
110 | uint8_t * src; |
118 | uint8_t * src; |
111 | uint8_t * dest; |
119 | uint8_t * dest; |
112 | int length; |
120 | int length; |
113 | void * data; |
121 | void * data; |
114 | udp_header_ref header; |
122 | udp_header_ref header; |
115 | socket_core_ref * socket; |
123 | socket_core_ref * socket; |
116 | packet_t next_packet; |
124 | packet_t next_packet; |
117 | int total_length; |
125 | int total_length; |
118 | // uint16_t checksum; |
126 | // uint16_t checksum; |
119 | int fragments; |
127 | int fragments; |
120 | packet_t tmp_packet; |
128 | packet_t tmp_packet; |
121 | 129 | ||
122 | // get packet data |
130 | // get packet data |
123 | length = packet_get_addr( packet, & src, & dest ); |
131 | length = packet_get_addr( packet, & src, & dest ); |
124 | if( length < 0 ) return length; |
132 | if( length < 0 ) return length; |
125 | if( length != sizeof( in_addr_t )) return EINVAL; |
133 | if( length != sizeof( in_addr_t )) return EINVAL; |
126 | // TODO received ipopts? |
134 | // TODO received ipopts? |
127 | ERROR_PROPAGATE( ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL )); |
135 | ERROR_PROPAGATE( ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL )); |
128 | 136 | ||
129 | // TODO remove debug dump: |
137 | // TODO remove debug dump: |
130 | /* uint8_t * rdata; |
138 | /* uint8_t * rdata; |
131 | rdata = packet_get_data( packet ); |
139 | rdata = packet_get_data( packet ); |
132 | printf( "Receiving udp packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), rdata[ 0 ], rdata[ 1 ], rdata[ 2 ], rdata[ 3 ], rdata[ 4 ], rdata[ 5 ], rdata[ 6 ], rdata[ 7 ], rdata[ 8 ], rdata[ 9 ], rdata[ 10 ], rdata[ 11 ], rdata[ 12 ], rdata[ 13 ], rdata[ 14 ], rdata[ 15 ], rdata[ 16 ], rdata[ 17 ], rdata[ 18 ], rdata[ 19 ], rdata[ 20 ], rdata[ 21 ], rdata[ 22 ], rdata[ 23 ], rdata[ 24 ], rdata[ 25 ], rdata[ 26 ], rdata[ 27 ], rdata[ 28 ], rdata[ 29 ], rdata[ 30 ], rdata[ 31 ], rdata[ 32 ], rdata[ 33 ], rdata[ 34 ], rdata[ 35 ], rdata[ 36 ], rdata[ 37 ], rdata[ 38 ], rdata[ 39 ], rdata[ 40 ], rdata[ 41 ], rdata[ 42 ], rdata[ 43 ], rdata[ 44 ], rdata[ 45 ], rdata[ 46 ], rdata[ 47 ], rdata[ 48 ], rdata[ 49 ], rdata[ 50 ], rdata[ 51 ], rdata[ 52 ], rdata[ 53 ], rdata[ 54 ], rdata[ 55 ], rdata[ 56 ], rdata[ 57 ], rdata[ 58 ], rdata[ 59 ] ); |
140 | printf( "Receiving udp packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), rdata[ 0 ], rdata[ 1 ], rdata[ 2 ], rdata[ 3 ], rdata[ 4 ], rdata[ 5 ], rdata[ 6 ], rdata[ 7 ], rdata[ 8 ], rdata[ 9 ], rdata[ 10 ], rdata[ 11 ], rdata[ 12 ], rdata[ 13 ], rdata[ 14 ], rdata[ 15 ], rdata[ 16 ], rdata[ 17 ], rdata[ 18 ], rdata[ 19 ], rdata[ 20 ], rdata[ 21 ], rdata[ 22 ], rdata[ 23 ], rdata[ 24 ], rdata[ 25 ], rdata[ 26 ], rdata[ 27 ], rdata[ 28 ], rdata[ 29 ], rdata[ 30 ], rdata[ 31 ], rdata[ 32 ], rdata[ 33 ], rdata[ 34 ], rdata[ 35 ], rdata[ 36 ], rdata[ 37 ], rdata[ 38 ], rdata[ 39 ], rdata[ 40 ], rdata[ 41 ], rdata[ 42 ], rdata[ 43 ], rdata[ 44 ], rdata[ 45 ], rdata[ 46 ], rdata[ 47 ], rdata[ 48 ], rdata[ 49 ], rdata[ 50 ], rdata[ 51 ], rdata[ 52 ], rdata[ 53 ], rdata[ 54 ], rdata[ 55 ], rdata[ 56 ], rdata[ 57 ], rdata[ 58 ], rdata[ 59 ] ); |
133 | */ |
141 | */ |
134 | length = packet_get_data_length( packet ); |
142 | length = packet_get_data_length( packet ); |
135 | if( length < 0 ) return length; |
143 | if( length < 0 ) return length; |
136 | if( length < sizeof( udp_header_t )) return NO_DATA; |
144 | if( length < sizeof( udp_header_t )) return NO_DATA; |
137 | data = packet_get_data( packet ); |
145 | data = packet_get_data( packet ); |
138 | if( ! data ) return NO_DATA; |
146 | if( ! data ) return NO_DATA; |
139 | // get udp header |
147 | // get udp header |
140 | header = ( udp_header_ref ) data; |
148 | header = ( udp_header_ref ) data; |
141 | // find the destination socket |
149 | // find the destination socket |
142 | socket = socket_ports_find( & udp_globals.sockets, ntohs( header->dest )); |
150 | socket = socket_ports_find( & udp_globals.sockets, ntohs( header->dest )); |
143 | if( ! socket ) return EADDRNOTAVAIL; |
151 | if( ! socket ) return EADDRNOTAVAIL; |
144 | // count the received packet fragments |
152 | // count the received packet fragments |
145 | next_packet = packet; |
153 | next_packet = packet; |
146 | fragments = 0; |
154 | fragments = 0; |
147 | total_length = ntohs( header->len ); |
155 | total_length = ntohs( header->len ); |
148 | do{ |
156 | do{ |
149 | ++ fragments; |
157 | ++ fragments; |
150 | length = packet_get_data_length( packet ); |
158 | length = packet_get_data_length( packet ); |
151 | if( length < 0 ) return length; |
159 | if( length < 0 ) return length; |
152 | if( ! length ) return NO_DATA; |
160 | if( ! length ) return NO_DATA; |
153 | if( total_length < length ){ |
161 | if( total_length < length ){ |
154 | // cut of the suffix if too long |
162 | // cut of the suffix if too long |
155 | ERROR_PROPAGATE( packet_trim( next_packet, 0, length - total_length )); |
163 | ERROR_PROPAGATE( packet_trim( next_packet, 0, length - total_length )); |
156 | // relese the rest of the packet fragments |
164 | // relese the rest of the packet fragments |
157 | tmp_packet = pq_next( next_packet ); |
165 | tmp_packet = pq_next( next_packet ); |
158 | while( tmp_packet ){ |
166 | while( tmp_packet ){ |
159 | next_packet = pq_detach( tmp_packet ); |
167 | next_packet = pq_detach( tmp_packet ); |
160 | pq_release( udp_globals.net_phone, packet_get_id( tmp_packet )); |
168 | pq_release( udp_globals.net_phone, packet_get_id( tmp_packet )); |
161 | tmp_packet = next_packet; |
169 | tmp_packet = next_packet; |
162 | } |
170 | } |
163 | break; |
171 | break; |
164 | } |
172 | } |
165 | total_length -= length; |
173 | total_length -= length; |
166 | /* if( header->header_checksum ){ |
174 | /* if( header->header_checksum ){ |
167 | } |
175 | } |
168 | */ |
176 | */ |
169 | }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 )); |
177 | }while(( next_packet = pq_next( next_packet )) && ( total_length > 0 )); |
170 | // queue the received packet |
178 | // queue the received packet |
171 | ERROR_PROPAGATE( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE )); |
179 | ERROR_PROPAGATE( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE )); |
172 | 180 | ||
173 | // notify the destination socket |
181 | // notify the destination socket |
174 | async_msg_2(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ** socket ).socket_id, fragments ); |
182 | async_msg_2(( ** socket ).phone, NET_SOCKET_RECEIVED, ( ** socket ).socket_id, fragments ); |
175 | return EOK; |
183 | return EOK; |
176 | } |
184 | } |
177 | 185 | ||
178 | int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
186 | int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
179 | ERROR_DECLARE; |
187 | ERROR_DECLARE; |
180 | 188 | ||
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 | } |
193 | 205 | ||
194 | int process_client_messages( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
206 | int process_client_messages( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
195 | ERROR_DECLARE; |
207 | ERROR_DECLARE; |
196 | 208 | ||
197 | int res; |
209 | int res; |
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 ); |
216 | // just to be precize |
230 | // just to be precize |
217 | IPC_SET_METHOD( * answer, 0 ); |
231 | IPC_SET_METHOD( * answer, 0 ); |
218 | IPC_SET_ARG1( * answer, 0 ); |
232 | IPC_SET_ARG1( * answer, 0 ); |
219 | IPC_SET_ARG2( * answer, 0 ); |
233 | IPC_SET_ARG2( * answer, 0 ); |
220 | IPC_SET_ARG3( * answer, 0 ); |
234 | IPC_SET_ARG3( * answer, 0 ); |
221 | IPC_SET_ARG4( * answer, 0 ); |
235 | IPC_SET_ARG4( * answer, 0 ); |
222 | IPC_SET_ARG5( * answer, 0 ); |
236 | IPC_SET_ARG5( * answer, 0 ); |
223 | 237 | ||
224 | callid = async_get_call( call ); |
238 | callid = async_get_call( call ); |
225 | // printf( "message %d\n", IPC_GET_METHOD( * call )); |
239 | // printf( "message %d\n", IPC_GET_METHOD( * call )); |
226 | 240 | ||
227 | switch( IPC_GET_METHOD( * call )){ |
241 | switch( IPC_GET_METHOD( * call )){ |
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; |
270 | break; |
302 | break; |
271 | } |
303 | } |
272 | 304 | ||
273 | // printf( "res = %d\n", res ); |
305 | // printf( "res = %d\n", res ); |
274 | 306 | ||
275 | switch( * answer_count ){ |
307 | switch( * answer_count ){ |
276 | case 0: ipc_answer_0( callid, res ); |
308 | case 0: ipc_answer_0( callid, res ); |
277 | continue; |
309 | continue; |
278 | case 1: ipc_answer_1( callid, res, IPC_GET_ARG1( * answer )); |
310 | case 1: ipc_answer_1( callid, res, IPC_GET_ARG1( * answer )); |
279 | continue; |
311 | continue; |
280 | case 2: ipc_answer_2( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer )); |
312 | case 2: ipc_answer_2( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer )); |
281 | continue; |
313 | continue; |
282 | case 3: ipc_answer_3( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer )); |
314 | case 3: ipc_answer_3( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer )); |
283 | continue; |
315 | continue; |
284 | case 4: ipc_answer_4( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer )); |
316 | case 4: ipc_answer_4( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer )); |
285 | continue; |
317 | continue; |
286 | default: ipc_answer_5( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer ), IPC_GET_ARG5( * answer )); |
318 | default: ipc_answer_5( callid, res, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer ), IPC_GET_ARG5( * answer )); |
287 | continue; |
319 | continue; |
288 | } |
320 | } |
289 | } |
321 | } |
290 | 322 | ||
291 | socket_cores_destroy( & local_sockets ); |
323 | socket_cores_destroy( & local_sockets ); |
292 | 324 | ||
293 | return EOK; |
325 | return EOK; |
294 | } |
326 | } |
295 | 327 | ||
296 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ){ |
328 | int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ){ |
297 | ERROR_DECLARE; |
329 | ERROR_DECLARE; |
298 | 330 | ||
299 | socket_core_ref socket; |
331 | socket_core_ref socket; |
300 | struct sockaddr * address; |
332 | struct sockaddr * address; |
301 | struct sockaddr_in * address_in; |
333 | struct sockaddr_in * address_in; |
302 | packet_t packet; |
334 | packet_t packet; |
303 | packet_t next_packet; |
335 | packet_t next_packet; |
304 | udp_header_ref header; |
336 | udp_header_ref header; |
305 | int index; |
337 | int index; |
306 | int total_length; |
338 | int total_length; |
307 | int length; |
339 | int length; |
308 | 340 | ||
309 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
341 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
310 | address = ( struct sockaddr * ) addr; |
342 | address = ( struct sockaddr * ) addr; |
311 | switch( address->sa_family ){ |
343 | switch( address->sa_family ){ |
312 | case AF_INET: |
344 | case AF_INET: |
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 ); |
323 | if( total_length < 0 ) return total_length; |
366 | if( total_length < 0 ) return total_length; |
324 | // prefix the udp header |
367 | // prefix the udp header |
325 | header = PACKET_PREFIX( packet, udp_header_t ); |
368 | header = PACKET_PREFIX( packet, udp_header_t ); |
326 | if( ! header ){ |
369 | if( ! header ){ |
327 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
370 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
328 | return ENOMEM; |
371 | return ENOMEM; |
329 | } |
372 | } |
330 | // read the rest of the packet fragments |
373 | // read the rest of the packet fragments |
331 | for( index = 1; index < fragments; ++ index ){ |
374 | for( index = 1; index < fragments; ++ index ){ |
332 | length = socket_read_packet_data( & next_packet, 0, address_in ); |
375 | length = socket_read_packet_data( & next_packet, 0, address_in ); |
333 | if( length < 0 ){ |
376 | if( length < 0 ){ |
334 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
377 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
335 | return length; |
378 | return length; |
336 | } |
379 | } |
337 | packet = pq_add( packet, next_packet, index, 0 ); |
380 | packet = pq_add( packet, next_packet, index, 0 ); |
338 | total_length += length; |
381 | total_length += length; |
339 | } |
382 | } |
340 | // set the udp header |
383 | // set the udp header |
341 | header->source = ( socket->port < 0 ) ? 0 : htons( socket->port ); |
384 | header->source = ( socket->port < 0 ) ? 0 : htons( socket->port ); |
342 | header->dest = htons( address_in->sin_port ); |
385 | header->dest = htons( address_in->sin_port ); |
343 | header->len = htons( total_length + sizeof( udp_header_t )); |
386 | header->len = htons( total_length + sizeof( udp_header_t )); |
344 | // TODO my ip address for the pseudo header checksum |
387 | // TODO my ip address for the pseudo header checksum |
345 | header->check = 0; |
388 | header->check = 0; |
346 | // prepare the first packet fragment |
389 | // prepare the first packet fragment |
347 | if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){ |
390 | if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){ |
348 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
391 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
349 | return ERROR_CODE; |
392 | return ERROR_CODE; |
350 | } |
393 | } |
351 | // send the packet |
394 | // send the packet |
352 | return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP ); |
395 | return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP ); |
353 | // TODO IPv6 |
396 | // TODO IPv6 |
354 | default: |
397 | default: |
355 | return EAFNOSUPPORT; |
398 | return EAFNOSUPPORT; |
356 | } |
399 | } |
357 | return EOK; |
400 | return EOK; |
358 | } |
401 | } |
359 | 402 | ||
360 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ){ |
403 | int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ){ |
361 | ERROR_DECLARE; |
404 | ERROR_DECLARE; |
362 | 405 | ||
363 | socket_core_ref socket; |
406 | socket_core_ref socket; |
364 | int packet_id; |
407 | int packet_id; |
365 | packet_t packet; |
408 | packet_t packet; |
366 | udp_header_ref header; |
409 | udp_header_ref header; |
367 | struct sockaddr_in address; |
410 | struct sockaddr_in address; |
368 | int length; |
411 | int length; |
369 | packet_t next_packet; |
412 | packet_t next_packet; |
370 | void * data; |
413 | void * data; |
371 | int fragments; |
414 | int fragments; |
372 | int * lengths; |
415 | int * lengths; |
373 | int index; |
416 | int index; |
374 | uint8_t * addr; |
417 | uint8_t * addr; |
375 | 418 | ||
376 | // find the socket |
419 | // find the socket |
377 | socket = socket_cores_find( local_sockets, socket_id ); |
420 | socket = socket_cores_find( local_sockets, socket_id ); |
378 | if( ! socket ) return ENOTSOCK; |
421 | if( ! socket ) return ENOTSOCK; |
379 | // get the next received packet |
422 | // get the next received packet |
380 | packet_id = dyn_fifo_value( & socket->received ); |
423 | packet_id = dyn_fifo_value( & socket->received ); |
381 | if( packet_id < 0 ) return packet_id; |
424 | if( packet_id < 0 ) return packet_id; |
382 | ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id )); |
425 | ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id )); |
383 | // get udp header |
426 | // get udp header |
384 | data = packet_get_data( packet ); |
427 | data = packet_get_data( packet ); |
385 | if( ! data ){ |
428 | if( ! data ){ |
386 | pq_release( udp_globals.net_phone, packet_id ); |
429 | pq_release( udp_globals.net_phone, packet_id ); |
387 | return NO_DATA; |
430 | return NO_DATA; |
388 | } |
431 | } |
389 | header = ( udp_header_ref ) data; |
432 | header = ( udp_header_ref ) data; |
390 | // set the source address |
433 | // set the source address |
391 | address.sin_family = PF_INET; |
434 | address.sin_family = PF_INET; |
392 | address.sin_port = ntohs( header->source ); |
435 | address.sin_port = ntohs( header->source ); |
393 | length = packet_get_addr( packet, & addr, NULL ); |
436 | length = packet_get_addr( packet, & addr, NULL ); |
394 | if( length != sizeof( address.sin_addr.s_addr )){ |
437 | if( length != sizeof( address.sin_addr.s_addr )){ |
395 | pq_release( udp_globals.net_phone, packet_id ); |
438 | pq_release( udp_globals.net_phone, packet_id ); |
396 | return EINVAL; |
439 | return EINVAL; |
397 | } |
440 | } |
398 | address.sin_addr.s_addr = *(( uint32_t * ) addr ); |
441 | address.sin_addr.s_addr = *(( uint32_t * ) addr ); |
399 | bzero( & address.sin_zero, sizeof( address.sin_zero )); |
442 | bzero( & address.sin_zero, sizeof( address.sin_zero )); |
400 | // send the source address |
443 | // send the source address |
401 | ERROR_PROPAGATE( socket_write_data( & address, sizeof( address ))); |
444 | ERROR_PROPAGATE( socket_write_data( & address, sizeof( address ))); |
402 | next_packet = pq_next( packet ); |
445 | next_packet = pq_next( packet ); |
403 | if( ! next_packet ){ |
446 | if( ! next_packet ){ |
404 | // write all if only one fragment |
447 | // write all if only one fragment |
405 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t ))); |
448 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), packet_get_data_length( packet ) - sizeof( udp_header_t ))); |
406 | // store the total length |
449 | // store the total length |
407 | length = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
450 | length = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
408 | }else{ |
451 | }else{ |
409 | // count the packet fragments |
452 | // count the packet fragments |
410 | fragments = 1; |
453 | fragments = 1; |
411 | next_packet = pq_next( packet ); |
454 | next_packet = pq_next( packet ); |
412 | while(( next_packet = pq_next( next_packet ))){ |
455 | while(( next_packet = pq_next( next_packet ))){ |
413 | ++ fragments; |
456 | ++ fragments; |
414 | } |
457 | } |
415 | // compute and store the fragment lengths |
458 | // compute and store the fragment lengths |
416 | lengths = ( int * ) malloc( sizeof( int ) * ( fragments + 1 )); |
459 | lengths = ( int * ) malloc( sizeof( int ) * ( fragments + 1 )); |
417 | if( ! lengths ) return ENOMEM; |
460 | if( ! lengths ) return ENOMEM; |
418 | lengths[ 0 ] = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
461 | lengths[ 0 ] = packet_get_data_length( packet ) - sizeof( udp_header_t ); |
419 | lengths[ fragments ] = lengths[ 0 ]; |
462 | lengths[ fragments ] = lengths[ 0 ]; |
420 | next_packet = pq_next( packet ); |
463 | next_packet = pq_next( packet ); |
421 | for( index = 1; index < fragments; ++ index ){ |
464 | for( index = 1; index < fragments; ++ index ){ |
422 | lengths[ index ] = packet_get_data_length( next_packet ); |
465 | lengths[ index ] = packet_get_data_length( next_packet ); |
423 | lengths[ fragments ] += lengths[ index ]; |
466 | lengths[ fragments ] += lengths[ index ]; |
424 | next_packet = pq_next( packet ); |
467 | next_packet = pq_next( packet ); |
425 | }while( next_packet ); |
468 | }while( next_packet ); |
426 | // write the fragment lengths |
469 | // write the fragment lengths |
427 | ERROR_PROPAGATE( socket_write_data( lengths, sizeof( int ) * ( fragments + 1 ))); |
470 | ERROR_PROPAGATE( socket_write_data( lengths, sizeof( int ) * ( fragments + 1 ))); |
428 | // write the first fragment |
471 | // write the first fragment |
429 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), lengths[ 0 ] )); |
472 | ERROR_PROPAGATE( socket_write_data( data + sizeof( udp_header_t ), lengths[ 0 ] )); |
430 | next_packet = pq_next( packet ); |
473 | next_packet = pq_next( packet ); |
431 | // write the rest of the fragments |
474 | // write the rest of the fragments |
432 | for( index = 1; index < fragments; ++ index ){ |
475 | for( index = 1; index < fragments; ++ index ){ |
433 | ERROR_PROPAGATE( socket_write_data( packet_get_data( next_packet ), lengths[ index ] )); |
476 | ERROR_PROPAGATE( socket_write_data( packet_get_data( next_packet ), lengths[ index ] )); |
434 | next_packet = pq_next( packet ); |
477 | next_packet = pq_next( packet ); |
435 | }while( next_packet ); |
478 | }while( next_packet ); |
436 | // store the total length |
479 | // store the total length |
437 | length = lengths[ fragments ]; |
480 | length = lengths[ fragments ]; |
438 | free( lengths ); |
481 | free( lengths ); |
439 | } |
482 | } |
440 | // release the packet |
483 | // release the packet |
441 | dyn_fifo_pop( & socket->received ); |
484 | dyn_fifo_pop( & socket->received ); |
442 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
485 | pq_release( udp_globals.net_phone, packet_get_id( packet )); |
443 | // return the total length |
486 | // return the total length |
444 | return length; |
487 | return length; |
445 | } |
488 | } |
446 | 489 | ||
447 | int socket_write_data( void * data, size_t data_length ){ |
490 | int socket_write_data( void * data, size_t data_length ){ |
448 | size_t length; |
491 | size_t length; |
449 | ipc_callid_t callid; |
492 | ipc_callid_t callid; |
450 | 493 | ||
451 | if(( ! ipc_data_read_receive( & callid, & length )) |
494 | if(( ! ipc_data_read_receive( & callid, & length )) |
452 | || ( length < data_length )){ |
495 | || ( length < data_length )){ |
453 | return EINVAL; |
496 | return EINVAL; |
454 | } |
497 | } |
455 | return ipc_data_read_finalize( callid, data, data_length ); |
498 | return ipc_data_read_finalize( callid, data, data_length ); |
456 | } |
499 | } |
457 | 500 | ||
458 | int socket_read_data( void ** data, size_t * length ){ |
501 | int socket_read_data( void ** data, size_t * length ){ |
459 | ERROR_DECLARE; |
502 | ERROR_DECLARE; |
460 | 503 | ||
461 | ipc_callid_t callid; |
504 | ipc_callid_t callid; |
462 | 505 | ||
463 | if( !( data && length )) return EBADMEM; |
506 | if( !( data && length )) return EBADMEM; |
464 | if( ! ipc_data_write_receive( & callid, length )) return EINVAL; |
507 | if( ! ipc_data_write_receive( & callid, length )) return EINVAL; |
465 | * data = malloc( * length ); |
508 | * data = malloc( * length ); |
466 | if( ! data ) return ENOMEM; |
509 | if( ! data ) return ENOMEM; |
467 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, * data, * length ))){ |
510 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, * data, * length ))){ |
468 | free( data ); |
511 | free( data ); |
469 | return ERROR_CODE; |
512 | return ERROR_CODE; |
470 | } |
513 | } |
471 | return EOK; |
514 | return EOK; |
472 | } |
515 | } |
473 | 516 | ||
474 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ){ |
517 | int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ){ |
475 | ERROR_DECLARE; |
518 | ERROR_DECLARE; |
476 | 519 | ||
477 | ipc_callid_t callid; |
520 | ipc_callid_t callid; |
478 | size_t length; |
521 | size_t length; |
479 | void * data; |
522 | void * data; |
480 | 523 | ||
481 | // get the data length |
524 | // get the data length |
482 | if( ! ipc_data_write_receive( & callid, & length )) return EINVAL; |
525 | if( ! ipc_data_write_receive( & callid, & length )) return EINVAL; |
483 | // get a new packet |
526 | // get a new packet |
484 | * packet = packet_get_4( udp_globals.net_phone, length, udp_globals.addr_len, prefix + udp_globals.prefix, udp_globals.suffix ); |
527 | * packet = packet_get_4( udp_globals.net_phone, length, udp_globals.addr_len, prefix + udp_globals.prefix, udp_globals.suffix ); |
485 | if( ! packet ) return ENOMEM; |
528 | if( ! packet ) return ENOMEM; |
486 | // allocate space in the packet |
529 | // allocate space in the packet |
487 | data = packet_suffix( * packet, length ); |
530 | data = packet_suffix( * packet, length ); |
488 | if( ! data ){ |
531 | if( ! data ){ |
489 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
532 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
490 | return ENOMEM; |
533 | return ENOMEM; |
491 | } |
534 | } |
492 | // read the data into the packet |
535 | // read the data into the packet |
493 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length )) |
536 | if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length )) |
494 | // set the packet destination address |
537 | // set the packet destination address |
495 | || ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){ |
538 | || ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){ |
496 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
539 | pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
497 | return ERROR_CODE; |
540 | return ERROR_CODE; |
498 | } |
541 | } |
499 | return length; |
542 | return length; |
500 | } |
543 | } |
501 | 544 | ||
502 | /** @} |
545 | /** @} |
503 | */ |
546 | */ |
504 | 547 |