Support access web

Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
This commit is contained in:
Jianhui Zhao
2021-01-06 00:28:55 +08:00
parent 5f348a7690
commit 486a2b3c9f
8 changed files with 314 additions and 35 deletions
+1 -1
View File
@@ -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
+47 -32
View File
@@ -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);
+4
View File
@@ -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
+5
View File
@@ -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
View File
@@ -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;
+222
View File
@@ -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);
}
+32
View File
@@ -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