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);
            //拿到一些基本信息后创建一个client
            MyQuicToyClient *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_); 
  }
  //协商MTU
  int32_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 MB
  const uint32_t kStreamMaxRecvWindowSize = 6 * 1024 * 1024;    //  6 MB
  if (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);
//创建UDPsocket
  int 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服务器还注册了这个fd
  fd_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;
  }
  //返回连接层的connect
  return session()->connection()->connected();    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值