Example #1
0
static int getSocket(int conid) {
  size_t len;
  char *info_name;
  int readfd;
  void *info = GetConnectionInfo(conid,&info_name, &readfd, &len);
  return (info_name && strcmp(info_name,"tcp")==0) ? readfd : -1;
}
Example #2
0
void
nsHttpPipeline::Close(nsresult reason)
{
    LOG(("nsHttpPipeline::Close [this=%p reason=%x]\n", this, reason));

    if (mClosed) {
        LOG(("  already closed\n"));
        return;
    }

    // the connection is going away!
    mStatus = reason;
    mClosed = true;

    nsRefPtr<nsHttpConnectionInfo> ci;
    GetConnectionInfo(getter_AddRefs(ci));
    uint32_t numRescheduled = CancelPipeline(reason);

    // numRescheduled can be 0 if there is just a single response in the
    // pipeline object. That isn't really a meaningful pipeline that
    // has been forced to be rescheduled so it does not need to generate
    // negative feedback.
    if (ci && numRescheduled)
        gHttpHandler->ConnMgr()->PipelineFeedbackInfo(
            ci, nsHttpConnectionMgr::RedCanceledPipeline, nullptr, 0);

    nsAHttpTransaction *trans = Response(0);
    if (!trans)
        return;

    // The current transaction can be restarted via reset
    // if the response has not started to arrive and the reason
    // for failure is innocuous (e.g. not an SSL error)
    if (!mResponseIsPartial &&
        (reason == NS_ERROR_NET_RESET ||
         reason == NS_OK ||
         reason == NS_ERROR_NET_TIMEOUT ||
         reason == NS_BASE_STREAM_CLOSED)) {
        trans->Close(NS_ERROR_NET_RESET);
    }
    else {
        trans->Close(reason);
    }

    NS_RELEASE(trans);
    mResponseQ.Clear();
}
/// <summary>Sets the connection string used to open a DataStore. SetConnectionString can only be set while the
/// connection is closed.</summary>
/// <param name="value">Input the connection string</param> 
/// <returns>Returns nothing</returns> 
void SuperMapConnection::SetConnectionString (FdoString* value)
{
	TRACE(_T("调用 SuperMapConnection::SetConnectionString(%ls)。\n"), value);
	FdoConnectionState state = GetConnectionState();
	if (state == FdoConnectionState_Closed || state == FdoConnectionState_Pending)
	{
		// Update the connection string:
		m_ConnectionString = value;

		// Update the connection property dictionary:
		FdoPtr<FdoIConnectionInfo> connInfo = GetConnectionInfo();
		FdoPtr<FdoCommonConnPropDictionary> connDict = dynamic_cast<FdoCommonConnPropDictionary*>(connInfo->GetConnectionProperties());
		connDict->UpdateFromConnectionString(m_ConnectionString);
	}
	else
		throw FdoException::Create (NlsMsgGet(SUPERMAP_CONNECTION_ALREADY_OPEN, "The connection is already open."));
}
NS_INTERFACE_MAP_END


//-----------------------------------------------------------------------------
// nsHttpPipeline::nsAHttpConnection
//-----------------------------------------------------------------------------

nsresult
nsHttpPipeline::OnHeadersAvailable(nsAHttpTransaction *trans,
                                   nsHttpRequestHead *requestHead,
                                   nsHttpResponseHead *responseHead,
                                   bool *reset)
{
    LOG(("nsHttpPipeline::OnHeadersAvailable [this=%x]\n", this));

    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
    NS_ASSERTION(mConnection, "no connection");
    
    nsRefPtr<nsHttpConnectionInfo> ci;
    GetConnectionInfo(getter_AddRefs(ci));

    NS_ABORT_IF_FALSE(ci, "no connection info");
    
    bool pipeliningBefore = gHttpHandler->ConnMgr()->SupportsPipelining(ci);
    
    // trans has now received its response headers; forward to the real connection
    nsresult rv = mConnection->OnHeadersAvailable(trans,
                                                  requestHead,
                                                  responseHead,
                                                  reset);
    
    if (!pipeliningBefore && gHttpHandler->ConnMgr()->SupportsPipelining(ci))
        // The received headers have expanded the eligible
        // pipeline depth for this connection
        gHttpHandler->ConnMgr()->ProcessPendingQForEntry(ci);

    return rv;
}
nsresult
nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer,
                              PRUint32 count,
                              PRUint32 *countWritten)
{
    LOG(("nsHttpPipeline::WriteSegments [this=%x count=%u]\n", this, count));

    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");

    if (mClosed)
        return NS_SUCCEEDED(mStatus) ? NS_BASE_STREAM_CLOSED : mStatus;

    nsAHttpTransaction *trans; 
    nsresult rv;

    trans = Response(0);
    // This code deals with the establishment of a CONNECT tunnel through
    // an HTTP proxy. It allows the connection to do the CONNECT/200
    // HTTP transaction to establish an SSL tunnel as a precursor to the
    // actual pipeline of regular HTTP transactions.
    if (!trans && mRequestQ.Length() &&
        mConnection->IsProxyConnectInProgress()) {
        LOG(("nsHttpPipeline::WriteSegments [this=%p] Forced Delegation\n",
             this));
        trans = Request(0);
    }

    if (!trans) {
        if (mRequestQ.Length() > 0)
            rv = NS_BASE_STREAM_WOULD_BLOCK;
        else
            rv = NS_BASE_STREAM_CLOSED;
    }
    else {
        // 
        // ask the transaction to consume data from the connection.
        // PushBack may be called recursively.
        //
        rv = trans->WriteSegments(writer, count, countWritten);

        if (rv == NS_BASE_STREAM_CLOSED || trans->IsDone()) {
            trans->Close(NS_OK);

            // Release the transaction if it is not IsProxyConnectInProgress()
            if (trans == Response(0)) {
                NS_RELEASE(trans);
                mResponseQ.RemoveElementAt(0);
                mResponseIsPartial = false;
                ++mHttp1xTransactionCount;
            }

            // ask the connection manager to add additional transactions
            // to our pipeline.
            nsRefPtr<nsHttpConnectionInfo> ci;
            GetConnectionInfo(getter_AddRefs(ci));
            if (ci)
                gHttpHandler->ConnMgr()->ProcessPendingQForEntry(ci);
        }
        else
            mResponseIsPartial = true;
    }

    if (mPushBackLen) {
        nsHttpPushBackWriter writer(mPushBackBuf, mPushBackLen);
        PRUint32 len = mPushBackLen, n;
        mPushBackLen = 0;

        // This progress notification has previously been sent from
        // the socket transport code, but it was delivered to the
        // previous transaction on the pipeline.
        nsITransport *transport = Transport();
        if (transport)
            OnTransportStatus(transport,
                              nsISocketTransport::STATUS_RECEIVING_FROM,
                              mReceivingFromProgress);

        // the push back buffer is never larger than NS_HTTP_SEGMENT_SIZE,
        // so we are guaranteed that the next response will eat the entire
        // push back buffer (even though it might again call PushBack).
        rv = WriteSegments(&writer, len, &n);
    }

    return rv;
}
Example #6
0
File: DOSAPI.c Project: g8bpq/BPQ32
VOID CHOSTAPI(ULONG * pEAX, ULONG * pEBX, ULONG * pECX, ULONG * pEDX, VOID ** pESI, VOID ** pEDI)
{
	ULONG EAX = *pEAX;
	ULONG EBX = *pEBX;
	ULONG ECX = *pECX;
	ULONG EDX = *pEDX;
	VOID * ESI = *pESI;
	VOID * EDI = *pEDI;

	int Command;
	int Stream;
	int n;
	int Temp;
	PBPQVECSTRUC HostVec;
	TRANSPORTENTRY * Session;

/*
;	COMMANDS SUPPORTED ARE
;
;	AH = 0	Get node/switch version number and description.  On return
;		AH = major version number and AL = minor version number,
;		and user's buffer pointed to by ES:ESI is set to the text
;		string normally output by the USERS command, eg:
;		"G8BPQ Packet Switch Version 4.01 Dev".  CX is set to the
;		length of the text string.
;
;
;	AH = 1	Set application mask to value in DL (or even DX if 16
;		applications are ever to be supported).
;
;		Set application flag(s) to value in CL (or CX).
;		whether user gets connected/disconnected messages issued
;		by the node etc.
;
;
;	AH = 2	Send frame in ES:ESI (length CX)
;
;
;	AH = 3	Receive frame into buffer at ES:ESI, length of frame returned
;		in CX.  BX returns the number of outstanding frames still to
;		be received (ie. after this one) or zero if no more frames
;		(ie. this is last one).
;
;
;
;	AH = 4	Get stream status.  Returns:
;
;		CX = 0 if stream disconnected or CX = 1 if stream connected
;		DX = 0 if no change of state since last read, or DX = 1 if
;		       the connected/disconnected state has changed since
;		       last read (ie. delta-stream status).
;
;
;
;	AH = 6	Session control.
;
;		CX = 0 Conneect - _APPLMASK in DL
;		CX = 1 connect
;		CX = 2 disconnect
;		CX = 3 return user to node
;
;
;	AH = 7	Get buffer counts for stream.  Returns:
;
;		AX = number of status change messages to be received
;		BX = number of frames queued for receive
;		CX = number of un-acked frames to be sent
;		DX = number of buffers left in node
;		SI = number of trace frames queued for receive
;
;AH = 8		Port control/information.  Called with a stream number
;		in AL returns:
;
;		AL = Radio port on which channel is connected (or zero)
;		AH = SESSION TYPE BITS
;		BX = L2 paclen for the radio port
;		CX = L2 maxframe for the radio port
;		DX = L4 window size (if L4 circuit, or zero)
;		ES:EDI = CALLSIGN

;AH = 9		Fetch node/application callsign & alias.  AL = application
;		number:
;
;		0 = node
;		1 = BBS
;		2 = HOST
;		3 = SYSOP etc. etc.
;
;		Returns string with alias & callsign or application name in
;		user's buffer pointed to by ES:ESI length CX.  For example:
;
;		"WORCS:G8TIC"  or "TICPMS:G8TIC-10".
;
;
;	AH = 10	Unproto transmit frame.  Data pointed to by ES:ESI, of
;		length CX, is transmitted as a HDLC frame on the radio
;		port (not stream) in AL.
;
;
;	AH = 11 Get Trace (RAW Data) Frame into ES:EDI,
;			 Length to CX, Timestamp to AX
;
;
;	AH = 12 Update Switch. At the moment only Beacon Text may be updated
;		DX = Function
;		     1=update BT. ES:ESI, Len CX = Text
;		     2=kick off nodes broadcast
;
;	AH = 14 Internal Interface for IP Router
;
;		Send frame - to NETROM L3 if DL=0
;			     to L2 Session if DL<>0
;
;
; 	AH = 15 Get interval timer
;

*/

	Command = (EAX & 0xFFFF) >> 8;

	Stream = (EAX & 0xFF);
	n = Stream - 1;				// API Numbers Streams 1-64 

	if (n < 0 || n > 63)
		n = 64;

	HostVec = &BPQHOSTVECTOR[n];
	Session = HostVec->HOSTSESSION;

	switch (Command)
	{
	case 0:					// Check Loaded/Get Version
	
		EAX = ('P' << 8) | 'B';
		EBX =  ('Q' << 8) | ' ';
	
		EDX = (MAJORVERSION << 8) | MINORVERSION; 
		break;

	case 1:					// Set Appl mAsk
	
		HostVec->HOSTAPPLMASK = EDX;	// APPL MASK
		HostVec->HOSTAPPLFLAGS = (UCHAR)ECX;	// APPL FLAGS
	
		// If either is non-zero, set allocated and Process. This gets round problem with
		// stations that don't call allocate stream
	
		if (ECX || EBX)
		{
			HostVec->HOSTFLAGS |= 0x80;		// SET ALLOCATED BIT	
			HostVec->STREAMOWNER = GetCurrentProcessId();
	
			//	Set Program Name

			memcpy(&HostVec->PgmName, pgm, 31);
		}
		break;

	case 2:							// Send Frame

		//	ES:ESI = MESSAGE, CX = LENGTH, BX = VECTOR

		EAX = SendMsg(Stream, ESI, ECX);
		break;
	
	case 3:

	//	AH = 3	Receive frame into buffer at ES:EDI, length of frame returned
	//		in CX.  BX returns the number of outstanding frames still to
	//		be received (ie. after this one) or zero if no more frames
	//		(ie. this is last one).

		EAX = GetMsg(Stream, EDI, &ECX, &EBX);
		break;

	case 4:

	//	AH = 4	Get stream status.  Returns:
	//	CX = 0 if stream disconnected or CX = 1 if stream connected
	//	DX = 0 if no change of state since last read, or DX = 1 if
	//	       the connected/disconnected state has changed since
	//	       last read (ie. delta-stream status).

		ECX = EDX = 0;

		if (HostVec->HOSTFLAGS & 3)		//STATE CHANGE BITS
			EDX = 1;

		if (Session)
			ECX = 1;
		
		break;
		
	case 5:

	//	AH = 5	Ack stream status change

		HostVec->HOSTFLAGS &= 0xFC;		// Clear Chnage Bits
		break;

	case 6:

	//	AH = 6	Session control.

	//	CX = 0 Conneect - APPLMASK in DL
	//	CX = 1 connect
	//	CX = 2 disconnect
	//	CX = 3 return user to node

		SessionControl(Stream, ECX, EDX);
		break;

	case 7:

	//	AH = 7	Get buffer counts for stream.  Returns:

	//	AX = number of status change messages to be received
	//	BX = number of frames queued for receive
	//	CX = number of un-acked frames to be sent
	//	DX = number of buffers left in node
	//	SI = number of trace frames queued for receive


	ECX = 0;				// unacked frames
	EDX = QCOUNT;

	ESI = (void *)MONCount(Stream);
	EBX = RXCount(Stream);
	ECX = TXCount(Stream);

	EAX = 0;				// Is this right ???

	break;

	case 8:

	//	AH = 8		Port control/information.  Called with a stream number
	//		in AL returns:
	//
	//	AL = Radio port on which channel is connected (or zero)
	//	AH = SESSION TYPE BITS
	//	BX = L2 paclen for the radio port
	//	CX = L2 maxframe for the radio port
	//	DX = L4 window size (if L4 circuit, or zero)
	//	ES:EDI = CALLSIGN


		GetConnectionInfo(Stream, EDI, &EAX, &Temp, &EBX, &ECX, &EDX); // Return the Secure Session Flag rather than not connected
		EAX |= Temp <<8;

		break;


	case 9:

		// Not Implemented

		break;

	case 10:

	//	AH = 10	Unproto transmit frame.  Data pointed to by ES:ESI, of
	//	length CX, is transmitted as a HDLC frame on the radio
	//	port (not stream) in AL.

		EAX = SendRaw(EAX, ESI, ECX);
		return;

	case 11:

	//	AH = 11 Get Trace (RAW Data) Frame into ES:EDI,
	//	 Length to CX, Timestamp to AX

		EAX =  GetRaw(Stream, EDI, &ECX, &EBX);
		break;

	case 12:

	// Update Switch

		if (EDX == 2)
		{
			SENDNODESMSG();
			break;
		}
		if (EDX == 2)
		{
			//	UPDATE BT

			BTLENGTH = ECX;
			memcpy(BTEXTFLD, ESI, ECX + 7);
		}

		break;

	case 13:

		// BPQALLOC

		//	AL = 0 = Find Free
		//	AL != 0 Alloc or Release

		if (EAX == 0)
		{
			EAX = FindFreeStream();
			break;
		}

		if (ECX == 1)			// Allocate
		{
			 EAX = AllocateStream(Stream);
			 break;
		}
		
		DeallocateStream(Stream);
		break;

	case 14:

	//	AH = 14 Internal Interface for IP Router

	//	Send frame - to NETROM L3 if DL=0
	//	             to L2 Session if DL<>0

		break;			// Shouldn't be needed

	case 15:

		// GETTIME

		EAX = REALTIMETICKS;
		EBX = 0;
	
#ifdef EXCLUDEBITS
	
		EBX = (ULONG)ExcludeList;

#endif
		break;

	}

	*pEAX = EAX;
	*pEBX = EBX;
	*pECX = ECX;
	*pEDX = EDX;
	*pESI = ESI;
	*pEDI = EDI;

	return;
}	
Example #7
0
//============================================================================
//		NMessageServer::ServerThread : Server thread.
//----------------------------------------------------------------------------
void NMessageServer::ServerThread(NSocket *theSocket)
{	NNetworkMessage			msgServerInfo, msgConnectRequest, msgConnectResponse;
	NStatus					theErr, acceptErr;
	NMessageHandshake		clientHandshake;
	NString					thePassword;
	NDictionary				serverInfo;
	bool					addClient;
	NEntityID				clientID;



	// Validate our state
	NN_ASSERT(mStatus == kNServerStarted);



	// Do the handshake
	theErr = ReadHandshake(theSocket, clientHandshake);

	if (theErr == kNoErr)
		theErr = WriteHandshake(theSocket, CreateHandshake());

	if (theErr == kNoErr)
		theErr = ValidateHandshake(clientHandshake);

	if (theErr != kNoErr)
		{
		theSocket->Close(theErr);
		return;
		}



	// Send the server info
	mLock.Lock();
	serverInfo    = GetConnectionInfo();
	msgServerInfo = CreateMessage(kNMessageServerInfoMsg, kNEntityEveryone);
	msgServerInfo.SetProperties(serverInfo);
	mLock.Unlock();

	theErr = WriteMessage(theSocket, msgServerInfo);
	if (theErr != kNoErr)
		{
		theSocket->Close(theErr);
		return;
		}



	// Read the connection request
	//
	// If the client does not wish to continue connecting, they will disconnect.
	theErr = ReadMessage(theSocket, msgConnectRequest);
	if (theErr != kNoErr)
		{
		theSocket->Close();
		return;
		}

	NN_ASSERT(msgConnectRequest.GetType()   == kNMessageConnectRequestMsg);
	NN_ASSERT(msgConnectRequest.GetSource() == kNEntityInvalid);



	// Accept the connection
	mLock.Lock();

	clientID  = GetNextClientID();
	acceptErr = AcceptConnection(serverInfo, msgConnectRequest.GetProperties(), clientID);

	msgConnectResponse = CreateMessage(kNMessageConnectResponseMsg, clientID);
	msgConnectResponse.SetValue(kNMessageStatusKey, acceptErr);

	theErr    = WriteMessage(theSocket, msgConnectResponse);
	addClient = (theErr == kNoErr && acceptErr == kNoErr);
	
	if (addClient)
		AddClient(clientID, theSocket);

	mLock.Unlock();

	if (!addClient)
		{
		theSocket->Close(theErr);
		return;
		}



	// Process messages
	ClientConnected(clientID);

	ProcessMessages(theSocket);
}
Example #8
0
int Connected(Stream)
{
	int n;
	ChatCIRCUIT * conn;
	struct UserInfo * user = NULL;
	char callsign[10];
	int port, paclen, maxframe, l4window;
	char ConnectedMsg[] = "*** CONNECTED    ";
	char Msg[100];
	LINK    *link;
	KNOWNNODE *node;

	for (n = 0; n < NumberofChatStreams; n++)
	{
  		conn = &ChatConnections[n];
		
		if (Stream == conn->BPQStream)
		{
			if (conn->Active)
			{
				// Probably an outgoing connect
		
				if (conn->rtcflags == p_linkini)
				{
					conn->paclen = 236;
					nprintf(conn, "c %s\r", conn->u.link->call);
					return 0;
				}
			}
	
			memset(conn, 0, sizeof(ChatCIRCUIT));		// Clear everything
			conn->Active = TRUE;
			conn->BPQStream = Stream;

			conn->Secure_Session = GetConnectionInfo(Stream, callsign,
				&port, &conn->SessType, &paclen, &maxframe, &l4window);

			conn->paclen = paclen;

			strlop(callsign, ' ');		// Remove trailing spaces

			memcpy(conn->Callsign, callsign, 10);

			strlop(callsign, '-');		// Remove any SSID

			user = zalloc(sizeof(struct UserInfo));

			strcpy(user->Call, callsign);

			conn->UserPointer = user;

			n=sprintf_s(Msg, sizeof(Msg), "Incoming Connect from %s", user->Call);
			
			// Send SID and Prompt

			WriteLogLine(conn, '|',Msg, n, LOG_CHAT);
			conn->Flags |= CHATMODE;

			nodeprintf(conn, ChatSID, Ver[0], Ver[1], Ver[2], Ver[3]);

			// See if from a defined node
				
			for (link = link_hd; link; link = link->next)
			{
				if (matchi(conn->Callsign, link->call))
				{
					conn->rtcflags = p_linkwait;
					return 0;						// Wait for *RTL
				}
			}

			// See if from a previously known node

			node = knownnode_find(conn->Callsign);

			if (node)
			{
				// A node is trying to link, but we don't have it defined - close

				Logprintf(LOG_CHAT, conn, '!', "Node %s connected, but is not defined as a Node - closing",
					conn->Callsign);

				nodeprintf(conn, "Node %s does not have %s defined as a node to link to - closing.\r",
					OurNode, conn->Callsign);

				ChatFlush(conn);

				Sleep(500);

				Disconnect(conn->BPQStream);

				return 0;
			}

			if (user->Name[0] == 0)
			{
				char * Name = lookupuser(user->Call);

				if (Name)
				{
					if (strlen(Name) > 17)
						Name[17] = 0;

					strcpy(user->Name, Name);
					free(Name);
				}
				else
				{
					conn->Flags |= GETTINGUSER;
					nputs(conn, NewUserPrompt);
					return TRUE;
				}
			}

			SendWelcomeMsg(Stream, conn, user);
			RefreshMainWindow();
			ChatFlush(conn);
			
			return 0;
		}
	}

	return 0;
}
Example #9
0
//==============================================================================
// GetHostConnectionInfo()
//
// Returns DPN_CONNECTION_INFO for the host of the game.
//==============================================================================
HRESULT CDarkPeer::GetHostConnectionInfo(DPN_CONNECTION_INFO* pConnectInfo)
{
	return GetConnectionInfo(m_dpnidHost, pConnectInfo);
}
enum TVerdict TE_RConnectionTest501::doTestStepL(void)
{
    SetTestStepResult(EFail);
    TInt err;

