michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "UDPSocketChild.h" michael@0: #include "mozilla/net/NeckoChild.h" michael@0: michael@0: using mozilla::net::gNeckoChild; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: NS_IMPL_ISUPPORTS(UDPSocketChildBase, nsIUDPSocketChild) michael@0: michael@0: UDPSocketChildBase::UDPSocketChildBase() michael@0: : mIPCOpen(false) michael@0: { michael@0: } michael@0: michael@0: UDPSocketChildBase::~UDPSocketChildBase() michael@0: { michael@0: } michael@0: michael@0: void michael@0: UDPSocketChildBase::ReleaseIPDLReference() michael@0: { michael@0: MOZ_ASSERT(mIPCOpen); michael@0: mIPCOpen = false; michael@0: this->Release(); michael@0: } michael@0: michael@0: void michael@0: UDPSocketChildBase::AddIPDLReference() michael@0: { michael@0: MOZ_ASSERT(!mIPCOpen); michael@0: mIPCOpen = true; michael@0: this->AddRef(); michael@0: } michael@0: michael@0: NS_IMETHODIMP_(MozExternalRefCountType) UDPSocketChild::Release(void) michael@0: { michael@0: nsrefcnt refcnt = UDPSocketChildBase::Release(); michael@0: if (refcnt == 1 && mIPCOpen) { michael@0: PUDPSocketChild::SendRequestDelete(); michael@0: return 1; michael@0: } michael@0: return refcnt; michael@0: } michael@0: michael@0: UDPSocketChild::UDPSocketChild() michael@0: :mLocalPort(0) michael@0: { michael@0: } michael@0: michael@0: UDPSocketChild::~UDPSocketChild() michael@0: { michael@0: } michael@0: michael@0: // nsIUDPSocketChild Methods michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::Bind(nsIUDPSocketInternal *aSocket, michael@0: const nsACString& aHost, michael@0: uint16_t aPort) michael@0: { michael@0: NS_ENSURE_ARG(aSocket); michael@0: michael@0: mSocket = aSocket; michael@0: AddIPDLReference(); michael@0: michael@0: gNeckoChild->SendPUDPSocketConstructor(this, nsCString(aHost), aPort, mFilterName); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::Close() michael@0: { michael@0: SendClose(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::Send(const nsACString& aHost, michael@0: uint16_t aPort, michael@0: const uint8_t *aData, michael@0: uint32_t aByteLength) michael@0: { michael@0: NS_ENSURE_ARG(aData); michael@0: michael@0: FallibleTArray fallibleArray; michael@0: if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) { michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: InfallibleTArray array; michael@0: array.SwapElements(fallibleArray); michael@0: SendData(array, nsCString(aHost), aPort); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::SendWithAddr(nsINetAddr *aAddr, michael@0: const uint8_t *aData, michael@0: uint32_t aByteLength) michael@0: { michael@0: NS_ENSURE_ARG(aAddr); michael@0: NS_ENSURE_ARG(aData); michael@0: michael@0: NetAddr addr; michael@0: aAddr->GetNetAddr(&addr); michael@0: michael@0: return SendWithAddress(&addr, aData, aByteLength); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::SendWithAddress(const NetAddr *aAddr, michael@0: const uint8_t *aData, michael@0: uint32_t aByteLength) michael@0: { michael@0: NS_ENSURE_ARG(aAddr); michael@0: NS_ENSURE_ARG(aData); michael@0: michael@0: FallibleTArray fallibleArray; michael@0: if (!fallibleArray.InsertElementsAt(0, aData, aByteLength)) { michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: } michael@0: michael@0: InfallibleTArray array; michael@0: array.SwapElements(fallibleArray); michael@0: SendDataWithAddress(array, *aAddr); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::GetLocalPort(uint16_t *aLocalPort) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aLocalPort); michael@0: michael@0: *aLocalPort = mLocalPort; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::GetLocalAddress(nsACString &aLocalAddress) michael@0: { michael@0: aLocalAddress = mLocalAddress; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::SetFilterName(const nsACString &aFilterName) michael@0: { michael@0: if (!mFilterName.IsEmpty()) { michael@0: // filter name can only be set once. michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: mFilterName = aFilterName; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: UDPSocketChild::GetFilterName(nsACString &aFilterName) michael@0: { michael@0: aFilterName = mFilterName; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // PUDPSocketChild Methods michael@0: bool michael@0: UDPSocketChild::RecvCallback(const nsCString &aType, michael@0: const UDPCallbackData &aData, michael@0: const nsCString &aState) michael@0: { michael@0: if (NS_FAILED(mSocket->UpdateReadyState(aState))) michael@0: NS_ERROR("Shouldn't fail!"); michael@0: michael@0: nsresult rv = NS_ERROR_FAILURE; michael@0: if (aData.type() == UDPCallbackData::Tvoid_t) { michael@0: rv = mSocket->CallListenerVoid(aType); michael@0: } else if (aData.type() == UDPCallbackData::TUDPError) { michael@0: const UDPError& err(aData.get_UDPError()); michael@0: rv = mSocket->CallListenerError(aType, err.message(), err.filename(), michael@0: err.lineNumber(), err.columnNumber()); michael@0: } else if (aData.type() == UDPCallbackData::TUDPMessage) { michael@0: const UDPMessage& message(aData.get_UDPMessage()); michael@0: InfallibleTArray data(message.data()); michael@0: rv = mSocket->CallListenerReceivedData(aType, message.fromAddr(), message.port(), michael@0: data.Elements(), data.Length()); michael@0: } else if (aData.type() == UDPCallbackData::TUDPAddressInfo) { michael@0: //update local address and port. michael@0: const UDPAddressInfo& addressInfo(aData.get_UDPAddressInfo()); michael@0: mLocalAddress = addressInfo.local(); michael@0: mLocalPort = addressInfo.port(); michael@0: rv = mSocket->CallListenerVoid(aType); michael@0: } else if (aData.type() == UDPCallbackData::TUDPSendResult) { michael@0: const UDPSendResult& returnValue(aData.get_UDPSendResult()); michael@0: rv = mSocket->CallListenerSent(aType, returnValue.value()); michael@0: } else { michael@0: MOZ_ASSERT(false, "Invalid callback type!"); michael@0: } michael@0: michael@0: NS_ENSURE_SUCCESS(rv, true); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla