625 ret = KErrLocked; |
618 ret = KErrLocked; |
626 else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow)) |
619 else if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow)) |
627 iSockInBufSize = KTcpMinimumWindow; |
620 iSockInBufSize = KTcpMinimumWindow; |
628 else |
621 else |
629 { |
622 { |
630 //If its the startup case, then there should be no algorithm used to shrink |
623 |
631 //or expand the window size from the default value provided in the ini file |
624 //If new TCP window is larger then the previous window, increase the |
632 //the new value should be set directly |
625 //iSockInBufSize right now. TCP recv function takes care of |
633 if(iSocketStartupCase) |
626 //advertising a new effective TCP window. |
634 { |
627 if (intValue >= iSockInBufSize) |
635 //Add the extra window to free window pool |
628 { |
636 //if the window being set is greater than what is specified in ini file (startup case), then just overwrite the new window. |
629 //Make it Zero so TCP could avoid the |
637 //Add difference to free window |
630 //TCP window shrinking processing in Recv. |
638 //else set free window to zero |
631 iNewTcpWindow = 0; |
639 if(intValue > iSockInBufSize) |
632 //FreeWindow has to be increased at the same time. |
640 iFreeWindow += intValue - iSockInBufSize; |
633 iFreeWindow += intValue - iSockInBufSize; |
641 else |
634 // Make the new TCP receive buffer change effective now. |
642 iFreeWindow = 0; |
635 iSockInBufSize = intValue; |
643 //set the buffer |
636 } |
644 iSockInBufSize = intValue; |
637 else |
645 //disable startup flag. |
638 { |
646 iSocketStartupCase = EFalse; |
639 //This sets iNewTcpWindow to a non-zero value, which indicates |
647 } |
640 //to the TCP that window is shrunk and process TCP segments |
648 else |
641 //which are in air before setting a new TCP receive buffer. |
649 { |
642 //TCP Receive window starts moving only when TCP hidden window |
650 // Check for minimum value |
643 //size exceeds the size of the shrunk window. |
651 if (intValue < STATIC_CAST(TInt, KTcpMinimumWindow)) |
644 |
652 { |
645 iNewTcpWindow = intValue; |
653 intValue = STATIC_CAST(TInt, KTcpMinimumWindow); |
646 //Even in case of window shrink we can set the receive buffer size |
654 } |
647 //immediately. This will be helpful, for processing SYN-ACK and other |
655 // Handle the situation where the connection has been established and |
648 //receiver side processing. |
656 // window scaling is not in use |
649 //For already connected sockets iNewTcpWindow will be taking care |
657 if ( InState( ETcpSynReceived | ETcpEstablished ) && !iRcvWscale ) |
650 //of shrinking the window size for that TCP session. |
658 { |
651 iSockInBufSize = iNewTcpWindow; |
659 // Do not allow window sizes larger than 0xFFFF |
652 if( iAdvertisedWindow > iNewTcpWindow ) |
660 intValue = Min ( intValue, 0xFFFF ); |
653 { |
661 } |
654 iShrinkedWindowSize = iAdvertisedWindow - iNewTcpWindow; |
662 |
655 } |
663 // Check whether we are increasing or decreasing window size |
656 else |
664 if ( intValue >= iSockInBufSize ) |
657 { |
665 { |
658 // No Need to process TCP receive window processing. |
666 // New window is larger than current one, check if a |
659 iNewTcpWindow = 0; |
667 // shrinking process is active |
660 } |
668 if ( !iNewTcpWindow ) |
661 } |
669 { |
662 |
670 // Mark new "space" as free, it will be updated to |
663 } |
671 // peer on next operation. |
664 |
672 iFreeWindow += intValue - iSockInBufSize; |
|
673 } |
|
674 else |
|
675 { |
|
676 // In the middle of shrinking process. |
|
677 if ( iShrinkedWindowSize <= ( intValue - iSockInBufSize )) |
|
678 { |
|
679 // Increment to window size is enough to complete |
|
680 // shrinking process. Update variables and exit |
|
681 // from shrinking process. |
|
682 iFreeWindow = ( intValue - iSockInBufSize ) - iShrinkedWindowSize; |
|
683 iShrinkedWindowSize = 0; |
|
684 iNewTcpWindow = 0; |
|
685 } |
|
686 else |
|
687 { |
|
688 // Not quite there yet but closer. Less to shrink, |
|
689 // update this, but do not exit from shrinking |
|
690 // process |
|
691 iShrinkedWindowSize -= intValue - iSockInBufSize; |
|
692 iNewTcpWindow = intValue; |
|
693 } |
|
694 } |
|
695 } |
|
696 else |
|
697 { |
|
698 // Requested window is smaller than current one. Start or |
|
699 // continue shrinking process. RCV window can be occupied |
|
700 // for two different purpose at the moment |
|
701 // 1. Client data in iSockInQ not read by application |
|
702 // 2. Free window "opened" to peer (iAdvertisedWindow) |
|
703 // When shrinking, we must ensure that when reopening |
|
704 // the window to client there must be truly empty space |
|
705 // in the window. Thus, freeze the right edge of the |
|
706 // window (iRCV.NXT + iRCV.WND stays constant) until |
|
707 // shrinking is completed. |
|
708 |
|
709 if ( iNewTcpWindow ) |
|
710 { |
|
711 // There is an ongoing shrink process, add the |
|
712 // change to the amount to be shrinked |
|
713 iShrinkedWindowSize += iSockInBufSize - intValue; |
|
714 iNewTcpWindow = intValue; |
|
715 } |
|
716 else |
|
717 { |
|
718 // This is a new shrinking process, count how much |
|
719 // needs to be shrinked |
|
720 iShrinkedWindowSize = iSockInQLen + iRCV.WND; |
|
721 if ( iShrinkedWindowSize >= intValue ) |
|
722 { |
|
723 // We need to shrink since the currently occupied |
|
724 // window does not fit to new one |
|
725 iShrinkedWindowSize -= intValue; |
|
726 // There is now free space in the window |
|
727 iFreeWindow = 0; |
|
728 // iNewTcpWindow is used as a state variable for |
|
729 // shrinking |
|
730 iNewTcpWindow = intValue; |
|
731 } |
|
732 else |
|
733 { |
|
734 // No need to shrink since we can fit the current |
|
735 // contents to the new window, update free window |
|
736 // If TCP connection is not yet setup, the free |
|
737 // window will be updated on connection setup, |
|
738 // for existing connection it will be used |
|
739 // next time application reads data |
|
740 if ( iFreeWindow >= ( iSockInBufSize - intValue )) |
|
741 { |
|
742 iFreeWindow -= iSockInBufSize - intValue; |
|
743 } |
|
744 else |
|
745 { |
|
746 // Something wrong. Try to reevaluate... |
|
747 iFreeWindow = intValue - iShrinkedWindowSize; |
|
748 } |
|
749 iShrinkedWindowSize = 0; |
|
750 } |
|
751 } |
|
752 } |
|
753 // Even in case of window shrink we can set the receive buffer size |
|
754 // immediately. This will be helpful, for processing SYN-ACK and other |
|
755 // receiver side processing. |
|
756 // For already connected sockets iNewTcpWindow will be taking care |
|
757 // of shrinking the window size for that TCP session. |
|
758 iSockInBufSize = intValue; |
|
759 } |
|
760 } |
|
761 } |
665 } |
762 break; |
666 break; |
763 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
667 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
764 case KSoTcpRecvWinSize: |
668 case KSoTcpRecvWinSize: |
765 { |
669 { |
1471 //We need to make sure, that we will show that window is not shrinked |
1373 //We need to make sure, that we will show that window is not shrinked |
1472 //to the sender, so tha right edge of the sender window remains constant. |
1374 //to the sender, so tha right edge of the sender window remains constant. |
1473 //if This is true, then it is a case of TCP window shrink and we need |
1375 //if This is true, then it is a case of TCP window shrink and we need |
1474 //to handle it. |
1376 //to handle it. |
1475 if ( iNewTcpWindow ) |
1377 if ( iNewTcpWindow ) |
1476 { |
1378 { |
1477 // Check if we can complete shrinking process |
1379 //Log this message for information, that Window is shrinked |
1478 if ( aLength > iShrinkedWindowSize ) |
1380 LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode on"), (TInt)this)); |
1479 { |
1381 |
1480 // We can exit from the shrinking process. Reset variables and |
1382 //Increase the hidden free TCP receive window. |
1481 // update free window. |
1383 iHiddenFreeWindow += aLength; |
1482 iFreeWindow = aLength - iShrinkedWindowSize; |
1384 |
1483 iShrinkedWindowSize = 0; |
1385 if (iHiddenFreeWindow >= iShrinkedWindowSize) |
1484 iNewTcpWindow = 0; |
1386 { |
1485 } |
1387 //Disable window shrink processing, so that TCP could switch |
1486 else |
1388 //to the normal processing. |
1487 { |
1389 iSockInBufSize = iNewTcpWindow; |
1488 // Substract the needed shrinking amount by the amount of bytes client |
1390 |
1489 // read from the buffer |
1391 //Add the usable window to the free window. |
1490 iShrinkedWindowSize -= aLength; |
1392 iFreeWindow += iHiddenFreeWindow - iShrinkedWindowSize; |
1491 } |
1393 |
1492 } |
1394 //There are chances that TCP receive window might further shrink. |
|
1395 iHiddenFreeWindow = 0; |
|
1396 |
|
1397 //TCP Receive window shrink phase is over. |
|
1398 iNewTcpWindow = 0; |
|
1399 |
|
1400 //Log this message for information, that Window is shrinked |
|
1401 LOG(Log::Printf(_L("\ttcp SAP[%u] TCP window shrinking mode off"), (TInt)this)); |
|
1402 } |
|
1403 } |
1493 else |
1404 else |
1494 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
1405 #endif //SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW |
1495 |
1406 |
1496 { |
1407 { |
1497 iFreeWindow += aLength; |
1408 iFreeWindow += aLength; |