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 "webrtc/base/win32.h" 12 #define SECURITY_WIN32 13 #include <security.h> 14 #include <schannel.h> 15 16 #include <iomanip> 17 #include <vector> 18 19 #include "webrtc/base/common.h" 20 #include "webrtc/base/logging.h" 21 #include "webrtc/base/schanneladapter.h" 22 #include "webrtc/base/sec_buffer.h" 23 #include "webrtc/base/thread.h" 24 25 namespace rtc { 26 27 ///////////////////////////////////////////////////////////////////////////// 28 // SChannelAdapter 29 ///////////////////////////////////////////////////////////////////////////// 30 31 extern const ConstantLabel SECURITY_ERRORS[]; 32 33 const ConstantLabel SCHANNEL_BUFFER_TYPES[] = { 34 KLABEL(SECBUFFER_EMPTY), // 0 35 KLABEL(SECBUFFER_DATA), // 1 36 KLABEL(SECBUFFER_TOKEN), // 2 37 KLABEL(SECBUFFER_PKG_PARAMS), // 3 38 KLABEL(SECBUFFER_MISSING), // 4 39 KLABEL(SECBUFFER_EXTRA), // 5 40 KLABEL(SECBUFFER_STREAM_TRAILER), // 6 41 KLABEL(SECBUFFER_STREAM_HEADER), // 7 42 KLABEL(SECBUFFER_MECHLIST), // 11 43 KLABEL(SECBUFFER_MECHLIST_SIGNATURE), // 12 44 KLABEL(SECBUFFER_TARGET), // 13 45 KLABEL(SECBUFFER_CHANNEL_BINDINGS), // 14 46 LASTLABEL 47 }; 48 49 void DescribeBuffer(LoggingSeverity severity, const char* prefix, 50 const SecBuffer& sb) { 51 LOG_V(severity) 52 << prefix 53 << "(" << sb.cbBuffer 54 << ", " << FindLabel(sb.BufferType & ~SECBUFFER_ATTRMASK, 55 SCHANNEL_BUFFER_TYPES) 56 << ", " << sb.pvBuffer << ")"; 57 } 58 59 void DescribeBuffers(LoggingSeverity severity, const char* prefix, 60 const SecBufferDesc* sbd) { 61 if (!LOG_CHECK_LEVEL_V(severity)) 62 return; 63 LOG_V(severity) << prefix << "("; 64 for (size_t i=0; i<sbd->cBuffers; ++i) { 65 DescribeBuffer(severity, " ", sbd->pBuffers[i]); 66 } 67 LOG_V(severity) << ")"; 68 } 69 70 const ULONG SSL_FLAGS_DEFAULT = ISC_REQ_ALLOCATE_MEMORY 71 | ISC_REQ_CONFIDENTIALITY 72 | ISC_REQ_EXTENDED_ERROR 73 | ISC_REQ_INTEGRITY 74 | ISC_REQ_REPLAY_DETECT 75 | ISC_REQ_SEQUENCE_DETECT 76 | ISC_REQ_STREAM; 77 //| ISC_REQ_USE_SUPPLIED_CREDS; 78 79 typedef std::vector<char> SChannelBuffer; 80 81 struct SChannelAdapter::SSLImpl { 82 CredHandle cred; 83 CtxtHandle ctx; 84 bool cred_init, ctx_init; 85 SChannelBuffer inbuf, outbuf, readable; 86 SecPkgContext_StreamSizes sizes; 87 88 SSLImpl() : cred_init(false), ctx_init(false) { } 89 }; 90 91 SChannelAdapter::SChannelAdapter(AsyncSocket* socket) 92 : SSLAdapter(socket), state_(SSL_NONE), 93 restartable_(false), signal_close_(false), message_pending_(false), 94 impl_(new SSLImpl) { 95 } 96 97 SChannelAdapter::~SChannelAdapter() { 98 Cleanup(); 99 } 100 101 int 102 SChannelAdapter::StartSSL(const char* hostname, bool restartable) { 103 if (state_ != SSL_NONE) 104 return ERROR_ALREADY_INITIALIZED; 105 106 ssl_host_name_ = hostname; 107 restartable_ = restartable; 108 109 if (socket_->GetState() != Socket::CS_CONNECTED) { 110 state_ = SSL_WAIT; 111 return 0; 112 } 113 114 state_ = SSL_CONNECTING; 115 if (int err = BeginSSL()) { 116 Error("BeginSSL", err, false); 117 return err; 118 } 119 120 return 0; 121 } 122 123 int 124 SChannelAdapter::BeginSSL() { 125 LOG(LS_VERBOSE) << "BeginSSL: " << ssl_host_name_; 126 ASSERT(state_ == SSL_CONNECTING); 127 128 SECURITY_STATUS ret; 129 130 SCHANNEL_CRED sc_cred = { 0 }; 131 sc_cred.dwVersion = SCHANNEL_CRED_VERSION; 132 //sc_cred.dwMinimumCipherStrength = 128; // Note: use system default 133 sc_cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_AUTO_CRED_VALIDATION; 134 135 ret = AcquireCredentialsHandle(NULL, UNISP_NAME, SECPKG_CRED_OUTBOUND, NULL, 136 &sc_cred, NULL, NULL, &impl_->cred, NULL); 137 if (ret != SEC_E_OK) { 138 LOG(LS_ERROR) << "AcquireCredentialsHandle error: " 139 << ErrorName(ret, SECURITY_ERRORS); 140 return ret; 141 } 142 impl_->cred_init = true; 143 144 if (LOG_CHECK_LEVEL(LS_VERBOSE)) { 145 SecPkgCred_CipherStrengths cipher_strengths = { 0 }; 146 ret = QueryCredentialsAttributes(&impl_->cred, 147 SECPKG_ATTR_CIPHER_STRENGTHS, 148 &cipher_strengths); 149 if (SUCCEEDED(ret)) { 150 LOG(LS_VERBOSE) << "SChannel cipher strength: " 151 << cipher_strengths.dwMinimumCipherStrength << " - " 152 << cipher_strengths.dwMaximumCipherStrength; 153 } 154 155 SecPkgCred_SupportedAlgs supported_algs = { 0 }; 156 ret = QueryCredentialsAttributes(&impl_->cred, 157 SECPKG_ATTR_SUPPORTED_ALGS, 158 &supported_algs); 159 if (SUCCEEDED(ret)) { 160 LOG(LS_VERBOSE) << "SChannel supported algorithms:"; 161 for (DWORD i=0; i<supported_algs.cSupportedAlgs; ++i) { 162 ALG_ID alg_id = supported_algs.palgSupportedAlgs[i]; 163 PCCRYPT_OID_INFO oinfo = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, 164 &alg_id, 0); 165 LPCWSTR alg_name = (NULL != oinfo) ? oinfo->pwszName : L"Unknown"; 166 LOG(LS_VERBOSE) << " " << ToUtf8(alg_name) << " (" << alg_id << ")"; 167 } 168 CSecBufferBase::FreeSSPI(supported_algs.palgSupportedAlgs); 169 } 170 } 171 172 ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0; 173 if (ignore_bad_cert()) 174 flags |= ISC_REQ_MANUAL_CRED_VALIDATION; 175 176 CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out; 177 ret = InitializeSecurityContextA(&impl_->cred, NULL, 178 const_cast<char*>(ssl_host_name_.c_str()), 179 flags, 0, 0, NULL, 0, 180 &impl_->ctx, sb_out.desc(), 181 &ret_flags, NULL); 182 if (SUCCEEDED(ret)) 183 impl_->ctx_init = true; 184 return ProcessContext(ret, NULL, sb_out.desc()); 185 } 186 187 int 188 SChannelAdapter::ContinueSSL() { 189 LOG(LS_VERBOSE) << "ContinueSSL"; 190 ASSERT(state_ == SSL_CONNECTING); 191 192 SECURITY_STATUS ret; 193 194 CSecBufferBundle<2> sb_in; 195 sb_in[0].BufferType = SECBUFFER_TOKEN; 196 sb_in[0].cbBuffer = static_cast<unsigned long>(impl_->inbuf.size()); 197 sb_in[0].pvBuffer = &impl_->inbuf[0]; 198 //DescribeBuffers(LS_VERBOSE, "Input Buffer ", sb_in.desc()); 199 200 ULONG flags = SSL_FLAGS_DEFAULT, ret_flags = 0; 201 if (ignore_bad_cert()) 202 flags |= ISC_REQ_MANUAL_CRED_VALIDATION; 203 204 CSecBufferBundle<2, CSecBufferBase::FreeSSPI> sb_out; 205 ret = InitializeSecurityContextA(&impl_->cred, &impl_->ctx, 206 const_cast<char*>(ssl_host_name_.c_str()), 207 flags, 0, 0, sb_in.desc(), 0, 208 NULL, sb_out.desc(), 209 &ret_flags, NULL); 210 return ProcessContext(ret, sb_in.desc(), sb_out.desc()); 211 } 212 213 int 214 SChannelAdapter::ProcessContext(long int status, _SecBufferDesc* sbd_in, 215 _SecBufferDesc* sbd_out) { 216 if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED && 217 status != SEC_E_INCOMPLETE_MESSAGE) { 218 LOG(LS_ERROR) 219 << "InitializeSecurityContext error: " 220 << ErrorName(status, SECURITY_ERRORS); 221 } 222 //if (sbd_in) 223 // DescribeBuffers(LS_VERBOSE, "Input Buffer ", sbd_in); 224 //if (sbd_out) 225 // DescribeBuffers(LS_VERBOSE, "Output Buffer ", sbd_out); 226 227 if (status == SEC_E_INCOMPLETE_MESSAGE) { 228 // Wait for more input from server. 229 return Flush(); 230 } 231 232 if (FAILED(status)) { 233 // We can't continue. Common errors: 234 // SEC_E_CERT_EXPIRED - Typically, this means the computer clock is wrong. 235 return status; 236 } 237 238 // Note: we check both input and output buffers for SECBUFFER_EXTRA. 239 // Experience shows it appearing in the input, but the documentation claims 240 // it should appear in the output. 241 size_t extra = 0; 242 if (sbd_in) { 243 for (size_t i=0; i<sbd_in->cBuffers; ++i) { 244 SecBuffer& buffer = sbd_in->pBuffers[i]; 245 if (buffer.BufferType == SECBUFFER_EXTRA) { 246 extra += buffer.cbBuffer; 247 } 248 } 249 } 250 if (sbd_out) { 251 for (size_t i=0; i<sbd_out->cBuffers; ++i) { 252 SecBuffer& buffer = sbd_out->pBuffers[i]; 253 if (buffer.BufferType == SECBUFFER_EXTRA) { 254 extra += buffer.cbBuffer; 255 } else if (buffer.BufferType == SECBUFFER_TOKEN) { 256 impl_->outbuf.insert(impl_->outbuf.end(), 257 reinterpret_cast<char*>(buffer.pvBuffer), 258 reinterpret_cast<char*>(buffer.pvBuffer) + buffer.cbBuffer); 259 } 260 } 261 } 262 263 if (extra) { 264 ASSERT(extra <= impl_->inbuf.size()); 265 size_t consumed = impl_->inbuf.size() - extra; 266 memmove(&impl_->inbuf[0], &impl_->inbuf[consumed], extra); 267 impl_->inbuf.resize(extra); 268 } else { 269 impl_->inbuf.clear(); 270 } 271 272 if (SEC_I_CONTINUE_NEEDED == status) { 273 // Send data to server and wait for response. 274 // Note: ContinueSSL will result in a Flush, anyway. 275 return impl_->inbuf.empty() ? Flush() : ContinueSSL(); 276 } 277 278 if (SEC_E_OK == status) { 279 LOG(LS_VERBOSE) << "QueryContextAttributes"; 280 status = QueryContextAttributes(&impl_->ctx, SECPKG_ATTR_STREAM_SIZES, 281 &impl_->sizes); 282 if (FAILED(status)) { 283 LOG(LS_ERROR) << "QueryContextAttributes error: " 284 << ErrorName(status, SECURITY_ERRORS); 285 return status; 286 } 287 288 state_ = SSL_CONNECTED; 289 290 if (int err = DecryptData()) { 291 return err; 292 } else if (int err = Flush()) { 293 return err; 294 } else { 295 // If we decrypted any data, queue up a notification here 296 PostEvent(); 297 // Signal our connectedness 298 AsyncSocketAdapter::OnConnectEvent(this); 299 } 300 return 0; 301 } 302 303 if (SEC_I_INCOMPLETE_CREDENTIALS == status) { 304 // We don't support client authentication in schannel. 305 return status; 306 } 307 308 // We don't expect any other codes 309 ASSERT(false); 310 return status; 311 } 312 313 int 314 SChannelAdapter::DecryptData() { 315 SChannelBuffer& inbuf = impl_->inbuf; 316 SChannelBuffer& readable = impl_->readable; 317 318 while (!inbuf.empty()) { 319 CSecBufferBundle<4> in_buf; 320 in_buf[0].BufferType = SECBUFFER_DATA; 321 in_buf[0].cbBuffer = static_cast<unsigned long>(inbuf.size()); 322 in_buf[0].pvBuffer = &inbuf[0]; 323 324 //DescribeBuffers(LS_VERBOSE, "Decrypt In ", in_buf.desc()); 325 SECURITY_STATUS status = DecryptMessage(&impl_->ctx, in_buf.desc(), 0, 0); 326 //DescribeBuffers(LS_VERBOSE, "Decrypt Out ", in_buf.desc()); 327 328 // Note: We are explicitly treating SEC_E_OK, SEC_I_CONTEXT_EXPIRED, and 329 // any other successful results as continue. 330 if (SUCCEEDED(status)) { 331 size_t data_len = 0, extra_len = 0; 332 for (size_t i=0; i<in_buf.desc()->cBuffers; ++i) { 333 if (in_buf[i].BufferType == SECBUFFER_DATA) { 334 data_len += in_buf[i].cbBuffer; 335 readable.insert(readable.end(), 336 reinterpret_cast<char*>(in_buf[i].pvBuffer), 337 reinterpret_cast<char*>(in_buf[i].pvBuffer) + in_buf[i].cbBuffer); 338 } else if (in_buf[i].BufferType == SECBUFFER_EXTRA) { 339 extra_len += in_buf[i].cbBuffer; 340 } 341 } 342 // There is a bug on Win2K where SEC_I_CONTEXT_EXPIRED is misclassified. 343 if ((data_len == 0) && (inbuf[0] == 0x15)) { 344 status = SEC_I_CONTEXT_EXPIRED; 345 } 346 if (extra_len) { 347 size_t consumed = inbuf.size() - extra_len; 348 memmove(&inbuf[0], &inbuf[consumed], extra_len); 349 inbuf.resize(extra_len); 350 } else { 351 inbuf.clear(); 352 } 353 // TODO: Handle SEC_I_CONTEXT_EXPIRED to do clean shutdown 354 if (status != SEC_E_OK) { 355 LOG(LS_INFO) << "DecryptMessage returned continuation code: " 356 << ErrorName(status, SECURITY_ERRORS); 357 } 358 continue; 359 } 360 361 if (status == SEC_E_INCOMPLETE_MESSAGE) { 362 break; 363 } else { 364 return status; 365 } 366 } 367 368 return 0; 369 } 370 371 void 372 SChannelAdapter::Cleanup() { 373 if (impl_->ctx_init) 374 DeleteSecurityContext(&impl_->ctx); 375 if (impl_->cred_init) 376 FreeCredentialsHandle(&impl_->cred); 377 delete impl_; 378 } 379 380 void 381 SChannelAdapter::PostEvent() { 382 // Check if there's anything notable to signal 383 if (impl_->readable.empty() && !signal_close_) 384 return; 385 386 // Only one post in the queue at a time 387 if (message_pending_) 388 return; 389 390 if (Thread* thread = Thread::Current()) { 391 message_pending_ = true; 392 thread->Post(this); 393 } else { 394 LOG(LS_ERROR) << "No thread context available for SChannelAdapter"; 395 ASSERT(false); 396 } 397 } 398 399 void 400 SChannelAdapter::Error(const char* context, int err, bool signal) { 401 LOG(LS_WARNING) << "SChannelAdapter::Error(" 402 << context << ", " 403 << ErrorName(err, SECURITY_ERRORS) << ")"; 404 state_ = SSL_ERROR; 405 SetError(err); 406 if (signal) 407 AsyncSocketAdapter::OnCloseEvent(this, err); 408 } 409 410 int 411 SChannelAdapter::Read() { 412 char buffer[4096]; 413 SChannelBuffer& inbuf = impl_->inbuf; 414 while (true) { 415 int ret = AsyncSocketAdapter::Recv(buffer, sizeof(buffer)); 416 if (ret > 0) { 417 inbuf.insert(inbuf.end(), buffer, buffer + ret); 418 } else if (GetError() == EWOULDBLOCK) { 419 return 0; // Blocking 420 } else { 421 return GetError(); 422 } 423 } 424 } 425 426 int 427 SChannelAdapter::Flush() { 428 int result = 0; 429 size_t pos = 0; 430 SChannelBuffer& outbuf = impl_->outbuf; 431 while (pos < outbuf.size()) { 432 int sent = AsyncSocketAdapter::Send(&outbuf[pos], outbuf.size() - pos); 433 if (sent > 0) { 434 pos += sent; 435 } else if (GetError() == EWOULDBLOCK) { 436 break; // Blocking 437 } else { 438 result = GetError(); 439 break; 440 } 441 } 442 if (int remainder = static_cast<int>(outbuf.size() - pos)) { 443 memmove(&outbuf[0], &outbuf[pos], remainder); 444 outbuf.resize(remainder); 445 } else { 446 outbuf.clear(); 447 } 448 return result; 449 } 450 451 // 452 // AsyncSocket Implementation 453 // 454 455 int 456 SChannelAdapter::Send(const void* pv, size_t cb) { 457 switch (state_) { 458 case SSL_NONE: 459 return AsyncSocketAdapter::Send(pv, cb); 460 461 case SSL_WAIT: 462 case SSL_CONNECTING: 463 SetError(EWOULDBLOCK); 464 return SOCKET_ERROR; 465 466 case SSL_CONNECTED: 467 break; 468 469 case SSL_ERROR: 470 default: 471 return SOCKET_ERROR; 472 } 473 474 size_t written = 0; 475 SChannelBuffer& outbuf = impl_->outbuf; 476 while (written < cb) { 477 const size_t encrypt_len = std::min<size_t>(cb - written, 478 impl_->sizes.cbMaximumMessage); 479 480 CSecBufferBundle<4> out_buf; 481 out_buf[0].BufferType = SECBUFFER_STREAM_HEADER; 482 out_buf[0].cbBuffer = impl_->sizes.cbHeader; 483 out_buf[1].BufferType = SECBUFFER_DATA; 484 out_buf[1].cbBuffer = static_cast<unsigned long>(encrypt_len); 485 out_buf[2].BufferType = SECBUFFER_STREAM_TRAILER; 486 out_buf[2].cbBuffer = impl_->sizes.cbTrailer; 487 488 size_t packet_len = out_buf[0].cbBuffer 489 + out_buf[1].cbBuffer 490 + out_buf[2].cbBuffer; 491 492 SChannelBuffer message; 493 message.resize(packet_len); 494 out_buf[0].pvBuffer = &message[0]; 495 out_buf[1].pvBuffer = &message[out_buf[0].cbBuffer]; 496 out_buf[2].pvBuffer = &message[out_buf[0].cbBuffer + out_buf[1].cbBuffer]; 497 498 memcpy(out_buf[1].pvBuffer, 499 static_cast<const char*>(pv) + written, 500 encrypt_len); 501 502 //DescribeBuffers(LS_VERBOSE, "Encrypt In ", out_buf.desc()); 503 SECURITY_STATUS res = EncryptMessage(&impl_->ctx, 0, out_buf.desc(), 0); 504 //DescribeBuffers(LS_VERBOSE, "Encrypt Out ", out_buf.desc()); 505 506 if (FAILED(res)) { 507 Error("EncryptMessage", res, false); 508 return SOCKET_ERROR; 509 } 510 511 // We assume that the header and data segments do not change length, 512 // or else encrypting the concatenated packet in-place is wrong. 513 ASSERT(out_buf[0].cbBuffer == impl_->sizes.cbHeader); 514 ASSERT(out_buf[1].cbBuffer == static_cast<unsigned long>(encrypt_len)); 515 516 // However, the length of the trailer may change due to padding. 517 ASSERT(out_buf[2].cbBuffer <= impl_->sizes.cbTrailer); 518 519 packet_len = out_buf[0].cbBuffer 520 + out_buf[1].cbBuffer 521 + out_buf[2].cbBuffer; 522 523 written += encrypt_len; 524 outbuf.insert(outbuf.end(), &message[0], &message[packet_len-1]+1); 525 } 526 527 if (int err = Flush()) { 528 state_ = SSL_ERROR; 529 SetError(err); 530 return SOCKET_ERROR; 531 } 532 533 return static_cast<int>(written); 534 } 535 536 int 537 SChannelAdapter::Recv(void* pv, size_t cb) { 538 switch (state_) { 539 case SSL_NONE: 540 return AsyncSocketAdapter::Recv(pv, cb); 541 542 case SSL_WAIT: 543 case SSL_CONNECTING: 544 SetError(EWOULDBLOCK); 545 return SOCKET_ERROR; 546 547 case SSL_CONNECTED: 548 break; 549 550 case SSL_ERROR: 551 default: 552 return SOCKET_ERROR; 553 } 554 555 SChannelBuffer& readable = impl_->readable; 556 if (readable.empty()) { 557 SetError(EWOULDBLOCK); 558 return SOCKET_ERROR; 559 } 560 size_t read = _min(cb, readable.size()); 561 memcpy(pv, &readable[0], read); 562 if (size_t remaining = readable.size() - read) { 563 memmove(&readable[0], &readable[read], remaining); 564 readable.resize(remaining); 565 } else { 566 readable.clear(); 567 } 568 569 PostEvent(); 570 return static_cast<int>(read); 571 } 572 573 int 574 SChannelAdapter::Close() { 575 if (!impl_->readable.empty()) { 576 LOG(WARNING) << "SChannelAdapter::Close with readable data"; 577 // Note: this isn't strictly an error, but we're using it temporarily to 578 // track bugs. 579 //ASSERT(false); 580 } 581 if (state_ == SSL_CONNECTED) { 582 DWORD token = SCHANNEL_SHUTDOWN; 583 CSecBufferBundle<1> sb_in; 584 sb_in[0].BufferType = SECBUFFER_TOKEN; 585 sb_in[0].cbBuffer = sizeof(token); 586 sb_in[0].pvBuffer = &token; 587 ApplyControlToken(&impl_->ctx, sb_in.desc()); 588 // TODO: In theory, to do a nice shutdown, we need to begin shutdown 589 // negotiation with more calls to InitializeSecurityContext. Since the 590 // socket api doesn't support nice shutdown at this point, we don't bother. 591 } 592 Cleanup(); 593 impl_ = new SSLImpl; 594 state_ = restartable_ ? SSL_WAIT : SSL_NONE; 595 signal_close_ = false; 596 message_pending_ = false; 597 return AsyncSocketAdapter::Close(); 598 } 599 600 Socket::ConnState 601 SChannelAdapter::GetState() const { 602 if (signal_close_) 603 return CS_CONNECTED; 604 ConnState state = socket_->GetState(); 605 if ((state == CS_CONNECTED) 606 && ((state_ == SSL_WAIT) || (state_ == SSL_CONNECTING))) 607 state = CS_CONNECTING; 608 return state; 609 } 610 611 void 612 SChannelAdapter::OnConnectEvent(AsyncSocket* socket) { 613 LOG(LS_VERBOSE) << "SChannelAdapter::OnConnectEvent"; 614 if (state_ != SSL_WAIT) { 615 ASSERT(state_ == SSL_NONE); 616 AsyncSocketAdapter::OnConnectEvent(socket); 617 return; 618 } 619 620 state_ = SSL_CONNECTING; 621 if (int err = BeginSSL()) { 622 Error("BeginSSL", err); 623 } 624 } 625 626 void 627 SChannelAdapter::OnReadEvent(AsyncSocket* socket) { 628 if (state_ == SSL_NONE) { 629 AsyncSocketAdapter::OnReadEvent(socket); 630 return; 631 } 632 633 if (int err = Read()) { 634 Error("Read", err); 635 return; 636 } 637 638 if (impl_->inbuf.empty()) 639 return; 640 641 if (state_ == SSL_CONNECTED) { 642 if (int err = DecryptData()) { 643 Error("DecryptData", err); 644 } else if (!impl_->readable.empty()) { 645 AsyncSocketAdapter::OnReadEvent(this); 646 } 647 } else if (state_ == SSL_CONNECTING) { 648 if (int err = ContinueSSL()) { 649 Error("ContinueSSL", err); 650 } 651 } 652 } 653 654 void 655 SChannelAdapter::OnWriteEvent(AsyncSocket* socket) { 656 if (state_ == SSL_NONE) { 657 AsyncSocketAdapter::OnWriteEvent(socket); 658 return; 659 } 660 661 if (int err = Flush()) { 662 Error("Flush", err); 663 return; 664 } 665 666 // See if we have more data to write 667 if (!impl_->outbuf.empty()) 668 return; 669 670 // Buffer is empty, submit notification 671 if (state_ == SSL_CONNECTED) { 672 AsyncSocketAdapter::OnWriteEvent(socket); 673 } 674 } 675 676 void 677 SChannelAdapter::OnCloseEvent(AsyncSocket* socket, int err) { 678 if ((state_ == SSL_NONE) || impl_->readable.empty()) { 679 AsyncSocketAdapter::OnCloseEvent(socket, err); 680 return; 681 } 682 683 // If readable is non-empty, then we have a pending Message 684 // that will allow us to signal close (eventually). 685 signal_close_ = true; 686 } 687 688 void 689 SChannelAdapter::OnMessage(Message* pmsg) { 690 if (!message_pending_) 691 return; // This occurs when socket is closed 692 693 message_pending_ = false; 694 if (!impl_->readable.empty()) { 695 AsyncSocketAdapter::OnReadEvent(this); 696 } else if (signal_close_) { 697 signal_close_ = false; 698 AsyncSocketAdapter::OnCloseEvent(this, 0); // TODO: cache this error? 699 } 700 } 701 702 } // namespace rtc 703