QUIC代理客户端代码阅读

编程入门 行业动态 更新时间:2024-10-27 12:36:52

QUIC代理<a href=https://www.elefans.com/category/jswz/34/1771403.html style=客户端代码阅读"/>

QUIC代理客户端代码阅读

1、首先是从配置问价中读取配置信息,读取配置文件的代码如下,可留着备用

//从配置文件中读取数据  配置文件所在的位置  /src/client_config.ini
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,client_ini_file,"client_config.ini","Path to the certificate chain.");
std::string ini=GetQuicFlag(FLAGS_client_ini_file);ini_t *config= ini_load(ini.c_str());if(!config){return 0;}//拿到了目的地址、以及连接的数目std::string dest(ini_get(config, "client", "dest"));std::string tunip(ini_get(config, "client", "tunip"));std::string nic(ini_get(config, "client", "nic"));//多少个连接数   std::unique_ptr<ProxyClientBackend> backend(new ProxyClientBackend(dest));    int num = std::stoi(nic);for(int i=0;i<num;i++){//分别将两个连接的IP也给读了出来std::string key="nicip"+std::to_string(i+1);//读到client_config.ini配置文件中的ip地址std::string value(ini_get(config, "client", key.c_str()));backend->LocalIpAddress(value);}std::cout<<dest<<" "<<tunip<<std::endl;ini_free(config);//使用结束还需要释放

2、根据传入的目的地址创建一个ProxyClientBackend对象

 std::unique_ptr<ProxyClientBackend> backend(new ProxyClientBackend(dest)); 

接着又创建了一个ProxyClient对象,因为ProxyClientBackend继承了MyQuicBackend类,所以可以用这种方法来创建

