#include "udp_client.h" #include "conn_map.h" #include "utils.h" #include "hv/UdpClient.h" #include "bolt/datagram.h" #include "spdlog/spdlog.h" #include std::string get_key(struct sockaddr_in t_addr, struct sockaddr_in u_addr) { std::ostringstream string_stream; string_stream << t_addr.sin_addr.s_addr << t_addr.sin_port; string_stream << u_addr.sin_addr.s_addr << u_addr.sin_port; return string_stream.str(); } bool UdpServerBoltProxy::analyzeData(struct sockaddr_in t_addr, struct sockaddr_in u_addr, uint32_t session_id, char *dest, int dest_len, char *extend, int extend_len) { auto key = get_key(t_addr, u_addr); auto client = _map.get(key); if (!client) { hloop_t *loop = (hloop_t *)hevent_userdata(io); std::unique_ptr new_client = std::make_unique(t_addr, u_addr, session_id); if (!new_client->init(loop)) { return false; } client = new_client.get(); _map.add(key, new_client); } // if (getConfig().ept_type == CRYPT_TYPE::XOR) // { // xor_::crypt((char *)dest, dest_len, getConfig().ept_key); // } hio_write(client->getClientIO(), dest, dest_len); return true; } int UdpServerBoltProxy::sendData(struct sockaddr_in t_addr, struct sockaddr_in u_addr, void *data, int data_len) { // if (getConfig().ept_type == CRYPT_TYPE::XOR) // { // xor_::crypt((char *)data, data_len, getConfig().ept_key); // } PACK_TUNNEL_DATA(boltdata, boltdata_len, BOLT_VERSION, BOLT_RESERVE, BOLT_PAYLOAD_TYPE_UDP, t_addr.sin_addr.s_addr, t_addr.sin_port, u_addr.sin_addr.s_addr, u_addr.sin_port, config.session_id, 0, 0, data, data_len) return hio_write(io, boltdata, boltdata_len); } void UdpServerBoltProxy::closeClient(struct sockaddr_in &t_addr, struct sockaddr_in &u_addr) { auto key = get_key(t_addr, u_addr); _map.remove(key); } void UdpServerBoltProxy::recycle() { for (auto it = _map.begin(); it != _map.end(); ++it) { it->second->close(); } _map.clear(); } bool UdpClientProxy::init(hloop_t *loop) { spdlog::info("UdpClientProxy::init {}:{}<==>{}:{}", inet_ntoa(u_addr.sin_addr), ntohs(u_addr.sin_port), inet_ntoa(t_addr.sin_addr), ntohs(t_addr.sin_port)); cli_io = hloop_create_udp_client(loop, inet_ntoa(t_addr.sin_addr), ntohs(t_addr.sin_port)); if (cli_io == nullptr) { return false; } hevent_set_userdata(cli_io, this); hio_setcb_read(cli_io, [](hio_t *io, void *buf, int readbytes) { UdpClientProxy *cli = (UdpClientProxy *)hevent_userdata(io); if (cli) { cli->onRecv(buf, readbytes); } }); hio_setcb_write(cli_io, [](hio_t *io, const void *buf, int writebytes) { UdpClientProxy* cli = (UdpClientProxy*)hevent_userdata(io); if (cli) { cli->onWrited(buf, writebytes); } }); hio_setcb_close(cli_io, [](hio_t *io) { UdpClientProxy* cli = (UdpClientProxy*)hevent_userdata(io); if (cli) { cli->onClosed(); } }); hio_read(cli_io); timer = htimer_add(loop, [](htimer_t *timer) { UdpClientProxy* cli = (UdpClientProxy*)hevent_userdata(timer); if (cli) { long timeout = cli->isDns() ? DNS_TIMEOUT : TIMEOUT_TIMEUNIT; long time = currentTimeMillis() - cli->ts; if (time > 0 && time < timeout) { long remaining = (timeout - time); if (remaining < TIMEOUT_TIMEUNIT) { htimer_reset(timer, remaining); } else { htimer_reset(timer, TIMEOUT_TIMEUNIT); } } else { cli->close(); } } }, TIMEOUT_TIMEUNIT); hevent_set_userdata(timer, this); return true; } void UdpClientProxy::close() { if (timer) { htimer_del(timer); timer = nullptr; } if (cli_io) { hio_close(cli_io); cli_io = nullptr; } } void UdpClientProxy::onRecv(void *buf, int readbytes) { spdlog::info("UdpClientProxy::onRecv {}:{}<==>{}:{} <<< size:{} : data: {}", inet_ntoa(u_addr.sin_addr), ntohs(u_addr.sin_port), inet_ntoa(t_addr.sin_addr), ntohs(t_addr.sin_port), readbytes, std::string((char *)buf, readbytes).c_str()); auto serverProxy = UdpConnMap::getInstance().get(session_id); if (!serverProxy) { return; } ts = currentTimeMillis(); serverProxy->sendData(t_addr, u_addr, buf, readbytes); } void UdpClientProxy::onWrited(const void *buf, int writebytes) { spdlog::info("UdpClientProxy::onWrited {}:{}<==>{}:{} >>> size:{} : data: {}", inet_ntoa(u_addr.sin_addr), ntohs(u_addr.sin_port), inet_ntoa(t_addr.sin_addr), ntohs(t_addr.sin_port), writebytes, std::string((char *)buf, writebytes).c_str()); } void UdpClientProxy::onClosed() { spdlog::info("UdpClientProxy::onClosed {}:{}<==>{}:{}", inet_ntoa(u_addr.sin_addr), ntohs(u_addr.sin_port), inet_ntoa(t_addr.sin_addr), ntohs(t_addr.sin_port)); auto key = get_key(t_addr, u_addr); auto serverProxy = UdpConnMap::getInstance().get(session_id); if (!serverProxy) { return; } serverProxy->closeClient(t_addr, u_addr); }