~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.1.0/pjlib/src/pj/ioqueue_symbian.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: ioqueue_symbian.cpp 4374 2013-02-27 07:15:57Z riza $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pj/ioqueue.h>
 
21
#include <pj/assert.h>
 
22
#include <pj/errno.h>
 
23
#include <pj/list.h>
 
24
#include <pj/lock.h>
 
25
#include <pj/pool.h>
 
26
#include <pj/string.h>
 
27
 
 
28
#include "os_symbian.h"
 
29
 
 
30
class CIoqueueCallback;
 
31
 
 
32
/*
 
33
 * IO Queue structure.
 
34
 */
 
35
struct pj_ioqueue_t
 
36
{
 
37
    int              eventCount;
 
38
};
 
39
 
 
40
 
 
41
/////////////////////////////////////////////////////////////////////////////
 
42
// Class to encapsulate asynchronous socket operation.
 
43
//
 
44
class CIoqueueCallback : public CActive
 
45
{
 
46
public:
 
47
    static CIoqueueCallback* NewL(pj_ioqueue_t *ioqueue,
 
48
                                  pj_ioqueue_key_t *key, 
 
49
                                  pj_sock_t sock, 
 
50
                                  const pj_ioqueue_callback *cb, 
 
51
                                  void *user_data);
 
52
 
 
53
    //
 
54
    // Start asynchronous recv() operation
 
55
    //
 
56
    pj_status_t StartRead(pj_ioqueue_op_key_t *op_key, 
 
57
                          void *buf, pj_ssize_t *size, unsigned flags,
 
58
                          pj_sockaddr_t *addr, int *addrlen);
 
59
 
 
60
    //
 
61
    // Start asynchronous accept() operation.
 
62
    //
 
63
    pj_status_t StartAccept(pj_ioqueue_op_key_t *op_key,
 
64
                            pj_sock_t *new_sock,
 
65
                            pj_sockaddr_t *local,
 
66
                            pj_sockaddr_t *remote,
 
67
                            int *addrlen );
 
68
 
 
69
    //
 
70
    // Completion callback.
 
71
    //
 
72
    void RunL();
 
73
 
 
74
    //
 
75
    // CActive's DoCancel()
 
76
    //
 
77
    void DoCancel();
 
78
 
 
79
    //
 
80
    // Cancel operation and call callback.
 
81
    //
 
82
    void CancelOperation(pj_ioqueue_op_key_t *op_key, 
 
83
                         pj_ssize_t bytes_status);
 
84
 
 
85
    //
 
86
    // Accessors
 
87
    //
 
88
    void* get_user_data() const
 
89
    {
 
90
        return user_data_;
 
91
    }
 
92
    void set_user_data(void *user_data)
 
93
    {
 
94
        user_data_ = user_data;
 
95
    }
 
96
    pj_ioqueue_op_key_t *get_op_key() const
 
97
    {
 
98
        return pending_data_.common_.op_key_;
 
99
    }
 
100
    CPjSocket* get_pj_socket()
 
101
    {
 
102
        return sock_;
 
103
    }
 
104
 
 
105
private:
 
106
    // Type of pending operation.
 
107
    enum Type {
 
108
        TYPE_NONE,
 
109
        TYPE_READ,
 
110
        TYPE_ACCEPT,
 
111
    };
 
112
 
 
113
    // Static data.
 
114
    pj_ioqueue_t                *ioqueue_;
 
115
    pj_ioqueue_key_t            *key_;
 
116
    CPjSocket                   *sock_;
 
117
    pj_ioqueue_callback          cb_;
 
118
    void                        *user_data_;
 
119
 
 
120
    // Symbian data.
 
121
    TPtr8                        aBufferPtr_;
 
122
    TInetAddr                    aAddress_;
 
123
 
 
124
    // Application data.
 
125
    Type                         type_;
 
126
 
 
127
    union Pending_Data
 
128
    {
 
129
        struct Common
 
130
        {
 
131
            pj_ioqueue_op_key_t *op_key_;
 
132
        } common_;
 
133
 
 
134
        struct Pending_Read
 
135
        {
 
136
            pj_ioqueue_op_key_t *op_key_;
 
137
            pj_sockaddr_t       *addr_;
 
138
            int                 *addrlen_;
 
139
        } read_;
 
140
 
 
141
        struct Pending_Accept
 
142
        {
 
143
            pj_ioqueue_op_key_t *op_key_;
 
144
            pj_sock_t           *new_sock_;
 
145
            pj_sockaddr_t       *local_;
 
146
            pj_sockaddr_t       *remote_;
 
147
            int                 *addrlen_;
 
148
        } accept_;
 
149
    };
 
150
 
 
151
    union Pending_Data           pending_data_;
 
152
    RSocket                     blank_sock_;
 
153
 
 
154
    CIoqueueCallback(pj_ioqueue_t *ioqueue,
 
155
                     pj_ioqueue_key_t *key, pj_sock_t sock, 
 
156
                     const pj_ioqueue_callback *cb, void *user_data)
 
157
    : CActive(CActive::EPriorityStandard),
 
158
          ioqueue_(ioqueue), key_(key), sock_((CPjSocket*)sock), 
 
159
          user_data_(user_data), aBufferPtr_(NULL, 0), type_(TYPE_NONE)
 
160
    {
 
161
        pj_memcpy(&cb_, cb, sizeof(*cb));
 
162
    }
 
163
 
 
164
 
 
165
    void ConstructL()
 
166
    {
 
167
        CActiveScheduler::Add(this);
 
168
    }
 
169
    
 
170
    void HandleReadCompletion();
 
171
    CPjSocket *HandleAcceptCompletion();
 
172
};
 
