/*
 * 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)
{
    CPjSocket *sock = key->cbObj->get_pj_socket();

    // If address is specified, check that the length match the
    // address family
    if (addr || addrlen) {
        PJ_ASSERT_RETURN(addr && addrlen && *addrlen, PJ_EINVAL);
        if (sock->GetAf() == PJ_AF_INET) {
            PJ_ASSERT_RETURN(*addrlen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL);
        } else if (sock->GetAf() == PJ_AF_INET6) {
            PJ_ASSERT_RETURN(*addrlen>=(int)sizeof(pj_sockaddr_in6), PJ_EINVAL);
        }
    }

    // If socket has reader, delete it.
    if (sock->Reader())
        sock->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);
}
Beispiel #2
0
//
// Handle asynchronous Accept() completion.
//
CPjSocket *CIoqueueCallback::HandleAcceptCompletion()
{
    CPjSocket *pjNewSock = new CPjSocket (get_pj_socket()->GetAf(),
                                          get_pj_socket()->GetSockType(),
                                          blank_sock_);
    int addrlen = 0;

    if (pending_data_.accept_.new_sock_) {
        *pending_data_.accept_.new_sock_ = (pj_sock_t) pjNewSock;
        pending_data_.accept_.new_sock_ = NULL;
    }

    if (pending_data_.accept_.local_) {
        TInetAddr aAddr;
        pj_sockaddr *ptr_sockaddr;

        blank_sock_.LocalName (aAddr);
        ptr_sockaddr = (pj_sockaddr*) pending_data_.accept_.local_;
        addrlen = *pending_data_.accept_.addrlen_;
        PjSymbianOS::Addr2pj (aAddr, *ptr_sockaddr, &addrlen);
        pending_data_.accept_.local_ = NULL;
    }

    if (pending_data_.accept_.remote_) {
        TInetAddr aAddr;
        pj_sockaddr *ptr_sockaddr;

        blank_sock_.RemoteName (aAddr);
        ptr_sockaddr = (pj_sockaddr*) pending_data_.accept_.remote_;
        addrlen = *pending_data_.accept_.addrlen_;
        PjSymbianOS::Addr2pj (aAddr, *ptr_sockaddr, &addrlen);
        pending_data_.accept_.remote_ = NULL;
    }

    if (pending_data_.accept_.addrlen_) {
        if (addrlen == 0) {
            if (pjNewSock->GetAf() == PJ_AF_INET)
                addrlen = sizeof (pj_sockaddr_in);
            else if (pjNewSock->GetAf() == PJ_AF_INET6)
                addrlen = sizeof (pj_sockaddr_in6);
            else {
                pj_assert (!"Unsupported address family");
            }
        }

        *pending_data_.accept_.addrlen_ = addrlen;
        pending_data_.accept_.addrlen_ = NULL;
    }

    return pjNewSock;
}
Beispiel #3
0
/*
 * Accept incoming connections
 */
PJ_DEF(pj_status_t) pj_sock_accept( pj_sock_t serverfd,
				    pj_sock_t *newsock,
				    pj_sockaddr_t *addr,
				    int *addrlen)
{
    PJ_CHECK_STACK();

    PJ_ASSERT_RETURN(serverfd && newsock, PJ_EINVAL);

    CPjSocket *pjSock = (CPjSocket*)serverfd;
    RSocket &rSock = pjSock->Socket();

    // Create a 'blank' socket
    RSocket newSock;
    newSock.Open(PjSymbianOS::Instance()->SocketServ());

    // Call Accept()
    TRequestStatus reqStatus;

    rSock.Accept(newSock, reqStatus);
    User::WaitForRequest(reqStatus);

    if (reqStatus != KErrNone) {
	return PJ_RETURN_OS_ERROR(reqStatus.Int());
    }

    // Create PJ socket
    CPjSocket *newPjSock = new CPjSocket(pjSock->GetAf(), pjSock->GetSockType(),
					 newSock);
    newPjSock->SetConnected(true);

    *newsock = (pj_sock_t) newPjSock;

    if (addr && addrlen) {
	return pj_sock_getpeername(*newsock, addr, addrlen);
    }

    return PJ_SUCCESS;
}