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