173
 
 
174
 
 
175
CIoqueueCallback* CIoqueueCallback::NewL(pj_ioqueue_t *ioqueue,
 
176
                                         pj_ioqueue_key_t *key, 
 
177
                                         pj_sock_t sock, 
 
178
                                         const pj_ioqueue_callback *cb, 
 
179
                                         void *user_data)
 
180
{
 
181
    CIoqueueCallback *self = new CIoqueueCallback(ioqueue, key, sock, 
 
182
                                                  cb, user_data);
 
183
    CleanupStack::PushL(self);
 
184
    self->ConstructL();
 
185
    CleanupStack::Pop(self);
 
186
 
 
187
    return self;
 
188
}
 
189
 
 
190
 
 
191
//
 
192
// Start asynchronous recv() operation
 
193
//
 
194
pj_status_t CIoqueueCallback::StartRead(pj_ioqueue_op_key_t *op_key, 
 
195
                                        void *buf, pj_ssize_t *size, 
 
196
                                        unsigned flags,
 
197
                                        pj_sockaddr_t *addr, int *addrlen)
 
198
{
 
199
    PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY);
 
200
    PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY);
 
201
 
 
202
    flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
 
203
 
 
204
    pending_data_.read_.op_key_ = op_key;
 
205
    pending_data_.read_.addr_ = addr;
 
206
    pending_data_.read_.addrlen_ = addrlen;
 
207
 
 
208
    aBufferPtr_.Set((TUint8*)buf, 0, (TInt)*size);
 
209
 
 
210
    type_ = TYPE_READ;
 
211
    if (addr && addrlen) {
 
212
        sock_->Socket().RecvFrom(aBufferPtr_, aAddress_, flags, iStatus);
 
213
    } else {
 
214
        aAddress_.SetAddress(0);
 
215
        aAddress_.SetPort(0);
 
216
 
 
217
        if (sock_->IsDatagram()) {
 
218
            sock_->Socket().Recv(aBufferPtr_, flags, iStatus);
 
219
        } else {
 
220
            // Using static like this is not pretty, but we don't need to use
 
221
            // the value anyway, hence doing it like this is probably most
 
222
            // optimal.
 
223
            static TSockXfrLength len;
 
224
            sock_->Socket().RecvOneOrMore(aBufferPtr_, flags, iStatus, len);
 
225
        }
 
226
    }
 
227
 
 
228
    SetActive();
 
229
    return PJ_EPENDING;
 
230
}
 
231
 
 
232
 
 
233
//
 
234
// Start asynchronous accept() operation.
 
235
//
 
