1 Star 0 Fork 6

nackman/xfrpc

forked from liudengfeng/xfrpc 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
proxy_udp.c 6.80 KB
一键复制 编辑 原始数据 按行查看 历史
staylightblow8 提交于 2023-08-27 19:34 . feat: add udp support
/* vim: set et ts=4 sts=4 sw=4 : */
/********************************************************************\
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation; either version 2 of *
* the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
* Boston, MA 02111-1307, USA gnu@gnu.org *
* *
\********************************************************************/
/** @file proxy_tcp.c
@brief xfrp proxy udp implemented
@author Copyright (C) 2016 Dengfeng Liu <liudf0716@gmail.com>
*/
#include <arpa/inet.h>
#include "debug.h"
#include "uthash.h"
#include "common.h"
#include "proxy.h"
#include "config.h"
#include "tcpmux.h"
#include "control.h"
static const char base64_table[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int
base64_encode(const uint8_t *src, int srclen, char *dst)
{
uint32_t ac = 0;
int bits = 0;
int i;
char *cp = dst;
for (i = 0; i < srclen; i++) {
ac = (ac << 8) | src[i];
bits += 8;
do {
bits -= 6;
*cp++ = base64_table[(ac >> bits) & 0x3f];
} while (bits >= 6);
}
if (bits) {
*cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
bits -= 6;
}
while (bits < 0) {
*cp++ = '=';
bits += 2;
}
return cp - dst;
}
static int
base64_decode(const char *src, int srclen, uint8_t *dst)
{
uint32_t ac = 0;
int bits = 0;
int i;
uint8_t *bp = dst;
for (i = 0; i < srclen; i++) {
const char *p = strchr(base64_table, src[i]);
if (src[i] == '=') {
ac = (ac << 6);
bits += 6;
if (bits >= 8)
bits -= 8;
continue;
}
if (p == NULL || src[i] == 0)
return -1;
ac = (ac << 6) | (p - base64_table);
bits += 6;
if (bits >= 8) {
bits -= 8;
*bp++ = (uint8_t)(ac >> bits);
}
}
if (ac & ((1 << bits) - 1))
return -1;
return bp - dst;
}
static void
evutil_base64_decode(struct evbuffer *src, struct evbuffer *dst)
{
uint8_t dbuff[1500] = {0};
size_t len = evbuffer_get_length(src);
char *buf = (char *)malloc(len);
assert(buf != NULL);
memset(buf, 0, len);
evbuffer_remove(src, buf, len);
int decode_len = base64_decode(buf, len, dbuff);
assert(decode_len > 0 && decode_len < 1500);
evbuffer_add(dst, dbuff, decode_len);
free(buf);
}
static void
evutil_base64_encode(struct evbuffer *src, struct evbuffer *dst)
{
char ebuff[2048] = {0}; // 2048 is enough for base64 encode
size_t len = evbuffer_get_length(src);
uint8_t *buf = (uint8_t *)malloc(len);
assert(buf != NULL);
memset(buf, 0, len);
evbuffer_remove(src, buf, len);
int encode_len = base64_encode(buf, len, ebuff);
assert(encode_len > 0 && encode_len < 2048);
evbuffer_add(dst, ebuff, encode_len);
free(buf);
}
void
handle_udp_packet(struct udp_packet *udp_pkt, struct proxy_client *client)
{
// debase64 of udp_pkt->content
struct evbuffer *base64_input = evbuffer_new();
size_t content_len = strlen(udp_pkt->content);
evbuffer_add(base64_input, udp_pkt->content, content_len);
struct evbuffer *base64_output = evbuffer_new();
evutil_base64_decode(base64_input, base64_output);
evbuffer_free(base64_input);
// send buf content to local_proxy_bev
struct bufferevent *local_proxy_bev = client->local_proxy_bev;
assert(local_proxy_bev != NULL);
// according to client proxy service's local address and port, send buf to local_proxy_bev
assert(client->ps);
// if client->ps->local_addr is domain, need to resolve it
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(client->ps->local_port);
if (inet_pton(AF_INET, client->ps->local_ip, &local_addr.sin_addr) <= 0) {
// domain
struct hostent *host = gethostbyname(client->ps->local_ip);
assert(host != NULL);
if (host == NULL) {
debug(LOG_ERR, "gethostbyname %s failed", client->ps->local_ip);
evbuffer_free(base64_output);
return;
}
memcpy(&local_addr.sin_addr, host->h_addr, host->h_length);
}
// send buf to local_proxy_bev
struct evbuffer *dst = bufferevent_get_output(local_proxy_bev);
evbuffer_add_buffer(dst, base64_output);
evbuffer_free(base64_output);
}
void
udp_proxy_c2s_cb(struct bufferevent *bev, void *ctx)
{
struct common_conf *c_conf = get_common_config();
struct proxy_client *client = (struct proxy_client *)ctx;
assert(client);
struct bufferevent *partner = client->ctl_bev;
assert(partner);
struct evbuffer *src = bufferevent_get_input(bev);
// encode src to base64
struct evbuffer *base64_output = evbuffer_new();
evutil_base64_encode(src, base64_output);
evbuffer_free(src);
// convert base64_output to udp_packet and json marshal
struct udp_packet *udp_pkt = (struct udp_packet *)malloc(sizeof(struct udp_packet));
assert(udp_pkt != NULL);
memset(udp_pkt, 0, sizeof(struct udp_packet));
udp_pkt->content = evbuffer_pullup(base64_output, -1);
udp_pkt->raddr = (struct udp_addr *)malloc(sizeof(struct udp_addr));
assert(udp_pkt->raddr != NULL);
memset(udp_pkt->raddr, 0, sizeof(struct udp_addr));
udp_pkt->raddr->addr = client->ps->local_ip;
udp_pkt->raddr->port = client->ps->local_port;
char *buf = NULL;
new_udp_packet_marshal(udp_pkt, &buf);
size_t len = strlen(buf);
free(udp_pkt->raddr);
free(udp_pkt);
if (!c_conf->tcp_mux) {
struct evbuffer *dst = bufferevent_get_output(partner);
evbuffer_add(dst, buf, len);
free(buf);
return;
}
uint32_t nr = tmux_stream_write(partner, buf, len, &client->stream);
if (nr < len) {
debug(LOG_DEBUG, "stream_id [%d] len is %d tmux_stream_write %d data, disable read", client->stream.id, len, nr);
bufferevent_disable(bev, EV_READ);
}
free(buf);
}
void
udp_proxy_s2c_cb(struct bufferevent *bev, void *ctx)
{
struct proxy_client *client = (struct proxy_client *)ctx;
assert(client);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/nackman/xfrpc.git
git@gitee.com:nackman/xfrpc.git
nackman
xfrpc
xfrpc
master

搜索帮助