Rev 4377 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4377 | Rev 4692 | ||
---|---|---|---|
Line 91... | Line 91... | ||
91 | * Otherwise return 0. |
91 | * Otherwise return 0. |
92 | */ |
92 | */ |
93 | static inline int method_is_forwardable(unative_t method) |
93 | static inline int method_is_forwardable(unative_t method) |
94 | { |
94 | { |
95 | switch (method) { |
95 | switch (method) { |
- | 96 | case IPC_M_CONNECTION_CLONE: |
|
- | 97 | case IPC_M_CONNECT_ME: |
|
96 | case IPC_M_PHONE_HUNGUP: |
98 | case IPC_M_PHONE_HUNGUP: |
97 | /* This message is meant only for the original recipient. */ |
99 | /* This message is meant only for the original recipient. */ |
98 | return 0; |
100 | return 0; |
99 | default: |
101 | default: |
100 | return 1; |
102 | return 1; |
Line 138... | Line 140... | ||
138 | * Return 0 otherwise. |
140 | * Return 0 otherwise. |
139 | */ |
141 | */ |
140 | static inline int answer_need_old(call_t *call) |
142 | static inline int answer_need_old(call_t *call) |
141 | { |
143 | { |
142 | switch (IPC_GET_METHOD(call->data)) { |
144 | switch (IPC_GET_METHOD(call->data)) { |
- | 145 | case IPC_M_CONNECTION_CLONE: |
|
- | 146 | case IPC_M_CONNECT_ME: |
|
143 | case IPC_M_CONNECT_TO_ME: |
147 | case IPC_M_CONNECT_TO_ME: |
144 | case IPC_M_CONNECT_ME_TO: |
148 | case IPC_M_CONNECT_ME_TO: |
145 | case IPC_M_SHARE_OUT: |
149 | case IPC_M_SHARE_OUT: |
146 | case IPC_M_SHARE_IN: |
150 | case IPC_M_SHARE_IN: |
147 | case IPC_M_DATA_WRITE: |
151 | case IPC_M_DATA_WRITE: |
Line 180... | Line 184... | ||
180 | } |
184 | } |
181 | 185 | ||
182 | if (!olddata) |
186 | if (!olddata) |
183 | return 0; |
187 | return 0; |
184 | 188 | ||
- | 189 | if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTION_CLONE) { |
|
- | 190 | phoneid = IPC_GET_ARG1(*olddata); |
|
- | 191 | phone_t *phone = &TASK->phones[phoneid]; |
|
- | 192 | if (IPC_GET_RETVAL(answer->data) != EOK) { |
|
- | 193 | /* |
|
- | 194 | * The recipient of the cloned phone rejected the offer. |
|
- | 195 | * In this case, the connection was established at the |
|
- | 196 | * request time and therefore we need to slam the phone. |
|
- | 197 | * We don't merely hangup as that would result in |
|
- | 198 | * sending IPC_M_HUNGUP to the third party on the |
|
- | 199 | * other side of the cloned phone. |
|
- | 200 | */ |
|
- | 201 | mutex_lock(&phone->lock); |
|
- | 202 | if (phone->state == IPC_PHONE_CONNECTED) { |
|
- | 203 | spinlock_lock(&phone->callee->lock); |
|
- | 204 | list_remove(&phone->link); |
|
- | 205 | phone->state = IPC_PHONE_SLAMMED; |
|
- | 206 | spinlock_unlock(&phone->callee->lock); |
|
- | 207 | } |
|
- | 208 | mutex_unlock(&phone->lock); |
|
- | 209 | } |
|
- | 210 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME) { |
|
- | 211 | phone_t *phone = (phone_t *)IPC_GET_ARG5(*olddata); |
|
- | 212 | if (IPC_GET_RETVAL(answer->data) != EOK) { |
|
- | 213 | /* |
|
- | 214 | * The other party on the cloned phoned rejected our |
|
- | 215 | * request for connection on the protocol level. |
|
- | 216 | * We need to break the connection without sending |
|
- | 217 | * IPC_M_HUNGUP back. |
|
- | 218 | */ |
|
- | 219 | mutex_lock(&phone->lock); |
|
- | 220 | if (phone->state == IPC_PHONE_CONNECTED) { |
|
- | 221 | spinlock_lock(&phone->callee->lock); |
|
- | 222 | list_remove(&phone->link); |
|
- | 223 | phone->state = IPC_PHONE_SLAMMED; |
|
- | 224 | spinlock_unlock(&phone->callee->lock); |
|
- | 225 | } |
|
- | 226 | mutex_unlock(&phone->lock); |
|
- | 227 | } |
|
185 | if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { |
228 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { |
186 | phoneid = IPC_GET_ARG5(*olddata); |
229 | phoneid = IPC_GET_ARG5(*olddata); |
187 | if (IPC_GET_RETVAL(answer->data)) { |
230 | if (IPC_GET_RETVAL(answer->data) != EOK) { |
188 | /* The connection was not accepted */ |
231 | /* The connection was not accepted */ |
189 | phone_dealloc(phoneid); |
232 | phone_dealloc(phoneid); |
190 | } else { |
233 | } else { |
191 | /* The connection was accepted */ |
234 | /* The connection was accepted */ |
192 | phone_connect(phoneid, &answer->sender->answerbox); |
235 | phone_connect(phoneid, &answer->sender->answerbox); |
Line 194... | Line 237... | ||
194 | IPC_SET_ARG5(answer->data, |
237 | IPC_SET_ARG5(answer->data, |
195 | (unative_t) &TASK->phones[phoneid]); |
238 | (unative_t) &TASK->phones[phoneid]); |
196 | } |
239 | } |
197 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) { |
240 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) { |
198 | /* If the users accepted call, connect */ |
241 | /* If the users accepted call, connect */ |
199 | if (!IPC_GET_RETVAL(answer->data)) { |
242 | if (IPC_GET_RETVAL(answer->data) == EOK) { |
200 | ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), |
243 | ipc_phone_connect((phone_t *) IPC_GET_ARG5(*olddata), |
201 | &TASK->answerbox); |
244 | &TASK->answerbox); |
202 | } |
245 | } |
203 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_OUT) { |
246 | } else if (IPC_GET_METHOD(*olddata) == IPC_M_SHARE_OUT) { |
204 | if (!IPC_GET_RETVAL(answer->data)) { |
247 | if (!IPC_GET_RETVAL(answer->data)) { |
Line 291... | Line 334... | ||
291 | answer->buffer = NULL; |
334 | answer->buffer = NULL; |
292 | } |
335 | } |
293 | return 0; |
336 | return 0; |
294 | } |
337 | } |
295 | 338 | ||
- | 339 | static void phones_lock(phone_t *p1, phone_t *p2) |
|
- | 340 | { |
|
- | 341 | if (p1 < p2) { |
|
- | 342 | mutex_lock(&p1->lock); |
|
- | 343 | mutex_lock(&p2->lock); |
|
- | 344 | } else if (p1 > p2) { |
|
- | 345 | mutex_lock(&p2->lock); |
|
- | 346 | mutex_lock(&p1->lock); |
|
- | 347 | } else { |
|
- | 348 | mutex_lock(&p1->lock); |
|
- | 349 | } |
|
- | 350 | } |
|
- | 351 | ||
- | 352 | static void phones_unlock(phone_t *p1, phone_t *p2) |
|
- | 353 | { |
|
- | 354 | mutex_unlock(&p1->lock); |
|
- | 355 | if (p1 != p2) |
|
- | 356 | mutex_unlock(&p2->lock); |
|
- | 357 | } |
|
- | 358 | ||
296 | /** Called before the request is sent. |
359 | /** Called before the request is sent. |
297 | * |
360 | * |
298 | * @param call Call structure with the request. |
361 | * @param call Call structure with the request. |
299 | * @param phone Phone that the call will be sent through. |
362 | * @param phone Phone that the call will be sent through. |
300 | * |
363 | * |
Line 306... | Line 369... | ||
306 | size_t size; |
369 | size_t size; |
307 | uintptr_t src; |
370 | uintptr_t src; |
308 | int rc; |
371 | int rc; |
309 | 372 | ||
310 | switch (IPC_GET_METHOD(call->data)) { |
373 | switch (IPC_GET_METHOD(call->data)) { |
- | 374 | case IPC_M_CONNECTION_CLONE: { |
|
- | 375 | phone_t *cloned_phone; |
|
- | 376 | GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data), |
|
- | 377 | return ENOENT); |
|
- | 378 | phones_lock(cloned_phone, phone); |
|
- | 379 | if ((cloned_phone->state != IPC_PHONE_CONNECTED) || |
|
- | 380 | phone->state != IPC_PHONE_CONNECTED) { |
|
- | 381 | phones_unlock(cloned_phone, phone); |
|
- | 382 | return EINVAL; |
|
- | 383 | } |
|
- | 384 | /* |
|
- | 385 | * We can be pretty sure now that both tasks exist and we are |
|
- | 386 | * connected to them. As we continue to hold the phone locks, |
|
- | 387 | * we are effectively preventing them from finishing their |
|
- | 388 | * potential cleanup. |
|
- | 389 | */ |
|
- | 390 | newphid = phone_alloc(phone->callee->task); |
|
- | 391 | if (newphid < 0) { |
|
- | 392 | phones_unlock(cloned_phone, phone); |
|
- | 393 | return ELIMIT; |
|
- | 394 | } |
|
- | 395 | ipc_phone_connect(&phone->callee->task->phones[newphid], |
|
- | 396 | cloned_phone->callee); |
|
- | 397 | phones_unlock(cloned_phone, phone); |
|
- | 398 | /* Set the new phone for the callee. */ |
|
- | 399 | IPC_SET_ARG1(call->data, newphid); |
|
- | 400 | break; |
|
- | 401 | } |
|
- | 402 | case IPC_M_CONNECT_ME: |
|
- | 403 | IPC_SET_ARG5(call->data, (unative_t) phone); |
|
- | 404 | break; |
|
311 | case IPC_M_CONNECT_ME_TO: |
405 | case IPC_M_CONNECT_ME_TO: |
312 | newphid = phone_alloc(); |
406 | newphid = phone_alloc(TASK); |
313 | if (newphid < 0) |
407 | if (newphid < 0) |
314 | return ELIMIT; |
408 | return ELIMIT; |
315 | /* Set arg5 for server */ |
409 | /* Set arg5 for server */ |
316 | IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]); |
410 | IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]); |
317 | call->flags |= IPC_CALL_CONN_ME_TO; |
411 | call->flags |= IPC_CALL_CONN_ME_TO; |
Line 397... | Line 491... | ||
397 | static int process_request(answerbox_t *box, call_t *call) |
491 | static int process_request(answerbox_t *box, call_t *call) |
398 | { |
492 | { |
399 | int phoneid; |
493 | int phoneid; |
400 | 494 | ||
401 | if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) { |
495 | if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) { |
402 | phoneid = phone_alloc(); |
496 | phoneid = phone_alloc(TASK); |
403 | if (phoneid < 0) { /* Failed to allocate phone */ |
497 | if (phoneid < 0) { /* Failed to allocate phone */ |
404 | IPC_SET_RETVAL(call->data, ELIMIT); |
498 | IPC_SET_RETVAL(call->data, ELIMIT); |
405 | ipc_answer(box, call); |
499 | ipc_answer(box, call); |
406 | return -1; |
500 | return -1; |
407 | } |
501 | } |