📄 ot_net.cp
字号:
return(theErr);
}
// close_drivers() should close any network drivers used by the program
// NOTE: The program MUST not make any other calls to the network drivers
// until init_drivers() has been called
HX_RESULT
OT_net::close_drivers(void *params)
{
if(sHaveOT)
{
#ifdef _CARBON
CloseOpenTransportInContext(sOToutClientContext);
#else
CloseOpenTransport();
#endif
}
return(HXR_OK);
}
HX_RESULT
OT_net::host_to_ip_str(char *host, char *ip, UINT32 ulBufLen)
{
HX_RESULT theErr = HXR_OK;
ULONG32 addr;
UINT16 port;
theErr = lookup_host(host,&addr, &port);
if(!theErr) OTInetHostToString(addr,ip);
if(theErr) theErr = HXR_BIND;
return(theErr);
}
ULONG32 OT_net::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
ULONG32 OT_net::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
HX_RESULT
OT_net::lookup_host (
char *name,
ULONG32 *addr,
UINT16 *port,
UINT16 defaultPort)
{
HX_RESULT theErr = HXR_OK;
InetHostInfo hInfoOT;
char domainName[256];
char *p, *q;
OTSvcInfo svcInfo;
p = name;
q = domainName;
while (*p != 0 && *p != ',' && *p != ' ' && *p != ':') *q++ = *p++;
*q = 0;
q = p;
while (*q == ' ') q++;
if (*q == 0)
*port = defaultPort;
else
{
p++;
if (!isdigit(*p)) return HXR_BIND;
q = p+1;
while (isdigit(*q)) q++;
while (*q == ' ') q++;
if (*q != 0) return HXR_BIND;
*port = atoi(p);
}
// check if DNS has been cached
if(conn::is_cached(domainName,addr))
return HXR_OK;
theErr = OTInetStringToHost(domainName, addr);
if (theErr != HXR_OK)
{
theErr = OpenInetServices(&svcInfo);
if (theErr == kEINVALErr) return HXR_BIND;
if (theErr != HXR_OK) return (theErr);
svcInfo.complete = false;
theErr = OTInetStringToAddress(svcInfo.ref, domainName, &hInfoOT);
if (theErr == HXR_OK) theErr = OTSvcWait(&svcInfo);
OTCloseProvider(svcInfo.ref);
if (theErr != HXR_OK)
{
if (theErr == kOTNoDataErr || theErr == kOTBadNameErr) theErr = HXR_BIND;
return (theErr);
}
*addr = hInfoOT.addrs[0];
}
conn::add_to_cache(domainName, *addr);
return HXR_OK;
}
HX_RESULT OT_net::dns_find_ip_addr(const char * host, UINT16 blocking)
{
if(!host)
{
mLastError = HX_INVALID_HOST;
return mLastError;
}
//XXXCWB
// if(get_sock() < 0)
// {
// mLastError = HX_NET_SOCKET_INVALID;
// return mLastError;
// }
if (conn::is_cached((char *) host, &mHostIPAddr))
{
mHostIPValid = TRUE;
mDNSDone = TRUE;
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, TRUE);
}
return( mLastError = HXR_OK);
}
char* pTemp = strrchr(host, '.');
if (pTemp && atoi(pTemp + 1))
{ /* IP address. */
struct in_addr addr;
mHostIPValid = FALSE;
mHostIPAddr = 0;
mDNSDone = TRUE;
::OTInetStringToHost((char*)host, &addr.s_addr); //!!!!!
if ((UINT)addr.s_addr == (UINT)-1)
{
mLastError = HX_INVALID_HOST;
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, FALSE);
}
return mLastError;
}
mHostIPValid = TRUE;
mHostIPAddr = *(ULONG32 *) &addr;
conn::add_to_cache((char *) host, mHostIPAddr);
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, TRUE);
}
return HXR_OK;
}
if (blocking)
{
struct in_addr addr;
mHostIPValid = FALSE;
mHostIPAddr = 0;
mDNSDone = TRUE;
InetHostInfo ihost;
OTSvcInfo svcInfo;
OSErr theErr = OpenInetServices(&svcInfo);
if (theErr == kEINVALErr) return HXR_BIND;
if (theErr != HXR_OK) return (theErr);
svcInfo.complete = false;
::OTInetStringToAddress(svcInfo.ref,(char*)host,&ihost);
if (theErr == HXR_OK) theErr = OTSvcWait(&svcInfo);
OTCloseProvider(svcInfo.ref);
if (!ihost.addrs )
{
mLastError = HX_INVALID_HOST;
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, FALSE);
}
return mLastError;
}
memcpy(&addr, ihost.addrs, sizeof(struct in_addr));
mHostIPValid = TRUE;
mHostIPAddr = *(ULONG32 *) &addr;
conn::add_to_cache((char *) host, mHostIPAddr);
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, TRUE);
}
return( mLastError = HXR_OK);
}
else // non-blocking
{
mDNSDone = TRUE;
mHostIPValid = FALSE;
mHostIPAddr = 0;
HX_RESULT theErr;
MyOTInfo myOTInfo;
::memset(&myOTInfo, 0, sizeof(myOTInfo));
myOTInfo.hostName = host;
myOTInfo.complete = false;
#ifdef _CARBON
theErr = OTAsyncOpenInternetServicesInContext(kDefaultInternetServicesPath, 0,
::NewOTNotifyUPP(MyOTNotifyProc), &myOTInfo, NULL);
#else
theErr = OTAsyncOpenInternetServices(kDefaultInternetServicesPath, 0,
MyOTNotifyProc, &myOTInfo);
#endif
if (theErr != HXR_OK)
{
return( mLastError = HXR_BIND);
}
// MyOTNotifyProc() handles asynch. functionality of this routine
Boolean cancel = false;
do
{
cancel = Mac_net::CheckForCancel();
}
while (!myOTInfo.complete && !cancel);
// Save the IP address
Boolean bFound;
if (myOTInfo.hostInfo.addrs && *myOTInfo.hostInfo.addrs)
{
bFound = true;
mLastError = HXR_OK;
struct in_addr addr;
memcpy(&addr, myOTInfo.hostInfo.addrs, sizeof(struct in_addr));
mHostIPValid = TRUE;
mHostIPAddr = *(ULONG32 *) &addr;
conn::add_to_cache((char *) host, mHostIPAddr);
}
else
{
bFound = false;
mLastError = HX_INVALID_HOST;
}
::OTRemoveNotifier(myOTInfo.inetSvcRef);
::OTCloseProvider (myOTInfo.inetSvcRef);
if (mCallBack)
{
mCallBack->Func(DNS_NOTIFICATION, bFound);
}
return(mLastError);
}
return FALSE;
}
pascal void OT_net::MyOTNotifyProc
(
void* contextPtr,
OTEventCode code,
OTResult result,
void* cookie
)
{
MyOTInfo* myOTInfoPtr = (MyOTInfo *) contextPtr;
switch (code)
{
case T_OPENCOMPLETE:
myOTInfoPtr->inetSvcRef = (InetSvcRef)cookie;
::OTInetStringToAddress(myOTInfoPtr->inetSvcRef, (char*)myOTInfoPtr->hostName, &myOTInfoPtr->hostInfo);
break;
case T_DNRSTRINGTOADDRCOMPLETE:
case T_DNRADDRTONAMECOMPLETE:
myOTInfoPtr->complete = true;
break;
}
}
BOOL OT_net::dns_ip_addr_found(BOOL * valid, ULONG32 *addr)
{
if (mDNSDone)
{
*valid = mHostIPValid;
*addr = mHostIPAddr;
return TRUE;
}
else
return FALSE;
return FALSE;
}
/***********Common code for OT_UDP/OT_TCP*************************/
pascal void OT_net::UDPTCPNotifyProc (
void *stream,
OTEventCode code,
OTResult result,
void *cookie )
{
HXMM_INTERRUPTON();
OT_net* s = (OT_net*) stream;
#ifdef _USE_OT_DEFER
if (s->m_OTDeferredCookie != 0)
#else
if (s->m_DeferredTaskStruct.dtAddr != NULL)
#endif
{
OTCallbackInfo* pOTCallbackInfo = new OTCallbackInfo(code, result, cookie);
s->AddToThePendingList((void*) pOTCallbackInfo);
if (!s->m_bDeferredTaskPending)
{
if ( !s->m_bIsQuitting )
{
s->m_bDeferredTaskPending = TRUE;
#ifdef _USE_OT_DEFER
OTScheduleDeferredTask(s->m_OTDeferredCookie);
#else
DTInstall(&s->m_DeferredTaskStruct);
#endif
}
}
}
HXMM_INTERRUPTOFF();
}
#ifdef _USE_OT_DEFER
pascal void OT_net::DeferredTaskProc(void* inParam)
#else
pascal void OT_net::DeferredTaskProc(long inParam)
#endif
{
HXMM_INTERRUPTON();
OT_net* s = (OT_net*) inParam;
if(s)
{
if ( !s->m_bIsQuitting )
{
s->ProcessPendingCallbacks();
}
s->m_bDeferredTaskPending = FALSE;
}
HXMM_INTERRUPTOFF();
}
void OT_net::AddToThePendingList(void* pNode)
{
/* Atleast one of the list MUST be free to operate on */
HX_ASSERT(!m_bUsingListOne || !m_bUsingListTwo);
if (!m_bUsingListOne)
{
if (!m_pPendingCallbackListOne)
{
m_pPendingCallbackListOne = new CHXSimpleList;
}
m_pPendingCallbackListOne->AddTail(pNode);
}
else if (!m_bUsingListTwo)
{
if (!m_pPendingCallbackListTwo)
{
m_pPendingCallbackListTwo = new CHXSimpleList;
}
m_pPendingCallbackListTwo->AddTail(pNode);
}
}
void OT_net::ProcessPendingCallbacks()
{
start:
m_bUsingListOne = TRUE;
while (m_pPendingCallbackListOne &&
!m_pPendingCallbackListOne->IsEmpty())
{
OTCallbackInfo* cmd = (OTCallbackInfo*) m_pPendingCallbackListOne->RemoveHead();
/* Send time sync for ONLY the last pending audio callback */
ProcessCmd(cmd->m_Code, cmd->m_Result, cmd->m_Cookie);
delete cmd;
}
m_bUsingListOne = FALSE;
m_bUsingListTwo = TRUE;
while (m_pPendingCallbackListTwo &&
!m_pPendingCallbackListTwo->IsEmpty())
{
OTCallbackInfo* cmd = (OTCallbackInfo*) m_pPendingCallbackListTwo->RemoveHead();
/* Send time sync for ONLY the last pending audio callback */
ProcessCmd(cmd->m_Code, cmd->m_Result, cmd->m_Cookie);
delete cmd;
}
m_bUsingListTwo = FALSE;
/* Do we still have more pending callbacks to process? */
if ((m_pPendingCallbackListOne && m_pPendingCallbackListOne->GetCount() > 0) ||
(m_pPendingCallbackListTwo && m_pPendingCallbackListTwo->GetCount() > 0))
{
goto start;
}
}
void OT_net::CleanupPendingLists()
{
m_bUsingListOne = TRUE;
while(m_pPendingCallbackListOne && !m_pPendingCallbackListOne->IsEmpty())
{
SndCommand* cmd = (SndCommand*)m_pPendingCallbackListOne->RemoveHead();
delete cmd;
}
m_bUsingListOne = FALSE;
m_bUsingListTwo = TRUE;
while(m_pPendingCallbackListTwo && !m_pPendingCallbackListTwo->IsEmpty())
{
SndCommand* cmd = (SndCommand*)m_pPendingCallbackListTwo->RemoveHead();
delete cmd;
}
m_bUsingListTwo = FALSE;
}
OTResult OT_net::GetFourByteOption(EndpointRef ep,
OTXTILevel level,
OTXTIName name,
UInt32 *value)
{
OTResult err;
TOption option;
TOptMgmt request;
TOptMgmt result;
/* Set up the option buffer */
option.len = kOTFourByteOptionSize;
option.level= level;
option.name = name;
option.status = 0;
option.value[0] = 0;// Ignored because we're getting the value.
/* Set up the request parameter for OTOptionManagement to point
to the option buffer we just filled out */
request.opt.buf= (UInt8 *) &option;
request.opt.len= sizeof(option);
request.flags= T_CURRENT;
/* Set up the reply parameter for OTOptionManagement. */
result.opt.buf = (UInt8 *) &option;
result.opt.maxlen = sizeof(option);
err = OTOptionManagement(ep, &request, &result);
if (err == noErr) {
switch (option.status)
{
case T_SUCCESS:
case T_READONLY:
*value = option.value[0];
break;
default:
err = option.status;
break;
}
}
return (err);
}
OTResult OT_net::SetFourByteOption(EndpointRef ep,
OTXTILevel level,
OTXTIName name,
UInt32 value)
{
OTResult err;
TOption option;
TOptMgmt request;
TOptMgmt result;
/* Set up the option buffer */
option.len = kOTFourByteOptionSize;
option.level= level;
option.name = name;
option.status = 0;
option.value[0] = value; // set the value here
/* Set up the request parameter for OTOptionManagement to point
to the option buffer we just filled out */
request.opt.buf= (UInt8 *) &option;
request.opt.len= sizeof(option);
request.flags= T_NEGOTIATE;
/* Set up the reply parameter for OTOptionManagement. */
result.opt.buf = (UInt8 *) &option;
result.opt.maxlen = sizeof(option);
err = OTOptionManagement(ep, &request, &result);
if (err == noErr) {
switch (option.status)
{
case T_SUCCESS:
case T_READONLY:
value = option.value[0];
break;
default:
err = option.status;
break;
}
}
return (err);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -