MockReflector.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // libtgvoip is free and unencumbered public domain software.
  3. // For more information, see http://unlicense.org or the UNLICENSE file
  4. // you should have received with this source code distribution.
  5. //
  6. #include "MockReflector.h"
  7. #include <arpa/inet.h>
  8. #include <assert.h>
  9. #include <stdio.h>
  10. using namespace tgvoip;
  11. using namespace tgvoip::test;
  12. struct UdpReflectorSelfInfo{
  13. uint8_t peerTag[16];
  14. uint64_t _id1=0xFFFFFFFFFFFFFFFFLL;
  15. uint32_t _id2=0xFFFFFFFF;
  16. uint32_t magic=0xc01572c7;
  17. int32_t date;
  18. uint64_t query_id;
  19. uint64_t my_ip_padding1;
  20. uint32_t my_ip_padding2;
  21. uint32_t my_ip;
  22. uint32_t my_port;
  23. } __attribute__((packed));
  24. MockReflector::MockReflector(std::string bindAddress, uint16_t bindPort){
  25. sfd=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  26. assert(sfd!=-1);
  27. sockaddr_in bindAddr={0};
  28. bindAddr.sin_family=AF_INET;
  29. bindAddr.sin_port=htons(bindPort);
  30. inet_aton(bindAddress.c_str(), &bindAddr.sin_addr);
  31. int res=bind(sfd, (struct sockaddr*)&bindAddr, sizeof(bindAddr));
  32. assert(res==0);
  33. }
  34. MockReflector::~MockReflector(){
  35. }
  36. std::array<std::array<uint8_t, 16>, 2> MockReflector::GeneratePeerTags(){
  37. std::array<uint8_t, 16> tag1;
  38. for(int i=0;i<16;i++){
  39. tag1[i]=(uint8_t)rand();
  40. }
  41. tag1[15] &= 0xFE;
  42. std::array<std::array<uint8_t, 16>, 2> res;
  43. res[0]=tag1;
  44. std::copy(tag1.begin(), tag1.end(), res[1].begin());
  45. res[1][15] |= 1;
  46. return res;
  47. }
  48. void MockReflector::Start(){
  49. if(running)
  50. return;
  51. running=true;
  52. pthread_create(&thread, NULL, [](void* arg) -> void* {
  53. reinterpret_cast<MockReflector*>(arg)->RunThread();
  54. return NULL;
  55. }, this);
  56. }
  57. void MockReflector::Stop(){
  58. running=false;
  59. shutdown(sfd, SHUT_RDWR);
  60. close(sfd);
  61. pthread_join(thread, NULL);
  62. }
  63. void MockReflector::SetDropAllPackets(bool drop){
  64. dropAllPackets=drop;
  65. }
  66. void MockReflector::RunThread(){
  67. while(running){
  68. std::array<uint8_t, 1500> buf;
  69. sockaddr_in addr;
  70. socklen_t addrlen=sizeof(addr);
  71. ssize_t len=recvfrom(sfd, buf.data(), sizeof(buf), 0, (struct sockaddr*)&addr, &addrlen);
  72. if(len<=0)
  73. return;
  74. if(len>=32){
  75. std::array<uint8_t, 16> peerTag;
  76. int32_t specialID[4];
  77. std::copy(buf.begin(), buf.begin()+16, peerTag.begin());
  78. memcpy(specialID, buf.data()+16, 16);
  79. uint64_t tagID=*reinterpret_cast<uint64_t*>(peerTag.data());
  80. ClientPair c=clients[tagID];
  81. sockaddr_in* dest;
  82. if(peerTag[15] & 1){
  83. c.addr1=addr;
  84. dest=&c.addr0;
  85. }else{
  86. c.addr0=addr;
  87. dest=&c.addr1;
  88. }
  89. clients[tagID]=c;
  90. if(specialID[0]==-1 && specialID[1]==-1 && specialID[2]==-1){
  91. if(specialID[3]==-1){
  92. continue;
  93. }else if(specialID[3]==-2){
  94. UdpReflectorSelfInfo response;
  95. memcpy(response.peerTag, peerTag.data(), 16);
  96. response.date=(int32_t)time(NULL);
  97. response.query_id=*reinterpret_cast<uint64_t*>(buf.data()+32);
  98. response.my_ip_padding1=0;
  99. response.my_ip_padding2=0xFFFF0000;
  100. response.my_ip=(uint32_t)addr.sin_addr.s_addr;
  101. response.my_port=ntohs(addr.sin_port);
  102. sendto(sfd, &response, sizeof(response), 0, (struct sockaddr*)&addr, sizeof(addr));
  103. continue;
  104. }
  105. }
  106. if(dest->sin_family==AF_INET && !dropAllPackets){
  107. if(peerTag[15] & 1)
  108. buf[15] &= 0xFE;
  109. else
  110. buf[15] |= 1;
  111. sendto(sfd, buf.data(), len, 0, (struct sockaddr*)dest, sizeof(sockaddr_in));
  112. }
  113. }
  114. }
  115. }