CTR-Pia  5.4.3
Game Communication Engine
 全て クラス ネームスペース 関数 変数 型定義 列挙型 列挙型の値 ページ
transport_ReliableProtocol.h
1 /*--------------------------------------------------------------------------------*
2  Copyright (C)Nintendo All rights reserved.
3 
4  These coded instructions, statements, and computer programs contain proprietary
5  information of Nintendo and/or its licensed developers and are protected by
6  national and international copyright laws. They may not be disclosed to third
7  parties or copied or duplicated in any form, in whole or in part, without the
8  prior written consent of Nintendo.
9 
10  The content herein is highly confidential and should be handled accordingly.
11  *--------------------------------------------------------------------------------*/
12 
13 
14 #pragma once
15 
16 #include <nn/pia/transport/transport_Definitions.h>
17 
18 #include <nn/pia/common/common_Types.h>
19 #include <nn/pia/transport/transport_Protocol.h>
20 
21 #include <nn/pia/transport/transport_ProtocolEvent.h>
22 
23 namespace nn
24 {
25 namespace pia
26 {
27 namespace transport
28 {
29 
30 class ReliableSlidingWindow;
31 
32 /*!
33  @brief 到達保証された通信を行うプロトコルです。
34 
35  */
37 {
38 public:
39  static const uint32_t ThroughputLimitMax = 0x0FFFFFFF; //!< SetThroughputLimit() で設定できる値の最大値です。
40 
41  /*!
42  @cond PRIVATE
43  @brief デフォルトコンストラクタです。
44 
45  @details アプリケーションプログラムは、このコンストラクタを直接呼び出してはいけません。
46  インスタンスの作成は、 @ref Transport::CreateProtocol を利用してください。
47  */
48  ReliableProtocol(void);
49  //! @endcond
50 
51 
52  /*!
53  @cond PRIVATE
54  @brief デストラクタです。
55 
56  @details アプリケーションプログラムは、このデストラクタを直接呼び出してはいけません。
57  インスタンスの破棄は、 @ref Transport::DestroyProtocol を利用してください。
58  */
59  virtual ~ReliableProtocol(void);
60  //! @endcond
61 
62 
63  PIA_PROTOCOL_TYPE_INFO(ProtocolTypeReliable);
64 
65 
66  /*!
67  @brief インスタンスを初期化します。 BeginSetup() ~ EndSetup() 間で呼び出す必要があります。
68 
69  @details 送信バッファ、受信バッファで実際に利用された数は @ref common::WatermarkManager で
70  @ref common::WatermarkManager::KeyReliableProtocolSendBufferNum および
71  @ref common::WatermarkManager::KeyReliableProtocolReceiveBufferNum を
72  指定することにより計測することができます。
73  @details ReliableProtocol が消費するおおよそのメモリ量は、以下の計算式で求められます(単位はバイト)。<br>
74  (sendBufferSize * 1500 + receiveBufferSize * 1500) * (Transport::Setting::maxStationNum - 1)
75 
76  @param[in] sendBufferSize 送信バッファのデータ数です。 1 以上の値を指定する必要があります。
77  送信バッファは Send() したデータを送信相手に届いたことが確認されるまで保持するために使われます。
78  @param[in] receiveBufferSize 受信バッファのデータ数です。 1 以上の値を指定する必要があります。
79  受信バッファは、受信したデータを Receive() されるまで保持するために使われます。
80 
81  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。この関数がエラーを返さないようにアプリケーションを実装する必要があります。
82 
83  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
84  @retval ResultAlreadyInitialized 既に初期化されています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
85 
86  @see Finalize
87  */
88  Result Initialize(uint32_t sendBufferSize, uint32_t receiveBufferSize);
89 
90 
91  /*!
92  @brief 終了処理を行います。
93 
94  @see Initialize
95  */
96  void Finalize();
97 
98 
99  /*!
100  @cond PRIVATE
101  @brief 通信を開始します。
102 
103  @param[in] localStationAddress 自分の StationAddress です。
104 
105  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。
106 
107  @retval ResultNotInitialized 初期化されていません。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
108  @retval ResultInvalidState 既に通信中です。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
109  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
110  */
111  virtual Result StartupWithStationAddress(const common::StationAddress& localStationAddress);
112  //! @endcond
113 
114 
115  /*!
116  @cond PRIVATE
117  @brief 通信を終了します。
118  */
119  virtual void CleanupWithStationAddress();
120  //! @endcond
121 
122 
123  /*!
124  @cond PRIVATE
125  @brief メインの処理です。
126 
127  @return ResultSuccess が返されます。
128  */
129  virtual Result Dispatch();
130  //! @endcond
131 
132 
133  /*!
134  @cond PRIVATE
135  @brief 接続状態の切り替え。
136 
137  @param[in] event 操作内容を表すイベントです。
138 
139  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。
140 
141  @retval ResultInvalidState 呼び出し状態が不正です。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
142  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
143  */
144  virtual Result UpdateProtocolEvent(const transport::ProtocolEvent& event);
145  //! @endcond
146 
147 
148  /*!
149  @brief データを送信します。
150 
151  @details この関数でセットされた送信データは、パケットに対して適切なサイズに分割され内部のバッファに保持されます。
152  その後の @ref common::Scheduler::Dispatch() の中で順次パケットが作成され送信されていきます。
153  送信してからしばらくたっても到達が確認できないデータは再送されます。
154  再送までの時間は RTT に応じて自動的に調整されます。
155  到達が確認できたデータはバッファから削除され、バッファはその後のデータ送信のために使う事ができるようになります。
156 
157  @param[in] destinationStationId 送信先の @ref StationId です。
158  @param[in] pData 送信するデータのアドレスです。
159  @param[in] dataSize 送信するデータのサイズ(バイト)です。
160 
161  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。
162 
163  @retval ResultInvalidState ReliableProtocol が初期化されていないか、session のセットアップが完了していない可能性があります。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
164  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
165  @retval ResultNotInCommunication 指定された送信先と通信中ではありません。自分か指定した相手がセッション内に存在しません。アプリケーションで適切にハンドリングしてください。
166  @retval ResultBufferIsFull 送信バッファに空きがありません。頻発する場合は、 Initialize() で指定する送信バッファのデータ数を増やすことを検討してください。アプリケーションで適切にハンドリングしてください。
167  @retval ResultTemporaryUnavailable セッション移行処理中のため、一時的に API を利用できない状態です。ジョイントセッション機能使用時にのみ返ります。アプリケーションで適切にハンドリングしてください。
168  @retval ResultNotFound 指定された送信先が見つかりません。アプリケーションで適切にハンドリングしてください。
169 
170  @see Receive, SendToAll
171  */
172  Result Send(StationId destinationStationId, const void* pData, uint32_t dataSize);
173 
174 
175  /*!
176  @brief データを全ステーションに向けて送信します。
177 
178  @details この関数でセットされた送信データは、パケットに対して適切なサイズに分割され内部のバッファに保持されます。
179  その後の @ref common::Scheduler::Dispatch() の中で順次パケットが作成され送信されていきます。
180  送信してからしばらくたっても到達が確認できないデータは再送されます。
181  再送までの時間は RTT に応じて自動的に調整されます。
182  到達が確認できたデータはバッファから削除され、バッファはその後のデータ送信のために使う事ができるようになります。
183 
184  @param[in] pData 送信するデータのアドレスです。
185  @param[in] dataSize 送信するデータのサイズ(バイト)です。
186 
187  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。
188 
189  @retval ResultInvalidState ReliableProtocol が初期化されていないか、session のセットアップが完了していない可能性があります。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
190  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
191  @retval ResultNotInCommunication 通信中ではありません。アプリケーションで適切にハンドリングしてください。
192  @retval ResultBufferIsFull 送信バッファに空きがありません。頻発する場合は、 Initialize() で指定する送信バッファのデータ数を増やすことを検討してください。アプリケーションで適切にハンドリングしてください。
193 
194  @see Receive, Send
195  */
196  Result SendToAll(const void* pData, uint32_t dataSize);
197 
198 
199  /*!
200  @cond PRIVATE
201  @brief データを送信します。
202  */
203  Result Send(StationIndex destinationStationIndex, const void* pData, uint32_t dataSize);
204  //! @endcond
205 
206 
207  /*!
208  @brief データを受信します。
209 
210  @details @ref common::Scheduler::Dispatch() のタイミングで受信したパケットは解析され、内部のバッファに蓄積されていきます。
211  Send() で分割されたデータがすべて届いていることが確認できているデータはこの関数で結合され取得できます。
212  内部バッファもこのタイミングで解放され、次の受信のために使われます。
213 
214  @param[out] pSourceStationId 受信データの送信元の @ref StationId を書き込むバッファへのポインタです。
215  @param[out] pBuffer 受信データを書き込むバッファへのポインタです。
216  @param[out] pDataSize 受信データのサイズを書き込むバッファへのポインタです。
217  @param[in] bufferSize 受信データを書き込むバッファのサイズ(バイト)です。
218 
219  @return 成功すれば、 IsSuccess() が true を返す Result が返されます。
220 
221  @retval ResultInvalidState 初期化されていません。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
222  @retval ResultInvalidArgument 引数が誤っています。プログラミングエラーです。このエラーが返らないようにソースコードを修正してください。
223  @retval ResultNotInCommunication 通信中でありません。セッションに参加していない状態と同じです。アプリケーションで適切にハンドリングしてください。
224  @retval ResultNoData 受信したデータはありません。アプリケーションで適切にハンドリングしてください。
225  @retval ResultBrokenData 受信したデータが大きすぎて受信バッファに入りきらないか渡されたバッファに書ききれません。セッションのスタートアップからやり直す必要があります。
226  この Result はチートなどによって送信側が不正なデータを送ってきたときに発生する可能性があるため実行時にハンドリングする必要がありますが、
227  送信側の挙動が正常な場合はこの Result が返らないようにプログラムを修正する必要があります。アプリケーションで適切にハンドリングしてください。
228 
229  @see Send, SendToAll
230  */
231  Result Receive(StationId* pSourceStationId, void* pBuffer, uint32_t* pDataSize, uint32_t bufferSize);
232 
233 
234  /*!
235  @cond PRIVATE
236  @brief データを受信します。
237  */
238  Result Receive(StationIndex* pSourceStationIndex, void* pBuffer, uint32_t* pDataSize, uint32_t bufferSize);
239  //! @endcond
240 
241 
242  /*!
243  @brief 指定した相手と通信中かどうかを取得します。
244 
245  @details 自分および指定した相手がセッション内に存在すれば true を返します。
246  <br>
247  @param[in] stationId 通信相手の @ref StationId です。
248 
249  @return 通信中なら true が返されます。
250  */
251  bool IsInCommunication(StationId stationId) const;
252 
253 
254  /*!
255  @cond PRIVATE
256  @brief 指定した相手と通信中かどうかを取得します。
257  */
258  bool IsInCommunication(StationIndex stationId) const;
259  //! @endcond
260 
261 
262  /*!
263  @brief common::Scheduler::Dispatch の 1 回の呼び出しあたりにこのプロトコルが送信するデータ量の上限を指定します。
264 
265  @details このプロトコルが common::Scheduler::Dispatch の 1 回あたりに送信するデータ量の平均値が
266  この関数で設定した値以下になるように制限されます。
267  瞬間的にはここで設定した値以上のサイズの送信が行われることもあります。
268 
269  設定できる値の最大値は @ref ThroughputLimitMax です。これより大きな値を設定した場合は、@ref ThroughputLimitMax を設定したものと扱います。
270  この API を呼び出さなかった場合のデフォルト値は @ref ThroughputLimitMax です。
271 
272  @param[in] throughputLimit 設定する送信データ量の上限サイズ(バイト)です。
273  */
274  void SetThroughputLimit(uint32_t throughputLimit);
275 
276 
277  // 再送時間算出コールバック型。
278  // rtt にはミリ秒単位での RTT が、resendCount にはデータの再送回数が渡されます。
279  // コールバックの返り値が再送時間となります。単位はミリ秒です。
280  typedef int32_t (*ResendTimeCallback)(int32_t rtt, int32_t resendCount);
281 
282 
283  /*!
284  @cond PRIVATE
285  @brief 再送時間を算出するコールバック関数を登録します。
286  デフォルトではコールバック関数は登録されていません。
287 
288  @return 直前まで保持されていたコールバック関数のポインタが返されます。
289  */
290  static ResendTimeCallback RegisterResendTimeCallback(ResendTimeCallback cb);
291  //! @endcond
292 
293 
294  /*!
295  @brief デバッグに有用な情報をプリントします。
296 
297  @param[in] flag トレースフラグの論理和。詳細は @ref TraceFlag 型を参照してください。
298  */
299  virtual void Trace(uint64_t flag) const;
300 
301 #if NN_PIA_EXPERIMENT_RELIABLE_DETAIL_INFO
302  void PrintDebugInfo(void) const;
303  void ClearAllResendCount(void);
304  uint32_t GetAllResendCount(void) const;
305 #endif
306 
307 private:
308  ReliableSlidingWindow* GetSlidingWindow(StationIndex stationId);
309  const ReliableSlidingWindow* GetSlidingWindow(StationIndex stationId) const;
310 
311  Result ReceiveImpl(StationIndex* pSourceStationIndex, void* pBuffer, uint32_t* pDataSize, uint32_t bufferSize, bool bCheckStationIdTable);
312 
313 private:
314  StationIndex m_LocalStationIndex;
315  uint32_t m_MaxConnections;
316  ReliableSlidingWindow* m_paSlidingWindow;
317  uint32_t m_DispatchSlidingWindowIdx;
318 
319  uint32_t m_ThroughputLimit;
320  uint32_t m_RestThroughputLimit;
321 
322  static ResendTimeCallback s_pfResendTimeCallback; // 再送時間算出コールバック。
323 };
324 }
325 }
326 } // end of namespace nn::pia::transport