236
pj_status_t CIoqueueCallback::StartAccept(pj_ioqueue_op_key_t *op_key,
 
237
                                          pj_sock_t *new_sock,
 
238
                                          pj_sockaddr_t *local,
 
239
                                          pj_sockaddr_t *remote,
 
240
                                          int *addrlen )
 
241
{
 
242
    PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY);
 
243
    PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY);
 
244
 
 
245
    // addrlen must be specified if local or remote is specified
 
246
    PJ_ASSERT_RETURN((!local && !remote) ||
 
247
                     (addrlen && *addrlen), PJ_EINVAL);
 
248
    
 
249
    pending_data_.accept_.op_key_ = op_key;
 
250
    pending_data_.accept_.new_sock_ = new_sock;
 
251
    pending_data_.accept_.local_ = local;
 
252
    pending_data_.accept_.remote_ = remote;
 
253
    pending_data_.accept_.addrlen_ = addrlen;
 
254
 
 
255
    // Create blank socket
 
256
    blank_sock_.Open(PjSymbianOS::Instance()->SocketServ());
 
257
 
 
258
    type_ = TYPE_ACCEPT;
 
259
    sock_->Socket().Accept(blank_sock_, iStatus);
 
260
 
 
261
    SetActive();
 
262
    return PJ_EPENDING;
 
263
}
 
264
 
 
265
 
 
266
//
 
267
// Handle asynchronous RecvFrom() completion
 
268
//
 
269
void CIoqueueCallback::HandleReadCompletion() 
 
270
{
 
271
    if (pending_data_.read_.addr_ && pending_data_.read_.addrlen_) {
 
272
        PjSymbianOS::Addr2pj(aAddress_, 
 
273
                             *(pj_sockaddr*)pending_data_.read_.addr_,
 
274
                             pending_data_.read_.addrlen_);
 
275
        pending_data_.read_.addr_ = NULL;
 
276
        pending_data_.read_.addrlen_ = NULL;
 
277
    }
 
278
        
 
279
    pending_data_.read_.op_key_ = NULL;
 
280
}
 
281
 
 
282
 
 
283
//
 
284
// Handle asynchronous Accept() completion.
 
285
//
 
286
CPjSocket *CIoqueueCallback::HandleAcceptCompletion() 
 
287
{
 
288
        CPjSocket *pjNewSock = new CPjSocket(get_pj_socket()->GetAf(), 
 
289
                                             get_pj_socket()->GetSockType(),
 
290
                                             blank_sock_);
 
291
        int addrlen = 0;
 
292
        
 
293
        if (pending_data_.accept_.new_sock_) {
 
294
            *pending_data_.accept_.new_sock_ = (pj_sock_t)pjNewSock;
 
295
            pending_data_.accept_.new_sock_ = NULL;
 
296
        }
 
297
 
 
298
        if (pending_data_.accept_.local_) {
 
299
            TInetAddr aAddr;
 
300
            pj_sockaddr *ptr_sockaddr;
 
301
            
 
302
            blank_sock_.LocalName(aAddr);
 
303
            ptr_sockaddr = (pj_sockaddr*)pending_data_.accept_.local_;
 
304
            addrlen = *pending_data_.accept_.addrlen_;
 
305
            PjSymbianOS::Addr2pj(aAddr, *ptr_sockaddr, &addrlen);
 
306
            pending_data_.accept_.local_ = NULL;
 
307
        }
 
308
 
 
309
        if (pending_data_.accept_.remote_) {
 
310
            TInetAddr aAddr;
 
311
            pj_sockaddr *ptr_sockaddr;
 
312
 
 
313
            blank_sock_.RemoteName(aAddr);
 
314
            ptr_sockaddr = (pj_sockaddr*)pending_data_.accept_.remote_;
 
315
            addrlen = *pending_data_.accept_.addrlen_;
 
316
            PjSymbianOS::Addr2pj(aAddr, *ptr_sockaddr, &addrlen);
 
317
            pending_data_.accept_.remote_ = NULL;
 
318
        }
 
319
 
 
320
        if (pending_data_.accept_.addrlen_) {
 
321
            if (addrlen == 0) {
 
322
                if (pjNewSock->GetAf() == PJ_AF_INET)
 
323
                    addrlen = sizeof(pj_sockaddr_in);
 
324
                else if (pjNewSock->GetAf() == PJ_AF_INET6)
 
325
                    addrlen = sizeof(pj_sockaddr_in6);
 
326
                else {
 
327
                    pj_assert(!"Unsupported address family");
 
328
                }
 
329
            }
 
330
            *pending_data_.accept_.addrlen_ = addrlen;
 
331
            pending_data_.accept_.addrlen_ = NULL;
 
332
        }
 
333
        
 
334
        return pjNewSock;
 
335
}
 
