1 /*-------------------------------------------------------------------------- 2 Project: HorizonSDK 3 File: rdt_ResendQueue.h 4 5 Copyright 2009 Nintendo. All rights reserved. 6 7 These coded instructions, statements, and computer programs contain 8 proprietary information of Nintendo of America Inc. and/or Nintendo 9 Company Ltd., and are protected by Federal copyright law. They may 10 not be disclosed to third parties or copied or duplicated in any form, 11 in whole or in part, without the prior written consent of Nintendo. 12 13 $Date:: 2010-09-16#$ 14 $Rev: 26004 $ 15 $Author: hiratsu_daisuke $ 16 *-------------------------------------------------------------------------*/ 17 18 #include "stdafx.h" 19 20 #ifndef NN_RDT_RESENDQUEUE_H_ 21 #define NN_RDT_RESENDQUEUE_H_ 22 23 #include "rdt_Deque.h" 24 25 #include "rdt_Segment.h" 26 27 #include "rdt_Utility.h" 28 29 30 namespace nn { namespace rdt { namespace CTR { 31 32 /*! 33 @brief これは再送キューのクラスです。 34 再送キューには、リモートに向けて送信したセグメントのコピーが詰められ、 35 送信時の時刻が記録されます。 36 ただし、このクラス自身は再送処理を行いません。 37 */ 38 39 class ResendQueue{ 40 public: 41 /*! 42 @brief 初期化します。 43 */ 44 ResendQueue(void); 45 46 /*! 47 @brief 解放します。 48 */ 49 ~ResendQueue(void); 50 51 /*! 52 @brief セグメントを再送キューに詰め込みます。 53 キューの深さをオーバーしてしまうような場合にはfalseが返ります。 54 詰め込んだセグメントは、この関数呼び出し時点での時刻が関連づけられます。 55 @param[in] seg 送信したセグメント。 56 @return Push操作が成功すればtrue、キューが満杯だった等の理由で失敗したときはfalse。 57 */ 58 bool Push(const Segment &seg); 59 60 /*! 61 @brief 時刻に関係なく、キューの先頭要素を返します。 62 キューがカラッポであればfalseが返ります。 63 */ 64 bool Front(Segment *pSeg) const; 65 66 /*! 67 @brief ACKによって、リモート側に届いたことが確認できたセグメントを再送キューから除去します。 68 ack引数には、リモートから届いたセグメントに記録されていたACK番号をそのまま渡します。 69 */ 70 void Remove(u32 ack); 71 72 /*! 73 @brief デフォルト(通常のデータセグメント)のタイムアウト時間を設定します。(単位はミリ秒) 74 */ SetDefaultTimeout(MSEC_T msec)75 void SetDefaultTimeout(MSEC_T msec) { m_defaultTimeout = msec; } 76 77 /*! 78 @brief キューに詰め込んでから、一定時刻が経過してしまっているセグメントがあれば、 79 trueを返します。さもなければfalse。 80 */ 81 bool IsResendRequired(void) const; 82 83 /*! 84 @brief キューに詰めこまれたセグメントに含まれる、実データ部分の 85 合計を返します。すなわち、到着したかどうか定かでない 86 データのサイズが求められます。 87 */ 88 u32 GetTotalDataSize(void) const; 89 90 /*! 91 @brief 再送キューを空っぽにし、まっさらな状態に戻します。 92 */ 93 void Clear(void); 94 95 96 /*! 97 @brief 先頭の要素を最後尾に持ってきます。 98 全要素についてTryAgain()し終えると、IsResendMode()状態は解除されます。 99 */ 100 void TryAgain(void); 101 102 /*! 103 @brief キューに含まれる全要素を再送する必要があるモードであるかどうかを判定します。 104 全要素についてTryAgain()し終えると、IsResendMode()状態は解除されます。 105 タイムアウトを迎えたセグメントがキューに見つかったか、 106 あるいはいったんそういうセグメントが見つかり、残りの 107 セグメントを送り終えるのを待っている状態か。 108 */ 109 bool IsResendMode(void) const; 110 111 /*! 112 @brief 再送キューが満杯であるかどうかを判定します。 113 この関数がtrueを返す状況では、それ以上Pushすることは 114 できません。 115 */ IsFull(void)116 bool IsFull(void) const { return m_queue.IsFull(); } 117 118 /*! 119 @brief デバッグ用の関数です。 120 */ 121 void PrintDebugInfo(void) const; 122 123 /*! 124 @brief CUnitを用いた単体テストです。 125 */ 126 static void Test(void); 127 128 private: 129 /*! 130 @brief コピーコンストラクタは封印します。 131 */ 132 ResendQueue (const ResendQueue&); 133 134 /*! 135 @brief 代入演算子は封印します。 136 */ 137 ResendQueue& operator=(const ResendQueue&); 138 139 // キューのキャパシティは、受信側から通知されるウィンドウサイズよりも 140 // 大きくないと、キューが満杯になる可能性がある。 141 // RDTのペイロードを1400バイトとすると、16 * 1400 = 22400バイトなので、 142 // 受信側が受信バッファ(ウインドウサイズ)をこれより大きく設定したり 143 // すると、送信側のキューが詰まる可能性が生まれる。 144 static const size_t DEPTH = 16; 145 146 // TODO: CTR実機で要調整のパラメータ。スループットに重大な影響を及ぼす。 147 // 以前はこの数値が500だった。このとき、256KBのデータ送受信に35秒もかかっていた。 148 // static const MSEC_T DEFAULT_TIMEOUT = 100; 149 static const MSEC_T DEFAULT_TIMEOUT = 50; // 150 ~ 180KB 150 151 // SYNを含むセグメントのタイムアウト値。データセグメントと 152 // 同様の速いペースで再送していると、接続がハーフオープン状態に 153 // なってしまったりするバグを回避するために用意。 154 static const MSEC_T SYN_SEGMENT_TIMEOUT = 200; 155 156 bool checkTimeStamp(void) const; 157 158 struct SegmentWithTime 159 { SegmentWithTimeSegmentWithTime160 SegmentWithTime(void) : timeStamp(0), timeOut(0), resendMark(false) {} IsTimeOutSegmentWithTime161 bool IsTimeOut(void) const { return (timeStamp + timeOut < GetCurrentTimeAsMillisecond()); } 162 163 Segment segment; 164 MSEC_T timeStamp; // 送信時の時刻 165 MSEC_T timeOut; // ここで指定された時間が経過したなら、再送対象となる。 166 bool resendMark; // 再送モードに入った瞬間の要素に対してマーキングされる。 167 u8 padding[7]; // パディング 168 }; 169 170 MSEC_T m_defaultTimeout; // タイムアウト時間(ミリ秒) 171 Deque<SegmentWithTime, DEPTH> m_queue; // 再送キュー 172 173 bool m_bResendMode; // 再送モードフラグ 174 u8 m_padding[7]; 175 }; 176 177 178 }}} // namespace nn::rdt::CTR 179 180 #endif // end of NN_RDT_RESENDQUEUE_H_ 181