Subversion Repositories HelenOS

Rev

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

Rev 4055 Rev 4420
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 306... Line 349...
306
    size_t size;
349
    size_t size;
307
    uintptr_t src;
350
    uintptr_t src;
308
    int rc;
351
    int rc;
309
 
352
 
310
    switch (IPC_GET_METHOD(call->data)) {
353
    switch (IPC_GET_METHOD(call->data)) {
-
 
354
    case IPC_M_CONNECTION_CLONE: {
-
 
355
        phone_t *cloned_phone;
-
 
356
        GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
-
 
357
            return ENOENT);
-
 
358
        if (cloned_phone < phone) {
-
 
359
            mutex_lock(&cloned_phone->lock);
-
 
360
            mutex_lock(&phone->lock);
-
 
361
        } else {
-
 
362
            mutex_lock(&phone->lock);
-
 
363
            mutex_lock(&cloned_phone->lock);
-
 
364
        }
-
 
365
        if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
-
 
366
            phone->state != IPC_PHONE_CONNECTED) {
-
 
367
            mutex_unlock(&cloned_phone->lock);
-
 
368
            mutex_unlock(&phone->lock);
-
 
369
            return EINVAL;
-
 
370
        }
-
 
371
        /*
-
 
372
         * We can be pretty sure now that both tasks exist and we are
-
 
373
         * connected to them. As we continue to hold the phone locks,
-
 
374
         * we are effectively preventing them from finishing their
-
 
375
         * potential cleanup.
-
 
376
         */
-
 
377
        newphid = phone_alloc(phone->callee->task);
-
 
378
        if (newphid < 0) {
-
 
379
            mutex_unlock(&cloned_phone->lock);
-
 
380
            mutex_unlock(&phone->lock);
-
 
381
            return ELIMIT;
-
 
382
        }
-
 
383
        ipc_phone_connect(&phone->callee->task->phones[newphid],
-
 
384
            cloned_phone->callee);
-
 
385
        mutex_unlock(&cloned_phone->lock);
-
 
386
        mutex_unlock(&phone->lock);
-
 
387
        /* Set the new phone for the callee. */
-
 
388
        IPC_SET_ARG1(call->data, newphid);
-
 
389
        break;
-
 
390
    }
-
 
391
    case IPC_M_CONNECT_ME:
-
 
392
        IPC_SET_ARG5(call->data, (unative_t) phone);
-
 
393
        break;
311
    case IPC_M_CONNECT_ME_TO:
394
    case IPC_M_CONNECT_ME_TO:
312
        newphid = phone_alloc();
395
        newphid = phone_alloc(TASK);
313
        if (newphid < 0)
396
        if (newphid < 0)
314
            return ELIMIT;
397
            return ELIMIT;
315
        /* Set arg5 for server */
398
        /* Set arg5 for server */
316
        IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
399
        IPC_SET_ARG5(call->data, (unative_t) &TASK->phones[newphid]);
317
        call->flags |= IPC_CALL_CONN_ME_TO;
400
        call->flags |= IPC_CALL_CONN_ME_TO;
Line 330... Line 413...
330
        break;
413
        break;
331
    case IPC_M_DATA_WRITE:
414
    case IPC_M_DATA_WRITE:
332
        src = IPC_GET_ARG1(call->data);
415
        src = IPC_GET_ARG1(call->data);
333
        size = IPC_GET_ARG2(call->data);
416
        size = IPC_GET_ARG2(call->data);
334
       
417
       
335
        if ((size <= 0) || (size > DATA_XFER_LIMIT))
418
        if (size > DATA_XFER_LIMIT)
336
            return ELIMIT;
419
            return ELIMIT;
337
       
420
       
338
        call->buffer = (uint8_t *) malloc(size, 0);
421
        call->buffer = (uint8_t *) malloc(size, 0);
339
        rc = copy_from_uspace(call->buffer, (void *) src, size);
422
        rc = copy_from_uspace(call->buffer, (void *) src, size);
340
        if (rc != 0) {
423
        if (rc != 0) {
Line 397... Line 480...
397
static int process_request(answerbox_t *box, call_t *call)
480
static int process_request(answerbox_t *box, call_t *call)
398
{
481
{
399
    int phoneid;
482
    int phoneid;
400
 
483
 
401
    if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
484
    if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) {
402
        phoneid = phone_alloc();
485
        phoneid = phone_alloc(TASK);
403
        if (phoneid < 0) { /* Failed to allocate phone */
486
        if (phoneid < 0) { /* Failed to allocate phone */
404
            IPC_SET_RETVAL(call->data, ELIMIT);
487
            IPC_SET_RETVAL(call->data, ELIMIT);
405
            ipc_answer(box, call);
488
            ipc_answer(box, call);
406
            return -1;
489
            return -1;
407
        }
490
        }