📄 ot_net.cp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "hxcom.h"
#include "Mac_net.h"
#include "OT_net.h"
#include "OT_TCP.h"
#include "OT_UDP.h"
#include "hxmm.h"
#include "hxerrors.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "hxslist.h"
ULONG32 OT_net::sMacAddress = 0L;
Boolean OT_net::sMacAddressValid = FALSE;
Boolean OT_net::sCheckedOT = FALSE;
Boolean OT_net::sHaveOT = FALSE;
Boolean OT_net::sMacAddressStrValid = FALSE;
char OT_net::sMacAddrStr[16];
#ifdef _CARBON
OTClientContextPtr OT_net::sOToutClientContext = NULL;
#endif
//#define _LOG_DATA 1
#if defined(_DEBUG) && defined (_LOG_DATA)
#define DEBUGSTR(x) DebugStr(x)
#else
#define DEBUGSTR(x)
#endif
OT_net*
OT_net::new_socket(UINT16 type)
{
OT_net *c = NULL;
switch(type)
{
case HX_TCP_SOCKET:
c = new OT_TCP;
break;
case HX_UDP_SOCKET:
c = new OT_UDP;
break;
}
return(c);
}
// Creator should set the socket reference to a value indicating the socket is not open
OT_net::OT_net (void)
: mActiveName (NULL)
, mRef (0)
, mDataArrived (FALSE)
, mDataFlowOn (FALSE)
, mClosing (FALSE)
, mOtherSideHasClosed (FALSE)
, mWeHaveClosed (FALSE)
, mRelease (FALSE)
, mStartedReceivingData (FALSE)
, mAsyncError(HXR_OK)
, m_lRefCount(0)
, m_pPendingCallbackListOne(NULL)
, m_pPendingCallbackListTwo(NULL)
, m_bUsingListOne(FALSE)
, m_bUsingListTwo(FALSE)
, m_bDeferredTaskPending(FALSE)
, m_bIsQuitting(FALSE)
{
#ifdef _USE_OT_DEFER
m_OTDeferredCookie = OTCreateDeferredTask(OT_net::DeferredTaskProc, this);
#else
m_DeferredTaskStruct.dtReserved = 0;
m_DeferredTaskStruct.dtFlags = 0;
#ifdef _CARBON
m_DeferredTaskStruct.dtAddr = NewDeferredTaskUPP(OT_net::DeferredTaskProc);;
#else
m_DeferredTaskStruct.dtAddr = NewDeferredTaskProc(OT_net::DeferredTaskProc);;
#endif
m_DeferredTaskStruct.dtParam = (long) this;
m_DeferredTaskStruct.qType = dtQType;
#endif
}
// ~OT_net should close the socket if it is open
OT_net::~OT_net(void)
{
m_bIsQuitting = TRUE;
UINT32 timeout = TickCount() + 300L;
while ( m_bDeferredTaskPending && timeout - TickCount() > 0 )
{
// sit-n-spin, awaiting completion of callbacks.
}
#ifdef _USE_OT_DEFER
if (m_OTDeferredCookie != 0)
{
OTDestroyDeferredTask(m_OTDeferredCookie);
m_OTDeferredCookie = 0;
}
#else
if (m_DeferredTaskStruct.dtAddr != NULL)
{
#ifdef _CARBON
DisposeDeferredTaskUPP(m_DeferredTaskStruct.dtAddr);
#else
DisposeRoutineDescriptor(m_DeferredTaskStruct.dtAddr);
#endif
m_DeferredTaskStruct.dtAddr = NULL;
}
#endif
CleanupPendingLists();
HX_DELETE(m_pPendingCallbackListOne);
HX_DELETE(m_pPendingCallbackListTwo);
if(mRef)
OTCloseProvider(mRef);
mRef = 0;
if (mActiveName)
delete [] mActiveName;
mActiveName = nil;
}
void
OT_net::done (void)
{
mLastError = HXR_OK;
}
#if 1
/*----------------------------------------------------------------------------
OTWait
Wait for an asynchronous Open Transport stream call to complete.
Exit: function result = error code.
----------------------------------------------------------------------------*/
HX_RESULT
OT_net::OTWait (void)
{
Boolean cancel = FALSE;
do {
cancel = Mac_net::CheckForCancel();
}
while (!mComplete && !cancel);
if(cancel)
mResult = HXR_BLOCK_CANCELED;
return mResult;
}
#else
/*----------------------------------------------------------------------------
OTWait
Wait for an asynchronous Open Transport stream call to complete.
Exit: function result = error code.
----------------------------------------------------------------------------*/
HX_RESULT
OT_net::OTWait (void)
{
EventRecord macEvent;
do {
WaitNextEvent(nullEvent, &macEvent, 0L,NULL);
}
while (!mComplete);
return mResult;
}
#endif
/*----------------------------------------------------------------------------
OTSvcWait
Wait for an asynchronous Open Transport Internet services call to complete.
Entry: svcInfo = pointer to OTSvcInfo struct.
Exit: function result = error code.
----------------------------------------------------------------------------*/
HX_RESULT
OT_net::OTSvcWait (OTSvcInfo *svcInfo)
{
Boolean cancel = FALSE;
HX_RESULT theErr = HXR_OK;
do
{
cancel = Mac_net::CheckForCancel();
}
while (!svcInfo->complete && !cancel);
if(cancel)
theErr = HXR_BLOCK_CANCELED;
else
theErr = svcInfo->result;
return theErr;
}
/*----------------------------------------------------------------------------
NetHaveOT
Determine whether we have Open Transport.
Exit: function result = true if Open Transport and Open Transport/TCP
are both installed.
----------------------------------------------------------------------------*/
Boolean
OT_net::NetHaveOT (void)
{
HX_RESULT theErr = HXR_OK;
long result;
if (!sCheckedOT)
{
theErr = Gestalt(gestaltOpenTpt, &result);
sHaveOT = theErr == HXR_OK &&
(result & gestaltOpenTptPresentMask) != 0 &&
(result & gestaltOpenTptTCPPresentMask) != 0;
sCheckedOT = true;
}
return sHaveOT;
}
/*----------------------------------------------------------------------------
MyOTInetSvcNotifyProc
Open Transport notifier proc for an Internet services provider.
Entry: svcIfno = pointer to MyOTInetSvcInfo struct.
code = OT event code.
result = OT result.
cookie = OT cookie.
----------------------------------------------------------------------------*/
pascal void OT_net::SvcNotifyProc (
void *stream,
OTEventCode code,
OTResult result,
void *cookie )
{
OTSvcInfo *svcInfo = (OTSvcInfo *) stream;
switch (code)
{
case T_OPENCOMPLETE:
case T_DNRSTRINGTOADDRCOMPLETE:
case T_DNRADDRTONAMECOMPLETE:
svcInfo->complete = true;
svcInfo->result = result;
svcInfo->cookie = cookie;
break;
}
}
/*----------------------------------------------------------------------------
OpenInetServices
Open an Internet services provider.
Entry: svcInfo = pointer to OTSvcInfo struct for this
provider.
Exit: function result = error code.
----------------------------------------------------------------------------*/
HX_RESULT
OT_net::OpenInetServices (OTSvcInfo *svcInfo)
{
HX_RESULT theErr = HXR_OK;
svcInfo->complete = false;
#ifdef _CARBON
theErr = OTAsyncOpenInternetServicesInContext(kDefaultInternetServicesPath, 0,
(OTNotifyUPP)SvcNotifyProc, svcInfo, NULL);
#else
theErr = OTAsyncOpenInternetServices(kDefaultInternetServicesPath, 0,
SvcNotifyProc, svcInfo);
#endif
if(!theErr) theErr = OTSvcWait(svcInfo);
if(!theErr) svcInfo->ref = (InetSvcRef) svcInfo->cookie;
return theErr;
}
/*----------------------------------------------------------------------------
NetGetMyAddr
Get this Mac's IP address.
Exit: function result = error code.
*addr = the IP address of this Mac.
With Open Transport, if the Mac has more than one IP interface, the
IP address of the default interface is returned.
----------------------------------------------------------------------------*/
HX_RESULT OT_net::NetGetMyAddr (unsigned long *addr)
{
HX_RESULT theErr = HXR_OK;
InetInterfaceInfo ifaceInfo;
if (!sMacAddressValid)
{
theErr = OTInetGetInterfaceInfo(&ifaceInfo, kDefaultInetInterface);
if (theErr != HXR_OK) return (theErr);
sMacAddress = ifaceInfo.fAddress;
sMacAddressValid = true;
}
*addr = sMacAddress;
return HXR_OK;
}
HX_RESULT OT_net::NetGetIfaceInfo(InetInterfaceInfo* ifaceInfo)
{
return (OTInetGetInterfaceInfo(ifaceInfo, kDefaultInetInterface));
}
HX_RESULT
OT_net::blocking(void)
{
return(HXR_OK);
}
HX_RESULT
OT_net::nonblocking(void)
{
return(HXR_OK);
}
/*----------------------------------------------------------------------------
NetGetMyAddrStr
Get this Mac's IP address as a dotted-decimal string
Exit: function result = error code.
name = this Mac's IP address, as a C-format string.
You must allocate at least 16 bytes for this string.
The returned string has max length 15.
----------------------------------------------------------------------------*/
HX_RESULT OT_net::NetGetMyAddrStr (char *addrStr)
{
unsigned long addr;
HX_RESULT theErr = HXR_OK;
if (!sMacAddressStrValid)
{
theErr = NetGetMyAddr(&addr);
if (theErr != HXR_OK) return (theErr);
sprintf(sMacAddrStr, "%ld.%ld.%ld.%ld",
(addr >> 24) & 0xff,
(addr >> 16) & 0xff,
(addr >> 8) & 0xff,
addr & 0xff);
sMacAddressStrValid = TRUE;
}
strcpy(addrStr, sMacAddrStr);
return HXR_OK;
}
/*----------------------------------------------------------------------------
NetNameToAddr
Translate a domain name to an IP address.
Entry: name = C-format domain name string, optionally followed by a
comma, space, or colon and then the port number.
defaultPort = default port number.
Exit: function result = error code.
*addr = IP address.
*port = port number.
----------------------------------------------------------------------------*/
HX_RESULT OT_net::NetNameToAddr (
char *name,
unsigned short defaultPort,
unsigned long *addr,
unsigned short *port)
{
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);
}
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);
}
OTCloseProvider(svcInfo.ref);
}
conn::add_to_cache(domainName, *addr);
if (mActiveName)
{
delete [] mActiveName;
mActiveName = NULL;
}
mActiveName = (Ptr) new char[ (::strlen (domainName) + 1)];
if (HXR_OK != (theErr = ::MemError ())) return (theErr);
::strcpy (mActiveName, domainName);
return HXR_OK;
}
/*----------------------------------------------------------------------------
NetAddrToName
Translate an IP address to a domain name.
Entry: addr = IP address.
Exit: function result = error code.
name = domain name, as a C-format string.
----------------------------------------------------------------------------*/
HX_RESULT OT_net::NetAddrToName (unsigned long addr, InetDomainName name)
{
HX_RESULT theErr = HXR_OK;
OTSvcInfo svcInfo;
theErr = OpenInetServices(&svcInfo);
if (theErr != HXR_OK) return (theErr);
svcInfo.complete = false;
theErr = OTInetAddressToName(svcInfo.ref, addr, name);
if (theErr == HXR_OK) theErr = OTSvcWait(&svcInfo);
OTCloseProvider(svcInfo.ref);
if (theErr != HXR_OK) {
if (theErr == kOTNoDataErr || theErr == kOTBadNameErr) theErr = HXR_BIND;
return (theErr);
}
return HXR_OK;
}
// init_drivers() should do any network driver initialization here
// params is a pointer to a platform specfic defined struct that
// contains an required initialization data
HX_RESULT
OT_net::init_drivers(void *params)
{
return(NetInit());
}
HX_RESULT OT_net::NetInit (void)
{
HX_RESULT theErr = HXR_OK;
if(NetHaveOT())
{
#ifdef _CARBON
theErr = InitOpenTransportInContext(kInitOTForApplicationMask, &sOToutClientContext);
// in the embedded player case, the above call may fail
// so try again with kInitOTForExtensionMask flag
// sOToutClientContext has to be provided when not calling from an application
if (theErr != HXR_OK)
{
theErr = InitOpenTransportInContext(kInitOTForExtensionMask, &sOToutClientContext);
}
HX_ASSERT( theErr == HXR_OK );
if (theErr != HXR_OK) return HXR_OK;
#else
theErr = InitOpenTransport();
#endif
if (theErr != HXR_OK) return HX_OPEN_DRIVER_ERROR;
}
else
theErr = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -