1 /*--------------------------------------------------------------------------
2   Project:  HorizonSDK
3   File:     rdt_ReceiverImpl.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_RECEIVERIMPL_H_
21 #define NN_RDT_RECEIVERIMPL_H_
22 
23 #include "rdt_HostBase.h"
24 #include "rdt_ReceiveBuffer.h"
25 #include "rdt_Segment.h"
26 
27 
28 namespace nn { namespace rdt { namespace CTR {
29 
30 // 先行宣言
31 class ReceiverStateBase;
32 
33 /*!
34     @brief これはReceiverクラスの内部実装のためのクラスです。
35 */
36 class ReceiverImpl : public HostBase{
37 public:
38 /*!
39     @brief コンストラクタです。初期化フラグを下ろす以外のことはしません。
40 */
41     ReceiverImpl(void) throw();
42 
43 /*!
44     @brief デストラクタです。
45 */
46     virtual ~ReceiverImpl(void);
47 
48 /*!
49     @brief 初期化します。
50 */
51 #ifdef _WIN32
52     nn::Result Initialize(SOCKET sock, void *pRecvBuf, u16 recvBufSize);
53 #elif defined(NN_PLATFORM_CTR)
54     nn::Result Initialize(u16 nodeId, u8 port, void *pRecvBuf, u16 recvBufSize);
55 #endif
56 
57 /*!
58     @brief 解放します。
59 */
60     void Finalize(void);
61 
62 /*!
63     @brief Senderが接続しにくるのを待つリクエストを発行します。
64 */
65     nn::Result Wait(void);
66 
67 /*!
68     @brief データを全て受信した後で呼ぶことを想定されています。
69            オブジェクトの状態がCLOSED状態に戻り、再利用できるようになります。
70 */
71     nn::Result Close(void);
72 
73 /*!
74     @brief ライブラリの受信バッファに溜められたデータを読み取ります。
75     成功した場合、読み取ったバイト数がrecvSizeに記録されます。
76     読み取るデータが1バイトも存在していなかった場合は、recvSizeにゼロが書き込まれます。
77 */
78     nn::Result Receive(void *pBuf, size_t *recvSize, size_t bufSize);
79 
80 /*!
81     @brief 通信処理を進行させます。実際の通信処理は、この関数の内部で実行されます。
82            アプリ側から、毎フレーム程度の間隔で呼び出してもらうことを想定しています。
83            一連の処理において、何らかのエラーがあった場合はエラーが返ります。
84 */
85     nn::Result Process(void);
86 
87 /*!
88     @brief 処理の中断をリクエストします。
89 */
90     void Cancel(void);
91 
92 /*!
93     @brief Receiverインスタンスの状態を取得します。
94 */
95     enum ReceiverState GetStatus(void) const;
96 
97 /*!
98     @brief 配置new演算子です。
99 */
new(size_t size,void * pBuf)100     static void* operator new(size_t size, void *pBuf) throw()
101     {
102         if(size!=sizeof(ReceiverImpl))
103         {
104             PANIC("Wrong size.\n");
105             return NULL;
106         }
107 
108         if(pBuf==NULL)
109         {
110             PANIC("NULL pointer is detected.\n");
111             return NULL;
112         }
113 
114         ALIGN_ASSERT(pBuf, 8);
115 
116         return pBuf;
117     }
118 
delete(void * p)119     static void  operator delete (void *p) throw()
120     {
121         PANIC("Do not call this delete!  Please call destructor manually.\n");
122         (void)p;
123     }
124 
125 
126 /*!
127     @brief このオブジェクトの詳細な内部状態をプリントします。(デバッグ用)
128 */
129     void PrintDebugInfo(void) const;
130 
131 private:
132 /*!
133     @brief コピーコンストラクタは封印します。
134 */
135     ReceiverImpl           (const ReceiverImpl&);
136 
137 /*!
138     @brief 代入演算子は封印します。
139 */
140     ReceiverImpl& operator=(const ReceiverImpl&);
141 
142     // 定数
143     static const MSEC_T FIN_TIMEOUT = 1000;  // TORIAEZU。CTR実機で要調整のパラメータ。
144 
145     // プライベート関数群。
146     void changeState(void);          // この関数を呼ぶことで、状態遷移が実行される。
147     void setNextState(ReceiverStateBase *p); // 次の状態をセット。
148 
149     // SYNに対する応答を作成する際に呼ぶ。
150     void putSynAckSegment(u32 ack);
151 
152     // ACKのセグメントを作る際に呼ぶ。
153     void putAckSegment(void);
154 
155     // FINに対するACKのセグメントを送信する際に呼ぶ。
156     // このとき、ACK送信時刻も記録される。
157     void putFinAckSegment(u32 ack);
158 
159     // FINに対するACKを送ってから十分な時間が経ち、相手は
160     // クローズしたと確信できるか?
161     bool isSenderClosed(void) const;
162 
163     // 受信バッファはカラッポか?
isReceiveBufferEmpty(void)164     bool isReceiveBufferEmpty(void) const { return m_recvBuf.IsEmpty(); }
165 
166     // Closed状態に入るときなどに呼ばれることを想定。
167     // Stateパターンにおける状態を保持するメンバを除き、
168     // 各種メンバ変数をまっさらな状態に戻す。
169     void clear(void);
170 
171     // メンバ変数群。
172     ReceiveBuffer m_recvBuf;    // 受信バッファ。Senderからやってきた実データはここに格納される。
173     bool   m_initialized;       // 初期化済み?
174     u8     m_padding[7];        // MSEC_T型が64bitであることに注意!
175     MSEC_T m_finAckSentTime;    // 最後にFINセグメントに対するACKを送信したときの時刻。
176 
177     // Stateパターンの実践。
178     ReceiverStateBase *m_pState;
179     ReceiverStateBase *m_pNextState;
180     friend class ReceiverStateWaiting;
181     friend class ReceiverStateOpened;
182     friend class ReceiverStateWaitingFinished;
183     friend class ReceiverStateFinished;
184     friend class ReceiverStateClosed;
185 };
186 
187 }}} // namespace nn::rdt::CTR
188 
189 #endif  // end of NN_RDT_RECEIVERIMPL_H_
190