1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: rdt_Utility.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. 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 $Rev: 46347 $
14 *---------------------------------------------------------------------------*/
15
16 #include "stdafx.h"
17
18 #include "rdt_Utility.h"
19
20 #include <nn/rdt/CTR/rdt_Sender.h>
21 #include <nn/rdt/CTR/rdt_Receiver.h>
22
23 #ifdef _WIN32
24 #include <iostream>
25 #include <assert.h>
26 #else
27 #include <nn/os.h>
28 #include <nn/fnd.h>
29 #include <nn/dbg.h>
30 #endif // end of _WIN32
31
32 namespace
33 {
34 #ifdef _WIN32
35 WSADATA s_wsaData;
36 SOCKET s_sendSock = INVALID_SOCKET;
37 SOCKET s_recvSock = INVALID_SOCKET;
38 u8 s_senderWorkBuf[nn::rdt::CTR::Sender::SENDER_WORKBUF_SIZE];
39 u8 s_receiverWorkBuf[nn::rdt::CTR::Receiver::RECEIVER_WORKBUF_SIZE];
40 #endif
41 } // End of anonymous namespace
42
43 namespace nn { namespace rdt { namespace CTR {
44
45
46 #ifdef _WIN32
SetupNetwork(void)47 void SetupNetwork(void)
48 {
49 // Specifies winsock version. Seems to be three types: 1.0, 1.1, and 2.0.
50 int result = WSAStartup(MAKEWORD(2, 0), &s_wsaData);
51 assert(result==0); // Returns zero if successful.
52 }
53
54
CleanupNetwork(void)55 void CleanupNetwork(void)
56 {
57 WSACleanup();
58 }
59
60
SetupServerSide(u16 port)61 SOCKET SetupServerSide(u16 port)
62 {
63 using namespace std;
64
65 SOCKET sock0; // Socket for waiting for connections.
66 struct sockaddr_in addr; // Information for a socket that forms a pair with a connected client.
67 struct sockaddr_in client; // Maintains the information for the connected client.
68 int len;
69 SOCKET sock;
70 int result = 0;
71
72 // Create socket
73 sock0 = socket(AF_INET, SOCK_STREAM, 0);
74 // sock0 = socket(AF_UNSPEC, SOCK_STREAM, 0); // A deliberate example of a failure.
75 if(sock0==INVALID_SOCKET)
76 {
77 cout << "socket() failed." << "Error: " << WSAGetLastError() << endl;
78 abort();
79 }
80
81 // Socket setting
82 addr.sin_family = AF_INET;
83 addr.sin_port = htons(port); // Change byte order. Host to Network short.
84 addr.sin_addr.S_un.S_addr = INADDR_ANY;
85 result = bind(sock0, (struct sockaddr*)&addr, sizeof(addr));
86 if(result!=0)
87 {
88 cout << "port: " << port << endl;
89 cout << "bind() failed. " << "Error: " << WSAGetLastError() << endl;
90 abort();
91 }
92
93 // Wait
94 result = listen(sock0, 5);
95 assert(result==0); // If no error, the listen function returns zero.
96
97
98 // Connection is permitted
99 len = sizeof(client);
100 //// cout << "Before the accept function was called, 'len' was " << len << "." << endl;
101 sock = accept(sock0, (struct sockaddr*)&client, &len);
102 if(sock==INVALID_SOCKET)
103 {
104 cout << "accept() failed." << "Error: " << WSAGetLastError() << endl;
105 abort();
106 }
107 //// cout << "After the accept function was called, 'len' became " << len << "." << endl;
108
109 // Socket to non-blocking mode.
110 {
111 u_long val = 1;
112 int ret = ioctlsocket(sock, FIONBIO, &val);
113 if(ret!=0)
114 {
115 printf("error: %d\n", ret);
116 abort();
117 }
118 }
119
120 return sock;
121 }
122
123
CleanupServerSide(SOCKET sock)124 void CleanupServerSide(SOCKET sock)
125 {
126 // TCP session end.
127 closesocket(sock);
128 }
129
130
SetupClientSide(u16 port)131 SOCKET SetupClientSide(u16 port)
132 {
133 struct sockaddr_in server;
134 SOCKET sock;
135
136 sock = socket(AF_INET, SOCK_STREAM, 0);
137
138 // Structure for specifying connection destination.
139 server.sin_family = AF_INET;
140 server.sin_port = htons(port); // Change network byte order.
141 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
142
143 // Connect to server. If no error occurs, the connect function returns zero.
144 int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
145 assert(ret==0);
146
147 // Socket to non-blocking mode.
148 {
149 u_long val = 1;
150 int ret = ioctlsocket(sock, FIONBIO, &val);
151 if(ret!=0)
152 {
153 printf("error: %d\n", ret);
154 abort();
155 }
156 }
157
158 return sock;
159 }
160
161
CleanupClientSide(SOCKET sock)162 void CleanupClientSide(SOCKET sock)
163 {
164 closesocket(sock);
165 }
166
167
168 // Return the port numbers that can be used.
169 // Port number use is distinguished for debug builds and release builds
170 // (because the aim is for simultaneous execution).
GetAvailablePort(void)171 u16 GetAvailablePort(void)
172 {
173 const u16 PERIOD = 5000;
174 #ifdef NDEBUG
175 const u16 OFFSET = 50000;
176 #else
177 const u16 OFFSET = 50000 + PERIOD;
178 #endif
179
180 static u16 s_counter = 0;
181
182 u16 ret = s_counter + OFFSET;
183 s_counter = (s_counter + 1) % PERIOD;
184
185 // Port number that can be freely used are 49152 to 65535.
186 ASSERT((49152<=ret) && (ret <= 65535));
187 return ret;
188 }
189
190
191 // Create and destroy instances.
CreateSender(u16 port,void * pSendBuf,u16 sendBufSize)192 Sender* CreateSender(u16 port, void *pSendBuf, u16 sendBufSize)
193 {
194 if(s_sendSock==INVALID_SOCKET)
195 {
196 s_sendSock = SetupClientSide(port);
197 if(s_sendSock!=INVALID_SOCKET)
198 {
199 Sender *s = new Sender();
200 SenderConfig cfg;
201 cfg.pWorkBuf = s_senderWorkBuf;
202 cfg.pSendBuf = pSendBuf;
203 cfg.sendBufSize = sendBufSize;
204 cfg.sock = s_sendSock;
205 nn::Result result = s->Initialize(cfg);
206 if(result.IsFailure())
207 {
208 PANIC("Failed to initialize Sender! \n");
209 }
210 return s;
211 }
212 else
213 {
214 PANIC("Socket creation failed. \n");
215 return NULL;
216 }
217 }
218 else
219 {
220 PANIC("%s was called multiple times. \n", __FUNCTION__);
221 return NULL;
222 }
223 }
224
225
DestroySender(Sender * s)226 void DestroySender(Sender *s)
227 {
228 ASSERT(s!=NULL);
229 ASSERT(s_sendSock!=INVALID_SOCKET);
230
231 s->Finalize();
232 delete s;
233 CleanupClientSide(s_sendSock);
234 s_sendSock = INVALID_SOCKET;
235 }
236
237
CreateReceiver(u16 port,void * pRecvBuf,u16 recvBufSize)238 Receiver* CreateReceiver (u16 port, void *pRecvBuf, u16 recvBufSize)
239 {
240 if(s_recvSock==INVALID_SOCKET)
241 {
242 s_recvSock = SetupServerSide(port);
243 if(s_recvSock!=INVALID_SOCKET)
244 {
245 Receiver *r = new Receiver();
246 ReceiverConfig cfg;
247 cfg.pWorkBuf = s_receiverWorkBuf;
248 cfg.pRecvBuf = pRecvBuf;
249 cfg.recvBufSize = recvBufSize;
250 cfg.sock = s_recvSock;
251 nn::Result result = r->Initialize(cfg);
252 if(result.IsFailure())
253 {
254 PANIC("Failed to initialize Receiver! \n");
255 }
256 return r;
257 }
258 else
259 {
260 PANIC("Socket creation failed. \n");
261 return NULL;
262 }
263 }
264 else
265 {
266 PANIC("%s was called multiple times. \n", __FUNCTION__);
267 return NULL;
268 }
269 }
270
271
DestroyReceiver(Receiver * r)272 void DestroyReceiver(Receiver *r)
273 {
274 ASSERT(r!=NULL);
275 ASSERT(s_recvSock!=INVALID_SOCKET);
276
277 delete r;
278 CleanupClientSide(s_recvSock);
279 s_recvSock = INVALID_SOCKET;
280 }
281
282
SleepCurrentThread(s32 msec)283 void SleepCurrentThread(s32 msec)
284 {
285 Sleep(msec);
286 }
287
288
GetCurrentTimeAsMillisecond(void)289 MSEC_T GetCurrentTimeAsMillisecond(void)
290 {
291 return clock();
292 }
293
294
295 #else
296 // Below is for CTR.
297
298
299 void SleepCurrentThread(s32 msec)
300 {
301 nn::os::Thread::Sleep(nn::fnd::TimeSpan::FromMilliSeconds(msec));
302 }
303
304
305 MSEC_T GetCurrentTimeAsMillisecond(void)
306 {
307 return nn::os::Tick::GetSystemCurrent().ToTimeSpan().GetMilliSeconds();
308 }
309
310
311 void PrintResultCode(nn::Result r)
312 {
313 if(GetLogLevel()==LOG_LEVEL_ALL)
314 {
315 if(r.IsSuccess())
316 {
317 LOG("Success.\n");
318 }
319 else
320 {
321 LOG("Failure...\n");
322 NN_DBG_TPRINT_RESULT_(r);
323 }
324 }
325 }
326
327
328 #endif
329
330 // At the time this function is called, it gets how much stack is being consumed.
stackChecker(void)331 void stackChecker(void)
332 {
333 int dmy;
334 #ifdef NN_SWITCH_DISABLE_DEBUG_PRINT
335 NN_UNUSED_VAR(dmy);
336 #endif
337 LOG("addr: 0x%08x\n", &dmy);
338 LOG("%d bytes used.\n", 0x0fffffff - reinterpret_cast<u32>(&dmy));
339 }
340
341
342
343 }}} // namespace nn::rdt::CTR
344