creators.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #include "stdafx.h"
  2. #include <string.h>
  3. #include <util/generic/utility.h>
  4. #include <util/network/init.h>
  5. #include <util/system/defaults.h>
  6. #include <util/system/yassert.h>
  7. #include "socket.h"
  8. namespace NNetlibaSocket {
  9. void* CreateTos(const ui8 tos, void* buffer) {
  10. #ifdef _win_
  11. *(int*)buffer = (int)tos;
  12. #else
  13. // glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=13500
  14. memset(buffer, 0, TOS_BUFFER_SIZE);
  15. msghdr dummy;
  16. Zero(dummy);
  17. dummy.msg_control = buffer;
  18. dummy.msg_controllen = TOS_BUFFER_SIZE;
  19. // TODO: in FreeBSD setting TOS for dual stack sockets does not affect ipv4 frames
  20. cmsghdr* cmsg = CMSG_FIRSTHDR(&dummy);
  21. cmsg->cmsg_level = IPPROTO_IPV6;
  22. cmsg->cmsg_type = IPV6_TCLASS;
  23. cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  24. memcpy(CMSG_DATA(cmsg), &tos, sizeof(tos)); // memcpy shut ups alias restrict warning
  25. Y_ASSERT(CMSG_NXTHDR(&dummy, cmsg) == nullptr);
  26. #endif
  27. return buffer;
  28. }
  29. TMsgHdr* AddSockAuxData(TMsgHdr* header, const ui8 tos, const sockaddr_in6& myAddr, void* buffer, size_t bufferSize) {
  30. #ifdef _win_
  31. Y_UNUSED(header);
  32. Y_UNUSED(tos);
  33. Y_UNUSED(myAddr);
  34. Y_UNUSED(buffer);
  35. Y_UNUSED(bufferSize);
  36. return nullptr;
  37. #else
  38. header->msg_control = buffer;
  39. header->msg_controllen = bufferSize;
  40. size_t totalLen = 0;
  41. #ifdef _cygwin_
  42. Y_UNUSED(tos);
  43. #else
  44. // Cygwin does not support IPV6_TCLASS, so we ignore it
  45. cmsghdr* cmsgTos = CMSG_FIRSTHDR(header);
  46. if (cmsgTos == nullptr) {
  47. header->msg_control = nullptr;
  48. header->msg_controllen = 0;
  49. return nullptr;
  50. }
  51. cmsgTos->cmsg_level = IPPROTO_IPV6;
  52. cmsgTos->cmsg_type = IPV6_TCLASS;
  53. cmsgTos->cmsg_len = CMSG_LEN(sizeof(int));
  54. totalLen = CMSG_SPACE(sizeof(int));
  55. *(ui8*)CMSG_DATA(cmsgTos) = tos;
  56. #endif
  57. if (*(ui64*)myAddr.sin6_addr.s6_addr != 0u) {
  58. in6_pktinfo* pktInfo;
  59. #ifdef _cygwin_
  60. cmsghdr* cmsgAddr = CMSG_FIRSTHDR(header);
  61. #else
  62. cmsghdr* cmsgAddr = CMSG_NXTHDR(header, cmsgTos);
  63. #endif
  64. if (cmsgAddr == nullptr) {
  65. // leave only previous record
  66. header->msg_controllen = totalLen;
  67. return nullptr;
  68. }
  69. cmsgAddr->cmsg_level = IPPROTO_IPV6;
  70. cmsgAddr->cmsg_type = IPV6_PKTINFO;
  71. cmsgAddr->cmsg_len = CMSG_LEN(sizeof(*pktInfo));
  72. totalLen += CMSG_SPACE(sizeof(*pktInfo));
  73. pktInfo = (in6_pktinfo*)CMSG_DATA(cmsgAddr);
  74. pktInfo->ipi6_addr = myAddr.sin6_addr;
  75. pktInfo->ipi6_ifindex = 0; /* 0 = use interface specified in routing table */
  76. }
  77. header->msg_controllen = totalLen; //write right len
  78. return header;
  79. #endif
  80. }
  81. TIoVec CreateIoVec(char* data, const size_t dataSize) {
  82. TIoVec result;
  83. Zero(result);
  84. result.iov_base = data;
  85. result.iov_len = dataSize;
  86. return result;
  87. }
  88. TMsgHdr CreateSendMsgHdr(const sockaddr_in6& addr, const TIoVec& iov, void* tosBuffer) {
  89. TMsgHdr result;
  90. Zero(result);
  91. result.msg_name = (void*)&addr;
  92. result.msg_namelen = sizeof(addr);
  93. result.msg_iov = (TIoVec*)&iov;
  94. result.msg_iovlen = 1;
  95. if (tosBuffer) {
  96. #ifdef _win_
  97. result.Tos = *(int*)tosBuffer;
  98. #else
  99. result.msg_control = tosBuffer;
  100. result.msg_controllen = TOS_BUFFER_SIZE;
  101. #endif
  102. }
  103. return result;
  104. }
  105. TMsgHdr CreateRecvMsgHdr(sockaddr_in6* addrBuf, const TIoVec& iov, void* controllBuffer) {
  106. TMsgHdr result;
  107. Zero(result);
  108. Zero(*addrBuf);
  109. result.msg_name = addrBuf;
  110. result.msg_namelen = sizeof(*addrBuf);
  111. result.msg_iov = (TIoVec*)&iov;
  112. result.msg_iovlen = 1;
  113. #ifndef _win_
  114. if (controllBuffer) {
  115. memset(controllBuffer, 0, CTRL_BUFFER_SIZE);
  116. result.msg_control = controllBuffer;
  117. result.msg_controllen = CTRL_BUFFER_SIZE;
  118. }
  119. #endif
  120. return result;
  121. }
  122. }