⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ot_tcp.cp

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 CP
📖 第 1 页 / 共 2 页
字号:
/* ***** 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 "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;
		
		mState = TCP_STATE_LISTEN;
	}
	if ( !theErr )
	{
		// check to see if we are not being called again...
		// calling done() on mNewConnection should be fine, because
		// it should be released after a connection has been accepted. 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -