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