| 1 | /* Copyright (C) 2010-2022 The RetroArch team |
| 2 | * |
| 3 | * --------------------------------------------------------------------------------------- |
| 4 | * The following license statement only applies to this file (net_compat.h). |
| 5 | * --------------------------------------------------------------------------------------- |
| 6 | * |
| 7 | * Permission is hereby granted, free of charge, |
| 8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), |
| 9 | * to deal in the Software without restriction, including without limitation the rights to |
| 10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, |
| 11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 12 | * |
| 13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
| 16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 21 | */ |
| 22 | |
| 23 | #ifndef _LIBRETRO_SDK_NET_COMPAT_H |
| 24 | #define _LIBRETRO_SDK_NET_COMPAT_H |
| 25 | |
| 26 | #include <stdint.h> |
| 27 | #include <boolean.h> |
| 28 | #include <retro_inline.h> |
| 29 | |
| 30 | #include <errno.h> |
| 31 | |
| 32 | #ifndef _WIN32 |
| 33 | #include <sys/time.h> |
| 34 | #include <unistd.h> |
| 35 | #endif |
| 36 | |
| 37 | #include <retro_common_api.h> |
| 38 | |
| 39 | #if defined(_WIN32) && !defined(_XBOX) |
| 40 | #define WIN32_LEAN_AND_MEAN |
| 41 | |
| 42 | #include <winsock2.h> |
| 43 | #include <windows.h> |
| 44 | #include <ws2tcpip.h> |
| 45 | |
| 46 | #if _MSC_VER && _MSC_VER <= 1600 |
| 47 | /* If we are using MSVC2010 or lower, disable WSAPoll support |
| 48 | * to ensure Windows XP and earlier backwards compatibility */ |
| 49 | #else |
| 50 | #ifndef WIN32_SUPPORTS_POLL |
| 51 | #define WIN32_SUPPORTS_POLL 1 |
| 52 | #endif |
| 53 | #endif |
| 54 | |
| 55 | #if defined(WIN32_SUPPORTS_POLL) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 |
| 56 | #define NETWORK_HAVE_POLL 1 |
| 57 | #endif |
| 58 | |
| 59 | #elif defined(_XBOX) |
| 60 | #define NOD3D |
| 61 | |
| 62 | #include <xtl.h> |
| 63 | #include <io.h> |
| 64 | |
| 65 | #ifndef SO_KEEPALIVE |
| 66 | #define SO_KEEPALIVE 0 /* verify if correct */ |
| 67 | #endif |
| 68 | |
| 69 | #define socklen_t unsigned int |
| 70 | |
| 71 | #elif defined(VITA) |
| 72 | #include <psp2/net/net.h> |
| 73 | #include <psp2/net/netctl.h> |
| 74 | |
| 75 | #define NETWORK_HAVE_POLL 1 |
| 76 | |
| 77 | #define AF_UNSPEC 0 |
| 78 | #define AF_INET SCE_NET_AF_INET |
| 79 | |
| 80 | #define SOCK_STREAM SCE_NET_SOCK_STREAM |
| 81 | #define SOCK_DGRAM SCE_NET_SOCK_DGRAM |
| 82 | |
| 83 | #define INADDR_ANY SCE_NET_INADDR_ANY |
| 84 | #define INADDR_NONE 0xFFFFFFFF |
| 85 | |
| 86 | #define SOL_SOCKET SCE_NET_SOL_SOCKET |
| 87 | #define SO_REUSEADDR SCE_NET_SO_REUSEADDR |
| 88 | #define SO_KEEPALIVE SCE_NET_SO_KEEPALIVE |
| 89 | #define SO_BROADCAST SCE_NET_SO_BROADCAST |
| 90 | #define SO_SNDBUF SCE_NET_SO_SNDBUF |
| 91 | #define SO_RCVBUF SCE_NET_SO_RCVBUF |
| 92 | #define SO_SNDTIMEO SCE_NET_SO_SNDTIMEO |
| 93 | #define SO_RCVTIMEO SCE_NET_SO_RCVTIMEO |
| 94 | #define SO_ERROR SCE_NET_SO_ERROR |
| 95 | #define SO_NBIO SCE_NET_SO_NBIO |
| 96 | |
| 97 | #define IPPROTO_IP SCE_NET_IPPROTO_IP |
| 98 | #define IP_MULTICAST_TTL SCE_NET_IP_MULTICAST_TTL |
| 99 | |
| 100 | #define IPPROTO_TCP SCE_NET_IPPROTO_TCP |
| 101 | #define TCP_NODELAY SCE_NET_TCP_NODELAY |
| 102 | |
| 103 | #define IPPROTO_UDP SCE_NET_IPPROTO_UDP |
| 104 | |
| 105 | #define MSG_DONTWAIT SCE_NET_MSG_DONTWAIT |
| 106 | |
| 107 | #define POLLIN SCE_NET_EPOLLIN |
| 108 | #define POLLOUT SCE_NET_EPOLLOUT |
| 109 | #define POLLERR SCE_NET_EPOLLERR |
| 110 | #define POLLHUP SCE_NET_EPOLLHUP |
| 111 | #define POLLNVAL 0 |
| 112 | |
| 113 | #define sockaddr SceNetSockaddr |
| 114 | #define sockaddr_in SceNetSockaddrIn |
| 115 | #define in_addr SceNetInAddr |
| 116 | #define socklen_t unsigned int |
| 117 | |
| 118 | #define socket(a,b,c) sceNetSocket("unknown",a,b,c) |
| 119 | #define getsockname sceNetGetsockname |
| 120 | #define getsockopt sceNetGetsockopt |
| 121 | #define setsockopt sceNetSetsockopt |
| 122 | #define bind sceNetBind |
| 123 | #define listen sceNetListen |
| 124 | #define accept sceNetAccept |
| 125 | #define connect sceNetConnect |
| 126 | #define send sceNetSend |
| 127 | #define sendto sceNetSendto |
| 128 | #define recv sceNetRecv |
| 129 | #define recvfrom sceNetRecvfrom |
| 130 | #define htonl sceNetHtonl |
| 131 | #define ntohl sceNetNtohl |
| 132 | #define htons sceNetHtons |
| 133 | #define ntohs sceNetNtohs |
| 134 | #define inet_ntop sceNetInetNtop |
| 135 | #define inet_pton sceNetInetPton |
| 136 | |
| 137 | #elif defined(GEKKO) |
| 138 | #include <network.h> |
| 139 | |
| 140 | #define NETWORK_HAVE_POLL 1 |
| 141 | |
| 142 | #define pollfd pollsd |
| 143 | |
| 144 | #define socket(a,b,c) net_socket(a,b,c) |
| 145 | #define getsockopt(a,b,c,d,e) net_getsockopt(a,b,c,d,e) |
| 146 | #define setsockopt(a,b,c,d,e) net_setsockopt(a,b,c,d,e) |
| 147 | #define bind(a,b,c) net_bind(a,b,c) |
| 148 | #define listen(a,b) net_listen(a,b) |
| 149 | #define accept(a,b,c) net_accept(a,b,c) |
| 150 | #define connect(a,b,c) net_connect(a,b,c) |
| 151 | #define send(a,b,c,d) net_send(a,b,c,d) |
| 152 | #define sendto(a,b,c,d,e,f) net_sendto(a,b,c,d,e,f) |
| 153 | #define recv(a,b,c,d) net_recv(a,b,c,d) |
| 154 | #define recvfrom(a,b,c,d,e,f) net_recvfrom(a,b,c,d,e,f) |
| 155 | #define select(a,b,c,d,e) net_select(a,b,c,d,e) |
| 156 | #define gethostbyname(a) net_gethostbyname(a) |
| 157 | |
| 158 | #else |
| 159 | #include <sys/types.h> |
| 160 | #include <sys/socket.h> |
| 161 | #include <sys/select.h> |
| 162 | |
| 163 | #include <netinet/in.h> |
| 164 | #ifndef __PSL1GHT__ |
| 165 | #include <netinet/tcp.h> |
| 166 | #endif |
| 167 | |
| 168 | #include <arpa/inet.h> |
| 169 | #include <netdb.h> |
| 170 | #include <fcntl.h> |
| 171 | |
| 172 | #if !defined(__PSL1GHT__) && defined(__PS3__) |
| 173 | #include <netex/libnetctl.h> |
| 174 | #include <netex/errno.h> |
| 175 | #else |
| 176 | #include <signal.h> |
| 177 | #endif |
| 178 | |
| 179 | #if defined(__PSL1GHT__) |
| 180 | #include <net/poll.h> |
| 181 | |
| 182 | #define NETWORK_HAVE_POLL 1 |
| 183 | |
| 184 | #elif defined(WIIU) |
| 185 | #define WIIU_RCVBUF 0x40000 |
| 186 | #define WIIU_SNDBUF 0x40000 |
| 187 | |
| 188 | #elif !defined(__PS3__) |
| 189 | #include <poll.h> |
| 190 | |
| 191 | #define NETWORK_HAVE_POLL 1 |
| 192 | |
| 193 | #endif |
| 194 | #endif |
| 195 | |
| 196 | #ifndef MSG_NOSIGNAL |
| 197 | #define MSG_NOSIGNAL 0 |
| 198 | #endif |
| 199 | |
| 200 | #if defined(AF_INET6) && !defined(HAVE_SOCKET_LEGACY) && !defined(_3DS) |
| 201 | #define HAVE_INET6 1 |
| 202 | #endif |
| 203 | |
| 204 | #ifdef NETWORK_HAVE_POLL |
| 205 | #ifdef GEKKO |
| 206 | #define NET_POLL_FD(sockfd, sockfds) (sockfds)->socket = (sockfd) |
| 207 | #else |
| 208 | #define NET_POLL_FD(sockfd, sockfds) (sockfds)->fd = (sockfd) |
| 209 | #endif |
| 210 | #define NET_POLL_EVENT(sockev, sockfds) (sockfds)->events |= (sockev) |
| 211 | #define NET_POLL_HAS_EVENT(sockev, sockfds) ((sockfds)->revents & (sockev)) |
| 212 | #endif |
| 213 | |
| 214 | RETRO_BEGIN_DECLS |
| 215 | |
| 216 | /* Compatibility layer for legacy or incomplete BSD socket implementations. |
| 217 | * Only for IPv4. Mostly useful for the consoles which do not support |
| 218 | * anything reasonably modern on the socket API side of things. */ |
| 219 | #ifdef HAVE_SOCKET_LEGACY |
| 220 | #define sockaddr_storage sockaddr_in |
| 221 | |
| 222 | #ifdef AI_PASSIVE |
| 223 | #undef AI_PASSIVE |
| 224 | #endif |
| 225 | #ifdef AI_CANONNAME |
| 226 | #undef AI_CANONNAME |
| 227 | #endif |
| 228 | #ifdef AI_NUMERICHOST |
| 229 | #undef AI_NUMERICHOST |
| 230 | #endif |
| 231 | #ifdef AI_NUMERICSERV |
| 232 | #undef AI_NUMERICSERV |
| 233 | #endif |
| 234 | |
| 235 | #ifdef NI_NUMERICHOST |
| 236 | #undef NI_NUMERICHOST |
| 237 | #endif |
| 238 | #ifdef NI_NUMERICSERV |
| 239 | #undef NI_NUMERICSERV |
| 240 | #endif |
| 241 | #ifdef NI_NOFQDN |
| 242 | #undef NI_NOFQDN |
| 243 | #endif |
| 244 | #ifdef NI_NAMEREQD |
| 245 | #undef NI_NAMEREQD |
| 246 | #endif |
| 247 | #ifdef NI_DGRAM |
| 248 | #undef NI_DGRAM |
| 249 | #endif |
| 250 | |
| 251 | #define AI_PASSIVE 1 |
| 252 | #define AI_CANONNAME 2 |
| 253 | #define AI_NUMERICHOST 4 |
| 254 | #define AI_NUMERICSERV 8 |
| 255 | |
| 256 | #define NI_NUMERICHOST 1 |
| 257 | #define NI_NUMERICSERV 2 |
| 258 | #define NI_NOFQDN 4 |
| 259 | #define NI_NAMEREQD 8 |
| 260 | #define NI_DGRAM 16 |
| 261 | |
| 262 | #ifndef __PS3__ |
| 263 | struct addrinfo |
| 264 | { |
| 265 | int ai_flags; |
| 266 | int ai_family; |
| 267 | int ai_socktype; |
| 268 | int ai_protocol; |
| 269 | socklen_t ai_addrlen; |
| 270 | struct sockaddr *ai_addr; |
| 271 | char *ai_canonname; |
| 272 | struct addrinfo *ai_next; |
| 273 | }; |
| 274 | #endif |
| 275 | |
| 276 | /* gai_strerror() not used, so we skip that. */ |
| 277 | |
| 278 | #else |
| 279 | /* Ensure that getaddrinfo and getnameinfo flags are always defined. */ |
| 280 | #ifndef AI_PASSIVE |
| 281 | #define AI_PASSIVE 0 |
| 282 | #endif |
| 283 | #ifndef AI_CANONNAME |
| 284 | #define AI_CANONNAME 0 |
| 285 | #endif |
| 286 | #ifndef AI_NUMERICHOST |
| 287 | #define AI_NUMERICHOST 0 |
| 288 | #endif |
| 289 | #ifndef AI_NUMERICSERV |
| 290 | #define AI_NUMERICSERV 0 |
| 291 | #endif |
| 292 | |
| 293 | #ifndef NI_NUMERICHOST |
| 294 | #define NI_NUMERICHOST 0 |
| 295 | #endif |
| 296 | #ifndef NI_NUMERICSERV |
| 297 | #define NI_NUMERICSERV 0 |
| 298 | #endif |
| 299 | #ifndef NI_NOFQDN |
| 300 | #define NI_NOFQDN 0 |
| 301 | #endif |
| 302 | #ifndef NI_NAMEREQD |
| 303 | #define NI_NAMEREQD 0 |
| 304 | #endif |
| 305 | #ifndef NI_DGRAM |
| 306 | #define NI_DGRAM 0 |
| 307 | #endif |
| 308 | |
| 309 | #endif |
| 310 | |
| 311 | #if defined(_XBOX) |
| 312 | struct hostent |
| 313 | { |
| 314 | char *h_name; |
| 315 | char **h_aliases; |
| 316 | int h_addrtype; |
| 317 | int h_length; |
| 318 | char **h_addr_list; |
| 319 | char *h_addr; |
| 320 | char *h_end; |
| 321 | }; |
| 322 | |
| 323 | #elif defined(VITA) |
| 324 | struct pollfd |
| 325 | { |
| 326 | int fd; |
| 327 | unsigned events; |
| 328 | unsigned revents; |
| 329 | unsigned __pad; /* Align to 64-bits boundary */ |
| 330 | }; |
| 331 | |
| 332 | struct hostent |
| 333 | { |
| 334 | char *h_name; |
| 335 | char **h_aliases; |
| 336 | int h_addrtype; |
| 337 | int h_length; |
| 338 | char **h_addr_list; |
| 339 | char *h_addr; |
| 340 | char *h_end; |
| 341 | }; |
| 342 | |
| 343 | #endif |
| 344 | |
| 345 | static INLINE bool isagain(int val) |
| 346 | { |
| 347 | #if defined(_WIN32) |
| 348 | return (val == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK); |
| 349 | #elif !defined(__PSL1GHT__) && defined(__PS3__) |
| 350 | return (sys_net_errno == SYS_NET_EAGAIN) || (sys_net_errno == SYS_NET_EWOULDBLOCK); |
| 351 | #elif defined(VITA) |
| 352 | return (val == SCE_NET_ERROR_EAGAIN) || (val == SCE_NET_ERROR_EWOULDBLOCK); |
| 353 | #elif defined(WIIU) |
| 354 | return (val == -1) && (socketlasterr() == SO_SUCCESS || socketlasterr() == SO_EWOULDBLOCK); |
| 355 | #else |
| 356 | return (val < 0) && (errno == EAGAIN || errno == EWOULDBLOCK); |
| 357 | #endif |
| 358 | } |
| 359 | |
| 360 | static INLINE bool isinprogress(int val) |
| 361 | { |
| 362 | #if defined(_WIN32) |
| 363 | return (val == SOCKET_ERROR) && (WSAGetLastError() == WSAEWOULDBLOCK); |
| 364 | #elif !defined(__PSL1GHT__) && defined(__PS3__) |
| 365 | return (sys_net_errno == SYS_NET_EINPROGRESS); |
| 366 | #elif defined(VITA) |
| 367 | return (val == SCE_NET_ERROR_EINPROGRESS); |
| 368 | #elif defined(WIIU) |
| 369 | return (val == -1) && (socketlasterr() == SO_EINPROGRESS); |
| 370 | #else |
| 371 | return (val < 0) && (errno == EINPROGRESS); |
| 372 | #endif |
| 373 | } |
| 374 | |
| 375 | #if defined(_WIN32) && !defined(_XBOX) |
| 376 | #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 |
| 377 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); |
| 378 | int inet_pton(int af, const char *src, void *dst); |
| 379 | #endif |
| 380 | |
| 381 | #elif defined(_XBOX) |
| 382 | struct hostent *gethostbyname(const char *name); |
| 383 | |
| 384 | #elif defined(VITA) |
| 385 | char *inet_ntoa(struct in_addr in); |
| 386 | int inet_aton(const char *cp, struct in_addr *inp); |
| 387 | uint32_t inet_addr(const char *cp); |
| 388 | |
| 389 | struct hostent *gethostbyname(const char *name); |
| 390 | |
| 391 | #elif defined(GEKKO) |
| 392 | const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); |
| 393 | int inet_pton(int af, const char *src, void *dst); |
| 394 | |
| 395 | #endif |
| 396 | |
| 397 | int getaddrinfo_retro(const char *node, const char *service, |
| 398 | struct addrinfo *hints, struct addrinfo **res); |
| 399 | |
| 400 | void freeaddrinfo_retro(struct addrinfo *res); |
| 401 | |
| 402 | int getnameinfo_retro(const struct sockaddr *addr, socklen_t addrlen, |
| 403 | char *host, socklen_t hostlen, char *serv, socklen_t servlen, int flags); |
| 404 | |
| 405 | bool addr_6to4(struct sockaddr_storage *addr); |
| 406 | |
| 407 | bool ipv4_is_lan_address(const struct sockaddr_in *addr); |
| 408 | bool ipv4_is_cgnat_address(const struct sockaddr_in *addr); |
| 409 | |
| 410 | /** |
| 411 | * network_init: |
| 412 | * |
| 413 | * Platform specific socket library initialization. |
| 414 | * |
| 415 | * @return true if successful, otherwise false. |
| 416 | **/ |
| 417 | bool network_init(void); |
| 418 | |
| 419 | RETRO_END_DECLS |
| 420 | |
| 421 | #endif |