nsFTPChannel.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /* vim:set ts=4 sts=4 sw=4 et cin: */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #include "nsFTPChannel.h"
  7. #include "nsFtpConnectionThread.h" // defines nsFtpState
  8. #include "nsThreadUtils.h"
  9. #include "mozilla/Attributes.h"
  10. using namespace mozilla;
  11. using namespace mozilla::net;
  12. extern LazyLogModule gFTPLog;
  13. #undef LOG
  14. #define LOG(args) MOZ_LOG(gFTPLog, mozilla::LogLevel::Debug, args)
  15. // There are two transport connections established for an
  16. // ftp connection. One is used for the command channel , and
  17. // the other for the data channel. The command channel is the first
  18. // connection made and is used to negotiate the second, data, channel.
  19. // The data channel is driven by the command channel and is either
  20. // initiated by the server (PORT command) or by the client (PASV command).
  21. // Client initiation is the most common case and is attempted first.
  22. //-----------------------------------------------------------------------------
  23. NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel,
  24. nsBaseChannel,
  25. nsIUploadChannel,
  26. nsIResumableChannel,
  27. nsIFTPChannel,
  28. nsIProxiedChannel,
  29. nsIForcePendingChannel,
  30. nsIChannelWithDivertableParentListener)
  31. //-----------------------------------------------------------------------------
  32. NS_IMETHODIMP
  33. nsFtpChannel::SetUploadStream(nsIInputStream *stream,
  34. const nsACString &contentType,
  35. int64_t contentLength)
  36. {
  37. NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
  38. mUploadStream = stream;
  39. // NOTE: contentLength is intentionally ignored here.
  40. return NS_OK;
  41. }
  42. NS_IMETHODIMP
  43. nsFtpChannel::GetUploadStream(nsIInputStream **stream)
  44. {
  45. NS_ENSURE_ARG_POINTER(stream);
  46. *stream = mUploadStream;
  47. NS_IF_ADDREF(*stream);
  48. return NS_OK;
  49. }
  50. //-----------------------------------------------------------------------------
  51. NS_IMETHODIMP
  52. nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
  53. {
  54. NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
  55. mEntityID = aEntityID;
  56. mStartPos = aStartPos;
  57. mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
  58. return NS_OK;
  59. }
  60. NS_IMETHODIMP
  61. nsFtpChannel::GetEntityID(nsACString& entityID)
  62. {
  63. if (mEntityID.IsEmpty())
  64. return NS_ERROR_NOT_RESUMABLE;
  65. entityID = mEntityID;
  66. return NS_OK;
  67. }
  68. //-----------------------------------------------------------------------------
  69. NS_IMETHODIMP
  70. nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
  71. {
  72. *aProxyInfo = ProxyInfo();
  73. NS_IF_ADDREF(*aProxyInfo);
  74. return NS_OK;
  75. }
  76. //-----------------------------------------------------------------------------
  77. nsresult
  78. nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
  79. nsIChannel** channel)
  80. {
  81. if (!async)
  82. return NS_ERROR_NOT_IMPLEMENTED;
  83. nsFtpState *state = new nsFtpState();
  84. if (!state)
  85. return NS_ERROR_OUT_OF_MEMORY;
  86. NS_ADDREF(state);
  87. nsresult rv = state->Init(this);
  88. if (NS_FAILED(rv)) {
  89. NS_RELEASE(state);
  90. return rv;
  91. }
  92. *result = state;
  93. return NS_OK;
  94. }
  95. bool
  96. nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
  97. {
  98. nsAutoCString host;
  99. URI()->GetHost(host);
  100. CopyUTF8toUTF16(host, statusArg);
  101. return true;
  102. }
  103. void
  104. nsFtpChannel::OnCallbacksChanged()
  105. {
  106. mFTPEventSink = nullptr;
  107. }
  108. //-----------------------------------------------------------------------------
  109. namespace {
  110. class FTPEventSinkProxy final : public nsIFTPEventSink
  111. {
  112. ~FTPEventSinkProxy() {}
  113. public:
  114. explicit FTPEventSinkProxy(nsIFTPEventSink* aTarget)
  115. : mTarget(aTarget)
  116. , mTargetThread(do_GetCurrentThread())
  117. { }
  118. NS_DECL_THREADSAFE_ISUPPORTS
  119. NS_DECL_NSIFTPEVENTSINK
  120. class OnFTPControlLogRunnable : public Runnable
  121. {
  122. public:
  123. OnFTPControlLogRunnable(nsIFTPEventSink* aTarget,
  124. bool aServer,
  125. const char* aMessage)
  126. : mTarget(aTarget)
  127. , mServer(aServer)
  128. , mMessage(aMessage)
  129. { }
  130. NS_DECL_NSIRUNNABLE
  131. private:
  132. nsCOMPtr<nsIFTPEventSink> mTarget;
  133. bool mServer;
  134. nsCString mMessage;
  135. };
  136. private:
  137. nsCOMPtr<nsIFTPEventSink> mTarget;
  138. nsCOMPtr<nsIThread> mTargetThread;
  139. };
  140. NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
  141. NS_IMETHODIMP
  142. FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg)
  143. {
  144. RefPtr<OnFTPControlLogRunnable> r =
  145. new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
  146. return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
  147. }
  148. NS_IMETHODIMP
  149. FTPEventSinkProxy::OnFTPControlLogRunnable::Run()
  150. {
  151. mTarget->OnFTPControlLog(mServer, mMessage.get());
  152. return NS_OK;
  153. }
  154. } // namespace
  155. void
  156. nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
  157. {
  158. if (!mFTPEventSink) {
  159. nsCOMPtr<nsIFTPEventSink> ftpSink;
  160. GetCallback(ftpSink);
  161. if (ftpSink) {
  162. mFTPEventSink = new FTPEventSinkProxy(ftpSink);
  163. }
  164. }
  165. aResult = mFTPEventSink;
  166. }
  167. NS_IMETHODIMP
  168. nsFtpChannel::ForcePending(bool aForcePending)
  169. {
  170. // Set true here so IsPending will return true.
  171. // Required for callback diversion from child back to parent. In such cases
  172. // OnStopRequest can be called in the parent before callbacks are diverted
  173. // back from the child to the listener in the parent.
  174. mForcePending = aForcePending;
  175. return NS_OK;
  176. }
  177. NS_IMETHODIMP
  178. nsFtpChannel::IsPending(bool *result)
  179. {
  180. *result = Pending();
  181. return NS_OK;
  182. }
  183. bool
  184. nsFtpChannel::Pending() const
  185. {
  186. return nsBaseChannel::Pending() || mForcePending;
  187. }
  188. NS_IMETHODIMP
  189. nsFtpChannel::Suspend()
  190. {
  191. LOG(("nsFtpChannel::Suspend [this=%p]\n", this));
  192. nsresult rv = nsBaseChannel::Suspend();
  193. nsresult rvParentChannel = NS_OK;
  194. if (mParentChannel) {
  195. rvParentChannel = mParentChannel->SuspendMessageDiversion();
  196. }
  197. return NS_FAILED(rv) ? rv : rvParentChannel;
  198. }
  199. NS_IMETHODIMP
  200. nsFtpChannel::Resume()
  201. {
  202. LOG(("nsFtpChannel::Resume [this=%p]\n", this));
  203. nsresult rv = nsBaseChannel::Resume();
  204. nsresult rvParentChannel = NS_OK;
  205. if (mParentChannel) {
  206. rvParentChannel = mParentChannel->ResumeMessageDiversion();
  207. }
  208. return NS_FAILED(rv) ? rv : rvParentChannel;
  209. }
  210. //-----------------------------------------------------------------------------
  211. // AChannelHasDivertableParentChannelAsListener internal functions
  212. //-----------------------------------------------------------------------------
  213. NS_IMETHODIMP
  214. nsFtpChannel::MessageDiversionStarted(ADivertableParentChannel *aParentChannel)
  215. {
  216. MOZ_ASSERT(!mParentChannel);
  217. mParentChannel = aParentChannel;
  218. return NS_OK;
  219. }
  220. NS_IMETHODIMP
  221. nsFtpChannel::MessageDiversionStop()
  222. {
  223. LOG(("nsFtpChannel::MessageDiversionStop [this=%p]", this));
  224. MOZ_ASSERT(mParentChannel);
  225. mParentChannel = nullptr;
  226. return NS_OK;
  227. }
  228. NS_IMETHODIMP
  229. nsFtpChannel::SuspendInternal()
  230. {
  231. LOG(("nsFtpChannel::SuspendInternal [this=%p]\n", this));
  232. return nsBaseChannel::Suspend();
  233. }
  234. NS_IMETHODIMP
  235. nsFtpChannel::ResumeInternal()
  236. {
  237. LOG(("nsFtpChannel::ResumeInternal [this=%p]\n", this));
  238. return nsBaseChannel::Resume();
  239. }