336
 
 
337
 
 
338
//
 
339
// Completion callback.
 
340
//
 
341
void CIoqueueCallback::RunL()
 
342
{
 
343
    pj_ioqueue_t *ioq = ioqueue_;
 
344
    Type cur_type = type_;
 
345
 
 
346
    type_ = TYPE_NONE;
 
347
 
 
348
    if (cur_type == TYPE_READ) {
 
349
        //
 
350
        // Completion of asynchronous RecvFrom()
 
351
        //
 
352
 
 
353
        /* Clear op_key (save it to temp variable first!) */
 
354
        pj_ioqueue_op_key_t     *op_key = pending_data_.read_.op_key_;
 
355
        pending_data_.read_.op_key_ = NULL;
 
356
 
 
357
        // Handle failure condition
 
358
        if (iStatus != KErrNone) {
 
359
            if (cb_.on_read_complete) {
 
360
                cb_.on_read_complete( key_, op_key, 
 
361
                                      -PJ_RETURN_OS_ERROR(iStatus.Int()));
 
362
            }
 
363
            return;
 
364
        }
 
365
 
 
366
        HandleReadCompletion();
 
367
 
 
368
        /* Call callback */
 
369
        if (cb_.on_read_complete) {
 
370
            cb_.on_read_complete(key_, op_key, aBufferPtr_.Length());
 
371
        }
 
372
 
 
373
    } else if (cur_type == TYPE_ACCEPT) {
 
374
        //
 
375
        // Completion of asynchronous Accept()
 
376
        //
 
377
        
 
378
        /* Clear op_key (save it to temp variable first!) */
 
379
        pj_ioqueue_op_key_t     *op_key = pending_data_.read_.op_key_;
 
380
        pending_data_.read_.op_key_ = NULL;
 
381
 
 
382
        // Handle failure condition
 
383
        if (iStatus != KErrNone) {
 
384
            if (pending_data_.accept_.new_sock_)
 
385
                *pending_data_.accept_.new_sock_ = PJ_INVALID_SOCKET;
 
386
            
 
387
            if (cb_.on_accept_complete) {
 
388
                cb_.on_accept_complete( key_, op_key, PJ_INVALID_SOCKET,
 
389
                                        -PJ_RETURN_OS_ERROR(iStatus.Int()));
 
390
            }
 
391
            return;
 
392
        }
 
393
 
 
394
        CPjSocket *pjNewSock = HandleAcceptCompletion();
 
395
        
 
396
        // Call callback.
 
397
        if (cb_.on_accept_complete) {
 
398
            cb_.on_accept_complete( key_, op_key, (pj_sock_t)pjNewSock, 
 
399
                                    PJ_SUCCESS);
 
400
        }
 
401
    }
 
402
 
 
403
    ioq->eventCount++;
 
404
}
 
405
 
 
406
//
 
407
// CActive's DoCancel()
 
408
//
 
409
void CIoqueueCallback::DoCancel()
 
410
{
 
411
    if (type_ == TYPE_READ)
 
412
        sock_->Socket().CancelRecv();
 
413
    else if (type_ == TYPE_ACCEPT)
 
414
        sock_->Socket().CancelAccept();
 
415
 
 
416
    type_ = TYPE_NONE;
 
417
    pending_data_.common_.op_key_ = NULL;
 
418
}
 
419
 
 
420
//
 
421
// Cancel operation and call callback.
 
422
//
 
423
void CIoqueueCallback::CancelOperation(pj_ioqueue_op_key_t *op_key, 
 
424
                                       pj_ssize_t bytes_status)
 
425
{
 
426
    Type cur_type = type_;
 
427
 
 
428
    pj_assert(op_key == pending_data_.common_.op_key_);
 
429
 
 
430
    Cancel();
 
431
 
 
432
    if (cur_type == TYPE_READ) {
 
433
        if (cb_.on_read_complete)
 
434
            cb_.on_read_complete(key_, op_key, bytes_status);
 
435
    } else if (cur_type == TYPE_ACCEPT)
 
436
        ;    
 
437
}
 
438
 
 
439
 
 
440
/////////////////////////////////////////////////////////////////////////////
 
441
/*
 
442
 * IO Queue key structure.
 
443
 */
 
444
struct pj_ioqueue_key_t
 
445
{
 
446
    CIoqueueCallback    *cbObj;
 
447
};
 
448
 
 
449
 
 
450
/*
 
451
 * Return the name of the ioqueue implementation.
 
452
 */
 
453
PJ_DEF(const char*) pj_ioqueue_name(void)
 
454
{
 
455
    return "ioqueue-symbian";
 
456
}
 
457
 
 
458
 
 
459
/*
 
460
 * Create a new I/O Queue framework.
 
461
 */
 
462
PJ_DEF(pj_status_t) pj_ioqueue_create(  pj_pool_t *pool, 
 
463
                                        pj_size_t max_fd,
 
464
                                        pj_ioqueue_t **p_ioqueue)
 
465
{
 
466
    pj_ioqueue_t *ioq;
 
467
 
 
468
    PJ_UNUSED_ARG(max_fd);
 
469
 
 
470
    ioq = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_t);
 
471
    *p_ioqueue = ioq;
 
472
    return PJ_SUCCESS;
 
473
}
 
474
 
 
475
 
 
476
/*
 
477
 * Destroy the I/O queue.
 
478
 */
 
479
PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioq )
 
480
{
 
481
    PJ_UNUSED_ARG(ioq);
 
482
    return PJ_SUCCESS;
 
483
}
 
484
 
 
485
 
 
486
/*
 
487
 * Set the lock object to be used by the I/O Queue. 
 
488
 */
 
489
PJ_DEF(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioq, 
 
490
                                         pj_lock_t *lock,
 
491
                                         pj_bool_t auto_delete )
 
492
{
 
493
    /* Don't really need lock for now */
 
494
    PJ_UNUSED_ARG(ioq);
 
495
    
 
496
    if (auto_delete) {
 
497
        pj_lock_destroy(lock);
 
498
    }
 
499
 
 
500
    return PJ_SUCCESS;
 
501
}
 
502
 
 
503
PJ_DEF(pj_status_t) pj_ioqueue_set_default_concurrency(pj_ioqueue_t *ioqueue,
 
504
                                                                                                           pj_bool_t allow)
 
505
{
 
506
        /* Not supported, just return PJ_SUCCESS silently */
 
507
        PJ_UNUSED_ARG(ioqueue);
 
508
        PJ_UNUSED_ARG(allow);
 
509
        return PJ_SUCCESS;
 
510
}
 
511
 
 
512
/*
 
513
 * Register a socket to the I/O queue framework. 
 
514
 */
 
515
PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool,
 
516
                                              pj_ioqueue_t *ioq,
 
517
                                              pj_sock_t sock,
 
518
                                              void *user_data,
 
519
                                              const pj_ioqueue_callback *cb,
 
520
                                              pj_ioqueue_key_t **p_key )
 
521
{
 
522
    pj_ioqueue_key_t *key;
 
523
 
 
524
    key = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_key_t);
 
525
    key->cbObj = CIoqueueCallback::NewL(ioq, key, sock, cb, user_data);
 
526
 
 
527
    *p_key = key;
 
528
    return PJ_SUCCESS;
 
529
}
 
530
 
 
531
PJ_DEF(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool,
 
532
                                              pj_ioqueue_t *ioqueue,
 
533
                                              pj_sock_t sock,
 
534
                                              pj_grp_lock_t *grp_lock,
 
535
                                              void *user_data,
 
536
                                              const pj_ioqueue_callback *cb,
 
537
                                              pj_ioqueue_key_t **p_key)
 
538
{
 
539
    PJ_UNUSED_ARG(grp_lock);
 
540
 
 
541
    return pj_ioqueue_register_sock(pool, ioqueue, sock, user_data, cb, p_key);
 
542
}
 
