prife / hdc

fork from https://gitee.com/openharmony/developtools_hdc
Apache License 2.0
0 stars 0 forks source link

hdc client-server协议分析 #1

Open prife opened 5 months ago

prife commented 5 months ago

发送协议

void HdcChannelBase::SendChannel(HChannel hChannel, uint8_t *bufPtr, const int size)
{
    StartTraceScope("HdcChannelBase::SendChannel");
    uv_stream_t *sendStream = nullptr;
    int sizeNewBuf = size + DWORD_SERIALIZE_SIZE;
    auto data = new uint8_t[sizeNewBuf]();
    if (!data) {
        return;
    }
    *reinterpret_cast<uint32_t *>(data) = htonl(size);  // big endian  // 这里先发送大端
    if (memcpy_s(data + DWORD_SERIALIZE_SIZE, sizeNewBuf - DWORD_SERIALIZE_SIZE, bufPtr, size)) {
        delete[] data;
        return;
    }
    if (hChannel->hWorkThread == uv_thread_self()) {
        sendStream = (uv_stream_t *)&hChannel->hWorkTCP;
    } else {
        sendStream = (uv_stream_t *)&hChannel->hChildWorkTCP;
    }
    if (!uv_is_closing((const uv_handle_t *)sendStream) && uv_is_writable(sendStream)) {
        ++hChannel->ref;
        Base::SendToStreamEx(sendStream, data, sizeNewBuf, nullptr, (void *)WriteCallback, data);
    } else {
        delete[] data;
    }
}

*reinterpret_cast<uint32_t *>(data) = htonl(size); // big endian // 这里先发送大端,这里以大端的方式,发送了4个自己的长度。

prife commented 5 months ago
image
prife commented 5 months ago

channelID

uint32_t HdcChannelBase::GetChannelPseudoUid()
{
    uint32_t uid = 0;
    do {
        uid = static_cast<uint32_t>(Base::GetRandom());
    } while (AdminChannel(OP_QUERY, uid, nullptr) != nullptr);
    return uid;
}

然后会存到map<uint32_t, HChannel> mapChannel;数据结构中

prife commented 5 months ago

host/Client.cpp

int HdcClient::ReadChannel(HChannel hChannel, uint8_t *buf, const int bytesIO)
{
    if (!hChannel->handshakeOK) {
        return PreHandshake(hChannel, buf);
    }

握手,将channelID更新为远程返回的channelID,同时刷新mapChannel

int HdcClient::PreHandshake(HChannel hChannel, const uint8_t *buf)
{
    ChannelHandShake *hShake = reinterpret_cast<ChannelHandShake *>(const_cast<uint8_t *>(buf));
    if (strncmp(hShake->banner, HANDSHAKE_MESSAGE.c_str(), HANDSHAKE_MESSAGE.size())) {
        hChannel->availTailIndex = 0;
        WRITE_LOG(LOG_DEBUG, "Channel Hello failed");
        return ERR_BUF_CHECK;
    }
    // sync remote session id to local
    uint32_t unOld = hChannel->channelId;
    hChannel->channelId = ntohl(hShake->channelId);
    AdminChannel(OP_UPDATE, unOld, hChannel);

然后client向server回发ChannelHandShake结构,注意version字段不一定发送,根据hdc编译参数控制

    struct ChannelHandShake {
        char banner[12];  // must first index
        union {
            uint32_t channelId;
            char connectKey[MAX_CONNECTKEY_SIZE];
        };
        char version[BUF_SIZE_TINY] = { 0 };
    } __attribute__((packed));

调用链

int HdcClient::ExecuteCommand(const string &commandIn)
  -->    ConnectServerForClient(ip, port);
           --> uv_tcp_connect(conn, (uv_tcp_t *)&channel->hWorkTCP, (const struct sockaddr *)&dest, Connect);

void HdcClient::Connect(uv_connect_t *connection, int status)
{
    HdcClient *thisClass = (HdcClient *)connection->data;
    delete connection;
    HChannel hChannel = reinterpret_cast<HChannel>(thisClass->channel);
    if (status < 0 || uv_is_closing((const uv_handle_t *)&hChannel->hWorkTCP)) {
        WRITE_LOG(LOG_FATAL, "connect failed status:%d", status);
        thisClass->FreeChannel(hChannel->channelId);
        return;
    }
    thisClass->BindLocalStd(hChannel);
    Base::SetTcpOptions((uv_tcp_t *)&hChannel->hWorkTCP);
    uv_read_start((uv_stream_t *)&hChannel->hWorkTCP, AllocCallback, ReadStream);
}

接下在ReadStream中检查是否完成PreHandShake
prife commented 5 months ago

server 协议

image
        execl(path, "hdc", "-m", "-s", listenString, nullptr);
prife commented 5 months ago

启动服务

./build/host/hdc kill &  ./build/host/hdc -m -d t -s 127.0.0.1:8710
./build/host/hdc -t 127.0.0.1:5555 fport tcp:5000 tcp:8080

启动一个端口

[D][2024-05-07 14:44:56.113][2afc6f80][channel.cpp:402] Mallocchannel:2102695180
[D][2024-05-07 14:44:56.119][2afc6f80][server_for_client.cpp:63] AcceptClient uid:2102695180
[D][2024-05-07 14:44:56.126][2afc6f80][server_for_client.cpp:84] Server ver:Ver: 2.0.0aHDC_MSG_HASH
[D][2024-05-07 14:44:56.132][2afc6f80][server_for_client.cpp:784] ServerForClient channel handshake finished
[D][2024-05-07 14:44:56.137][970f2606][server_for_client.cpp:837] ReadChannel command: fport tcp:5000 tcp:8080
[D][2024-05-07 14:44:56.142][970f2606][session.cpp:1335] New HTaskInfo channelId:2102695180 command:2500
[D][2024-05-07 14:44:56.147][970f2606][session.cpp:750] AdminTask add session 3047959635, channelId 2102695180, mapTask size: 1
[D][2024-05-07 14:44:56.151][970f2606][task.cpp:32] HdcTaskBase channelId:2102695180
[D][2024-05-07 14:44:56.155][970f2606][forward.cpp:836] CommandDispatch command:2500 payloadSize:17
[D][2024-05-07 14:44:56.160][970f2606][forward.cpp:836] CommandDispatch command:2502 payloadSize:5
[I][2024-05-07 14:44:56.166][970f2606][server.cpp:555] CMD_KERNEL_ECHO size:21 channelId:2102695180
[W][2024-05-07 14:44:56.641][2afc6f80][host_usb.cpp:250] get active config des fail, errno is 0.