    RSocketServ socketServer;
    RConnection startConn;
    RConnection monitorConn;

    err = OpenSocketServer(socketServer);
    TESTEL(KErrNone == err, err);
    CleanupClosePushL(socketServer);

    err = OpenConnection(startConn, socketServer);
    TESTEL(KErrNone == err, err);
    CleanupClosePushL(startConn);

    err = OpenConnection(monitorConn, socketServer);
    TESTEL(KErrNone == err, err);
    CleanupClosePushL(monitorConn);

    // start up connection (destined to fail startup)
    TRequestStatus startStatus;
    StartConnectionAsynchronous(startConn, startStatus);

    // wait for completion of selection, after which we can attach to the connection
    TNifProgressBuf progressBuf;
    TRequestStatus progressStatus;
    ProgressNotification(startConn, progressStatus, progressBuf, KFinishedSelection);
    User::WaitForRequest(progressStatus);

    // Attach to the connection from another RConnection
    //
    // It can take a finite time from KFinishedSelection progress to the point where the
    // connection actually appears in the enumeration list, so take this into account by looping
    // waiting for the connection to enumerate.  We are only interested in obtaining the connection
    // info so that we can attach to the starting connection - we are not testing connection
    // enumeration here.

    TInt i = 0;
    TUint count;
    do
    {
        err = EnumerateConnections(startConn, count);
        TESTEL(KErrNone == err, err);
        if (count == 0)
        {
            User::After(50000);
        }
    }
    while (count == 0 && ++i <= 5);
    TESTEL(1 == count, count);

