soc_u.cpp 24 KB

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