From 73cbb5ae24cea27bd1fb0c670ecc8bbe97f5df69 Mon Sep 17 00:00:00 2001 From: "mscott%netscape.com" Date: Mon, 25 Jan 1999 19:10:04 +0000 Subject: [PATCH] socket implementation of the transport interface. (not currently being built by checked in makefiles) git-svn-id: svn://10.0.0.236/trunk@18503 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/network/module/nsSocketTransport.cpp | 288 +++++++++++++++++++ mozilla/network/module/nsSocketTransport.h | 110 +++++++ 2 files changed, 398 insertions(+) create mode 100644 mozilla/network/module/nsSocketTransport.cpp create mode 100644 mozilla/network/module/nsSocketTransport.h diff --git a/mozilla/network/module/nsSocketTransport.cpp b/mozilla/network/module/nsSocketTransport.cpp new file mode 100644 index 00000000000..d2c1b35dbc7 --- /dev/null +++ b/mozilla/network/module/nsSocketTransport.cpp @@ -0,0 +1,288 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#include "nsRepository.h" +#include "nsNetStream.h" +#include "nsSocketTransport.h" +#include "nsINetService.h" +#include "nsINetlibURL.h" + +#include "nsIServiceManager.h" +#include "nsXPComCIID.h" + +#include "mktcp.h" +#include "sockstub.h" + +#include "plstr.h" + +extern nsIStreamListener* ns_NewStreamListenerProxy(nsIStreamListener* aListener, PLEventQueue* aEventQ); +static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); +static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID); + +//////////////////////////////////////////////////////////////////////////// +// from nsISupports + +static NS_DEFINE_IID(kITransportIID, NS_ITRANSPORT_IID); +NS_IMPL_ADDREF(nsSocketTransport) +NS_IMPL_RELEASE(nsSocketTransport) +NS_IMPL_QUERY_INTERFACE(nsSocketTransport, kITransportIID); + +//////////////////////////////////////////////////////////////////////////// +// from nsITransport: + +NS_METHOD +nsSocketTransport::GetURL(nsIURL* *result) +{ + *result = m_url; + return NS_OK; +} + + +static NS_DEFINE_IID(kINetlibURLIID, NS_INETLIBURL_IID); + + +NS_METHOD +nsSocketTransport::LoadURL(nsIURL *pURL) +{ + nsresult rv = NS_OK; + if (nsnull == pURL) { + return NS_ERROR_NULL_POINTER; + } + + if (nsnull == m_inputStreamConsumer) { + return NS_ERROR_NULL_POINTER; + } + + m_url = pURL; + NS_IF_ADDREF(m_url); + pURL->SetHostPort(m_port); + + nsresult ns_result = NS_OpenURL(pURL, m_inputStreamConsumer); + if (NS_OK != ns_result) { + return ns_result; + } + + return NS_OK; +} + +NS_METHOD +nsSocketTransport::SetInputStreamConsumer(nsIStreamListener* aListener) +{ + // generates the thread safe proxy + m_inputStreamConsumer = ns_NewStreamListenerProxy(aListener, m_evQueue); + return NS_OK; +} + + +NS_METHOD +nsSocketTransport::GetOutputStreamConsumer(nsIStreamListener ** aConsumer) +{ + // assuming the transport layer is a nsIStreamListener + *aConsumer = ns_NewStreamListenerProxy(this, m_evQueue); + return NS_OK; +} + + +NS_METHOD +nsSocketTransport::GetOutputStream(nsIOutputStream ** aOutputStream) +{ + if (aOutputStream) { + // a buffered stream supports the nsIOutputStream interface + nsBufferedStream * stream = new nsBufferedStream(); + if (stream) // return the buffer in the format they want + stream->QueryInterface(kIOutputStreamIID, (void **) aOutputStream); + else + *aOutputStream = NULL; + } + return NS_OK; +} + + +NS_IMETHODIMP +nsSocketTransport::OnStartBinding(nsIURL* pURL, const char *aContentType) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::OnProgress(nsIURL* pURL, + PRUint32 aProgress, + PRUint32 aProgressMax) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::OnStatus(nsIURL* pURL, const PRUnichar* aMsg) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::OnStopBinding(nsIURL* pURL, + nsresult aStatus, + const PRUnichar* aMsg) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::GetBindInfo(nsIURL* pURL, + nsStreamBindingInfo* aInfo) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::OnDataAvailable(nsIURL* pURL, + nsIInputStream *aIStream, + PRUint32 aLength) +{ + nsresult rv = NS_OK; + PRUint32 len, lenRead; + URL_Struct* URL_s; + m_ready_fd = NULL; + + /* XXX: HACK The following is a hack. + * Get the URL_s structure and pass it to sockstub protocol code to get the + * socket FD so that we could write the data back. + */ + rv = GetURLInfo(pURL, &URL_s); + + if (NS_SUCCEEDED(rv)) { + if (nsnull != URL_s) { + /* Find the socket given URL_s pointer */ + m_ready_fd = NET_GetSocketToHashTable(URL_s); + } + } else { + return rv; + } + + if (m_ready_fd == NULL) { + return NS_ERROR_NULL_POINTER; + } + + aIStream->GetLength(&len); + + memset(m_buffer, '\0', NET_SOCKSTUB_BUF_SIZE); + while (len > 0) { + if (len < NET_SOCKSTUB_BUF_SIZE) { + lenRead = len; + } + else { + lenRead = NET_SOCKSTUB_BUF_SIZE; + } + + rv = aIStream->Read(m_buffer, 0, lenRead, &lenRead); + if (NS_OK != rv) { + return rv; + } + + /* XXX: We should check if the write has succeeded or not */ + (int) NET_BlockingWrite(m_ready_fd, m_buffer, lenRead); + len -= lenRead; + } + + return rv; +} + + + +//////////////////////////////////////////////////////////////////////////// +// from nsSocketTransport: + +nsSocketTransport::nsSocketTransport(PRUint32 aPortToUse, const char * aHostName) +{ + NS_INIT_REFCNT(); + + // remember the port and host name + NS_PRECONDITION(aPortToUse > 0 && aHostName, "Creating a socket transport with an invalid port or host name."); + m_port = aPortToUse; + if (aHostName) + m_hostName = PL_strdup(aHostName); + else + m_hostName = PL_strdup(""); + + m_inputStream = NULL; + m_inputStreamConsumer = NULL; + m_url = NULL; + + m_outStream = NULL; + m_outStreamSize = 0; + + /* + * Cache the EventQueueService... + */ + // XXX: What if this fails? + mEventQService = nsnull; + m_evQueue = nsnull; + nsresult rv = nsServiceManager::GetService(kEventQueueServiceCID, + kIEventQueueServiceIID, + (nsISupports **)&mEventQService); + + if (nsnull != mEventQService) { + mEventQService->GetThreadEventQueue(PR_GetCurrentThread(), &m_evQueue); + } +} + +nsSocketTransport::~nsSocketTransport() +{ + nsresult rv = NS_OK; + URL_Struct* URL_s; + + /* XXX: HACK The following is a hack. + * Get the URL_s structure and pass it to sockstub protocol code to delete it + */ + rv = GetURLInfo(m_url, &URL_s); + + if (NS_SUCCEEDED(rv)) { + if (nsnull != URL_s) { + /* Release the socket given URL_s pointer */ + int32 res = NET_FreeSocket(URL_s); + } + } + + if (m_hostName) + PR_Free(m_hostName); + + NS_IF_RELEASE(m_outStream); + NS_IF_RELEASE(m_url); +} + +NS_IMETHODIMP +nsSocketTransport::GetURLInfo(nsIURL* pURL, URL_Struct_ **aResult) +{ + nsresult rv = NS_OK; + nsINetlibURL *pNetlibURL = NULL; + + NS_PRECONDITION(aResult != nsnull, "invalid input argument"); + if (aResult) + { + *aResult = nsnull; + + rv = pURL->QueryInterface(kINetlibURLIID, (void**)&pNetlibURL); + if (NS_SUCCEEDED(rv) && pNetlibURL) { + + pNetlibURL->GetURLInfo(aResult); + NS_RELEASE(pNetlibURL); + } + } + + return rv; +} diff --git a/mozilla/network/module/nsSocketTransport.h b/mozilla/network/module/nsSocketTransport.h new file mode 100644 index 00000000000..8397c0239ac --- /dev/null +++ b/mozilla/network/module/nsSocketTransport.h @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#ifndef nsSocketTransport_h__ +#define nsSocketTransport_h__ + +#include "nsRepository.h" +#include "nsITransport.h" +#include "nsIStreamListener.h" +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "nsIEventQueueService.h" +#include "nsAgg.h" +#include "nsString.h" + +#define NET_SOCKSTUB_BUF_SIZE 1024 + +/* forward declaration */ +struct URL_Struct_; + +class nsSocketTransport : public nsITransport +{ +public: + //////////////////////////////////////////////////////////////////////////// + // from nsISupports: + + NS_DECL_ISUPPORTS + + + //////////////////////////////////////////////////////////////////////////// + // from nsITransport: + + NS_IMETHOD GetURL(nsIURL* *result); + + NS_IMETHOD LoadURL(nsIURL *url); + + NS_IMETHOD SetInputStreamConsumer(nsIStreamListener* aListener); + + NS_IMETHOD GetOutputStreamConsumer(nsIStreamListener ** aConsumer); + + NS_IMETHOD GetOutputStream(nsIOutputStream ** aOutputStream); + + + //////////////////////////////////////////////////////////////////////////// + // from nsIStreamListener: + + NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType); + NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax); + NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg); + NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult aStatus, const PRUnichar* aMsg); + NS_IMETHOD GetBindInfo(nsIURL* aURL, nsStreamBindingInfo* aInfo); + NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream *aIStream, + PRUint32 aLength); + + + //////////////////////////////////////////////////////////////////////////// + // nsSocketTransport: + + nsSocketTransport(PRUint32 aPortToUse, const char * aHostName); + virtual ~nsSocketTransport(void); + NS_IMETHOD GetURLInfo(nsIURL* pURL, URL_Struct_ **aResult); + + // the following routines are called by the sock stub protocol hack.... + // we should be able to remove this dependency once we move things to the new + // net lib world... + PRUint32 GetPort() {return m_port;} + const char * GetHostName() { return m_hostName;} + +protected: + + // socket specific information... + PRUint32 m_port; + char *m_hostName; + + // the stream we write data from the socket into + nsIInputStream * m_inputStream; + + // XXX sock stub hack..need to remember stream with data to be written to the socket + nsIInputStream * m_outStream; + PRUint32 m_outStreamSize; + + // the proxied stream listener. Whenever the transport layer + // writes socket date to input stream, it calls OnDataAvailable + // through the inputStreamConsumer any socket specific data + nsIStreamListener *m_inputStreamConsumer; + + nsIURL *m_url; + nsString* mData; + PRFileDesc *m_ready_fd; + nsIEventQueueService* mEventQService; + PLEventQueue* m_evQueue; + char m_buffer[NET_SOCKSTUB_BUF_SIZE]; +}; + +#endif // nsSocketTransport_h__