📄 ot_udp.cp
字号:
{
UInt8 buf1[256];
UInt8 buf2[256];
UDErr.addr.maxlen = 256;
UDErr.addr.buf = buf1;
UDErr.opt.maxlen = 256;
UDErr.opt.buf = buf2;
lookErr = ::OTRcvUDErr(mRef, &UDErr);
theErr = HXR_NET_WRITE;
}
else
{
theErr = HXR_NET_WRITE;
break;
}
}
break;
default:
theErr = HXR_NET_WRITE;
break;
}
*size = 0;
mLastError = theErr;
return theErr;
}
/*******************************************************************************
** read
********************************************************************************/
HX_RESULT
OT_UDP::read (void *data, UINT16 *len)
{
return HXR_NOTIMPL;
}
HX_RESULT
OT_UDP::readfrom (REF(IHXBuffer*) pBuffer,
REF(UINT32) ulAddress,
REF(UINT16) ulPort)
{
UINT16 size = 0;
OSStatus theErr = HXR_OK;
TUnitData unitdata;
OTFlags flags;
InetAddress sin;
pBuffer = NULL;
ulAddress = 0;
ulPort = 0;
mLastError = HXR_OK;
if(!mDataArrived)
{
return HXR_WOULD_BLOCK;
}
unitdata.opt.len = 0;
unitdata.addr.len = 0;
unitdata.udata.len = 0;
unitdata.addr.maxlen = sizeof(struct InetAddress);
unitdata.opt.maxlen = 0;
unitdata.opt.buf = 0;
unitdata.udata.maxlen = TCP_BUF_SIZE; // used to be 256
unitdata.udata.buf = (UInt8*)m_pInBuffer;
unitdata.addr.buf = (UInt8*) &sin;
theErr = OTRcvUData(mRef,&unitdata, &flags);
if (theErr == HXR_OK)
{
size = unitdata.udata.len;
/* I have seen the size to be a really large value some times.
* This was before I added initializaion of
* unitdata.opt.len = 0;
* unitdata.addr.len = 0;
* unitdata.udata.len = 0;
*
* It looks like sometimes OTRecvData returns no error and DOES NOT
* set the udata.len value. We now make sure that we have indeed
* received some data before creating an IHXBuffer
*
* XXXRA
*/
HX_ASSERT(size > 0);
if (size > 0)
{
CHXTimeStampedBuffer* pTimeBuffer = new CHXTimeStampedBuffer;
pTimeBuffer->AddRef();
pTimeBuffer->SetTimeStamp(HX_GET_TICKCOUNT());
pTimeBuffer->Set((UCHAR*)m_pInBuffer, size);
pBuffer = (IHXBuffer*) pTimeBuffer;
ulAddress = DwToHost(sin.fHost);
ulPort = WToHost(sin.fPort);
}
}
else if(theErr == kOTNoDataErr)
{
theErr = HXR_NO_DATA;
// xxxbobclark This used to return HXR_OK if there was no data.
// But now there's threaded networking code that needs to rely
// on this returning HXR_NO_DATA if there's really no data.
}
else if(theErr == kEWOULDBLOCKErr)
theErr = HXR_WOULD_BLOCK;
else
theErr = HXR_SERVER_DISCONNECTED;
mLastError = theErr;
return theErr;
}
/*
HX_RESULT
OT_UDP::listen (UINT16 backlog)
{
return(HXR_INVALID_OPERATION);
}
*/
HX_RESULT
OT_UDP::connect(
const char *host,
UINT16 port,
UINT16 blocking,
ULONG32 ulPlatform)
{
return(HXR_INVALID_OPERATION);
}
/* join_multicast_group() has this socket join a multicast group */
HX_RESULT
OT_UDP::join_multicast_group (ULONG32 multicastHost, ULONG32 if_addr)
{
OSStatus theErr = kOTNoError;
// mLocalPort is set by the init() function
// ::OTInitInetAddress(&mMulticastAddr, mLocalPort, multicastHost);
// since we are already bound to an IP addr on our system
// (bind occurred in the init() function) we can now Let
// IP know to listen for this multicast IP address on all interfaces.
TOptMgmt optReq;
UInt8 optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
ULONG32 optLength = kOTOptionHeaderSize + sizeof(TIPAddMulticast);
TOption* opt = (TOption*)optBuffer;
TIPAddMulticast* addopt = (TIPAddMulticast*)opt->value;
optReq.flags = T_NEGOTIATE;
optReq.opt.len = optLength;
optReq.opt.maxlen = optLength;
optReq.opt.buf = (UInt8*) optBuffer;
opt->level = INET_IP;
#ifdef _MAC_MACHO
opt->name = kIP_ADD_MEMBERSHIP;
#else
opt->name = IP_ADD_MEMBERSHIP;
#endif
opt->len = optLength;
opt->status = 0;
addopt->multicastGroupAddress = multicastHost;
addopt->interfaceAddress = if_addr;
// clear completion flag
mComplete = false;
theErr = ::OTOptionManagement(mRef,&optReq, &optReq);
// wait for completion
if(!theErr)
theErr = OTWait();
if(theErr)
theErr = HX_MULTICAST_JOIN_ERROR;
return theErr;
}
HX_RESULT
OT_UDP::leave_multicast_group(ULONG32 multicastHost, ULONG32 if_addr)
{
HX_RESULT theErr = HXR_OK;
TOptMgmt optReq;
UInt8 optBuffer[ kOTOptionHeaderSize + sizeof(TIPAddMulticast) ];
ULONG32 optLength = kOTOptionHeaderSize + sizeof(TIPAddMulticast);
TOption* opt = (TOption*)optBuffer;
TIPAddMulticast* addopt = (TIPAddMulticast*)opt->value;
optReq.flags = T_NEGOTIATE;
optReq.opt.len = optLength;
optReq.opt.maxlen = optLength;
optReq.opt.buf = (UInt8*) optBuffer;
opt->level = INET_IP;
#ifdef _MAC_MACHO
opt->name = kIP_DROP_MEMBERSHIP;
#else
opt->name = IP_DROP_MEMBERSHIP;
#endif
opt->len = optLength;
opt->status = 0;
addopt->multicastGroupAddress = multicastHost;
addopt->interfaceAddress = if_addr;
// clear completion flag
mComplete = false;
theErr = ::OTOptionManagement(mRef,&optReq, &optReq);
// wait for completion
if(!theErr)
theErr = OTWait();
if(theErr)
return HX_GENERAL_MULTICAST_ERROR;
return HXR_OK;
}
HX_RESULT
OT_UDP::set_broadcast(BOOL enable)
{
OSStatus theErr = kOTNoError;
mComplete = false;
m_bIsBroadcastEnabled = enable;
return HXR_OK;
}
/*----------------------------------------------------------------------------
UDPNotifyProc
Open Transport notifier proc for UDP streams.
Entry: s = pointer to UDP stream.
code = OT event code.
result = OT result.
cookie = OT cookie.
----------------------------------------------------------------------------*/
pascal void OT_UDP::UDPNotifyProc (
void *stream,
OTEventCode code,
OTResult result,
void *cookie )
{
OT_UDP* s = (OT_UDP*) stream;
HXMM_INTERRUPTON();
s->ProcessCmd(code, result, cookie);
HXMM_INTERRUPTOFF();
return;
}
void
OT_UDP::ProcessCmd(OTEventCode code, OTResult result, void* cookie)
{
switch (code)
{
case T_DISCONNECT:
/* Other side has aborted. */
mOtherSideHasClosed = true;
mComplete = true;
mConnectionOpen = FALSE;
MWDebugPStr("\pT_DISCONNECT");
if(mCallBack) mCallBack->Func(CONNECT_NOTIFICATION, FALSE);
break;
case T_ORDREL:
/* Other side has closed. Close our side if necessary. */
mOtherSideHasClosed = true;
mComplete = true;
mConnectionOpen = FALSE;
if (mClosing) mRelease = true;
MWDebugPStr("\pT_ORDREL");
break;
case T_DATA:
mDataArrived = TRUE;
//if(mCallBack) mCallBack->callback_task(HX_UDP_CALLBACK);
if(mCallBack) mCallBack->Func(READ_NOTIFICATION);
break;
case T_BINDCOMPLETE:
case T_CONNECT:
case T_PASSCON:
mComplete = true;
mCode = code;
mResult = result;
mCookie = cookie;
break;
case T_OPENCOMPLETE:
mConnectionOpen = TRUE;
mComplete = true;
mCode = code;
mResult = result;
mCookie = cookie;
if(mCallBack) mCallBack->Func(CONNECT_NOTIFICATION);
break;
case T_GODATA:
mDataFlowOn = FALSE;
MWDebugPStr("\pT_GODATA");
break;
case T_OPTMGMTCOMPLETE:
mComplete = true;
mCode = code;
mResult = result;
mCookie = cookie;
break;
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -