gecko-dev/network/module/nsSocketTransport.cpp
alecf%netscape.com bc55677bba make this thread safer by addreffing it before storing the variable
Also check pURL before dereferencing
1999-02-02 07:57:56 +00:00

290 lines
6.8 KiB
C++

/* -*- 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 "netutils.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;
}
NS_IF_ADDREF(pURL);
m_url = pURL;
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;
if (pURL)
rv = pURL->QueryInterface(kINetlibURLIID, (void**)&pNetlibURL);
if (NS_SUCCEEDED(rv) && pNetlibURL) {
pNetlibURL->GetURLInfo(aResult);
NS_RELEASE(pNetlibURL);
}
}
return rv;
}