📄 hxopwavetcpsock.cpp
字号:
}
//OpDPRINTF("Write: this=%p, lwsize=%d, bread=%d, newwritesize=%d, bwrite=%d\n", this, m_ulBytesLeftToWrite, m_bReadable, pBuffer->GetSize(), m_bWritable);
UCHAR* pBufData = pBuffer->GetBuffer();
if (SUCCEEDED(res) && (m_state == tcpConnected))
{
/// First add to our list
pBuffer->AddRef();
m_writeList.AddTail(pBuffer);
/// decide if we need to do a write
/// because last time when it is ready to write, there is no data
/// to be written.
if (m_bWritable)
{
if (!m_pWriteBuffer)
{
m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();
}
res =DoWrite();
if (SUCCEEDED(res))
{
m_bWritable = FALSE;
}
}
}
return res;
}
/// This is working method to do actual write from
/// the m_pWriteBuffer which is guranteed to have data to be written
/// and the socket is ready to accept data
HX_RESULT HXOpwaveTCPSocket::DoWrite()
{
HX_RESULT res = HXR_OK;
UCHAR* pBufData = m_pWriteBuffer->GetBuffer();
size_t ulActualWritten = write(pBufData, m_ulBytesLeftToWrite);
HX_ASSERT(m_ulBytesLeftToWrite >= ulActualWritten);
//OpDPRINTF("DoWrite, this=%p, written%d, write=%d\n\n",this, ulActualWritten, m_ulBytesLeftToWrite);
m_ulBytesLeftToWrite -= ulActualWritten;
if (m_ulBytesLeftToWrite > 0)
{
// more left in this m_pWriteBuffer to be written out
UCHAR* pLeftData = new UCHAR[m_ulBytesLeftToWrite];
if (!pLeftData)
{
res = HXR_OUTOFMEMORY;
OnWriteDone(res);
return res;
}
memcpy(pLeftData, pBufData+ulActualWritten, m_ulBytesLeftToWrite);
m_pWriteBuffer->Set(pLeftData, m_ulBytesLeftToWrite);
delete pLeftData;
}
return res;
}
/************************************************************************
* Method:
* IHXTCPSocket::WantWrite
* Purpose:
* This method is called when you wish to write a large amount of
* data. If you are only writing small amounts of data, you can
* just call Write (all data not ready to be transmitted will be
* buffered on your behalf). When the TCP channel is ready to be
* written to, the response interfaces WriteReady method will be
* called.
*/
STDMETHODIMP
HXOpwaveTCPSocket::WantWrite(THIS)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::WantWrite()\n"));
m_bWantWrite = TRUE;
return HXR_OK;
}
/************************************************************************
* Method:
* IHXTCPSocket::GetForeignAddress
* Purpose:
* Returns the address of the other end of the TCP socket as a
* ULONG32 in local host order
*/
STDMETHODIMP
HXOpwaveTCPSocket::GetForeignAddress(THIS_ REF(ULONG32) lAddress)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetForeignAddress()\n"));
/// OpSocket's DNS should make this better
HX_RESULT res = HXR_OK;
if (m_state == tcpConnected)
{
lAddress = m_ipDest;
}
return res;
}
STDMETHODIMP
HXOpwaveTCPSocket::GetLocalAddress(THIS_ REF(ULONG32) lAddress)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetLocalAddress()\n"));
HX_RESULT res = HXR_OK;
lAddress = m_ulLocalAddr;
return res;
}
/************************************************************************
* Method:
* IHXTCPSocket::GetForeignPort
* Purpose:
* Returns the port of the other end of the TCP socket in local
* host order.
*/
STDMETHODIMP
HXOpwaveTCPSocket::GetForeignPort(THIS_ REF(UINT16) port)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetForeignPort()\n"));
/// Until OpSocket has DNS, this is not appropriately implemented
HX_RESULT res = HXR_OK;
if (m_state == tcpConnected)
{
port = m_nConnectPort;
}
else
{
res = HXR_FAILED;
}
return res;
}
STDMETHODIMP
HXOpwaveTCPSocket::GetLocalPort(THIS_
REF(UINT16) port)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::GetLocalPort()\n"));
HX_RESULT res = HXR_OK;
if ((m_state != tcpNotInitialized) &&
(m_state != tcpInitialized))
{
port = m_nLocalPort;
}
return res;
}
STDMETHODIMP
HXOpwaveTCPSocket::SetOption(THIS_
HX_SOCKET_OPTION option,
UINT32 ulValue)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::SetOption(%d, %lu)\n", option, ulValue));
HX_RESULT res = HXR_FAILED;
if (m_state == tcpNotInitialized)
{
switch(option)
{
case HX_SOCKOPT_REUSE_ADDR:
case HX_SOCKOPT_REUSE_PORT:
//// OpSocket doesn't support set socket options
{
res = HXR_NOTIMPL;
}
break;
case HX_SOCKOPT_BROADCAST:
case HX_SOCKOPT_SET_RECVBUF_SIZE:
case HX_SOCKOPT_SET_SENDBUF_SIZE:
case HX_SOCKOPT_MULTICAST_IF:
res = HXR_UNEXPECTED;
break;
default:
break;
}
}
return res;
}
HX_RESULT
HXOpwaveTCPSocket::GetHostByNameDone(HX_RESULT status,
ULONG32 ulAddr)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::ResolveDone(%ld, %08lx)\n", status, ulAddr));
HX_ASSERT( m_state == tcpResolving);
if (SUCCEEDED(status))
{
m_ipDest = ulAddr;
m_state = tcpConnecting;
connect(m_nLocalPort, m_nConnectPort, m_ipDest);
/*
char* stopstring = NULL;
UINT32 segVal = 0;
segVal = strtoul(pDestination, &stopstring, 10);
m_ipDest = segVal << 24;
pDestination = stopstring + 1;
segVal = strtoul(pDestination, &stopstring, 10);
m_ipDest += (segVal << 16);
pDestination = stopstring + 1;
segVal = strtoul(pDestination, &stopstring, 10);
m_ipDest += (segVal << 8);
pDestination = stopstring + 1;
segVal = strtoul(pDestination, &stopstring, 10);
m_ipDest += segVal;
connect(m_nLocalPort, nPort, m_ipDest);
//OpDPRINTF("Connect: this=%p, localPort=%d,remotePort=%d,desIP=%d\n", this, m_nLocalPort, nPort, m_ipDest);
*/
m_bWritable = FALSE;
m_bReadable = FALSE;
}
return status;
}
void HXOpwaveTCPSocket::OnConnect(HX_RESULT status)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnConnect(%ld)\n",status));
HX_ASSERT(m_state == tcpConnecting);
DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
if (status == HXR_OK)
{
m_state = tcpConnected;
}
else
{
m_state = tcpBound;
}
if (m_pResponse)
{
m_pResponse->ConnectDone(status);
}
}
void HXOpwaveTCPSocket::OnWriteDone(HX_RESULT status)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnWriteDone(%ld)\n", status));
DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
if (status == HXR_OK)
{
HX_RELEASE(m_pWriteBuffer);
if (m_writeList.GetCount() > 0)
{
m_pWriteBuffer = (IHXBuffer*)m_writeList.RemoveHead();
m_ulBytesLeftToWrite = m_pWriteBuffer->GetSize();
}
// Signal WriteReady() if we don't have any
// writes pending and the response object
// wants these calls
if (m_bWantWrite && m_pResponse)
{
m_pResponse->WriteReady(HXR_OK);
}
}
else
{
CloseConnection(status);
}
}
void HXOpwaveTCPSocket::OnReadDone(HX_RESULT status, IHXBuffer* pBuffer)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::OnReadDone(%ld)\n", status));
DECLARE_SMART_POINTER_UNKNOWN scopeRef((IHXTCPSocket*)this);
if (m_pResponse)
{
m_pResponse->ReadDone(status, pBuffer);
}
if (status != HXR_OK)
{
CloseConnection(status);
}
}
void HXOpwaveTCPSocket::CloseConnection(HX_RESULT status)
{
DPRINTF(D_TCPSOCKET, ("HXOpwaveTCPSocket::CloseConnection(%ld)\n", status));
if (m_state != tcpNotInitialized)
{
close(true);
}
// Clear the writer list
while (m_writeList.GetCount() > 0)
{
// Release all the left unsent buffers in the list
IHXBuffer* pBuffer = (IHXBuffer*)m_writeList.RemoveHead();
HX_RELEASE(pBuffer);
}
if ((m_state != tcpInitialized) && m_pResponse)
{
m_pResponse->Closed(HXR_OK);
}
m_state = tcpNotInitialized;
}
void HXOpwaveTCPSocket::onReadable(OpSocketEvent *pSocketEvent)
{
HX_RESULT res = HXR_OK;
m_bReadable = TRUE;
//OpDPRINTF("onReadable: this=%p, mrsize=%d, bread=%d, state=%d, bwrite=%d\n", this, m_ulReadSize, m_bReadable, m_state, m_bWritable);
if (m_ulReadSize > 0)
{
/// avoid recursion that might occur because
/// OnReadDone call in DoRead invoke ::Read again
m_bReadable = FALSE;
DoRead();
}
}
void HXOpwaveTCPSocket::onWritable(OpSocketEvent *pSocketEvent)
{
HX_RESULT res = HXR_OK;
m_bWritable = TRUE;
//OpDPRINTF("onWritable: this=%p, mrsize=%d, bread=%d, lwsize=%d, bwrite=%d\n", this, m_ulReadSize, m_bReadable, m_ulBytesLeftToWrite, m_bWritable);
if (m_state == tcpConnecting)
{
/// Since Openwave OpSocket's api is designed to have kWritable as the first
/// event sending back to clients, so we first respond to core for connection
/// status
OpSocketEvent::Condition sockCond = pSocketEvent->getCondition();
HX_RESULT status = sockCond == OpSocketEvent::kException ? HXR_NET_CONNECT : HXR_OK;
OnConnect(status);
}
/// Normal write process
/// Call OnWriteDone for handling the notification of last write
if (m_ulBytesLeftToWrite == 0)
{
/// Notify last writing is completely done
OnWriteDone(res);
}
/// Do the next writing
if (m_pWriteBuffer && m_ulBytesLeftToWrite > 0)
{
if (DoWrite() == HXR_OK)
{
m_bWritable = FALSE;
}
}
}
void HXOpwaveTCPSocket::onException(OpSocketEvent *pSocketEvent)
{
OpSocketEvent::Exception except = pSocketEvent->getException();
}
#if 0
// Don't need it for the time being because
// all the cases are handled by the above three callbacks.
bool HXOpwaveTCPSocket::onEvent(OpEvent& ev)
{
OpSocketEvent* pSockEvt = NULL;
if ( (pSockEvt = OpSocketEvent::Cast(&ev)) != NULL)
{
HX_RESULT status = pSockEvt->getCondition() == OpSocketEvent::kException ? HXR_NET_CONNECT : HXR_OK;
OnConnect(status);
return true;
}
return OpEventSink::onEvent(ev);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -