1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 
7 #ifndef mozilla_dom_UDPSocket_h__
8 #define mozilla_dom_UDPSocket_h__
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "mozilla/dom/Promise.h"
13 #include "mozilla/dom/SocketCommonBinding.h"
14 #include "nsIUDPSocket.h"
15 #include "nsIUDPSocketChild.h"
16 #include "nsTArray.h"
17 
18 struct JSContext;
19 
20 //
21 // set MOZ_LOG=UDPSocket:5
22 //
23 
24 namespace mozilla {
25 class ErrorResult;
26 class LazyLogModule;
27 
28 namespace net {
29 extern LazyLogModule gUDPSocketLog;
30 #define UDPSOCKET_LOG(args) \
31   MOZ_LOG(::mozilla::net::gUDPSocketLog, LogLevel::Debug, args)
32 #define UDPSOCKET_LOG_ENABLED() \
33   MOZ_LOG_TEST(::mozilla::net::gUDPSocketLog, LogLevel::Debug)
34 }  // namespace net
35 
36 namespace dom {
37 
38 struct UDPOptions;
39 class StringOrBlobOrArrayBufferOrArrayBufferView;
40 class UDPSocketChild;
41 
42 class UDPSocket final : public DOMEventTargetHelper,
43                         public nsIUDPSocketListener,
44                         public nsIUDPSocketInternal {
45  public:
46   NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UDPSocket,DOMEventTargetHelper)47   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UDPSocket, DOMEventTargetHelper)
48   NS_DECL_NSIUDPSOCKETLISTENER
49   NS_DECL_NSIUDPSOCKETINTERNAL
50 
51  public:
52   nsPIDOMWindowInner* GetParentObject() const { return GetOwner(); }
53 
54   virtual JSObject* WrapObject(JSContext* aCx,
55                                JS::Handle<JSObject*> aGivenProto) override;
56 
57   virtual void DisconnectFromOwner() override;
58 
59   static already_AddRefed<UDPSocket> Constructor(const GlobalObject& aGlobal,
60                                                  const UDPOptions& aOptions,
61                                                  ErrorResult& aRv);
62 
GetLocalAddress(nsString & aRetVal)63   void GetLocalAddress(nsString& aRetVal) const { aRetVal = mLocalAddress; }
64 
GetLocalPort()65   Nullable<uint16_t> GetLocalPort() const { return mLocalPort; }
66 
GetRemoteAddress(nsString & aRetVal)67   void GetRemoteAddress(nsString& aRetVal) const {
68     if (mRemoteAddress.IsVoid()) {
69       SetDOMStringToNull(aRetVal);
70       return;
71     }
72 
73     CopyUTF8toUTF16(mRemoteAddress, aRetVal);
74   }
75 
GetRemotePort()76   Nullable<uint16_t> GetRemotePort() const { return mRemotePort; }
77 
AddressReuse()78   bool AddressReuse() const { return mAddressReuse; }
79 
Loopback()80   bool Loopback() const { return mLoopback; }
81 
ReadyState()82   SocketReadyState ReadyState() const { return mReadyState; }
83 
Opened()84   Promise* Opened() const { return mOpened; }
85 
Closed()86   Promise* Closed() const { return mClosed; }
87 
88   IMPL_EVENT_HANDLER(message)
89 
90   already_AddRefed<Promise> Close();
91 
92   void JoinMulticastGroup(const nsAString& aMulticastGroupAddress,
93                           ErrorResult& aRv);
94 
95   void LeaveMulticastGroup(const nsAString& aMulticastGroupAddress,
96                            ErrorResult& aRv);
97 
98   bool Send(const StringOrBlobOrArrayBufferOrArrayBufferView& aData,
99             const Optional<nsAString>& aRemoteAddress,
100             const Optional<Nullable<uint16_t>>& aRemotePort, ErrorResult& aRv);
101 
102  private:
103   class ListenerProxy : public nsIUDPSocketListener,
104                         public nsIUDPSocketInternal {
105    public:
106     NS_DECL_ISUPPORTS
NS_FORWARD_SAFE_NSIUDPSOCKETLISTENER(mSocket)107     NS_FORWARD_SAFE_NSIUDPSOCKETLISTENER(mSocket)
108     NS_FORWARD_SAFE_NSIUDPSOCKETINTERNAL(mSocket)
109 
110     explicit ListenerProxy(UDPSocket* aSocket) : mSocket(aSocket) {}
111 
Disconnect()112     void Disconnect() { mSocket = nullptr; }
113 
114    private:
115     virtual ~ListenerProxy() = default;
116 
117     UDPSocket* mSocket;
118   };
119 
120   UDPSocket(nsPIDOMWindowInner* aOwner, const nsCString& aRemoteAddress,
121             const Nullable<uint16_t>& aRemotePort);
122 
123   virtual ~UDPSocket();
124 
125   nsresult Init(const nsString& aLocalAddress,
126                 const Nullable<uint16_t>& aLocalPort, const bool& aAddressReuse,
127                 const bool& aLoopback);
128 
129   nsresult InitLocal(const nsAString& aLocalAddress,
130                      const uint16_t& aLocalPort);
131 
132   nsresult InitRemote(const nsAString& aLocalAddress,
133                       const uint16_t& aLocalPort);
134 
135   void HandleReceivedData(const nsACString& aRemoteAddress,
136                           const uint16_t& aRemotePort,
137                           const nsTArray<uint8_t>& aData);
138 
139   nsresult DispatchReceivedData(const nsACString& aRemoteAddress,
140                                 const uint16_t& aRemotePort,
141                                 const nsTArray<uint8_t>& aData);
142 
143   void CloseWithReason(nsresult aReason);
144 
145   nsresult DoPendingMcastCommand();
146 
147   nsString mLocalAddress;
148   Nullable<uint16_t> mLocalPort;
149   nsCString mRemoteAddress;
150   Nullable<uint16_t> mRemotePort;
151   bool mAddressReuse;
152   bool mLoopback;
153   SocketReadyState mReadyState;
154   RefPtr<Promise> mOpened;
155   RefPtr<Promise> mClosed;
156 
157   nsCOMPtr<nsIUDPSocket> mSocket;
158   RefPtr<UDPSocketChild> mSocketChild;
159   RefPtr<ListenerProxy> mListenerProxy;
160 
161   struct MulticastCommand {
162     enum CommandType { Join, Leave };
163 
MulticastCommandMulticastCommand164     MulticastCommand(CommandType aCommand, const nsAString& aAddress)
165         : mCommand(aCommand), mAddress(aAddress) {}
166 
167     CommandType mCommand;
168     nsString mAddress;
169   };
170 
171   nsTArray<MulticastCommand> mPendingMcastCommands;
172 };
173 
174 }  // namespace dom
175 }  // namespace mozilla
176 
177 #endif  // mozilla_dom_UDPSocket_h__
178