    TPckgBuf<TConnectionInfo> info;
    err = GetConnectionInfo(startConn, 1, info);
    TESTEL(KErrNone == err, err);

    err = AttachMonitor(monitorConn, info);
    TESTEL(KErrNone == err, err);

    ProgressNotification(monitorConn, progressStatus, progressBuf, KLinkLayerClosed);

    // wait for the startup to fail
    User::WaitForRequest(startStatus);
    TESTEL(KErrIfAuthenticationFailure == startStatus.Int(), startStatus.Int());

    // Wait for KLinkLayerClosed or any progress which has an error associated.  Actually,
    // we are more interested in waiting for a progress with an error than KLinkLayerClosed.
    // Use a timer to prevent waiting forever and fail with an error if the progress never arrives.
    RTimer timer;
    err = timer.CreateLocal();
    TESTEL(KErrNone == err, err);
    CleanupClosePushL(timer);

    TRequestStatus timerStatus;
    const TUint KMaxProgressWait = 5;
    timer.After(timerStatus, KMaxProgressWait * 1000000);

    User::WaitForRequest(progressStatus, timerStatus);
    if (progressStatus.Int() == KRequestPending)
    {
        // failure - timer fired
        CancelProgressNotification(monitorConn);
        User::WaitForRequest(progressStatus);
    }

    if (timerStatus.Int() == KRequestPending)
    {
        // success - progress arrived
        timer.Cancel();
        User::WaitForRequest(timerStatus);
    }
    // check that we correctly received a progress with an associated error on the RConnection
    // that attached to the underlying connection.
    TESTEL(KErrNone == progressStatus.Int(), progressStatus.Int());
    TESTEL(KErrIfAuthenticationFailure == progressBuf().iError, progressBuf().iError);
    SetTestStepResult(EPass);

    // ************************************************************************************
    // NOTE:
    // The following pause is apparently necessary to prevent WinTunnel from intermittently
    // entering an endless cpu loop and hanging the emulator.  The cause needs to be
    // investigated and fixed and then this pause can be removed.
    // ************************************************************************************
    User::After(1000000);

    CleanupStack::PopAndDestroy(&timer);
    CloseConnection(monitorConn);
    CleanupStack::Pop(&monitorConn);
    CloseConnection(startConn);
    CleanupStack::Pop(&startConn);
    CloseSocketServer(socketServer);
    CleanupStack::Pop(&socketServer);	// just sanity check our pops

    return TestStepResult();
}