Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / libjingle / xmpp / xmppsocket.cc
1 /*
2  *  Copyright 2004 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 "xmppsocket.h"
12
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
16
17 #include <errno.h>
18 #include "webrtc/base/basicdefs.h"
19 #include "webrtc/base/logging.h"
20 #include "webrtc/base/thread.h"
21 #ifdef FEATURE_ENABLE_SSL
22 #include "webrtc/base/ssladapter.h"
23 #endif
24
25 #ifdef USE_SSLSTREAM
26 #include "webrtc/base/socketstream.h"
27 #ifdef FEATURE_ENABLE_SSL
28 #include "webrtc/base/sslstreamadapter.h"
29 #endif  // FEATURE_ENABLE_SSL
30 #endif  // USE_SSLSTREAM
31
32 namespace buzz {
33
34 XmppSocket::XmppSocket(buzz::TlsOptions tls) : cricket_socket_(NULL),
35                                                tls_(tls) {
36   state_ = buzz::AsyncSocket::STATE_CLOSED;
37 }
38
39 void XmppSocket::CreateCricketSocket(int family) {
40   rtc::Thread* pth = rtc::Thread::Current();
41   if (family == AF_UNSPEC) {
42     family = AF_INET;
43   }
44   rtc::AsyncSocket* socket =
45       pth->socketserver()->CreateAsyncSocket(family, SOCK_STREAM);
46 #ifndef USE_SSLSTREAM
47 #ifdef FEATURE_ENABLE_SSL
48   if (tls_ != buzz::TLS_DISABLED) {
49     socket = rtc::SSLAdapter::Create(socket);
50   }
51 #endif  // FEATURE_ENABLE_SSL
52   cricket_socket_ = socket;
53   cricket_socket_->SignalReadEvent.connect(this, &XmppSocket::OnReadEvent);
54   cricket_socket_->SignalWriteEvent.connect(this, &XmppSocket::OnWriteEvent);
55   cricket_socket_->SignalConnectEvent.connect(this,
56                                               &XmppSocket::OnConnectEvent);
57   cricket_socket_->SignalCloseEvent.connect(this, &XmppSocket::OnCloseEvent);
58 #else  // USE_SSLSTREAM
59   cricket_socket_ = socket;
60   stream_ = new rtc::SocketStream(cricket_socket_);
61 #ifdef FEATURE_ENABLE_SSL
62   if (tls_ != buzz::TLS_DISABLED)
63     stream_ = rtc::SSLStreamAdapter::Create(stream_);
64 #endif  // FEATURE_ENABLE_SSL
65   stream_->SignalEvent.connect(this, &XmppSocket::OnEvent);
66 #endif  // USE_SSLSTREAM
67 }
68
69 XmppSocket::~XmppSocket() {
70   Close();
71 #ifndef USE_SSLSTREAM
72   delete cricket_socket_;
73 #else  // USE_SSLSTREAM
74   delete stream_;
75 #endif  // USE_SSLSTREAM
76 }
77
78 #ifndef USE_SSLSTREAM
79 void XmppSocket::OnReadEvent(rtc::AsyncSocket * socket) {
80   SignalRead();
81 }
82
83 void XmppSocket::OnWriteEvent(rtc::AsyncSocket * socket) {
84   // Write bytes if there are any
85   while (buffer_.Length() != 0) {
86     int written = cricket_socket_->Send(buffer_.Data(), buffer_.Length());
87     if (written > 0) {
88       buffer_.Consume(written);
89       continue;
90     }
91     if (!cricket_socket_->IsBlocking())
92       LOG(LS_ERROR) << "Send error: " << cricket_socket_->GetError();
93     return;
94   }
95 }
96
97 void XmppSocket::OnConnectEvent(rtc::AsyncSocket * socket) {
98 #if defined(FEATURE_ENABLE_SSL)
99   if (state_ == buzz::AsyncSocket::STATE_TLS_CONNECTING) {
100     state_ = buzz::AsyncSocket::STATE_TLS_OPEN;
101     SignalSSLConnected();
102     OnWriteEvent(cricket_socket_);
103     return;
104   }
105 #endif  // !defined(FEATURE_ENABLE_SSL)
106   state_ = buzz::AsyncSocket::STATE_OPEN;
107   SignalConnected();
108 }
109
110 void XmppSocket::OnCloseEvent(rtc::AsyncSocket * socket, int error) {
111   SignalCloseEvent(error);
112 }
113
114 #else  // USE_SSLSTREAM
115
116 void XmppSocket::OnEvent(rtc::StreamInterface* stream,
117                          int events, int err) {
118   if ((events & rtc::SE_OPEN)) {
119 #if defined(FEATURE_ENABLE_SSL)
120     if (state_ == buzz::AsyncSocket::STATE_TLS_CONNECTING) {
121       state_ = buzz::AsyncSocket::STATE_TLS_OPEN;
122       SignalSSLConnected();
123       events |= rtc::SE_WRITE;
124     } else
125 #endif
126     {
127       state_ = buzz::AsyncSocket::STATE_OPEN;
128       SignalConnected();
129     }
130   }
131   if ((events & rtc::SE_READ))
132     SignalRead();
133   if ((events & rtc::SE_WRITE)) {
134     // Write bytes if there are any
135     while (buffer_.Length() != 0) {
136       rtc::StreamResult result;
137       size_t written;
138       int error;
139       result = stream_->Write(buffer_.Data(), buffer_.Length(),
140                               &written, &error);
141       if (result == rtc::SR_ERROR) {
142         LOG(LS_ERROR) << "Send error: " << error;
143         return;
144       }
145       if (result == rtc::SR_BLOCK)
146         return;
147       ASSERT(result == rtc::SR_SUCCESS);
148       ASSERT(written > 0);
149       buffer_.Shift(written);
150     }
151   }
152   if ((events & rtc::SE_CLOSE))
153     SignalCloseEvent(err);
154 }
155 #endif  // USE_SSLSTREAM
156
157 buzz::AsyncSocket::State XmppSocket::state() {
158   return state_;
159 }
160
161 buzz::AsyncSocket::Error XmppSocket::error() {
162   return buzz::AsyncSocket::ERROR_NONE;
163 }
164
165 int XmppSocket::GetError() {
166   return 0;
167 }
168
169 bool XmppSocket::Connect(const rtc::SocketAddress& addr) {
170   if (cricket_socket_ == NULL) {
171     CreateCricketSocket(addr.family());
172   }
173   if (cricket_socket_->Connect(addr) < 0) {
174     return cricket_socket_->IsBlocking();
175   }
176   return true;
177 }
178
179 bool XmppSocket::Read(char * data, size_t len, size_t* len_read) {
180 #ifndef USE_SSLSTREAM
181   int read = cricket_socket_->Recv(data, len);
182   if (read > 0) {
183     *len_read = (size_t)read;
184     return true;
185   }
186 #else  // USE_SSLSTREAM
187   rtc::StreamResult result = stream_->Read(data, len, len_read, NULL);
188   if (result == rtc::SR_SUCCESS)
189     return true;
190 #endif  // USE_SSLSTREAM
191   return false;
192 }
193
194 bool XmppSocket::Write(const char * data, size_t len) {
195   buffer_.WriteBytes(data, len);
196 #ifndef USE_SSLSTREAM
197   OnWriteEvent(cricket_socket_);
198 #else  // USE_SSLSTREAM
199   OnEvent(stream_, rtc::SE_WRITE, 0);
200 #endif  // USE_SSLSTREAM
201   return true;
202 }
203
204 bool XmppSocket::Close() {
205   if (state_ != buzz::AsyncSocket::STATE_OPEN)
206     return false;
207 #ifndef USE_SSLSTREAM
208   if (cricket_socket_->Close() == 0) {
209     state_ = buzz::AsyncSocket::STATE_CLOSED;
210     SignalClosed();
211     return true;
212   }
213   return false;
214 #else  // USE_SSLSTREAM
215   state_ = buzz::AsyncSocket::STATE_CLOSED;
216   stream_->Close();
217   SignalClosed();
218   return true;
219 #endif  // USE_SSLSTREAM
220 }
221
222 bool XmppSocket::StartTls(const std::string & domainname) {
223 #if defined(FEATURE_ENABLE_SSL)
224   if (tls_ == buzz::TLS_DISABLED)
225     return false;
226 #ifndef USE_SSLSTREAM
227   rtc::SSLAdapter* ssl_adapter =
228     static_cast<rtc::SSLAdapter *>(cricket_socket_);
229   if (ssl_adapter->StartSSL(domainname.c_str(), false) != 0)
230     return false;
231 #else  // USE_SSLSTREAM
232   rtc::SSLStreamAdapter* ssl_stream =
233     static_cast<rtc::SSLStreamAdapter *>(stream_);
234   if (ssl_stream->StartSSLWithServer(domainname.c_str()) != 0)
235     return false;
236 #endif  // USE_SSLSTREAM
237   state_ = buzz::AsyncSocket::STATE_TLS_CONNECTING;
238   return true;
239 #else  // !defined(FEATURE_ENABLE_SSL)
240   return false;
241 #endif  // !defined(FEATURE_ENABLE_SSL)
242 }
243
244 }  // namespace buzz
245