mirror of
https://github.com/zhaojh329/rtty.git
synced 2026-02-27 09:53:17 +08:00
Add support KCP protocol
https://github.com/skywind3000/kcp/blob/master/README.en.md Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
This commit is contained in:
committed by
Jianhui Zhao
parent
1cfc93852c
commit
d1fa4efd86
@@ -7,3 +7,6 @@
|
||||
[submodule "src/log"]
|
||||
path = src/log
|
||||
url = https://github.com/zhaojh329/log.git
|
||||
[submodule "src/kcp"]
|
||||
path = src/kcp
|
||||
url = https://github.com/skywind3000/kcp.git
|
||||
|
||||
+21
-3
@@ -3,25 +3,43 @@ set(RTTY_VERSION_MAJOR 9)
|
||||
set(RTTY_VERSION_MINOR 0)
|
||||
set(RTTY_VERSION_PATCH 2)
|
||||
|
||||
option(KCP_SUPPORT "KCP support" ON)
|
||||
|
||||
# Check the third party Libraries
|
||||
find_package(Libev REQUIRED)
|
||||
|
||||
aux_source_directory(. SRCS)
|
||||
aux_source_directory(log SRCS)
|
||||
aux_source_directory(buffer SRCS)
|
||||
|
||||
add_subdirectory(ssl)
|
||||
|
||||
list(APPEND SRCS main.c rtty.c net.c utils.c file.c filectl.c command.c http.c)
|
||||
|
||||
if(KCP_SUPPORT)
|
||||
if (NOT SSL_SUPPORT)
|
||||
message(WARNING "SSL Not enabled, disable KCP")
|
||||
set(KCP_SUPPORT OFF)
|
||||
else()
|
||||
list(APPEND SRCS kcp.c crc32.c crypt.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(rtty ${SRCS})
|
||||
target_compile_definitions(rtty PRIVATE _GNU_SOURCE)
|
||||
target_compile_options(rtty PRIVATE -O -Wall -Werror --std=gnu99)
|
||||
target_include_directories(rtty PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/buffer ${LIBEV_INCLUDE_DIR})
|
||||
target_link_libraries(rtty PRIVATE ${LIBEV_LIBRARY} util crypt m)
|
||||
|
||||
add_subdirectory(ssl)
|
||||
|
||||
if(SSL_SUPPORT)
|
||||
target_compile_definitions(rtty PRIVATE ${SSL_DEFINE})
|
||||
target_link_libraries(rtty PRIVATE ${SSL_TARGET})
|
||||
endif()
|
||||
|
||||
if(KCP_SUPPORT)
|
||||
add_subdirectory(kcp)
|
||||
target_link_libraries(rtty PRIVATE kcp)
|
||||
endif()
|
||||
|
||||
# configure a header file to pass some of the CMake settings to the source code
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
|
||||
@@ -31,5 +31,6 @@
|
||||
#define RTTY_VERSION_STRING "@RTTY_VERSION_MAJOR@.@RTTY_VERSION_MINOR@.@RTTY_VERSION_PATCH@"
|
||||
|
||||
#cmakedefine SSL_SUPPORT
|
||||
#cmakedefine KCP_SUPPORT
|
||||
|
||||
#endif
|
||||
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define IEEE 0xedb88320
|
||||
|
||||
#define slicing8_cutoff 16
|
||||
|
||||
typedef uint32_t table[256];
|
||||
|
||||
typedef struct slicing8_table {
|
||||
table tables[8];
|
||||
} slicing8_table;
|
||||
|
||||
static slicing8_table tab;
|
||||
|
||||
static void simple_populate_table(uint32_t poly, table t)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
uint32_t crc = i;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
t[i] = crc;
|
||||
}
|
||||
}
|
||||
|
||||
static void slicing_make_table(uint32_t poly)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
simple_populate_table(poly, tab.tables[0]);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
uint32_t crc = tab.tables[0][i];
|
||||
for (j = 1; j < 8; j++) {
|
||||
crc = tab.tables[0][crc & 0xFF] ^ (crc >> 8);
|
||||
tab.tables[j][i] = crc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t simple_update(uint32_t crc, const table tab, const uint8_t *p, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
crc = ~crc;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
crc = tab[(uint8_t)crc ^ p[i]] ^ (crc >> 8);
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
uint32_t crc32_checksum_ieee(const uint8_t* p, size_t len)
|
||||
{
|
||||
static bool inited;
|
||||
uint32_t crc = 0;
|
||||
|
||||
if (!inited) {
|
||||
inited = true;
|
||||
slicing_make_table(IEEE);
|
||||
}
|
||||
|
||||
if (len >= slicing8_cutoff) {
|
||||
crc = ~crc;
|
||||
while (len >= 8) {
|
||||
uint32_t n;
|
||||
memcpy(&n, p, sizeof(n));
|
||||
crc ^= n;
|
||||
crc = tab.tables[0][p[7]] ^
|
||||
tab.tables[1][p[6]] ^
|
||||
tab.tables[2][p[5]] ^
|
||||
tab.tables[3][p[4]] ^
|
||||
tab.tables[4][crc >> 24] ^
|
||||
tab.tables[5][(crc >> 16) & 0xFF] ^
|
||||
tab.tables[6][(crc >> 8) & 0xFF] ^
|
||||
tab.tables[7][crc & 0xFF];
|
||||
p += 8;
|
||||
len -= 8;
|
||||
}
|
||||
crc = ~crc;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
return crc;
|
||||
|
||||
return simple_update(crc, tab.tables[0], p, len);
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 RTTY_CRC32_H
|
||||
#define RTTY_CRC32_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t crc32_checksum_ieee(const uint8_t *p, size_t len);
|
||||
|
||||
#endif
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
#include <openssl/evp.h>
|
||||
#elif defined(HAVE_WOLFSSL)
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/openssl/evp.h>
|
||||
#else
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/md.h>
|
||||
#endif
|
||||
|
||||
#include "crypt.h"
|
||||
|
||||
void *cipher_init_ctx(const char *password)
|
||||
{
|
||||
uint8_t key[32];
|
||||
|
||||
#if defined(HAVE_OPENSSL) || defined(HAVE_WOLFSSL)
|
||||
EVP_CIPHER_CTX *cipher = EVP_CIPHER_CTX_new();
|
||||
|
||||
PKCS5_PBKDF2_HMAC(password, strlen(password), NULL, 0, 1024, EVP_sha256(), 32, key);
|
||||
EVP_EncryptInit(cipher, EVP_aes_256_ecb(), key, NULL);
|
||||
|
||||
return cipher;
|
||||
#else
|
||||
mbedtls_aes_context *aes_ctx;
|
||||
mbedtls_md_context_t md_ctx;
|
||||
|
||||
mbedtls_md_init(&md_ctx);
|
||||
mbedtls_md_setup(&md_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
|
||||
mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, (const uint8_t *)password, strlen(password),
|
||||
NULL, 0, 1024, 32, key);
|
||||
mbedtls_md_free(&md_ctx);
|
||||
|
||||
aes_ctx = malloc(sizeof(mbedtls_aes_context));
|
||||
|
||||
mbedtls_aes_init(aes_ctx);
|
||||
mbedtls_aes_setkey_enc(aes_ctx, key, 256);
|
||||
|
||||
return aes_ctx;
|
||||
#endif
|
||||
}
|
||||
|
||||
int get_random_bytes(uint8_t *out, size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (read(fd, out, len) < 0)
|
||||
ret = -1;
|
||||
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t initial_vector[] = {167, 115, 79, 156, 18, 172, 27, 1, 164, 21, 242, 193, 252, 120, 230, 107};
|
||||
|
||||
static void xor_bytes(uint8_t *dst, const uint8_t *a, const uint8_t *b, size_t n)
|
||||
{
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
dst[i] = a[i] ^ b[i];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void aes_block_encrypt(void *ctx, uint8_t *dst, const uint8_t *src)
|
||||
{
|
||||
#if defined(HAVE_OPENSSL) || defined(HAVE_WOLFSSL)
|
||||
int out_len;
|
||||
EVP_EncryptUpdate(ctx, dst, &out_len, src, 16);
|
||||
#else
|
||||
mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, src, dst);
|
||||
#endif
|
||||
}
|
||||
|
||||
void encrypt16(void *ctx, uint8_t *dst, const uint8_t *src, size_t src_len)
|
||||
{
|
||||
size_t n = src_len / 16;
|
||||
size_t repeat = n / 8;
|
||||
size_t left = n % 8;
|
||||
size_t remaining;
|
||||
size_t base = 0;
|
||||
uint8_t tbl[16];
|
||||
|
||||
aes_block_encrypt(ctx, tbl, initial_vector);
|
||||
|
||||
for (size_t i = 0; i < repeat; i++) {
|
||||
const uint8_t *s = src + base;
|
||||
uint8_t *d = dst + base;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
xor_bytes(d + j*16, s + j*16, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, d + j * 16);
|
||||
}
|
||||
base += 128;
|
||||
}
|
||||
|
||||
switch (left) {
|
||||
case 7:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 6:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 5:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 4:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 3:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 2:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 1:
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
aes_block_encrypt(ctx, tbl, dst + base);
|
||||
base += 16;
|
||||
case 0:
|
||||
remaining = src_len - base;
|
||||
if (remaining > 0)
|
||||
xor_bytes(dst + base, src + base, tbl, remaining);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void decrypt16(void *ctx, uint8_t *dst, const uint8_t *src, size_t src_len)
|
||||
{
|
||||
size_t n = src_len / 16;
|
||||
size_t repeat = n / 8;
|
||||
size_t left = n % 8;
|
||||
size_t base = 0;
|
||||
uint8_t buf[32];
|
||||
uint8_t *tbl = buf;
|
||||
uint8_t *next = buf + 16;
|
||||
uint8_t *temp_ptr;
|
||||
|
||||
aes_block_encrypt(ctx, tbl, initial_vector);
|
||||
|
||||
for (size_t i = 0; i < repeat; i++) {
|
||||
const uint8_t *s = src + base;
|
||||
uint8_t *d = dst + base;
|
||||
|
||||
aes_block_encrypt(ctx, next, s);
|
||||
xor_bytes(d, s, tbl, 16);
|
||||
|
||||
aes_block_encrypt(ctx, tbl, s + 16);
|
||||
xor_bytes(d + 16, s + 16, next, 16);
|
||||
|
||||
aes_block_encrypt(ctx, next, s + 32);
|
||||
xor_bytes(d + 32, s + 32, tbl, 16);
|
||||
|
||||
aes_block_encrypt(ctx, tbl, s + 48);
|
||||
xor_bytes(d + 48, s + 48, next, 16);
|
||||
|
||||
aes_block_encrypt(ctx, next, s + 64);
|
||||
xor_bytes(d + 64, s + 64, tbl, 16);
|
||||
|
||||
aes_block_encrypt(ctx, tbl, s + 80);
|
||||
xor_bytes(d + 80, s + 80, next, 16);
|
||||
|
||||
aes_block_encrypt(ctx, next, s + 96);
|
||||
xor_bytes(d + 96, s + 96, tbl, 16);
|
||||
|
||||
aes_block_encrypt(ctx, tbl, s + 112);
|
||||
xor_bytes(d + 112, s + 112, next, 16);
|
||||
|
||||
base += 128;
|
||||
}
|
||||
|
||||
switch (left) {
|
||||
case 7:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 6:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 5:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 4:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 3:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 2:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 1:
|
||||
aes_block_encrypt(ctx, next, src + base);
|
||||
xor_bytes(dst + base, src + base, tbl, 16);
|
||||
temp_ptr = tbl;
|
||||
tbl = next;
|
||||
next = temp_ptr;
|
||||
base += 16;
|
||||
case 0:
|
||||
size_t remaining = src_len - base;
|
||||
if (remaining > 0)
|
||||
xor_bytes(dst + base, src + base, tbl, remaining);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 RTTY_CRYPT_H
|
||||
#define RTTY_CRYPT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void *cipher_init_ctx(const char *password);
|
||||
|
||||
int get_random_bytes(uint8_t *out, size_t len);
|
||||
|
||||
void encrypt16(void *ctx, uint8_t *dst, const uint8_t *src, size_t src_len);
|
||||
void decrypt16(void *ctx, uint8_t *dst, const uint8_t *src, size_t src_len);
|
||||
|
||||
#endif
|
||||
Submodule
+1
Submodule src/kcp added at f4f3a89cc6
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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 <endian.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "log/log.h"
|
||||
#include "crc32.h"
|
||||
#include "crypt.h"
|
||||
#include "rtty.h"
|
||||
|
||||
#define NONCE_SIZE 16
|
||||
#define CRC_SIZE 4
|
||||
#define CRYPT_HEADER_SIZE (NONCE_SIZE + CRC_SIZE)
|
||||
|
||||
#ifdef KCP_SUPPORT
|
||||
|
||||
void rtty_kcp_init_cipher(struct rtty_kcp *kcp)
|
||||
{
|
||||
if (!kcp->password)
|
||||
return;
|
||||
|
||||
kcp->cipher = cipher_init_ctx(kcp->password);
|
||||
}
|
||||
|
||||
static uint32_t rtty_kcp_now(struct rtty *rtty)
|
||||
{
|
||||
long now = ev_now(rtty->loop) * 1000;
|
||||
return now & 0xffffffff;
|
||||
}
|
||||
|
||||
void rtty_kcp_check(struct rtty *rtty)
|
||||
{
|
||||
uint32_t now = rtty_kcp_now(rtty);
|
||||
uint32_t next;
|
||||
long delay;
|
||||
|
||||
next = ikcp_check(rtty->kcp.kcp, now);
|
||||
delay = next - now;
|
||||
|
||||
if (delay <= 0)
|
||||
delay = 1;
|
||||
|
||||
ev_timer_set(&rtty->kcp.tmr, 0, delay / 1000.0);
|
||||
ev_timer_again(rtty->loop, &rtty->kcp.tmr);
|
||||
}
|
||||
|
||||
static int rtty_kcp_encrypt(struct rtty_kcp *kcp, uint8_t *dst, const uint8_t *src, int srclen)
|
||||
{
|
||||
uint32_t crc32;
|
||||
|
||||
get_random_bytes(dst, NONCE_SIZE);
|
||||
|
||||
crc32 = crc32_checksum_ieee(src, srclen);
|
||||
|
||||
crc32 = htole32(crc32);
|
||||
|
||||
memcpy(dst + NONCE_SIZE, &crc32, CRC_SIZE);
|
||||
memcpy(dst + CRYPT_HEADER_SIZE, src, srclen);
|
||||
|
||||
encrypt16(kcp->cipher, dst, dst, srclen + CRYPT_HEADER_SIZE);
|
||||
|
||||
return CRYPT_HEADER_SIZE + srclen;
|
||||
}
|
||||
|
||||
static int rtty_kcp_decrypt(struct rtty_kcp *kcp, uint8_t *dst, const uint8_t *src, int srclen)
|
||||
{
|
||||
uint32_t crc32_your, crc32_our;
|
||||
|
||||
if (srclen < CRYPT_HEADER_SIZE) {
|
||||
log_debug("data length too short\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
decrypt16(kcp->cipher, dst, src, srclen);
|
||||
|
||||
crc32_our = crc32_checksum_ieee(src + CRYPT_HEADER_SIZE, srclen - CRYPT_HEADER_SIZE);
|
||||
|
||||
memcpy(&crc32_your, dst + NONCE_SIZE, CRC_SIZE);
|
||||
|
||||
if (le32toh(crc32_your) !=crc32_our) {
|
||||
log_debug("crc32 error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return srclen;
|
||||
}
|
||||
|
||||
static int udp_output(const char *buf, int len, ikcpcb *kcp, void *user)
|
||||
{
|
||||
struct rtty *rtty = user;
|
||||
|
||||
if (rtty->kcp.password) {
|
||||
uint8_t dst[1500];
|
||||
int ret= rtty_kcp_encrypt(&rtty->kcp, dst, (const uint8_t *)buf, len);
|
||||
return send(rtty->sock, dst, ret, 0);
|
||||
}
|
||||
|
||||
return send(rtty->sock, buf, len, 0);
|
||||
}
|
||||
|
||||
static void kcp_timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
{
|
||||
struct rtty *rtty = container_of(w, struct rtty, kcp.tmr);
|
||||
uint32_t now = rtty_kcp_now(rtty);
|
||||
|
||||
ikcp_update(rtty->kcp.kcp, now);
|
||||
rtty_kcp_check(rtty);
|
||||
}
|
||||
|
||||
int rtty_kcp_init(struct rtty *rtty)
|
||||
{
|
||||
ikcpcb *kcp;
|
||||
|
||||
if (!rtty->kcp.on)
|
||||
return 0;
|
||||
|
||||
kcp = ikcp_create(random(), rtty);
|
||||
if (!kcp) {
|
||||
log_err("malloc: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ikcp_setoutput(kcp, udp_output);
|
||||
|
||||
ikcp_nodelay(kcp, rtty->kcp.nodelay, rtty->kcp.interval,
|
||||
rtty->kcp.resend, rtty->kcp.nc);
|
||||
|
||||
ikcp_wndsize(kcp, rtty->kcp.sndwnd, rtty->kcp.rcvwnd);
|
||||
|
||||
ikcp_setmtu(kcp, rtty->kcp.mtu);
|
||||
|
||||
ev_timer_init(&rtty->kcp.tmr, kcp_timer_cb, 1.0, 0);
|
||||
|
||||
rtty->kcp.kcp = kcp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtty_kcp_release(struct rtty *rtty)
|
||||
{
|
||||
if (rtty->kcp.kcp)
|
||||
return;
|
||||
|
||||
ikcp_release(rtty->kcp.kcp);
|
||||
rtty->kcp.kcp = NULL;
|
||||
}
|
||||
|
||||
int rtty_kcp_read(struct rtty *rtty, int fd)
|
||||
{
|
||||
char buf[1500];
|
||||
char *in = buf;
|
||||
int ret;
|
||||
|
||||
ret = read(fd, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
log_err("socket read error: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rtty->kcp.password) {
|
||||
ret = rtty_kcp_decrypt(&rtty->kcp, (uint8_t *)buf, (const uint8_t *)buf, ret);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
in = buf + CRYPT_HEADER_SIZE;
|
||||
ret -= CRYPT_HEADER_SIZE;
|
||||
}
|
||||
|
||||
ret = ikcp_input(rtty->kcp.kcp, in, ret);
|
||||
if (ret < 0) {
|
||||
log_err("ikcp_input fail: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
ret = ikcp_recv(rtty->kcp.kcp, buf, sizeof(buf));
|
||||
if (ret < 0)
|
||||
break;
|
||||
buffer_put_data(&rtty->rb, buf, ret);
|
||||
}
|
||||
|
||||
rtty_kcp_check(rtty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtty_kcp_write(struct rtty *rtty, int fd)
|
||||
{
|
||||
struct buffer *b = &rtty->wb;
|
||||
ikcpcb *kcp = rtty->kcp.kcp;
|
||||
size_t mss = kcp->mss;
|
||||
int ret;
|
||||
|
||||
if (rtty->kcp.password)
|
||||
mss -= CRYPT_HEADER_SIZE;
|
||||
|
||||
while (true) {
|
||||
size_t len = buffer_length(b);
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
if (len > mss)
|
||||
len = mss;
|
||||
|
||||
ret = ikcp_send(kcp, buffer_data(b), len);
|
||||
if (ret < 0) {
|
||||
log_err("ikcp_send fail: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_pull(b, NULL, ret);
|
||||
}
|
||||
|
||||
rtty_kcp_check(rtty);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 RTTY_KCP_H
|
||||
#define RTTY_KCP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <ev.h>
|
||||
|
||||
#include "kcp/ikcp.h"
|
||||
|
||||
struct rtty;
|
||||
|
||||
struct rtty_kcp {
|
||||
bool on;
|
||||
|
||||
ikcpcb *kcp;
|
||||
|
||||
struct ev_timer tmr;
|
||||
|
||||
const char *password;
|
||||
void *cipher;
|
||||
|
||||
bool nodelay;
|
||||
int interval;
|
||||
int resend;
|
||||
bool nc;
|
||||
int sndwnd;
|
||||
int rcvwnd;
|
||||
int mtu;
|
||||
};
|
||||
|
||||
void rtty_kcp_init_cipher(struct rtty_kcp *kcp);
|
||||
void rtty_kcp_check(struct rtty *rtty);
|
||||
int rtty_kcp_init(struct rtty *rtty);
|
||||
void rtty_kcp_release(struct rtty *rtty);
|
||||
int rtty_kcp_read(struct rtty *rtty, int fd);
|
||||
int rtty_kcp_write(struct rtty *rtty, int fd);
|
||||
|
||||
#endif
|
||||
+67
-2
@@ -34,7 +34,18 @@
|
||||
#include "rtty.h"
|
||||
|
||||
enum {
|
||||
LONG_OPT_HELP = 1
|
||||
LONG_OPT_HELP = 1,
|
||||
#ifdef KCP_SUPPORT
|
||||
LONG_OPT_KCP,
|
||||
LONG_OPT_KCP_NODELAY,
|
||||
LONG_OPT_KCP_INTERVAL,
|
||||
LONG_OPT_KCP_RESEND,
|
||||
LONG_OPT_KCP_NC,
|
||||
LONG_OPT_KCP_SNDWND,
|
||||
LONG_OPT_KCP_RCVWND,
|
||||
LONG_OPT_KCP_MTU,
|
||||
LONG_OPT_KCP_KEY,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
@@ -70,6 +81,17 @@ static struct option long_options[] = {
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"description", required_argument, NULL, 'd'},
|
||||
{"token", required_argument, NULL, 't'},
|
||||
#ifdef KCP_SUPPORT
|
||||
{"kcp", no_argument, NULL, LONG_OPT_KCP},
|
||||
{"kcp-nodelay", no_argument, NULL, LONG_OPT_KCP_NODELAY},
|
||||
{"kcp-interval", required_argument, NULL, LONG_OPT_KCP_INTERVAL},
|
||||
{"kcp-resend", required_argument, NULL, LONG_OPT_KCP_RESEND},
|
||||
{"kcp-nc", no_argument, NULL, LONG_OPT_KCP_NC},
|
||||
{"kcp-sndwnd", required_argument, NULL, LONG_OPT_KCP_SNDWND},
|
||||
{"kcp-rcvwnd", required_argument, NULL, LONG_OPT_KCP_RCVWND},
|
||||
{"kcp-mtu", required_argument, NULL, LONG_OPT_KCP_MTU},
|
||||
{"kcp-key", required_argument, NULL, LONG_OPT_KCP_KEY},
|
||||
#endif
|
||||
#ifdef SSL_SUPPORT
|
||||
{"cacert", required_argument, NULL, 'C'},
|
||||
{"insecure", no_argument, NULL, 'x'},
|
||||
@@ -92,6 +114,17 @@ static void usage(const char *prog)
|
||||
" -d, --description=string Add a description to the device(Maximum 126 bytes)\n"
|
||||
" -a Auto reconnect to the server\n"
|
||||
" -i number Set heartbeat interval in seconds(Default is 30s)\n"
|
||||
#ifdef KCP_SUPPORT
|
||||
" --kcp Using KCP protocol\n"
|
||||
" --kcp-nodelay Whether enable nodelay mode for KCP\n"
|
||||
" --kcp-interval number KCP protocol internal work interval(Default is 100ms)\n"
|
||||
" --kcp-resend number Fast retransmission mode for KCP\n"
|
||||
" --kcp-nc Whether to turn off flow control for KCP\n"
|
||||
" --kcp-sndwnd number Maximum send window for KCP\n"
|
||||
" --kcp-rcvwnd number Maximum receive window for KCP\n"
|
||||
" --kcp-mtu number Maximum transmission unit for KCP\n"
|
||||
" --kcp-key Key used to encrypt data\n"
|
||||
#endif
|
||||
#ifdef SSL_SUPPORT
|
||||
" -s SSL on\n"
|
||||
" -C, --cacert CA certificate to verify peer against\n"
|
||||
@@ -129,7 +162,10 @@ int main(int argc, char **argv)
|
||||
.host = "localhost",
|
||||
.port = 5912,
|
||||
.loop = loop,
|
||||
.sock = -1
|
||||
.sock = -1,
|
||||
#ifdef KCP_SUPPORT
|
||||
.kcp.interval = -1
|
||||
#endif
|
||||
};
|
||||
#ifdef SSL_SUPPORT
|
||||
bool has_cacert = false;
|
||||
@@ -194,6 +230,35 @@ int main(int argc, char **argv)
|
||||
case 'a':
|
||||
rtty.reconnect = true;
|
||||
break;
|
||||
#ifdef KCP_SUPPORT
|
||||
case LONG_OPT_KCP:
|
||||
rtty.kcp.on = true;
|
||||
break;
|
||||
case LONG_OPT_KCP_NODELAY:
|
||||
rtty.kcp.nodelay = true;
|
||||
break;
|
||||
case LONG_OPT_KCP_INTERVAL:
|
||||
rtty.kcp.interval = atoi(optarg);
|
||||
break;
|
||||
case LONG_OPT_KCP_RESEND:
|
||||
rtty.kcp.resend = atoi(optarg);
|
||||
break;
|
||||
case LONG_OPT_KCP_NC:
|
||||
rtty.kcp.nc = true;
|
||||
break;
|
||||
case LONG_OPT_KCP_SNDWND:
|
||||
rtty.kcp.sndwnd = atoi(optarg);
|
||||
break;
|
||||
case LONG_OPT_KCP_RCVWND:
|
||||
rtty.kcp.rcvwnd = atoi(optarg);
|
||||
break;
|
||||
case LONG_OPT_KCP_MTU:
|
||||
rtty.kcp.mtu = atoi(optarg);
|
||||
break;
|
||||
case LONG_OPT_KCP_KEY:
|
||||
rtty.kcp.password = optarg;
|
||||
break;
|
||||
#endif
|
||||
#ifdef SSL_SUPPORT
|
||||
case 's':
|
||||
rtty.ssl_on = true;
|
||||
|
||||
@@ -167,22 +167,17 @@ err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
void (*on_connected)(int sock, void *arg), void *arg)
|
||||
static int getaddr_by_name(int socktype, const char *host, int port,
|
||||
struct sockaddr *dest, int *addrlen)
|
||||
{
|
||||
struct sockaddr *addr = NULL;
|
||||
struct addrinfo *result, *rp;
|
||||
struct addrinfo hints = {
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_socktype = socktype,
|
||||
.ai_flags = AI_ADDRCONFIG
|
||||
};
|
||||
int sock = -1;
|
||||
int addrlen;
|
||||
int ret;
|
||||
|
||||
log_debug("connecting to %s:%d\n", host, port);
|
||||
|
||||
ret = getaddrinfo(host, port2str(port), &hints, &result);
|
||||
if (ret) {
|
||||
if (ret == EAI_SYSTEM) {
|
||||
@@ -194,22 +189,67 @@ int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = -1;
|
||||
|
||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||
if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) {
|
||||
addr = rp->ai_addr;
|
||||
addrlen = rp->ai_addrlen;
|
||||
memcpy(dest, rp->ai_addr, rp->ai_addrlen);
|
||||
*addrlen = rp->ai_addrlen;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr) {
|
||||
freeaddrinfo(result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
void (*on_connected)(int sock, void *arg), void *arg)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
int addrlen;
|
||||
|
||||
log_debug("connecting to %s:%d\n", host, port);
|
||||
|
||||
if (getaddr_by_name(SOCK_STREAM, host, port, &addr, &addrlen)) {
|
||||
log_err("getaddrinfo failed: Not found addr\n");
|
||||
goto free_addrinfo;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = tcp_connect_sockaddr(loop, addr, addrlen, on_connected, arg);
|
||||
return tcp_connect_sockaddr(loop, &addr, addrlen, on_connected, arg);
|
||||
}
|
||||
|
||||
int udp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
void (*on_connected)(int sock, void *arg), void *arg)
|
||||
{
|
||||
struct sockaddr addr;
|
||||
int addrlen;
|
||||
int sock;
|
||||
int ret;
|
||||
|
||||
log_debug("connecting to %s:%d\n", host, port);
|
||||
|
||||
if (getaddr_by_name(SOCK_DGRAM, host, port, &addr, &addrlen)) {
|
||||
log_err("getaddrinfo failed: Not found addr\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = socket(addr.sa_family, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
||||
if (sock < 0) {
|
||||
log_err("create socket failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = connect(sock, &addr, addrlen);
|
||||
if (ret < 0) {
|
||||
close(sock);
|
||||
log_err("connect '%s:%d' failed: %s\n", host, port, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
on_connected(sock, arg);
|
||||
|
||||
free_addrinfo:
|
||||
freeaddrinfo(result);
|
||||
return sock;
|
||||
}
|
||||
|
||||
@@ -34,4 +34,7 @@ int tcp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
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 udp_connect(struct ev_loop *loop, const char *host, int port,
|
||||
void (*on_connected)(int sock, void *arg), void *arg);
|
||||
|
||||
#endif
|
||||
|
||||
+51
-10
@@ -302,6 +302,10 @@ void rtty_exit(struct rtty *rtty)
|
||||
del_tty(tty);
|
||||
}
|
||||
|
||||
#ifdef KCP_SUPPORT
|
||||
rtty_kcp_release(rtty);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if (rtty->ssl) {
|
||||
ssl_session_free(rtty->ssl);
|
||||
@@ -608,10 +612,18 @@ static void on_net_read(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
goto err;
|
||||
#endif
|
||||
} else {
|
||||
ret = buffer_put_fd(&rtty->rb, w->fd, 4096, &eof);
|
||||
if (ret < 0) {
|
||||
log_err("socket read error: %s\n", strerror(errno));
|
||||
goto err;
|
||||
#ifdef KCP_SUPPORT
|
||||
if (rtty->kcp.on) {
|
||||
if (rtty_kcp_read(rtty, w->fd))
|
||||
goto err;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = buffer_put_fd(&rtty->rb, w->fd, 4096, &eof);
|
||||
if (ret < 0) {
|
||||
log_err("socket read error: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,10 +671,18 @@ static void on_net_write(struct ev_loop *loop, struct ev_io *w, int revents)
|
||||
buffer_pull(b, NULL, ret);
|
||||
#endif
|
||||
} else {
|
||||
ret = buffer_pull_to_fd(&rtty->wb, w->fd, -1);
|
||||
if (ret < 0) {
|
||||
log_err("socket write error: %s\n", strerror(errno));
|
||||
goto err;
|
||||
#ifdef KCP_SUPPORT
|
||||
if (rtty->kcp.on) {
|
||||
if (rtty_kcp_write(rtty, w->fd))
|
||||
goto err;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = buffer_pull_to_fd(&rtty->wb, w->fd, -1);
|
||||
if (ret < 0) {
|
||||
log_err("socket write error: %s\n", strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -688,12 +708,22 @@ static void on_net_connected(int sock, void *arg)
|
||||
|
||||
rtty->sock = sock;
|
||||
|
||||
#ifdef KCP_SUPPORT
|
||||
if (rtty_kcp_init(rtty)) {
|
||||
ev_break(rtty->loop, EVBREAK_ALL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ev_io_init(&rtty->ior, on_net_read, sock, EV_READ);
|
||||
ev_io_start(rtty->loop, &rtty->ior);
|
||||
|
||||
ev_io_init(&rtty->iow, on_net_write, sock, EV_WRITE);
|
||||
|
||||
if (rtty->ssl_on) {
|
||||
#ifdef KCP_SUPPORT
|
||||
assert(!rtty->kcp.on);
|
||||
#endif
|
||||
#ifdef SSL_SUPPORT
|
||||
rtty->ssl = ssl_session_new(rtty->ssl_ctx, sock);
|
||||
if (!rtty->ssl) {
|
||||
@@ -768,12 +798,23 @@ static void rtty_timer_cb(struct ev_loop *loop, struct ev_timer *w, int revents)
|
||||
|
||||
int rtty_start(struct rtty *rtty)
|
||||
{
|
||||
int ret;
|
||||
|
||||
rtty_run_state(RTTY_STATE_DISCONNECTED);
|
||||
|
||||
ev_init(&rtty->tmr, rtty_timer_cb);
|
||||
|
||||
if (tcp_connect(rtty->loop, rtty->host, rtty->port, on_net_connected, rtty) < 0
|
||||
&& !rtty->reconnect)
|
||||
#ifdef KCP_SUPPORT
|
||||
if (rtty->kcp.on) {
|
||||
rtty_kcp_init_cipher(&rtty->kcp);
|
||||
ret = udp_connect(rtty->loop, rtty->host, rtty->port, on_net_connected, rtty);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
ret = tcp_connect(rtty->loop, rtty->host, rtty->port, on_net_connected, rtty);
|
||||
}
|
||||
|
||||
if (ret < 0 && !rtty->reconnect)
|
||||
return -1;
|
||||
|
||||
INIT_LIST_HEAD(&rtty->ttys);
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
#include "ssl/ssl.h"
|
||||
#endif
|
||||
|
||||
#ifdef KCP_SUPPORT
|
||||
#include "kcp.h"
|
||||
#endif
|
||||
|
||||
#define RTTY_PROTO_VER 5
|
||||
#define RTTY_MAX_TTY 10
|
||||
#define RTTY_HEARTBEAT_TIMEOUT 3.0
|
||||
@@ -122,6 +126,9 @@ struct rtty {
|
||||
int ntty; /* tty number */
|
||||
struct list_head ttys;
|
||||
struct list_head http_conns;
|
||||
#ifdef KCP_SUPPORT
|
||||
struct rtty_kcp kcp;
|
||||
#endif
|
||||
};
|
||||
|
||||
int rtty_start(struct rtty *rtty);
|
||||
|
||||
Reference in New Issue
Block a user