|
|
|
Lines 395-428
nsHttpConnectionMgr::ProcessOneTransacti
|
Link Here
|
|---|
|
| 395 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
395 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
| 396 |
|
396 |
|
| 397 |
if (self->ProcessPendingQForEntry(ent)) |
397 |
if (self->ProcessPendingQForEntry(ent)) |
| 398 |
return kHashEnumerateStop; |
398 |
return kHashEnumerateStop; |
| 399 |
|
399 |
|
| 400 |
return kHashEnumerateNext; |
400 |
return kHashEnumerateNext; |
| 401 |
} |
401 |
} |
| 402 |
|
402 |
|
|
|
403 |
// If the global number of idle connections is preventing the opening of |
| 404 |
// new connections to a host without idle connections, then |
| 405 |
// close them regardless of their TTL |
| 403 |
PRIntn |
406 |
PRIntn |
| 404 |
nsHttpConnectionMgr::PurgeOneIdleConnectionCB(nsHashKey *key, void *data, void *closure) |
407 |
nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(nsHashKey *key, |
|
|
408 |
void *data, void *closure) |
| 405 |
{ |
409 |
{ |
| 406 |
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure; |
410 |
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure; |
| 407 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
411 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
| 408 |
|
412 |
|
| 409 |
if (ent->mIdleConns.Length() > 0) { |
413 |
while (self->mNumIdleConns + self->mNumActiveConns + 1 >= self->mMaxConns) { |
|
|
414 |
if (!ent->mIdleConns.Length()) { |
| 415 |
// There are no idle conns left in this connection entry |
| 416 |
return kHashEnumerateNext; |
| 417 |
} |
| 410 |
nsHttpConnection *conn = ent->mIdleConns[0]; |
418 |
nsHttpConnection *conn = ent->mIdleConns[0]; |
| 411 |
ent->mIdleConns.RemoveElementAt(0); |
419 |
ent->mIdleConns.RemoveElementAt(0); |
| 412 |
conn->Close(NS_ERROR_ABORT); |
420 |
conn->Close(NS_ERROR_ABORT); |
| 413 |
NS_RELEASE(conn); |
421 |
NS_RELEASE(conn); |
| 414 |
self->mNumIdleConns--; |
422 |
self->mNumIdleConns--; |
| 415 |
if (0 == self->mNumIdleConns) |
423 |
if (0 == self->mNumIdleConns) |
| 416 |
self->StopPruneDeadConnectionsTimer(); |
424 |
self->StopPruneDeadConnectionsTimer(); |
| 417 |
return kHashEnumerateStop; |
|
|
| 418 |
} |
425 |
} |
| 419 |
|
426 |
return kHashEnumerateStop; |
| 420 |
return kHashEnumerateNext; |
|
|
| 421 |
} |
427 |
} |
| 422 |
|
428 |
|
| 423 |
PRIntn |
429 |
PRIntn |
| 424 |
nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *closure) |
430 |
nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *closure) |
| 425 |
{ |
431 |
{ |
| 426 |
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure; |
432 |
nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure; |
| 427 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
433 |
nsConnectionEntry *ent = (nsConnectionEntry *) data; |
| 428 |
|
434 |
|
|
Lines 469-484
nsHttpConnectionMgr::PruneDeadConnection
|
Link Here
|
|---|
|
| 469 |
LOG((" active conn [%x] with trans [%x]\n", conn, conn->Transaction())); |
475 |
LOG((" active conn [%x] with trans [%x]\n", conn, conn->Transaction())); |
| 470 |
} |
476 |
} |
| 471 |
} |
477 |
} |
| 472 |
#endif |
478 |
#endif |
| 473 |
|
479 |
|
| 474 |
// if this entry is empty, then we can remove it. |
480 |
// if this entry is empty, then we can remove it. |
| 475 |
if (ent->mIdleConns.Length() == 0 && |
481 |
if (ent->mIdleConns.Length() == 0 && |
| 476 |
ent->mActiveConns.Length() == 0 && |
482 |
ent->mActiveConns.Length() == 0 && |
|
|
483 |
ent->mHalfOpens.Length() == 0 && |
| 477 |
ent->mPendingQ.Length() == 0) { |
484 |
ent->mPendingQ.Length() == 0) { |
| 478 |
LOG((" removing empty connection entry\n")); |
485 |
LOG((" removing empty connection entry\n")); |
| 479 |
delete ent; |
486 |
delete ent; |
| 480 |
return kHashEnumerateRemove; |
487 |
return kHashEnumerateRemove; |
| 481 |
} |
488 |
} |
| 482 |
|
489 |
|
| 483 |
// else, use this opportunity to compact our arrays... |
490 |
// else, use this opportunity to compact our arrays... |
| 484 |
ent->mIdleConns.Compact(); |
491 |
ent->mIdleConns.Compact(); |
|
Lines 528-543
nsHttpConnectionMgr::ShutdownPassCB(nsHa
|
Link Here
|
|---|
|
| 528 |
trans = ent->mPendingQ[0]; |
535 |
trans = ent->mPendingQ[0]; |
| 529 |
|
536 |
|
| 530 |
ent->mPendingQ.RemoveElementAt(0); |
537 |
ent->mPendingQ.RemoveElementAt(0); |
| 531 |
|
538 |
|
| 532 |
trans->Close(NS_ERROR_ABORT); |
539 |
trans->Close(NS_ERROR_ABORT); |
| 533 |
NS_RELEASE(trans); |
540 |
NS_RELEASE(trans); |
| 534 |
} |
541 |
} |
| 535 |
|
542 |
|
|
|
543 |
// close all half open tcp connections |
| 544 |
for (PRInt32 i = ((PRInt32) ent->mHalfOpens.Length()) - 1; i >= 0; i--) |
| 545 |
ent->mHalfOpens[i]->Abandon(); |
| 546 |
|
| 536 |
delete ent; |
547 |
delete ent; |
| 537 |
return kHashEnumerateRemove; |
548 |
return kHashEnumerateRemove; |
| 538 |
} |
549 |
} |
| 539 |
|
550 |
|
| 540 |
//----------------------------------------------------------------------------- |
551 |
//----------------------------------------------------------------------------- |
| 541 |
|
552 |
|
| 542 |
PRBool |
553 |
PRBool |
| 543 |
nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent) |
554 |
nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent) |
|
Lines 547-563
nsHttpConnectionMgr::ProcessPendingQForE
|
Link Here
|
|---|
|
| 547 |
|
558 |
|
| 548 |
PRInt32 i, count = ent->mPendingQ.Length(); |
559 |
PRInt32 i, count = ent->mPendingQ.Length(); |
| 549 |
if (count > 0) { |
560 |
if (count > 0) { |
| 550 |
LOG((" pending-count=%u\n", count)); |
561 |
LOG((" pending-count=%u\n", count)); |
| 551 |
nsHttpTransaction *trans = nsnull; |
562 |
nsHttpTransaction *trans = nsnull; |
| 552 |
nsHttpConnection *conn = nsnull; |
563 |
nsHttpConnection *conn = nsnull; |
| 553 |
for (i=0; i<count; ++i) { |
564 |
for (i=0; i<count; ++i) { |
| 554 |
trans = ent->mPendingQ[i]; |
565 |
trans = ent->mPendingQ[i]; |
| 555 |
GetConnection(ent, trans->Caps(), &conn); |
566 |
GetConnection(ent, trans, &conn); |
| 556 |
if (conn) |
567 |
if (conn) |
| 557 |
break; |
568 |
break; |
| 558 |
} |
569 |
} |
| 559 |
if (conn) { |
570 |
if (conn) { |
| 560 |
LOG((" dispatching pending transaction...\n")); |
571 |
LOG((" dispatching pending transaction...\n")); |
| 561 |
|
572 |
|
| 562 |
// remove pending transaction |
573 |
// remove pending transaction |
| 563 |
ent->mPendingQ.RemoveElementAt(i); |
574 |
ent->mPendingQ.RemoveElementAt(i); |
|
Lines 587-604
nsHttpConnectionMgr::ProcessPendingQForE
|
Link Here
|
|---|
|
| 587 |
PRBool |
598 |
PRBool |
| 588 |
nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps) |
599 |
nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps) |
| 589 |
{ |
600 |
{ |
| 590 |
nsHttpConnectionInfo *ci = ent->mConnInfo; |
601 |
nsHttpConnectionInfo *ci = ent->mConnInfo; |
| 591 |
|
602 |
|
| 592 |
LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n", |
603 |
LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n", |
| 593 |
ci->HashKey().get(), caps)); |
604 |
ci->HashKey().get(), caps)); |
| 594 |
|
605 |
|
| 595 |
// If we have more active connections than the limit, then we're done -- |
606 |
// If there are more active connections than the global limit, then we're |
| 596 |
// purging idle connections won't get us below it. |
607 |
// done. Purging idle connections won't get us below it. |
| 597 |
if (mNumActiveConns >= mMaxConns) { |
608 |
if (mNumActiveConns >= mMaxConns) { |
| 598 |
LOG((" num active conns == max conns\n")); |
609 |
LOG((" num active conns == max conns\n")); |
| 599 |
return PR_TRUE; |
610 |
return PR_TRUE; |
| 600 |
} |
611 |
} |
| 601 |
|
612 |
|
| 602 |
nsHttpConnection *conn; |
613 |
nsHttpConnection *conn; |
| 603 |
PRInt32 i, totalCount, persistCount = 0; |
614 |
PRInt32 i, totalCount, persistCount = 0; |
| 604 |
|
615 |
|
|
Lines 606-621
nsHttpConnectionMgr::AtActiveConnectionL
|
Link Here
|
|---|
|
| 606 |
|
617 |
|
| 607 |
// count the number of persistent connections |
618 |
// count the number of persistent connections |
| 608 |
for (i=0; i<totalCount; ++i) { |
619 |
for (i=0; i<totalCount; ++i) { |
| 609 |
conn = ent->mActiveConns[i]; |
620 |
conn = ent->mActiveConns[i]; |
| 610 |
if (conn->IsKeepAlive()) // XXX make sure this is thread-safe |
621 |
if (conn->IsKeepAlive()) // XXX make sure this is thread-safe |
| 611 |
persistCount++; |
622 |
persistCount++; |
| 612 |
} |
623 |
} |
| 613 |
|
624 |
|
|
|
625 |
// Add in the in-progress tcp connections, we will assume they are |
| 626 |
// keepalive enabled. |
| 627 |
totalCount += ent->mHalfOpens.Length(); |
| 628 |
persistCount += ent->mHalfOpens.Length(); |
| 629 |
|
| 614 |
LOG((" total=%d, persist=%d\n", totalCount, persistCount)); |
630 |
LOG((" total=%d, persist=%d\n", totalCount, persistCount)); |
| 615 |
|
631 |
|
| 616 |
PRUint16 maxConns; |
632 |
PRUint16 maxConns; |
| 617 |
PRUint16 maxPersistConns; |
633 |
PRUint16 maxPersistConns; |
| 618 |
|
634 |
|
| 619 |
if (ci->UsingHttpProxy() && !ci->UsingSSL()) { |
635 |
if (ci->UsingHttpProxy() && !ci->UsingSSL()) { |
| 620 |
maxConns = mMaxConnsPerProxy; |
636 |
maxConns = mMaxConnsPerProxy; |
| 621 |
maxPersistConns = mMaxPersistConnsPerProxy; |
637 |
maxPersistConns = mMaxPersistConnsPerProxy; |
|
Lines 626-653
nsHttpConnectionMgr::AtActiveConnectionL
|
Link Here
|
|---|
|
| 626 |
} |
642 |
} |
| 627 |
|
643 |
|
| 628 |
// use >= just to be safe |
644 |
// use >= just to be safe |
| 629 |
return (totalCount >= maxConns) || ( (caps & NS_HTTP_ALLOW_KEEPALIVE) && |
645 |
return (totalCount >= maxConns) || ( (caps & NS_HTTP_ALLOW_KEEPALIVE) && |
| 630 |
(persistCount >= maxPersistConns) ); |
646 |
(persistCount >= maxPersistConns) ); |
| 631 |
} |
647 |
} |
| 632 |
|
648 |
|
| 633 |
void |
649 |
void |
| 634 |
nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps, |
650 |
nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, |
|
|
651 |
nsHttpTransaction *trans, |
| 635 |
nsHttpConnection **result) |
652 |
nsHttpConnection **result) |
| 636 |
{ |
653 |
{ |
| 637 |
LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n", |
654 |
LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n", |
| 638 |
ent->mConnInfo->HashKey().get(), PRUint32(caps))); |
655 |
ent->mConnInfo->HashKey().get(), PRUint32(trans->Caps()))); |
|
|
656 |
|
| 657 |
// First, see if an idle persistent connection may be reused instead of |
| 658 |
// establishing a new socket. We do not need to check the connection limits |
| 659 |
// yet as they govern the maximum number of open connections and reusing |
| 660 |
// an old connection never increases that. |
| 639 |
|
661 |
|
| 640 |
*result = nsnull; |
662 |
*result = nsnull; |
| 641 |
|
663 |
|
| 642 |
nsHttpConnection *conn = nsnull; |
664 |
nsHttpConnection *conn = nsnull; |
| 643 |
|
665 |
|
| 644 |
if (caps & NS_HTTP_ALLOW_KEEPALIVE) { |
666 |
if (trans->Caps() & NS_HTTP_ALLOW_KEEPALIVE) { |
| 645 |
// search the idle connection list |
667 |
// search the idle connection list. Each element in the list |
|
|
668 |
// has a reference, so if we remove it from the list into a local |
| 669 |
// ptr, that ptr now owns the reference |
| 646 |
while (!conn && (ent->mIdleConns.Length() > 0)) { |
670 |
while (!conn && (ent->mIdleConns.Length() > 0)) { |
| 647 |
conn = ent->mIdleConns[0]; |
671 |
conn = ent->mIdleConns[0]; |
| 648 |
// we check if the connection can be reused before even checking if |
672 |
// we check if the connection can be reused before even checking if |
| 649 |
// it is a "matching" connection. |
673 |
// it is a "matching" connection. |
| 650 |
if (!conn->CanReuse()) { |
674 |
if (!conn->CanReuse()) { |
| 651 |
LOG((" dropping stale connection: [conn=%x]\n", conn)); |
675 |
LOG((" dropping stale connection: [conn=%x]\n", conn)); |
| 652 |
conn->Close(NS_ERROR_ABORT); |
676 |
conn->Close(NS_ERROR_ABORT); |
| 653 |
NS_RELEASE(conn); |
677 |
NS_RELEASE(conn); |
|
Lines 667-707
nsHttpConnectionMgr::GetConnection(nsCon
|
Link Here
|
|---|
|
| 667 |
if (!conn) { |
691 |
if (!conn) { |
| 668 |
// Check if we need to purge an idle connection. Note that we may have |
692 |
// Check if we need to purge an idle connection. Note that we may have |
| 669 |
// removed one above; if so, this will be a no-op. We do this before |
693 |
// removed one above; if so, this will be a no-op. We do this before |
| 670 |
// checking the active connection limit to catch the case where we do |
694 |
// checking the active connection limit to catch the case where we do |
| 671 |
// have an idle connection, but the purge timer hasn't fired yet. |
695 |
// have an idle connection, but the purge timer hasn't fired yet. |
| 672 |
// XXX this just purges a random idle connection. we should instead |
696 |
// XXX this just purges a random idle connection. we should instead |
| 673 |
// enumerate the entire hash table to find the eldest idle connection. |
697 |
// enumerate the entire hash table to find the eldest idle connection. |
| 674 |
if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns) |
698 |
if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns) |
| 675 |
mCT.Enumerate(PurgeOneIdleConnectionCB, this); |
699 |
mCT.Enumerate(PurgeExcessIdleConnectionsCB, this); |
| 676 |
|
700 |
|
| 677 |
// Need to make a new TCP connection. First, we check if we've hit |
701 |
// Need to make a new TCP connection. First, we check if we've hit |
| 678 |
// either the maximum connection limit globally or for this particular |
702 |
// either the maximum connection limit globally or for this particular |
| 679 |
// host or proxy. If we have, we're done. |
703 |
// host or proxy. If we have, we're done. |
| 680 |
if (AtActiveConnectionLimit(ent, caps)) { |
704 |
if (AtActiveConnectionLimit(ent, trans->Caps())) { |
| 681 |
LOG((" at active connection limit!\n")); |
705 |
LOG(("nsHttpConnectionMgr::GetConnection [ci = %s]" |
|
|
706 |
"at active connection limit - will queue\n", |
| 707 |
ent->mConnInfo->HashKey().get())); |
| 682 |
return; |
708 |
return; |
| 683 |
} |
709 |
} |
| 684 |
|
710 |
|
| 685 |
conn = new nsHttpConnection(); |
711 |
nsresult rv = CreateTransport(ent, trans); |
| 686 |
if (!conn) |
712 |
if (NS_FAILED(rv)) |
| 687 |
return; |
713 |
trans->Close(rv); |
| 688 |
NS_ADDREF(conn); |
714 |
return; |
| 689 |
|
|
|
| 690 |
nsresult rv = conn->Init(ent->mConnInfo, mMaxRequestDelay); |
| 691 |
if (NS_FAILED(rv)) { |
| 692 |
NS_RELEASE(conn); |
| 693 |
return; |
| 694 |
} |
| 695 |
} |
715 |
} |
| 696 |
|
716 |
|
|
|
717 |
// hold an owning ref to this connection |
| 718 |
ent->mActiveConns.AppendElement(conn); |
| 719 |
mNumActiveConns++; |
| 720 |
NS_ADDREF(conn); |
| 721 |
|
| 697 |
*result = conn; |
722 |
*result = conn; |
| 698 |
} |
723 |
} |
| 699 |
|
724 |
|
|
|
725 |
void |
| 726 |
nsHttpConnectionMgr::AddActiveConn(nsHttpConnection *conn, |
| 727 |
nsConnectionEntry *ent) |
| 728 |
{ |
| 729 |
NS_ADDREF(conn); |
| 730 |
ent->mActiveConns.AppendElement(conn); |
| 731 |
mNumActiveConns++; |
| 732 |
} |
| 733 |
|
| 734 |
void |
| 735 |
nsHttpConnectionMgr::StartedConnect() |
| 736 |
{ |
| 737 |
mNumActiveConns++; |
| 738 |
} |
| 739 |
|
| 740 |
void |
| 741 |
nsHttpConnectionMgr::RecvdConnect() |
| 742 |
{ |
| 743 |
mNumActiveConns--; |
| 744 |
} |
| 745 |
|
| 746 |
nsresult |
| 747 |
nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent, |
| 748 |
nsHttpTransaction *trans) |
| 749 |
{ |
| 750 |
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread"); |
| 751 |
|
| 752 |
nsRefPtr<nsHalfOpenSocket> sock = new nsHalfOpenSocket(ent, trans); |
| 753 |
nsresult rv = sock->SetupPrimaryStreams(); |
| 754 |
NS_ENSURE_SUCCESS(rv, rv); |
| 755 |
|
| 756 |
sock->SetupBackupTimer(); |
| 757 |
ent->mHalfOpens.AppendElement(sock); |
| 758 |
return NS_OK; |
| 759 |
} |
| 760 |
|
| 700 |
nsresult |
761 |
nsresult |
| 701 |
nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, |
762 |
nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, |
| 702 |
nsAHttpTransaction *trans, |
763 |
nsAHttpTransaction *trans, |
| 703 |
PRUint8 caps, |
764 |
PRUint8 caps, |
| 704 |
nsHttpConnection *conn) |
765 |
nsHttpConnection *conn) |
| 705 |
{ |
766 |
{ |
| 706 |
LOG(("nsHttpConnectionMgr::DispatchTransaction [ci=%s trans=%x caps=%x conn=%x]\n", |
767 |
LOG(("nsHttpConnectionMgr::DispatchTransaction [ci=%s trans=%x caps=%x conn=%x]\n", |
| 707 |
ent->mConnInfo->HashKey().get(), trans, caps, conn)); |
768 |
ent->mConnInfo->HashKey().get(), trans, caps, conn)); |
|
Lines 713-733
nsHttpConnectionMgr::DispatchTransaction
|
Link Here
|
|---|
|
| 713 |
|
774 |
|
| 714 |
nsHttpPipeline *pipeline = nsnull; |
775 |
nsHttpPipeline *pipeline = nsnull; |
| 715 |
if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) { |
776 |
if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) { |
| 716 |
LOG((" looking to build pipeline...\n")); |
777 |
LOG((" looking to build pipeline...\n")); |
| 717 |
if (BuildPipeline(ent, trans, &pipeline)) |
778 |
if (BuildPipeline(ent, trans, &pipeline)) |
| 718 |
trans = pipeline; |
779 |
trans = pipeline; |
| 719 |
} |
780 |
} |
| 720 |
|
781 |
|
| 721 |
// hold an owning ref to this connection |
|
|
| 722 |
ent->mActiveConns.AppendElement(conn); |
| 723 |
mNumActiveConns++; |
| 724 |
NS_ADDREF(conn); |
| 725 |
|
| 726 |
// give the transaction the indirect reference to the connection. |
782 |
// give the transaction the indirect reference to the connection. |
| 727 |
trans->SetConnection(handle); |
783 |
trans->SetConnection(handle); |
| 728 |
|
784 |
|
| 729 |
nsresult rv = conn->Activate(trans, caps); |
785 |
nsresult rv = conn->Activate(trans, caps); |
| 730 |
|
786 |
|
| 731 |
if (NS_FAILED(rv)) { |
787 |
if (NS_FAILED(rv)) { |
| 732 |
LOG((" conn->Activate failed [rv=%x]\n", rv)); |
788 |
LOG((" conn->Activate failed [rv=%x]\n", rv)); |
| 733 |
ent->mActiveConns.RemoveElement(conn); |
789 |
ent->mActiveConns.RemoveElement(conn); |
|
Lines 790-805
nsHttpConnectionMgr::BuildPipeline(nsCon
|
Link Here
|
|---|
|
| 790 |
LOG((" pipelined %u transactions\n", numAdded)); |
846 |
LOG((" pipelined %u transactions\n", numAdded)); |
| 791 |
NS_ADDREF(*result = pipeline); |
847 |
NS_ADDREF(*result = pipeline); |
| 792 |
return PR_TRUE; |
848 |
return PR_TRUE; |
| 793 |
} |
849 |
} |
| 794 |
|
850 |
|
| 795 |
nsresult |
851 |
nsresult |
| 796 |
nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) |
852 |
nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) |
| 797 |
{ |
853 |
{ |
|
|
854 |
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread"); |
| 855 |
|
| 798 |
// since "adds" and "cancels" are processed asynchronously and because |
856 |
// since "adds" and "cancels" are processed asynchronously and because |
| 799 |
// various events might trigger an "add" directly on the socket thread, |
857 |
// various events might trigger an "add" directly on the socket thread, |
| 800 |
// we must take care to avoid dispatching a transaction that has already |
858 |
// we must take care to avoid dispatching a transaction that has already |
| 801 |
// been canceled (see bug 190001). |
859 |
// been canceled (see bug 190001). |
| 802 |
if (NS_FAILED(trans->Status())) { |
860 |
if (NS_FAILED(trans->Status())) { |
| 803 |
LOG((" transaction was canceled... dropping event!\n")); |
861 |
LOG((" transaction was canceled... dropping event!\n")); |
| 804 |
return NS_OK; |
862 |
return NS_OK; |
| 805 |
} |
863 |
} |
|
Lines 832-859
nsHttpConnectionMgr::ProcessNewTransacti
|
Link Here
|
|---|
|
| 832 |
|
890 |
|
| 833 |
// steal reference from connection handle. |
891 |
// steal reference from connection handle. |
| 834 |
// XXX prevent SetConnection(nsnull) from calling ReclaimConnection |
892 |
// XXX prevent SetConnection(nsnull) from calling ReclaimConnection |
| 835 |
conn = handle->mConn; |
893 |
conn = handle->mConn; |
| 836 |
handle->mConn = nsnull; |
894 |
handle->mConn = nsnull; |
| 837 |
|
895 |
|
| 838 |
// destroy connection handle. |
896 |
// destroy connection handle. |
| 839 |
trans->SetConnection(nsnull); |
897 |
trans->SetConnection(nsnull); |
| 840 |
|
|
|
| 841 |
// remove sticky connection from active connection list; we'll add it |
| 842 |
// right back in DispatchTransaction. |
| 843 |
if (ent->mActiveConns.RemoveElement(conn)) |
| 844 |
mNumActiveConns--; |
| 845 |
else { |
| 846 |
NS_ERROR("sticky connection not found in active list"); |
| 847 |
return NS_ERROR_UNEXPECTED; |
| 848 |
} |
| 849 |
} |
898 |
} |
| 850 |
else |
899 |
else |
| 851 |
GetConnection(ent, caps, &conn); |
900 |
GetConnection(ent, trans, &conn); |
| 852 |
|
901 |
|
| 853 |
nsresult rv; |
902 |
nsresult rv; |
| 854 |
if (!conn) { |
903 |
if (!conn) { |
| 855 |
LOG((" adding transaction to pending queue [trans=%x pending-count=%u]\n", |
904 |
LOG((" adding transaction to pending queue [trans=%x pending-count=%u]\n", |
| 856 |
trans, ent->mPendingQ.Length()+1)); |
905 |
trans, ent->mPendingQ.Length()+1)); |
| 857 |
// put this transaction on the pending queue... |
906 |
// put this transaction on the pending queue... |
| 858 |
InsertTransactionSorted(ent->mPendingQ, trans); |
907 |
InsertTransactionSorted(ent->mPendingQ, trans); |
| 859 |
NS_ADDREF(trans); |
908 |
NS_ADDREF(trans); |
|
Lines 993-1030
nsHttpConnectionMgr::OnMsgReclaimConnect
|
Link Here
|
|---|
|
| 993 |
nsHttpConnectionInfo *ci = conn->ConnectionInfo(); |
1042 |
nsHttpConnectionInfo *ci = conn->ConnectionInfo(); |
| 994 |
NS_ADDREF(ci); |
1043 |
NS_ADDREF(ci); |
| 995 |
|
1044 |
|
| 996 |
nsCStringKey key(ci->HashKey()); |
1045 |
nsCStringKey key(ci->HashKey()); |
| 997 |
nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key); |
1046 |
nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key); |
| 998 |
|
1047 |
|
| 999 |
NS_ASSERTION(ent, "no connection entry"); |
1048 |
NS_ASSERTION(ent, "no connection entry"); |
| 1000 |
if (ent) { |
1049 |
if (ent) { |
| 1001 |
ent->mActiveConns.RemoveElement(conn); |
1050 |
// If the connection is in the active list, remove that entry |
| 1002 |
mNumActiveConns--; |
1051 |
// and the reference held by the mActiveConns list. |
|
|
1052 |
// This is never the final reference on conn as the event context |
| 1053 |
// is also holding one that is released at the end of this function. |
| 1054 |
if (ent->mActiveConns.RemoveElement(conn)) { |
| 1055 |
nsHttpConnection *temp = conn; |
| 1056 |
NS_RELEASE(temp); |
| 1057 |
mNumActiveConns--; |
| 1058 |
} |
| 1059 |
|
| 1003 |
if (conn->CanReuse()) { |
1060 |
if (conn->CanReuse()) { |
| 1004 |
LOG((" adding connection to idle list\n")); |
1061 |
LOG((" adding connection to idle list\n")); |
| 1005 |
// hold onto this connection in the idle list. we push it to |
1062 |
// hold onto this connection in the idle list. we push it to |
| 1006 |
// the end of the list so as to ensure that we'll visit older |
1063 |
// the end of the list so as to ensure that we'll visit older |
| 1007 |
// connections first before getting to this one. |
1064 |
// connections first before getting to this one. |
|
|
1065 |
NS_ADDREF(conn); |
| 1008 |
ent->mIdleConns.AppendElement(conn); |
1066 |
ent->mIdleConns.AppendElement(conn); |
| 1009 |
mNumIdleConns++; |
1067 |
mNumIdleConns++; |
| 1010 |
// If the added connection was first idle connection or has shortest |
1068 |
// If the added connection was first idle connection or has shortest |
| 1011 |
// time to live among the idle connections, pruning dead |
1069 |
// time to live among the idle connections, pruning dead |
| 1012 |
// connections needs to be done when it can't be reused anymore. |
1070 |
// connections needs to be done when it can't be reused anymore. |
| 1013 |
PRUint32 timeToLive = conn->TimeToLive(); |
1071 |
PRUint32 timeToLive = conn->TimeToLive(); |
| 1014 |
if(!mTimer || NowInSeconds() + timeToLive < mTimeOfNextWakeUp) |
1072 |
if(!mTimer || NowInSeconds() + timeToLive < mTimeOfNextWakeUp) |
| 1015 |
PruneDeadConnectionsAfter(timeToLive); |
1073 |
PruneDeadConnectionsAfter(timeToLive); |
| 1016 |
} |
1074 |
} |
| 1017 |
else { |
1075 |
else { |
| 1018 |
LOG((" connection cannot be reused; closing connection\n")); |
1076 |
LOG((" connection cannot be reused; closing connection\n")); |
| 1019 |
// make sure the connection is closed and release our reference. |
1077 |
// make sure the connection is closed and release our reference. |
| 1020 |
conn->Close(NS_ERROR_ABORT); |
1078 |
conn->Close(NS_ERROR_ABORT); |
| 1021 |
nsHttpConnection *temp = conn; |
|
|
| 1022 |
NS_RELEASE(temp); |
| 1023 |
} |
1079 |
} |
| 1024 |
} |
1080 |
} |
| 1025 |
|
1081 |
|
| 1026 |
OnMsgProcessPendingQ(NS_OK, ci); // releases |ci| |
1082 |
OnMsgProcessPendingQ(NS_OK, ci); // releases |ci| |
| 1027 |
NS_RELEASE(conn); |
1083 |
NS_RELEASE(conn); |
| 1028 |
} |
1084 |
} |
| 1029 |
|
1085 |
|
| 1030 |
void |
1086 |
void |
|
Lines 1125-1140
nsHttpConnectionMgr::nsConnectionHandle:
|
Link Here
|
|---|
|
| 1125 |
} |
1181 |
} |
| 1126 |
|
1182 |
|
| 1127 |
nsresult |
1183 |
nsresult |
| 1128 |
nsHttpConnectionMgr::nsConnectionHandle::PushBack(const char *buf, PRUint32 bufLen) |
1184 |
nsHttpConnectionMgr::nsConnectionHandle::PushBack(const char *buf, PRUint32 bufLen) |
| 1129 |
{ |
1185 |
{ |
| 1130 |
return mConn->PushBack(buf, bufLen); |
1186 |
return mConn->PushBack(buf, bufLen); |
| 1131 |
} |
1187 |
} |
| 1132 |
|
1188 |
|
|
|
1189 |
|
| 1190 |
//////////////////////// nsHalfOpenSocket |
| 1191 |
|
| 1192 |
|
| 1193 |
NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpConnectionMgr::nsHalfOpenSocket, |
| 1194 |
nsIOutputStreamCallback, |
| 1195 |
nsITransportEventSink, |
| 1196 |
nsIInterfaceRequestor, |
| 1197 |
nsITimerCallback) |
| 1198 |
|
| 1199 |
nsHttpConnectionMgr:: |
| 1200 |
nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent, |
| 1201 |
nsHttpTransaction *trans) |
| 1202 |
: mEnt(ent), |
| 1203 |
mTransaction(trans) |
| 1204 |
{ |
| 1205 |
NS_ABORT_IF_FALSE(ent && trans, "constructor with null arguments"); |
| 1206 |
LOG(("Creating nsHalfOpenSocket [this=%p trans=%p ent=%s]\n", |
| 1207 |
this, trans, ent->mConnInfo->Host())); |
| 1208 |
} |
| 1209 |
|
| 1210 |
nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket() |
| 1211 |
{ |
| 1212 |
NS_ABORT_IF_FALSE(!mStreamOut, "streamout not null"); |
| 1213 |
NS_ABORT_IF_FALSE(!mBackupStreamOut, "backupstreamout not null"); |
| 1214 |
NS_ABORT_IF_FALSE(!mSynTimer, "syntimer not null"); |
| 1215 |
LOG(("Destroying nsHalfOpenSocket [this=%p]\n", this)); |
| 1216 |
|
| 1217 |
if (mEnt) { |
| 1218 |
PRInt32 index = mEnt->mHalfOpens.IndexOf(this); |
| 1219 |
NS_ABORT_IF_FALSE(index != -1, "half open complete but no item"); |
| 1220 |
mEnt->mHalfOpens.RemoveElementAt(index); |
| 1221 |
} |
| 1222 |
} |
| 1223 |
|
| 1224 |
nsresult |
| 1225 |
nsHttpConnectionMgr:: |
| 1226 |
nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, |
| 1227 |
nsIAsyncInputStream **instream, |
| 1228 |
nsIAsyncOutputStream **outstream) |
| 1229 |
{ |
| 1230 |
nsresult rv; |
| 1231 |
|
| 1232 |
const char* types[1]; |
| 1233 |
types[0] = (mEnt->mConnInfo->UsingSSL()) ? |
| 1234 |
"ssl" : gHttpHandler->DefaultSocketType(); |
| 1235 |
PRUint32 typeCount = (types[0] != nsnull); |
| 1236 |
|
| 1237 |
nsCOMPtr<nsISocketTransport> socketTransport; |
| 1238 |
nsCOMPtr<nsISocketTransportService> sts; |
| 1239 |
|
| 1240 |
sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); |
| 1241 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1242 |
|
| 1243 |
rv = sts->CreateTransport(types, typeCount, |
| 1244 |
nsDependentCString(mEnt->mConnInfo->Host()), |
| 1245 |
mEnt->mConnInfo->Port(), |
| 1246 |
mEnt->mConnInfo->ProxyInfo(), |
| 1247 |
getter_AddRefs(socketTransport)); |
| 1248 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1249 |
|
| 1250 |
PRUint32 tmpFlags = 0; |
| 1251 |
if (mTransaction->Caps() & NS_HTTP_REFRESH_DNS) |
| 1252 |
tmpFlags = nsISocketTransport::BYPASS_CACHE; |
| 1253 |
|
| 1254 |
if (mTransaction->Caps() & NS_HTTP_LOAD_ANONYMOUS) |
| 1255 |
tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT; |
| 1256 |
|
| 1257 |
socketTransport->SetConnectionFlags(tmpFlags); |
| 1258 |
|
| 1259 |
socketTransport->SetQoSBits(gHttpHandler->GetQoSBits()); |
| 1260 |
|
| 1261 |
rv = socketTransport->SetEventSink(this, nsnull); |
| 1262 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1263 |
|
| 1264 |
rv = socketTransport->SetSecurityCallbacks(this); |
| 1265 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1266 |
|
| 1267 |
nsCOMPtr<nsIOutputStream> sout; |
| 1268 |
rv = socketTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, |
| 1269 |
0, 0, |
| 1270 |
getter_AddRefs(sout)); |
| 1271 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1272 |
|
| 1273 |
nsCOMPtr<nsIInputStream> sin; |
| 1274 |
rv = socketTransport->OpenInputStream(nsITransport::OPEN_UNBUFFERED, |
| 1275 |
0, 0, |
| 1276 |
getter_AddRefs(sin)); |
| 1277 |
NS_ENSURE_SUCCESS(rv, rv); |
| 1278 |
|
| 1279 |
socketTransport.forget(transport); |
| 1280 |
CallQueryInterface(sin, instream); |
| 1281 |
CallQueryInterface(sout, outstream); |
| 1282 |
|
| 1283 |
rv = (*outstream)->AsyncWait(this, 0, 0, nsnull); |
| 1284 |
if (NS_SUCCEEDED(rv)) |
| 1285 |
gHttpHandler->ConnMgr()->StartedConnect(); |
| 1286 |
|
| 1287 |
return rv; |
| 1288 |
} |
| 1289 |
|
| 1290 |
nsresult |
| 1291 |
nsHttpConnectionMgr::nsHalfOpenSocket::SetupPrimaryStreams() |
| 1292 |
{ |
| 1293 |
nsresult rv = SetupStreams(getter_AddRefs(mSocketTransport), |
| 1294 |
getter_AddRefs(mStreamIn), |
| 1295 |
getter_AddRefs(mStreamOut)); |
| 1296 |
LOG(("nsHalfOpenSocket::SetupPrimaryStream [this=%p ent=%s rv=%x]", |
| 1297 |
this, mEnt->mConnInfo->Host(), rv)); |
| 1298 |
if (NS_FAILED(rv)) { |
| 1299 |
if (mStreamOut) |
| 1300 |
mStreamOut->AsyncWait(nsnull, 0, 0, nsnull); |
| 1301 |
mStreamOut = nsnull; |
| 1302 |
mStreamIn = nsnull; |
| 1303 |
mSocketTransport = nsnull; |
| 1304 |
} |
| 1305 |
return rv; |
| 1306 |
} |
| 1307 |
|
| 1308 |
nsresult |
| 1309 |
nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupStreams() |
| 1310 |
{ |
| 1311 |
nsresult rv = SetupStreams(getter_AddRefs(mBackupTransport), |
| 1312 |
getter_AddRefs(mBackupStreamIn), |
| 1313 |
getter_AddRefs(mBackupStreamOut)); |
| 1314 |
LOG(("nsHalfOpenSocket::SetupBackupStream [this=%p ent=%s rv=%x]", |
| 1315 |
this, mEnt->mConnInfo->Host(), rv)); |
| 1316 |
if (NS_FAILED(rv)) { |
| 1317 |
if (mBackupStreamOut) |
| 1318 |
mBackupStreamOut->AsyncWait(nsnull, 0, 0, nsnull); |
| 1319 |
mBackupStreamOut = nsnull; |
| 1320 |
mBackupStreamIn = nsnull; |
| 1321 |
mBackupTransport = nsnull; |
| 1322 |
} |
| 1323 |
return rv; |
| 1324 |
} |
| 1325 |
|
| 1326 |
void |
| 1327 |
nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupTimer() |
| 1328 |
{ |
| 1329 |
PRUint16 timeout = gHttpHandler->GetIdleSynTimeout(); |
| 1330 |
NS_ABORT_IF_FALSE(!mSynTimer, "timer already initd"); |
| 1331 |
if (timeout) { |
| 1332 |
// Setup the timer that will establish a backup socket |
| 1333 |
// if we do not get a writable event on the main one. |
| 1334 |
// We do this because a lost SYN takes a very long time |
| 1335 |
// to repair at the TCP level. |
| 1336 |
// |
| 1337 |
// Failure to setup the timer is something we can live with, |
| 1338 |
// so don't return an error in that case. |
| 1339 |
nsresult rv; |
| 1340 |
mSynTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); |
| 1341 |
if (NS_SUCCEEDED(rv)) |
| 1342 |
mSynTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT); |
| 1343 |
} |
| 1344 |
} |
| 1345 |
|
| 1346 |
void |
| 1347 |
nsHttpConnectionMgr::nsHalfOpenSocket::Abandon() |
| 1348 |
{ |
| 1349 |
LOG(("nsHalfOpenSocket::Abandon [this=%p ent=%s]", |
| 1350 |
this, mEnt->mConnInfo->Host())); |
| 1351 |
nsRefPtr<nsHalfOpenSocket> deleteProtector(this); |
| 1352 |
|
| 1353 |
if (mStreamOut) { |
| 1354 |
gHttpHandler->ConnMgr()->RecvdConnect(); |
| 1355 |
mStreamOut->AsyncWait(nsnull, 0, 0, nsnull); |
| 1356 |
mStreamOut = nsnull; |
| 1357 |
} |
| 1358 |
if (mBackupStreamOut) { |
| 1359 |
gHttpHandler->ConnMgr()->RecvdConnect(); |
| 1360 |
mBackupStreamOut->AsyncWait(nsnull, 0, 0, nsnull); |
| 1361 |
mBackupStreamOut = nsnull; |
| 1362 |
} |
| 1363 |
if (mSynTimer) { |
| 1364 |
mSynTimer->Cancel(); |
| 1365 |
mSynTimer = nsnull; |
| 1366 |
} |
| 1367 |
|
| 1368 |
mEnt = nsnull; |
| 1369 |
} |
| 1370 |
|
| 1371 |
NS_IMETHODIMP // method for nsITimerCallback |
| 1372 |
nsHttpConnectionMgr::nsHalfOpenSocket::Notify(nsITimer *timer) |
| 1373 |
{ |
| 1374 |
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread"); |
| 1375 |
NS_ABORT_IF_FALSE(timer == mSynTimer, "wrong timer"); |
| 1376 |
|
| 1377 |
mSynTimer = nsnull; |
| 1378 |
if (!gHttpHandler->ConnMgr()-> |
| 1379 |
AtActiveConnectionLimit(mEnt, mTransaction->Caps())) { |
| 1380 |
SetupBackupStreams(); |
| 1381 |
} |
| 1382 |
return NS_OK; |
| 1383 |
} |
| 1384 |
|
| 1385 |
// method for nsIAsyncOutputStreamCallback |
| 1386 |
NS_IMETHODIMP |
| 1387 |
nsHttpConnectionMgr:: |
| 1388 |
nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) |
| 1389 |
{ |
| 1390 |
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread"); |
| 1391 |
NS_ABORT_IF_FALSE(out == mStreamOut || |
| 1392 |
out == mBackupStreamOut, "stream mismatch"); |
| 1393 |
LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n", |
| 1394 |
this, mEnt->mConnInfo->Host(), |
| 1395 |
out == mStreamOut ? "primary" : "backup")); |
| 1396 |
PRInt32 index; |
| 1397 |
nsresult rv; |
| 1398 |
|
| 1399 |
gHttpHandler->ConnMgr()->RecvdConnect(); |
| 1400 |
|
| 1401 |
// If the syntimer is still armed, we can cancel it because no backup |
| 1402 |
// socket should be formed at this point |
| 1403 |
if (mSynTimer) { |
| 1404 |
NS_ABORT_IF_FALSE (out == mStreamOut, "timer for non existant stream"); |
| 1405 |
LOG(("nsHalfOpenSocket::OnOutputStreamReady " |
| 1406 |
"Backup connection timer canceled\n")); |
| 1407 |
mSynTimer->Cancel(); |
| 1408 |
mSynTimer = nsnull; |
| 1409 |
} |
| 1410 |
|
| 1411 |
// assign the new socket to the http connection |
| 1412 |
nsRefPtr<nsHttpConnection> conn = new nsHttpConnection(); |
| 1413 |
LOG(("nsHalfOpenSocket::OnOutputStreamReady " |
| 1414 |
"Created new nshttpconnection %p\n", conn)); |
| 1415 |
|
| 1416 |
nsCOMPtr<nsIInterfaceRequestor> callbacks; |
| 1417 |
nsCOMPtr<nsIEventTarget> callbackTarget; |
| 1418 |
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), |
| 1419 |
getter_AddRefs(callbackTarget)); |
| 1420 |
if (out == mStreamOut) { |
| 1421 |
rv = conn->Init(mEnt->mConnInfo, |
| 1422 |
gHttpHandler->ConnMgr()->mMaxRequestDelay, |
| 1423 |
mSocketTransport, mStreamIn, mStreamOut, |
| 1424 |
callbacks, callbackTarget); |
| 1425 |
|
| 1426 |
// The nsHttpConnection object now owns these streams and sockets |
| 1427 |
mStreamOut = nsnull; |
| 1428 |
mStreamIn = nsnull; |
| 1429 |
mSocketTransport = nsnull; |
| 1430 |
} |
| 1431 |
else { |
| 1432 |
rv = conn->Init(mEnt->mConnInfo, |
| 1433 |
gHttpHandler->ConnMgr()->mMaxRequestDelay, |
| 1434 |
mBackupTransport, mBackupStreamIn, mBackupStreamOut, |
| 1435 |
callbacks, callbackTarget); |
| 1436 |
|
| 1437 |
// The nsHttpConnection object now owns these streams and sockets |
| 1438 |
mBackupStreamOut = nsnull; |
| 1439 |
mBackupStreamIn = nsnull; |
| 1440 |
mBackupTransport = nsnull; |
| 1441 |
} |
| 1442 |
|
| 1443 |
if (NS_FAILED(rv)) { |
| 1444 |
LOG(("nsHalfOpenSocket::OnOutputStreamReady " |
| 1445 |
"conn->init (%p) failed %x\n", conn, rv)); |
| 1446 |
return rv; |
| 1447 |
} |
| 1448 |
|
| 1449 |
// if this is still in the pending list, remove it and dispatch it |
| 1450 |
index = mEnt->mPendingQ.IndexOf(mTransaction); |
| 1451 |
if (index != -1) { |
| 1452 |
mEnt->mPendingQ.RemoveElementAt(index); |
| 1453 |
nsHttpTransaction *temp = mTransaction; |
| 1454 |
NS_RELEASE(temp); |
| 1455 |
gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt); |
| 1456 |
rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, mTransaction, |
| 1457 |
mTransaction->Caps(), |
| 1458 |
conn); |
| 1459 |
} |
| 1460 |
else { |
| 1461 |
// this transaction was dispatched off the pending q before all the |
| 1462 |
// sockets established themselves. |
| 1463 |
|
| 1464 |
// We need to establish a small non-zero idle timeout so the connection |
| 1465 |
// mgr perceives this socket as suitable for persistent connection reuse |
| 1466 |
conn->SetIdleTimeout(NS_MIN((PRUint16) 5, gHttpHandler->IdleTimeout())); |
| 1467 |
|
| 1468 |
// After about 1 second allow for the possibility of restarting a |
| 1469 |
// transaction due to server close. Keep at sub 1 second as that is the |
| 1470 |
// minimum granularity we can expect a server to be timing out with. |
| 1471 |
conn->SetIsReusedAfter(950); |
| 1472 |
|
| 1473 |
NS_ADDREF(conn); // because onmsg*() expects to drop a reference |
| 1474 |
gHttpHandler->ConnMgr()->OnMsgReclaimConnection(NS_OK, conn); |
| 1475 |
} |
| 1476 |
|
| 1477 |
return rv; |
| 1478 |
} |
| 1479 |
|
| 1480 |
// method for nsITransportEventSink |
| 1481 |
NS_IMETHODIMP |
| 1482 |
nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans, |
| 1483 |
nsresult status, |
| 1484 |
PRUint64 progress, |
| 1485 |
PRUint64 progressMax) |
| 1486 |
{ |
| 1487 |
if (mTransaction) |
| 1488 |
mTransaction->OnTransportStatus(status, progress); |
| 1489 |
return NS_OK; |
| 1490 |
} |
| 1491 |
|
| 1492 |
// method for nsIInterfaceRequestor |
| 1493 |
NS_IMETHODIMP |
| 1494 |
nsHttpConnectionMgr::nsHalfOpenSocket::GetInterface(const nsIID &iid, |
| 1495 |
void **result) |
| 1496 |
{ |
| 1497 |
if (mTransaction) { |
| 1498 |
nsCOMPtr<nsIInterfaceRequestor> callbacks; |
| 1499 |
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), nsnull); |
| 1500 |
if (callbacks) |
| 1501 |
return callbacks->GetInterface(iid, result); |
| 1502 |
} |
| 1503 |
return NS_ERROR_NO_INTERFACE; |
| 1504 |
} |
| 1505 |
|
| 1133 |
PRBool |
1506 |
PRBool |
| 1134 |
nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent() |
1507 |
nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent() |
| 1135 |
{ |
1508 |
{ |
| 1136 |
return mConn->LastTransactionExpectedNoContent(); |
1509 |
return mConn->LastTransactionExpectedNoContent(); |
| 1137 |
} |
1510 |
} |
| 1138 |
|
1511 |
|
| 1139 |
void |
1512 |
void |
| 1140 |
nsHttpConnectionMgr:: |
1513 |
nsHttpConnectionMgr:: |