WinSockHelper.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Net.Sockets;
  5. namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd.Impl
  6. {
  7. static class WinSockHelper
  8. {
  9. private static readonly Dictionary<WsaError, LinuxError> _errorMap = new()
  10. {
  11. // WSAEINTR
  12. { WsaError.WSAEINTR, LinuxError.EINTR },
  13. // WSAEWOULDBLOCK
  14. { WsaError.WSAEWOULDBLOCK, LinuxError.EWOULDBLOCK },
  15. // WSAEINPROGRESS
  16. { WsaError.WSAEINPROGRESS, LinuxError.EINPROGRESS },
  17. // WSAEALREADY
  18. { WsaError.WSAEALREADY, LinuxError.EALREADY },
  19. // WSAENOTSOCK
  20. { WsaError.WSAENOTSOCK, LinuxError.ENOTSOCK },
  21. // WSAEDESTADDRREQ
  22. { WsaError.WSAEDESTADDRREQ, LinuxError.EDESTADDRREQ },
  23. // WSAEMSGSIZE
  24. { WsaError.WSAEMSGSIZE, LinuxError.EMSGSIZE },
  25. // WSAEPROTOTYPE
  26. { WsaError.WSAEPROTOTYPE, LinuxError.EPROTOTYPE },
  27. // WSAENOPROTOOPT
  28. { WsaError.WSAENOPROTOOPT, LinuxError.ENOPROTOOPT },
  29. // WSAEPROTONOSUPPORT
  30. { WsaError.WSAEPROTONOSUPPORT, LinuxError.EPROTONOSUPPORT },
  31. // WSAESOCKTNOSUPPORT
  32. { WsaError.WSAESOCKTNOSUPPORT, LinuxError.ESOCKTNOSUPPORT },
  33. // WSAEOPNOTSUPP
  34. { WsaError.WSAEOPNOTSUPP, LinuxError.EOPNOTSUPP },
  35. // WSAEPFNOSUPPORT
  36. { WsaError.WSAEPFNOSUPPORT, LinuxError.EPFNOSUPPORT },
  37. // WSAEAFNOSUPPORT
  38. { WsaError.WSAEAFNOSUPPORT, LinuxError.EAFNOSUPPORT },
  39. // WSAEADDRINUSE
  40. { WsaError.WSAEADDRINUSE, LinuxError.EADDRINUSE },
  41. // WSAEADDRNOTAVAIL
  42. { WsaError.WSAEADDRNOTAVAIL, LinuxError.EADDRNOTAVAIL },
  43. // WSAENETDOWN
  44. { WsaError.WSAENETDOWN, LinuxError.ENETDOWN },
  45. // WSAENETUNREACH
  46. { WsaError.WSAENETUNREACH, LinuxError.ENETUNREACH },
  47. // WSAENETRESET
  48. { WsaError.WSAENETRESET, LinuxError.ENETRESET },
  49. // WSAECONNABORTED
  50. { WsaError.WSAECONNABORTED, LinuxError.ECONNABORTED },
  51. // WSAECONNRESET
  52. { WsaError.WSAECONNRESET, LinuxError.ECONNRESET },
  53. // WSAENOBUFS
  54. { WsaError.WSAENOBUFS, LinuxError.ENOBUFS },
  55. // WSAEISCONN
  56. { WsaError.WSAEISCONN, LinuxError.EISCONN },
  57. // WSAENOTCONN
  58. { WsaError.WSAENOTCONN, LinuxError.ENOTCONN },
  59. // WSAESHUTDOWN
  60. { WsaError.WSAESHUTDOWN, LinuxError.ESHUTDOWN },
  61. // WSAETOOMANYREFS
  62. { WsaError.WSAETOOMANYREFS, LinuxError.ETOOMANYREFS },
  63. // WSAETIMEDOUT
  64. { WsaError.WSAETIMEDOUT, LinuxError.ETIMEDOUT },
  65. // WSAECONNREFUSED
  66. { WsaError.WSAECONNREFUSED, LinuxError.ECONNREFUSED },
  67. // WSAELOOP
  68. { WsaError.WSAELOOP, LinuxError.ELOOP },
  69. // WSAENAMETOOLONG
  70. { WsaError.WSAENAMETOOLONG, LinuxError.ENAMETOOLONG },
  71. // WSAEHOSTDOWN
  72. { WsaError.WSAEHOSTDOWN, LinuxError.EHOSTDOWN },
  73. // WSAEHOSTUNREACH
  74. { WsaError.WSAEHOSTUNREACH, LinuxError.EHOSTUNREACH },
  75. // WSAENOTEMPTY
  76. { WsaError.WSAENOTEMPTY, LinuxError.ENOTEMPTY },
  77. // WSAEUSERS
  78. { WsaError.WSAEUSERS, LinuxError.EUSERS },
  79. // WSAEDQUOT
  80. { WsaError.WSAEDQUOT, LinuxError.EDQUOT },
  81. // WSAESTALE
  82. { WsaError.WSAESTALE, LinuxError.ESTALE },
  83. // WSAEREMOTE
  84. { WsaError.WSAEREMOTE, LinuxError.EREMOTE },
  85. // WSAEINVAL
  86. { WsaError.WSAEINVAL, LinuxError.EINVAL },
  87. // WSAEFAULT
  88. { WsaError.WSAEFAULT, LinuxError.EFAULT },
  89. // NOERROR
  90. { 0, 0 }
  91. };
  92. private static readonly Dictionary<int, LinuxError> _errorMapMacOs = new()
  93. {
  94. { 35, LinuxError.EAGAIN },
  95. { 11, LinuxError.EDEADLOCK },
  96. { 91, LinuxError.ENOMSG },
  97. { 90, LinuxError.EIDRM },
  98. { 77, LinuxError.ENOLCK },
  99. { 70, LinuxError.ESTALE },
  100. { 36, LinuxError.EINPROGRESS },
  101. { 37, LinuxError.EALREADY },
  102. { 38, LinuxError.ENOTSOCK },
  103. { 39, LinuxError.EDESTADDRREQ },
  104. { 40, LinuxError.EMSGSIZE },
  105. { 41, LinuxError.EPROTOTYPE },
  106. { 42, LinuxError.ENOPROTOOPT },
  107. { 43, LinuxError.EPROTONOSUPPORT },
  108. { 44, LinuxError.ESOCKTNOSUPPORT },
  109. { 45, LinuxError.EOPNOTSUPP },
  110. { 46, LinuxError.EPFNOSUPPORT },
  111. { 47, LinuxError.EAFNOSUPPORT },
  112. { 48, LinuxError.EADDRINUSE },
  113. { 49, LinuxError.EADDRNOTAVAIL },
  114. { 50, LinuxError.ENETDOWN },
  115. { 51, LinuxError.ENETUNREACH },
  116. { 52, LinuxError.ENETRESET },
  117. { 53, LinuxError.ECONNABORTED },
  118. { 54, LinuxError.ECONNRESET },
  119. { 55, LinuxError.ENOBUFS },
  120. { 56, LinuxError.EISCONN },
  121. { 57, LinuxError.ENOTCONN },
  122. { 58, LinuxError.ESHUTDOWN },
  123. { 60, LinuxError.ETIMEDOUT },
  124. { 61, LinuxError.ECONNREFUSED },
  125. { 64, LinuxError.EHOSTDOWN },
  126. { 65, LinuxError.EHOSTUNREACH },
  127. { 68, LinuxError.EUSERS },
  128. { 62, LinuxError.ELOOP },
  129. { 63, LinuxError.ENAMETOOLONG },
  130. { 66, LinuxError.ENOTEMPTY },
  131. { 69, LinuxError.EDQUOT },
  132. { 71, LinuxError.EREMOTE },
  133. { 78, LinuxError.ENOSYS },
  134. { 59, LinuxError.ETOOMANYREFS },
  135. { 92, LinuxError.EILSEQ },
  136. { 89, LinuxError.ECANCELED },
  137. { 84, LinuxError.EOVERFLOW }
  138. };
  139. private static readonly Dictionary<BsdSocketOption, SocketOptionName> _soSocketOptionMap = new()
  140. {
  141. { BsdSocketOption.SoDebug, SocketOptionName.Debug },
  142. { BsdSocketOption.SoReuseAddr, SocketOptionName.ReuseAddress },
  143. { BsdSocketOption.SoKeepAlive, SocketOptionName.KeepAlive },
  144. { BsdSocketOption.SoDontRoute, SocketOptionName.DontRoute },
  145. { BsdSocketOption.SoBroadcast, SocketOptionName.Broadcast },
  146. { BsdSocketOption.SoUseLoopBack, SocketOptionName.UseLoopback },
  147. { BsdSocketOption.SoLinger, SocketOptionName.Linger },
  148. { BsdSocketOption.SoOobInline, SocketOptionName.OutOfBandInline },
  149. { BsdSocketOption.SoReusePort, SocketOptionName.ReuseAddress },
  150. { BsdSocketOption.SoSndBuf, SocketOptionName.SendBuffer },
  151. { BsdSocketOption.SoRcvBuf, SocketOptionName.ReceiveBuffer },
  152. { BsdSocketOption.SoSndLoWat, SocketOptionName.SendLowWater },
  153. { BsdSocketOption.SoRcvLoWat, SocketOptionName.ReceiveLowWater },
  154. { BsdSocketOption.SoSndTimeo, SocketOptionName.SendTimeout },
  155. { BsdSocketOption.SoRcvTimeo, SocketOptionName.ReceiveTimeout },
  156. { BsdSocketOption.SoError, SocketOptionName.Error },
  157. { BsdSocketOption.SoType, SocketOptionName.Type }
  158. };
  159. private static readonly Dictionary<BsdSocketOption, SocketOptionName> _ipSocketOptionMap = new()
  160. {
  161. { BsdSocketOption.IpOptions, SocketOptionName.IPOptions },
  162. { BsdSocketOption.IpHdrIncl, SocketOptionName.HeaderIncluded },
  163. { BsdSocketOption.IpTtl, SocketOptionName.IpTimeToLive },
  164. { BsdSocketOption.IpMulticastIf, SocketOptionName.MulticastInterface },
  165. { BsdSocketOption.IpMulticastTtl, SocketOptionName.MulticastTimeToLive },
  166. { BsdSocketOption.IpMulticastLoop, SocketOptionName.MulticastLoopback },
  167. { BsdSocketOption.IpAddMembership, SocketOptionName.AddMembership },
  168. { BsdSocketOption.IpDropMembership, SocketOptionName.DropMembership },
  169. { BsdSocketOption.IpDontFrag, SocketOptionName.DontFragment },
  170. { BsdSocketOption.IpAddSourceMembership, SocketOptionName.AddSourceMembership },
  171. { BsdSocketOption.IpDropSourceMembership, SocketOptionName.DropSourceMembership }
  172. };
  173. private static readonly Dictionary<BsdSocketOption, SocketOptionName> _tcpSocketOptionMap = new()
  174. {
  175. { BsdSocketOption.TcpNoDelay, SocketOptionName.NoDelay },
  176. { BsdSocketOption.TcpKeepIdle, SocketOptionName.TcpKeepAliveTime },
  177. { BsdSocketOption.TcpKeepIntvl, SocketOptionName.TcpKeepAliveInterval },
  178. { BsdSocketOption.TcpKeepCnt, SocketOptionName.TcpKeepAliveRetryCount }
  179. };
  180. public static LinuxError ConvertError(WsaError errorCode)
  181. {
  182. if (OperatingSystem.IsMacOS())
  183. {
  184. if (_errorMapMacOs.TryGetValue((int)errorCode, out LinuxError errno))
  185. {
  186. return errno;
  187. }
  188. }
  189. else
  190. {
  191. if (_errorMap.TryGetValue(errorCode, out LinuxError errno))
  192. {
  193. return errno;
  194. }
  195. }
  196. return (LinuxError)errorCode;
  197. }
  198. public static bool TryConvertSocketOption(BsdSocketOption option, SocketOptionLevel level, out SocketOptionName name)
  199. {
  200. var table = level switch
  201. {
  202. SocketOptionLevel.Socket => _soSocketOptionMap,
  203. SocketOptionLevel.IP => _ipSocketOptionMap,
  204. SocketOptionLevel.Tcp => _tcpSocketOptionMap,
  205. _ => null
  206. };
  207. if (table == null)
  208. {
  209. name = default;
  210. return false;
  211. }
  212. return table.TryGetValue(option, out name);
  213. }
  214. }
  215. }