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