1 /*
2  * upnpcp.h
3  *
4  * UPnP NAT Traversal class.
5  *
6  * h323plus library
7  *
8  * Copyright (c) 2009 ISVO (Asia) Pte. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.1 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Alternatively, the contents of this file may be used under the terms
16  * of the General Public License (the  "GNU License"), in which case the
17  * provisions of GNU License are applicable instead of those
18  * above. If you wish to allow use of your version of this file only
19  * under the terms of the GNU License and not to allow others to use
20  * your version of this file under the MPL, indicate your decision by
21  * deleting the provisions above and replace them with the notice and
22  * other provisions required by the GNU License. If you do not delete
23  * the provisions above, a recipient may use your version of this file
24  * under either the MPL or the GNU License."
25  *
26  * Software distributed under the License is distributed on an "AS IS"
27  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
28  * the License for the specific language governing rights and limitations
29  * under the License.
30  *
31  *
32  * The Initial Developer of the Original Code is ISVO (Asia) Pte. Ltd.
33  *
34  *
35  * Contributor(s): ______________________________________.
36  *
37  * $Id$
38  *
39  *
40  */
41 
42 #ifndef H_UPNP
43 #define H_UPNP
44 
45 #include <ptclib/pnat.h>
46 
47 #if _MSC_VER
48 #pragma once
49 #endif
50 
51 class H323EndPoint;
52 class UPnPThread;
53 class PNatMethod_UPnP : public H323NatMethod
54 {
55     PCLASSINFO(PNatMethod_UPnP,H323NatMethod);
56 
57 public:
58 
59   /**@name Construction */
60   //@{
61     /** Default Contructor
62     */
63     PNatMethod_UPnP();
64 
65     /** Deconstructor
66     */
67     ~PNatMethod_UPnP();
68   //@}
69 
70   /**@name General Functions */
71   //@{
72    void AttachEndPoint(H323EndPoint * _ep);
73 
74    virtual PBoolean GetExternalAddress(
75       PIPSocket::Address & externalAddress, /// External address of router
76       const PTimeInterval & maxAge = 1000   /// Maximum age for caching
77       );
78 
79  /**  CreateSocketPair
80         Create the UDP Socket pair (not used)
81   */
CreateSocketPair(PUDPSocket * &,PUDPSocket * &,const PIPSocket::Address &)82    virtual PBoolean CreateSocketPair(
83        PUDPSocket *&,PUDPSocket *&,
84        const PIPSocket::Address &) { return false; }
85 
86   /**  CreateSocketPair
87         Create the UDP Socket pair
88   */
89     virtual PBoolean CreateSocketPair(
90       PUDPSocket * & socket1,
91       PUDPSocket * & socket2,
92       const PIPSocket::Address & binding,
93       void * userData
94     );
95 
96   /** Retreive a random port in the allocated port range
97     */
98     WORD GetRandomPort();
99 
100   /**  isAvailable.
101         Returns whether the Nat Method is ready and available in
102         assisting in NAT Traversal. The principal is function is
103         to allow the EP to detect various methods and if a method
104         is detected then this method is available for NAT traversal
105         The Order of adding to the PNstStrategy determines which method
106         is used
107   */
108    virtual bool IsAvailable(const PIPSocket::Address & ip);
109 
110    void SetAvailable();
111 
112    void SetAvailable(const PString & devName);
113 
114    virtual void Activate(bool act);
115 
116    PBoolean OpenSocket(PUDPSocket & socket, PortInfo & portInfo, const PIPSocket::Address & binding) const;
117 
118 #if PTLIB_VER >= 2130
119    static const char * MethodName();
120    virtual PCaselessString GetMethodName() const;
121 #elif PTLIB_VER > 2120
GetNatMethodName()122    static PString GetNatMethodName() { return "UPnP"; }
GetName()123    virtual PString GetName() const
124             { return GetNatMethodName(); }
125 #else
GetNatMethodName()126    static PStringList GetNatMethodName() {  return PStringArray("UPnP"); }
GetName()127    virtual PString GetName() const
128             { return GetNatMethodName()[0]; }
129 #endif
130 
131    // All these are virtual and never used.
GetServerAddress(PIPSocket::Address & address,WORD & port)132     virtual bool GetServerAddress(
133       PIPSocket::Address & address,   ///< Address of server
134       WORD & port                     ///< Port server is using.
135       ) const { return false; }
136 
GetInterfaceAddress(PIPSocket::Address & internalAddress)137     virtual bool GetInterfaceAddress(
138       PIPSocket::Address & internalAddress
139       ) const { return false; }
140 
141     virtual PBoolean CreateSocket(
142       PUDPSocket * & socket,
143       const PIPSocket::Address & binding = PIPSocket::GetDefaultIpAny(),
144       WORD localPort = 0
145       ) { return false; }
146 
147     virtual RTPSupportTypes GetRTPSupport(
148       PBoolean force = PFalse    ///< Force a new check
149       );
150   //@}
151 
152     void SetExtIPAddress(const PString & newAddr);
153 
154     PBoolean OnUPnPAvailable(const PString & devName);
155 
156     PBoolean CreateUPnPMap(bool pair, const PString & protocol, const PIPSocket::Address & localIP,
157                            const WORD & locPort, PIPSocket::Address & extIP , WORD & extPort, PBoolean force = false);
158 
159     void RemoveUPnPMap(WORD port, PBoolean udp = true);
160 
161     H323EndPoint * GetEndPoint();
162 
163 #if PTLIB_VER >= 2110
GetServer()164     virtual PString GetServer() const { return PString(); }
GetServerAddress(PIPSocketAddressAndPort &)165     virtual bool GetServerAddress(PIPSocketAddressAndPort & ) const { return false; }
GetNatType(bool)166     virtual NatTypes GetNatType(bool) { return UnknownNat; }
GetNatType(const PTimeInterval &)167     virtual NatTypes GetNatType(const PTimeInterval &) { return UnknownNat; }
SetServer(const PString &)168     virtual bool SetServer(const PString &) { return false; }
Open(const PIPSocket::Address &)169     virtual bool Open(const PIPSocket::Address &) { return false; }
170     virtual bool CreateSocket(BYTE component,PUDPSocket * & socket,
171             const PIPSocket::Address & binding = PIPSocket::GetDefaultIpAny(),WORD localPort = 0)  { return false; }
SetCredentials(const PString &,const PString &,const PString &)172     virtual void SetCredentials(const PString &, const PString &, const PString &) {}
173 protected:
174 #if PTLIB_VER < 2130
InternalGetNatType(bool,const PTimeInterval &)175     virtual NatTypes InternalGetNatType(bool, const PTimeInterval &) { return UnknownNat; }
176 #endif
177 #if PTLIB_VER >= 2120
InternalCreateSocket(Component component,PObject * context)178     virtual PNATUDPSocket * InternalCreateSocket(Component component, PObject * context)  { return NULL; }
InternalUpdate()179     virtual void InternalUpdate() {};
180 #endif
181 #endif
182 
183 protected:
184 
185     void SetConnectionSockets(PUDPSocket * data,  PUDPSocket * control,
186                               H323Connection::SessionInformation * info );
187 
188 private:
189     H323EndPoint*                            ep;
190     UPnPThread*                                m_pUPnP;
191 
192     PIPSocket::Address                        m_pExtIP;
193 
194     PBoolean                                m_pShutdown;
195     PBoolean                                available;
196     PBoolean                                active;
197 };
198 
199 
200 #ifndef _WIN32_WCE
201     #if PTLIB_VER > 260
202        PPLUGIN_STATIC_LOAD(UPnP,PNatMethod);
203     #else
204        PWLIB_STATIC_LOAD_PLUGIN(UPnP,PNatMethod);
205     #endif
206 #endif
207 
208 
209 class UPnPUDPSocket : public H323UDPSocket
210 {
211   PCLASSINFO(UPnPUDPSocket, H323UDPSocket);
212   public:
213   /**@name Construction/Deconstructor */
214   //@{
215     /** create a UDP Socket Fully Nat Supported
216         ready for H323plus to Call.
217     */
218     UPnPUDPSocket(PNatMethod_UPnP * nat);
219 
220     /** Deconstructor to reallocate Socket and remove any exiting
221         allocated NAT ports,
222     */
223     ~UPnPUDPSocket();
224 
225     virtual PBoolean Close();
226 
227     /** Set Masq Address
228       */
229     void SetMasqAddress(const PIPSocket::Address & ip, WORD port);
230 
231     PBoolean GetLocalAddress(Address & addr);
232 
233     PBoolean GetLocalAddress(Address & addr, WORD & port);
234 
235    //@}
236 
237   protected:
238     PNatMethod_UPnP*        natMethod;
239 
240     PIPSocket::Address        extIP;
241     WORD                    extPort;
242 
243 };
244 
245 #endif  // H_UPNP
246 
247