543
 
 
544
/*
 
545
 * Unregister from the I/O Queue framework. 
 
546
 */
 
547
PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key )
 
548
{
 
549
    if (key == NULL || key->cbObj == NULL)
 
550
        return PJ_SUCCESS;
 
551
 
 
552
    // Cancel pending async object
 
553
    if (key->cbObj) {
 
554
        key->cbObj->Cancel();
 
555
    }
 
556
 
 
557
    // Close socket.
 
558
    key->cbObj->get_pj_socket()->Socket().Close();
 
559
    delete key->cbObj->get_pj_socket();
 
560
 
 
561
    // Delete async object.
 
562
    if (key->cbObj) {
 
563
        delete key->cbObj;
 
564
        key->cbObj = NULL;
 
565
    }
 
566
 
 
567
    return PJ_SUCCESS;
 
568
}
 
569
 
 
570
 
 
571
/*
 
572
 * Get user data associated with an ioqueue key.
 
573
 */
 
574
PJ_DEF(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key )
 
575
{
 
576
    return key->cbObj->get_user_data();
 
577
}
 
578
 
 
579
 
 
580
/*
 
581
 * Set or change the user data to be associated with the file descriptor or
 
582
 * handle or socket descriptor.
 
583
 */
 
584
PJ_DEF(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key,
 
585
                                              void *user_data,
 
586
                                              void **old_data)
 
587
{
 
588
    if (old_data)
 
589
        *old_data = key->cbObj->get_user_data();
 
590
    key->cbObj->set_user_data(user_data);
 
591
 
 
592
    return PJ_SUCCESS;
 
593
}
 
594
 
 
595
 
 
596
/*
 
597
 * Initialize operation key.
 
598
 */
 
599
PJ_DEF(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
 
600
                                     pj_size_t size )
 
601
{
 
602
    pj_bzero(op_key, size);
 
603
}
 
604
 
 
605
 
 
606
/*
 
607
 * Check if operation is pending on the specified operation key.
 
608
 */
 
609
PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
 
610
                                         pj_ioqueue_op_key_t *op_key )
 
611
{
 
612
    return key->cbObj->get_op_key()==op_key &&
 
613
           key->cbObj->IsActive();
 
614
}
 
615
 
 
616
 
 
617
/*
 
618
 * Post completion status to the specified operation key and call the
 
619
 * appropriate callback. 
 
620
 */
 
621
PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,
 
622
                                                pj_ioqueue_op_key_t *op_key,
 
623
                                                pj_ssize_t bytes_status )
 
624
{
 
625
    if (pj_ioqueue_is_pending(key, op_key)) {
 
626
        key->cbObj->CancelOperation(op_key, bytes_status);
 
627
    }
 
628
    return PJ_SUCCESS;
 
629
}
 
630
 
 
631
 
 
632
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
 
633
/**
 
634
 * Instruct I/O Queue to accept incoming connection on the specified 
 
635
 * listening socket.
 
636
 */
 
637
PJ_DEF(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key,
 
638
                                       pj_ioqueue_op_key_t *op_key,
 
639
                                       pj_sock_t *new_sock,
 
640
                                       pj_sockaddr_t *local,
 
641
                                       pj_sockaddr_t *remote,
 
642
                                       int *addrlen )
 
643
{
 
644
    
 
645
    return key->cbObj->StartAccept(op_key, new_sock, local, remote, addrlen);
 
646
}
 
647
 
 
648
 
 
649
/*
 
650
 * Initiate non-blocking socket connect.
 
651
 */
 
652
PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
 
653
                                        const pj_sockaddr_t *addr,
 
654
                                        int addrlen )
 
