diff --git a/netwerk/base/src/nsSocketTransport.cpp b/netwerk/base/src/nsSocketTransport.cpp index fe3ce239b9d5..2fd125e5b87a 100644 --- a/netwerk/base/src/nsSocketTransport.cpp +++ b/netwerk/base/src/nsSocketTransport.cpp @@ -52,7 +52,7 @@ nsSocketState gStateTable[eSocketOperation_Max][eSocketState_Max] = { eSocketState_Error, // WaitWrite -> Error eSocketState_Connected, // Done -> Connected eSocketState_Error, // Timeout -> Error - eSocketState_Error // Error -> Error + eSocketState_Closed // Error -> Closed }, // eSocketOperation_Read: { @@ -65,7 +65,7 @@ nsSocketState gStateTable[eSocketOperation_Max][eSocketState_Max] = { eSocketState_Error, // WaitWrite -> Error eSocketState_Connected, // Done -> Connected eSocketState_Error, // Timeout -> Error - eSocketState_Error // Error -> Error + eSocketState_Connected // Error -> Connected }, // eSocketOperation_Write: { @@ -78,7 +78,7 @@ nsSocketState gStateTable[eSocketOperation_Max][eSocketState_Max] = { eSocketState_Done, // WaitWrite -> Done eSocketState_Connected, // Done -> Connected eSocketState_Error, // Timeout -> Error - eSocketState_Error // Error -> Error + eSocketState_Connected // Error -> Connected } }; @@ -194,8 +194,9 @@ nsresult nsSocketTransport::Init(nsSocketTransportService* aService, nsresult nsSocketTransport::Process(PRInt16 aSelectFlags) { nsresult rv = NS_OK; + PRBool done = PR_FALSE; - while ((eSocketOperation_None != mOperation) && (rv == NS_OK)) + while (!done) { switch (mCurrentState) { case eSocketState_Created: @@ -209,12 +210,17 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags) break; case eSocketState_Done: + case eSocketState_Error: if (mListener) { mListener->OnStopBinding(mContext, rv, nsnull); } NS_IF_RELEASE(mContext); + // + // Set up the connection for the next operation... + // mCurrentState = gStateTable[mOperation][mCurrentState]; - mOperation = eSocketOperation_None; + mOperation = eSocketOperation_None; + done = PR_TRUE; continue; case eSocketState_WaitDNS: @@ -238,8 +244,10 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags) rv = NS_ERROR_FAILURE; break; - case eSocketState_Error: - NS_ASSERTION(0, "Unexpected Error..."); + default: + NS_ASSERTION(0, "Unexpected state..."); + rv = NS_ERROR_FAILURE; + break; } // // If the current state has successfully completed, then move to the @@ -247,17 +255,33 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags) // if (NS_OK == rv) { mCurrentState = gStateTable[mOperation][mCurrentState]; - // - // Any select flags are *only* valid the first time through the loop... - // - aSelectFlags = 0; + } + else if (NS_FAILED(rv)) { + mCurrentState = eSocketState_Error; } + else if (NS_BASE_STREAM_WOULD_BLOCK == rv) { + done = PR_TRUE; + } + // + // Any select flags are *only* valid the first time through the loop... + // + aSelectFlags = 0; } return rv; } +//----- +// +// doResolveHost: +// +// Return Codes: +// NS_OK +// NS_ERROR_HOST_NOT_FOUND +// NS_ERROR_FAILURE +// +//----- nsresult nsSocketTransport::doResolveHost(void) { PRStatus status; @@ -296,7 +320,19 @@ nsresult nsSocketTransport::doResolveHost(void) return rv; } - +//----- +// +// doConnection: +// +// Return values: +// NS_OK +// NS_BASE_STREAM_WOULD_BLOCK +// +// NS_ERROR_CONNECTION_REFUSED (XXX: Not yet defined) +// NS_ERROR_FAILURE +// NS_ERROR_OUT_OF_MEMORY +// +//----- nsresult nsSocketTransport::doConnection(PRInt16 aSelectFlags) { PRStatus status; @@ -366,8 +402,7 @@ nsresult nsSocketTransport::doConnection(PRInt16 aSelectFlags) // else { // Connection refused... - // XXX: what should the next state be? - mCurrentState = eSocketState_Error; + // XXX: Should be NS_ERROR_CONNECTION_REFUSED rv = NS_ERROR_FAILURE; } } @@ -378,8 +413,7 @@ nsresult nsSocketTransport::doConnection(PRInt16 aSelectFlags) // else if (NS_SUCCEEDED(rv) && aSelectFlags) { if (PR_POLL_EXCEPT & aSelectFlags) { - // XXX: what should the next state be? - mCurrentState = eSocketState_Error; + // XXX: Should be NS_ERROR_CONNECTION_REFUSED rv = NS_ERROR_FAILURE; } // @@ -394,6 +428,17 @@ nsresult nsSocketTransport::doConnection(PRInt16 aSelectFlags) } +//----- +// +// doRead: +// +// Return values: +// NS_OK +// NS_BASE_STREAM_WOULD_BLOCK +// +// NS_ERROR_FAILURE +// +//----- nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) { PRUint32 size, bytesWritten, totalBytesWritten; @@ -403,8 +448,16 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) NS_ASSERTION(eSocketState_WaitRead == mCurrentState, "Wrong state."); + // + // Check for an error during PR_Poll(...) + // + if (PR_POLL_EXCEPT & aSelectFlags) { + // XXX: What should this error code be? + rv = NS_ERROR_FAILURE; + } + totalBytesWritten = 0; - do { + while (NS_OK == rv) { // // Determine how much space is available in the input stream... // @@ -429,10 +482,6 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) // The read operation has completed... // else if (len == 0) { - // - // Notify the listener that the read operation has completed... - // - //mListener->OnStopBinding(mContext, rv, nsnull); rv = NS_OK; break; } @@ -444,6 +493,7 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) rv = NS_BASE_STREAM_WOULD_BLOCK; } else { + // XXX: What should this error code be? rv = NS_ERROR_FAILURE; } } @@ -452,13 +502,21 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) // There is no room in the input stream for more data... Give the // consumer more time to empty the stream... // + // XXX: Until there is a mechanism to remove this entry from the + // select list until the consumer has read some data, this will + // cause the transport thread to spin !! + // else { rv = NS_BASE_STREAM_WOULD_BLOCK; } - } while (NS_OK == rv); + } - if (bytesWritten) { - mListener->OnDataAvailable(mContext, mReadStream, bytesWritten); + // + // Fire a single OnDataAvaliable(...) notification once as much data has + // been filled into the stream as possible... + // + if (totalBytesWritten) { + mListener->OnDataAvailable(mContext, mReadStream, totalBytesWritten); } // @@ -472,6 +530,17 @@ nsresult nsSocketTransport::doRead(PRInt16 aSelectFlags) } +//----- +// +// doWrite: +// +// Return values: +// NS_OK +// NS_BASE_STREAM_WOULD_BLOCK +// +// NS_ERROR_FAILURE +// +//----- nsresult nsSocketTransport::doWrite(PRInt16 aSelectFlags) { PRUint32 size, bytesRead; @@ -481,7 +550,15 @@ nsresult nsSocketTransport::doWrite(PRInt16 aSelectFlags) NS_ASSERTION(eSocketState_WaitWrite == mCurrentState, "Wrong state."); - do { + // + // Check for an error during PR_Poll(...) + // + if (PR_POLL_EXCEPT & aSelectFlags) { + // XXX: What should this error code be? + rv = NS_ERROR_FAILURE; + } + + while (NS_OK == rv) { rv = mWriteStream->Read(gIOBuffer, sizeof(gIOBuffer), &bytesRead); if (NS_SUCCEEDED(rv)) { if (bytesRead > 0) { @@ -501,15 +578,11 @@ nsresult nsSocketTransport::doWrite(PRInt16 aSelectFlags) // The write operation has completed... // else if (bytesRead == 0) { - // - // Notify the listener that the write operation has completed... - // - //mListener->OnStopBinding(mContext, rv, nsnull); rv = NS_OK; break; } } - } while(NS_OK == rv); + } // // Set up the select flags for connect... diff --git a/netwerk/test/TestSocketIO.cpp b/netwerk/test/TestSocketIO.cpp index d4f4d3b90198..ca0360187e34 100644 --- a/netwerk/test/TestSocketIO.cpp +++ b/netwerk/test/TestSocketIO.cpp @@ -15,7 +15,7 @@ * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ -#include "stdio.h" +#include #include #include "nspr.h" @@ -43,6 +43,7 @@ static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static PRTime gElapsedTime; static int gKeepRunning = 1; static PLEventQueue* gEventQ = nsnull; @@ -86,7 +87,7 @@ NS_IMPL_ISUPPORTS(InputTestConsumer,kIStreamListenerIID); NS_IMETHODIMP InputTestConsumer::OnStartBinding(nsISupports* context) { -/// printf("\n+++ InputTestConsumer::OnStartBinding +++\n"); + printf("\n+++ InputTestConsumer::OnStartBinding +++\n"); return NS_OK; } @@ -114,7 +115,7 @@ InputTestConsumer::OnStopBinding(nsISupports* context, nsIString* aMsg) { gKeepRunning = 0; -/// printf("\n+++ InputTestConsumer::OnStopBinding +++\n"); + printf("\n+++ InputTestConsumer::OnStopBinding (status = %x) +++\n", aStatus); return NS_OK; } @@ -160,7 +161,7 @@ NS_IMPL_ISUPPORTS(TestWriteObserver,nsIStreamObserver::GetIID()); NS_IMETHODIMP TestWriteObserver::OnStartBinding(nsISupports* context) { -/// printf("\n+++ TestWriteObserver::OnStartBinding +++\n"); + printf("\n+++ TestWriteObserver::OnStartBinding +++\n"); return NS_OK; } @@ -170,9 +171,14 @@ TestWriteObserver::OnStopBinding(nsISupports* context, nsresult aStatus, nsIString* aMsg) { -/// printf("\n+++ TestWriteObserver::OnStopBinding +++\n"); + printf("\n+++ TestWriteObserver::OnStopBinding (status = %x) +++\n", aStatus); + + if (NS_SUCCEEDED(aStatus)) { + mTransport->AsyncRead(nsnull, gEventQ, new InputTestConsumer); + } else { + gKeepRunning = 0; + } - mTransport->AsyncRead(nsnull, gEventQ, new InputTestConsumer); return NS_OK; } @@ -193,7 +199,7 @@ main(int argc, char* argv[]) char* hostName = argv[1]; char* fileName = argv[2]; int port = 80; - + // XXX why do I have to do this?! nsComponentManager::RegisterComponent(kEventQueueServiceCID, NULL, NULL, XPCOM_DLL, PR_FALSE, PR_FALSE); rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, @@ -222,7 +228,7 @@ main(int argc, char* argv[]) char *buffer = PR_smprintf("GET %s HTML/1.0\r\n\r\n", fileName); stream->Fill(buffer, strlen(buffer), &bytesWritten); -/// printf("Request is: %s\n", buffer); + printf("\n+++ Request is: %s\n", buffer); // Create the socket transport... nsITransport* transport; @@ -230,6 +236,7 @@ main(int argc, char* argv[]) if (NS_SUCCEEDED(rv)) { TestWriteObserver* observer = new TestWriteObserver(transport); + gElapsedTime = PR_Now(); transport->AsyncWrite(stream, nsnull, gEventQ, observer); NS_RELEASE(transport); @@ -240,13 +247,19 @@ main(int argc, char* argv[]) #ifdef XP_PC MSG msg; - if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); + } else { + gKeepRunning = FALSE; } #endif } + PRTime endTime; + endTime = PR_Now(); + printf("Elapsed time: %ld\n", (PRInt32)(endTime/1000UL-gElapsedTime/1000UL)); + sts->Shutdown(); NS_RELEASE(sts); NS_RELEASE(eventQService);