netwerk/protocol/ftp/nsFtpControlConnection.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsIOService.h"
     7 #include "nsFtpControlConnection.h"
     8 #include "nsFtpProtocolHandler.h"
     9 #include "prlog.h"
    10 #include "nsIInputStream.h"
    11 #include "nsISocketTransportService.h"
    12 #include "nsISocketTransport.h"
    13 #include "nsThreadUtils.h"
    14 #include "nsIOutputStream.h"
    15 #include "nsNetCID.h"
    16 #include <algorithm>
    18 #if defined(PR_LOGGING)
    19 extern PRLogModuleInfo* gFTPLog;
    20 #endif
    21 #define LOG(args)         PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
    22 #define LOG_ALWAYS(args)  PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
    24 //
    25 // nsFtpControlConnection implementation ...
    26 //
    28 NS_IMPL_ISUPPORTS(nsFtpControlConnection, nsIInputStreamCallback)
    30 NS_IMETHODIMP
    31 nsFtpControlConnection::OnInputStreamReady(nsIAsyncInputStream *stream)
    32 {
    33     char data[4096];
    35     // Consume data whether we have a listener or not.
    36     uint64_t avail64;
    37     uint32_t avail = 0;
    38     nsresult rv = stream->Available(&avail64);
    39     if (NS_SUCCEEDED(rv)) {
    40         avail = (uint32_t)std::min(avail64, (uint64_t)sizeof(data));
    42         uint32_t n;
    43         rv = stream->Read(data, avail, &n);
    44         if (NS_SUCCEEDED(rv))
    45             avail = n;
    46     }
    48     // It's important that we null out mListener before calling one of its
    49     // methods as it may call WaitData, which would queue up another read.
    51     nsRefPtr<nsFtpControlConnectionListener> listener;
    52     listener.swap(mListener);
    54     if (!listener)
    55         return NS_OK;
    57     if (NS_FAILED(rv)) {
    58         listener->OnControlError(rv);
    59     } else {
    60         listener->OnControlDataAvailable(data, avail);
    61     }
    63     return NS_OK;
    64 }
    66 nsFtpControlConnection::nsFtpControlConnection(const nsCSubstring& host,
    67                                                uint32_t port)
    68     : mServerType(0), mSessionId(gFtpHandler->GetSessionId())
    69     , mUseUTF8(false), mHost(host), mPort(port)
    70 {
    71     LOG_ALWAYS(("FTP:CC created @%p", this));
    72 }
    74 nsFtpControlConnection::~nsFtpControlConnection() 
    75 {
    76     LOG_ALWAYS(("FTP:CC destroyed @%p", this));
    77 }
    79 bool
    80 nsFtpControlConnection::IsAlive()
    81 {
    82     if (!mSocket) 
    83         return false;
    85     bool isAlive = false;
    86     mSocket->IsAlive(&isAlive);
    87     return isAlive;
    88 }
    89 nsresult 
    90 nsFtpControlConnection::Connect(nsIProxyInfo* proxyInfo,
    91                                 nsITransportEventSink* eventSink)
    92 {
    93     if (mSocket)
    94         return NS_OK;
    96     // build our own
    97     nsresult rv;
    98     nsCOMPtr<nsISocketTransportService> sts =
    99             do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
   100     if (NS_FAILED(rv))
   101         return rv;
   103     rv = sts->CreateTransport(nullptr, 0, mHost, mPort, proxyInfo,
   104                               getter_AddRefs(mSocket)); // the command transport
   105     if (NS_FAILED(rv))
   106         return rv;
   108     mSocket->SetQoSBits(gFtpHandler->GetControlQoSBits());
   110     // proxy transport events back to current thread
   111     if (eventSink)
   112         mSocket->SetEventSink(eventSink, NS_GetCurrentThread());
   114     // open buffered, blocking output stream to socket.  so long as commands
   115     // do not exceed 1024 bytes in length, the writing thread (the main thread)
   116     // will not block.  this should be OK.
   117     rv = mSocket->OpenOutputStream(nsITransport::OPEN_BLOCKING, 1024, 1,
   118                                    getter_AddRefs(mSocketOutput));
   119     if (NS_FAILED(rv))
   120         return rv;
   122     // open buffered, non-blocking/asynchronous input stream to socket.
   123     nsCOMPtr<nsIInputStream> inStream;
   124     rv = mSocket->OpenInputStream(0,
   125                                   nsIOService::gDefaultSegmentSize,
   126                                   nsIOService::gDefaultSegmentCount,
   127                                   getter_AddRefs(inStream));
   128     if (NS_SUCCEEDED(rv))
   129         mSocketInput = do_QueryInterface(inStream);
   131     return rv;
   132 }
   134 nsresult
   135 nsFtpControlConnection::WaitData(nsFtpControlConnectionListener *listener)
   136 {
   137     LOG(("FTP:(%p) wait data [listener=%p]\n", this, listener));
   139     // If listener is null, then simply disconnect the listener.  Otherwise,
   140     // ensure that we are listening.
   141     if (!listener) {
   142         mListener = nullptr;
   143         return NS_OK;
   144     }
   146     NS_ENSURE_STATE(mSocketInput);
   148     mListener = listener;
   149     return mSocketInput->AsyncWait(this, 0, 0, NS_GetCurrentThread());
   150 }
   152 nsresult 
   153 nsFtpControlConnection::Disconnect(nsresult status)
   154 {
   155     if (!mSocket)
   156         return NS_OK;  // already disconnected
   158     LOG_ALWAYS(("FTP:(%p) CC disconnecting (%x)", this, status));
   160     if (NS_FAILED(status)) {
   161         // break cyclic reference!
   162         mSocket->Close(status);
   163         mSocket = 0;
   164         mSocketInput->AsyncWait(nullptr, 0, 0, nullptr);  // clear any observer
   165         mSocketInput = nullptr;
   166         mSocketOutput = nullptr;
   167     }
   169     return NS_OK;
   170 }
   172 nsresult 
   173 nsFtpControlConnection::Write(const nsCSubstring& command)
   174 {
   175     NS_ENSURE_STATE(mSocketOutput);
   177     uint32_t len = command.Length();
   178     uint32_t cnt;
   179     nsresult rv = mSocketOutput->Write(command.Data(), len, &cnt);
   181     if (NS_FAILED(rv))
   182         return rv;
   184     if (len != cnt)
   185         return NS_ERROR_FAILURE;
   187     return NS_OK;
   188 }

mercurial