1 /*--------------------------------------------------------------------------
2 Project: HorizonSDK
3 File: rdt_Utility.cpp
4 Copyright 2009 Nintendo. All rights reserved.
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10 $Date:: 2010-10-19#$
11 $Rev: 28318 $
12 $Author: hiratsu_daisuke $
13 *-------------------------------------------------------------------------
14
15
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 // Specifies winsock version. Seems to be three types: 1.0, 1.1, and 2.0.
52 int result = WSAStartup(MAKEWORD(2, 0), &s_wsaData);
53 assert(result==0); // Zero is returned if successful.
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; // Socket waiting for connection
68 struct sockaddr_in addr; // Information of socket to establish a pair with client that connects
69 struct sockaddr_in client; // Stores information of newly connected client
70 int len;
71 SOCKET sock;
72 int result = 0;
73
74 // Create socket
75 sock0 = socket(AF_INET, SOCK_STREAM, 0);
76 // sock0 = socket(AF_UNSPEC, SOCK_STREAM, 0); // Example of deliberate failure.
77 if(sock0==INVALID_SOCKET)
78 {
79 cout << "socket() failed." << "Error: " << WSAGetLastError() << endl;
80 abort();
81 }
82
83 // Socket settings
84 addr.sin_family = AF_INET;
85 addr.sin_port = htons(port); // Byte order conversion. 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 // Wait
96 result = listen(sock0, 5);
97 assert(result==0); // If no errors, listen() returns zero.
98
99
100 // Allow connections
101 len = sizeof(client);
102 //// cout << "Before the accept function was called, 'len' was " << 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 << "After the accept function was called, 'len' became " << len << "." << endl;
110
111 // Make socket to non-blocking mode
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 session end
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 // Structure to specify connection destination
141 server.sin_family = AF_INET;
142 server.sin_port = htons(port); // Network byte order conversion
143 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
144
145 // Connect to server. If no errors occur, connect() returns zero.
146 int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
147 assert(ret==0);
148
149 // Make socket to non-blocking mode
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 // Returns the port number that can be used.
171 // Port numbers are differentiated for debug builds and release builds
172 // (targeting simultaneous execution)
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 // Port numbers that can be freely used are nos. 49152 - 65535
188 ASSERT((49152<=ret) && (ret <= 65535));
189 return ret;
190 }
191
192
193 // Create and destroy instances.
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 initialization failed! \n");
211 }
212 return s;
213 }
214 else
215 {
216 PANIC("Failed to create socket. \n");
217 return NULL;
218 }
219 }
220 else
221 {
222 PANIC("%s called multiple times. \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 initialization failed! \n");
257 }
258 return r;
259 }
260 else
261 {
262 PANIC("Failed to create socket. \n");
263 return NULL;
264 }
265 }
266 else
267 {
268 PANIC("%s called multiple times. \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 // Below is for 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 // When this function was called, gets how much of the stack was consumed.
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