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