mirror of
https://github.com/zhaojh329/rtty.git
synced 2026-02-27 09:53:17 +08:00
+1
-1
@@ -95,7 +95,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_executable(rtty main.c utils.c buffer/buffer.c log.c net.c net.h rtty.c rtty.h command.c
|
||||
file.c upfile.c upfile.h downfile.c downfile.h ssl.c ssl.h)
|
||||
file.c upfile.c upfile.h downfile.c downfile.h ssl.c ssl.h web.c)
|
||||
target_link_libraries(rtty ${EXTRA_LIBS})
|
||||
|
||||
# configure a header file to pass some of the CMake settings to the source code
|
||||
|
||||
+1
-1
Submodule src/buffer updated: 2fb5523d44...1bd1b6d192
@@ -22,13 +22,15 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <ev.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "net.h"
|
||||
#include "log.h"
|
||||
|
||||
@@ -56,7 +58,7 @@ static const char *port2str(int port)
|
||||
|
||||
static void sock_write_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct net_context *ctx = w->data;
|
||||
struct net_context *ctx = container_of(w, struct net_context, iow);
|
||||
int err = 0;
|
||||
socklen_t len = sizeof(err);
|
||||
int ret;
|
||||
@@ -76,40 +78,69 @@ static void sock_write_cb(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
}
|
||||
|
||||
ctx->on_connected(w->fd, ctx->arg);
|
||||
free(ctx);
|
||||
return;
|
||||
|
||||
err:
|
||||
close(w->fd);
|
||||
ctx->on_connected(-1, ctx->arg);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
{
|
||||
struct net_context *ctx = w->data;
|
||||
struct net_context *ctx = container_of(w, struct net_context, tmr);
|
||||
|
||||
log_err("network connect timeout\n");
|
||||
|
||||
ev_io_stop(loop, &ctx->iow);
|
||||
close(ctx->sock);
|
||||
ctx->on_connected(-1, ctx->arg);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void wait_connect(struct ev_loop *loop, int sock, int timeout,
|
||||
void (*on_connected)(int sock, void *arg), void *arg)
|
||||
{
|
||||
static struct net_context ctx;
|
||||
struct net_context *ctx = calloc(1, sizeof(struct net_context));
|
||||
|
||||
ctx.sock = sock;
|
||||
ctx.arg = arg;
|
||||
ctx.on_connected = on_connected;
|
||||
ctx->sock = sock;
|
||||
ctx->arg = arg;
|
||||
ctx->on_connected = on_connected;
|
||||
|
||||
ev_timer_init(&ctx.tmr, timer_cb, timeout, 0);
|
||||
ctx.tmr.data = &ctx;
|
||||
ev_timer_start(loop, &ctx.tmr);
|
||||
ev_timer_init(&ctx->tmr, timer_cb, timeout, 0);
|
||||
ev_timer_start(loop, &ctx->tmr);
|
||||
|
||||
ev_io_init(&ctx.iow, sock_write_cb, sock, EV_WRITE);
|
||||
ctx.iow.data = &ctx;
|
||||
ev_io_start(loop, &ctx.iow);
|
||||
ev_io_init(&ctx->iow, sock_write_cb, sock, EV_WRITE);
|
||||
ev_io_start(loop, &ctx->iow);
|
||||
}
|
||||
|
||||
int tcp_connect_sockaddr(struct ev_loop *loop, const struct sockaddr *addr, socklen_t addrlen,
|
||||
void (*on_connected)(int sock, void *arg), void *arg)
|
||||
{
|
||||
int sock;
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (sock < 0) {
|
||||
log_err("create socket failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (connect(sock, addr, addrlen) < 0) {
|
||||
if (errno != EINPROGRESS) {
|
||||
log_err("connect failed: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
wait_connect(loop, sock, 3, on_connected, arg);
|
||||
} else {
|
||||
on_connected(sock, arg);
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
err:
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
@@ -123,7 +154,7 @@ int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
.ai_flags = AI_ADDRCONFIG
|
||||
};
|
||||
int sock = -1;
|
||||
int addr_len;
|
||||
int addrlen;
|
||||
int ret;
|
||||
|
||||
ret = getaddrinfo(host, port2str(port), &hints, &result);
|
||||
@@ -140,7 +171,7 @@ int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
if (rp->ai_family == AF_INET) {
|
||||
addr = rp->ai_addr;
|
||||
addr_len = rp->ai_addrlen;
|
||||
addrlen = rp->ai_addrlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -150,23 +181,7 @@ int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
goto free_addrinfo;
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (sock < 0) {
|
||||
log_err("create socket failed: %s\n", strerror(errno));
|
||||
goto free_addrinfo;
|
||||
}
|
||||
|
||||
if (connect(sock, addr, addr_len) < 0) {
|
||||
if (errno != EINPROGRESS) {
|
||||
log_err("connect failed: %s\n", strerror(errno));
|
||||
close(sock);
|
||||
sock = -1;
|
||||
goto free_addrinfo;
|
||||
}
|
||||
wait_connect(loop, sock, 3, on_connected, arg);
|
||||
} else {
|
||||
on_connected(sock, arg);
|
||||
}
|
||||
sock = tcp_connect_sockaddr(loop, addr, addrlen, on_connected, arg);
|
||||
|
||||
free_addrinfo:
|
||||
freeaddrinfo(result);
|
||||
|
||||
@@ -25,9 +25,13 @@
|
||||
#ifndef RTTY_NET_H
|
||||
#define RTTY_NET_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <ev.h>
|
||||
|
||||
int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
void (*on_connected)(int sock, void *arg), void *arg);
|
||||
|
||||
int tcp_connect_sockaddr(struct ev_loop *loop, const struct sockaddr *addr, socklen_t addrlen,
|
||||
void (*on_connected)(int sock, void *arg), void *arg);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "ssl.h"
|
||||
#include "net.h"
|
||||
#include "log.h"
|
||||
#include "web.h"
|
||||
#include "file.h"
|
||||
#include "rtty.h"
|
||||
#include "list.h"
|
||||
@@ -330,6 +331,10 @@ static void parse_msg(struct rtty *rtty)
|
||||
parse_file_msg(&rtty->file_context, buffer_pull_u8(rb), rb, msglen - 1);
|
||||
break;
|
||||
|
||||
case MSG_TYPE_WEB:
|
||||
web_request(rtty, msglen);
|
||||
break;
|
||||
|
||||
default:
|
||||
log_err("invalid message type: %d\n", msgtype);
|
||||
rtty_exit(rtty);
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ enum {
|
||||
MSG_TYPE_WINSIZE = 0x04,
|
||||
MSG_TYPE_CMD = 0x05,
|
||||
MSG_TYPE_HEARTBEAT = 0x06,
|
||||
MSG_TYPE_FILE = 0x07
|
||||
MSG_TYPE_FILE = 0x07,
|
||||
MSG_TYPE_WEB = 0x08
|
||||
};
|
||||
|
||||
struct rtty;
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "web.h"
|
||||
#include "net.h"
|
||||
#include "log.h"
|
||||
|
||||
struct web_request_ctx {
|
||||
struct list_head head;
|
||||
struct rtty *rtty;
|
||||
struct ev_timer tmr;
|
||||
struct ev_io ior;
|
||||
struct ev_io iow;
|
||||
struct buffer rb;
|
||||
struct buffer wb;
|
||||
ev_tstamp active;
|
||||
bool closed;
|
||||
int sock;
|
||||
int id;
|
||||
};
|
||||
|
||||
static LIST_HEAD(reqs);
|
||||
|
||||
static void web_request_free(struct web_request_ctx *ctx)
|
||||
{
|
||||
struct rtty *rtty = ctx->rtty;
|
||||
struct ev_loop *loop = rtty->loop;
|
||||
struct buffer *wb = &rtty->wb;
|
||||
|
||||
if (ctx->sock > 0) {
|
||||
ev_io_stop(loop, &ctx->ior);
|
||||
ev_io_stop(loop, &ctx->iow);
|
||||
ev_timer_stop(loop, &ctx->tmr);
|
||||
close(ctx->sock);
|
||||
}
|
||||
|
||||
buffer_put_u8(wb, MSG_TYPE_WEB);
|
||||
buffer_put_u16be(wb, 2);
|
||||
buffer_put_u16be(wb, ctx->id);
|
||||
ev_io_start(loop, &rtty->iow);
|
||||
|
||||
buffer_free(&ctx->rb);
|
||||
buffer_free(&ctx->wb);
|
||||
|
||||
list_del(&ctx->head);
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static void on_net_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct web_request_ctx *ctx = container_of(w, struct web_request_ctx, ior);
|
||||
struct rtty *rtty = ctx->rtty;
|
||||
struct buffer *wb = &rtty->wb;
|
||||
uint8_t buf[4096];
|
||||
int ret;
|
||||
|
||||
ret = read(w->fd, buf, 4096);
|
||||
if (ret <= 0)
|
||||
goto done;
|
||||
|
||||
buffer_put_u8(wb, MSG_TYPE_WEB);
|
||||
buffer_put_u16be(wb, 2 + ret);
|
||||
buffer_put_u16be(wb, ctx->id);
|
||||
buffer_put_data(wb, buf, ret);
|
||||
ev_io_start(rtty->loop, &rtty->iow);
|
||||
|
||||
ctx->active = ev_now(rtty->loop);
|
||||
|
||||
return;
|
||||
|
||||
done:
|
||||
web_request_free(ctx);
|
||||
}
|
||||
|
||||
static void on_net_write(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
{
|
||||
struct web_request_ctx *ctx = container_of(w, struct web_request_ctx, iow);
|
||||
|
||||
if (buffer_pull_to_fd(&ctx->wb, w->fd, -1) < 0)
|
||||
goto err;
|
||||
|
||||
if (buffer_length(&ctx->wb) > 0)
|
||||
return;
|
||||
|
||||
err:
|
||||
if (ctx->closed) {
|
||||
web_request_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ev_io_stop(loop, w);
|
||||
}
|
||||
|
||||
static void on_timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
{
|
||||
struct web_request_ctx *ctx = container_of(w, struct web_request_ctx, tmr);
|
||||
ev_tstamp now = ev_now(loop);
|
||||
|
||||
if (now - ctx->active < 30)
|
||||
return;
|
||||
|
||||
web_request_free(ctx);
|
||||
}
|
||||
|
||||
static void on_connected(int sock, void *arg)
|
||||
{
|
||||
struct web_request_ctx *ctx = (struct web_request_ctx *)arg;
|
||||
struct ev_loop *loop = ctx->rtty->loop;
|
||||
|
||||
if (sock < 0) {
|
||||
web_request_free(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
ev_io_init(&ctx->ior, on_net_read, sock, EV_READ);
|
||||
ev_io_start(loop, &ctx->ior);
|
||||
|
||||
ev_io_init(&ctx->iow, on_net_write, sock, EV_WRITE);
|
||||
ev_io_start(loop, &ctx->iow);
|
||||
|
||||
ev_timer_init(&ctx->tmr, on_timer_cb, 1, 0);
|
||||
ev_timer_start(loop, &ctx->tmr);
|
||||
|
||||
ctx->sock = sock;
|
||||
}
|
||||
|
||||
static struct web_request_ctx *find_exist_ctx(int port)
|
||||
{
|
||||
struct web_request_ctx *ctx;
|
||||
|
||||
list_for_each_entry(ctx, &reqs, head)
|
||||
if (ctx->id == port)
|
||||
return ctx;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void web_request(struct rtty *rtty, int len)
|
||||
{
|
||||
struct web_request_ctx *ctx;
|
||||
int id, sock, req_len;
|
||||
struct sockaddr_in addrin = {
|
||||
.sin_family = AF_INET
|
||||
};
|
||||
void *data;
|
||||
|
||||
id = buffer_pull_u16be(&rtty->rb);
|
||||
req_len = len - 2;
|
||||
|
||||
ctx = find_exist_ctx(id);
|
||||
if (ctx) {
|
||||
if (req_len == 0) {
|
||||
ctx->closed = true;
|
||||
if (ctx->sock > 0)
|
||||
ev_io_start(rtty->loop, &ctx->iow);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_pull(&rtty->rb, NULL, 6);
|
||||
req_len -= 6;
|
||||
|
||||
data = buffer_put(&ctx->wb, req_len);
|
||||
buffer_pull(&rtty->rb, data, req_len);
|
||||
|
||||
if (ctx->sock > 0)
|
||||
ev_io_start(rtty->loop, &ctx->iow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (req_len == 0)
|
||||
return;
|
||||
|
||||
addrin.sin_addr.s_addr = buffer_pull_u32(&rtty->rb);
|
||||
addrin.sin_port = buffer_pull_u16(&rtty->rb);
|
||||
|
||||
req_len -= 6;
|
||||
|
||||
ctx = (struct web_request_ctx *)calloc(1, sizeof(struct web_request_ctx));
|
||||
ctx->rtty = rtty;
|
||||
ctx->id = id;
|
||||
ctx->active = ev_now(rtty->loop);
|
||||
|
||||
data = buffer_put(&ctx->wb, req_len);
|
||||
buffer_pull(&rtty->rb, data, req_len);
|
||||
|
||||
list_add(&ctx->head, &reqs);
|
||||
|
||||
sock = tcp_connect_sockaddr(rtty->loop, (struct sockaddr *)&addrin, sizeof(addrin), on_connected, ctx);
|
||||
if (sock < 0)
|
||||
web_request_free(ctx);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2019 Jianhui Zhao <zhaojh329@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _WEB_H
|
||||
#define _WEB_H
|
||||
|
||||
#include "rtty.h"
|
||||
|
||||
void web_request(struct rtty *rtty, int len);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user