• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libjingle
3  * Copyright 2004--2005, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #ifndef TALK_P2P_BASE_PORT_H_
29 #define TALK_P2P_BASE_PORT_H_
30 
31 #include <string>
32 #include <vector>
33 #include <map>
34 
35 #include "talk/base/network.h"
36 #include "talk/base/packetsocketfactory.h"
37 #include "talk/base/proxyinfo.h"
38 #include "talk/base/ratetracker.h"
39 #include "talk/base/sigslot.h"
40 #include "talk/base/socketaddress.h"
41 #include "talk/base/thread.h"
42 #include "talk/p2p/base/candidate.h"
43 #include "talk/p2p/base/stun.h"
44 #include "talk/p2p/base/stunrequest.h"
45 
46 namespace talk_base {
47 class AsyncPacketSocket;
48 }
49 
50 namespace cricket {
51 
52 class Connection;
53 class ConnectionRequest;
54 
55 enum ProtocolType {
56   PROTO_UDP,
57   PROTO_TCP,
58   PROTO_SSLTCP,
59   PROTO_LAST = PROTO_SSLTCP
60 };
61 
62 const char* ProtoToString(ProtocolType proto);
63 bool StringToProto(const char* value, ProtocolType* proto);
64 
65 struct ProtocolAddress {
66   talk_base::SocketAddress address;
67   ProtocolType proto;
68 
ProtocolAddressProtocolAddress69   ProtocolAddress(const talk_base::SocketAddress& a, ProtocolType p)
70     : address(a), proto(p) { }
71 };
72 
73 // Represents a local communication mechanism that can be used to create
74 // connections to similar mechanisms of the other client.  Subclasses of this
75 // one add support for specific mechanisms like local UDP ports.
76 class Port : public talk_base::MessageHandler, public sigslot::has_slots<> {
77  public:
78   Port(talk_base::Thread* thread, const std::string& type,
79        talk_base::PacketSocketFactory* factory, talk_base::Network* network,
80        uint32 ip, int min_port, int max_port);
81   virtual ~Port();
82 
83   // The thread on which this port performs its I/O.
thread()84   talk_base::Thread* thread() { return thread_; }
85 
86   // The factory used to create the sockets of this port.
socket_factory()87   talk_base::PacketSocketFactory* socket_factory() const { return factory_; }
set_socket_factory(talk_base::PacketSocketFactory * factory)88   void set_socket_factory(talk_base::PacketSocketFactory* factory) {
89     factory_ = factory;
90   }
91 
92   // Each port is identified by a name (for debugging purposes).
name()93   const std::string& name() const { return name_; }
set_name(const std::string & name)94   void set_name(const std::string& name) { name_ = name; }
95 
96   // In order to establish a connection to this Port (so that real data can be
97   // sent through), the other side must send us a STUN binding request that is
98   // authenticated with this username and password.
99   // Fills in the username fragment and password.  These will be initially set
100   // in the constructor to random values.  Subclasses or tests can override.
101   // TODO: Change this to "username" rather than "username_fragment".
username_fragment()102   const std::string& username_fragment() const { return username_frag_; }
set_username_fragment(const std::string & username)103   void set_username_fragment(const std::string& username) {
104     username_frag_ = username;
105   }
106 
password()107   const std::string& password() const { return password_; }
set_password(const std::string & password)108   void set_password(const std::string& password) { password_ = password; }
109 
110 
111   // A value in [0,1] that indicates the preference for this port versus other
112   // ports on this client.  (Larger indicates more preference.)
preference()113   float preference() const { return preference_; }
set_preference(float preference)114   void set_preference(float preference) { preference_ = preference; }
115 
116   // Identifies the port type.
type()117   const std::string& type() const { return type_; }
118 
119   // Identifies network that this port was allocated on.
network()120   talk_base::Network* network() { return network_; }
121 
122   // Identifies the generation that this port was created in.
generation()123   uint32 generation() { return generation_; }
set_generation(uint32 generation)124   void set_generation(uint32 generation) { generation_ = generation; }
125 
126   // PrepareAddress will attempt to get an address for this port that other
127   // clients can send to.  It may take some time before the address is read.
128   // Once it is ready, we will send SignalAddressReady.  If errors are
129   // preventing the port from getting an address, it may send
130   // SignalAddressError.
131   virtual void PrepareAddress() = 0;
132   sigslot::signal1<Port*> SignalAddressReady;
133   sigslot::signal1<Port*> SignalAddressError;
134 
135   // Provides all of the above information in one handy object.
candidates()136   const std::vector<Candidate>& candidates() const { return candidates_; }
137 
138   // Returns a map containing all of the connections of this port, keyed by the
139   // remote address.
140   typedef std::map<talk_base::SocketAddress, Connection*> AddressMap;
connections()141   const AddressMap& connections() { return connections_; }
142 
143   // Returns the connection to the given address or NULL if none exists.
144   Connection* GetConnection(const talk_base::SocketAddress& remote_addr);
145 
146   // Creates a new connection to the given address.
147   enum CandidateOrigin { ORIGIN_THIS_PORT, ORIGIN_OTHER_PORT, ORIGIN_MESSAGE };
148   virtual Connection* CreateConnection(const Candidate& remote_candidate,
149     CandidateOrigin origin) = 0;
150 
151   // Called each time a connection is created.
152   sigslot::signal2<Port*, Connection*> SignalConnectionCreated;
153 
154   // Sends the given packet to the given address, provided that the address is
155   // that of a connection or an address that has sent to us already.
156   virtual int SendTo(
157       const void* data, size_t size, const talk_base::SocketAddress& addr,
158       bool payload) = 0;
159 
160   // Indicates that we received a successful STUN binding request from an
161   // address that doesn't correspond to any current connection.  To turn this
162   // into a real connection, call CreateConnection.
163   sigslot::signal4<Port*, const talk_base::SocketAddress&, StunMessage*,
164                    const std::string&> SignalUnknownAddress;
165 
166   // Sends a response message (normal or error) to the given request.  One of
167   // these methods should be called as a response to SignalUnknownAddress.
168   // NOTE: You MUST call CreateConnection BEFORE SendBindingResponse.
169   void SendBindingResponse(StunMessage* request,
170                            const talk_base::SocketAddress& addr);
171   void SendBindingErrorResponse(
172       StunMessage* request, const talk_base::SocketAddress& addr,
173       int error_code, const std::string& reason);
174 
175   // Indicates that errors occurred when performing I/O.
176   sigslot::signal2<Port*, int> SignalReadError;
177   sigslot::signal2<Port*, int> SignalWriteError;
178 
179   // Functions on the underlying socket(s).
180   virtual int SetOption(talk_base::Socket::Option opt, int value) = 0;
181   virtual int GetError() = 0;
182 
set_proxy(const std::string & user_agent,const talk_base::ProxyInfo & proxy)183   void set_proxy(const std::string& user_agent,
184                  const talk_base::ProxyInfo& proxy) {
185     user_agent_ = user_agent;
186     proxy_ = proxy;
187   }
user_agent()188   const std::string& user_agent() { return user_agent_; }
proxy()189   const talk_base::ProxyInfo& proxy() { return proxy_; }
190 
191   // Normally, packets arrive through a connection (or they result signaling of
192   // unknown address).  Calling this method turns off delivery of packets
193   // through their respective connection and instead delivers every packet
194   // through this port.
195   void EnablePortPackets();
196   sigslot::signal4<Port*, const char*, size_t, const talk_base::SocketAddress&>
197       SignalReadPacket;
198 
199   // Indicates to the port that its official use has now begun.  This will
200   // start the timer that checks to see if the port is being used.
201   void Start();
202 
203   // Called if the port has no connections and is no longer useful.
204   void Destroy();
205 
206   // Signaled when this port decides to delete itself because it no longer has
207   // any usefulness.
208   sigslot::signal1<Port*> SignalDestroyed;
209 
210   virtual void OnMessage(talk_base::Message *pmsg);
211 
212   // Debugging description of this port
213   std::string ToString() const;
214 
215  protected:
216   // Fills in the local address of the port.
217   void AddAddress(const talk_base::SocketAddress& address,
218                   const std::string& protocol, bool final);
219 
220   // Adds the given connection to the list.  (Deleting removes them.)
221   void AddConnection(Connection* conn);
222 
223   // Called when a packet is received from an unknown address that is not
224   // currently a connection.  If this is an authenticated STUN binding request,
225   // then we will signal the client.
226   void OnReadPacket(const char* data, size_t size,
227                     const talk_base::SocketAddress& addr);
228 
229 
230   // If the given data comprises a complete and correct STUN message then the
231   // return value is true, otherwise false. If the message username corresponds
232   // with this port's username fragment, msg will contain the parsed STUN
233   // message.  Otherwise, the function may send a STUN response internally.
234   // remote_username contains the remote fragment of the STUN username.
235   bool GetStunMessage(const char* data, size_t size,
236                       const talk_base::SocketAddress& addr,
237                       StunMessage** out_msg, std::string* out_username);
238 
239   // TODO: make these members private
240   talk_base::Thread* thread_;
241   talk_base::PacketSocketFactory* factory_;
242   std::string type_;
243   talk_base::Network* network_;
244   uint32 ip_;
245   int min_port_;
246   int max_port_;
247   uint32 generation_;
248   std::string name_;
249   std::string username_frag_;
250   std::string password_;
251   float preference_;
252   std::vector<Candidate> candidates_;
253   AddressMap connections_;
254   enum Lifetime { LT_PRESTART, LT_PRETIMEOUT, LT_POSTTIMEOUT } lifetime_;
255   bool enable_port_packets_;
256 
257  private:
258   // Called when one of our connections deletes itself.
259   void OnConnectionDestroyed(Connection* conn);
260 
261   // Checks if this port is useless, and hence, should be destroyed.
262   void CheckTimeout();
263 
264   // Information to use when going through a proxy.
265   std::string user_agent_;
266   talk_base::ProxyInfo proxy_;
267 
268   friend class Connection;
269 };
270 
271 // Represents a communication link between a port on the local client and a
272 // port on the remote client.
273 class Connection : public talk_base::MessageHandler,
274     public sigslot::has_slots<> {
275  public:
276   virtual ~Connection();
277 
278   // The local port where this connection sends and receives packets.
port()279   Port* port() { return port_; }
port()280   const Port* port() const { return port_; }
281 
282   // Returns the description of the local port
283   virtual const Candidate& local_candidate() const;
284 
285   // Returns the description of the remote port to which we communicate.
remote_candidate()286   const Candidate& remote_candidate() const { return remote_candidate_; }
287 
288   enum ReadState {
289     STATE_READABLE     = 0,  // we have received pings recently
290     STATE_READ_TIMEOUT = 1   // we haven't received pings in a while
291   };
292 
read_state()293   ReadState read_state() const { return read_state_; }
294 
295   enum WriteState {
296     STATE_WRITABLE      = 0,  // we have received ping responses recently
297     STATE_WRITE_CONNECT = 1,  // we have had a few ping failures
298     STATE_WRITE_TIMEOUT = 2   // we have had a large number of ping failures
299   };
300 
write_state()301   WriteState write_state() const { return write_state_; }
302 
303   // Determines whether the connection has finished connecting.  This can only
304   // be false for TCP connections.
connected()305   bool connected() const { return connected_; }
306 
307   // Estimate of the round-trip time over this connection.
rtt()308   uint32 rtt() const { return rtt_; }
309 
310   size_t sent_total_bytes();
311   size_t sent_bytes_second();
312   size_t recv_total_bytes();
313   size_t recv_bytes_second();
314   sigslot::signal1<Connection*> SignalStateChange;
315 
316   // Sent when the connection has decided that it is no longer of value.  It
317   // will delete itself immediately after this call.
318   sigslot::signal1<Connection*> SignalDestroyed;
319 
320   // The connection can send and receive packets asynchronously.  This matches
321   // the interface of AsyncPacketSocket, which may use UDP or TCP under the
322   // covers.
323   virtual int Send(const void* data, size_t size) = 0;
324 
325   // Error if Send() returns < 0
326   virtual int GetError() = 0;
327 
328   sigslot::signal3<Connection*, const char*, size_t> SignalReadPacket;
329 
330   // Called when a packet is received on this connection.
331   void OnReadPacket(const char* data, size_t size);
332 
333   // Called when a connection is determined to be no longer useful to us.  We
334   // still keep it around in case the other side wants to use it.  But we can
335   // safely stop pinging on it and we can allow it to time out if the other
336   // side stops using it as well.
pruned()337   bool pruned() const { return pruned_; }
338   void Prune();
339 
340   // Makes the connection go away.
341   void Destroy();
342 
343   // Checks that the state of this connection is up-to-date.  The argument is
344   // the current time, which is compared against various timeouts.
345   void UpdateState(uint32 now);
346 
347   // Called when this connection should try checking writability again.
last_ping_sent()348   uint32 last_ping_sent() const { return last_ping_sent_; }
349   void Ping(uint32 now);
350 
351   // Called whenever a valid ping is received on this connection.  This is
352   // public because the connection intercepts the first ping for us.
353   void ReceivedPing();
354 
355   // Debugging description of this connection
356   std::string ToString() const;
357 
reported()358   bool reported() const { return reported_; }
set_reported(bool reported)359   void set_reported(bool reported) { reported_ = reported;}
360 
361  protected:
362   // Constructs a new connection to the given remote port.
363   Connection(Port* port, size_t index, const Candidate& candidate);
364 
365   // Called back when StunRequestManager has a stun packet to send
366   void OnSendStunPacket(const void* data, size_t size, StunRequest* req);
367 
368   // Callbacks from ConnectionRequest
369   void OnConnectionRequestResponse(ConnectionRequest* req,
370                                    StunMessage* response);
371   void OnConnectionRequestErrorResponse(ConnectionRequest* req,
372                                         StunMessage* response);
373   void OnConnectionRequestTimeout(ConnectionRequest* req);
374 
375   // Changes the state and signals if necessary.
376   void set_read_state(ReadState value);
377   void set_write_state(WriteState value);
378   void set_connected(bool value);
379 
380   // Checks if this connection is useless, and hence, should be destroyed.
381   void CheckTimeout();
382 
383   void OnMessage(talk_base::Message *pmsg);
384 
385   Port* port_;
386   size_t local_candidate_index_;
387   Candidate remote_candidate_;
388   ReadState read_state_;
389   WriteState write_state_;
390   bool connected_;
391   bool pruned_;
392   StunRequestManager requests_;
393   uint32 rtt_;
394   uint32 last_ping_sent_;      // last time we sent a ping to the other side
395   uint32 last_ping_received_;  // last time we received a ping from the other
396                                // side
397   uint32 last_data_received_;
398   std::vector<uint32> pings_since_last_response_;
399 
400   talk_base::RateTracker recv_rate_tracker_;
401   talk_base::RateTracker send_rate_tracker_;
402 
403  private:
404   bool reported_;
405 
406   friend class Port;
407   friend class ConnectionRequest;
408 };
409 
410 // ProxyConnection defers all the interesting work to the port
411 class ProxyConnection : public Connection {
412  public:
413   ProxyConnection(Port* port, size_t index, const Candidate& candidate);
414 
415   virtual int Send(const void* data, size_t size);
GetError()416   virtual int GetError() { return error_; }
417 
418  private:
419   int error_;
420 };
421 
422 }  // namespace cricket
423 
424 #endif  // TALK_P2P_BASE_PORT_H_
425