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