1 /*--------------------------------------------------------------------------
2   Project:  HorizonSDK
3   File:     rdt_Utility.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:: 2011-02-07#$
14   $Rev: 34174 $
15   $Author: okubata_ryoma $
16  *-------------------------------------------------------------------------*/
17 
18 #include "stdafx.h"
19 
20 #ifndef NN_RDT_UTILITY_H_
21 #define NN_RDT_UTILITY_H_
22 
23 
24 #ifdef _WIN32
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "types.h"
28 #include <time.h>
29 #else
30 #include <nn/types.h>
31 #endif
32 
33 #include <nn/rdt/CTR/rdt_Misc.h>
34 
35 /*!
36     @brief これは、便利な関数(ユーティリティ関数)をまとめたものです。
37 */
38 
39 #ifdef _WIN32
40 #define PRINTF printf
41 #else
42 #define PRINTF NN_LOG
43 #endif
44 
45 
infinite_loop(void)46 inline void infinite_loop(void)
47 {
48 #if defined(NN_BUILD_NOOPT) || defined(NN_BUILD_VERBOSE)
49     while(1)
50     {
51     }
52 #else
53     // Do nothing. (Release build)
54 #endif
55 }
56 
57 
58 #define WARNING(exp) (void) ((exp) || (nn::rdt::CTR::GetLogLevel()==nn::rdt::CTR::LOG_LEVEL_NONE) || \
59                                   (PRINTF("WARNING: %s line: %d\n", __FILE__, __LINE__), \
60                                   0))
61 
62 
63 #define WARNINGMSG(exp, ...) (void) ((exp) || (nn::rdt::CTR::GetLogLevel()==nn::rdt::CTR::LOG_LEVEL_NONE) ||  \
64                                   (PRINTF("WARNING: %s line: %d ", __FILE__, __LINE__), \
65                                    PRINTF(__VA_ARGS__),                                 \
66                                    PRINTF("\n"),                                        \
67                                   0))
68 
69 #define PANIC(...) (void) (PRINTF("PANIC: %s line: %d ", __FILE__, __LINE__), \
70                            PRINTF(__VA_ARGS__),                               \
71                            PRINTF("\n"),                                      \
72                            infinite_loop()/*abort()*/)
73 
74 #define ASSERT(exp) (void) ((exp) || \
75                              (PRINTF("ASSERT: %s line: %d\n", __FILE__, __LINE__), \
76                               infinite_loop() /*abort()*/,                         \
77                               0))
78 
79 
80 
81 #define ASSERTMSG(exp, ...) (void) ((exp) || \
82                                     (PRINTF("ASSERTMSG: %s line: %d ", __FILE__, __LINE__), \
83                                      PRINTF(__VA_ARGS__),                                   \
84                                      PRINTF("\n"),                                          \
85                                      infinite_loop() /*abort()*/,                           \
86                                      0))
87 
88 #define LOG(...) if(nn::rdt::CTR::GetLogLevel()==nn::rdt::CTR::LOG_LEVEL_ALL)(void) (PRINTF(__VA_ARGS__))
89 
90 #define VERBOSE(...) (void)(0)
91 
92 
93 #ifdef _WIN32
94 #define ALIGN_ASSERT(exp, align) ASSERTMSG( ((uptr)(exp)) % (align) == 0, "%s must be %d byte aligned.", #exp, align )
95 #elif defined(NN_PLATFORM_CTR)
96 #define ALIGN_ASSERT(exp, align) NN_ALIGN_ASSERT(exp, align)
97 #endif
98 
99 //#define alignof(type) ((int)offsetof(struct { char top; type bot; }, bot))
100 template <class T>
101 class Align{
102 public:
Align(void)103     Align(void)
104     {
105         struct S{
106             char top;  // 1バイトの変数が欲しいだけ。
107             T    t;
108         };
109 
110         LOG("offset: %d\n", offsetof(S, t));
111     }
112 };
113 
114 
115 namespace nn { namespace rdt { namespace CTR {
116 
117 // 先行宣言
118 class Sender;
119 class Receiver;
120 
121 // ネットワークの準備/後始末を行います。
122 // データ通信ができる状況にまでもっていくことが目的です。
123 void SetupNetwork  (void);
124 void CleanupNetwork(void);
125 
126 // インスタンスの作成・削除。Create()系関数で返されたポインタをDestroy()して下さい。
127 Sender*   CreateSender   (u16 port, void *pSendBuf, u16 sendBufSize);
128 void      DestroySender  (Sender *s);
129 
130 Receiver* CreateReceiver (u16 port, void *pRecvBuf, u16 recvBufSize);
131 void      DestroyReceiver(Receiver *r);
132 
133 // スレッドの休眠。Windows環境とCTR環境の違いを内部実装で吸収している。
134 void SleepCurrentThread(s32 msec);
135 
136 
137 // バッファへのポインタがNULLポインタだったときに使う。
MakeNullPointerResult(void)138 inline nn::Result MakeNullPointerResult(void)
139 {
140     return MakeUsageResult(
141         Result::SUMMARY_INVALID_ARGUMENT,
142         Result::MODULE_NN_RDT,
143         Result::DESCRIPTION_INVALID_POINTER);
144 }
145 
146 
147 // バッファの長さを表す引数がゼロだったときに使う。
MakeZeroSizeResult(void)148 inline nn::Result MakeZeroSizeResult(void)
149 {
150     return MakeUsageResult(
151         Result::SUMMARY_INVALID_ARGUMENT,
152         Result::MODULE_NN_RDT,
153         Result::DESCRIPTION_INVALID_SIZE);
154 }
155 
156 
157 // 関数を呼ぶべきステートではなかったときに使う。
MakeInvalidState(void)158 inline nn::Result MakeInvalidState(void)
159 {
160     return MakeStatusResult(
161         Result::SUMMARY_INVALID_STATE,
162         Result::MODULE_NN_RDT,
163         Result::DESCRIPTION_INVALID_RESULT_VALUE);  // TORIAEZU。この値は適切ではない気がするが…。
164 }
165 
166 
167 // 未実装の関数の返値…。
MakeNotImplemented(void)168 inline nn::Result MakeNotImplemented(void)
169 {
170     return MakeFatalResult(
171         Result::SUMMARY_INTERNAL,
172         Result::MODULE_NN_RDT,
173         Result::DESCRIPTION_NOT_IMPLEMENTED);
174 }
175 
176 
177 // リソース確保に失敗
MakeResourceAllocationFailure(void)178 inline nn::Result MakeResourceAllocationFailure(void)
179 {
180     return MakeStatusResult(
181         Result::SUMMARY_OUT_OF_RESOURCE,
182         Result::MODULE_NN_RDT,
183         Result::DESCRIPTION_OUT_OF_MEMORY);   // TORIAEZU。メモリ以外のリソースが不足していた場合のDESCRIPTIONが欲しい…。
184 }
185 
186 
187 // 初期化済み状態の時に初期化しようとしたケースで返される。
MakeAlreadyInitialized(void)188 inline nn::Result MakeAlreadyInitialized(void)
189 {
190         return MakeInfoResult(
191             Result::SUMMARY_NOTHING_HAPPENED,
192             Result::MODULE_NN_RDT,
193             Result::DESCRIPTION_ALREADY_INITIALIZED);
194 }
195 
196 
197 // リモートからRSTを受け取ったときに、ユーザーにそれを伝えるためのエラーコード。
MakeResetReceived(void)198 inline nn::Result MakeResetReceived(void)
199 {
200         return MakeReInitResult(
201             Result::SUMMARY_CANCELLED,            // TORIAEZU。
202             Result::MODULE_NN_RDT,
203             Result::DESCRIPTION_CANCEL_REQUESTED);  // TORIAEZU。
204 }
205 
206 
207 // 接続が失われたときのエラー。
MakeDisconnected(void)208 inline nn::Result MakeDisconnected(void)
209 {
210         return MakeReInitResult(
211             Result::SUMMARY_OUT_OF_RESOURCE,
212             Result::MODULE_NN_RDT,
213             Result::DESCRIPTION_NOT_FOUND);       // TORIAEZU。
214 }
215 
216 
217 // 受信セグメントが無かった(まだ到着していない)場合。
MakeNoData(void)218 inline nn::Result MakeNoData(void)
219 {
220     return MakeTemporaryResult(
221         Result::SUMMARY_NOT_FOUND,
222         Result::MODULE_NN_RDT,
223         Result::DESCRIPTION_NO_DATA);
224 }
225 
226 
227 // やや引っかかるところはあるが、エラーを宣告するほどではない時に使う。
MakeNothingHappened(void)228 inline nn::Result MakeNothingHappened(void)
229 {
230         return MakeInfoResult(
231             Result::SUMMARY_NOTHING_HAPPENED,
232             Result::MODULE_NN_RDT,
233             Result::DESCRIPTION_SUCCESS);
234 }
235 
236 #ifdef _WIN32
237 // サーバー側のソケットのセットアップ、クリーンアップを実行する。Windows専用。
238 // 内部でlisten(), accept()などの処理を実行し、データを送受信できる状態にまで
239 // 持って行く。
240 SOCKET SetupServerSide(u16 port);
241 void CleanupServerSide(SOCKET sock);
242 
243 // クライアント側のソケットのセットアップ、クリーンアップを実行する。
244 // 内部ではconnect()等の処理を実行し、データを送受信できる状態にまで
245 // 持って行く。
246 SOCKET SetupClientSide(u16 port);
247 void CleanupClientSide(SOCKET sock);
248 
249 // 利用可能なポート番号を返す。
250 u16 GetAvailablePort(void);
251 
252 // ミリセカンド型。
253 typedef clock_t MSEC_T;
254 MSEC_T GetCurrentTimeAsMillisecond(void);
255 
256 #else
257 template <class T>
min(T a,T b)258 T min(T a, T b)
259 {
260     return a < b ? a : b;
261 }
262 
263 template <class T>
max(T a,T b)264 T max(T a, T b)
265 {
266     return a > b ? a : b;
267 }
268 
269 
270 // ミリセカンド型。
271 typedef s64 MSEC_T;
272 MSEC_T GetCurrentTimeAsMillisecond(void);
273 
274 
275 void PrintResultCode(nn::Result r);
276 
277 #endif // end of _WIN32
278 
279 
280 // この関数を呼び出した時点で、どれだけスタックが食いつぶされているかを得る。
281 void stackChecker(void);
282 
283 
284 }}} // namespace nn::rdt::CTR
285 
286 #endif  // end of NN_RDT_UTILITY_H_
287