2 Star 9 Fork 2

liudengfeng / project_25300166

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
client.c 6.20 KB
一键复制 编辑 原始数据 按行查看 历史
liudengfeng 提交于 2022-10-21 10:31 . refactor: refactor tcp mux
/* 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 client.c
@brief client surrogate for local service
@author Copyright (C) 2016 Dengfeng Liu <liu_df@qq.com>
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <syslog.h>
#include <zlib.h>
#include "debug.h"
#include "client.h"
#include "uthash.h"
#include "control.h"
#include "config.h"
#include "const.h"
#include "uthash.h"
#include "zip.h"
#include "common.h"
#include "proxy.h"
#include "utils.h"
#include "tcpmux.h"
static struct proxy_client *all_pc = NULL;
static void
xfrp_worker_event_cb(struct bufferevent *bev, short what, void *ctx)
{
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
debug(LOG_DEBUG, "working connection closed!");
bufferevent_free(bev);
}
}
static void
xfrp_proxy_event_cb(struct bufferevent *bev, short what, void *ctx)
{
struct proxy_client *client = ctx;
assert(client);
if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
debug(LOG_DEBUG, "xfrpc proxy close connect server [%s:%d] stream_id %d: %s",
client->ps->local_ip, client->ps->local_port,
client->stream_id, strerror(errno));
tmux_stream_close(client->ctl_bev, &client->stream);
} else if (what & BEV_EVENT_CONNECTED) {
debug(LOG_DEBUG, "client [%d] connected", client->stream_id);
//client->stream.state = ESTABLISHED;
if (client->data_tail_size > 0) {
debug(LOG_DEBUG, "send client data ...");
send_client_data_tail(client);
}
}
}
int
is_ftp_proxy(const struct proxy_service *ps)
{
if (! ps || ! ps->proxy_type)
return 0;
if (0 == strcmp(ps->proxy_type, "ftp") && ps->remote_data_port > 0)
return 1;
return 0;
}
// create frp tunnel for service
void
start_xfrp_tunnel(struct proxy_client *client)
{
if (! client->ctl_bev) {
debug(LOG_ERR, "proxy client control bev is invalid!");
return;
}
struct event_base *base = client->base;
struct common_conf *c_conf = get_common_config();
struct proxy_service *ps = client->ps;
if ( !base ) {
debug(LOG_ERR, "service event base get failed");
return;
}
if ( !ps ) {
debug(LOG_ERR, "service tunnel started failed, no proxy service resource.");
return;
}
if ( !ps->local_port ) {
debug(LOG_ERR, "service tunnel started failed, proxy service resource unvalid.");
return;
}
client->local_proxy_bev = connect_server(base, ps->local_ip, ps->local_port);
if ( !client->local_proxy_bev ) {
debug(LOG_ERR, "frpc tunnel connect local proxy port [%d] failed!", ps->local_port);
del_proxy_client(client);
return;
}
debug(LOG_DEBUG, "proxy server [%s:%d] <---> client [%s:%d]",
c_conf->server_addr,
ps->remote_port,
ps->local_ip ? ps->local_ip:"::1",
ps->local_port);
bufferevent_data_cb proxy_s2c_recv, proxy_c2s_recv;
if (is_ftp_proxy(client->ps)) {
proxy_c2s_recv = ftp_proxy_c2s_cb;
proxy_s2c_recv = ftp_proxy_s2c_cb;
} else {
proxy_c2s_recv = tcp_proxy_c2s_cb; // local service ---> xfrpc
proxy_s2c_recv = tcp_proxy_s2c_cb; // frps ---> xfrpc
}
if (!c_conf->tcp_mux) {
bufferevent_setcb(client->ctl_bev,
proxy_s2c_recv,
NULL,
xfrp_worker_event_cb,
client);
bufferevent_enable(client->ctl_bev, EV_READ|EV_WRITE);
}
bufferevent_setcb(client->local_proxy_bev,
proxy_c2s_recv,
NULL,
xfrp_proxy_event_cb,
client);
bufferevent_enable(client->local_proxy_bev, EV_READ|EV_WRITE);
}
int
send_client_data_tail(struct proxy_client *client)
{
int send_l = 0;
if (client->data_tail && client->data_tail_size && client->local_proxy_bev) {
send_l = bufferevent_write(client->local_proxy_bev, client->data_tail, client->data_tail_size);
client->data_tail = NULL;
client->data_tail_size = 0;
}
return send_l;
}
static void
free_proxy_client(struct proxy_client *client)
{
debug(LOG_DEBUG, "free client %d", client->stream_id);
if (client->local_proxy_bev) bufferevent_free(client->local_proxy_bev);
free(client);
}
void
del_proxy_client(struct proxy_client *client)
{
if (!client || !all_pc ) {
debug(LOG_INFO, "all_pc or client is NULL");
return;
}
HASH_DEL(all_pc, client);
free_proxy_client(client);
}
void
del_proxy_client_by_stream_id(uint32_t sid)
{
del_stream(sid);
struct proxy_client *pc = get_proxy_client(sid);
del_proxy_client(pc);
}
struct proxy_client *
get_proxy_client(uint32_t sid)
{
struct proxy_client *pc = NULL;
HASH_FIND_INT(all_pc, &sid, pc);
return pc;
}
struct proxy_client *
new_proxy_client()
{
struct proxy_client *client = calloc(1, sizeof(struct proxy_client));
assert(client);
client->stream_id = get_next_session_id();
init_tmux_stream(&client->stream, client->stream_id, INIT);
HASH_ADD_INT(all_pc, stream_id, client);
return client;
}
void
clear_all_proxy_client()
{
if (!all_pc) return;
struct proxy_client *client, *tmp;
HASH_ITER(hh, all_pc, client, tmp) {
HASH_DEL(all_pc, client);
free_proxy_client(client);
}
}
C
1
https://gitee.com/apfree/xfrpc.git
git@gitee.com:apfree/xfrpc.git
apfree
xfrpc
project_25300166
master

搜索帮助