std::unique_ptr<ProxyClient> client(new ProxyClient(backend.get()));
ProxyClient::ProxyClient(MyQuicBackend *backend){backend_=backend;epoll_server_.reset(new QuicEpollServer());//创建了一个epoll服务器alarm_factory_.reset(new QuicEpollAlarmFactory(epoll_server_.get()));clock_.reset(new QuicEpollClock(epoll_server_.get()));//创建一个factory对象factory_.reset(new MyProxyClientFactory(this,backend_));

看一下这个MyQuicContext,里面就是包含了一些基本的信息

class MyQuicContext{
public:virtual ~MyQuicContext(){}virtual QuicClock *clock()=0;virtual QuicAlarmFactory* alarm_factory() =0;virtual QuicEpollServer* epoll_server() =0;virtual base::PlatformThreadId context_id() =0;template <class Closure,typename std::enable_if<!std::is_convertible<Closure,std::unique_ptr<QueuedTask>>::value>::type* = nullptr>void PostTask(Closure&& closure){PostInnerTask(NewClosure(std::forward<Closure>(closure)));} 
protected:virtual void PostInnerTask(std::unique_ptr<QueuedTask> task)=0;
};

2、客户端程序中是需要配置默认路由,到达目的地数据引入大tun设备上面去

int ret=configure_route(ROUTE_ADD,tun_name.c_str(),dest.c_str(),32);
int configure_route(RouteCommand add,const char* dev,const char *dst,int masklen){char cmd[kRouteBufferSize]; uint32_t ip;::inet_pton(AF_INET,dst,(void*)&ip);ip=ntohl(ip); uint32_t mask = 0xffffffff << (32-masklen);  ip=(ip)&mask;ip=htonl(ip);char ip4[20]={0};::inet_ntop(AF_INET, (void *)&ip, ip4, 16);   QUIC_LOG(INFO)<<ip4;if(add==ROUTE_ADD){//设置到达目的的ip走tun设备sprintf(cmd, "ip route add %s/%d dev %s", ip4, masklen, dev);}else{//完事儿还需要删除这条路由规则sprintf(cmd, "ip route del %s/%d dev %s", ip4, masklen, dev);}int res=system(cmd);if ( res< 0){QUIC_LOG(ERROR)<<"route add error";return -1;}return 0;
}

3、接下来就进入到handleEvent程序

while (m_running){client->HandleEvent();}
//
void ProxyClient::HandleEvent(){if(context_id_==base::kInvalidThreadId){context_id_=base::PlatformThread::CurrentId();}HandleInactiveClient();//删除失效的  处理非失效的std::deque <RequestClientConfig> requests;{//加锁、交换链QuicWriterMutexLock lock(&request_mutex_);requests.swap(requests_);}      if(requests.size()>0){        while(!requests.empty()){auto it=requests.begin();QuicIpAddress local=(*it).local;size_t length=(*it).length;const char *data=(*it).join_indication;requests.erase(it);//拿到一些基本信息后创建一个clientMyQuicToyClient *client=new MyQuicToyClient(factory_.get());client->set_notifier(this);//绑定地址client->set_bind_to_address(local);//创建一个字符串std::string indication(data,length);if(length>0){                                    client->JoinIndication(indication);}//初始化和建立连接的过程                int ret=client->InitialAndConnect();if(ret!=0){delete client;}else{active_clients_.insert(client);}}}std::deque<std::unique_ptr<QueuedTask>> tasks;{QuicWriterMutexLock lock(&task_mutex_);tasks.swap(queued_tasks_);}while(!tasks.empty()){tasks.front()->Run();tasks.pop_front();}         epoll_server_->WaitForEventsAndExecuteCallbacks();        
}

//看看这个建立连接的过程

int MyQuicToyClient::InitialAndConnect() {std::string host = GetQuicFlag(FLAGS_host);if (host.empty()) {return 1;}int port = GetQuicFlag(FLAGS_port);if (port == 0) {return 1;}quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();std::string quic_version_string = GetQuicFlag(FLAGS_quic_version);if (GetQuicFlag(FLAGS_quic_ietf_draft)) {quic::QuicVersionInitializeSupportForIetfDraft();versions = {};for (const ParsedQuicVersion& version : AllSupportedVersions()) {if (version.HasIetfQuicFrames() &&version.handshake_protocol == quic::PROTOCOL_TLS1_3) {versions.push_back(version);}}quic::QuicEnableVersion(versions[0]);} else if (!quic_version_string.empty()) {quic::ParsedQuicVersion parsed_quic_version =quic::ParseQuicVersionString(quic_version_string);if (parsed_quic_version.transport_version ==quic::QUIC_VERSION_UNSUPPORTED) {return 1;}versions = {parsed_quic_version};quic::QuicEnableVersion(parsed_quic_version);}if (GetQuicFlag(FLAGS_force_version_negotiation)) {versions.insert(versions.begin(),quic::QuicVersionReservedForNegotiation());}
//版本协商 std::unique_ptr<quic::ProofVerifier> proof_verifier=std::make_unique<FakeProofVerifier>();//校验证书 包含这一些版本协商、证书等信息//创建一个客户端,并尝试着连接// Build the client, and try to connect.client_= client_factory_->CreateClient(this,host, port, versions, std::move(proof_verifier));if (client_ == nullptr){std::cerr << "Failed to create client." << std::endl;return 1;}client_->set_requester(this);//绑定地址if(bind_to_address_.IsInitialized()){std::cout<<"bind addr "<<bind_to_address_<<std::endl;client_->set_bind_to_address(bind_to_address_); }//协商MTUint32_t initial_mtu = GetQuicFlag(FLAGS_initial_mtu);client_->set_initial_max_packet_length(initial_mtu != 0 ? initial_mtu : quic::kDefaultMaxPacketSize);if (!client_->Initialize()) {std::cerr << "Failed to initialize client." << std::endl;return 1;}/**
bool QuicClientBase::Initialize() {num_sent_client_hellos_ = 0;connection_error_ = QUIC_NO_ERROR;connected_or_attempting_connect_ = false;// If an initial flow control window has not explicitly been set, then use the// same values that Chrome uses.const uint32_t kSessionMaxRecvWindowSize = 15 * 1024 * 1024;  // 15 MBconst uint32_t kStreamMaxRecvWindowSize = 6 * 1024 * 1024;    //  6 MBif (config()->GetInitialStreamFlowControlWindowToSend() ==kDefaultFlowControlSendWindow) {config()->SetInitialStreamFlowControlWindowToSend(kStreamMaxRecvWindowSize);}if (config()->GetInitialSessionFlowControlWindowToSend() ==kDefaultFlowControlSendWindow) {config()->SetInitialSessionFlowControlWindowToSend(kSessionMaxRecvWindowSize);}
//这里面出现了创建UDP绑定if (!network_helper_->CreateUDPSocketAndBind(server_address_,bind_to_address_, local_port_)) {return false;}initialized_ = true;return true;
}
*///cofigure epoll, 50ms unwanted.//client_->epoll_server()->set_timeout_in_us(0);/*if (!client_->Connect()) {quic::QuicErrorCode error = client_->session()->error();if (error == quic::QUIC_INVALID_VERSION) {std::cerr << "Server talks QUIC, but none of the versions supported by "<< "this client: " << ParsedQuicVersionVectorToString(versions)<< std::endl;// 0: No error.// 20: Failed to connect due to QUIC_INVALID_VERSION.return GetQuicFlag(FLAGS_version_mismatch_ok) ? 0 : 20;}std::cerr << "Failed to connect to " << host << ":" << port<< ". Error: " << quic::QuicErrorCodeToString(error) << std::endl;return 1;}*/client_->AsynConnect();//std::cerr << "Connected to " << host << ":" << port << std::endl;return 0;
}

看看client的建立过程

//包含着对端的IP、端口、版本等一一些信息
client_= client_factory_->CreateClient(this,host, port, versions, std::move(proof_verifier));
std::unique_ptr<MyQuicClient> MyQuicClientFactory::CreateClient(QuicSession::Visitor *owner,std::string host_for_lookup,uint16_t port,ParsedQuicVersionVector versions,std::unique_ptr<ProofVerifier> verifier) {QuicSocketAddress addr =tools::LookupAddress(host_for_lookup, quiche::QuicheStrCat(port));if (!addr.IsInitialized()) {QUIC_LOG(ERROR) << "Unable to resolve address: " << host_for_lookup;return nullptr;}QuicServerId server_id(host_for_lookup, port, false);return std::make_unique<MyQuicClient>(owner,addr, server_id, versions, context_,backend_,std::move(verifier));
}
//至此、客户端算是建立成功

//看看QUIC底层的UDP创建和绑定的过程

CreateUDPSocketAndBind(server_address_,bind_to_address_, local_port_)bool QuicClientEpollNetworkHelper::CreateUDPSocketAndBind(QuicSocketAddress server_address,QuicIpAddress bind_to_address,int bind_to_port) {epoll_server_->set_timeout_in_us(50 * 1000);
//创建UDPsocketint fd = CreateUDPSocket(server_address, &overflow_supported_);if (fd < 0) {return false;}QuicSocketAddress client_address;if (bind_to_address.IsInitialized()) {client_address = QuicSocketAddress(bind_to_address, client_->local_port());} else if (server_address.host().address_family() == IpAddressFamily::IP_V4) {client_address = QuicSocketAddress(QuicIpAddress::Any4(), bind_to_port);} else {client_address = QuicSocketAddress(QuicIpAddress::Any6(), bind_to_port);}sockaddr_storage addr = client_address.generic_address();int rc = bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));if (rc < 0) {QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno)<< " bind_to_address:" << bind_to_address<< ", bind_to_port:" << bind_to_port<< ", client_address:" << client_address;return false;}if (client_address.FromSocket(fd) != 0) {QUIC_LOG(ERROR) << "Unable to get self address.  Error: "<< strerror(errno);}
epoll服务器还注册了这个fdfd_address_map_[fd] = client_address;epoll_server_->RegisterFD(fd, this, kEpollFlags);return true;
}

最后剩下这个 client_->AsynConnect();连接

  client_->AsynConnect()bool MyQuicClient::AsynConnect(){if (!connected()){//判断是否连接上StartConnect();}if (session() == nullptr) {QUIC_BUG << "Missing session after Connect";return false;}//返回连接层的connectreturn session()->connection()->connected();    
}

更多推荐

QUIC代理客户端代码阅读

本文发布于:2024-02-12 22:06:58,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1689588.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:客户端   代码   QUIC

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!