1 /*-------------------------------------------------------------------------- 2 Project: HorizonSDK 3 File: rdt_SenderImpl.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-13#$ 14 $Rev: 25720 $ 15 $Author: hiratsu_daisuke $ 16 *-------------------------------------------------------------------------*/ 17 18 #include "stdafx.h" 19 20 #ifndef NN_RDT_SENDERIMPL_H_ 21 #define NN_RDT_SENDERIMPL_H_ 22 23 #include "rdt_HostBase.h" 24 #include "rdt_SendBuffer.h" 25 #include "rdt_ResendQueue.h" 26 #include "rdt_Segment.h" 27 28 namespace nn { namespace rdt { namespace CTR { 29 30 // 先行宣言 31 class SenderStateBase; 32 33 34 /*! 35 @brief これはSenderクラスの内部実装のためのクラスです。 36 */ 37 class SenderImpl : public HostBase{ 38 public: 39 /*! 40 @brief 初期化します。 41 */ 42 SenderImpl(void) throw(); 43 44 /*! 45 @brief デストラクタです。仮にFinalize()が呼ばれていなくても、この中で自動的に呼び出されます。 46 */ 47 virtual ~SenderImpl(void); 48 49 /*! 50 @brief 初期化します。 51 */ 52 #ifdef _WIN32 53 nn::Result Initialize(SOCKET sock, void *pSendBuf, u16 sendBufSize); 54 #elif defined(NN_PLATFORM_CTR) 55 nn::Result Initialize(u16 nodeId, u8 port, void *pSendBuf, u16 sendBufSize); 56 #endif 57 58 /*! 59 @brief 解放します。 60 */ 61 void Finalize(void); 62 63 /*! 64 @brief 接続要求を出すリクエストを発行します。 65 リクエストのキューがいっぱいであるなどの理由で 66 失敗することがあります。 67 */ 68 nn::Result Open(void); 69 70 /*! 71 @brief 接続を閉じるリクエストを発行します。 72 リクエストのキューがいっぱいであるなどの理由で 73 失敗することがあります。 74 */ 75 nn::Result Close(void); 76 77 /*! 78 @brief データをRDTライブラリの送信バッファに書き込み、送信の準備をします。 79 送信バッファがいっぱいの場合は、失敗します。このとき、送信バッファには 80 データは1バイトたりとも書き込まれません。 81 この関数呼び出しで渡したデータが実際に送信されるのは、もう少し後になることに 82 注意して下さい。 83 */ 84 nn::Result Send(const void *pBuf, size_t bufSize); 85 86 /*! 87 @brief 通信処理を進行させます。実際の通信処理は、この関数の内部で実行されます。 88 アプリ側から、毎フレーム程度の間隔で呼び出してもらうことを想定しています。 89 */ 90 nn::Result Process(void); 91 92 /*! 93 @brief 処理の中断をリクエストします。 94 */ 95 void Cancel(void); 96 97 /*! 98 @brief オブジェクトの状態を取得します。 99 */ 100 enum SenderState GetStatus(void) const; 101 102 103 /*! 104 @brief 配置new演算子です。 105 */ new(size_t size,void * pBuf)106 static void* operator new(size_t size, void *pBuf) throw() 107 { 108 if(size!=sizeof(SenderImpl)) 109 { 110 PANIC("Wrong size.\n"); 111 return NULL; 112 } 113 114 if(pBuf==NULL) 115 { 116 PANIC("NULL pointer is detected.\n"); 117 return NULL; 118 } 119 120 ALIGN_ASSERT(pBuf, 8); 121 122 return pBuf; 123 } 124 125 // 配置deleteを記述したのだが、delete(m_pImpl, m_workBuf)のように 126 // 呼ぶと、何故かグローバルなdelete(void *p)が呼び出されているようだった。 127 // Webにも上記の説を補強する記述が見つかったので、deleteは定義しないで 128 // 置こうとした。…しかし、それだとRealViewコンパイラにWarningで叱られた。 129 // よって定義だけはしておく。ただし呼ばないこと。 130 // SenderImplは、それを使う人が明示的にデストラクタを呼ぶこと。 131 132 // C++ Labyringth (http://www.fides.dti.ne.jp/~oka-t/cpplab-placement-new-2.html) 133 // もし operator delete( void *p ) と両方が定義されていた場合は、 134 // operator delete( void *p ) のほうが呼び出される。 これは C++ の 135 // 規格書に述べられていることなのだが、 なんとも不明瞭な仕様だと 136 // 言わざるをえない。昔の仕様との整合性を重んじた結果だろうか。 137 delete(void * p)138 static void operator delete (void *p) throw() 139 { 140 PANIC("Do not call this delete! Please call destructor manually.\n"); 141 (void)p; 142 } 143 144 145 /*! 146 @brief Senderインスタンスの詳細な内部状態をプリントします。(デバッグ用) 147 */ 148 void PrintDebugInfo(void) const; 149 150 /*! 151 @brief SenderImplクラスの内部構造を知りたくなったときに作った関数です(デバッグ用) 152 */ 153 static void PrintProperty(void); 154 155 /*! 156 @brief CUnitの単体テストです。 157 */ 158 static void Test(void); 159 160 161 private: 162 /*! 163 @brief コピーコンストラクタは封印します。 164 */ 165 SenderImpl (const SenderImpl&); 166 167 /*! 168 @brief 代入演算子は封印します。 169 */ 170 SenderImpl& operator=(const SenderImpl&); 171 172 173 // プライベート関数群。 174 void changeState(void); // この関数を呼ぶことで、状態遷移が実行される。 175 void setNextState(SenderStateBase *p); // 次の状態をセット。 176 177 void putSegmentWithResend(const Segment &seg); 178 179 // segには、受信できたセグメントを与える。 180 // 受信セグメントに対する共通処理がこの関数の中に 181 // まとめられている。 182 void processReceivedSegment(const Segment &seg); 183 184 // 一連の再送処理を実行する。 185 // セグメントの再送が行われた場合はtrueが返る。 186 // 行われなかった場合はfalse。 187 bool processResending(void); 188 189 // キャンセル処理を実行。 190 void processCanceling(void); 191 192 // 送信バッファにデータが溜まっていたら、1つのセグメントに 193 // 収まる量だけ吸い出して、送信します。 194 void sendData(void); 195 196 // SYN要求を込めたセグメントを作成し、送信します。 197 void sendSynSegment(void); 198 199 // FIN要求を込めたセグメントを作成し、送信します。 200 // この関数は、送信バッファがカラッポの状況で呼び出す必要があります。 201 void sendFinSegment(void); 202 203 // 送信バッファはカラッポ? isSendBufferEmpty(void)204 bool isSendBufferEmpty(void) const { return m_sendBuffer.IsEmpty(); } 205 206 // Closed状態に入るときなどに呼ばれることを想定。 207 // Stateパターンにおける状態を保持するメンバを除き、 208 // 各種メンバ変数をまっさらな状態に戻す。 209 void clear(void); 210 211 // ISS(初期シーケンス番号)を取得。 getInitialSequenceNumber(void)212 u32 getInitialSequenceNumber(void) const { return m_iss; } 213 214 // 到達未確認のオクテットのうち、最も古いシーケンス番号を取得 getUnacknowledgeNumber(void)215 u32 getUnacknowledgeNumber(void) const { return m_una; } 216 217 // 次に送信することになるオクテットのシーケンス番号 getNextSequenceNumber(void)218 u32 getNextSequenceNumber(void) const { return m_nxt; } 219 220 // リモートから受信したACKは正当? 221 bool isValidAckNumber(u32 ack) const; 222 223 // メンバ変数群。 224 SendBuffer m_sendBuffer; // 送信バッファ 225 u16 m_remoteWindowSize; // リモート側から通知されたウィンドウサイズの最新情報。 226 bool m_initialized; 227 u8 m_padding; // パディング 228 u32 m_iss; // 初期シーケンス番号 229 u32 m_una; // 到達未確認のシーケンス番号のうち、最も古いもの 230 u32 m_nxt; // 次に送信されるべきオクテットのシーケンス番号 231 ResendQueue m_resendQueue; // 再送キュー(8バイトアライメントが要求される) 232 233 // Stateパターンの実践。 234 SenderStateBase *m_pState; 235 SenderStateBase *m_pNextState; 236 friend class SenderStateOpenRequested; 237 friend class SenderStateOpening; 238 friend class SenderStateOpened; 239 friend class SenderStateCloseRequested; 240 friend class SenderStateClosing; 241 friend class SenderStateClosed; 242 243 // デバッグ用変数 244 u32 m_arrivals; // セグメント到着回数 245 246 // SenderImplクラスもResendQueueのアライメントに引きずられるので、 247 // ここでパディングする必要があることもある 248 u8 m_padding2[4]; 249 }; 250 251 }}} // namespace nn::rdt::CTR 252 253 #endif // end of NN_RDT_SENDERIMPL_H_ 254