ProxyServerTcp / src /tcp_client.cpp
xukc
[fix]udp runtime error
99dc157
#include "tcp_client.h"
#include "bolt/datagram.h"
#include "tcp_client_map.h"
#include "utils.h"
#include "spdlog/spdlog.h"
#include <string>
#include <time.h>
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();
}