TCPSocketChild.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  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 file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include <algorithm>
  6. #include "TCPSocketChild.h"
  7. #include "mozilla/Unused.h"
  8. #include "mozilla/UniquePtr.h"
  9. #include "mozilla/net/NeckoChild.h"
  10. #include "mozilla/dom/PBrowserChild.h"
  11. #include "mozilla/dom/TabChild.h"
  12. #include "nsITCPSocketCallback.h"
  13. #include "TCPSocket.h"
  14. #include "nsContentUtils.h"
  15. #include "jsapi.h"
  16. #include "jsfriendapi.h"
  17. using mozilla::net::gNeckoChild;
  18. namespace IPC {
  19. bool
  20. DeserializeArrayBuffer(JSContext* cx,
  21. const InfallibleTArray<uint8_t>& aBuffer,
  22. JS::MutableHandle<JS::Value> aVal)
  23. {
  24. mozilla::UniquePtr<uint8_t[], JS::FreePolicy> data(js_pod_malloc<uint8_t>(aBuffer.Length()));
  25. if (!data)
  26. return false;
  27. memcpy(data.get(), aBuffer.Elements(), aBuffer.Length());
  28. JSObject* obj = JS_NewArrayBufferWithContents(cx, aBuffer.Length(), data.get());
  29. if (!obj)
  30. return false;
  31. // If JS_NewArrayBufferWithContents returns non-null, the ownership of
  32. // the data is transfered to obj, so we release the ownership here.
  33. mozilla::Unused << data.release();
  34. aVal.setObject(*obj);
  35. return true;
  36. }
  37. } // namespace IPC
  38. namespace mozilla {
  39. namespace dom {
  40. NS_IMPL_CYCLE_COLLECTION_CLASS(TCPSocketChildBase)
  41. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TCPSocketChildBase)
  42. NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSocket)
  43. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  44. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TCPSocketChildBase)
  45. NS_IMPL_CYCLE_COLLECTION_UNLINK(mSocket)
  46. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  47. NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TCPSocketChildBase)
  48. NS_IMPL_CYCLE_COLLECTION_TRACE_END
  49. NS_IMPL_CYCLE_COLLECTING_ADDREF(TCPSocketChildBase)
  50. NS_IMPL_CYCLE_COLLECTING_RELEASE(TCPSocketChildBase)
  51. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TCPSocketChildBase)
  52. NS_INTERFACE_MAP_ENTRY(nsISupports)
  53. NS_INTERFACE_MAP_END
  54. TCPSocketChildBase::TCPSocketChildBase()
  55. : mIPCOpen(false)
  56. {
  57. mozilla::HoldJSObjects(this);
  58. }
  59. TCPSocketChildBase::~TCPSocketChildBase()
  60. {
  61. mozilla::DropJSObjects(this);
  62. }
  63. NS_IMETHODIMP_(MozExternalRefCountType) TCPSocketChild::Release(void)
  64. {
  65. nsrefcnt refcnt = TCPSocketChildBase::Release();
  66. if (refcnt == 1 && mIPCOpen) {
  67. PTCPSocketChild::SendRequestDelete();
  68. return 1;
  69. }
  70. return refcnt;
  71. }
  72. TCPSocketChild::TCPSocketChild(const nsAString& aHost, const uint16_t& aPort)
  73. : mHost(aHost)
  74. , mPort(aPort)
  75. {
  76. }
  77. void
  78. TCPSocketChild::SendOpen(nsITCPSocketCallback* aSocket, bool aUseSSL, bool aUseArrayBuffers)
  79. {
  80. mSocket = aSocket;
  81. AddIPDLReference();
  82. gNeckoChild->SendPTCPSocketConstructor(this, mHost, mPort);
  83. MOZ_ASSERT(mFilterName.IsEmpty()); // Currently nobody should use this
  84. PTCPSocketChild::SendOpen(mHost, mPort, aUseSSL, aUseArrayBuffers);
  85. }
  86. void
  87. TCPSocketChild::SendWindowlessOpenBind(nsITCPSocketCallback* aSocket,
  88. const nsACString& aRemoteHost, uint16_t aRemotePort,
  89. const nsACString& aLocalHost, uint16_t aLocalPort,
  90. bool aUseSSL)
  91. {
  92. mSocket = aSocket;
  93. AddIPDLReference();
  94. gNeckoChild->SendPTCPSocketConstructor(this,
  95. NS_ConvertUTF8toUTF16(aRemoteHost),
  96. aRemotePort);
  97. PTCPSocketChild::SendOpenBind(nsCString(aRemoteHost), aRemotePort,
  98. nsCString(aLocalHost), aLocalPort,
  99. aUseSSL, true, mFilterName);
  100. }
  101. void
  102. TCPSocketChildBase::ReleaseIPDLReference()
  103. {
  104. MOZ_ASSERT(mIPCOpen);
  105. mIPCOpen = false;
  106. mSocket = nullptr;
  107. this->Release();
  108. }
  109. void
  110. TCPSocketChildBase::AddIPDLReference()
  111. {
  112. MOZ_ASSERT(!mIPCOpen);
  113. mIPCOpen = true;
  114. this->AddRef();
  115. }
  116. TCPSocketChild::~TCPSocketChild()
  117. {
  118. }
  119. bool
  120. TCPSocketChild::RecvUpdateBufferedAmount(const uint32_t& aBuffered,
  121. const uint32_t& aTrackingNumber)
  122. {
  123. mSocket->UpdateBufferedAmount(aBuffered, aTrackingNumber);
  124. return true;
  125. }
  126. bool
  127. TCPSocketChild::RecvCallback(const nsString& aType,
  128. const CallbackData& aData,
  129. const uint32_t& aReadyState)
  130. {
  131. mSocket->UpdateReadyState(aReadyState);
  132. if (aData.type() == CallbackData::Tvoid_t) {
  133. mSocket->FireEvent(aType);
  134. } else if (aData.type() == CallbackData::TTCPError) {
  135. const TCPError& err(aData.get_TCPError());
  136. mSocket->FireErrorEvent(err.name(), err.message());
  137. } else if (aData.type() == CallbackData::TSendableData) {
  138. const SendableData& data = aData.get_SendableData();
  139. if (data.type() == SendableData::TArrayOfuint8_t) {
  140. mSocket->FireDataArrayEvent(aType, data.get_ArrayOfuint8_t());
  141. } else if (data.type() == SendableData::TnsCString) {
  142. mSocket->FireDataStringEvent(aType, data.get_nsCString());
  143. } else {
  144. MOZ_CRASH("Invalid callback data type!");
  145. }
  146. } else {
  147. MOZ_CRASH("Invalid callback type!");
  148. }
  149. return true;
  150. }
  151. void
  152. TCPSocketChild::SendSend(const nsACString& aData, uint32_t aTrackingNumber)
  153. {
  154. SendData(nsCString(aData), aTrackingNumber);
  155. }
  156. nsresult
  157. TCPSocketChild::SendSend(const ArrayBuffer& aData,
  158. uint32_t aByteOffset,
  159. uint32_t aByteLength,
  160. uint32_t aTrackingNumber)
  161. {
  162. uint32_t buflen = aData.Length();
  163. uint32_t offset = std::min(buflen, aByteOffset);
  164. uint32_t nbytes = std::min(buflen - aByteOffset, aByteLength);
  165. FallibleTArray<uint8_t> fallibleArr;
  166. if (!fallibleArr.InsertElementsAt(0, aData.Data() + offset, nbytes, fallible)) {
  167. return NS_ERROR_OUT_OF_MEMORY;
  168. }
  169. InfallibleTArray<uint8_t> arr;
  170. arr.SwapElements(fallibleArr);
  171. SendData(arr, aTrackingNumber);
  172. return NS_OK;
  173. }
  174. NS_IMETHODIMP
  175. TCPSocketChild::SendSendArray(nsTArray<uint8_t>& aArray, uint32_t aTrackingNumber)
  176. {
  177. SendData(aArray, aTrackingNumber);
  178. return NS_OK;
  179. }
  180. void
  181. TCPSocketChild::SetSocket(TCPSocket* aSocket)
  182. {
  183. mSocket = aSocket;
  184. }
  185. void
  186. TCPSocketChild::GetHost(nsAString& aHost)
  187. {
  188. aHost = mHost;
  189. }
  190. void
  191. TCPSocketChild::GetPort(uint16_t* aPort)
  192. {
  193. *aPort = mPort;
  194. }
  195. nsresult
  196. TCPSocketChild::SetFilterName(const nsACString& aFilterName)
  197. {
  198. if (!mFilterName.IsEmpty()) {
  199. // filter name can only be set once.
  200. return NS_ERROR_FAILURE;
  201. }
  202. mFilterName = aFilterName;
  203. return NS_OK;
  204. }
  205. bool
  206. TCPSocketChild::RecvRequestDelete()
  207. {
  208. mozilla::Unused << Send__delete__(this);
  209. return true;
  210. }
  211. } // namespace dom
  212. } // namespace mozilla