pair.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "pair.h"
  2. int SocketPair(SOCKET socks[2], bool overlapped, bool cloexec) {
  3. #if defined(_win_)
  4. struct sockaddr_in addr;
  5. SOCKET listener;
  6. int e;
  7. int addrlen = sizeof(addr);
  8. DWORD flags = (overlapped ? WSA_FLAG_OVERLAPPED : 0) | (cloexec ? WSA_FLAG_NO_HANDLE_INHERIT : 0);
  9. if (socks == 0) {
  10. WSASetLastError(WSAEINVAL);
  11. return SOCKET_ERROR;
  12. }
  13. socks[0] = INVALID_SOCKET;
  14. socks[1] = INVALID_SOCKET;
  15. if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
  16. return SOCKET_ERROR;
  17. }
  18. memset(&addr, 0, sizeof(addr));
  19. addr.sin_family = AF_INET;
  20. addr.sin_addr.s_addr = htonl(0x7f000001);
  21. addr.sin_port = 0;
  22. e = bind(listener, (const struct sockaddr*)&addr, sizeof(addr));
  23. if (e == SOCKET_ERROR) {
  24. e = WSAGetLastError();
  25. closesocket(listener);
  26. WSASetLastError(e);
  27. return SOCKET_ERROR;
  28. }
  29. e = getsockname(listener, (struct sockaddr*)&addr, &addrlen);
  30. if (e == SOCKET_ERROR) {
  31. e = WSAGetLastError();
  32. closesocket(listener);
  33. WSASetLastError(e);
  34. return SOCKET_ERROR;
  35. }
  36. do {
  37. if (listen(listener, 1) == SOCKET_ERROR) {
  38. break;
  39. }
  40. if ((socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, nullptr, 0, flags)) == INVALID_SOCKET) {
  41. break;
  42. }
  43. if (connect(socks[0], (const struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
  44. break;
  45. }
  46. if ((socks[1] = accept(listener, nullptr, nullptr)) == INVALID_SOCKET) {
  47. break;
  48. }
  49. closesocket(listener);
  50. return 0;
  51. } while (0);
  52. e = WSAGetLastError();
  53. closesocket(listener);
  54. closesocket(socks[0]);
  55. closesocket(socks[1]);
  56. WSASetLastError(e);
  57. return SOCKET_ERROR;
  58. #else
  59. (void)overlapped;
  60. #if defined(_linux_)
  61. return socketpair(AF_LOCAL, SOCK_STREAM | (cloexec ? SOCK_CLOEXEC : 0), 0, socks);
  62. #else
  63. int r = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
  64. // Non-atomic wrt exec
  65. if (r == 0 && cloexec) {
  66. for (int i = 0; i < 2; ++i) {
  67. int flags = fcntl(socks[i], F_GETFD, 0);
  68. if (flags < 0) {
  69. return flags;
  70. }
  71. r = fcntl(socks[i], F_SETFD, flags | FD_CLOEXEC);
  72. if (r < 0) {
  73. return r;
  74. }
  75. }
  76. }
  77. return r;
  78. #endif
  79. #endif
  80. }