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(); | |
} |