123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /**
- * Tencent is pleased to support the open source community by making Tars available.
- *
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
- *
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * https://opensource.org/licenses/BSD-3-Clause
- *
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License.
- */
- #include "util/tc_proxy_info.h"
- #include "util/tc_http.h"
- #include "util/tc_base64.h"
- namespace tars
- {
- shared_ptr<TC_ProxyInfo> TC_ProxyInfo::createProxyInfo(const TC_ProxyInfo::ProxyBaseInfo &baseInfo)
- {
- shared_ptr<TC_ProxyInfo> proxyInfo;
- switch(baseInfo.type)
- {
- case eProxy_Type_Sock4:
- proxyInfo.reset(new TC_ProxySock4(baseInfo.ep));
- break;
- case eProxy_Type_Sock5:
- proxyInfo.reset(new TC_ProxySock5(baseInfo.ep, baseInfo.user, baseInfo.pass));
- break;
- case eProxy_Type_Http:
- proxyInfo.reset(new TC_ProxyHttp(baseInfo.ep, baseInfo.user, baseInfo.pass));
- break;
- }
- return proxyInfo;
- }
- void TC_ProxyInfo::onDisconnect()
- {
- setProxyStage(eProxy_Stage_DisConn);
- }
- void TC_ProxyInfo::onConnSuccess()
- {
- setProxyStage(eProxy_Stage_Connected);
- }
- void TC_ProxyInfo::setProxyStage(TC_ProxyInfo::EMProxyStageType proxyStage)
- {
- if (_stage == proxyStage) {
- return;
- }
- _stage = proxyStage;
- }
- ////////////////////////////////////////////////////////////////////////
- bool TC_ProxySock4::sendProxyPacket(vector<char> & buff, const TC_Endpoint & dst)
- {
- //first handshake
- buff.push_back(kProxy_Sock4_Req1_VN);
- buff.push_back(kProxy_Sock4_Req1_CD);
- unsigned short nPort = htons(dst.getPort());
- buff.insert(buff.end(), (const char *)&nPort, (const char *)&nPort + sizeof(nPort));
- struct in_addr addr;
- TC_Socket::parseAddr(dst.getHost(), addr);
- int32_t tmpLong = addr.s_addr;
- buff.insert(buff.end(), (const char *)&tmpLong, (const char *)&tmpLong + sizeof(tmpLong));
- buff.push_back('a');
- buff.push_back(0);
- return true;
- }
- bool TC_ProxySock4::recvProxyPacket(const char *buff, size_t length)
- {
- switch (_stage) {
- case eProxy_Stage_Establish: {
- //send first handshake
- if (sizeof(struct sock4ans1) != length) {
- _errMsg = "proxy disconnected: Establish protocol length error";
- onDisconnect();
- return false;
- }
- struct sock4ans1 *pSockAns1 = (struct sock4ans1 *) buff;
- if (pSockAns1->VN != kProxy_Sock4_Ans1_VN || pSockAns1->CD != kProxy_Sock4_Ans1_CD) {
- _errMsg = "proxy disconnected: Establish protocol version error";
- onDisconnect();
- return false;
- }
- //success
- onConnSuccess();
- return true;
- }
- default: {
- assert(false);
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- bool TC_ProxySock5::sendProxyPacket(vector<char> & vBuffer, const TC_Endpoint & dst)
- {
- switch (_stage) {
- case eProxy_Stage_DisConn:
- case eProxy_Stage_Establish: {
- //first handshake
- vBuffer.push_back(kProxy_Sock5_Req1_Ver);
- vBuffer.push_back(kProxy_Sock5_Req1_nMethods);
- vBuffer.push_back(kProxy_Sock5_Req1_nMethods0);
- vBuffer.push_back(kProxy_Sock5_Req1_nMethods1);
- return true;
- }
- case eProxy_Stage_ACK1: {
- //second handshake user pwd
- char nUserLength = (char) _user.size();
- char nPwdLength = (char) _pass.size();
- vBuffer.push_back(1);
- vBuffer.push_back(nUserLength);
- vBuffer.insert(vBuffer.end(), _user.begin(), _user.end());
- vBuffer.push_back(nPwdLength);
- vBuffer.insert(vBuffer.end(), _pass.begin(), _pass.end());
- return true;
- }
- case eProxy_Stage_ACK2: {
- //third handshake
- vBuffer.push_back(kProxy_Sock5_Req3_Ver);
- vBuffer.push_back(kProxy_Sock5_Req3_Cmd);
- vBuffer.push_back(kProxy_Sock5_Req3_Rsv);
- if(dst.isIPv6())
- {
- vBuffer.push_back(kProxy_Sock5_Req3_AtypIpv6);
- }
- else
- {
- vBuffer.push_back(kProxy_Sock5_Req3_AtypIpv4);
- }
- struct in_addr addr;
- TC_Socket::parseAddr(dst.getHost(), addr);
- int32_t tmpLong = addr.s_addr;
- vBuffer.insert(vBuffer.end(), (const char *)&tmpLong, (const char *)&tmpLong + sizeof(tmpLong));
- unsigned short nPort = htons(dst.getPort());
- vBuffer.insert(vBuffer.end(), (const char *)&nPort, (const char *)&nPort + sizeof(nPort));
- return true;
- }
- default: {
- assert(false);
- }
- }
- return false;
- }
- bool TC_ProxySock5::recvProxyPacket(const char *buff, size_t length)
- {
- switch (_stage) {
- case eProxy_Stage_Establish: {
- //send first handshake
- if (sizeof(struct sock5ans1) != length) {
- _errMsg = "proxy disconnected: Establish protocol length error";
- onDisconnect();
- return false;
- }
- struct sock5ans1 *pSock5Ans1 = (struct sock5ans1 *) buff;
- if (pSock5Ans1->Ver != kProxy_Sock5_Ans1_Ver || (pSock5Ans1->Method != kProxy_Sock5_Ans1_Method_Anonymous && pSock5Ans1->Method != kProxy_Sock5_Ans1_Method_User))
- {
- _errMsg = "proxy disconnected: Establish protocol version error";
- onDisconnect();
- return false;
- }
- //need user
- if (pSock5Ans1->Method == kProxy_Sock5_Ans1_Method_User) {
- setProxyStage(eProxy_Stage_ACK1);
- return true;
- }
- else {
- //Anonymous
- setProxyStage(eProxy_Stage_ACK2);
- return true;
- }
- }
- case eProxy_Stage_ACK1: {
- //send second handshake
- if (sizeof(struct authans) != length) {
- _errMsg = "proxy disconnected: ACK1 protocol length error";
- onDisconnect();
- return false;
- }
- struct authans *pSock5Anthans = (struct authans *) buff;
- if (pSock5Anthans->Ver != kProxy_Sock5_Anthans_Ver || pSock5Anthans->Status != kProxy_Sock5_Anthans_Status) {
- _errMsg = "proxy disconnected: ACK1 protocol version error";
- onDisconnect();
- return false;
- }
- setProxyStage(eProxy_Stage_ACK2);
- return true;
- }
- case eProxy_Stage_ACK2: {
- if (sizeof(struct sock5ans2) != length) {
- _errMsg = "proxy disconnected: ACK2 protocol length error";
- onDisconnect();
- return false;
- }
- struct sock5ans2 *pSock5An2 = (struct sock5ans2 *) buff;
- if (pSock5An2->Ver != kProxy_Sock5_Ans2_Ver || pSock5An2->Rep != kProxy_Sock5_Ans2_Rep) {
- _errMsg = "proxy disconnected: ACK2 protocol version error";
- onDisconnect();
- return false;
- }
- //success
- onConnSuccess();
- return true;
- }
- default: {
- assert(false);
- }
- }
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- bool TC_ProxyHttp::sendProxyPacket(vector<char> & buff, const TC_Endpoint & dst)
- {
- switch (_stage) {
- case eProxy_Stage_Establish: {
- ostringstream oss;
- //first handshake
- std::string strRev;
- if (_user.empty()) {
- oss << "CONNECT " << dst.getHost() << ":" << dst.getPort()
- << " HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\n\r\n";
- strRev = oss.str();
- }
- else {
- oss << "CONNECT " << dst.getHost() << ":" << dst.getPort()
- << " HTTP/1.1\r\nUser-Agent: Mozilla/4.0\r\n";
- oss << "Proxy-Authorization:Basic " << TC_Base64::encode(_user + ":" + _pass) << "\r\n\r\n";
- strRev = oss.str();
- }
- buff.insert(buff.end(), strRev.begin(), strRev.end());
- return true;
- }
- default: {
- assert(false);
- }
- }
- return false;
- }
- bool TC_ProxyHttp::recvProxyPacket(const char *buff, size_t length)
- {
- switch (_stage) {
- case eProxy_Stage_Establish: {
- TC_HttpResponse rsp;
- rsp.decode(buff, length);
- //send first handshake
- if (rsp.getStatus() != 200) {
- _errMsg = "proxy disconnected: " + TC_Common::tostr(rsp.getStatus()) + ", about:" + rsp.getAbout() + " error";
- onDisconnect();
- return false;
- }
- //success
- onConnSuccess();
- return true;
- }
- default: {
- assert(false);
- }
- }
- return false;
- }
- }
|