123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* vim:set ts=4 sts=4 sw=4 et cin: */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsFTPChannel.h"
- #include "nsFtpConnectionThread.h" // defines nsFtpState
- #include "nsThreadUtils.h"
- #include "mozilla/Attributes.h"
- using namespace mozilla;
- using namespace mozilla::net;
- extern LazyLogModule gFTPLog;
- #undef LOG
- #define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
- // There are two transport connections established for an
- // ftp connection. One is used for the command channel , and
- // the other for the data channel. The command channel is the first
- // connection made and is used to negotiate the second, data, channel.
- // The data channel is driven by the command channel and is either
- // initiated by the server (PORT command) or by the client (PASV command).
- // Client initiation is the most common case and is attempted first.
- //-----------------------------------------------------------------------------
- NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel,
- nsBaseChannel,
- nsIUploadChannel,
- nsIResumableChannel,
- nsIFTPChannel,
- nsIProxiedChannel,
- nsIForcePendingChannel,
- nsIChannelWithDivertableParentListener)
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- nsFtpChannel::SetUploadStream(nsIInputStream *stream,
- const nsACString &contentType,
- int64_t contentLength)
- {
- NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
- mUploadStream = stream;
- // NOTE: contentLength is intentionally ignored here.
-
- return NS_OK;
- }
- NS_IMETHODIMP
- nsFtpChannel::GetUploadStream(nsIInputStream **stream)
- {
- NS_ENSURE_ARG_POINTER(stream);
- *stream = mUploadStream;
- NS_IF_ADDREF(*stream);
- return NS_OK;
- }
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
- {
- NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
- mEntityID = aEntityID;
- mStartPos = aStartPos;
- mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsFtpChannel::GetEntityID(nsACString& entityID)
- {
- if (mEntityID.IsEmpty())
- return NS_ERROR_NOT_RESUMABLE;
- entityID = mEntityID;
- return NS_OK;
- }
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
- {
- *aProxyInfo = ProxyInfo();
- NS_IF_ADDREF(*aProxyInfo);
- return NS_OK;
- }
- //-----------------------------------------------------------------------------
- nsresult
- nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
- nsIChannel** channel)
- {
- if (!async)
- return NS_ERROR_NOT_IMPLEMENTED;
- nsFtpState *state = new nsFtpState();
- if (!state)
- return NS_ERROR_OUT_OF_MEMORY;
- NS_ADDREF(state);
- nsresult rv = state->Init(this);
- if (NS_FAILED(rv)) {
- NS_RELEASE(state);
- return rv;
- }
- *result = state;
- return NS_OK;
- }
- bool
- nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
- {
- nsAutoCString host;
- URI()->GetHost(host);
- CopyUTF8toUTF16(host, statusArg);
- return true;
- }
- void
- nsFtpChannel::OnCallbacksChanged()
- {
- mFTPEventSink = nullptr;
- }
- //-----------------------------------------------------------------------------
- namespace {
- class FTPEventSinkProxy final : public nsIFTPEventSink
- {
- ~FTPEventSinkProxy() {}
- public:
- explicit FTPEventSinkProxy(nsIFTPEventSink* aTarget)
- : mTarget(aTarget)
- , mTargetThread(do_GetCurrentThread())
- { }
-
- NS_DECL_THREADSAFE_ISUPPORTS
- NS_DECL_NSIFTPEVENTSINK
- class OnFTPControlLogRunnable : public Runnable
- {
- public:
- OnFTPControlLogRunnable(nsIFTPEventSink* aTarget,
- bool aServer,
- const char* aMessage)
- : mTarget(aTarget)
- , mServer(aServer)
- , mMessage(aMessage)
- { }
- NS_DECL_NSIRUNNABLE
- private:
- nsCOMPtr<nsIFTPEventSink> mTarget;
- bool mServer;
- nsCString mMessage;
- };
- private:
- nsCOMPtr<nsIFTPEventSink> mTarget;
- nsCOMPtr<nsIThread> mTargetThread;
- };
- NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
- NS_IMETHODIMP
- FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg)
- {
- RefPtr<OnFTPControlLogRunnable> r =
- new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
- return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
- }
- NS_IMETHODIMP
- FTPEventSinkProxy::OnFTPControlLogRunnable::Run()
- {
- mTarget->OnFTPControlLog(mServer, mMessage.get());
- return NS_OK;
- }
- } // namespace
- void
- nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
- {
- if (!mFTPEventSink) {
- nsCOMPtr<nsIFTPEventSink> ftpSink;
- GetCallback(ftpSink);
- if (ftpSink) {
- mFTPEventSink = new FTPEventSinkProxy(ftpSink);
- }
- }
- aResult = mFTPEventSink;
- }
- NS_IMETHODIMP
- nsFtpChannel::ForcePending(bool aForcePending)
- {
- // Set true here so IsPending will return true.
- // Required for callback diversion from child back to parent. In such cases
- // OnStopRequest can be called in the parent before callbacks are diverted
- // back from the child to the listener in the parent.
- mForcePending = aForcePending;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsFtpChannel::IsPending(bool *result)
- {
- *result = Pending();
- return NS_OK;
- }
- bool
- nsFtpChannel::Pending() const
- {
- return nsBaseChannel::Pending() || mForcePending;
- }
- NS_IMETHODIMP
- nsFtpChannel::Suspend()
- {
- LOG(("nsFtpChannel::Suspend [this=%p]\n", this));
- nsresult rv = nsBaseChannel::Suspend();
- nsresult rvParentChannel = NS_OK;
- if (mParentChannel) {
- rvParentChannel = mParentChannel->SuspendMessageDiversion();
- }
- return NS_FAILED(rv) ? rv : rvParentChannel;
- }
- NS_IMETHODIMP
- nsFtpChannel::Resume()
- {
- LOG(("nsFtpChannel::Resume [this=%p]\n", this));
- nsresult rv = nsBaseChannel::Resume();
- nsresult rvParentChannel = NS_OK;
- if (mParentChannel) {
- rvParentChannel = mParentChannel->ResumeMessageDiversion();
- }
- return NS_FAILED(rv) ? rv : rvParentChannel;
- }
- //-----------------------------------------------------------------------------
- // AChannelHasDivertableParentChannelAsListener internal functions
- //-----------------------------------------------------------------------------
- NS_IMETHODIMP
- nsFtpChannel::MessageDiversionStarted(ADivertableParentChannel *aParentChannel)
- {
- MOZ_ASSERT(!mParentChannel);
- mParentChannel = aParentChannel;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsFtpChannel::MessageDiversionStop()
- {
- LOG(("nsFtpChannel::MessageDiversionStop [this=%p]", this));
- MOZ_ASSERT(mParentChannel);
- mParentChannel = nullptr;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsFtpChannel::SuspendInternal()
- {
- LOG(("nsFtpChannel::SuspendInternal [this=%p]\n", this));
- return nsBaseChannel::Suspend();
- }
- NS_IMETHODIMP
- nsFtpChannel::ResumeInternal()
- {
- LOG(("nsFtpChannel::ResumeInternal [this=%p]\n", this));
- return nsBaseChannel::Resume();
- }
|