OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/examples/peerconnection/client/peer_connection_client.h" | 11 #include "webrtc/examples/peerconnection/client/peer_connection_client.h" |
12 | 12 |
13 #include "webrtc/examples/peerconnection/client/defaults.h" | 13 #include "webrtc/examples/peerconnection/client/defaults.h" |
| 14 #include "webrtc/base/checks.h" |
14 #include "webrtc/base/common.h" | 15 #include "webrtc/base/common.h" |
15 #include "webrtc/base/logging.h" | 16 #include "webrtc/base/logging.h" |
16 #include "webrtc/base/nethelpers.h" | 17 #include "webrtc/base/nethelpers.h" |
17 #include "webrtc/base/stringutils.h" | 18 #include "webrtc/base/stringutils.h" |
18 | 19 |
19 #ifdef WIN32 | 20 #ifdef WIN32 |
20 #include "webrtc/base/win32socketserver.h" | 21 #include "webrtc/base/win32socketserver.h" |
21 #endif | 22 #endif |
22 | 23 |
23 using rtc::sprintfn; | 24 using rtc::sprintfn; |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 // This is our magical hangup signal. | 28 // This is our magical hangup signal. |
28 const char kByeMessage[] = "BYE"; | 29 const char kByeMessage[] = "BYE"; |
29 // Delay between server connection retries, in milliseconds | 30 // Delay between server connection retries, in milliseconds |
30 const int kReconnectDelay = 2000; | 31 const int kReconnectDelay = 2000; |
31 | 32 |
32 rtc::AsyncSocket* CreateClientSocket(int family) { | 33 rtc::AsyncSocket* CreateClientSocket(int family) { |
33 #ifdef WIN32 | 34 #ifdef WIN32 |
34 rtc::Win32Socket* sock = new rtc::Win32Socket(); | 35 rtc::Win32Socket* sock = new rtc::Win32Socket(); |
35 sock->CreateT(family, SOCK_STREAM); | 36 sock->CreateT(family, SOCK_STREAM); |
36 return sock; | 37 return sock; |
37 #elif defined(WEBRTC_POSIX) | 38 #elif defined(WEBRTC_POSIX) |
38 rtc::Thread* thread = rtc::Thread::Current(); | 39 rtc::Thread* thread = rtc::Thread::Current(); |
39 ASSERT(thread != NULL); | 40 RTC_DCHECK(thread != NULL); |
40 return thread->socketserver()->CreateAsyncSocket(family, SOCK_STREAM); | 41 return thread->socketserver()->CreateAsyncSocket(family, SOCK_STREAM); |
41 #else | 42 #else |
42 #error Platform not supported. | 43 #error Platform not supported. |
43 #endif | 44 #endif |
44 } | 45 } |
45 | 46 |
46 } // namespace | 47 } // namespace |
47 | 48 |
48 PeerConnectionClient::PeerConnectionClient() | 49 PeerConnectionClient::PeerConnectionClient() |
49 : callback_(NULL), | 50 : callback_(NULL), |
50 resolver_(NULL), | 51 resolver_(NULL), |
51 state_(NOT_CONNECTED), | 52 state_(NOT_CONNECTED), |
52 my_id_(-1) { | 53 my_id_(-1) { |
53 } | 54 } |
54 | 55 |
55 PeerConnectionClient::~PeerConnectionClient() { | 56 PeerConnectionClient::~PeerConnectionClient() { |
56 } | 57 } |
57 | 58 |
58 void PeerConnectionClient::InitSocketSignals() { | 59 void PeerConnectionClient::InitSocketSignals() { |
59 ASSERT(control_socket_.get() != NULL); | 60 RTC_DCHECK(control_socket_.get() != NULL); |
60 ASSERT(hanging_get_.get() != NULL); | 61 RTC_DCHECK(hanging_get_.get() != NULL); |
61 control_socket_->SignalCloseEvent.connect(this, | 62 control_socket_->SignalCloseEvent.connect(this, |
62 &PeerConnectionClient::OnClose); | 63 &PeerConnectionClient::OnClose); |
63 hanging_get_->SignalCloseEvent.connect(this, | 64 hanging_get_->SignalCloseEvent.connect(this, |
64 &PeerConnectionClient::OnClose); | 65 &PeerConnectionClient::OnClose); |
65 control_socket_->SignalConnectEvent.connect(this, | 66 control_socket_->SignalConnectEvent.connect(this, |
66 &PeerConnectionClient::OnConnect); | 67 &PeerConnectionClient::OnConnect); |
67 hanging_get_->SignalConnectEvent.connect(this, | 68 hanging_get_->SignalConnectEvent.connect(this, |
68 &PeerConnectionClient::OnHangingGetConnect); | 69 &PeerConnectionClient::OnHangingGetConnect); |
69 control_socket_->SignalReadEvent.connect(this, | 70 control_socket_->SignalReadEvent.connect(this, |
70 &PeerConnectionClient::OnRead); | 71 &PeerConnectionClient::OnRead); |
71 hanging_get_->SignalReadEvent.connect(this, | 72 hanging_get_->SignalReadEvent.connect(this, |
72 &PeerConnectionClient::OnHangingGetRead); | 73 &PeerConnectionClient::OnHangingGetRead); |
73 } | 74 } |
74 | 75 |
75 int PeerConnectionClient::id() const { | 76 int PeerConnectionClient::id() const { |
76 return my_id_; | 77 return my_id_; |
77 } | 78 } |
78 | 79 |
79 bool PeerConnectionClient::is_connected() const { | 80 bool PeerConnectionClient::is_connected() const { |
80 return my_id_ != -1; | 81 return my_id_ != -1; |
81 } | 82 } |
82 | 83 |
83 const Peers& PeerConnectionClient::peers() const { | 84 const Peers& PeerConnectionClient::peers() const { |
84 return peers_; | 85 return peers_; |
85 } | 86 } |
86 | 87 |
87 void PeerConnectionClient::RegisterObserver( | 88 void PeerConnectionClient::RegisterObserver( |
88 PeerConnectionClientObserver* callback) { | 89 PeerConnectionClientObserver* callback) { |
89 ASSERT(!callback_); | 90 RTC_DCHECK(!callback_); |
90 callback_ = callback; | 91 callback_ = callback; |
91 } | 92 } |
92 | 93 |
93 void PeerConnectionClient::Connect(const std::string& server, int port, | 94 void PeerConnectionClient::Connect(const std::string& server, int port, |
94 const std::string& client_name) { | 95 const std::string& client_name) { |
95 ASSERT(!server.empty()); | 96 RTC_DCHECK(!server.empty()); |
96 ASSERT(!client_name.empty()); | 97 RTC_DCHECK(!client_name.empty()); |
97 | 98 |
98 if (state_ != NOT_CONNECTED) { | 99 if (state_ != NOT_CONNECTED) { |
99 LOG(WARNING) | 100 LOG(WARNING) |
100 << "The client must not be connected before you can call Connect()"; | 101 << "The client must not be connected before you can call Connect()"; |
101 callback_->OnServerConnectionFailure(); | 102 callback_->OnServerConnectionFailure(); |
102 return; | 103 return; |
103 } | 104 } |
104 | 105 |
105 if (server.empty() || client_name.empty()) { | 106 if (server.empty() || client_name.empty()) { |
106 callback_->OnServerConnectionFailure(); | 107 callback_->OnServerConnectionFailure(); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 state_ = SIGNING_IN; | 152 state_ = SIGNING_IN; |
152 if (!ret) { | 153 if (!ret) { |
153 callback_->OnServerConnectionFailure(); | 154 callback_->OnServerConnectionFailure(); |
154 } | 155 } |
155 } | 156 } |
156 | 157 |
157 bool PeerConnectionClient::SendToPeer(int peer_id, const std::string& message) { | 158 bool PeerConnectionClient::SendToPeer(int peer_id, const std::string& message) { |
158 if (state_ != CONNECTED) | 159 if (state_ != CONNECTED) |
159 return false; | 160 return false; |
160 | 161 |
161 ASSERT(is_connected()); | 162 RTC_DCHECK(is_connected()); |
162 ASSERT(control_socket_->GetState() == rtc::Socket::CS_CLOSED); | 163 RTC_DCHECK(control_socket_->GetState() == rtc::Socket::CS_CLOSED); |
163 if (!is_connected() || peer_id == -1) | 164 if (!is_connected() || peer_id == -1) |
164 return false; | 165 return false; |
165 | 166 |
166 char headers[1024]; | 167 char headers[1024]; |
167 sprintfn(headers, sizeof(headers), | 168 sprintfn(headers, sizeof(headers), |
168 "POST /message?peer_id=%i&to=%i HTTP/1.0\r\n" | 169 "POST /message?peer_id=%i&to=%i HTTP/1.0\r\n" |
169 "Content-Length: %i\r\n" | 170 "Content-Length: %i\r\n" |
170 "Content-Type: text/plain\r\n" | 171 "Content-Type: text/plain\r\n" |
171 "\r\n", | 172 "\r\n", |
172 my_id_, peer_id, message.length()); | 173 my_id_, peer_id, message.length()); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 peers_.clear(); | 219 peers_.clear(); |
219 if (resolver_ != NULL) { | 220 if (resolver_ != NULL) { |
220 resolver_->Destroy(false); | 221 resolver_->Destroy(false); |
221 resolver_ = NULL; | 222 resolver_ = NULL; |
222 } | 223 } |
223 my_id_ = -1; | 224 my_id_ = -1; |
224 state_ = NOT_CONNECTED; | 225 state_ = NOT_CONNECTED; |
225 } | 226 } |
226 | 227 |
227 bool PeerConnectionClient::ConnectControlSocket() { | 228 bool PeerConnectionClient::ConnectControlSocket() { |
228 ASSERT(control_socket_->GetState() == rtc::Socket::CS_CLOSED); | 229 RTC_DCHECK(control_socket_->GetState() == rtc::Socket::CS_CLOSED); |
229 int err = control_socket_->Connect(server_address_); | 230 int err = control_socket_->Connect(server_address_); |
230 if (err == SOCKET_ERROR) { | 231 if (err == SOCKET_ERROR) { |
231 Close(); | 232 Close(); |
232 return false; | 233 return false; |
233 } | 234 } |
234 return true; | 235 return true; |
235 } | 236 } |
236 | 237 |
237 void PeerConnectionClient::OnConnect(rtc::AsyncSocket* socket) { | 238 void PeerConnectionClient::OnConnect(rtc::AsyncSocket* socket) { |
238 ASSERT(!onconnect_data_.empty()); | 239 RTC_DCHECK(!onconnect_data_.empty()); |
239 size_t sent = socket->Send(onconnect_data_.c_str(), onconnect_data_.length()); | 240 size_t sent = socket->Send(onconnect_data_.c_str(), onconnect_data_.length()); |
240 ASSERT(sent == onconnect_data_.length()); | 241 RTC_DCHECK(sent == onconnect_data_.length()); |
241 RTC_UNUSED(sent); | 242 RTC_UNUSED(sent); |
242 onconnect_data_.clear(); | 243 onconnect_data_.clear(); |
243 } | 244 } |
244 | 245 |
245 void PeerConnectionClient::OnHangingGetConnect(rtc::AsyncSocket* socket) { | 246 void PeerConnectionClient::OnHangingGetConnect(rtc::AsyncSocket* socket) { |
246 char buffer[1024]; | 247 char buffer[1024]; |
247 sprintfn(buffer, sizeof(buffer), | 248 sprintfn(buffer, sizeof(buffer), |
248 "GET /wait?peer_id=%i HTTP/1.0\r\n\r\n", my_id_); | 249 "GET /wait?peer_id=%i HTTP/1.0\r\n\r\n", my_id_); |
249 int len = static_cast<int>(strlen(buffer)); | 250 int len = static_cast<int>(strlen(buffer)); |
250 int sent = socket->Send(buffer, len); | 251 int sent = socket->Send(buffer, len); |
251 ASSERT(sent == len); | 252 RTC_DCHECK(sent == len); |
252 RTC_UNUSED2(sent, len); | 253 RTC_UNUSED2(sent, len); |
253 } | 254 } |
254 | 255 |
255 void PeerConnectionClient::OnMessageFromPeer(int peer_id, | 256 void PeerConnectionClient::OnMessageFromPeer(int peer_id, |
256 const std::string& message) { | 257 const std::string& message) { |
257 if (message.length() == (sizeof(kByeMessage) - 1) && | 258 if (message.length() == (sizeof(kByeMessage) - 1) && |
258 message.compare(kByeMessage) == 0) { | 259 message.compare(kByeMessage) == 0) { |
259 callback_->OnPeerDisconnected(peer_id); | 260 callback_->OnPeerDisconnected(peer_id); |
260 } else { | 261 } else { |
261 callback_->OnMessageFromPeer(peer_id, message); | 262 callback_->OnMessageFromPeer(peer_id, message); |
262 } | 263 } |
263 } | 264 } |
264 | 265 |
265 bool PeerConnectionClient::GetHeaderValue(const std::string& data, | 266 bool PeerConnectionClient::GetHeaderValue(const std::string& data, |
266 size_t eoh, | 267 size_t eoh, |
267 const char* header_pattern, | 268 const char* header_pattern, |
268 size_t* value) { | 269 size_t* value) { |
269 ASSERT(value != NULL); | 270 RTC_DCHECK(value != NULL); |
270 size_t found = data.find(header_pattern); | 271 size_t found = data.find(header_pattern); |
271 if (found != std::string::npos && found < eoh) { | 272 if (found != std::string::npos && found < eoh) { |
272 *value = atoi(&data[found + strlen(header_pattern)]); | 273 *value = atoi(&data[found + strlen(header_pattern)]); |
273 return true; | 274 return true; |
274 } | 275 } |
275 return false; | 276 return false; |
276 } | 277 } |
277 | 278 |
278 bool PeerConnectionClient::GetHeaderValue(const std::string& data, size_t eoh, | 279 bool PeerConnectionClient::GetHeaderValue(const std::string& data, size_t eoh, |
279 const char* header_pattern, | 280 const char* header_pattern, |
280 std::string* value) { | 281 std::string* value) { |
281 ASSERT(value != NULL); | 282 RTC_DCHECK(value != NULL); |
282 size_t found = data.find(header_pattern); | 283 size_t found = data.find(header_pattern); |
283 if (found != std::string::npos && found < eoh) { | 284 if (found != std::string::npos && found < eoh) { |
284 size_t begin = found + strlen(header_pattern); | 285 size_t begin = found + strlen(header_pattern); |
285 size_t end = data.find("\r\n", begin); | 286 size_t end = data.find("\r\n", begin); |
286 if (end == std::string::npos) | 287 if (end == std::string::npos) |
287 end = eoh; | 288 end = eoh; |
288 value->assign(data.substr(begin, end - begin)); | 289 value->assign(data.substr(begin, end - begin)); |
289 return true; | 290 return true; |
290 } | 291 } |
291 return false; | 292 return false; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 | 332 |
332 void PeerConnectionClient::OnRead(rtc::AsyncSocket* socket) { | 333 void PeerConnectionClient::OnRead(rtc::AsyncSocket* socket) { |
333 size_t content_length = 0; | 334 size_t content_length = 0; |
334 if (ReadIntoBuffer(socket, &control_data_, &content_length)) { | 335 if (ReadIntoBuffer(socket, &control_data_, &content_length)) { |
335 size_t peer_id = 0, eoh = 0; | 336 size_t peer_id = 0, eoh = 0; |
336 bool ok = ParseServerResponse(control_data_, content_length, &peer_id, | 337 bool ok = ParseServerResponse(control_data_, content_length, &peer_id, |
337 &eoh); | 338 &eoh); |
338 if (ok) { | 339 if (ok) { |
339 if (my_id_ == -1) { | 340 if (my_id_ == -1) { |
340 // First response. Let's store our server assigned ID. | 341 // First response. Let's store our server assigned ID. |
341 ASSERT(state_ == SIGNING_IN); | 342 RTC_DCHECK(state_ == SIGNING_IN); |
342 my_id_ = static_cast<int>(peer_id); | 343 my_id_ = static_cast<int>(peer_id); |
343 ASSERT(my_id_ != -1); | 344 RTC_DCHECK(my_id_ != -1); |
344 | 345 |
345 // The body of the response will be a list of already connected peers. | 346 // The body of the response will be a list of already connected peers. |
346 if (content_length) { | 347 if (content_length) { |
347 size_t pos = eoh + 4; | 348 size_t pos = eoh + 4; |
348 while (pos < control_data_.size()) { | 349 while (pos < control_data_.size()) { |
349 size_t eol = control_data_.find('\n', pos); | 350 size_t eol = control_data_.find('\n', pos); |
350 if (eol == std::string::npos) | 351 if (eol == std::string::npos) |
351 break; | 352 break; |
352 int id = 0; | 353 int id = 0; |
353 std::string name; | 354 std::string name; |
354 bool connected; | 355 bool connected; |
355 if (ParseEntry(control_data_.substr(pos, eol - pos), &name, &id, | 356 if (ParseEntry(control_data_.substr(pos, eol - pos), &name, &id, |
356 &connected) && id != my_id_) { | 357 &connected) && id != my_id_) { |
357 peers_[id] = name; | 358 peers_[id] = name; |
358 callback_->OnPeerConnected(id, name); | 359 callback_->OnPeerConnected(id, name); |
359 } | 360 } |
360 pos = eol + 1; | 361 pos = eol + 1; |
361 } | 362 } |
362 } | 363 } |
363 ASSERT(is_connected()); | 364 RTC_DCHECK(is_connected()); |
364 callback_->OnSignedIn(); | 365 callback_->OnSignedIn(); |
365 } else if (state_ == SIGNING_OUT) { | 366 } else if (state_ == SIGNING_OUT) { |
366 Close(); | 367 Close(); |
367 callback_->OnDisconnected(); | 368 callback_->OnDisconnected(); |
368 } else if (state_ == SIGNING_OUT_WAITING) { | 369 } else if (state_ == SIGNING_OUT_WAITING) { |
369 SignOut(); | 370 SignOut(); |
370 } | 371 } |
371 } | 372 } |
372 | 373 |
373 control_data_.clear(); | 374 control_data_.clear(); |
374 | 375 |
375 if (state_ == SIGNING_IN) { | 376 if (state_ == SIGNING_IN) { |
376 ASSERT(hanging_get_->GetState() == rtc::Socket::CS_CLOSED); | 377 RTC_DCHECK(hanging_get_->GetState() == rtc::Socket::CS_CLOSED); |
377 state_ = CONNECTED; | 378 state_ = CONNECTED; |
378 hanging_get_->Connect(server_address_); | 379 hanging_get_->Connect(server_address_); |
379 } | 380 } |
380 } | 381 } |
381 } | 382 } |
382 | 383 |
383 void PeerConnectionClient::OnHangingGetRead(rtc::AsyncSocket* socket) { | 384 void PeerConnectionClient::OnHangingGetRead(rtc::AsyncSocket* socket) { |
384 LOG(INFO) << __FUNCTION__; | 385 LOG(INFO) << __FUNCTION__; |
385 size_t content_length = 0; | 386 size_t content_length = 0; |
386 if (ReadIntoBuffer(socket, ¬ification_data_, &content_length)) { | 387 if (ReadIntoBuffer(socket, ¬ification_data_, &content_length)) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 if (hanging_get_->GetState() == rtc::Socket::CS_CLOSED && | 421 if (hanging_get_->GetState() == rtc::Socket::CS_CLOSED && |
421 state_ == CONNECTED) { | 422 state_ == CONNECTED) { |
422 hanging_get_->Connect(server_address_); | 423 hanging_get_->Connect(server_address_); |
423 } | 424 } |
424 } | 425 } |
425 | 426 |
426 bool PeerConnectionClient::ParseEntry(const std::string& entry, | 427 bool PeerConnectionClient::ParseEntry(const std::string& entry, |
427 std::string* name, | 428 std::string* name, |
428 int* id, | 429 int* id, |
429 bool* connected) { | 430 bool* connected) { |
430 ASSERT(name != NULL); | 431 RTC_DCHECK(name != NULL); |
431 ASSERT(id != NULL); | 432 RTC_DCHECK(id != NULL); |
432 ASSERT(connected != NULL); | 433 RTC_DCHECK(connected != NULL); |
433 ASSERT(!entry.empty()); | 434 RTC_DCHECK(!entry.empty()); |
434 | 435 |
435 *connected = false; | 436 *connected = false; |
436 size_t separator = entry.find(','); | 437 size_t separator = entry.find(','); |
437 if (separator != std::string::npos) { | 438 if (separator != std::string::npos) { |
438 *id = atoi(&entry[separator + 1]); | 439 *id = atoi(&entry[separator + 1]); |
439 name->assign(entry.substr(0, separator)); | 440 name->assign(entry.substr(0, separator)); |
440 separator = entry.find(',', separator + 1); | 441 separator = entry.find(',', separator + 1); |
441 if (separator != std::string::npos) { | 442 if (separator != std::string::npos) { |
442 *connected = atoi(&entry[separator + 1]) ? true : false; | 443 *connected = atoi(&entry[separator + 1]) ? true : false; |
443 } | 444 } |
(...skipping 15 matching lines...) Expand all Loading... |
459 size_t* eoh) { | 460 size_t* eoh) { |
460 int status = GetResponseStatus(response.c_str()); | 461 int status = GetResponseStatus(response.c_str()); |
461 if (status != 200) { | 462 if (status != 200) { |
462 LOG(LS_ERROR) << "Received error from server"; | 463 LOG(LS_ERROR) << "Received error from server"; |
463 Close(); | 464 Close(); |
464 callback_->OnDisconnected(); | 465 callback_->OnDisconnected(); |
465 return false; | 466 return false; |
466 } | 467 } |
467 | 468 |
468 *eoh = response.find("\r\n\r\n"); | 469 *eoh = response.find("\r\n\r\n"); |
469 ASSERT(*eoh != std::string::npos); | 470 RTC_DCHECK(*eoh != std::string::npos); |
470 if (*eoh == std::string::npos) | 471 if (*eoh == std::string::npos) |
471 return false; | 472 return false; |
472 | 473 |
473 *peer_id = -1; | 474 *peer_id = -1; |
474 | 475 |
475 // See comment in peer_channel.cc for why we use the Pragma header and | 476 // See comment in peer_channel.cc for why we use the Pragma header and |
476 // not e.g. "X-Peer-Id". | 477 // not e.g. "X-Peer-Id". |
477 GetHeaderValue(response, *eoh, "\r\nPragma: ", peer_id); | 478 GetHeaderValue(response, *eoh, "\r\nPragma: ", peer_id); |
478 | 479 |
479 return true; | 480 return true; |
(...skipping 26 matching lines...) Expand all Loading... |
506 Close(); | 507 Close(); |
507 callback_->OnDisconnected(); | 508 callback_->OnDisconnected(); |
508 } | 509 } |
509 } | 510 } |
510 } | 511 } |
511 | 512 |
512 void PeerConnectionClient::OnMessage(rtc::Message* msg) { | 513 void PeerConnectionClient::OnMessage(rtc::Message* msg) { |
513 // ignore msg; there is currently only one supported message ("retry") | 514 // ignore msg; there is currently only one supported message ("retry") |
514 DoConnect(); | 515 DoConnect(); |
515 } | 516 } |
OLD | NEW |