/* * Send data */ PJ_DEF(pj_status_t) pj_sock_send(pj_sock_t sock, const void *buf, pj_ssize_t *len, unsigned flags) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); // send() should only be called to connected socket PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP); TPtrC8 data((const TUint8*)buf, (TInt)*len); TRequestStatus reqStatus; TSockXfrLength sentLen; rSock.Send(data, flags, reqStatus, sentLen); User::WaitForRequest(reqStatus); if (reqStatus.Int()==KErrNone) { //*len = (TInt) sentLen.Length(); return PJ_SUCCESS; } else return PJ_RETURN_OS_ERROR(reqStatus.Int()); }
PJ_DEF(pj_status_t) pj_sock_shutdown( pj_sock_t sock, int how) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock, PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); RSocket::TShutdown aHow; if (how == PJ_SD_RECEIVE) aHow = RSocket::EStopInput; else if (how == PJ_SHUT_WR) aHow = RSocket::EStopOutput; else aHow = RSocket::ENormal; TRequestStatus reqStatus; rSock.Shutdown(aHow, reqStatus); User::WaitForRequest(reqStatus); if (reqStatus == KErrNone) { return PJ_SUCCESS; } else { return PJ_RETURN_OS_ERROR(reqStatus.Int()); } }
/* * Connect socket. */ PJ_DEF(pj_status_t) pj_sock_connect( pj_sock_t sock, const pj_sockaddr_t *addr, int namelen) { pj_status_t status; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && addr && namelen, PJ_EINVAL); PJ_ASSERT_RETURN(((pj_sockaddr*)addr)->addr.sa_family == PJ_AF_INET, PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); TInetAddr inetAddr; TRequestStatus reqStatus; status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)addr, namelen, inetAddr); if (status != PJ_SUCCESS) return status; rSock.Connect(inetAddr, reqStatus); User::WaitForRequest(reqStatus); if (reqStatus == KErrNone) { pjSock->SetConnected(true); return PJ_SUCCESS; } else { return PJ_RETURN_OS_ERROR(reqStatus.Int()); } }
PJ_DEF(pj_status_t) pj_sock_set_qos_params(pj_sock_t sock, pj_qos_params *param) { PJ_ASSERT_RETURN(sock!=0 && sock!=PJ_INVALID_SOCKET, PJ_EINVAL); CPjSocket *pjsock = (CPjSocket*)sock; RSocket & rsock = pjsock->Socket(); pj_status_t last_err = PJ_ENOTSUP; /* SO_PRIORITY and WMM are not supported */ param->flags &= ~(PJ_QOS_PARAM_HAS_SO_PRIO | PJ_QOS_PARAM_HAS_WMM); if (param->flags & PJ_QOS_PARAM_HAS_DSCP) { TInt err; err = rsock.SetOpt(KSoIpTOS, KProtocolInetIp, (param->dscp_val << 2)); if (err != KErrNone) { last_err = PJ_RETURN_OS_ERROR(err); param->flags &= ~(PJ_QOS_PARAM_HAS_DSCP); } } return param->flags ? PJ_SUCCESS : last_err; }
/* * Receive data. */ PJ_DEF(pj_status_t) pj_sock_recvfrom(pj_sock_t sock, void *buf, pj_ssize_t *len, unsigned flags, pj_sockaddr_t *from, int *fromlen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && buf && len && from && fromlen, PJ_EINVAL); PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL); PJ_ASSERT_RETURN(*fromlen >= (int)sizeof(pj_sockaddr_in), PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); if (pjSock->Reader()) { CPjSocketReader *reader = pjSock->Reader(); while (reader->IsActive() && !reader->HasData()) { User::WaitForAnyRequest(); } if (reader->HasData()) { TPtr8 data((TUint8*)buf, (TInt)*len); TInetAddr inetAddr; reader->ReadData(data, &inetAddr); *len = data.Length(); if (from && fromlen) { return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)from, fromlen); } else { return PJ_SUCCESS; } } } TInetAddr inetAddr; TRequestStatus reqStatus; TSockXfrLength recvLen; TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len); rSock.RecvFrom(data, inetAddr, flags, reqStatus, recvLen); User::WaitForRequest(reqStatus); if (reqStatus == KErrNone) { //*len = (TInt)recvLen.Length(); *len = data.Length(); return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)from, fromlen); } else { *len = -1; *fromlen = -1; return PJ_RETURN_OS_ERROR(reqStatus.Int()); } }
// // CActive's DoCancel() // void CIoqueueCallback::DoCancel() { if (type_ == TYPE_READ) sock_->Socket().CancelRecv(); else if (type_ == TYPE_ACCEPT) sock_->Socket().CancelAccept(); type_ = TYPE_NONE; pending_data_.common_.op_key_ = NULL; }
// // 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; }
// // Start asynchronous accept() operation. // pj_status_t CIoqueueCallback::StartAccept(pj_ioqueue_op_key_t *op_key, pj_sock_t *new_sock, pj_sockaddr_t *local, pj_sockaddr_t *remote, int *addrlen ) { PJ_ASSERT_RETURN(IsActive()==false, PJ_EBUSY); PJ_ASSERT_RETURN(pending_data_.common_.op_key_==NULL, PJ_EBUSY); // addrlen must be specified if local or remote is specified PJ_ASSERT_RETURN((!local && !remote) || (addrlen && *addrlen), PJ_EINVAL); pending_data_.accept_.op_key_ = op_key; pending_data_.accept_.new_sock_ = new_sock; pending_data_.accept_.local_ = local; pending_data_.accept_.remote_ = remote; pending_data_.accept_.addrlen_ = addrlen; // Create blank socket blank_sock_.Open(PjSymbianOS::Instance()->SocketServ()); type_ = TYPE_ACCEPT; sock_->Socket().Accept(blank_sock_, iStatus); SetActive(); return PJ_EPENDING; }
/* * 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_status_t status; PJ_UNUSED_ARG (op_key); // Forcing pending operation is not supported. PJ_ASSERT_RETURN ( (flags & PJ_IOQUEUE_ALWAYS_ASYNC) ==0, PJ_EINVAL); // Return failure if access point is marked as down by app. PJ_SYMBIAN_CHECK_CONNECTION(); // Convert address status = PjSymbianOS::pj2Addr (* (const pj_sockaddr*) addr, addrlen, inetAddr); if (status != PJ_SUCCESS) return status; // Clear flag flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC; aBuffer.Set ( (const TUint8*) data, (TInt) *length); 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; }
/* * Get socket name. */ PJ_DEF(pj_status_t) pj_sock_getsockname( pj_sock_t sock, pj_sockaddr_t *addr, int *namelen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && addr && namelen && *namelen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); TInetAddr inetAddr; rSock.LocalName(inetAddr); return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)addr, namelen); }
PJ_DEF(pj_status_t) pj_sock_get_qos_params(pj_sock_t sock, pj_qos_params *p_param) { PJ_ASSERT_RETURN(sock!=0 && sock!=PJ_INVALID_SOCKET, PJ_EINVAL); CPjSocket *pjsock = (CPjSocket*)sock; RSocket & rsock = pjsock->Socket(); TInt err, dscp; pj_bzero(p_param, sizeof(*p_param)); err = rsock.GetOpt(KSoIpTOS, KProtocolInetIp, dscp); if (err == KErrNone) { p_param->flags |= PJ_QOS_PARAM_HAS_DSCP; p_param->dscp_val = (dscp >> 2); return PJ_SUCCESS; } else {
/* * Start listening to incoming connections. */ PJ_DEF(pj_status_t) pj_sock_listen( pj_sock_t sock, int backlog) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && backlog, PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); TInt rc = rSock.Listen((TUint)backlog); if (rc == KErrNone) { return PJ_SUCCESS; } else { return PJ_RETURN_OS_ERROR(rc); } }
/* * Get remote's name. */ PJ_DEF(pj_status_t) pj_sock_getpeername( pj_sock_t sock, pj_sockaddr_t *addr, int *namelen) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && addr && namelen && *namelen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); // Socket must be connected. PJ_ASSERT_RETURN(pjSock->IsConnected(), PJ_EINVALIDOP); TInetAddr inetAddr; rSock.RemoteName(inetAddr); return PjSymbianOS::Addr2pj(inetAddr, *(pj_sockaddr*)addr, namelen); }
/* * Send data. */ PJ_DEF(pj_status_t) pj_sock_sendto(pj_sock_t sock, const void *buf, pj_ssize_t *len, unsigned flags, const pj_sockaddr_t *to, int tolen) { pj_status_t status; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL); // Return failure if access point is marked as down by app. PJ_SYMBIAN_CHECK_CONNECTION(); CPjSocket *pjSock = (CPjSocket*)sock; RSocket &rSock = pjSock->Socket(); // Only supports AF_INET for now PJ_ASSERT_RETURN(tolen>=(int)sizeof(pj_sockaddr_in), PJ_EINVAL); TInetAddr inetAddr; status = PjSymbianOS::pj2Addr(*(pj_sockaddr*)to, tolen, inetAddr); if (status != PJ_SUCCESS) return status; TPtrC8 data((const TUint8*)buf, (TInt)*len); TRequestStatus reqStatus; TSockXfrLength sentLen; rSock.SendTo(data, inetAddr, flags, reqStatus, sentLen); User::WaitForRequest(reqStatus); if (reqStatus.Int()==KErrNone) { //For some reason TSockXfrLength is not returning correctly! //*len = (TInt) sentLen.Length(); return PJ_SUCCESS; } else return PJ_RETURN_OS_ERROR(reqStatus.Int()); }
/* * 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(), newSock); newPjSock->SetConnected(true); *newsock = (pj_sock_t) newPjSock; if (addr && addrlen) { return pj_sock_getpeername(*newsock, addr, addrlen); } return PJ_SUCCESS; }
// // Start asynchronous recv() operation // pj_status_t CIoqueueCallback::StartRead (pj_ioqueue_op_key_t *op_key, void *buf, pj_ssize_t *size, unsigned flags, pj_sockaddr_t *addr, int *addrlen) { PJ_ASSERT_RETURN (IsActive() ==false, PJ_EBUSY); PJ_ASSERT_RETURN (pending_data_.common_.op_key_==NULL, PJ_EBUSY); flags &= ~PJ_IOQUEUE_ALWAYS_ASYNC; pending_data_.read_.op_key_ = op_key; pending_data_.read_.addr_ = addr; pending_data_.read_.addrlen_ = addrlen; aBufferPtr_.Set ( (TUint8*) buf, 0, (TInt) *size); type_ = TYPE_READ; if (addr && addrlen) { sock_->Socket().RecvFrom (aBufferPtr_, aAddress_, flags, iStatus); } else { aAddress_.SetAddress (0); aAddress_.SetPort (0); if (sock_->IsDatagram()) { sock_->Socket().Recv (aBufferPtr_, flags, iStatus); } else { // Using static like this is not pretty, but we don't need to use // the value anyway, hence doing it like this is probably most // optimal. static TSockXfrLength len; sock_->Socket().RecvOneOrMore (aBufferPtr_, flags, iStatus, len); } } SetActive(); return PJ_EPENDING; }
/* * Receive data. */ PJ_DEF(pj_status_t) pj_sock_recv(pj_sock_t sock, void *buf, pj_ssize_t *len, unsigned flags) { PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sock && buf && len, PJ_EINVAL); PJ_ASSERT_RETURN(*len > 0, PJ_EINVAL); // Return failure if access point is marked as down by app. PJ_SYMBIAN_CHECK_CONNECTION(); CPjSocket *pjSock = (CPjSocket*)sock; if (pjSock->Reader()) { CPjSocketReader *reader = pjSock->Reader(); while (reader->IsActive() && !reader->HasData()) { User::WaitForAnyRequest(); } if (reader->HasData()) { TPtr8 data((TUint8*)buf, (TInt)*len); TInetAddr inetAddr; reader->ReadData(data, &inetAddr); *len = data.Length(); return PJ_SUCCESS; } } TRequestStatus reqStatus; TSockXfrLength recvLen; TPtr8 data((TUint8*)buf, (TInt)*len, (TInt)*len); if (pjSock->IsDatagram()) { pjSock->Socket().Recv(data, flags, reqStatus); } else { // Using static like this is not pretty, but we don't need to use // the value anyway, hence doing it like this is probably most // optimal. static TSockXfrLength len; pjSock->Socket().RecvOneOrMore(data, flags, reqStatus, len); } User::WaitForRequest(reqStatus); if (reqStatus == KErrNone) { //*len = (TInt)recvLen.Length(); *len = data.Length(); return PJ_SUCCESS; } else { *len = -1; return PJ_RETURN_OS_ERROR(reqStatus.Int()); } }
PJ_DEF(int) pj_sock_select( int n, pj_fd_set_t *readfds, pj_fd_set_t *writefds, pj_fd_set_t *exceptfds, const pj_time_val *timeout) { CPjTimeoutTimer *pjTimer; unsigned i; PJ_UNUSED_ARG(n); PJ_UNUSED_ARG(writefds); PJ_UNUSED_ARG(exceptfds); if (timeout) { pjTimer = PjSymbianOS::Instance()->SelectTimeoutTimer(); pjTimer->StartTimer(timeout->sec*1000 + timeout->msec); } else { pjTimer = NULL; } /* Scan for readable sockets */ if (readfds) { symbian_fd_set *fds = (symbian_fd_set *)readfds; do { /* Scan sockets for readily available data */ for (i=0; i<fds->count; ++i) { CPjSocket *pjsock = fds->sock[i]; if (pjsock->Reader()) { if (pjsock->Reader()->HasData() && !pjsock->Reader()->IsActive()) { /* Found socket with data ready */ PJ_FD_ZERO(readfds); PJ_FD_SET((pj_sock_t)pjsock, readfds); /* Cancel timer, if any */ if (pjTimer) { pjTimer->Cancel(); } /* Clear writable and exception fd_set */ if (writefds) PJ_FD_ZERO(writefds); if (exceptfds) PJ_FD_ZERO(exceptfds); return 1; } else if (!pjsock->Reader()->IsActive()) pjsock->Reader()->StartRecvFrom(); } else { pjsock->CreateReader(); pjsock->Reader()->StartRecvFrom(); } } PjSymbianOS::Instance()->WaitForActiveObjects(); } while (pjTimer==NULL || !pjTimer->HasTimedOut()); } /* Timeout */ if (readfds) PJ_FD_ZERO(readfds); if (writefds) PJ_FD_ZERO(writefds); if (exceptfds) PJ_FD_ZERO(exceptfds); return 0; }