soc_u.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/platform.h"
  5. #if EMU_PLATFORM == PLATFORM_WINDOWS
  6. #include <winsock2.h>
  7. #include <ws2tcpip.h>
  8. // MinGW does not define several errno constants
  9. #ifndef _MSC_VER
  10. #define EBADMSG 104
  11. #define ENODATA 120
  12. #define ENOMSG 122
  13. #define ENOSR 124
  14. #define ENOSTR 125
  15. #define ETIME 137
  16. #define EIDRM 2001
  17. #define ENOLINK 2002
  18. #endif // _MSC_VER
  19. #else
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <netdb.h>
  23. #include <arpa/inet.h>
  24. #include <fcntl.h>
  25. #include <poll.h>
  26. #endif
  27. #include "common/log.h"
  28. #include "common/scope_exit.h"
  29. #include "core/hle/hle.h"
  30. #include "core/hle/service/soc_u.h"
  31. #include <unordered_map>
  32. #if EMU_PLATFORM == PLATFORM_WINDOWS
  33. # define WSAEAGAIN WSAEWOULDBLOCK
  34. # define WSAEMULTIHOP -1 // Invalid dummy value
  35. # define ERRNO(x) WSA##x
  36. # define GET_ERRNO WSAGetLastError()
  37. # define poll(x, y, z) WSAPoll(x, y, z);
  38. #else
  39. # define ERRNO(x) x
  40. # define GET_ERRNO errno
  41. # define closesocket(x) close(x)
  42. #endif
  43. static const s32 SOCKET_ERROR_VALUE = -1;
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////
  45. // Namespace SOC_U
  46. namespace SOC_U {
  47. /// Holds the translation from system network errors to 3DS network errors
  48. static const std::unordered_map<int, int> error_map = { {
  49. { E2BIG, 1 },
  50. { ERRNO(EACCES), 2 },
  51. { ERRNO(EADDRINUSE), 3 },
  52. { ERRNO(EADDRNOTAVAIL), 4 },
  53. { ERRNO(EAFNOSUPPORT), 5 },
  54. { ERRNO(EAGAIN), 6 },
  55. { ERRNO(EALREADY), 7 },
  56. { ERRNO(EBADF), 8 },
  57. { EBADMSG, 9 },
  58. { EBUSY, 10 },
  59. { ECANCELED, 11 },
  60. { ECHILD, 12 },
  61. { ERRNO(ECONNABORTED), 13 },
  62. { ERRNO(ECONNREFUSED), 14 },
  63. { ERRNO(ECONNRESET), 15 },
  64. { EDEADLK, 16 },
  65. { ERRNO(EDESTADDRREQ), 17 },
  66. { EDOM, 18 },
  67. { ERRNO(EDQUOT), 19 },
  68. { EEXIST, 20 },
  69. { ERRNO(EFAULT), 21 },
  70. { EFBIG, 22 },
  71. { ERRNO(EHOSTUNREACH), 23 },
  72. { EIDRM, 24 },
  73. { EILSEQ, 25 },
  74. { ERRNO(EINPROGRESS), 26 },
  75. { ERRNO(EINTR), 27 },
  76. { ERRNO(EINVAL), 28 },
  77. { EIO, 29 },
  78. { ERRNO(EISCONN), 30 },
  79. { EISDIR, 31 },
  80. { ERRNO(ELOOP), 32 },
  81. { ERRNO(EMFILE), 33 },
  82. { EMLINK, 34 },
  83. { ERRNO(EMSGSIZE), 35 },
  84. { ERRNO(EMULTIHOP), 36 },
  85. { ERRNO(ENAMETOOLONG), 37 },
  86. { ERRNO(ENETDOWN), 38 },
  87. { ERRNO(ENETRESET), 39 },
  88. { ERRNO(ENETUNREACH), 40 },
  89. { ENFILE, 41 },
  90. { ERRNO(ENOBUFS), 42 },
  91. { ENODATA, 43 },
  92. { ENODEV, 44 },
  93. { ENOENT, 45 },
  94. { ENOEXEC, 46 },
  95. { ENOLCK, 47 },
  96. { ENOLINK, 48 },
  97. { ENOMEM, 49 },
  98. { ENOMSG, 50 },
  99. { ERRNO(ENOPROTOOPT), 51 },
  100. { ENOSPC, 52 },
  101. { ENOSR, 53 },
  102. { ENOSTR, 54 },
  103. { ENOSYS, 55 },
  104. { ERRNO(ENOTCONN), 56 },
  105. { ENOTDIR, 57 },
  106. { ERRNO(ENOTEMPTY), 58 },
  107. { ERRNO(ENOTSOCK), 59 },
  108. { ENOTSUP, 60 },
  109. { ENOTTY, 61 },
  110. { ENXIO, 62 },
  111. { ERRNO(EOPNOTSUPP), 63 },
  112. { EOVERFLOW, 64 },
  113. { EPERM, 65 },
  114. { EPIPE, 66 },
  115. { EPROTO, 67 },
  116. { ERRNO(EPROTONOSUPPORT), 68 },
  117. { ERRNO(EPROTOTYPE), 69 },
  118. { ERANGE, 70 },
  119. { EROFS, 71 },
  120. { ESPIPE, 72 },
  121. { ESRCH, 73 },
  122. { ERRNO(ESTALE), 74 },
  123. { ETIME, 75 },
  124. { ERRNO(ETIMEDOUT), 76 }
  125. }};
  126. /// Converts a network error from platform-specific to 3ds-specific
  127. static int TranslateError(int error) {
  128. auto found = error_map.find(error);
  129. if (found != error_map.end())
  130. return -found->second;
  131. return error;
  132. }
  133. /// Holds information about a particular socket
  134. struct SocketHolder {
  135. u32 socket_fd; ///< The socket descriptor
  136. bool blocking; ///< Whether the socket is blocking or not, it is only read on Windows.
  137. };
  138. /// Structure to represent the 3ds' pollfd structure, which is different than most implementations
  139. struct CTRPollFD {
  140. u32 fd; ///< Socket handle
  141. union Events {
  142. u32 hex; ///< The complete value formed by the flags
  143. BitField<0, 1, u32> pollin;
  144. BitField<1, 1, u32> pollpri;
  145. BitField<2, 1, u32> pollhup;
  146. BitField<3, 1, u32> pollerr;
  147. BitField<4, 1, u32> pollout;
  148. BitField<5, 1, u32> pollnval;
  149. Events& operator=(const Events& other) {
  150. hex = other.hex;
  151. return *this;
  152. }
  153. /// Translates the resulting events of a Poll operation from platform-specific to 3ds specific
  154. static Events TranslateTo3DS(u32 input_event) {
  155. Events ev = {};
  156. if (input_event & POLLIN)
  157. ev.pollin = 1;
  158. if (input_event & POLLPRI)
  159. ev.pollpri = 1;
  160. if (input_event & POLLHUP)
  161. ev.pollhup = 1;
  162. if (input_event & POLLERR)
  163. ev.pollerr = 1;
  164. if (input_event & POLLOUT)
  165. ev.pollout = 1;
  166. if (input_event & POLLNVAL)
  167. ev.pollnval = 1;
  168. return ev;
  169. }
  170. /// Translates the resulting events of a Poll operation from 3ds specific to platform specific
  171. static u32 TranslateToPlatform(Events input_event) {
  172. u32 ret = 0;
  173. if (input_event.pollin)
  174. ret |= POLLIN;
  175. if (input_event.pollpri)
  176. ret |= POLLPRI;
  177. if (input_event.pollhup)
  178. ret |= POLLHUP;
  179. if (input_event.pollerr)
  180. ret |= POLLERR;
  181. if (input_event.pollout)
  182. ret |= POLLOUT;
  183. if (input_event.pollnval)
  184. ret |= POLLNVAL;
  185. return ret;
  186. }
  187. };
  188. Events events; ///< Events to poll for (input)
  189. Events revents; ///< Events received (output)
  190. /// Converts a platform-specific pollfd to a 3ds specific structure
  191. static CTRPollFD FromPlatform(pollfd const& fd) {
  192. CTRPollFD result;
  193. result.events.hex = Events::TranslateTo3DS(fd.events).hex;
  194. result.revents.hex = Events::TranslateTo3DS(fd.revents).hex;
  195. result.fd = static_cast<u32>(fd.fd);
  196. return result;
  197. }
  198. /// Converts a 3ds specific pollfd to a platform-specific structure
  199. static pollfd ToPlatform(CTRPollFD const& fd) {
  200. pollfd result;
  201. result.events = Events::TranslateToPlatform(fd.events);
  202. result.revents = Events::TranslateToPlatform(fd.revents);
  203. result.fd = fd.fd;
  204. return result;
  205. }
  206. };
  207. /// Union to represent the 3ds' sockaddr structure
  208. union CTRSockAddr {
  209. /// Structure to represent a raw sockaddr
  210. struct {
  211. u8 len; ///< The length of the entire structure, only the set fields count
  212. u8 sa_family; ///< The address family of the sockaddr
  213. u8 sa_data[0x1A]; ///< The extra data, this varies, depending on the address family
  214. } raw;
  215. /// Structure to represent the 3ds' sockaddr_in structure
  216. struct CTRSockAddrIn {
  217. u8 len; ///< The length of the entire structure
  218. u8 sin_family; ///< The address family of the sockaddr_in
  219. u16 sin_port; ///< The port associated with this sockaddr_in
  220. u32 sin_addr; ///< The actual address of the sockaddr_in
  221. } in;
  222. /// Convert a 3DS CTRSockAddr to a platform-specific sockaddr
  223. static sockaddr ToPlatform(CTRSockAddr const& ctr_addr) {
  224. sockaddr result;
  225. result.sa_family = ctr_addr.raw.sa_family;
  226. memset(result.sa_data, 0, sizeof(result.sa_data));
  227. // We can not guarantee ABI compatibility between platforms so we copy the fields manually
  228. switch (result.sa_family) {
  229. case AF_INET:
  230. {
  231. sockaddr_in* result_in = reinterpret_cast<sockaddr_in*>(&result);
  232. result_in->sin_port = ctr_addr.in.sin_port;
  233. result_in->sin_addr.s_addr = ctr_addr.in.sin_addr;
  234. memset(result_in->sin_zero, 0, sizeof(result_in->sin_zero));
  235. break;
  236. }
  237. default:
  238. _dbg_assert_msg_(Service_SOC, false, "Unhandled address family (sa_family) in CTRSockAddr::ToPlatform");
  239. break;
  240. }
  241. return result;
  242. }
  243. /// Convert a platform-specific sockaddr to a 3DS CTRSockAddr
  244. static CTRSockAddr FromPlatform(sockaddr const& addr) {
  245. CTRSockAddr result;
  246. result.raw.sa_family = static_cast<u8>(addr.sa_family);
  247. // We can not guarantee ABI compatibility between platforms so we copy the fields manually
  248. switch (result.raw.sa_family) {
  249. case AF_INET:
  250. {
  251. sockaddr_in const* addr_in = reinterpret_cast<sockaddr_in const*>(&addr);
  252. result.raw.len = sizeof(CTRSockAddrIn);
  253. result.in.sin_port = addr_in->sin_port;
  254. result.in.sin_addr = addr_in->sin_addr.s_addr;
  255. break;
  256. }
  257. default:
  258. _dbg_assert_msg_(Service_SOC, false, "Unhandled address family (sa_family) in CTRSockAddr::ToPlatform");
  259. break;
  260. }
  261. return result;
  262. }
  263. };
  264. /// Holds info about the currently open sockets
  265. static std::unordered_map<u32, SocketHolder> open_sockets;
  266. /// Close all open sockets
  267. static void CleanupSockets() {
  268. for (auto sock : open_sockets)
  269. closesocket(sock.second.socket_fd);
  270. open_sockets.clear();
  271. }
  272. static void Socket(Service::Interface* self) {
  273. u32* cmd_buffer = Kernel::GetCommandBuffer();
  274. u32 domain = cmd_buffer[1]; // Address family
  275. u32 type = cmd_buffer[2];
  276. u32 protocol = cmd_buffer[3];
  277. // Only 0 is allowed according to 3dbrew, using 0 will let the OS decide which protocol to use
  278. if (protocol != 0) {
  279. cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
  280. return;
  281. }
  282. if (domain != AF_INET) {
  283. cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
  284. return;
  285. }
  286. if (type != SOCK_DGRAM && type != SOCK_STREAM) {
  287. cmd_buffer[1] = UnimplementedFunction(ErrorModule::SOC).raw; // TODO(Subv): Correct error code
  288. return;
  289. }
  290. u32 socket_handle = static_cast<u32>(::socket(domain, type, protocol));
  291. if ((s32)socket_handle != SOCKET_ERROR_VALUE)
  292. open_sockets[socket_handle] = { socket_handle, true };
  293. int result = 0;
  294. if ((s32)socket_handle == SOCKET_ERROR_VALUE)
  295. result = TranslateError(GET_ERRNO);
  296. cmd_buffer[1] = result;
  297. cmd_buffer[2] = socket_handle;
  298. }
  299. static void Bind(Service::Interface* self) {
  300. u32* cmd_buffer = Kernel::GetCommandBuffer();
  301. u32 socket_handle = cmd_buffer[1];
  302. u32 len = cmd_buffer[2];
  303. CTRSockAddr* ctr_sock_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6]));
  304. if (ctr_sock_addr == nullptr) {
  305. cmd_buffer[1] = -1; // TODO(Subv): Correct code
  306. return;
  307. }
  308. sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr);
  309. int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len));
  310. int result = 0;
  311. if (res != 0)
  312. result = TranslateError(GET_ERRNO);
  313. cmd_buffer[2] = res;
  314. cmd_buffer[1] = result;
  315. }
  316. static void Fcntl(Service::Interface* self) {
  317. u32* cmd_buffer = Kernel::GetCommandBuffer();
  318. u32 socket_handle = cmd_buffer[1];
  319. u32 ctr_cmd = cmd_buffer[2];
  320. u32 ctr_arg = cmd_buffer[3];
  321. int result = 0;
  322. u32 posix_ret = 0; // TODO: Check what hardware returns for F_SETFL (unspecified by POSIX)
  323. SCOPE_EXIT({
  324. cmd_buffer[1] = result;
  325. cmd_buffer[2] = posix_ret;
  326. });
  327. if (ctr_cmd == 3) { // F_GETFL
  328. #if EMU_PLATFORM == PLATFORM_WINDOWS
  329. posix_ret = 0;
  330. auto iter = open_sockets.find(socket_handle);
  331. if (iter != open_sockets.end() && iter->second.blocking == false)
  332. posix_ret |= 4; // O_NONBLOCK
  333. #else
  334. int ret = ::fcntl(socket_handle, F_GETFL, 0);
  335. if (ret == SOCKET_ERROR_VALUE) {
  336. result = TranslateError(GET_ERRNO);
  337. posix_ret = -1;
  338. return;
  339. }
  340. posix_ret = 0;
  341. if (ret & O_NONBLOCK)
  342. posix_ret |= 4; // O_NONBLOCK
  343. #endif
  344. } else if (ctr_cmd == 4) { // F_SETFL
  345. #if EMU_PLATFORM == PLATFORM_WINDOWS
  346. unsigned long tmp = (ctr_arg & 4 /* O_NONBLOCK */) ? 1 : 0;
  347. int ret = ioctlsocket(socket_handle, FIONBIO, &tmp);
  348. if (ret == SOCKET_ERROR_VALUE) {
  349. result = TranslateError(GET_ERRNO);
  350. posix_ret = -1;
  351. return;
  352. }
  353. auto iter = open_sockets.find(socket_handle);
  354. if (iter != open_sockets.end())
  355. iter->second.blocking = (tmp == 0);
  356. #else
  357. int flags = ::fcntl(socket_handle, F_GETFL, 0);
  358. if (flags == SOCKET_ERROR_VALUE) {
  359. result = TranslateError(GET_ERRNO);
  360. posix_ret = -1;
  361. return;
  362. }
  363. flags &= ~O_NONBLOCK;
  364. if (ctr_arg & 4) // O_NONBLOCK
  365. flags |= O_NONBLOCK;
  366. int ret = ::fcntl(socket_handle, F_SETFL, flags);
  367. if (ret == SOCKET_ERROR_VALUE) {
  368. result = TranslateError(GET_ERRNO);
  369. posix_ret = -1;
  370. return;
  371. }
  372. #endif
  373. } else {
  374. LOG_ERROR(Service_SOC, "Unsupported command (%d) in fcntl call", ctr_cmd);
  375. result = TranslateError(EINVAL); // TODO: Find the correct error
  376. posix_ret = -1;
  377. return;
  378. }
  379. }
  380. static void Listen(Service::Interface* self) {
  381. u32* cmd_buffer = Kernel::GetCommandBuffer();
  382. u32 socket_handle = cmd_buffer[1];
  383. u32 backlog = cmd_buffer[2];
  384. int ret = ::listen(socket_handle, backlog);
  385. int result = 0;
  386. if (ret != 0)
  387. result = TranslateError(GET_ERRNO);
  388. cmd_buffer[2] = ret;
  389. cmd_buffer[1] = result;
  390. }
  391. static void Accept(Service::Interface* self) {
  392. // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
  393. // preventing graceful shutdown when closing the emulator, this can be fixed by always
  394. // performing nonblocking operations and spinlock until the data is available
  395. u32* cmd_buffer = Kernel::GetCommandBuffer();
  396. u32 socket_handle = cmd_buffer[1];
  397. socklen_t max_addr_len = static_cast<socklen_t>(cmd_buffer[2]);
  398. sockaddr addr;
  399. socklen_t addr_len = sizeof(addr);
  400. u32 ret = static_cast<u32>(::accept(socket_handle, &addr, &addr_len));
  401. if ((s32)ret != SOCKET_ERROR_VALUE)
  402. open_sockets[ret] = { ret, true };
  403. int result = 0;
  404. if ((s32)ret == SOCKET_ERROR_VALUE) {
  405. result = TranslateError(GET_ERRNO);
  406. } else {
  407. CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr);
  408. Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len);
  409. }
  410. cmd_buffer[2] = ret;
  411. cmd_buffer[1] = result;
  412. }
  413. static void GetHostId(Service::Interface* self) {
  414. u32* cmd_buffer = Kernel::GetCommandBuffer();
  415. char name[128];
  416. gethostname(name, sizeof(name));
  417. hostent* host = gethostbyname(name);
  418. in_addr* addr = reinterpret_cast<in_addr*>(host->h_addr);
  419. cmd_buffer[2] = addr->s_addr;
  420. cmd_buffer[1] = 0;
  421. }
  422. static void Close(Service::Interface* self) {
  423. u32* cmd_buffer = Kernel::GetCommandBuffer();
  424. u32 socket_handle = cmd_buffer[1];
  425. int ret = 0;
  426. open_sockets.erase(socket_handle);
  427. ret = closesocket(socket_handle);
  428. int result = 0;
  429. if (ret != 0)
  430. result = TranslateError(GET_ERRNO);
  431. cmd_buffer[2] = ret;
  432. cmd_buffer[1] = result;
  433. }
  434. static void SendTo(Service::Interface* self) {
  435. u32* cmd_buffer = Kernel::GetCommandBuffer();
  436. u32 socket_handle = cmd_buffer[1];
  437. u32 len = cmd_buffer[2];
  438. u32 flags = cmd_buffer[3];
  439. u32 addr_len = cmd_buffer[4];
  440. u8* input_buff = Memory::GetPointer(cmd_buffer[8]);
  441. CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[10]));
  442. if (ctr_dest_addr == nullptr) {
  443. cmd_buffer[1] = -1; // TODO(Subv): Find the right error code
  444. return;
  445. }
  446. int ret = -1;
  447. if (addr_len > 0) {
  448. sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr);
  449. ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr));
  450. } else {
  451. ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0);
  452. }
  453. int result = 0;
  454. if (ret == SOCKET_ERROR_VALUE)
  455. result = TranslateError(GET_ERRNO);
  456. cmd_buffer[2] = ret;
  457. cmd_buffer[1] = result;
  458. }
  459. static void RecvFrom(Service::Interface* self) {
  460. // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
  461. // preventing graceful shutdown when closing the emulator, this can be fixed by always
  462. // performing nonblocking operations and spinlock until the data is available
  463. u32* cmd_buffer = Kernel::GetCommandBuffer();
  464. u32 socket_handle = cmd_buffer[1];
  465. u32 len = cmd_buffer[2];
  466. u32 flags = cmd_buffer[3];
  467. socklen_t addr_len = static_cast<socklen_t>(cmd_buffer[4]);
  468. u8* output_buff = Memory::GetPointer(cmd_buffer[0x104 >> 2]);
  469. sockaddr src_addr;
  470. socklen_t src_addr_len = sizeof(src_addr);
  471. int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len);
  472. if (cmd_buffer[0x1A0 >> 2] != 0) {
  473. CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x1A0 >> 2]));
  474. *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
  475. }
  476. int result = 0;
  477. int total_received = ret;
  478. if (ret == SOCKET_ERROR_VALUE) {
  479. result = TranslateError(GET_ERRNO);
  480. total_received = 0;
  481. }
  482. cmd_buffer[1] = result;
  483. cmd_buffer[2] = ret;
  484. cmd_buffer[3] = total_received;
  485. }
  486. static void Poll(Service::Interface* self) {
  487. u32* cmd_buffer = Kernel::GetCommandBuffer();
  488. u32 nfds = cmd_buffer[1];
  489. int timeout = cmd_buffer[2];
  490. CTRPollFD* input_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[6]));
  491. CTRPollFD* output_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
  492. // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes)
  493. // so we have to copy the data
  494. pollfd* platform_pollfd = new pollfd[nfds];
  495. for (unsigned current_fds = 0; current_fds < nfds; ++current_fds)
  496. platform_pollfd[current_fds] = CTRPollFD::ToPlatform(input_fds[current_fds]);
  497. int ret = ::poll(platform_pollfd, nfds, timeout);
  498. // Now update the output pollfd structure
  499. for (unsigned current_fds = 0; current_fds < nfds; ++current_fds)
  500. output_fds[current_fds] = CTRPollFD::FromPlatform(platform_pollfd[current_fds]);
  501. delete[] platform_pollfd;
  502. int result = 0;
  503. if (ret == SOCKET_ERROR_VALUE)
  504. result = TranslateError(GET_ERRNO);
  505. cmd_buffer[1] = result;
  506. cmd_buffer[2] = ret;
  507. }
  508. static void GetSockName(Service::Interface* self) {
  509. u32* cmd_buffer = Kernel::GetCommandBuffer();
  510. u32 socket_handle = cmd_buffer[1];
  511. socklen_t ctr_len = cmd_buffer[2];
  512. CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
  513. sockaddr dest_addr;
  514. socklen_t dest_addr_len = sizeof(dest_addr);
  515. int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len);
  516. if (ctr_dest_addr != nullptr) {
  517. *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr);
  518. } else {
  519. cmd_buffer[1] = -1; // TODO(Subv): Verify error
  520. return;
  521. }
  522. int result = 0;
  523. if (ret != 0)
  524. result = TranslateError(GET_ERRNO);
  525. cmd_buffer[2] = ret;
  526. cmd_buffer[1] = result;
  527. }
  528. static void Shutdown(Service::Interface* self) {
  529. u32* cmd_buffer = Kernel::GetCommandBuffer();
  530. u32 socket_handle = cmd_buffer[1];
  531. int how = cmd_buffer[2];
  532. int ret = ::shutdown(socket_handle, how);
  533. int result = 0;
  534. if (ret != 0)
  535. result = TranslateError(GET_ERRNO);
  536. cmd_buffer[2] = ret;
  537. cmd_buffer[1] = result;
  538. }
  539. static void GetPeerName(Service::Interface* self) {
  540. u32* cmd_buffer = Kernel::GetCommandBuffer();
  541. u32 socket_handle = cmd_buffer[1];
  542. socklen_t len = cmd_buffer[2];
  543. CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2]));
  544. sockaddr dest_addr;
  545. socklen_t dest_addr_len = sizeof(dest_addr);
  546. int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len);
  547. if (ctr_dest_addr != nullptr) {
  548. *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr);
  549. } else {
  550. cmd_buffer[1] = -1;
  551. return;
  552. }
  553. int result = 0;
  554. if (ret != 0)
  555. result = TranslateError(GET_ERRNO);
  556. cmd_buffer[2] = ret;
  557. cmd_buffer[1] = result;
  558. }
  559. static void Connect(Service::Interface* self) {
  560. // TODO(Subv): Calling this function on a blocking socket will block the emu thread,
  561. // preventing graceful shutdown when closing the emulator, this can be fixed by always
  562. // performing nonblocking operations and spinlock until the data is available
  563. u32* cmd_buffer = Kernel::GetCommandBuffer();
  564. u32 socket_handle = cmd_buffer[1];
  565. socklen_t len = cmd_buffer[2];
  566. CTRSockAddr* ctr_input_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6]));
  567. if (ctr_input_addr == nullptr) {
  568. cmd_buffer[1] = -1; // TODO(Subv): Verify error
  569. return;
  570. }
  571. sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr);
  572. int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr));
  573. int result = 0;
  574. if (ret != 0)
  575. result = TranslateError(GET_ERRNO);
  576. cmd_buffer[2] = ret;
  577. cmd_buffer[1] = result;
  578. }
  579. static void InitializeSockets(Service::Interface* self) {
  580. // TODO(Subv): Implement
  581. #if EMU_PLATFORM == PLATFORM_WINDOWS
  582. WSADATA data;
  583. WSAStartup(MAKEWORD(2, 2), &data);
  584. #endif
  585. u32* cmd_buffer = Kernel::GetCommandBuffer();
  586. cmd_buffer[1] = 0;
  587. }
  588. static void ShutdownSockets(Service::Interface* self) {
  589. // TODO(Subv): Implement
  590. CleanupSockets();
  591. #if EMU_PLATFORM == PLATFORM_WINDOWS
  592. WSACleanup();
  593. #endif
  594. u32* cmd_buffer = Kernel::GetCommandBuffer();
  595. cmd_buffer[1] = 0;
  596. }
  597. const Interface::FunctionInfo FunctionTable[] = {
  598. {0x00010044, InitializeSockets, "InitializeSockets"},
  599. {0x000200C2, Socket, "Socket"},
  600. {0x00030082, Listen, "Listen"},
  601. {0x00040082, Accept, "Accept"},
  602. {0x00050084, Bind, "Bind"},
  603. {0x00060084, Connect, "Connect"},
  604. {0x00070104, nullptr, "recvfrom_other"},
  605. {0x00080102, RecvFrom, "RecvFrom"},
  606. {0x00090106, nullptr, "sendto_other"},
  607. {0x000A0106, SendTo, "SendTo"},
  608. {0x000B0042, Close, "Close"},
  609. {0x000C0082, Shutdown, "Shutdown"},
  610. {0x000D0082, nullptr, "GetHostByName"},
  611. {0x000E00C2, nullptr, "GetHostByAddr"},
  612. {0x000F0106, nullptr, "unknown_resolve_ip"},
  613. {0x00110102, nullptr, "GetSockOpt"},
  614. {0x00120104, nullptr, "SetSockOpt"},
  615. {0x001300C2, Fcntl, "Fcntl"},
  616. {0x00140084, Poll, "Poll"},
  617. {0x00150042, nullptr, "SockAtMark"},
  618. {0x00160000, GetHostId, "GetHostId"},
  619. {0x00170082, GetSockName, "GetSockName"},
  620. {0x00180082, GetPeerName, "GetPeerName"},
  621. {0x00190000, ShutdownSockets, "ShutdownSockets"},
  622. {0x001A00C0, nullptr, "GetNetworkOpt"},
  623. {0x001B0040, nullptr, "ICMPSocket"},
  624. {0x001C0104, nullptr, "ICMPPing"},
  625. {0x001D0040, nullptr, "ICMPCancel"},
  626. {0x001E0040, nullptr, "ICMPClose"},
  627. {0x001F0040, nullptr, "GetResolverInfo"},
  628. {0x00210002, nullptr, "CloseSockets"},
  629. };
  630. ////////////////////////////////////////////////////////////////////////////////////////////////////
  631. // Interface class
  632. Interface::Interface() {
  633. Register(FunctionTable);
  634. }
  635. Interface::~Interface() {
  636. CleanupSockets();
  637. #if EMU_PLATFORM == PLATFORM_WINDOWS
  638. WSACleanup();
  639. #endif
  640. }
  641. } // namespace