source: mainline/uspace/lib/c/generic/net/modules.c@ c7a8442

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c7a8442 was c7a8442, checked in by Jakub Jermar <jakub@…>, 15 years ago

Move net_modules.[ch] to the standard library. Note that this functionality is
not directly related to networking so the next step regarding these two files
would be to somehow merge its functionality with what we already have in lib c.

  • Property mode set to 100644
File size: 8.3 KB
RevLine 
[c7a8442]1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
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
15 * derived from this software without specific prior written permission.
16 *
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
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32
33/** @file
34 * Generic module functions implementation.
35 *
36 * @todo MAKE IT POSSIBLE TO REMOVE THIS FILE VIA EITHER REPLACING PART OF ITS
37 * FUNCTIONALITY OR VIA INTEGRATING ITS FUNCTIONALITY MORE TIGHTLY WITH THE REST
38 * OF THE SYSTEM.
39 */
40
41#include <async.h>
42#include <malloc.h>
43#include <err.h>
44#include <sys/time.h>
45
46#include <ipc/ipc.h>
47#include <ipc/services.h>
48
49#include <net/modules.h>
50
51/** The time between connect requests in microseconds. */
52#define MODULE_WAIT_TIME (10 * 1000)
53
54/** Answers the call.
55 *
56 * @param[in] callid The call identifier.
57 * @param[in] result The message processing result.
58 * @param[in] answer The message processing answer.
59 * @param[in] answer_count The number of answer parameters.
60 */
61void
62answer_call(ipc_callid_t callid, int result, ipc_call_t *answer,
63 int answer_count)
64{
65 // choose the most efficient answer function
66 if (answer || (!answer_count)) {
67 switch (answer_count) {
68 case 0:
69 ipc_answer_0(callid, (ipcarg_t) result);
70 break;
71 case 1:
72 ipc_answer_1(callid, (ipcarg_t) result,
73 IPC_GET_ARG1(*answer));
74 break;
75 case 2:
76 ipc_answer_2(callid, (ipcarg_t) result,
77 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer));
78 break;
79 case 3:
80 ipc_answer_3(callid, (ipcarg_t) result,
81 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
82 IPC_GET_ARG3(*answer));
83 break;
84 case 4:
85 ipc_answer_4(callid, (ipcarg_t) result,
86 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
87 IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer));
88 break;
89 case 5:
90 default:
91 ipc_answer_5(callid, (ipcarg_t) result,
92 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
93 IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer),
94 IPC_GET_ARG5(*answer));
95 break;
96 }
97 }
98}
99
100/** Create bidirectional connection with the needed module service and registers
101 * the message receiver.
102 *
103 * @param[in] need The needed module service.
104 * @param[in] arg1 The first parameter.
105 * @param[in] arg2 The second parameter.
106 * @param[in] arg3 The third parameter.
107 * @param[in] client_receiver The message receiver.
108 *
109 * @return The phone of the needed service.
110 * @return Other error codes as defined for the ipc_connect_to_me()
111 * function.
112 */
113int bind_service(services_t need, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3,
114 async_client_conn_t client_receiver)
115{
116 return bind_service_timeout(need, arg1, arg2, arg3, client_receiver, 0);
117}
118
119/** Create bidirectional connection with the needed module service and registers
120 * the message receiver.
121 *
122 * @param[in] need The needed module service.
123 * @param[in] arg1 The first parameter.
124 * @param[in] arg2 The second parameter.
125 * @param[in] arg3 The third parameter.
126 * @param[in] client_receiver The message receiver.
127 * @param[in] timeout The connection timeout in microseconds. No timeout if
128 * set to zero (0).
129 *
130 * @return The phone of the needed service.
131 * @return ETIMEOUT if the connection timeouted.
132 * @return Other error codes as defined for the ipc_connect_to_me()
133 * function.
134 *
135 */
136int bind_service_timeout(services_t need, ipcarg_t arg1, ipcarg_t arg2,
137 ipcarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout)
138{
139 ERROR_DECLARE;
140
141 /* Connect to the needed service */
142 int phone = connect_to_service_timeout(need, timeout);
143 if (phone >= 0) {
144 /* Request the bidirectional connection */
145 ipcarg_t phonehash;
146 if (ERROR_OCCURRED(ipc_connect_to_me(phone, arg1, arg2, arg3,
147 &phonehash))) {
148 ipc_hangup(phone);
149 return ERROR_CODE;
150 }
151 async_new_connection(phonehash, 0, NULL, client_receiver);
152 }
153
154 return phone;
155}
156
157/** Connects to the needed module.
158 *
159 * @param[in] need The needed module service.
160 * @returns The phone of the needed service.
161 */
162int connect_to_service(services_t need)
163{
164 return connect_to_service_timeout(need, 0);
165}
166
167/** Connects to the needed module.
168 *
169 * @param[in] need The needed module service.
170 * @param[in] timeout The connection timeout in microseconds. No timeout if
171 * set to zero (0).
172 * @returns The phone of the needed service.
173 * @returns ETIMEOUT if the connection timeouted.
174 */
175int connect_to_service_timeout(services_t need, suseconds_t timeout)
176{
177 int phone;
178
179 // if no timeout is set
180 if (timeout <= 0)
181 return async_connect_me_to_blocking(PHONE_NS, need, 0, 0);
182
183 while (true) {
184 phone = async_connect_me_to(PHONE_NS, need, 0, 0);
185 if ((phone >= 0) || (phone != ENOENT))
186 return phone;
187
188 // end if no time is left
189 if (timeout <= 0)
190 return ETIMEOUT;
191
192 // wait the minimum of the module wait time and the timeout
193 usleep((timeout <= MODULE_WAIT_TIME) ?
194 timeout : MODULE_WAIT_TIME);
195 timeout -= MODULE_WAIT_TIME;
196 }
197}
198
199/** Receives data from the other party.
200 *
201 * The received data buffer is allocated and returned.
202 *
203 * @param[out] data The data buffer to be filled.
204 * @param[out] length The buffer length.
205 * @returns EOK on success.
206 * @returns EBADMEM if the data or the length parameter is NULL.
207 * @returns EINVAL if the client does not send data.
208 * @returns ENOMEM if there is not enough memory left.
209 * @returns Other error codes as defined for the
210 * async_data_write_finalize() function.
211 */
212int data_receive(void **data, size_t *length)
213{
214 ERROR_DECLARE;
215
216 ipc_callid_t callid;
217
218 if (!data || !length)
219 return EBADMEM;
220
221 // fetch the request
222 if (!async_data_write_receive(&callid, length))
223 return EINVAL;
224
225 // allocate the buffer
226 *data = malloc(*length);
227 if (!*data)
228 return ENOMEM;
229
230 // fetch the data
231 if (ERROR_OCCURRED(async_data_write_finalize(callid, *data, *length))) {
232 free(data);
233 return ERROR_CODE;
234 }
235
236 return EOK;
237}
238
239/** Replies the data to the other party.
240 *
241 * @param[in] data The data buffer to be sent.
242 * @param[in] data_length The buffer length.
243 * @returns EOK on success.
244 * @returns EINVAL if the client does not expect the data.
245 * @returns EOVERFLOW if the client does not expect all the data.
246 * Only partial data are transfered.
247 * @returns Other error codes as defined for the
248 * async_data_read_finalize() function.
249 */
250int data_reply(void *data, size_t data_length)
251{
252 size_t length;
253 ipc_callid_t callid;
254
255 // fetch the request
256 if (!async_data_read_receive(&callid, &length))
257 return EINVAL;
258
259 // check the requested data size
260 if (length < data_length) {
261 async_data_read_finalize(callid, data, length);
262 return EOVERFLOW;
263 }
264
265 // send the data
266 return async_data_read_finalize(callid, data, data_length);
267}
268
269/** Refreshes answer structure and parameters count.
270 *
271 * Erases all attributes.
272 *
273 * @param[in,out] answer The message processing answer structure.
274 * @param[in,out] answer_count The number of answer parameters.
275 */
276void refresh_answer(ipc_call_t *answer, int *answer_count)
277{
278 if (answer_count)
279 *answer_count = 0;
280
281 if (answer) {
282 IPC_SET_RETVAL(*answer, 0);
283 // just to be precize
284 IPC_SET_METHOD(*answer, 0);
285 IPC_SET_ARG1(*answer, 0);
286 IPC_SET_ARG2(*answer, 0);
287 IPC_SET_ARG3(*answer, 0);
288 IPC_SET_ARG4(*answer, 0);
289 IPC_SET_ARG5(*answer, 0);
290 }
291}
292
293/** @}
294 */
Note: See TracBrowser for help on using the repository browser.