CTR Pia  4.11.3
Game Communication Engine
transport_ReliableSlidingWindow.h
1 /*---------------------------------------------------------------------------*
2  Project: Pia
3  File: transport_ReliableSlidingWindow.h
4 
5  Copyright 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 
14 
15 #pragma once
16 
17 #include <pia/transport/transport_definitions.h>
18 #include <pia/common/common_types.h>
19 #include <pia/transport/transport_ProtocolID.h>
20 #include <pia/common/common_PacketDefine.h>
21 
22 
23 // Forward declaration.
24 namespace nn
25 {
26 namespace pia
27 {
28 namespace common
29 {
30 class String;
31 }
32 }
33 }
34 
35 namespace nn
36 {
37 namespace pia
38 {
39 namespace transport
40 {
41 
42 class ProtocolMessageReader;
43 class PacketHandler;
44 
45 /*!
46 @cond PRIVATE
47 @brief Represents a sliding window for reliable sending and receiving.
48 
49 @date 2014-01-29 Provided an interface to the resend time calculation callback.
50 @date 2013-01-22 Added functions to get and set the sample count when getting RTT.
51 @date 2013-01-22 Added functions to get and set the timeout rate for resending.
52 @date 2012-07-17 Added the <tt>GetString</tt> function.
53 @date 2012-04-06 Initial version.
54 */
55 class ReliableSlidingWindow : public common::RootObject
56 {
57 public:
58 /*!
59 @brief Instantiates the object with default parameters (default constructor).
60 */
61  ReliableSlidingWindow();
62 
63 
64 /*!
65 @brief Destroys the object.
66 */
67  virtual ~ReliableSlidingWindow();
68 
69 
70 /*!
71 @brief Initializes the object.
72 
73 @param[in] sendBufferSize Specifies the size of the send buffer. Specify a value of <tt>1</tt> or greater.
74 @param[in] receiveBufferSize Specifies the size of the receive buffer. Specify a value of <tt>1</tt> or greater.
75 
76 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
77 
78 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
79 @retval ResultAlreadyInitialized Indicates that the instance is already initialized. Programming error. Fix your program so that this error is not returned.
80 */
81  nn::Result Initialize(u32 sendBufferSize, u32 receiveBufferSize);
82 
83 
84 /*!
85 @brief Finalizes the object.
86 */
87  void Finalize();
88 
89 
90 /*!
91 @brief Starts communication.
92 
93 @param[in] pPacketHandler Specifies the packet handler to use.
94 @param[in] protocolId Specifies the protocol ID to use for communication.
95 @param[in] sourceStationIndex Specifies the ID of the local station. Specify a value between <tt>STATION_INDEX_1</tt> and <tt>STATION_INDEX_MAX</tt>.
96 @param[in] destinationStationIndex Specifies the ID of the station you are communicating with. Specify a value between <tt>STATION_INDEX_1</tt> and <tt>STATION_INDEX_MAX</tt>.
97 
98 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
99 
100 @retval ResultNotInitialized Indicates that the instance is not initialized. Programming error. Fix your program so that this error is not returned.
101 @retval ResultInvalidState Indicates that stations are already communicating. Programming error. Fix your program so that this error is not returned.
102 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
103 */
104  nn::Result Startup(PacketHandler* pPacketHandler, u32 protocolId, StationIndex sourceStationIndex, StationIndex destinationStationIndex);
105 
106 
107 /*!
108 @brief Starts communication as the host in the <tt>Station</tt> protocol.
109 
110 @param[in] pPacketHandler Specifies the packet handler to use.
111 @param[in] protocolId Specifies the protocol ID to use for communication.
112 
113 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
114 
115 @retval ResultNotInitialized Indicates that the instance is not initialized. Programming error. Fix your program so that this error is not returned.
116 @retval ResultInvalidState Indicates that stations are already communicating. Programming error. Fix your program so that this error is not returned.
117 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
118 */
119  nn::Result StartupForStationHost(PacketHandler* pPacketHandler, u32 protocolId);
120 
121 
122 /*!
123 @brief Starts communication as a client in the <tt>Station</tt> protocol.
124 
125 @param[in] pPacketHandler Specifies the packet handler to use.
126 @param[in] protocolId Specifies the protocol ID to use for communication.
127 
128 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
129 
130 @retval ResultNotInitialized Indicates that the instance is not initialized. Programming error. Fix your program so that this error is not returned.
131 @retval ResultInvalidState Indicates that stations are already communicating. Programming error. Fix your program so that this error is not returned.
132 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
133 */
134  nn::Result StartupForStationChild(PacketHandler* pPacketHandler, u32 protocolId);
135 
136 
137 /*!
138 @brief Sets the <tt>StationIndex</tt>.
139 
140 @param[in] sourceStationIndex Specifies the ID of the local station. Specify a value between <tt>STATION_INDEX_1</tt> and <tt>STATION_INDEX_MAX</tt>.
141 @param[in] destinationStationIndex Specifies the ID of the station you are communicating with. Specify a value between <tt>STATION_INDEX_1</tt> and <tt>STATION_INDEX_MAX</tt>.
142 
143 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
144 
145 @retval ResultInvalidState Indicates that the station is not communicating or that the <tt>StationID</tt> has already been set. Programming error. Fix your program so that this error is not returned.
146 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
147 */
148  nn::Result SetStationIndex(StationIndex sourceStationIndex, StationIndex destinationStationIndex);
149 
150 
151 /*!
152 @brief Ends communication.
153 */
154  void Cleanup();
155 
156 
157 /*!
158 @brief Gets whether communication is active.
159 
160 @return Returns <tt>true</tt> if currently communicating.
161 */
162  bool IsInCommunication() const;
163 
164 
165 /*!
166 @brief Parses a received message.
167 
168 @param[in] reader Specifies the received <tt>ProtocolMessageReader</tt>.
169 
170 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
171 
172 @retval ResultInvalidState Indicates that the station is not actively communicating. Programming error. Fix your program so that this error is not returned.
173 @retval ResultBrokenData Indicates that the data in the specified <tt>ProtocolMessageOld</tt> object was invalid. Handle appropriately in the application.
174 @retval ResultBufferIsFull Indicates that the receive buffer is full. Handle appropriately in the application.
175 */
176  nn::Result AnalyzeProtocolMessage(const ProtocolMessageReader& reader);
177 
178 
179 /*!
180 @brief The main process.
181 
182 @param[in] pPacketHandler Specifies the <tt>PacketHandler</tt> instance to use.
183 
184 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
185 
186 @retval ResultInvalidState Indicates that the station is not actively communicating. Programming error. Fix your program so that this error is not returned.
187 */
188  nn::Result Dispatch(PacketHandler* pPacketHandler);
189 
190 
191 /*!
192 @brief Gets received data.
193 
194 @param[out] pBuffer Returns a pointer to a buffer for holding the received data.
195 @param[out] pDataSize Returns a pointer to a buffer for holding the size of the received data.
196 @param[in] bufferSize Specifies the size of the buffer (in bytes) for holding the received data.
197 
198 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
199 
200 @retval ResultInvalidState Indicates that the station is not actively communicating. Programming error. Fix your program so that this error is not returned.
201 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
202 @retval ResultNoData Indicates that no data was received. Handle appropriately in the application.
203 @retval ResultBrokenData Indicates that the received data is too large to fit in the receive buffer or cannot all be written to the buffer passed into the function. Try the communication again. Handle appropriately in the application.
204 */
205  nn::Result PopData(void* pBuffer, size_t* pDataSize, size_t bufferSize);
206 
207 
208 /*!
209 @brief Adds data to send.
210 
211 @param[in] pData Specifies a pointer to the data to send.
212 @param[in] dataSize Specifies the size of the data to send.
213 
214 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
215 
216 @retval ResultInvalidState Indicates that the station is not actively communicating. Programming error. Fix your program so that this error is not returned.
217 @retval ResultInvalidArgument Indicates that an argument is invalid. Programming error. Fix your program so that this error is not returned.
218 @retval ResultBufferIsFull Indicates that there is not enough space in the send buffer. Handle appropriately in the application.
219 */
220  nn::Result PushData(const void* pData, size_t dataSize);
221 
222 
223 /*!
224 @brief Checks whether data to send can be added.
225 
226 @param[in] dataSize Specifies the size of the data to send.
227 
228 @return Returns <tt>true</tt> if data can be added, and <tt>false</tt> otherwise.
229 */
230  bool CanPushData(size_t dataSize);
231 
232 
233 /*!
234 @brief Gets the protocol ID.
235 
236 @return Returns the protocol ID.
237 */
238  u32 GetProtocolId() const
239  {
240  return m_ProtocolId;
241  }
242 
243 
244 /*!
245 @brief Gets the local <tt>StationIndex</tt>.
246 
247 @return Returns the local <tt>StationIndex</tt>.
248 */
249  StationIndex GetSource() const
250  {
251  return m_SourceStationIndex;
252  }
253 
254 
255 /*!
256 @brief Gets the <tt>StationIndex</tt> of the peer.
257 
258 @return Returns the <tt>StationIndex</tt> of the peer.
259 */
260  StationIndex GetDestination() const
261  {
262  return m_DestinationStationIndex;
263  }
264 
265 
266 /*!
267 @brief Prints information that is useful for debugging.
268 
269 @param[in] flag Specifies the bitwise OR of trace flags. For more information, see the <tt>@ref TraceFlag</tt> type.
270 */
271  virtual void Trace(u64 flag) const;
272 
273 /*!
274 @cond PRIVATE
275 @brief Gets information that is useful for debugging.
276 
277 @param[out] pString Returns a pointer to a <tt>String</tt> instance.
278 */
279  void GetString(common::String* pString) const;
280  //! @endcond
281 
282 
283 /*!
284 @cond PRIVATE
285 @brief Gets the number of elements used in the sending buffer.
286 @return Returns the number of elements used in the sending buffer.
287 */
288  u32 GetSendBufferDataNum() const
289  {
290  return m_SendBuffer.GetDataNum();
291  }
292  //! @endcond
293 
294 
295 /*!
296 @cond PRIVATE
297 @brief Gets the number of elements used in the receive buffer.
298 @return Returns the number of elements used in the receive buffer.
299 */
300  u32 GetReceiveBufferDataNum() const
301  {
302  return m_ReceiveBuffer.GetDataNum();
303  }
304  //! @endcond
305 
306 
307 /*!
308 @cond PRIVATE
309 @brief Sets the timeout rate for resending. The resend timeout is calculated using the product of this rate and the RTT.
310 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
311 @retval ResultInvalidArgument Indicates that one or more arguments is invalid (such as a negative number).
312 */
313  static nn::Result SetRetransmissionTimeOutRate(f32 rate);
314  //! @endcond
315 
316 
317 /*!
318 @cond PRIVATE
319 @brief Gets the timeout rate for resending.
320 @return Returns a rate that can be multiplied with the RTT.
321 */
322  static f32 GetRetransmissionTimeOutRate(void)
323  {
324  return s_RtoRate;
325  }
326  //! @endcond
327 
328 
329 /*!
330 @cond PRIVATE
331 @brief Sets the number of samples to use when getting the RTT.
332 The lower the value of <span class="argument">num</span>, the more the obtained RTT value is affected by the current conditions. Although this makes the RTT value more variable, it makes the value less stable.
333 
334 @param[in] num Specifies the number of samples to use when calculating the RTT.
335 @return Returns a <tt>Result</tt> value for which the <tt>IsSuccess</tt> function returns <tt>true</tt> if execution succeeds.
336 @retval ResultInvalidArgument Indicates that an argument is invalid.
337 */
338  static nn::Result SetRttSamplingNum(size_t num);
339  //! @endcond
340 
341 
342 /*!
343 @cond PRIVATE
344 @brief Gets the number of samples that this class uses to calculate RTT.
345 
346 @return Returns the number of samples used to calculate the RTT.
347 */
348  static size_t GetRttSamplingNum(void)
349  {
350  return s_RttSamplingNum;
351  }
352  //! @endcond
353 
354 
355  // Resend time calculation callback type.
356  typedef s32 (*ResendTimeCallback)(s32 rtt, size_t resendCount);
357 
358 
359 /*!
360 @cond PRIVATE
361 @brief Specifies a callback function that calculates the resend time.
362 No callback is registered by default.
363 
364 @return A pointer to the callback function registered before this function was called.
365 */
366  static ResendTimeCallback RegisterResendTimeCallback(ResendTimeCallback cb);
367 //! @endcond
368 
369 
370 #if NN_PIA_EXPERIMENT_RELIABLE_DETAIL_INFO
371  void PrintDebugInfo(void) const;
372 
373  void ClearResendCount(void);
374  u32 GetResendCount(void) const;
375 #endif
376 
377 private:
378  // Copying and comparisons are not implemented
379  ReliableSlidingWindow(const ReliableSlidingWindow& rhs);
380  bool operator==(const ReliableSlidingWindow& rhs) const;
381  bool operator!=(const ReliableSlidingWindow& rhs) const;
382  ReliableSlidingWindow& operator=(const ReliableSlidingWindow& rhs);
383 
384 
385  void StartupCommon(PacketHandler* pPacketHandler);
386 
387 private:
388  // The header attached to <tt>ProtocolMessageOld</tt>.
389  struct MessageHeader
390  {
391  u16 m_Flags;
392  u16 m_PayloadSize;
393  u32 m_Reserved;
394  u32 m_SequenceId;
395  u32 m_AckOrigin;
396  u64 m_AckFlag;
397  };
398 
399  // The maximum payload size that fits in a <tt>ProtocolMessage</tt> instance.
400  static const u32 c_PayloadSizeMax = (common::PROTOCOL_MESSGAE_PAYLOAD_SIZE_MAX / sizeof(u64) * sizeof(u64)) - sizeof(MessageHeader);
401 
402  // The message payload.
403  struct Payload
404  {
405  bit8 m_Buffer[c_PayloadSizeMax];
406  };
407 
408  // Data structure of <tt>ProtocolMessageOld</tt>.
409  struct MessageData
410  {
411  MessageHeader m_Header;
412  Payload m_Payload;
413  };
414 
415  // The data for the send buffer.
416  struct SendData
417  {
418  u64 m_ResendTime;
419  u32 m_DataSize;
420  u16 m_SendCount;
421  MessageData m_MessageData;
422  };
423 
424  // The data for the receive buffer.
425  struct ReceiveData
426  {
427  bool m_IsValid;
428  bool m_IsComplete;
429  u16 m_PayloadSize;
430  Payload m_Payload;
431  };
432 
433  // Common processes for the send and receive buffers.
434  template <typename T>
435  class Buffer : public common::RootObject
436  {
437  public:
438  Buffer();
439  ~Buffer();
440 
441  nn::Result Initialize(u32 size);
442  void Finalize();
443 
444  void Clear();
445 
446  T* GetData(u32 sequenceId);
447 
448  u32 GetSize() const
449  {
450  return m_Size;
451  }
452  u32 GetStartSequenceId() const
453  {
454  return m_StartSequenceId;
455  }
456  u32 GetDataNum() const
457  {
458  return m_DataNum;
459  }
460 
461  void Withdraw(u32 num);
462 
463  class Iterator
464  {
465  public:
466  Iterator(Buffer<T>* pBuffer)
467  : m_pBuffer(pBuffer)
468  {
469  Begin();
470  }
471 
472  T* Get()
473  {
474  PIA_ASSERT(IsEnd() == false);
475  u32 idx = m_pBuffer->m_StartIdx + m_Offset;
476  if (idx >= m_pBuffer->m_Size)
477  {
478  idx -= m_pBuffer->m_Size;
479  }
480  return &(m_pBuffer->m_pData[idx]);
481  }
482 
483  u32 Offset() const
484  {
485  return m_Offset;
486  }
487 
488  void Begin()
489  {
490  m_Offset = 0;
491  }
492  bool IsEnd() const
493  {
494  return m_Offset >= m_pBuffer->m_DataNum;
495  }
496  void Next()
497  {
498  if (IsEnd() == false)
499  {
500  ++m_Offset;
501  }
502  }
503 
504  private:
505  Buffer<T>* m_pBuffer;
506  u32 m_Offset;
507  };
508 
509  protected:
510  T* m_pData;
511  u32 m_Size;
512  u32 m_StartIdx;
513  u32 m_StartSequenceId;
514  u32 m_DataNum;
515  };
516 
517 
518  // Send buffer.
519  class SendBuffer : public Buffer<SendData>
520  {
521  public:
522  u32 GetAvailableDataNum() const
523  {
524  return m_Size - m_DataNum;
525  }
526  SendData* Assign();
527  };
528 
529 
530  // Receive buffer.
531  class ReceiveBuffer : public Buffer<ReceiveData>
532  {
533  public:
534  ReceiveData* Assign(u32 sequenceId);
535  };
536 
537 private:
538  transport::ProtocolId m_ProtocolId;
539  StationIndex m_SourceStationIndex;
540  StationIndex m_DestinationStationIndex;
541 
542  SendBuffer m_SendBuffer;
543  ReceiveBuffer m_ReceiveBuffer;
544 
545  u32 m_PayloadSize;
546 
547  u64 m_DispatchTime;
548  u64 m_DefaultResendTimeSpan;
549  u32 m_AckOrigin;
550  u64 m_AckFlag;
551  bool m_IsSendAck;
552 
553 #if NN_PIA_EXPERIMENT_RELIABLE_DETAIL_INFO
554  u32 m_ResendCount; // The number of resends.
555 #endif
556 
557  size_t m_LargeDataSendSize;
558  common::Time m_LargeDataSendStartTime;
559 
560  static f32 s_RtoRate; // Resend timeout rate (coefficient).
561  static size_t s_RttSamplingNum; // Number of samples used to calculate RTT.
562  static ResendTimeCallback s_pfResendTimeCallback; // Resend time calculation callback.
563 };
564 //! @endcond
565 }
566 }
567 } // end of namespace nn::pia::transport
void Finalize(void)
Finalizes the common module.
Class that represents time.
Definition: common_Time.h:39
StationIndex
Enumerates StationIndex values.
Definition: platformCtr.h:44
Definition: assert.h:115
Definition: transport_ReliableSlidingWindow.h:463
nn::Result Initialize(void *pMem, u32 size)
Initializes the common module.