📄 ioqueue_symbian.cpp
字号:
{
if (type_ == TYPE_READ)
sock_->Socket().CancelRecv();
else if (type_ == TYPE_ACCEPT)
sock_->Socket().CancelAccept();
type_ = TYPE_NONE;
}
//
// Cancel operation and call callback.
//
void CIoqueueCallback::CancelOperation(pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_status)
{
Type cur_type = type_;
Cancel();
if (cur_type == TYPE_READ) {
if (cb_.on_read_complete)
cb_.on_read_complete(key_, op_key, bytes_status);
} else if (cur_type == TYPE_ACCEPT)
;
}
/////////////////////////////////////////////////////////////////////////////
/*
* IO Queue key structure.
*/
struct pj_ioqueue_key_t
{
CIoqueueCallback *cbObj;
};
/*
* Return the name of the ioqueue implementation.
*/
PJ_DEF(const char*) pj_ioqueue_name(void)
{
return "ioqueue-symbian";
}
/*
* Create a new I/O Queue framework.
*/
PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool,
pj_size_t max_fd,
pj_ioqueue_t **p_ioqueue)
{
pj_ioqueue_t *ioq;
PJ_UNUSED_ARG(max_fd);
ioq = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_t);
*p_ioqueue = ioq;
return PJ_SUCCESS;
}
/*
* Destroy the I/O queue.
*/
PJ_DEF(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioq )
{
PJ_UNUSED_ARG(ioq);
return PJ_SUCCESS;
}
/*
* Set the lock object to be used by the I/O Queue.
*/
PJ_DEF(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioq,
pj_lock_t *lock,
pj_bool_t auto_delete )
{
/* Don't really need lock for now */
PJ_UNUSED_ARG(ioq);
if (auto_delete) {
pj_lock_destroy(lock);
}
return PJ_SUCCESS;
}
/*
* Register a socket to the I/O queue framework.
*/
PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool,
pj_ioqueue_t *ioq,
pj_sock_t sock,
void *user_data,
const pj_ioqueue_callback *cb,
pj_ioqueue_key_t **p_key )
{
pj_ioqueue_key_t *key;
key = PJ_POOL_ZALLOC_T(pool, pj_ioqueue_key_t);
key->cbObj = CIoqueueCallback::NewL(ioq, key, sock, cb, user_data);
*p_key = key;
return PJ_SUCCESS;
}
/*
* Unregister from the I/O Queue framework.
*/
PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key )
{
if (key == NULL || key->cbObj == NULL)
return PJ_SUCCESS;
// Cancel pending async object
if (key->cbObj && key->cbObj->IsActive()) {
key->cbObj->Cancel();
}
// Close socket.
key->cbObj->get_pj_socket()->Socket().Close();
delete key->cbObj->get_pj_socket();
// Delete async object.
if (key->cbObj) {
delete key->cbObj;
key->cbObj = NULL;
}
return PJ_SUCCESS;
}
/*
* Get user data associated with an ioqueue key.
*/
PJ_DEF(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key )
{
return key->cbObj->get_user_data();
}
/*
* Set or change the user data to be associated with the file descriptor or
* handle or socket descriptor.
*/
PJ_DEF(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key,
void *user_data,
void **old_data)
{
if (old_data)
*old_data = key->cbObj->get_user_data();
key->cbObj->set_user_data(user_data);
return PJ_SUCCESS;
}
/*
* Initialize operation key.
*/
PJ_DEF(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key,
pj_size_t size )
{
pj_bzero(op_key, size);
}
/*
* Check if operation is pending on the specified operation key.
*/
PJ_DEF(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key )
{
return key->cbObj->get_op_key()==op_key &&
key->cbObj->IsActive();
}
/*
* Post completion status to the specified operation key and call the
* appropriate callback.
*/
PJ_DEF(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_ssize_t bytes_status )
{
if (pj_ioqueue_is_pending(key, op_key)) {
key->cbObj->CancelOperation(op_key, bytes_status);
}
return PJ_SUCCESS;
}
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
/**
* Instruct I/O Queue to accept incoming connection on the specified
* listening socket.
*/
PJ_DEF(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
pj_sock_t *new_sock,
pj_sockaddr_t *local,
pj_sockaddr_t *remote,
int *addrlen )
{
return key->cbObj->StartAccept(op_key, new_sock, local, remote, addrlen);
}
/*
* Initiate non-blocking socket connect.
*/
PJ_DEF(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key,
const pj_sockaddr_t *addr,
int addrlen )
{
PJ_ASSERT_RETURN(addrlen == sizeof(pj_sockaddr_in), PJ_EINVAL);
RSocket &rSock = key->cbObj->get_pj_socket()->Socket();
TInetAddr inetAddr;
PjSymbianOS::pj2Addr(*(const pj_sockaddr_in*)addr, inetAddr);
TRequestStatus reqStatus;
// We don't support async connect for now.
PJ_TODO(IOQUEUE_SUPPORT_ASYNC_CONNECT);
rSock.Connect(inetAddr, reqStatus);
User::WaitForRequest(reqStatus);
if (reqStatus == KErrNone)
return PJ_SUCCESS;
return PJ_RETURN_OS_ERROR(reqStatus.Int());
}
#endif /* PJ_HAS_TCP */
/*
* Poll the I/O Queue for completed events.
*/
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioq,
const pj_time_val *timeout)
{
/* Polling is not necessary on Symbian, since all async activities
* are registered to active scheduler.
*/
PJ_UNUSED_ARG(ioq);
PJ_UNUSED_ARG(timeout);
return 0;
}
/*
* Instruct the I/O Queue to read from the specified handle.
*/
PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
pj_uint32_t flags )
{
// If socket has reader, delete it.
if (key->cbObj->get_pj_socket()->Reader())
key->cbObj->get_pj_socket()->DestroyReader();
// Clear flag
flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
return key->cbObj->StartRead(op_key, buffer, length, flags, NULL, NULL);
}
/*
* This function behaves similarly as #pj_ioqueue_recv(), except that it is
* normally called for socket, and the remote address will also be returned
* along with the data.
*/
PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
pj_uint32_t flags,
pj_sockaddr_t *addr,
int *addrlen)
{
// If socket has reader, delete it.
if (key->cbObj->get_pj_socket()->Reader())
key->cbObj->get_pj_socket()->DestroyReader();
if (key->cbObj->IsActive())
return PJ_EBUSY;
// Clear flag
flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
return key->cbObj->StartRead(op_key, buffer, length, flags, addr, addrlen);
}
/*
* Instruct the I/O Queue to write to the handle.
*/
PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
pj_uint32_t flags )
{
TRequestStatus reqStatus;
TPtrC8 aBuffer((const TUint8*)data, (TInt)*length);
TSockXfrLength aLen;
PJ_UNUSED_ARG(op_key);
// Forcing pending operation is not supported.
PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
// Clear flag
flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
key->cbObj->get_pj_socket()->Socket().Send(aBuffer, flags, reqStatus, aLen);
User::WaitForRequest(reqStatus);
if (reqStatus.Int() != KErrNone)
return PJ_RETURN_OS_ERROR(reqStatus.Int());
//At least in UIQ Emulator, aLen.Length() reports incorrect length
//for UDP (some newlc.com users seem to have reported this too).
//*length = aLen.Length();
return PJ_SUCCESS;
}
/*
* Instruct the I/O Queue to write to the handle.
*/
PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
pj_uint32_t flags,
const pj_sockaddr_t *addr,
int addrlen)
{
TRequestStatus reqStatus;
TPtrC8 aBuffer;
TInetAddr inetAddr;
TSockXfrLength aLen;
PJ_UNUSED_ARG(op_key);
// Forcing pending operation is not supported.
PJ_ASSERT_RETURN((flags & PJ_IOQUEUE_ALWAYS_ASYNC)==0, PJ_EINVAL);
// Must be pj_sockaddr_in for now.
PJ_ASSERT_RETURN(addrlen == sizeof(pj_sockaddr_in), PJ_EINVAL);
// Clear flag
flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC;
aBuffer.Set((const TUint8*)data, (TInt)*length);
PjSymbianOS::pj2Addr(*(const pj_sockaddr_in*)addr, inetAddr);
CPjSocket *pjSock = key->cbObj->get_pj_socket();
pjSock->Socket().SendTo(aBuffer, inetAddr, flags, reqStatus, aLen);
User::WaitForRequest(reqStatus);
if (reqStatus.Int() != KErrNone)
return PJ_RETURN_OS_ERROR(reqStatus.Int());
//At least in UIQ Emulator, aLen.Length() reports incorrect length
//for UDP (some newlc.com users seem to have reported this too).
//*length = aLen.Length();
return PJ_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -