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); // Zero is returned 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 waiting for connection
66 struct sockaddr_in addr; // Information of socket to establish a pair with client that connects
67 struct sockaddr_in client; // Stores information of newly 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); // Example of deliberate failure.
75 if(sock0==INVALID_SOCKET)
76 {
77 cout << "socket() failed." << "Error: " << WSAGetLastError() << endl;
78 abort();
79 }
80
81 // Socket settings
82 addr.sin_family = AF_INET;
83 addr.sin_port = htons(port); // Byte order conversion. 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 errors, listen() returns zero.
96
97
98 // Allow connections
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 // Make 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 to specify connection destination
139 server.sin_family = AF_INET;
140 server.sin_port = htons(port); // Network byte order conversion
141 server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
142
143 // Connect to server. If no errors occur, connect() returns zero.
144 int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
145 assert(ret==0);
146
147 // Make 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 // Returns the port number that can be used.
169 // Port numbers are differentiated for debug builds and release builds
170 // (targeting 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 numbers that can be freely used are nos. 49152 - 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("Sender initialization failed! \n");
209 }
210 return s;
211 }
212 else
213 {
214 PANIC("Failed to create socket. \n");
215 return NULL;
216 }
217 }
218 else
219 {
220 PANIC("%s 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("Receiver initialization failed! \n");
255 }
256 return r;
257 }
258 else
259 {
260 PANIC("Failed to create socket. \n");
261 return NULL;
262 }
263 }
264 else
265 {
266 PANIC("%s 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 // When this function was called, gets how much of the stack was 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