| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- //
- // Created by Grishka on 29.03.17.
- //
- #include "NetworkSocket.h"
- #include <stdexcept>
- #include <algorithm>
- #include <stdlib.h>
- #include <string.h>
- #if defined(_WIN32)
- #include "os/windows/NetworkSocketWinsock.h"
- #include <winsock2.h>
- #else
- #include "os/posix/NetworkSocketPosix.h"
- #endif
- #include "logging.h"
- #include "VoIPServerConfig.h"
- #include "VoIPController.h"
- #include "Buffers.h"
- #define MIN_UDP_PORT 16384
- #define MAX_UDP_PORT 32768
- using namespace tgvoip;
- NetworkSocket::NetworkSocket(NetworkProtocol protocol) : protocol(protocol){
- ipv6Timeout=ServerConfig::GetSharedInstance()->GetDouble("nat64_fallback_timeout", 3);
- failed=false;
- }
- NetworkSocket::~NetworkSocket(){
- }
- std::string NetworkSocket::GetLocalInterfaceInfo(IPv4Address *inet4addr, IPv6Address *inet6addr){
- std::string r="not implemented";
- return r;
- }
- uint16_t NetworkSocket::GenerateLocalPort(){
- uint16_t rnd;
- VoIPController::crypto.rand_bytes(reinterpret_cast<uint8_t*>(&rnd), 2);
- return (uint16_t) ((rnd%(MAX_UDP_PORT-MIN_UDP_PORT))+MIN_UDP_PORT);
- }
- void NetworkSocket::SetMaxPriority(){
- }
- bool NetworkSocket::IsFailed(){
- return failed;
- }
- NetworkSocket *NetworkSocket::Create(NetworkProtocol protocol){
- #ifndef _WIN32
- return new NetworkSocketPosix(protocol);
- #else
- return new NetworkSocketWinsock(protocol);
- #endif
- }
- IPv4Address *NetworkSocket::ResolveDomainName(std::string name){
- #ifndef _WIN32
- return NetworkSocketPosix::ResolveDomainName(name);
- #else
- return NetworkSocketWinsock::ResolveDomainName(name);
- #endif
- }
- void NetworkSocket::GenerateTCPO2States(unsigned char* buffer, TCPO2State* recvState, TCPO2State* sendState){
- memset(recvState, 0, sizeof(TCPO2State));
- memset(sendState, 0, sizeof(TCPO2State));
- unsigned char nonce[64];
- uint32_t *first = reinterpret_cast<uint32_t*>(nonce), *second = first + 1;
- uint32_t first1 = 0x44414548U, first2 = 0x54534f50U, first3 = 0x20544547U, first4 = 0x20544547U, first5 = 0xeeeeeeeeU;
- uint32_t second1 = 0;
- do {
- VoIPController::crypto.rand_bytes(nonce, sizeof(nonce));
- } while (*first == first1 || *first == first2 || *first == first3 || *first == first4 || *first == first5 || *second == second1 || *reinterpret_cast<unsigned char*>(nonce) == 0xef);
- // prepare encryption key/iv
- memcpy(sendState->key, nonce + 8, 32);
- memcpy(sendState->iv, nonce + 8 + 32, 16);
- // prepare decryption key/iv
- char reversed[48];
- memcpy(reversed, nonce + 8, sizeof(reversed));
- std::reverse(reversed, reversed + sizeof(reversed));
- memcpy(recvState->key, reversed, 32);
- memcpy(recvState->iv, reversed + 32, 16);
- // write protocol identifier
- *reinterpret_cast<uint32_t*>(nonce + 56) = 0xefefefefU;
- memcpy(buffer, nonce, 56);
- EncryptForTCPO2(nonce, sizeof(nonce), sendState);
- memcpy(buffer+56, nonce+56, 8);
- }
- void NetworkSocket::EncryptForTCPO2(unsigned char *buffer, size_t len, TCPO2State *state){
- VoIPController::crypto.aes_ctr_encrypt(buffer, len, state->key, state->iv, state->ecount, &state->num);
- }
- size_t NetworkSocket::Receive(unsigned char *buffer, size_t len){
- NetworkPacket pkt={0};
- pkt.data=buffer;
- pkt.length=len;
- Receive(&pkt);
- return pkt.length;
- }
- size_t NetworkSocket::Send(unsigned char *buffer, size_t len){
- NetworkPacket pkt={0};
- pkt.data=buffer;
- pkt.length=len;
- Send(&pkt);
- return pkt.length;
- }
- bool NetworkAddress::operator==(const NetworkAddress &other) const{
- const IPv4Address* self4=dynamic_cast<const IPv4Address*>(this);
- const IPv4Address* other4=dynamic_cast<const IPv4Address*>((NetworkAddress*)&other);
- if(self4 && other4){
- return self4->GetAddress()==other4->GetAddress();
- }
- const IPv6Address* self6=dynamic_cast<const IPv6Address*>(this);
- const IPv6Address* other6=dynamic_cast<const IPv6Address*>((NetworkAddress*)&other);
- if(self6 && other6){
- return memcmp(self6->GetAddress(), other6->GetAddress(), 16)==0;
- }
- return false;
- }
- bool NetworkAddress::operator!=(const NetworkAddress &other) const{
- return !(*this == other);
- }
- IPv4Address::IPv4Address(std::string addr){
- #ifndef _WIN32
- this->address=NetworkSocketPosix::StringToV4Address(addr);
- #else
- this->address=NetworkSocketWinsock::StringToV4Address(addr);
- #endif
- }
- IPv4Address::IPv4Address(uint32_t addr){
- this->address=addr;
- }
- IPv4Address::IPv4Address(){
- this->address=0;
- }
- std::string IPv4Address::ToString() const{
- #ifndef _WIN32
- return NetworkSocketPosix::V4AddressToString(address);
- #else
- return NetworkSocketWinsock::V4AddressToString(address);
- #endif
- }
- bool IPv4Address::PrefixMatches(const unsigned int prefix, const NetworkAddress &other) const{
- const IPv4Address* v4=dynamic_cast<const IPv4Address*>(&other);
- if(v4){
- uint32_t mask=0xFFFFFFFF << (32-prefix);
- return (address & mask) == (v4->address & mask);
- }
- return false;
- }
- /*sockaddr &IPv4Address::ToSockAddr(uint16_t port){
- sockaddr_in sa;
- sa.sin_family=AF_INET;
- sa.sin_addr=addr;
- sa.sin_port=port;
- return *((sockaddr *) &sa);
- }*/
- uint32_t IPv4Address::GetAddress() const{
- return address;
- }
- bool IPv4Address::IsEmpty() const{
- return address==0;
- }
- IPv6Address::IPv6Address(std::string addr){
- #ifndef _WIN32
- NetworkSocketPosix::StringToV6Address(addr, this->address);
- #else
- NetworkSocketWinsock::StringToV6Address(addr, this->address);
- #endif
- }
- IPv6Address::IPv6Address(const uint8_t* addr){
- memcpy(address, addr, 16);
- }
- IPv6Address::IPv6Address(){
- memset(address, 0, 16);
- }
- std::string IPv6Address::ToString() const{
- #ifndef _WIN32
- return NetworkSocketPosix::V6AddressToString(address);
- #else
- return NetworkSocketWinsock::V6AddressToString(address);
- #endif
- }
- bool IPv6Address::PrefixMatches(const unsigned int prefix, const NetworkAddress &other) const{
- return false;
- }
- bool IPv6Address::IsEmpty() const{
- const uint64_t* a=reinterpret_cast<const uint64_t*>(address);
- return a[0]==0LL && a[1]==0LL;
- }
- /*sockaddr &IPv6Address::ToSockAddr(uint16_t port){
- sockaddr_in6 sa;
- sa.sin6_family=AF_INET6;
- sa.sin6_addr=addr;
- sa.sin6_port=port;
- return *((sockaddr *) &sa);
- }*/
- const uint8_t *IPv6Address::GetAddress() const{
- return address;
- }
- bool NetworkSocket::Select(std::vector<NetworkSocket *> &readFds, std::vector<NetworkSocket*> &writeFds, std::vector<NetworkSocket *> &errorFds, SocketSelectCanceller *canceller){
- #ifndef _WIN32
- return NetworkSocketPosix::Select(readFds, writeFds, errorFds, canceller);
- #else
- return NetworkSocketWinsock::Select(readFds, writeFds, errorFds, canceller);
- #endif
- }
- SocketSelectCanceller::~SocketSelectCanceller(){
- }
- SocketSelectCanceller *SocketSelectCanceller::Create(){
- #ifndef _WIN32
- return new SocketSelectCancellerPosix();
- #else
- return new SocketSelectCancellerWin32();
- #endif
- }
- NetworkSocketTCPObfuscated::NetworkSocketTCPObfuscated(NetworkSocket *wrapped) : NetworkSocketWrapper(PROTO_TCP){
- this->wrapped=wrapped;
- }
- NetworkSocketTCPObfuscated::~NetworkSocketTCPObfuscated(){
- if(wrapped)
- delete wrapped;
- }
- NetworkSocket *NetworkSocketTCPObfuscated::GetWrapped(){
- return wrapped;
- }
- void NetworkSocketTCPObfuscated::InitConnection(){
- unsigned char buf[64];
- GenerateTCPO2States(buf, &recvState, &sendState);
- wrapped->Send(buf, 64);
- }
- void NetworkSocketTCPObfuscated::Send(NetworkPacket *packet){
- BufferOutputStream os(packet->length+4);
- size_t len=packet->length/4;
- if(len<0x7F){
- os.WriteByte((unsigned char)len);
- }else{
- os.WriteByte(0x7F);
- os.WriteByte((unsigned char)(len & 0xFF));
- os.WriteByte((unsigned char)((len >> 8) & 0xFF));
- os.WriteByte((unsigned char)((len >> 16) & 0xFF));
- }
- os.WriteBytes(packet->data, packet->length);
- EncryptForTCPO2(os.GetBuffer(), os.GetLength(), &sendState);
- wrapped->Send(os.GetBuffer(), os.GetLength());
- //LOGD("Sent %u bytes", os.GetLength());
- }
- bool NetworkSocketTCPObfuscated::OnReadyToSend(){
- if(!initialized){
- //LOGV("Initializing TCPO2 connection");
- initialized=true;
- InitConnection();
- readyToSend=true;
- return false;
- }
- return wrapped->OnReadyToSend();
- }
- void NetworkSocketTCPObfuscated::Receive(NetworkPacket *packet){
- unsigned char len1;
- size_t packetLen=0;
- size_t offset=0;
- size_t len;
- len=wrapped->Receive(&len1, 1);
- if(len<=0){
- packet->length=0;
- return;
- }
- EncryptForTCPO2(&len1, 1, &recvState);
- if(len1<0x7F){
- packetLen=(size_t)len1*4;
- }else{
- unsigned char len2[3];
- len=wrapped->Receive(len2, 3);
- if(len<=0){
- packet->length=0;
- return;
- }
- EncryptForTCPO2(len2, 3, &recvState);
- packetLen=((size_t)len2[0] | ((size_t)len2[1] << 8) | ((size_t)len2[2] << 16))*4;
- }
- if(packetLen>packet->length){
- LOGW("packet too big to fit into buffer (%u vs %u)", (unsigned int)packetLen, (unsigned int)packet->length);
- packet->length=0;
- return;
- }
- while(offset<packetLen){
- len=wrapped->Receive(packet->data+offset, packetLen-offset);
- if(len<=0){
- packet->length=0;
- return;
- }
- offset+=len;
- }
- EncryptForTCPO2(packet->data, packetLen, &recvState);
- //packet->address=&itr->address;
- packet->length=packetLen;
- //packet->port=itr->port;
- packet->protocol=PROTO_TCP;
- packet->address=wrapped->GetConnectedAddress();
- packet->port=wrapped->GetConnectedPort();
- }
- void NetworkSocketTCPObfuscated::Open(){
- }
- void NetworkSocketTCPObfuscated::Close(){
- wrapped->Close();
- }
- void NetworkSocketTCPObfuscated::Connect(const NetworkAddress *address, uint16_t port){
- wrapped->Connect(address, port);
- }
- bool NetworkSocketTCPObfuscated::IsFailed(){
- return wrapped->IsFailed();
- }
- NetworkSocketSOCKS5Proxy::NetworkSocketSOCKS5Proxy(NetworkSocket *tcp, NetworkSocket *udp, std::string username, std::string password) : NetworkSocketWrapper(udp ? PROTO_UDP : PROTO_TCP){
- this->tcp=tcp;
- this->udp=udp;
- this->username=std::move(username);
- this->password=std::move(password);
- connectedAddress=NULL;
- }
- NetworkSocketSOCKS5Proxy::~NetworkSocketSOCKS5Proxy(){
- delete tcp;
- if(connectedAddress)
- delete connectedAddress;
- }
- void NetworkSocketSOCKS5Proxy::Send(NetworkPacket *packet){
- if(protocol==PROTO_TCP){
- tcp->Send(packet);
- }else if(protocol==PROTO_UDP){
- unsigned char buf[1500];
- BufferOutputStream out(buf, sizeof(buf));
- out.WriteInt16(0); // RSV
- out.WriteByte(0); // FRAG
- const IPv4Address* v4=dynamic_cast<IPv4Address*>(packet->address);
- const IPv6Address* v6=dynamic_cast<IPv6Address*>(packet->address);
- if(v4){
- out.WriteByte(1); // ATYP (IPv4)
- out.WriteInt32(v4->GetAddress());
- }else{
- out.WriteByte(4); // ATYP (IPv6)
- out.WriteBytes((unsigned char *) v6->GetAddress(), 16);
- }
- out.WriteInt16(htons(packet->port));
- out.WriteBytes(packet->data, packet->length);
- NetworkPacket p={0};
- p.data=buf;
- p.length=out.GetLength();
- p.address=connectedAddress;
- p.port=connectedPort;
- p.protocol=PROTO_UDP;
- udp->Send(&p);
- }
- }
- void NetworkSocketSOCKS5Proxy::Receive(NetworkPacket *packet){
- if(protocol==PROTO_TCP){
- tcp->Receive(packet);
- packet->address=connectedAddress;
- packet->port=connectedPort;
- }else if(protocol==PROTO_UDP){
- unsigned char buf[1500];
- NetworkPacket p={0};
- p.data=buf;
- p.length=sizeof(buf);
- udp->Receive(&p);
- if(p.length && p.address && *p.address==*connectedAddress && p.port==connectedPort){
- BufferInputStream in(buf, p.length);
- in.ReadInt16(); // RSV
- in.ReadByte(); // FRAG
- unsigned char atyp=in.ReadByte();
- if(atyp==1){ // IPv4
- lastRecvdV4=IPv4Address((uint32_t) in.ReadInt32());
- packet->address=&lastRecvdV4;
- }else if(atyp==4){ // IPv6
- unsigned char addr[16];
- in.ReadBytes(addr, 16);
- lastRecvdV6=IPv6Address(addr);
- packet->address=&lastRecvdV6;
- }
- packet->port=ntohs(in.ReadInt16());
- if(packet->length>=in.Remaining()){
- packet->length=in.Remaining();
- in.ReadBytes(packet->data, in.Remaining());
- }else{
- packet->length=0;
- LOGW("socks5: received packet too big");
- }
- }
- }
- }
- void NetworkSocketSOCKS5Proxy::Open(){
- }
- void NetworkSocketSOCKS5Proxy::Close(){
- tcp->Close();
- }
- void NetworkSocketSOCKS5Proxy::Connect(const NetworkAddress *address, uint16_t port){
- const IPv4Address* v4=dynamic_cast<const IPv4Address*>(address);
- const IPv6Address* v6=dynamic_cast<const IPv6Address*>(address);
- connectedAddress=v4 ? (NetworkAddress*)new IPv4Address(*v4) : (NetworkAddress*)new IPv6Address(*v6);
- connectedPort=port;
- }
- NetworkSocket *NetworkSocketSOCKS5Proxy::GetWrapped(){
- return protocol==PROTO_TCP ? tcp : udp;
- }
- void NetworkSocketSOCKS5Proxy::InitConnection(){
- }
- bool NetworkSocketSOCKS5Proxy::IsFailed(){
- return NetworkSocket::IsFailed() || tcp->IsFailed();
- }
- NetworkAddress *NetworkSocketSOCKS5Proxy::GetConnectedAddress(){
- return connectedAddress;
- }
- uint16_t NetworkSocketSOCKS5Proxy::GetConnectedPort(){
- return connectedPort;
- }
- bool NetworkSocketSOCKS5Proxy::OnReadyToSend(){
- //LOGV("on ready to send, state=%d", state);
- unsigned char buf[1024];
- if(state==ConnectionState::Initial){
- BufferOutputStream p(buf, sizeof(buf));
- p.WriteByte(5); // VER
- if(!username.empty()){
- p.WriteByte(2); // NMETHODS
- p.WriteByte(0); // no auth
- p.WriteByte(2); // user/pass
- }else{
- p.WriteByte(1); // NMETHODS
- p.WriteByte(0); // no auth
- }
- tcp->Send(buf, p.GetLength());
- state=ConnectionState::WaitingForAuthMethod;
- return false;
- }
- return udp ? udp->OnReadyToSend() : tcp->OnReadyToSend();
- }
- bool NetworkSocketSOCKS5Proxy::OnReadyToReceive(){
- //LOGV("on ready to receive state=%d", state);
- unsigned char buf[1024];
- if(state==ConnectionState::WaitingForAuthMethod){
- size_t l=tcp->Receive(buf, sizeof(buf));
- if(l<2 || tcp->IsFailed()){
- failed=true;
- return false;
- }
- BufferInputStream in(buf, l);
- unsigned char ver=in.ReadByte();
- unsigned char chosenMethod=in.ReadByte();
- LOGV("socks5: VER=%02X, METHOD=%02X", ver, chosenMethod);
- if(ver!=5){
- LOGW("socks5: incorrect VER in response");
- failed=true;
- return false;
- }
- if(chosenMethod==0){
- // connected, no further auth needed
- SendConnectionCommand();
- }else if(chosenMethod==2 && !username.empty()){
- BufferOutputStream p(buf, sizeof(buf));
- p.WriteByte(1); // VER
- p.WriteByte((unsigned char)(username.length()>255 ? 255 : username.length())); // ULEN
- p.WriteBytes((unsigned char*)username.c_str(), username.length()>255 ? 255 : username.length()); // UNAME
- p.WriteByte((unsigned char)(password.length()>255 ? 255 : password.length())); // PLEN
- p.WriteBytes((unsigned char*)password.c_str(), password.length()>255 ? 255 : password.length()); // PASSWD
- tcp->Send(buf, p.GetLength());
- state=ConnectionState::WaitingForAuthResult;
- }else{
- LOGW("socks5: unsupported auth method");
- failed=true;
- return false;
- }
- return false;
- }else if(state==ConnectionState::WaitingForAuthResult){
- size_t l=tcp->Receive(buf, sizeof(buf));
- if(l<2 || tcp->IsFailed()){
- failed=true;
- return false;
- }
- BufferInputStream in(buf, l);
- uint8_t ver=in.ReadByte();
- unsigned char status=in.ReadByte();
- LOGV("socks5: auth response VER=%02X, STATUS=%02X", ver, status);
- if(ver!=1){
- LOGW("socks5: auth response VER is incorrect");
- failed=true;
- return false;
- }
- if(status!=0){
- LOGW("socks5: username/password auth failed");
- failed=true;
- return false;
- }
- LOGV("socks5: authentication succeeded");
- SendConnectionCommand();
- return false;
- }else if(state==ConnectionState::WaitingForCommandResult){
- size_t l=tcp->Receive(buf, sizeof(buf));
- if(protocol==PROTO_TCP){
- if(l<2 || tcp->IsFailed()){
- LOGW("socks5: connect failed")
- failed=true;
- return false;
- }
- BufferInputStream in(buf, l);
- unsigned char ver=in.ReadByte();
- if(ver!=5){
- LOGW("socks5: connect: wrong ver in response");
- failed=true;
- return false;
- }
- unsigned char rep=in.ReadByte();
- if(rep!=0){
- LOGW("socks5: connect: failed with error %02X", rep);
- failed=true;
- return false;
- }
- LOGV("socks5: connect succeeded");
- state=ConnectionState::Connected;
- tcp=new NetworkSocketTCPObfuscated(tcp);
- readyToSend=true;
- return tcp->OnReadyToSend();
- }else if(protocol==PROTO_UDP){
- if(l<2 || tcp->IsFailed()){
- LOGW("socks5: udp associate failed");
- failed=true;
- return false;
- }
- try{
- BufferInputStream in(buf, l);
- unsigned char ver=in.ReadByte();
- unsigned char rep=in.ReadByte();
- if(ver!=5){
- LOGW("socks5: udp associate: wrong ver in response");
- failed=true;
- return false;
- }
- if(rep!=0){
- LOGW("socks5: udp associate failed with error %02X", rep);
- failed=true;
- return false;
- }
- in.ReadByte(); // RSV
- unsigned char atyp=in.ReadByte();
- if(atyp==1){
- uint32_t addr=(uint32_t) in.ReadInt32();
- connectedAddress=new IPv4Address(addr);
- }else if(atyp==3){
- unsigned char len=in.ReadByte();
- char domain[256];
- memset(domain, 0, sizeof(domain));
- in.ReadBytes((unsigned char*)domain, len);
- LOGD("address type is domain, address=%s", domain);
- connectedAddress=ResolveDomainName(std::string(domain));
- if(!connectedAddress){
- LOGW("socks5: failed to resolve domain name '%s'", domain);
- failed=true;
- return false;
- }
- }else if(atyp==4){
- unsigned char addr[16];
- in.ReadBytes(addr, 16);
- connectedAddress=new IPv6Address(addr);
- }else{
- LOGW("socks5: unknown address type %d", atyp);
- failed=true;
- return false;
- }
- connectedPort=(uint16_t)ntohs(in.ReadInt16());
- state=ConnectionState::Connected;
- readyToSend=true;
- LOGV("socks5: udp associate successful, given endpoint %s:%d", connectedAddress->ToString().c_str(), connectedPort);
- }catch(std::out_of_range&){
- LOGW("socks5: udp associate response parse failed");
- failed=true;
- }
- }
- }
- return udp ? udp->OnReadyToReceive() : tcp->OnReadyToReceive();
- }
- void NetworkSocketSOCKS5Proxy::SendConnectionCommand(){
- unsigned char buf[1024];
- if(protocol==PROTO_TCP){
- BufferOutputStream out(buf, sizeof(buf));
- out.WriteByte(5); // VER
- out.WriteByte(1); // CMD (CONNECT)
- out.WriteByte(0); // RSV
- const IPv4Address* v4=dynamic_cast<const IPv4Address*>(connectedAddress);
- const IPv6Address* v6=dynamic_cast<const IPv6Address*>(connectedAddress);
- if(v4){
- out.WriteByte(1); // ATYP (IPv4)
- out.WriteInt32(v4->GetAddress());
- }else if(v6){
- out.WriteByte(4); // ATYP (IPv6)
- out.WriteBytes((unsigned char*)v6->GetAddress(), 16);
- }else{
- LOGW("socks5: unknown address type");
- failed=true;
- return;
- }
- out.WriteInt16(htons(connectedPort)); // DST.PORT
- tcp->Send(buf, out.GetLength());
- state=ConnectionState::WaitingForCommandResult;
- }else if(protocol==PROTO_UDP){
- LOGV("Sending udp associate");
- BufferOutputStream out(buf, sizeof(buf));
- out.WriteByte(5); // VER
- out.WriteByte(3); // CMD (UDP ASSOCIATE)
- out.WriteByte(0); // RSV
- out.WriteByte(1); // ATYP (IPv4)
- out.WriteInt32(0); // DST.ADDR
- out.WriteInt16(0); // DST.PORT
- tcp->Send(buf, out.GetLength());
- state=ConnectionState::WaitingForCommandResult;
- }
- }
- bool NetworkSocketSOCKS5Proxy::NeedSelectForSending(){
- return state==ConnectionState::Initial || state==ConnectionState::Connected;
- }
|