1 /*--------------------------------------------------------------------------
2 Project: HorizonSDK
3 File: rdt_Utility.cpp
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 #include "rdt_Utility.h"
21
22 #include <nn/rdt/CTR/rdt_Sender.h>
23 #include <nn/rdt/CTR/rdt_Receiver.h>
24
25 #ifdef _WIN32
26 #include <iostream>
27 #include <assert.h>
28 #else
29 #include <nn/os.h>
30 #include <nn/fnd.h>
31 #include <nn/dbg.h>
32 #endif // end of _WIN32
33
34 namespace
35 {
36 #ifdef _WIN32
37 WSADATA s_wsaData;
38 SOCKET s_sendSock = INVALID_SOCKET;
39 SOCKET s_recvSock = INVALID_SOCKET;
40 u8 s_senderWorkBuf[nn::rdt::CTR::Sender::SENDER_WORKBUF_SIZE];
41 u8 s_receiverWorkBuf[nn::rdt::CTR::Receiver::RECEIVER_WORKBUF_SIZE];
42 #endif
43 } // end of anonymous namespace
44
45 namespace nn { namespace rdt { namespace CTR {
46
47
48 #ifdef _WIN32
SetupNetwork(void)49 void SetupNetwork(void)
50 {
51 // winsockのバージョン指定。1.0, 1.1, 2.0の三種類あるらしい。
52 int result = WSAStartup(MAKEWORD(2, 0), &s_wsaData);
53 assert(result==0); // 成功すれば、ゼロが返される。
54 }
55
56
CleanupNetwork(void)57 void CleanupNetwork(void)
58 {
59 WSACleanup();
60 }
61
62
SetupServerSide(u16 port)63 SOCKET SetupServerSide(u16 port)
64 {
65 using namespace std;
66
67 SOCKET sock0; // 接続待ち用ソケット
68 struct sockaddr_in addr; // 接続してきたクライアントとペアをなすソケットの情報
69 struct sockaddr_in client; // 接続してきたクライアントの情報を保持
70 int len;
71 SOCKET sock;
72 int result = 0;
73
74 // ソケット作成
75 sock0 = socket(AF_INET, SOCK_STREAM, 0);
76 // sock0 = socket(AF_UNSPEC, SOCK_STREAM, 0); // わざと失敗する例。
77 if(sock0==INVALID_SOCKET)
78 {
79 cout << "socket() failed." << "Error: " << WSAGetLastError() << endl;
80 abort();
81 }
82
83 // ソケット設定
84 addr.sin_family = AF_INET;
85 addr.sin_port = htons(port); // バイトオーダーの変換。 Host to Network short。
86 addr.sin_addr.S_un.S_addr = INADDR_ANY;
87 result = bind(sock0, (struct sockaddr*)&addr, sizeof(addr));
88 if(result!=0)
89 {
90 cout << "port: " << port << endl;
91 cout << "bind() failed. " << "Error: " << WSAGetLastError() << endl;
92 abort();
93 }
94
95 // 待ち受け
96 result = listen(sock0, 5);
97 assert(result==0); // エラー無しなら、listen()はゼロを返す。
98
99
100 // 接続を許可
101 len = sizeof(client);
102 //// cout << "accept()呼び出し前、lenは" << len << "でした。" << endl;
103 sock = accept(sock0, (struct sockaddr*)&client, &len);
104 if(sock==INVALID_SOCKET)
105 {
106 cout << "accept() failed." << "Error: " << WSAGetLastError() << endl;
107 abort();
108 }
109 //// cout << "accept()呼び出し後、lenは" << len << "になりました。" << endl;
110
111 // ソケットをノンブロッキングモードに
112 {
113 u_long val = 1;
114 int ret = ioctlsocket(sock, FIONBIO, &val);
115 if(ret!=0)
116 {
117 printf("error: %d\n", ret);
118 abort();
119 }
120 }
121
122 return sock;
123 }
124
125
CleanupServerSide(SOCKET sock)126 void CleanupServerSide(SOCKET sock)
127 {
128 // TCPセッション終了
129 closesocket(sock);
130 }
131
132
SetupClientSide(u16 port)133 SOCKET SetupClientSide(u16 port)
134 {
135 struct sockaddr_in server;
136 SOCKET sock;
137
138 sock = socket(AF_INET, SOCK_STREAM, 0);
139
140 // 接続先指定用構造体
141 server.sin_family = AF_INET;
142 server.sin_port = htons(port); // ネットワークバイトオーダーの変換
143 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
144
145 // サーバに接続。エラーが起こらなければ、connect()はゼロを返す。
146 int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
147 assert(ret==0);
148
149 // ソケットをノンブロッキングモードに
150 {
151 u_long val = 1;
152 int ret = ioctlsocket(sock, FIONBIO, &val);
153 if(ret!=0)
154 {
155 printf("error: %d\n", ret);
156 abort();
157 }
158 }
159
160 return sock;
161 }
162
163
CleanupClientSide(SOCKET sock)164 void CleanupClientSide(SOCKET sock)
165 {
166 closesocket(sock);
167 }
168
169
170 // 利用可能なポート番号を返す。
171 // デバッグビルド・リリースビルドでポート番号を使い分ける
172 // (同時実行を狙っているので)
GetAvailablePort(void)173 u16 GetAvailablePort(void)
174 {
175 const u16 PERIOD = 5000;
176 #ifdef NDEBUG
177 const u16 OFFSET = 50000;
178 #else
179 const u16 OFFSET = 50000 + PERIOD;
180 #endif
181
182 static u16 s_counter = 0;
183
184 u16 ret = s_counter + OFFSET;
185 s_counter = (s_counter + 1) % PERIOD;
186
187 // 自由に使えるポート番号は、49152番 - 65535番
188 ASSERT((49152<=ret) && (ret <= 65535));
189 return ret;
190 }
191
192
193 // インスタンスの作成・削除。
CreateSender(u16 port,void * pSendBuf,u16 sendBufSize)194 Sender* CreateSender(u16 port, void *pSendBuf, u16 sendBufSize)
195 {
196 if(s_sendSock==INVALID_SOCKET)
197 {
198 s_sendSock = SetupClientSide(port);
199 if(s_sendSock!=INVALID_SOCKET)
200 {
201 Sender *s = new Sender();
202 SenderConfig cfg;
203 cfg.pWorkBuf = s_senderWorkBuf;
204 cfg.pSendBuf = pSendBuf;
205 cfg.sendBufSize = sendBufSize;
206 cfg.sock = s_sendSock;
207 nn::Result result = s->Initialize(cfg);
208 if(result.IsFailure())
209 {
210 PANIC("Senderの初期化に失敗!\n");
211 }
212 return s;
213 }
214 else
215 {
216 PANIC("ソケットの作成に失敗しました。\n");
217 return NULL;
218 }
219 }
220 else
221 {
222 PANIC("%sが多重に呼ばれています。\n", __FUNCTION__);
223 return NULL;
224 }
225 }
226
227
DestroySender(Sender * s)228 void DestroySender(Sender *s)
229 {
230 ASSERT(s!=NULL);
231 ASSERT(s_sendSock!=INVALID_SOCKET);
232
233 s->Finalize();
234 delete s;
235 CleanupClientSide(s_sendSock);
236 s_sendSock = INVALID_SOCKET;
237 }
238
239
CreateReceiver(u16 port,void * pRecvBuf,u16 recvBufSize)240 Receiver* CreateReceiver (u16 port, void *pRecvBuf, u16 recvBufSize)
241 {
242 if(s_recvSock==INVALID_SOCKET)
243 {
244 s_recvSock = SetupServerSide(port);
245 if(s_recvSock!=INVALID_SOCKET)
246 {
247 Receiver *r = new Receiver();
248 ReceiverConfig cfg;
249 cfg.pWorkBuf = s_receiverWorkBuf;
250 cfg.pRecvBuf = pRecvBuf;
251 cfg.recvBufSize = recvBufSize;
252 cfg.sock = s_recvSock;
253 nn::Result result = r->Initialize(cfg);
254 if(result.IsFailure())
255 {
256 PANIC("Receiverの初期化に失敗!\n");
257 }
258 return r;
259 }
260 else
261 {
262 PANIC("ソケットの作成に失敗しました。\n");
263 return NULL;
264 }
265 }
266 else
267 {
268 PANIC("%sが多重に呼ばれています。\n", __FUNCTION__);
269 return NULL;
270 }
271 }
272
273
DestroyReceiver(Receiver * r)274 void DestroyReceiver(Receiver *r)
275 {
276 ASSERT(r!=NULL);
277 ASSERT(s_recvSock!=INVALID_SOCKET);
278
279 delete r;
280 CleanupClientSide(s_recvSock);
281 s_recvSock = INVALID_SOCKET;
282 }
283
284
SleepCurrentThread(s32 msec)285 void SleepCurrentThread(s32 msec)
286 {
287 Sleep(msec);
288 }
289
290
GetCurrentTimeAsMillisecond(void)291 MSEC_T GetCurrentTimeAsMillisecond(void)
292 {
293 return clock();
294 }
295
296
297 #else
298 // 以下、CTR用。
299
300
301 void SleepCurrentThread(s32 msec)
302 {
303 nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(msec));
304 }
305
306
307 MSEC_T GetCurrentTimeAsMillisecond(void)
308 {
309 return nn::os::Tick::GetSystemCurrent().ToTimeSpan().GetMilliSeconds();
310 }
311
312
313 void PrintResultCode(nn::Result r)
314 {
315 if(GetLogLevel()==LOG_LEVEL_ALL)
316 {
317 if(r.IsSuccess())
318 {
319 LOG("Success.\n");
320 }
321 else
322 {
323 LOG("Failure...\n");
324 nn::dbg::PrintResult(r);
325 }
326 }
327 }
328
329
330 #endif
331
332 // この関数を呼び出した時点で、どれだけスタックが食いつぶされているかを得る。
stackChecker(void)333 void stackChecker(void)
334 {
335 int dmy;
336 #ifdef NN_SWITCH_DISABLE_DEBUG_PRINT
337 NN_UNUSED_VAR(dmy);
338 #endif
339 LOG("addr: 0x%08x\n", &dmy);
340 LOG("%d bytes used.\n", 0x0fffffff - reinterpret_cast<u32>(&dmy));
341 }
342
343
344
345 }}} // namespace nn::rdt::CTR
346