655
{
 
656
    pj_status_t status;
 
657
    
 
658
    RSocket &rSock = key->cbObj->get_pj_socket()->Socket();
 
659
    TInetAddr inetAddr;
 
660
    TRequestStatus reqStatus;
 
661
 
 
662
    // Return failure if access point is marked as down by app.
 
663
    PJ_SYMBIAN_CHECK_CONNECTION();
 
664
    
 
665
    // Convert address
 
666
    status = PjSymbianOS::pj2Addr(*(const pj_sockaddr*)addr, addrlen, 
 
667
                                  inetAddr);
 
668
    if (status != PJ_SUCCESS)
 
669
        return status;
 
670
    
 
671
    // We don't support async connect for now.
 
672
    PJ_TODO(IOQUEUE_SUPPORT_ASYNC_CONNECT);
 
673
 
 
674
    rSock.Connect(inetAddr, reqStatus);
 
675
    User::WaitForRequest(reqStatus);
 
676
 
 
677
    if (reqStatus == KErrNone)
 
678
        return PJ_SUCCESS;
 
679
 
 
680
    return PJ_RETURN_OS_ERROR(reqStatus.Int());
 
681
}
 
682
 
 
683
 
 
684
#endif  /* PJ_HAS_TCP */
 
685
 
 
686
/*
 
687
 * Poll the I/O Queue for completed events.
 
688
 */
 
689
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioq,
 
690
                             const pj_time_val *timeout)
 
691
{
 
692
    /* Polling is not necessary on Symbian, since all async activities
 
693
     * are registered to active scheduler.
 
694
     */
 
695
    PJ_UNUSED_ARG(ioq);
 
696
    PJ_UNUSED_ARG(timeout);
 
697
    return 0;
 
698
}
 
699
 
 
700
 
 
701
/*
 
702
 * Instruct the I/O Queue to read from the specified handle.
 
703
 */
 
704
PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
 
705
                                     pj_ioqueue_op_key_t *op_key,
 
706
                                     void *buffer,
 
707
                                     pj_ssize_t *length,
 
708
                                     pj_uint32_t flags )
 
709
{
 
710
    // If socket has reader, delete it.
 
711
    if (key->cbObj->get_pj_socket()->Reader())
 
712
        key->cbObj->get_pj_socket()->DestroyReader();
 
713
    
 
714
    // Clear flag
 
715
    flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
 
716
    return key->cbObj->StartRead(op_key, buffer, length, flags, NULL, NULL);
 
717
}
 
718
 
 
719
 
 
720
/*
 
721
 * This function behaves similarly as #pj_ioqueue_recv(), except that it is
 
722
 * normally called for socket, and the remote address will also be returned
 
723
 * along with the data.
 
724
 */
 
725
PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
 
726
                                         pj_ioqueue_op_key_t *op_key,
 
727
                                         void *buffer,
 
728
                                         pj_ssize_t *length,
 
729
                                         pj_uint32_t flags,
 
730
                                         pj_sockaddr_t *addr,
 
731
                                         int *addrlen)
 
732
{
 
733
    CPjSocket *sock = key->cbObj->get_pj_socket();
 
734
    
 
735
    // If address is specified, check that the length match the
 
736
    // address family
 
737
    if (addr || addrlen) {
 
738
        PJ_ASSERT_RETURN(addr && addrlen && *addrlen, PJ_EINVAL);
 
739
        if (sock->GetAf() == PJ_AF_INET) {
 
740
            PJ_ASSERT_RETURN(*addrlen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);
 
741
        } else if (sock->GetAf() == PJ_AF_INET6) {
 
742
            PJ_ASSERT_RETURN(*addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL);
 
743
        }
 
744
    }
 
745
    
 
746
    // If socket has reader, delete it.
 
747
    if (sock->Reader())
 
748
        sock->DestroyReader();
 
749
    
 
750
    if (key->cbObj->IsActive())
 
751
        return PJ_EBUSY;
 
752
 
 
753
    // Clear flag
 
754
    flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
 
755
    return key->cbObj->StartRead(op_key, buffer, length, flags, addr, addrlen);
 
756
}
 
757
 
 
758
 
 
759
/*
 
760
 * Instruct the I/O Queue to write to the handle.
 
761
 */
 
762
PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
 
763
                                     pj_ioqueue_op_key_t *op_key,
 
764
                                     const void *data,
 
765
                                     pj_ssize_t *length,
 
766
                                     pj_uint32_t flags )
 
