Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 // This file includes code GetDefaultCertNickname(), derived from | 5 // This file includes code GetDefaultCertNickname(), derived from | 
| 6 // nsNSSCertificate::defaultServerNickName() | 6 // nsNSSCertificate::defaultServerNickName() | 
| 7 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp | 7 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp | 
| 8 // and SSLClientSocketNSS::DoVerifyCertComplete() derived from | 8 // and SSLClientSocketNSS::DoVerifyCertComplete() derived from | 
| 9 // AuthCertificateCallback() in | 9 // AuthCertificateCallback() in | 
| 10 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 10 // mozilla/security/manager/ssl/src/nsNSSCallbacks.cpp. | 
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 74 | 74 | 
| 75 static const int kRecvBufferSize = 4096; | 75 static const int kRecvBufferSize = 4096; | 
| 76 | 76 | 
| 77 namespace net { | 77 namespace net { | 
| 78 | 78 | 
| 79 // State machines are easier to debug if you log state transitions. | 79 // State machines are easier to debug if you log state transitions. | 
| 80 // Enable these if you want to see what's going on. | 80 // Enable these if you want to see what's going on. | 
| 81 #if 1 | 81 #if 1 | 
| 82 #define EnterFunction(x) | 82 #define EnterFunction(x) | 
| 83 #define LeaveFunction(x) | 83 #define LeaveFunction(x) | 
| 84 #define GotoState(s) next_state_ = s | 84 #define GotoState(s) next_handshake_state_ = s | 
| 85 #define LogData(s, len) | 85 #define LogData(s, len) | 
| 86 #else | 86 #else | 
| 87 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 87 #define EnterFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 
| 88 " enter " << x << "; next_state " << next_state_ | 88 " enter " << x << \ | 
| 89 "; next_handshake_state " << next_handshake_state_ | |
| 89 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 90 #define LeaveFunction(x) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 
| 90 " leave " << x << "; next_state " << next_state_ | 91 " leave " << x << \ | 
| 92 "; next_handshake_state " << next_handshake_state_ | |
| 91 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 93 #define GotoState(s) do { LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 
| 92 " jump to state " << s; next_state_ = s; } while (0) | 94 " jump to state " << s; \ | 
| 95 next_handshake_state_ = s; } while (0) | |
| 93 #define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 96 #define LogData(s, len) LOG(INFO) << (void *)this << " " << __FUNCTION__ << \ | 
| 94 " data [" << std::string(s, len) << "]"; | 97 " data [" << std::string(s, len) << "]"; | 
| 95 | 98 | 
| 96 #endif | 99 #endif | 
| 97 | 100 | 
| 98 namespace { | 101 namespace { | 
| 99 | 102 | 
| 100 // Gets default certificate nickname from cert. | 103 // Gets default certificate nickname from cert. | 
| 101 // Derived from nsNSSCertificate::defaultServerNickname | 104 // Derived from nsNSSCertificate::defaultServerNickname | 
| 102 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp. | 105 // in mozilla/security/manager/ssl/src/nsNSSCertificate.cpp. | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 186 bool SSLClientSocketNSS::nss_options_initialized_ = false; | 189 bool SSLClientSocketNSS::nss_options_initialized_ = false; | 
| 187 | 190 | 
| 188 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, | 191 SSLClientSocketNSS::SSLClientSocketNSS(ClientSocket* transport_socket, | 
| 189 const std::string& hostname, | 192 const std::string& hostname, | 
| 190 const SSLConfig& ssl_config) | 193 const SSLConfig& ssl_config) | 
| 191 : | 194 : | 
| 192 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), | 195 buffer_send_callback_(this, &SSLClientSocketNSS::BufferSendComplete), | 
| 193 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), | 196 buffer_recv_callback_(this, &SSLClientSocketNSS::BufferRecvComplete), | 
| 194 transport_send_busy_(false), | 197 transport_send_busy_(false), | 
| 195 transport_recv_busy_(false), | 198 transport_recv_busy_(false), | 
| 196 io_callback_(this, &SSLClientSocketNSS::OnIOComplete), | 199 handshake_io_callback_(this, &SSLClientSocketNSS::OnHandshakeIOComplete), | 
| 197 transport_(transport_socket), | 200 transport_(transport_socket), | 
| 198 hostname_(hostname), | 201 hostname_(hostname), | 
| 199 ssl_config_(ssl_config), | 202 ssl_config_(ssl_config), | 
| 200 user_connect_callback_(NULL), | 203 user_connect_callback_(NULL), | 
| 201 user_callback_(NULL), | 204 user_read_callback_(NULL), | 
| 202 user_buf_len_(0), | 205 user_write_callback_(NULL), | 
| 206 user_read_buf_len_(0), | |
| 207 user_write_buf_len_(0), | |
| 203 completed_handshake_(false), | 208 completed_handshake_(false), | 
| 204 next_state_(STATE_NONE), | 209 next_handshake_state_(STATE_NONE), | 
| 205 nss_fd_(NULL), | 210 nss_fd_(NULL), | 
| 206 nss_bufs_(NULL) { | 211 nss_bufs_(NULL) { | 
| 207 EnterFunction(""); | 212 EnterFunction(""); | 
| 208 } | 213 } | 
| 209 | 214 | 
| 210 SSLClientSocketNSS::~SSLClientSocketNSS() { | 215 SSLClientSocketNSS::~SSLClientSocketNSS() { | 
| 211 EnterFunction(""); | 216 EnterFunction(""); | 
| 212 Disconnect(); | 217 Disconnect(); | 
| 213 LeaveFunction(""); | 218 LeaveFunction(""); | 
| 214 } | 219 } | 
| 215 | 220 | 
| 216 int SSLClientSocketNSS::Init() { | 221 int SSLClientSocketNSS::Init() { | 
| 217 EnterFunction(""); | 222 EnterFunction(""); | 
| 218 // Initialize NSS in a threadsafe way. | 223 // Initialize NSS in a threadsafe way. | 
| 219 base::EnsureNSSInit(); | 224 base::EnsureNSSInit(); | 
| 220 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop | 225 // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop | 
| 221 // by MessageLoopForIO::current(). | 226 // by MessageLoopForIO::current(). | 
| 222 // X509Certificate::Verify() runs on a worker thread of CertVerifier. | 227 // X509Certificate::Verify() runs on a worker thread of CertVerifier. | 
| 223 EnsureOCSPInit(); | 228 EnsureOCSPInit(); | 
| 224 | 229 | 
| 225 LeaveFunction(""); | 230 LeaveFunction(""); | 
| 226 return OK; | 231 return OK; | 
| 227 } | 232 } | 
| 228 | 233 | 
| 229 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { | 234 int SSLClientSocketNSS::Connect(CompletionCallback* callback) { | 
| 230 EnterFunction(""); | 235 EnterFunction(""); | 
| 231 DCHECK(transport_.get()); | 236 DCHECK(transport_.get()); | 
| 232 DCHECK(next_state_ == STATE_NONE); | 237 DCHECK(next_handshake_state_ == STATE_NONE); | 
| 233 DCHECK(!user_callback_); | 238 DCHECK(!user_read_callback_); | 
| 239 DCHECK(!user_write_callback_); | |
| 234 DCHECK(!user_connect_callback_); | 240 DCHECK(!user_connect_callback_); | 
| 235 DCHECK(!user_buf_); | 241 DCHECK(!user_read_buf_); | 
| 242 DCHECK(!user_write_buf_); | |
| 236 | 243 | 
| 237 if (Init() != OK) { | 244 if (Init() != OK) { | 
| 238 NOTREACHED() << "Couldn't initialize nss"; | 245 NOTREACHED() << "Couldn't initialize nss"; | 
| 239 } | 246 } | 
| 240 | 247 | 
| 241 // Transport connected, now hook it up to nss | 248 // Transport connected, now hook it up to nss | 
| 242 // TODO(port): specify rx and tx buffer sizes separately | 249 // TODO(port): specify rx and tx buffer sizes separately | 
| 243 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 250 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize); | 
| 244 if (nss_fd_ == NULL) { | 251 if (nss_fd_ == NULL) { | 
| 245 return 9999; // TODO(port): real error | 252 return 9999; // TODO(port): real error | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 314 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this); | 321 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this); | 
| 315 if (rv != SECSuccess) | 322 if (rv != SECSuccess) | 
| 316 return ERR_UNEXPECTED; | 323 return ERR_UNEXPECTED; | 
| 317 | 324 | 
| 318 // Tell SSL the hostname we're trying to connect to. | 325 // Tell SSL the hostname we're trying to connect to. | 
| 319 SSL_SetURL(nss_fd_, hostname_.c_str()); | 326 SSL_SetURL(nss_fd_, hostname_.c_str()); | 
| 320 | 327 | 
| 321 // Tell SSL we're a client; needed if not letting NSPR do socket I/O | 328 // Tell SSL we're a client; needed if not letting NSPR do socket I/O | 
| 322 SSL_ResetHandshake(nss_fd_, 0); | 329 SSL_ResetHandshake(nss_fd_, 0); | 
| 323 | 330 | 
| 324 GotoState(STATE_HANDSHAKE_READ); | 331 GotoState(STATE_HANDSHAKE); | 
| 325 rv = DoLoop(OK); | 332 rv = DoHandshakeLoop(OK); | 
| 326 if (rv == ERR_IO_PENDING) | 333 if (rv == ERR_IO_PENDING) | 
| 327 user_connect_callback_ = callback; | 334 user_connect_callback_ = callback; | 
| 328 | 335 | 
| 329 LeaveFunction(""); | 336 LeaveFunction(""); | 
| 330 return rv > OK ? OK : rv; | 337 return rv > OK ? OK : rv; | 
| 331 } | 338 } | 
| 332 | 339 | 
| 333 void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { | 340 void SSLClientSocketNSS::InvalidateSessionIfBadCertificate() { | 
| 334 if (UpdateServerCert() != NULL && | 341 if (UpdateServerCert() != NULL && | 
| 335 ssl_config_.IsAllowedBadCert(server_cert_)) { | 342 ssl_config_.IsAllowedBadCert(server_cert_)) { | 
| 336 SSL_InvalidateSession(nss_fd_); | 343 SSL_InvalidateSession(nss_fd_); | 
| 337 } | 344 } | 
| 338 } | 345 } | 
| 339 | 346 | 
| 340 void SSLClientSocketNSS::Disconnect() { | 347 void SSLClientSocketNSS::Disconnect() { | 
| 341 EnterFunction(""); | 348 EnterFunction(""); | 
| 342 | 349 | 
| 343 // TODO(wtc): Send SSL close_notify alert. | 350 // TODO(wtc): Send SSL close_notify alert. | 
| 344 if (nss_fd_ != NULL) { | 351 if (nss_fd_ != NULL) { | 
| 345 InvalidateSessionIfBadCertificate(); | 352 InvalidateSessionIfBadCertificate(); | 
| 346 PR_Close(nss_fd_); | 353 PR_Close(nss_fd_); | 
| 347 nss_fd_ = NULL; | 354 nss_fd_ = NULL; | 
| 348 } | 355 } | 
| 349 | 356 | 
| 350 // Shut down anything that may call us back (through buffer_send_callback_, | 357 // Shut down anything that may call us back (through buffer_send_callback_, | 
| 351 // buffer_recv_callback, or io_callback_). | 358 // buffer_recv_callback, or handshake_io_callback_). | 
| 352 verifier_.reset(); | 359 verifier_.reset(); | 
| 353 transport_->Disconnect(); | 360 transport_->Disconnect(); | 
| 354 | 361 | 
| 355 // Reset object state | 362 // Reset object state | 
| 356 transport_send_busy_ = false; | 363 transport_send_busy_ = false; | 
| 357 transport_recv_busy_ = false; | 364 transport_recv_busy_ = false; | 
| 358 user_connect_callback_ = NULL; | 365 user_connect_callback_ = NULL; | 
| 359 user_callback_ = NULL; | 366 user_read_callback_ = NULL; | 
| 360 user_buf_ = NULL; | 367 user_write_callback_ = NULL; | 
| 361 user_buf_len_ = 0; | 368 user_read_buf_ = NULL; | 
| 369 user_read_buf_len_ = 0; | |
| 370 user_write_buf_ = NULL; | |
| 371 user_write_buf_len_ = 0; | |
| 362 server_cert_ = NULL; | 372 server_cert_ = NULL; | 
| 363 server_cert_verify_result_.Reset(); | 373 server_cert_verify_result_.Reset(); | 
| 364 completed_handshake_ = false; | 374 completed_handshake_ = false; | 
| 365 nss_bufs_ = NULL; | 375 nss_bufs_ = NULL; | 
| 366 | 376 | 
| 367 LeaveFunction(""); | 377 LeaveFunction(""); | 
| 368 } | 378 } | 
| 369 | 379 | 
| 370 bool SSLClientSocketNSS::IsConnected() const { | 380 bool SSLClientSocketNSS::IsConnected() const { | 
| 371 // Ideally, we should also check if we have received the close_notify alert | 381 // Ideally, we should also check if we have received the close_notify alert | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 391 EnterFunction(""); | 401 EnterFunction(""); | 
| 392 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); | 402 bool ret = completed_handshake_ && transport_->IsConnectedAndIdle(); | 
| 393 LeaveFunction(""); | 403 LeaveFunction(""); | 
| 394 return ret; | 404 return ret; | 
| 395 } | 405 } | 
| 396 | 406 | 
| 397 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, | 407 int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, | 
| 398 CompletionCallback* callback) { | 408 CompletionCallback* callback) { | 
| 399 EnterFunction(buf_len); | 409 EnterFunction(buf_len); | 
| 400 DCHECK(completed_handshake_); | 410 DCHECK(completed_handshake_); | 
| 401 DCHECK(next_state_ == STATE_NONE); | 411 DCHECK(next_handshake_state_ == STATE_NONE); | 
| 402 DCHECK(!user_callback_); | 412 DCHECK(!user_read_callback_); | 
| 403 DCHECK(!user_connect_callback_); | 413 DCHECK(!user_connect_callback_); | 
| 404 DCHECK(!user_buf_); | 414 DCHECK(!user_read_buf_); | 
| 415 DCHECK(nss_bufs_); | |
| 405 | 416 | 
| 406 user_buf_ = buf; | 417 user_read_buf_ = buf; | 
| 407 user_buf_len_ = buf_len; | 418 user_read_buf_len_ = buf_len; | 
| 408 | 419 | 
| 409 GotoState(STATE_PAYLOAD_READ); | 420 int rv = DoReadLoop(OK); | 
| 410 int rv = DoLoop(OK); | 421 | 
| 411 if (rv == ERR_IO_PENDING) | 422 if (rv == ERR_IO_PENDING) | 
| 
 
wtc
2009/10/14 01:54:15
Please add braces {} to "if" when "else" has brace
 
 | |
| 412 user_callback_ = callback; | 423 user_read_callback_ = callback; | 
| 424 else { | |
| 425 user_read_buf_ = NULL; | |
| 426 user_read_buf_len_ = 0; | |
| 427 } | |
| 413 LeaveFunction(rv); | 428 LeaveFunction(rv); | 
| 414 return rv; | 429 return rv; | 
| 415 } | 430 } | 
| 416 | 431 | 
| 417 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, | 432 int SSLClientSocketNSS::Write(IOBuffer* buf, int buf_len, | 
| 418 CompletionCallback* callback) { | 433 CompletionCallback* callback) { | 
| 419 EnterFunction(buf_len); | 434 EnterFunction(buf_len); | 
| 420 DCHECK(completed_handshake_); | 435 DCHECK(completed_handshake_); | 
| 421 DCHECK(next_state_ == STATE_NONE); | 436 DCHECK(next_handshake_state_ == STATE_NONE); | 
| 422 DCHECK(!user_callback_); | 437 DCHECK(!user_write_callback_); | 
| 423 DCHECK(!user_connect_callback_); | 438 DCHECK(!user_connect_callback_); | 
| 424 DCHECK(!user_buf_); | 439 DCHECK(!user_write_buf_); | 
| 440 DCHECK(nss_bufs_); | |
| 425 | 441 | 
| 426 user_buf_ = buf; | 442 user_write_buf_ = buf; | 
| 427 user_buf_len_ = buf_len; | 443 user_write_buf_len_ = buf_len; | 
| 428 | 444 | 
| 429 GotoState(STATE_PAYLOAD_WRITE); | 445 int rv = DoWriteLoop(OK); | 
| 430 int rv = DoLoop(OK); | 446 | 
| 431 if (rv == ERR_IO_PENDING) | 447 if (rv == ERR_IO_PENDING) | 
| 432 user_callback_ = callback; | 448 user_write_callback_ = callback; | 
| 
 
wtc
2009/10/14 01:54:15
Same here: both "if" and "else" should have braces
 
 | |
| 449 else { | |
| 450 user_write_buf_ = NULL; | |
| 451 user_write_buf_len_ = 0; | |
| 452 } | |
| 433 LeaveFunction(rv); | 453 LeaveFunction(rv); | 
| 434 return rv; | 454 return rv; | 
| 435 } | 455 } | 
| 436 | 456 | 
| 437 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | 457 bool SSLClientSocketNSS::SetReceiveBufferSize(int32 size) { | 
| 438 return transport_->SetReceiveBufferSize(size); | 458 return transport_->SetReceiveBufferSize(size); | 
| 439 } | 459 } | 
| 440 | 460 | 
| 441 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { | 461 bool SSLClientSocketNSS::SetSendBufferSize(int32 size) { | 
| 442 return transport_->SetSendBufferSize(size); | 462 return transport_->SetSendBufferSize(size); | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 DCHECK(server_cert_ != NULL); | 504 DCHECK(server_cert_ != NULL); | 
| 485 ssl_info->cert = server_cert_; | 505 ssl_info->cert = server_cert_; | 
| 486 LeaveFunction(""); | 506 LeaveFunction(""); | 
| 487 } | 507 } | 
| 488 | 508 | 
| 489 void SSLClientSocketNSS::GetSSLCertRequestInfo( | 509 void SSLClientSocketNSS::GetSSLCertRequestInfo( | 
| 490 SSLCertRequestInfo* cert_request_info) { | 510 SSLCertRequestInfo* cert_request_info) { | 
| 491 // TODO(wtc): implement this. | 511 // TODO(wtc): implement this. | 
| 492 } | 512 } | 
| 493 | 513 | 
| 494 void SSLClientSocketNSS::DoCallback(int rv) { | 514 void SSLClientSocketNSS::DoReadCallback(int rv) { | 
| 495 EnterFunction(rv); | 515 EnterFunction(rv); | 
| 496 DCHECK(rv != ERR_IO_PENDING); | 516 DCHECK(rv != ERR_IO_PENDING); | 
| 497 DCHECK(user_callback_); | 517 DCHECK(user_read_callback_); | 
| 498 | 518 | 
| 499 // Since Run may result in Read being called, clear |user_callback_| up front. | 519 // Since Run may result in Read being called, clear |user_read_callback_| | 
| 500 CompletionCallback* c = user_callback_; | 520 // up front. | 
| 501 user_callback_ = NULL; | 521 CompletionCallback* c = user_read_callback_; | 
| 502 user_buf_ = NULL; | 522 user_read_callback_ = NULL; | 
| 523 user_read_buf_ = NULL; | |
| 524 user_read_buf_len_ = 0; | |
| 503 c->Run(rv); | 525 c->Run(rv); | 
| 504 LeaveFunction(""); | 526 LeaveFunction(""); | 
| 505 } | 527 } | 
| 528 | |
| 529 void SSLClientSocketNSS::DoWriteCallback(int rv) { | |
| 530 EnterFunction(rv); | |
| 531 DCHECK(rv != ERR_IO_PENDING); | |
| 532 DCHECK(user_write_callback_); | |
| 533 | |
| 534 // Since Run may result in Write being called, clear |user_write_callback_| | |
| 535 // up front. | |
| 536 CompletionCallback* c = user_write_callback_; | |
| 537 user_write_callback_ = NULL; | |
| 538 user_write_buf_ = NULL; | |
| 539 user_write_buf_len_ = 0; | |
| 540 c->Run(rv); | |
| 541 LeaveFunction(""); | |
| 542 } | |
| 506 | 543 | 
| 507 // As part of Connect(), the SSLClientSocketNSS object performs an SSL | 544 // As part of Connect(), the SSLClientSocketNSS object performs an SSL | 
| 508 // handshake. This requires network IO, which in turn calls | 545 // handshake. This requires network IO, which in turn calls | 
| 509 // BufferRecvComplete() with a non-zero byte count. This byte count eventually | 546 // BufferRecvComplete() with a non-zero byte count. This byte count eventually | 
| 510 // winds its way through the state machine and ends up being passed to the | 547 // winds its way through the state machine and ends up being passed to the | 
| 511 // callback. For Read() and Write(), that's what we want. But for Connect(), | 548 // callback. For Read() and Write(), that's what we want. But for Connect(), | 
| 512 // the caller expects OK (i.e. 0) for success. | 549 // the caller expects OK (i.e. 0) for success. | 
| 513 // | 550 // | 
| 514 void SSLClientSocketNSS::DoConnectCallback(int rv) { | 551 void SSLClientSocketNSS::DoConnectCallback(int rv) { | 
| 515 EnterFunction(rv); | 552 EnterFunction(rv); | 
| 516 DCHECK_NE(rv, ERR_IO_PENDING); | 553 DCHECK_NE(rv, ERR_IO_PENDING); | 
| 517 DCHECK(user_connect_callback_); | 554 DCHECK(user_connect_callback_); | 
| 518 | 555 | 
| 519 // Since Run may result in Read being called, clear |user_connect_callback_| | |
| 520 // up front. | |
| 521 CompletionCallback* c = user_connect_callback_; | 556 CompletionCallback* c = user_connect_callback_; | 
| 522 user_connect_callback_ = NULL; | 557 user_connect_callback_ = NULL; | 
| 523 c->Run(rv > OK ? OK : rv); | 558 c->Run(rv > OK ? OK : rv); | 
| 524 LeaveFunction(""); | 559 LeaveFunction(""); | 
| 525 } | 560 } | 
| 526 | 561 | 
| 527 void SSLClientSocketNSS::OnIOComplete(int result) { | 562 void SSLClientSocketNSS::OnHandshakeIOComplete(int result) { | 
| 528 EnterFunction(result); | 563 EnterFunction(result); | 
| 529 int rv = DoLoop(result); | 564 int rv = DoHandshakeLoop(result); | 
| 530 if (rv != ERR_IO_PENDING) { | 565 if (rv != ERR_IO_PENDING) | 
| 531 if (user_callback_) { | 566 DoConnectCallback(rv); | 
| 532 DoCallback(rv); | |
| 533 } else if (user_connect_callback_) { | |
| 534 DoConnectCallback(rv); | |
| 535 } | |
| 536 } | |
| 537 LeaveFunction(""); | 567 LeaveFunction(""); | 
| 538 } | 568 } | 
| 539 | 569 | 
| 570 void SSLClientSocketNSS::OnSendComplete(int result) { | |
| 571 EnterFunction(result); | |
| 572 if (next_handshake_state_ != STATE_NONE) { | |
| 573 // In handshake phase. | |
| 574 OnHandshakeIOComplete(result); | |
| 575 LeaveFunction(""); | |
| 576 return; | |
| 577 } | |
| 578 | |
| 579 // OnSendComplete may need to call DoPayloadRead while the renegotiation | |
| 580 // handshake is in progress. | |
| 581 int rv_read = ERR_IO_PENDING; | |
| 582 int rv_write = ERR_IO_PENDING; | |
| 583 bool network_moved; | |
| 584 do { | |
| 585 if (user_read_buf_) | |
| 586 rv_read = DoPayloadRead(); | |
| 587 if (user_write_buf_) | |
| 588 rv_write = DoPayloadWrite(); | |
| 589 network_moved = DoTransportIO(); | |
| 590 } while (rv_read == ERR_IO_PENDING && | |
| 591 rv_write == ERR_IO_PENDING && | |
| 592 network_moved); | |
| 593 | |
| 594 if (user_read_buf_ && rv_read != ERR_IO_PENDING) | |
| 595 DoReadCallback(rv_read); | |
| 596 if (user_write_buf_ && rv_write != ERR_IO_PENDING) | |
| 597 DoWriteCallback(rv_write); | |
| 598 | |
| 599 LeaveFunction(""); | |
| 600 } | |
| 601 | |
| 602 void SSLClientSocketNSS::OnRecvComplete(int result) { | |
| 603 EnterFunction(result); | |
| 604 if (next_handshake_state_ != STATE_NONE) { | |
| 605 // In handshake phase. | |
| 606 OnHandshakeIOComplete(result); | |
| 607 LeaveFunction(""); | |
| 608 return; | |
| 609 } | |
| 610 | |
| 611 // Network layer received some data, check if client requested to read | |
| 612 // decrypted data. | |
| 613 if (!user_read_buf_) { | |
| 614 LeaveFunction(""); | |
| 615 return; | |
| 616 } | |
| 617 | |
| 618 int rv = DoReadLoop(result); | |
| 619 if (rv != ERR_IO_PENDING) | |
| 620 DoReadCallback(rv); | |
| 621 LeaveFunction(""); | |
| 622 } | |
| 623 | |
| 540 // Map a Chromium net error code to an NSS error code | 624 // Map a Chromium net error code to an NSS error code | 
| 541 // See _MD_unix_map_default_error in the NSS source | 625 // See _MD_unix_map_default_error in the NSS source | 
| 542 // tree for inspiration. | 626 // tree for inspiration. | 
| 543 static PRErrorCode MapErrorToNSS(int result) { | 627 static PRErrorCode MapErrorToNSS(int result) { | 
| 544 if (result >=0) | 628 if (result >=0) | 
| 545 return result; | 629 return result; | 
| 546 // TODO(port): add real table | 630 // TODO(port): add real table | 
| 547 LOG(ERROR) << "MapErrorToNSS " << result; | 631 LOG(ERROR) << "MapErrorToNSS " << result; | 
| 548 return PR_UNKNOWN_ERROR; | 632 return PR_UNKNOWN_ERROR; | 
| 549 } | 633 } | 
| 550 | 634 | 
| 551 // Do network I/O between the given buffer and the given socket. | 635 // Do network I/O between the given buffer and the given socket. | 
| 636 // Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING) | |
| 637 bool SSLClientSocketNSS::DoTransportIO() { | |
| 638 EnterFunction(""); | |
| 639 bool network_moved = false; | |
| 640 if (nss_bufs_ != NULL) { | |
| 641 int nsent = BufferSend(); | |
| 642 int nreceived = BufferRecv(); | |
| 643 network_moved = (nsent > 0 || nreceived >= 0); | |
| 644 } | |
| 645 LeaveFunction(network_moved); | |
| 646 return network_moved; | |
| 647 } | |
| 648 | |
| 552 // Return 0 for EOF, | 649 // Return 0 for EOF, | 
| 553 // > 0 for bytes transferred immediately, | 650 // > 0 for bytes transferred immediately, | 
| 554 // < 0 for error (or the non-error ERR_IO_PENDING). | 651 // < 0 for error (or the non-error ERR_IO_PENDING). | 
| 555 int SSLClientSocketNSS::BufferSend(void) { | 652 int SSLClientSocketNSS::BufferSend(void) { | 
| 556 if (transport_send_busy_) return ERR_IO_PENDING; | 653 if (transport_send_busy_) return ERR_IO_PENDING; | 
| 557 | 654 | 
| 558 const char *buf; | 655 const char *buf; | 
| 559 int nb = memio_GetWriteParams(nss_bufs_, &buf); | 656 int nb = memio_GetWriteParams(nss_bufs_, &buf); | 
| 560 EnterFunction(nb); | 657 EnterFunction(nb); | 
| 561 | 658 | 
| (...skipping 11 matching lines...) Expand all Loading... | |
| 573 } | 670 } | 
| 574 | 671 | 
| 575 LeaveFunction(rv); | 672 LeaveFunction(rv); | 
| 576 return rv; | 673 return rv; | 
| 577 } | 674 } | 
| 578 | 675 | 
| 579 void SSLClientSocketNSS::BufferSendComplete(int result) { | 676 void SSLClientSocketNSS::BufferSendComplete(int result) { | 
| 580 EnterFunction(result); | 677 EnterFunction(result); | 
| 581 memio_PutWriteResult(nss_bufs_, result); | 678 memio_PutWriteResult(nss_bufs_, result); | 
| 582 transport_send_busy_ = false; | 679 transport_send_busy_ = false; | 
| 583 OnIOComplete(result); | 680 OnSendComplete(result); | 
| 584 LeaveFunction(""); | 681 LeaveFunction(""); | 
| 585 } | 682 } | 
| 586 | 683 | 
| 587 | 684 | 
| 588 int SSLClientSocketNSS::BufferRecv(void) { | 685 int SSLClientSocketNSS::BufferRecv(void) { | 
| 589 if (transport_recv_busy_) return ERR_IO_PENDING; | 686 if (transport_recv_busy_) return ERR_IO_PENDING; | 
| 590 | 687 | 
| 591 char *buf; | 688 char *buf; | 
| 592 int nb = memio_GetReadParams(nss_bufs_, &buf); | 689 int nb = memio_GetReadParams(nss_bufs_, &buf); | 
| 593 EnterFunction(nb); | 690 EnterFunction(nb); | 
| (...skipping 20 matching lines...) Expand all Loading... | |
| 614 void SSLClientSocketNSS::BufferRecvComplete(int result) { | 711 void SSLClientSocketNSS::BufferRecvComplete(int result) { | 
| 615 EnterFunction(result); | 712 EnterFunction(result); | 
| 616 if (result > 0) { | 713 if (result > 0) { | 
| 617 char *buf; | 714 char *buf; | 
| 618 memio_GetReadParams(nss_bufs_, &buf); | 715 memio_GetReadParams(nss_bufs_, &buf); | 
| 619 memcpy(buf, recv_buffer_->data(), result); | 716 memcpy(buf, recv_buffer_->data(), result); | 
| 620 } | 717 } | 
| 621 recv_buffer_ = NULL; | 718 recv_buffer_ = NULL; | 
| 622 memio_PutReadResult(nss_bufs_, result); | 719 memio_PutReadResult(nss_bufs_, result); | 
| 623 transport_recv_busy_ = false; | 720 transport_recv_busy_ = false; | 
| 624 OnIOComplete(result); | 721 OnRecvComplete(result); | 
| 625 LeaveFunction(""); | 722 LeaveFunction(""); | 
| 626 } | 723 } | 
| 627 | 724 | 
| 628 int SSLClientSocketNSS::DoLoop(int last_io_result) { | 725 int SSLClientSocketNSS::DoHandshakeLoop(int last_io_result) { | 
| 629 EnterFunction(last_io_result); | 726 EnterFunction(last_io_result); | 
| 630 bool network_moved; | 727 bool network_moved; | 
| 631 int rv = last_io_result; | 728 int rv = last_io_result; | 
| 632 do { | 729 do { | 
| 633 network_moved = false; | |
| 634 // Default to STATE_NONE for next state. | 730 // Default to STATE_NONE for next state. | 
| 635 // (This is a quirk carried over from the windows | 731 // (This is a quirk carried over from the windows | 
| 636 // implementation. It makes reading the logs a bit harder.) | 732 // implementation. It makes reading the logs a bit harder.) | 
| 637 // State handlers can and often do call GotoState just | 733 // State handlers can and often do call GotoState just | 
| 638 // to stay in the current state. | 734 // to stay in the current state. | 
| 639 State state = next_state_; | 735 State state = next_handshake_state_; | 
| 640 GotoState(STATE_NONE); | 736 GotoState(STATE_NONE); | 
| 641 switch (state) { | 737 switch (state) { | 
| 642 case STATE_NONE: | 738 case STATE_NONE: | 
| 643 // we're just pumping data between the buffer and the network | 739 // we're just pumping data between the buffer and the network | 
| 644 break; | 740 break; | 
| 645 case STATE_HANDSHAKE_READ: | 741 case STATE_HANDSHAKE: | 
| 646 rv = DoHandshakeRead(); | 742 rv = DoHandshake(); | 
| 647 break; | 743 break; | 
| 648 case STATE_VERIFY_CERT: | 744 case STATE_VERIFY_CERT: | 
| 649 DCHECK(rv == OK); | 745 DCHECK(rv == OK); | 
| 650 rv = DoVerifyCert(rv); | 746 rv = DoVerifyCert(rv); | 
| 651 break; | 747 break; | 
| 652 case STATE_VERIFY_CERT_COMPLETE: | 748 case STATE_VERIFY_CERT_COMPLETE: | 
| 653 rv = DoVerifyCertComplete(rv); | 749 rv = DoVerifyCertComplete(rv); | 
| 654 break; | 750 break; | 
| 655 case STATE_PAYLOAD_READ: | |
| 656 rv = DoPayloadRead(); | |
| 657 break; | |
| 658 case STATE_PAYLOAD_WRITE: | |
| 659 rv = DoPayloadWrite(); | |
| 660 break; | |
| 661 default: | 751 default: | 
| 662 rv = ERR_UNEXPECTED; | 752 rv = ERR_UNEXPECTED; | 
| 663 NOTREACHED() << "unexpected state"; | 753 NOTREACHED() << "unexpected state"; | 
| 664 break; | 754 break; | 
| 665 } | 755 } | 
| 666 | 756 | 
| 667 // Do the actual network I/O | 757 // Do the actual network I/O | 
| 668 if (nss_bufs_ != NULL) { | 758 network_moved = DoTransportIO(); | 
| 669 int nsent = BufferSend(); | |
| 670 int nreceived = BufferRecv(); | |
| 671 network_moved = (nsent > 0 || nreceived >= 0); | |
| 672 } | |
| 673 } while ((rv != ERR_IO_PENDING || network_moved) && | 759 } while ((rv != ERR_IO_PENDING || network_moved) && | 
| 674 next_state_ != STATE_NONE); | 760 next_handshake_state_ != STATE_NONE); | 
| 675 LeaveFunction(""); | 761 LeaveFunction(""); | 
| 676 return rv; | 762 return rv; | 
| 677 } | 763 } | 
| 764 | |
| 765 int SSLClientSocketNSS::DoReadLoop(int result) { | |
| 766 EnterFunction(""); | |
| 767 DCHECK(completed_handshake_); | |
| 768 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 769 | |
| 770 if (result < 0) | |
| 771 return result; | |
| 772 | |
| 773 if (!nss_bufs_) | |
| 774 return ERR_UNEXPECTED; | |
| 775 | |
| 776 bool network_moved; | |
| 777 int rv; | |
| 778 do { | |
| 779 rv = DoPayloadRead(); | |
| 780 network_moved = DoTransportIO(); | |
| 781 } while (rv == ERR_IO_PENDING && network_moved); | |
| 782 | |
| 783 LeaveFunction(""); | |
| 784 return rv; | |
| 785 } | |
| 786 | |
| 787 int SSLClientSocketNSS::DoWriteLoop(int result) { | |
| 788 EnterFunction(""); | |
| 789 DCHECK(completed_handshake_); | |
| 790 DCHECK(next_handshake_state_ == STATE_NONE); | |
| 791 | |
| 792 if (result < 0) | |
| 793 return result; | |
| 794 | |
| 795 if (!nss_bufs_) | |
| 796 return ERR_UNEXPECTED; | |
| 797 | |
| 798 bool network_moved; | |
| 799 int rv; | |
| 800 do { | |
| 801 rv = DoPayloadWrite(); | |
| 802 network_moved = DoTransportIO(); | |
| 803 } while (rv == ERR_IO_PENDING && network_moved); | |
| 804 | |
| 805 LeaveFunction(""); | |
| 806 return rv; | |
| 807 } | |
| 678 | 808 | 
| 679 // static | 809 // static | 
| 680 // NSS calls this if an incoming certificate needs to be verified. | 810 // NSS calls this if an incoming certificate needs to be verified. | 
| 681 // Do nothing but return SECSuccess. | 811 // Do nothing but return SECSuccess. | 
| 682 // This is called only in full handshake mode. | 812 // This is called only in full handshake mode. | 
| 683 // Peer certificate is retrieved in HandshakeCallback() later, which is called | 813 // Peer certificate is retrieved in HandshakeCallback() later, which is called | 
| 684 // in full handshake mode or in resumption handshake mode. | 814 // in full handshake mode or in resumption handshake mode. | 
| 685 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, | 815 SECStatus SSLClientSocketNSS::OwnAuthCertHandler(void* arg, | 
| 686 PRFileDesc* socket, | 816 PRFileDesc* socket, | 
| 687 PRBool checksig, | 817 PRBool checksig, | 
| 688 PRBool is_server) { | 818 PRBool is_server) { | 
| 689 // Tell NSS to not verify the certificate. | 819 // Tell NSS to not verify the certificate. | 
| 690 return SECSuccess; | 820 return SECSuccess; | 
| 691 } | 821 } | 
| 692 | 822 | 
| 693 // static | 823 // static | 
| 694 // NSS calls this when handshake is completed. | 824 // NSS calls this when handshake is completed. | 
| 695 // After the SSL handshake is finished, use CertVerifier to verify | 825 // After the SSL handshake is finished, use CertVerifier to verify | 
| 696 // the saved server certificate. | 826 // the saved server certificate. | 
| 697 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, | 827 void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket, | 
| 698 void* arg) { | 828 void* arg) { | 
| 699 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 829 SSLClientSocketNSS* that = reinterpret_cast<SSLClientSocketNSS*>(arg); | 
| 700 | 830 | 
| 701 that->UpdateServerCert(); | 831 that->UpdateServerCert(); | 
| 702 } | 832 } | 
| 703 | 833 | 
| 704 int SSLClientSocketNSS::DoHandshakeRead() { | 834 int SSLClientSocketNSS::DoHandshake() { | 
| 705 EnterFunction(""); | 835 EnterFunction(""); | 
| 706 int net_error = net::OK; | 836 int net_error = net::OK; | 
| 707 int rv = SSL_ForceHandshake(nss_fd_); | 837 int rv = SSL_ForceHandshake(nss_fd_); | 
| 708 | 838 | 
| 709 if (rv == SECSuccess) { | 839 if (rv == SECSuccess) { | 
| 710 // SSL handshake is completed. Let's verify the certificate. | 840 // SSL handshake is completed. Let's verify the certificate. | 
| 711 GotoState(STATE_VERIFY_CERT); | 841 GotoState(STATE_VERIFY_CERT); | 
| 712 // Done! | 842 // Done! | 
| 713 } else { | 843 } else { | 
| 714 PRErrorCode prerr = PR_GetError(); | 844 PRErrorCode prerr = PR_GetError(); | 
| 715 | 845 | 
| 716 // If the server closed on us, it is a protocol error. | 846 // If the server closed on us, it is a protocol error. | 
| 717 // Some TLS-intolerant servers do this when we request TLS. | 847 // Some TLS-intolerant servers do this when we request TLS. | 
| 718 if (prerr == PR_END_OF_FILE_ERROR) { | 848 if (prerr == PR_END_OF_FILE_ERROR) { | 
| 719 net_error = ERR_SSL_PROTOCOL_ERROR; | 849 net_error = ERR_SSL_PROTOCOL_ERROR; | 
| 720 } else { | 850 } else { | 
| 721 net_error = NetErrorFromNSPRError(prerr); | 851 net_error = NetErrorFromNSPRError(prerr); | 
| 722 } | 852 } | 
| 723 | 853 | 
| 724 // If not done, stay in this state | 854 // If not done, stay in this state | 
| 725 if (net_error == ERR_IO_PENDING) { | 855 if (net_error == ERR_IO_PENDING) { | 
| 726 GotoState(STATE_HANDSHAKE_READ); | 856 GotoState(STATE_HANDSHAKE); | 
| 727 } else { | 857 } else { | 
| 728 LOG(ERROR) << "handshake failed; NSS error code " << prerr | 858 LOG(ERROR) << "handshake failed; NSS error code " << prerr | 
| 729 << ", net_error " << net_error; | 859 << ", net_error " << net_error; | 
| 730 } | 860 } | 
| 731 } | 861 } | 
| 732 | 862 | 
| 733 LeaveFunction(""); | 863 LeaveFunction(""); | 
| 734 return net_error; | 864 return net_error; | 
| 735 } | 865 } | 
| 736 | 866 | 
| 737 int SSLClientSocketNSS::DoVerifyCert(int result) { | 867 int SSLClientSocketNSS::DoVerifyCert(int result) { | 
| 738 DCHECK(server_cert_); | 868 DCHECK(server_cert_); | 
| 739 GotoState(STATE_VERIFY_CERT_COMPLETE); | 869 GotoState(STATE_VERIFY_CERT_COMPLETE); | 
| 740 int flags = 0; | 870 int flags = 0; | 
| 741 if (ssl_config_.rev_checking_enabled) | 871 if (ssl_config_.rev_checking_enabled) | 
| 742 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 872 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED; | 
| 743 if (ssl_config_.verify_ev_cert) | 873 if (ssl_config_.verify_ev_cert) | 
| 744 flags |= X509Certificate::VERIFY_EV_CERT; | 874 flags |= X509Certificate::VERIFY_EV_CERT; | 
| 745 verifier_.reset(new CertVerifier); | 875 verifier_.reset(new CertVerifier); | 
| 746 return verifier_->Verify(server_cert_, hostname_, flags, | 876 return verifier_->Verify(server_cert_, hostname_, flags, | 
| 747 &server_cert_verify_result_, &io_callback_); | 877 &server_cert_verify_result_, | 
| 878 &handshake_io_callback_); | |
| 748 } | 879 } | 
| 749 | 880 | 
| 750 // Derived from AuthCertificateCallback() in | 881 // Derived from AuthCertificateCallback() in | 
| 751 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. | 882 // mozilla/source/security/manager/ssl/src/nsNSSCallbacks.cpp. | 
| 752 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { | 883 int SSLClientSocketNSS::DoVerifyCertComplete(int result) { | 
| 753 DCHECK(verifier_.get()); | 884 DCHECK(verifier_.get()); | 
| 754 verifier_.reset(); | 885 verifier_.reset(); | 
| 755 | 886 | 
| 756 if (result == OK) { | 887 if (result == OK) { | 
| 757 // Remember the intermediate CA certs if the server sends them to us. | 888 // Remember the intermediate CA certs if the server sends them to us. | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 if (IsCertificateError(result) && | 929 if (IsCertificateError(result) && | 
| 799 ssl_config_.IsAllowedBadCert(server_cert_)) { | 930 ssl_config_.IsAllowedBadCert(server_cert_)) { | 
| 800 LOG(INFO) << "accepting bad SSL certificate, as user told us to"; | 931 LOG(INFO) << "accepting bad SSL certificate, as user told us to"; | 
| 801 result = OK; | 932 result = OK; | 
| 802 } | 933 } | 
| 803 | 934 | 
| 804 completed_handshake_ = true; | 935 completed_handshake_ = true; | 
| 805 // TODO(ukai): we may not need this call because it is now harmless to have an | 936 // TODO(ukai): we may not need this call because it is now harmless to have an | 
| 806 // session with a bad cert. | 937 // session with a bad cert. | 
| 807 InvalidateSessionIfBadCertificate(); | 938 InvalidateSessionIfBadCertificate(); | 
| 808 // Exit DoLoop and return the result to the caller to Connect. | 939 // Exit DoHandshakeLoop and return the result to the caller to Connect. | 
| 809 DCHECK(next_state_ == STATE_NONE); | 940 DCHECK(next_handshake_state_ == STATE_NONE); | 
| 810 return result; | 941 return result; | 
| 811 } | 942 } | 
| 812 | 943 | 
| 813 int SSLClientSocketNSS::DoPayloadRead() { | 944 int SSLClientSocketNSS::DoPayloadRead() { | 
| 814 EnterFunction(user_buf_len_); | 945 EnterFunction(user_read_buf_len_); | 
| 815 int rv = PR_Read(nss_fd_, user_buf_->data(), user_buf_len_); | 946 DCHECK(user_read_buf_); | 
| 947 DCHECK(user_read_buf_len_ > 0); | |
| 948 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_); | |
| 816 if (rv >= 0) { | 949 if (rv >= 0) { | 
| 817 LogData(user_buf_->data(), rv); | 950 LogData(user_read_buf_->data(), rv); | 
| 818 user_buf_ = NULL; | |
| 819 LeaveFunction(""); | 951 LeaveFunction(""); | 
| 820 return rv; | 952 return rv; | 
| 821 } | 953 } | 
| 822 PRErrorCode prerr = PR_GetError(); | 954 PRErrorCode prerr = PR_GetError(); | 
| 823 if (prerr == PR_WOULD_BLOCK_ERROR) { | 955 if (prerr == PR_WOULD_BLOCK_ERROR) { | 
| 824 GotoState(STATE_PAYLOAD_READ); | |
| 825 LeaveFunction(""); | 956 LeaveFunction(""); | 
| 826 return ERR_IO_PENDING; | 957 return ERR_IO_PENDING; | 
| 827 } | 958 } | 
| 828 user_buf_ = NULL; | |
| 829 LeaveFunction(""); | 959 LeaveFunction(""); | 
| 830 return NetErrorFromNSPRError(prerr); | 960 return NetErrorFromNSPRError(prerr); | 
| 831 } | 961 } | 
| 832 | 962 | 
| 833 int SSLClientSocketNSS::DoPayloadWrite() { | 963 int SSLClientSocketNSS::DoPayloadWrite() { | 
| 834 EnterFunction(user_buf_len_); | 964 EnterFunction(user_write_buf_len_); | 
| 835 int rv = PR_Write(nss_fd_, user_buf_->data(), user_buf_len_); | 965 DCHECK(user_write_buf_); | 
| 966 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_); | |
| 836 if (rv >= 0) { | 967 if (rv >= 0) { | 
| 837 LogData(user_buf_->data(), rv); | 968 LogData(user_write_buf_->data(), rv); | 
| 838 user_buf_ = NULL; | |
| 839 LeaveFunction(""); | 969 LeaveFunction(""); | 
| 840 return rv; | 970 return rv; | 
| 841 } | 971 } | 
| 842 PRErrorCode prerr = PR_GetError(); | 972 PRErrorCode prerr = PR_GetError(); | 
| 843 if (prerr == PR_WOULD_BLOCK_ERROR) { | 973 if (prerr == PR_WOULD_BLOCK_ERROR) { | 
| 844 GotoState(STATE_PAYLOAD_WRITE); | |
| 845 return ERR_IO_PENDING; | 974 return ERR_IO_PENDING; | 
| 846 } | 975 } | 
| 847 user_buf_ = NULL; | |
| 848 LeaveFunction(""); | 976 LeaveFunction(""); | 
| 849 return NetErrorFromNSPRError(prerr); | 977 return NetErrorFromNSPRError(prerr); | 
| 850 } | 978 } | 
| 851 | 979 | 
| 852 } // namespace net | 980 } // namespace net | 
| OLD | NEW |