Rev 4348 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4348 | Rev 4691 | ||
|---|---|---|---|
| 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 | } |