Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / p2p / base / basicpacketsocketfactory.cc
1 /*
2  *  Copyright 2011 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11 #include "webrtc/p2p/base/basicpacketsocketfactory.h"
12
13 #include "webrtc/p2p/base/asyncstuntcpsocket.h"
14 #include "webrtc/p2p/base/stun.h"
15 #include "webrtc/base/asynctcpsocket.h"
16 #include "webrtc/base/asyncudpsocket.h"
17 #include "webrtc/base/logging.h"
18 #include "webrtc/base/nethelpers.h"
19 #include "webrtc/base/physicalsocketserver.h"
20 #include "webrtc/base/scoped_ptr.h"
21 #include "webrtc/base/socketadapters.h"
22 #include "webrtc/base/ssladapter.h"
23 #include "webrtc/base/thread.h"
24
25 namespace rtc {
26
27 BasicPacketSocketFactory::BasicPacketSocketFactory()
28     : thread_(Thread::Current()),
29       socket_factory_(NULL) {
30 }
31
32 BasicPacketSocketFactory::BasicPacketSocketFactory(Thread* thread)
33     : thread_(thread),
34       socket_factory_(NULL) {
35 }
36
37 BasicPacketSocketFactory::BasicPacketSocketFactory(
38     SocketFactory* socket_factory)
39     : thread_(NULL),
40       socket_factory_(socket_factory) {
41 }
42
43 BasicPacketSocketFactory::~BasicPacketSocketFactory() {
44 }
45
46 AsyncPacketSocket* BasicPacketSocketFactory::CreateUdpSocket(
47     const SocketAddress& address, uint16 min_port, uint16 max_port) {
48   // UDP sockets are simple.
49   rtc::AsyncSocket* socket =
50       socket_factory()->CreateAsyncSocket(
51           address.family(), SOCK_DGRAM);
52   if (!socket) {
53     return NULL;
54   }
55   if (BindSocket(socket, address, min_port, max_port) < 0) {
56     LOG(LS_ERROR) << "UDP bind failed with error "
57                     << socket->GetError();
58     delete socket;
59     return NULL;
60   }
61   return new rtc::AsyncUDPSocket(socket);
62 }
63
64 AsyncPacketSocket* BasicPacketSocketFactory::CreateServerTcpSocket(
65     const SocketAddress& local_address, uint16 min_port, uint16 max_port,
66     int opts) {
67
68   // Fail if TLS is required.
69   if (opts & PacketSocketFactory::OPT_TLS) {
70     LOG(LS_ERROR) << "TLS support currently is not available.";
71     return NULL;
72   }
73
74   rtc::AsyncSocket* socket =
75       socket_factory()->CreateAsyncSocket(local_address.family(),
76                                           SOCK_STREAM);
77   if (!socket) {
78     return NULL;
79   }
80
81   if (BindSocket(socket, local_address, min_port, max_port) < 0) {
82     LOG(LS_ERROR) << "TCP bind failed with error "
83                   << socket->GetError();
84     delete socket;
85     return NULL;
86   }
87
88   // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
89   if (opts & PacketSocketFactory::OPT_SSLTCP) {
90     ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
91     socket = new rtc::AsyncSSLSocket(socket);
92   }
93
94   // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
95   // See http://go/gtalktcpnodelayexperiment
96   socket->SetOption(rtc::Socket::OPT_NODELAY, 1);
97
98   if (opts & PacketSocketFactory::OPT_STUN)
99     return new cricket::AsyncStunTCPSocket(socket, true);
100
101   return new rtc::AsyncTCPSocket(socket, true);
102 }
103
104 AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
105     const SocketAddress& local_address, const SocketAddress& remote_address,
106     const ProxyInfo& proxy_info, const std::string& user_agent, int opts) {
107
108   rtc::AsyncSocket* socket =
109       socket_factory()->CreateAsyncSocket(local_address.family(), SOCK_STREAM);
110   if (!socket) {
111     return NULL;
112   }
113
114   if (BindSocket(socket, local_address, 0, 0) < 0) {
115     LOG(LS_ERROR) << "TCP bind failed with error "
116                   << socket->GetError();
117     delete socket;
118     return NULL;
119   }
120
121   // If using a proxy, wrap the socket in a proxy socket.
122   if (proxy_info.type == rtc::PROXY_SOCKS5) {
123     socket = new rtc::AsyncSocksProxySocket(
124         socket, proxy_info.address, proxy_info.username, proxy_info.password);
125   } else if (proxy_info.type == rtc::PROXY_HTTPS) {
126     socket = new rtc::AsyncHttpsProxySocket(
127         socket, user_agent, proxy_info.address,
128         proxy_info.username, proxy_info.password);
129   }
130
131   // If using TLS, wrap the socket in an SSL adapter.
132   if (opts & PacketSocketFactory::OPT_TLS) {
133     ASSERT(!(opts & PacketSocketFactory::OPT_SSLTCP));
134
135     rtc::SSLAdapter* ssl_adapter = rtc::SSLAdapter::Create(socket);
136     if (!ssl_adapter) {
137       return NULL;
138     }
139
140     socket = ssl_adapter;
141
142     if (ssl_adapter->StartSSL(remote_address.hostname().c_str(), false) != 0) {
143       delete ssl_adapter;
144       return NULL;
145     }
146
147   // If using SSLTCP, wrap the TCP socket in a pseudo-SSL socket.
148   } else if (opts & PacketSocketFactory::OPT_SSLTCP) {
149     ASSERT(!(opts & PacketSocketFactory::OPT_TLS));
150     socket = new rtc::AsyncSSLSocket(socket);
151   }
152
153   if (socket->Connect(remote_address) < 0) {
154     LOG(LS_ERROR) << "TCP connect failed with error "
155                   << socket->GetError();
156     delete socket;
157     return NULL;
158   }
159
160   // Finally, wrap that socket in a TCP or STUN TCP packet socket.
161   AsyncPacketSocket* tcp_socket;
162   if (opts & PacketSocketFactory::OPT_STUN) {
163     tcp_socket = new cricket::AsyncStunTCPSocket(socket, false);
164   } else {
165     tcp_socket = new rtc::AsyncTCPSocket(socket, false);
166   }
167
168   // Set TCP_NODELAY (via OPT_NODELAY) for improved performance.
169   // See http://go/gtalktcpnodelayexperiment
170   tcp_socket->SetOption(rtc::Socket::OPT_NODELAY, 1);
171
172   return tcp_socket;
173 }
174
175 AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
176   return new rtc::AsyncResolver();
177 }
178
179 int BasicPacketSocketFactory::BindSocket(
180     AsyncSocket* socket, const SocketAddress& local_address,
181     uint16 min_port, uint16 max_port) {
182   int ret = -1;
183   if (min_port == 0 && max_port == 0) {
184     // If there's no port range, let the OS pick a port for us.
185     ret = socket->Bind(local_address);
186   } else {
187     // Otherwise, try to find a port in the provided range.
188     for (int port = min_port; ret < 0 && port <= max_port; ++port) {
189       ret = socket->Bind(rtc::SocketAddress(local_address.ipaddr(),
190                                                   port));
191     }
192   }
193   return ret;
194 }
195
196 SocketFactory* BasicPacketSocketFactory::socket_factory() {
197   if (thread_) {
198     ASSERT(thread_ == Thread::Current());
199     return thread_->socketserver();
200   } else {
201     return socket_factory_;
202   }
203 }
204
205 }  // namespace rtc