767
{
 
768
    TRequestStatus reqStatus;
 
769
    TPtrC8 aBuffer((const TUint8*)data, (TInt)*length);
 
770
    TSockXfrLength aLen;
 
771
    
 
772
    PJ_UNUSED_ARG(op_key);
 
773
 
 
774
    // Forcing pending operation is not supported.
 
775
    PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
 
776
 
 
777
    // Return failure if access point is marked as down by app.
 
778
    PJ_SYMBIAN_CHECK_CONNECTION();
 
779
 
 
780
    // Clear flag
 
781
    flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
 
782
 
 
783
    key->cbObj->get_pj_socket()->Socket().Send(aBuffer, flags, reqStatus, aLen);
 
784
    User::WaitForRequest(reqStatus);
 
785
 
 
786
    if (reqStatus.Int() != KErrNone)
 
787
        return PJ_RETURN_OS_ERROR(reqStatus.Int());
 
788
 
 
789
    //At least in UIQ Emulator, aLen.Length() reports incorrect length
 
790
    //for UDP (some newlc.com users seem to have reported this too).
 
791
    //*length = aLen.Length();
 
792
    return PJ_SUCCESS;
 
793
}
 
794
 
 
795
 
 
796
/*
 
797
 * Instruct the I/O Queue to write to the handle.
 
798
 */
 
799
PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
 
800
                                       pj_ioqueue_op_key_t *op_key,
 
801
                                       const void *data,
 
802
                                       pj_ssize_t *length,
 
803
                                       pj_uint32_t flags,
 
804
                                       const pj_sockaddr_t *addr,
 
805
                                       int addrlen)
 
806
{
 
807
    TRequestStatus reqStatus;
 
808
    TPtrC8 aBuffer;
 
809
    TInetAddr inetAddr;
 
810
    TSockXfrLength aLen;
 
811
    pj_status_t status;
 
812
    
 
813
    PJ_UNUSED_ARG(op_key);
 
814
 
 
815
    // Forcing pending operation is not supported.
 
816
    PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
 
817
 
 
818
    // Return failure if access point is marked as down by app.
 
819
    PJ_SYMBIAN_CHECK_CONNECTION();
 
820
 
 
821
    // Convert address
 
822
    status = PjSymbianOS::pj2Addr(*(const pj_sockaddr*)addr, addrlen, 
 
823
                                  inetAddr);
 
824
    if (status != PJ_SUCCESS)
 
825
        return status;
 
826
    
 
827
    // Clear flag
 
828
    flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
 
829
 
 
830
    aBuffer.Set((const TUint8*)data, (TInt)*length);
 
831
    CPjSocket *pjSock = key->cbObj->get_pj_socket();
 
832
 
 
833
    pjSock->Socket().SendTo(aBuffer, inetAddr, flags, reqStatus, aLen);
 
834
    User::WaitForRequest(reqStatus);
 
835
 
 
836
    if (reqStatus.Int() != KErrNone)
 
837
        return PJ_RETURN_OS_ERROR(reqStatus.Int());
 
838
 
 
839
    //At least in UIQ Emulator, aLen.Length() reports incorrect length
 
840
    //for UDP (some newlc.com users seem to have reported this too).
 
841
    //*length = aLen.Length();
 
842
    return PJ_SUCCESS;
 
843
}
 
844
 
 
845
PJ_DEF(pj_status_t) pj_ioqueue_set_concurrency(pj_ioqueue_key_t *key,
 
846
                                                                                           pj_bool_t allow)
 
847
{
 
848
        /* Not supported, just return PJ_SUCCESS silently */
 
849
        PJ_UNUSED_ARG(key);
 
850
        PJ_UNUSED_ARG(allow);
 
851
        return PJ_SUCCESS;
 
852
}
 
853
 
 
854
PJ_DEF(pj_status_t) pj_ioqueue_lock_key(pj_ioqueue_key_t *key)
 
855
{
 
856
        /* Not supported, just return PJ_SUCCESS silently */
 
857
        PJ_UNUSED_ARG(key);
 
858
        return PJ_SUCCESS;
 
859
}
 
860
 
 
861
PJ_DEF(pj_status_t) pj_ioqueue_unlock_key(pj_ioqueue_key_t *key)
 
862
{
 
863
        /* Not supported, just return PJ_SUCCESS silently */
 
864
        PJ_UNUSED_ARG(key);
 
865
        return PJ_SUCCESS;
 
866
}