ot_tcp.cp
来自「symbian 下的helix player源代码」· CP 代码 · 共 1,147 行 · 第 1/2 页
CP
1,147 行
/* ***** BEGIN LICENSE BLOCK *****
* Source last modified: $Id: ot_tcp.cp,v 1.3.42.1 2004/07/09 02:06:38 hubbe Exp $
*
* Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the current version of the RealNetworks Community
* Source License (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.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL") in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your version of
* this file only under the terms of the GPL, and not to allow others
* to use your version of this file under the terms of either the RPSL
* or RCSL, indicate your decision by deleting the provisions above
* and replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient may
* use your version of this file under the terms of any one of the
* RPSL, the RCSL or the GPL.
*
* 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 "OT_TCP.h"
#include "MWDebug.h"
#include "hxerrors.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "hxmm.h"
//#define _LOG_DATA 1
//#define USE_DEFERRED_IMPL 1
#if defined(_DEBUG) && defined (_LOG_DATA)
#define DEBUGSTR(x) DebugStr(x)
#else
#define DEBUGSTR(x)
#endif
//#include "dcon.h"
OT_TCP::OT_TCP (void)
: mDNSOpen (FALSE)
, mSocketOpen (FALSE)
, mState (TCP_STATE_CLOSED)
, mDNSRef (0)
, mRemoteHostName (0)
, mNewConnection(NULL)
, mDataReady(FALSE)
{ /* begin OT_TCP */
//dprintf("this:%X OT_TCP::OT_TCP\n", this);
} /* end OT_TCP */
OT_TCP::~OT_TCP (void)
{ /* begin ~OT_TCP */
//dprintf("this:%X OT_TCP::~OT_TCP\n", this);
Cleanup(TRUE);
if(mRemoteHostName)
{
delete mRemoteHostName;
mRemoteHostName = NULL;
}
} /* end ~OT_TCP */
void
OT_TCP::done(void)
{
//dprintf("this:%X OT_TCP::done\n", this);
Cleanup(TRUE);
}
/*----------------------------------------------------------------------------
Cleanup
Cleanup a TCP stream.
Exit: function result = error code.
Any active connection is also aborted, if necessary, before releasing
the stream.
----------------------------------------------------------------------------*/
OSErr OT_TCP::Cleanup (Boolean orderly /* = FALSE */ )
{
//dprintf("this:%X OT_TCP::Cleanup orderly:%s\n", this, (orderly? "TRUE" : "FALSE"));
OSErr theErr = HXR_OK;
Boolean abort;
mState = TCP_STATE_CLOSED;
close_resolver();
if(mRef)
{
abort = (!mOtherSideHasClosed || !mWeHaveClosed) && mConnectionOpen;
if (abort)
{
mComplete = FALSE;
if (orderly && mStartedReceivingData)
{
mComplete = FALSE;
theErr = ::OTSndOrderlyDisconnect(mRef);
EventRecord macEvent;
long ticks = TickCount();
do
{
#ifndef THREADS_SUPPORTED
// xxxbobclark when threading networking is
// on, this code may be executing on a non-main-
// app thread. I don't even know what WNE would
// do in that scenario, but that it'd be bad.
WaitNextEvent(nullEvent, &macEvent, 6,NULL);
#endif
}
while (!mComplete && ((TickCount() - ticks) < 120));
}
else
theErr = ::OTSndDisconnect(mRef, nil);
}
::OTRemoveNotifier(mRef); // DS 12.4.95
theErr = ::OTCloseProvider(mRef);
}
if ( mNewConnection )
{
mNewConnection->done();
HX_RELEASE(mNewConnection);
}
mRef = 0;
return theErr;
}
HX_RESULT
OT_TCP::connect (
const char *host,
UINT16 port,
UINT16 blocking,
ULONG32 ulPlatform )
{
//dprintf("this:%X OT_TCP::connect - host:%s port:%u\n", this, host, port);
HX_RESULT theErr = HXR_OK;
// check if socket is in a valid state
if(mState != TCP_STATE_CLOSED)
return HXR_SOCKET_CREATE; // should be PN_SOCKET_STATE_ERROR
if(mRemoteHostName)
{
delete mRemoteHostName;
mRemoteHostName = NULL;
}
// allocate a buffer to hold the host name
mRemoteHostName = new char[::strlen(host) + 1];
if(mRemoteHostName == NULL)
theErr = HXR_OUTOFMEMORY;
if(!theErr)
{
mConnectionOpen = FALSE;
mRemotePort = port;
mDataFlowOn = FALSE;
mDataArrived = FALSE;
mAsyncError = HXR_OK;
// save a copy of the host name
::strcpy(mRemoteHostName,host);
// check if host name is already in IP format or has been cached
if((::OTInetStringToHost(mRemoteHostName, &mRemoteHost) == HXR_OK) ||
(conn::is_cached(mRemoteHostName,&mRemoteHost)))
{
// open the socket, bind and connect to remote host
mState = TCP_STATE_OPEN_SOCKET;
theErr = open_socket();
}
else // DNR is required on host name
{
// do DNR,open the socket, bind and connect to remote host
theErr = open_resolver();
}
}
if(!theErr && blocking)
{
// wait for mConnectionOpen == TRUE or cancel
}
return theErr;
}
HX_RESULT
OT_TCP::init (
UINT32 local_addr,
UINT16 port,
UINT16 blocking)
{
//dprintf("this:%X OT_TCP::init\n", this);
return (HXR_INVALID_OPERATION);
}
/*----------------------------------------------------------------------------
write
Send data on a stream.
Entry: data = pointer to data to send.
len = length of data to send.
Exit: function result = error code.
----------------------------------------------------------------------------*/
HX_RESULT
OT_TCP::write (
void *data,
UINT16 *len)
{
//dprintf("this:%X OT_TCP::write\n", this);
HX_RESULT theErr = HXR_OK;
mLastError=HXR_OK;
if(mAsyncError)
{
theErr = mAsyncError;
mAsyncError = HXR_OK;
return theErr;
}
OTResult result;
unsigned short length, count;
count = 0;
if (mOtherSideHasClosed) //cz
theErr = HXR_SERVER_DISCONNECTED;
else if (!mOtherSideHasClosed && !mConnectionOpen)
theErr = HXR_WOULD_BLOCK;
else
{
#if 1
if(mDataFlowOn)
{
// DebugStr("\pDataFlowOn");
*len = 0;
return(HXR_WOULD_BLOCK);
}
#endif
length = *len;
while (length > 0 && !theErr)
{
result = ::OTSnd(mRef, data, length, 0);
if (result >= 0)
{
count += result;
length -= result;
}
else
{
#if 0
Str255 s;
NumToString(result,s);
DebugStr(s);
#endif
switch(result)
{
case kOTFlowErr:
mWriteReady = FALSE;
mDataFlowOn = TRUE;
theErr = HXR_WOULD_BLOCK;
break;
case kENOMEMErr:
case kEBUSYErr:
case kOTOutStateErr:
case kEWOULDBLOCKErr:
case kOTStateChangeErr:
case kOTLookErr:
mLastError = HXR_WOULD_BLOCK;
theErr = HXR_WOULD_BLOCK;
break;
default:
#if 0
Str255 s;
DebugStr("\pOT_TCP::read");
NumToString(result,s);
DebugStr(s);
#endif
mLastError = HXR_SERVER_DISCONNECTED;
theErr = HXR_SERVER_DISCONNECTED;
break;
}
break; // break out of the while loop
}
}
}
*len = count; // return actual number of bytes written
return theErr;
}
/*----------------------------------------------------------------------------
read
read data on a stream.
Entry: data = pointer to data buffer.
*len = length of data buffer.
Exit: function result = error code.
*len = number of bytes received.
----------------------------------------------------------------------------*/
HX_RESULT
OT_TCP::read (void *data, UINT16 *len)
{
//dprintf("this:%X OT_TCP::read\n", this);
//dprintf("mConnectionOpen: %s\n", (mConnectionOpen ? "TRUE" : "FALSE") );
//dprintf("mOtherSideHadClosed: %s\n", (mOtherSideHasClosed ? "TRUE" : "FALSE"));
//dprintf("mDataArrived: %s\n", (mDataArrived ? "TRUE" : "FALSE"));
HX_RESULT theErr = HXR_OK;
OTResult result;
mLastError=HXR_OK;
if(mAsyncError)
{
theErr = mAsyncError;
mAsyncError = HXR_OK;
return theErr;
}
if (mOtherSideHasClosed)
theErr = HXR_SERVER_DISCONNECTED;
else if (!mOtherSideHasClosed && !mConnectionOpen)
theErr = HXR_WOULD_BLOCK;
else
{
if(!mDataArrived)
{
*len = 0;
mLastError = HXR_WOULD_BLOCK;
return HXR_WOULD_BLOCK;
}
result = ::OTRcv(mRef, data, *len, nil);
if (result >= 0)
{
//dprintf("data read\n");
*len = result;
theErr = HXR_OK;
}
else
{
//dprintf("read error\n");
switch(result)
{
/* take out this case after HXTCPSocket::TCPSchedulerCallbackProc
gets implemented - we're not getting data fast enough now XXXZach */
case kOTNoDataErr:
*len = 0;
theErr = HXR_OK;
break;
case kEBUSYErr:
case kOTOutStateErr:
case kEWOULDBLOCKErr:
case kOTStateChangeErr:
case kOTLookErr:
*len = 0;
mLastError = HXR_WOULD_BLOCK;
theErr = HXR_WOULD_BLOCK;
break;
default:
#if 0
Str255 s;
DebugStr("\pOT_TCP::read");
NumToString(result,s);
DebugStr(s);
#endif
*len = 0;
mLastError = HXR_SERVER_DISCONNECTED;
theErr = HXR_SERVER_DISCONNECTED; //cz
break;
}
}
}
return theErr;
}
HX_RESULT
OT_TCP::readfrom (REF(IHXBuffer*) pBuffer,
REF(UINT32) ulAddress,
REF(UINT16) ulPort)
{
//dprintf("this:%X OT_TCP::readfrom\n", this);
pBuffer = NULL;
ulAddress = 0;
ulPort = 0;
return HXR_NOTIMPL;
}
HX_RESULT OT_TCP::listen(ULONG32 ulLocalAddr,
UINT16 port,
UINT16 backlog,
UINT16 blocking,
ULONG32 ulPlatform)
{
//dprintf("this:%X OT_TCP::listen address:%X port:%u\n", this, ulLocalAddr, port);
// check if socket is in a valid state
if(mState != TCP_STATE_CLOSED)
return HXR_UNEXPECTED; // should be PN_SOCKET_STATE_ERROR
OSErr theErr = HXR_OK;
InetAddress reqAd,retAd;
TBind req,ret;
// Open TCP endpoint
mState = TCP_STATE_OPEN_LISTEN;
mComplete = false;
// Note: We are using the UDPTCPNotifyProc... Therefore we do
// not get a Proccess command call at interupt time. Normal
// operation somehow gets away with it...
#ifdef _CARBON
theErr = ::OTAsyncOpenEndpointInContext(OTCreateConfiguration(kTCPName), 0,NULL,
(OTNotifyUPP)UDPTCPNotifyProc, this, NULL);
#else
theErr = ::OTAsyncOpenEndpoint(OTCreateConfiguration(kTCPName),
0,NULL, UDPTCPNotifyProc, this);
#endif
if ( theErr )
{
mLastError = theErr;
theErr = HXR_SOCKET_CREATE;
}
// wait for open completion
if(!theErr)
{
theErr = OTWait();
if(theErr == kOTNoDataErr) theErr = HXR_OK;
if(theErr || mCode != T_OPENCOMPLETE)
{
theErr = theErr ? theErr : HXR_SOCKET_CREATE;
mLastError = theErr;
theErr = HXR_SOCKET_CREATE;
}
}
if ( !theErr )
{
// get Inet address of port
OTInitInetAddress(&reqAd, port, (InetHost) ulLocalAddr);
// bind tcp to current address and requested port
req.addr.maxlen = sizeof(struct InetAddress);
req.addr.len = sizeof(struct InetAddress);
req.addr.buf = (unsigned char *) &reqAd;
req.qlen = 1;
ret.addr.maxlen = sizeof(struct InetAddress);
ret.addr.len = sizeof(struct InetAddress);
ret.addr.buf = (unsigned char *) &retAd;
// clear completion flag
mComplete = false;
mState = TCP_STATE_BIND_LISTEN;
// bind provider to return structure
theErr = OTBind(mRef, &req, &ret);
}
if(theErr)
{
mLastError = theErr;
theErr = HXR_BIND;
}
// wait for bind completion
if(!theErr)
{
theErr = OTWait();
if(theErr == kOTNoDataErr) theErr = HXR_OK;
if(theErr || mCode != T_BINDCOMPLETE)
{
theErr = theErr ? theErr : HXR_BIND;
mLastError = theErr;
theErr = HXR_BIND;
}
}
// get local port
if(!theErr)
{
mConnectionOpen = FALSE;
mRemotePort = port;
mDataFlowOn = FALSE;
mDataArrived = FALSE;
mAsyncError = HXR_OK;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?