IClient.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. using Ryujinx.HLE.HOS.Ipc;
  2. using Ryujinx.HLE.Utilities;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.Threading.Tasks;
  8. namespace Ryujinx.HLE.HOS.Services.Bsd
  9. {
  10. class IClient : IpcService
  11. {
  12. private Dictionary<int, ServiceProcessRequest> m_Commands;
  13. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  14. private List<BsdSocket> Sockets = new List<BsdSocket>();
  15. public IClient()
  16. {
  17. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  18. {
  19. { 0, Initialize },
  20. { 1, StartMonitoring },
  21. { 2, Socket },
  22. { 6, Poll },
  23. { 8, Recv },
  24. { 10, Send },
  25. { 11, SendTo },
  26. { 12, Accept },
  27. { 13, Bind },
  28. { 14, Connect },
  29. { 18, Listen },
  30. { 21, SetSockOpt },
  31. { 24, Write },
  32. { 25, Read },
  33. { 26, Close }
  34. };
  35. }
  36. //(u32, u32, u32, u32, u32, u32, u32, u32, u64 pid, u64 transferMemorySize, pid, KObject) -> u32 bsd_errno
  37. public long Initialize(ServiceCtx Context)
  38. {
  39. /*
  40. typedef struct {
  41. u32 version; // Observed 1 on 2.0 LibAppletWeb, 2 on 3.0.
  42. u32 tcp_tx_buf_size; // Size of the TCP transfer (send) buffer (initial or fixed).
  43. u32 tcp_rx_buf_size; // Size of the TCP recieve buffer (initial or fixed).
  44. u32 tcp_tx_buf_max_size; // Maximum size of the TCP transfer (send) buffer. If it is 0, the size of the buffer is fixed to its initial value.
  45. u32 tcp_rx_buf_max_size; // Maximum size of the TCP receive buffer. If it is 0, the size of the buffer is fixed to its initial value.
  46. u32 udp_tx_buf_size; // Size of the UDP transfer (send) buffer (typically 0x2400 bytes).
  47. u32 udp_rx_buf_size; // Size of the UDP receive buffer (typically 0xA500 bytes).
  48. u32 sb_efficiency; // Number of buffers for each socket (standard values range from 1 to 8).
  49. } BsdBufferConfig;
  50. */
  51. Context.ResponseData.Write(0);
  52. //Todo: Stub
  53. return 0;
  54. }
  55. //(u64, pid)
  56. public long StartMonitoring(ServiceCtx Context)
  57. {
  58. //Todo: Stub
  59. return 0;
  60. }
  61. //(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno)
  62. public long Socket(ServiceCtx Context)
  63. {
  64. BsdSocket NewBsdSocket = new BsdSocket
  65. {
  66. Family = Context.RequestData.ReadInt32(),
  67. Type = Context.RequestData.ReadInt32(),
  68. Protocol = Context.RequestData.ReadInt32()
  69. };
  70. Sockets.Add(NewBsdSocket);
  71. NewBsdSocket.Handle = new Socket((AddressFamily)NewBsdSocket.Family,
  72. (SocketType)NewBsdSocket.Type,
  73. (ProtocolType)NewBsdSocket.Protocol);
  74. Context.ResponseData.Write(Sockets.Count - 1);
  75. Context.ResponseData.Write(0);
  76. return 0;
  77. }
  78. //(u32, u32, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>)
  79. public long Poll(ServiceCtx Context)
  80. {
  81. int PollCount = Context.RequestData.ReadInt32();
  82. int TimeOut = Context.RequestData.ReadInt32();
  83. //https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/poll.h
  84. //https://msdn.microsoft.com/fr-fr/library/system.net.sockets.socket.poll(v=vs.110).aspx
  85. //https://github.com/switchbrew/libnx/blob/e0457c4534b3c37426d83e1a620f82cb28c3b528/nx/source/services/bsd.c#L343
  86. //https://github.com/TuxSH/ftpd/blob/switch_pr/source/ftp.c#L1634
  87. //https://linux.die.net/man/2/poll
  88. byte[] SentBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
  89. Context.Request.SendBuff[0].Size);
  90. int SocketId = Get32(SentBuffer, 0);
  91. int RequestedEvents = Get16(SentBuffer, 4);
  92. int ReturnedEvents = Get16(SentBuffer, 6);
  93. //Todo: Stub - Need to implemented the Type-22 buffer.
  94. Context.ResponseData.Write(1);
  95. Context.ResponseData.Write(0);
  96. return 0;
  97. }
  98. //(u32 socket, u32 flags) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message)
  99. public long Recv(ServiceCtx Context)
  100. {
  101. int SocketId = Context.RequestData.ReadInt32();
  102. int SocketFlags = Context.RequestData.ReadInt32();
  103. (long ReceivePosition, long ReceiveLength) = Context.Request.GetBufferType0x22();
  104. byte[] ReceivedBuffer = new byte[ReceiveLength];
  105. try
  106. {
  107. int BytesRead = Sockets[SocketId].Handle.Receive(ReceivedBuffer);
  108. Context.Memory.WriteBytes(ReceivePosition, ReceivedBuffer);
  109. Context.ResponseData.Write(BytesRead);
  110. Context.ResponseData.Write(0);
  111. }
  112. catch (SocketException Ex)
  113. {
  114. Context.ResponseData.Write(-1);
  115. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  116. }
  117. return 0;
  118. }
  119. //(u32 socket, u32 flags, buffer<i8, 0x21, 0>) -> (i32 ret, u32 bsd_errno)
  120. public long Send(ServiceCtx Context)
  121. {
  122. int SocketId = Context.RequestData.ReadInt32();
  123. int SocketFlags = Context.RequestData.ReadInt32();
  124. (long SentPosition, long SentSize) = Context.Request.GetBufferType0x21();
  125. byte[] SentBuffer = Context.Memory.ReadBytes(SentPosition, SentSize);
  126. try
  127. {
  128. int BytesSent = Sockets[SocketId].Handle.Send(SentBuffer);
  129. Context.ResponseData.Write(BytesSent);
  130. Context.ResponseData.Write(0);
  131. }
  132. catch (SocketException Ex)
  133. {
  134. Context.ResponseData.Write(-1);
  135. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  136. }
  137. return 0;
  138. }
  139. //(u32 socket, u32 flags, buffer<i8, 0x21, 0>, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno)
  140. public long SendTo(ServiceCtx Context)
  141. {
  142. int SocketId = Context.RequestData.ReadInt32();
  143. int SocketFlags = Context.RequestData.ReadInt32();
  144. byte[] SentBuffer = Context.Memory.ReadBytes(Context.Request.SendBuff[0].Position,
  145. Context.Request.SendBuff[0].Size);
  146. (long AddressPosition, long AddressSize) = Context.Request.GetBufferType0x21(Index: 1);
  147. byte[] AddressBuffer = Context.Memory.ReadBytes(AddressPosition, AddressSize);
  148. if (!Sockets[SocketId].Handle.Connected)
  149. {
  150. try
  151. {
  152. ParseAddrBuffer(SocketId, AddressBuffer);
  153. Sockets[SocketId].Handle.Connect(Sockets[SocketId].RemoteEP);
  154. }
  155. catch (SocketException Ex)
  156. {
  157. Context.ResponseData.Write(-1);
  158. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  159. }
  160. }
  161. try
  162. {
  163. int BytesSent = Sockets[SocketId].Handle.Send(SentBuffer);
  164. Context.ResponseData.Write(BytesSent);
  165. Context.ResponseData.Write(0);
  166. }
  167. catch (SocketException Ex)
  168. {
  169. Context.ResponseData.Write(-1);
  170. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  171. }
  172. return 0;
  173. }
  174. //(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<sockaddr, 0x22, 0> addr)
  175. public long Accept(ServiceCtx Context)
  176. {
  177. int SocketId = Context.RequestData.ReadInt32();
  178. (long AddrBufferPosition, long AddrBuffSize) = Context.Request.GetBufferType0x22();
  179. Socket HandleAccept = null;
  180. Task TimeOut = Task.Factory.StartNew(() =>
  181. {
  182. try
  183. {
  184. HandleAccept = Sockets[SocketId].Handle.Accept();
  185. }
  186. catch (SocketException Ex)
  187. {
  188. Context.ResponseData.Write(-1);
  189. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  190. }
  191. });
  192. TimeOut.Wait(10000);
  193. if (HandleAccept != null)
  194. {
  195. BsdSocket NewBsdSocket = new BsdSocket
  196. {
  197. IpAddress = ((IPEndPoint)Sockets[SocketId].Handle.LocalEndPoint).Address,
  198. RemoteEP = ((IPEndPoint)Sockets[SocketId].Handle.LocalEndPoint),
  199. Handle = HandleAccept
  200. };
  201. Sockets.Add(NewBsdSocket);
  202. using (MemoryStream MS = new MemoryStream())
  203. {
  204. BinaryWriter Writer = new BinaryWriter(MS);
  205. Writer.Write((byte)0);
  206. Writer.Write((byte)NewBsdSocket.Handle.AddressFamily);
  207. Writer.Write((short)((IPEndPoint)NewBsdSocket.Handle.LocalEndPoint).Port);
  208. byte[] IpAddress = NewBsdSocket.IpAddress.GetAddressBytes();
  209. Writer.Write(IpAddress);
  210. Context.Memory.WriteBytes(AddrBufferPosition, MS.ToArray());
  211. Context.ResponseData.Write(Sockets.Count - 1);
  212. Context.ResponseData.Write(0);
  213. Context.ResponseData.Write(MS.Length);
  214. }
  215. }
  216. else
  217. {
  218. Context.ResponseData.Write(-1);
  219. Context.ResponseData.Write((int)BsdError.Timeout);
  220. }
  221. return 0;
  222. }
  223. //(u32 socket, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno)
  224. public long Bind(ServiceCtx Context)
  225. {
  226. int SocketId = Context.RequestData.ReadInt32();
  227. (long AddressPosition, long AddressSize) = Context.Request.GetBufferType0x21();
  228. byte[] AddressBuffer = Context.Memory.ReadBytes(AddressPosition, AddressSize);
  229. try
  230. {
  231. ParseAddrBuffer(SocketId, AddressBuffer);
  232. Context.ResponseData.Write(0);
  233. Context.ResponseData.Write(0);
  234. }
  235. catch (SocketException Ex)
  236. {
  237. Context.ResponseData.Write(-1);
  238. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  239. }
  240. return 0;
  241. }
  242. //(u32 socket, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno)
  243. public long Connect(ServiceCtx Context)
  244. {
  245. int SocketId = Context.RequestData.ReadInt32();
  246. (long AddressPosition, long AddressSize) = Context.Request.GetBufferType0x21();
  247. byte[] AddressBuffer = Context.Memory.ReadBytes(AddressPosition, AddressSize);
  248. try
  249. {
  250. ParseAddrBuffer(SocketId, AddressBuffer);
  251. Sockets[SocketId].Handle.Connect(Sockets[SocketId].RemoteEP);
  252. Context.ResponseData.Write(0);
  253. Context.ResponseData.Write(0);
  254. }
  255. catch (SocketException Ex)
  256. {
  257. Context.ResponseData.Write(-1);
  258. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  259. }
  260. return 0;
  261. }
  262. //(u32 socket, u32 backlog) -> (i32 ret, u32 bsd_errno)
  263. public long Listen(ServiceCtx Context)
  264. {
  265. int SocketId = Context.RequestData.ReadInt32();
  266. int BackLog = Context.RequestData.ReadInt32();
  267. try
  268. {
  269. Sockets[SocketId].Handle.Bind(Sockets[SocketId].RemoteEP);
  270. Sockets[SocketId].Handle.Listen(BackLog);
  271. Context.ResponseData.Write(0);
  272. Context.ResponseData.Write(0);
  273. }
  274. catch (SocketException Ex)
  275. {
  276. Context.ResponseData.Write(-1);
  277. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  278. }
  279. return 0;
  280. }
  281. //(u32 socket, u32 level, u32 option_name, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno)
  282. public long SetSockOpt(ServiceCtx Context)
  283. {
  284. int SocketId = Context.RequestData.ReadInt32();
  285. SocketOptionLevel SocketLevel = (SocketOptionLevel)Context.RequestData.ReadInt32();
  286. SocketOptionName SocketOptionName = (SocketOptionName)Context.RequestData.ReadInt32();
  287. byte[] SocketOptionValue = Context.Memory.ReadBytes(Context.Request.PtrBuff[0].Position,
  288. Context.Request.PtrBuff[0].Size);
  289. int OptionValue = Get32(SocketOptionValue, 0);
  290. try
  291. {
  292. Sockets[SocketId].Handle.SetSocketOption(SocketLevel, SocketOptionName, OptionValue);
  293. Context.ResponseData.Write(0);
  294. Context.ResponseData.Write(0);
  295. }
  296. catch (SocketException Ex)
  297. {
  298. Context.ResponseData.Write(-1);
  299. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  300. }
  301. return 0;
  302. }
  303. //(u32 socket, buffer<i8, 0x21, 0> message) -> (i32 ret, u32 bsd_errno)
  304. public long Write(ServiceCtx Context)
  305. {
  306. int SocketId = Context.RequestData.ReadInt32();
  307. (long SentPosition, long SentSize) = Context.Request.GetBufferType0x21();
  308. byte[] SentBuffer = Context.Memory.ReadBytes(SentPosition, SentSize);
  309. try
  310. {
  311. //Logging.Debug("Wrote Buffer:" + Environment.NewLine + Logging.HexDump(SentBuffer));
  312. int BytesSent = Sockets[SocketId].Handle.Send(SentBuffer);
  313. Context.ResponseData.Write(BytesSent);
  314. Context.ResponseData.Write(0);
  315. }
  316. catch (SocketException Ex)
  317. {
  318. Context.ResponseData.Write(-1);
  319. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  320. }
  321. return 0;
  322. }
  323. //(u32 socket) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message)
  324. public long Read(ServiceCtx Context)
  325. {
  326. int SocketId = Context.RequestData.ReadInt32();
  327. (long ReceivePosition, long ReceiveLength) = Context.Request.GetBufferType0x22();
  328. byte[] ReceivedBuffer = new byte[ReceiveLength];
  329. try
  330. {
  331. int BytesRead = Sockets[SocketId].Handle.Receive(ReceivedBuffer);
  332. Context.Memory.WriteBytes(ReceivePosition, ReceivedBuffer);
  333. Context.ResponseData.Write(BytesRead);
  334. Context.ResponseData.Write(0);
  335. }
  336. catch (SocketException Ex)
  337. {
  338. Context.ResponseData.Write(-1);
  339. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  340. }
  341. return 0;
  342. }
  343. //(u32 socket) -> (i32 ret, u32 bsd_errno)
  344. public long Close(ServiceCtx Context)
  345. {
  346. int SocketId = Context.RequestData.ReadInt32();
  347. try
  348. {
  349. Sockets[SocketId].Handle.Close();
  350. Sockets[SocketId] = null;
  351. Context.ResponseData.Write(0);
  352. Context.ResponseData.Write(0);
  353. }
  354. catch (SocketException Ex)
  355. {
  356. Context.ResponseData.Write(-1);
  357. Context.ResponseData.Write(Ex.ErrorCode - 10000);
  358. }
  359. return 0;
  360. }
  361. public void ParseAddrBuffer(int SocketId, byte[] AddrBuffer)
  362. {
  363. using (MemoryStream MS = new MemoryStream(AddrBuffer))
  364. {
  365. BinaryReader Reader = new BinaryReader(MS);
  366. int Size = Reader.ReadByte();
  367. int Family = Reader.ReadByte();
  368. int Port = EndianSwap.Swap16(Reader.ReadUInt16());
  369. string IpAddress = Reader.ReadByte().ToString() + "." +
  370. Reader.ReadByte().ToString() + "." +
  371. Reader.ReadByte().ToString() + "." +
  372. Reader.ReadByte().ToString();
  373. Sockets[SocketId].IpAddress = IPAddress.Parse(IpAddress);
  374. Sockets[SocketId].RemoteEP = new IPEndPoint(Sockets[SocketId].IpAddress, Port);
  375. }
  376. }
  377. private int Get16(byte[] Data, int Address)
  378. {
  379. return
  380. Data[Address + 0] << 0 |
  381. Data[Address + 1] << 8;
  382. }
  383. private int Get32(byte[] Data, int Address)
  384. {
  385. return
  386. Data[Address + 0] << 0 |
  387. Data[Address + 1] << 8 |
  388. Data[Address + 2] << 16 |
  389. Data[Address + 3] << 24;
  390. }
  391. }
  392. }