Spaces:
Paused
Paused
| void TcpClientBolt::onConnection(const hv::SocketChannelPtr &channel) | |
| { | |
| char buff[2]; | |
| buff[0] = BOLT_CHANNEL_CMD_TCP_HANDSHAKE_RESPONSE; | |
| buff[1] = BOLT_TCP_HANDSHAKE_SUCESS; | |
| int len = sizeof(buff); | |
| PACK_TUNNEL_DATA(boltdata, boltdata_len, BOLT_VERSION, BOLT_RESERVE, BOLT_PAYLOAD_TYPE_CMD, t_addr.sin_addr.s_addr, t_addr.sin_port, u_addr.sin_addr.s_addr, u_addr.sin_port, session_id, 0, 0, buff, len); | |
| hio_write(io, boltdata, boltdata_len); | |
| spdlog::info("BOLT_CHANNEL_CMD_TCP_HANDSHAKE_REQUEST: t_addr={}:{}, u_addr={}:{} ==> connect succ", inet_ntoa(t_addr.sin_addr), htons(t_addr.sin_port), inet_ntoa(u_addr.sin_addr), htons(u_addr.sin_port)); | |
| } | |
| void TcpClientBolt::onRecv(const hv::SocketChannelPtr &channel, hv::Buffer *buf) | |
| { | |
| auto config = TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().get(session_id); | |
| if (config) | |
| { | |
| if (config->encrypt) | |
| { | |
| switch (config->ept_type) | |
| { | |
| case CRYPT_TYPE::XOR: | |
| xor_::crypt((char *)buf->data(), buf->size(), config->ept_key); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| hio_write(io, buf->data(), buf->size()); | |
| } | |
| spdlog::info("t_addr={}:{}, u_addr={}:{} onRecv==> {}={}", inet_ntoa(t_addr.sin_addr), htons(t_addr.sin_port), inet_ntoa(u_addr.sin_addr), htons(u_addr.sin_port), buf->len, (const char*)buf->data()); | |
| } | |
| void TcpClientBolt::onWrited(const hv::SocketChannelPtr &channel, hv::Buffer *buf) | |
| { | |
| if (channel.get()->isWriteComplete()) | |
| { | |
| spdlog::info("t_addr={}:{}, u_addr={}:{} isWriteComplete==> {}={}", inet_ntoa(t_addr.sin_addr), htons(t_addr.sin_port), inet_ntoa(u_addr.sin_addr), htons(u_addr.sin_port), buf->len, (const char*)buf->data()); | |
| } | |
| } | |
| void TcpClientBolt::onDisConnection(const hv::SocketChannelPtr &channel) | |
| { | |
| if (is_bolt_server) | |
| { | |
| TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().remove(session_id); | |
| } | |
| hio_close(io); | |
| } | |
| bool TcpClientBolt::handShake(void *buf, int readbytes) | |
| { | |
| if (readbytes > 0) | |
| { | |
| UNPACK_TUNNEL_DATA(dest, dest_len, ver, res, type, t_ip, t_port, u_ip, u_port, session_id, extend, extend_len, buf, readbytes) | |
| if (ver == BOLT_VERSION && res == BOLT_RESERVE) | |
| { | |
| if (type == BOLT_PAYLOAD_TYPE_CMD) | |
| { | |
| if (dest_len == 1 && dest[0] == BOLT_CHANNEL_CMD_TCP_HANDSHAKE_REQUEST) | |
| { | |
| this->t_addr.sin_family = AF_INET; | |
| this->t_addr.sin_addr.s_addr = t_ip; | |
| this->t_addr.sin_port = t_port; | |
| this->u_addr.sin_family = AF_INET; | |
| this->u_addr.sin_addr.s_addr = u_ip; | |
| this->u_addr.sin_port = u_port; | |
| this->session_id = session_id; | |
| this->config = TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().get(session_id); | |
| if (!this->config) | |
| { | |
| char buff[1] = {BOLT_CHANNEL_CMD_INVALID_RESPONSE}; | |
| int len = sizeof(buff); | |
| PACK_TUNNEL_DATA(boltdata, boltdata_len, BOLT_VERSION, BOLT_RESERVE, BOLT_PAYLOAD_TYPE_CMD, t_addr.sin_addr.s_addr, t_addr.sin_port, u_addr.sin_addr.s_addr, u_addr.sin_port, session_id, 0, 0, buff, len); | |
| hio_write(io, buff, len); | |
| hio_close_async(io); | |
| return false; | |
| } | |
| if (!this->connect((struct sockaddr *)&t_addr)) | |
| { | |
| spdlog::info("[TCP]BOLT_CHANNEL_CMD_TCP_HANDSHAKE_REQUEST: t_addr={}:{}, u_addr={}:{} ==> connect fail", inet_ntoa(t_addr.sin_addr), htons(t_addr.sin_port), inet_ntoa(u_addr.sin_addr), htons(u_addr.sin_port)); | |
| char buff[2]; | |
| buff[0] = BOLT_CHANNEL_CMD_TCP_HANDSHAKE_RESPONSE; | |
| buff[1] = BOLT_TCP_HANDSHAKE_FAIL_TIMEOUT; | |
| int len = sizeof(buff); | |
| PACK_TUNNEL_DATA(boltdata, boltdata_len, BOLT_VERSION, BOLT_RESERVE, BOLT_PAYLOAD_TYPE_CMD, t_addr.sin_addr.s_addr, t_addr.sin_port, u_addr.sin_addr.s_addr, u_addr.sin_port, session_id, 0, 0, buff, len); | |
| hio_write(io, buff, len); | |
| hio_close_async(io); | |
| return false; | |
| } | |
| return true; | |
| } | |
| else if (dest_len == 73 && dest[0] == BOLT_CHANNEL_CMD_BIND_REQUEST) | |
| { | |
| UNPACK_BIND_DATA(command, request_id, signal_id, session_id, data_st, dest, dest_len) | |
| this->session_id = session_id; | |
| tcpBoltConfig config; | |
| config.request_id = request_id; | |
| config.session_id = session_id; | |
| config.data_st = data_st; | |
| config.signal_id = signal_id; | |
| if (extend_len >= 5) | |
| { | |
| if (strcmp(extend, "ept=1") == 0) | |
| { | |
| config.encrypt = true; | |
| } | |
| } | |
| config.ept_type = config.encrypt ? CRYPT_TYPE::XOR : CRYPT_TYPE::NONE; | |
| config.ept_key = config.encrypt ? generateRandomKey() : 0; | |
| spdlog::info("[TCP]BOLT_CHANNEL_CMD_BIND_REQUEST: requestId:{}, session_id:{}, encrypt:{}", request_id, session_id, config.encrypt); | |
| GENERATE_DECRYPT_KEY(extend_response, extend_response_len, config.ept_type, config.ept_key) | |
| uint32_t result = BOLT_BIND_RESPONSE_CODE_SUCESS; | |
| PACK_BIND_RESPONSE_DATA(bind_response, bind_response_len, BOLT_CHANNEL_CMD_BIND_RESPONSE, request_id, session_id, result) | |
| PACK_TUNNEL_DATA(response, response_len, BOLT_VERSION, BOLT_RESERVE, BOLT_PAYLOAD_TYPE_CMD, 0, 0, 0, 0, session_id, extend_response, extend_response_len, bind_response, bind_response_len) | |
| hio_write(io, response, response_len); | |
| TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().add(session_id, config); | |
| is_bolt_server = true; | |
| } | |
| else if (dest_len == 9 && dest[0] == BOLT_CHANNEL_CMD_UNBIND_REQUEST) | |
| { | |
| UNPACK_UNBIND_DATA(command, session_id, code, dest, dest_len) | |
| TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().remove(session_id); | |
| this->close(); | |
| hio_close_async(io); | |
| spdlog::info("[TCP]BOLT_CHANNEL_CMD_UNBIND_REQUEST: requestId:{}, session_id:{} t_addr={}:{}, u_addr={}:{}", config->request_id, config->session_id, inet_ntoa(t_addr.sin_addr), htons(t_addr.sin_port), inet_ntoa(u_addr.sin_addr), htons(u_addr.sin_port)); | |
| } | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| bool TcpClientBolt::connect(struct sockaddr *addr) | |
| { | |
| int connfd = cli.createsocket(addr); | |
| if (connfd < 0) | |
| { | |
| return false; | |
| } | |
| cli.onConnection = [this](const hv::SocketChannelPtr &channel) | |
| { | |
| std::string peeraddr = channel->peeraddr(); | |
| if (channel->isConnected()) | |
| { | |
| spdlog::info("connected to {}! connfd={}\n", peeraddr.c_str(), channel->fd()); | |
| onConnection(channel); | |
| } | |
| else | |
| { | |
| spdlog::info("disconnected to {}! connfd={}\n", peeraddr.c_str(), channel->fd()); | |
| onDisConnection(channel); | |
| } | |
| }; | |
| cli.onMessage = [this](const hv::SocketChannelPtr &channel, hv::Buffer *buf) | |
| { | |
| spdlog::info("<<< len:{} : {}", (int)buf->size(), (char *)buf->data()); | |
| onRecv(channel, buf); | |
| }; | |
| cli.onWriteComplete = [this](const hv::SocketChannelPtr &channel, hv::Buffer *buf) | |
| { | |
| spdlog::info(">>> len:{} : {}", (int)buf->size(), (char *)buf->data()); | |
| onWrited(channel, buf); | |
| }; | |
| cli.start(); | |
| return true; | |
| } | |
| int TcpClientBolt::send(char *data, int size) | |
| { | |
| if (cli.isConnected()) | |
| { | |
| auto config = TcpClientMap<uint32_t, tcpBoltConfig>::getInstance().get(session_id); | |
| if (config) | |
| { | |
| if (config->encrypt) | |
| { | |
| switch (config->ept_type) | |
| { | |
| case CRYPT_TYPE::XOR: | |
| xor_::crypt(data, size, config->ept_key); | |
| break; | |
| default: | |
| break; | |
| } | |
| } | |
| } | |
| return cli.send(data, size); | |
| } | |
| else | |
| { | |
| return -1; | |
| } | |
| } | |
| void TcpClientBolt::close() | |
| { | |
| spdlog::info("TcpClientBolt::close()\n"); | |
| cli.stop(); | |
| } |