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