Skip to content

Commit

Permalink
auto detect device when start
Browse files Browse the repository at this point in the history
add freebsd support
  • Loading branch information
nmq committed May 12, 2018
1 parent d621fa8 commit 4708238
Show file tree
Hide file tree
Showing 35 changed files with 918 additions and 416 deletions.
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[![Build Status](https://travis-ci.org/iceonsun/rsock.svg?branch=master)](https://travis-ci.org/iceonsun/rsock) [![Build status](https://ci.appveyor.com/api/projects/status/cqtcqeg2n2k0eivl?svg=true)](https://ci.appveyor.com/project/iceonsun/rsock)

-
---

### Introduction

Expand Down Expand Up @@ -44,29 +44,25 @@ done
It means allow client connects to server from port 10000 to 10010.
(**rsock use port range 10001-10010 by default. If you want to change the default value, please check Parameter Explanation section.**)

`sudo ./server_rsock_Linux -d eth0 -t 127.0.0.1:9999`
`sudo ./server_rsock_Linux -t 127.0.0.1:9999`

Parameter explanation:

eth0, name of network interface card of Internet, not LAN, e.g. eth1

127.0.0.1:9999, target address,aka address of kcptun server working on.

#### Client

Take mac as an example:

`sudo ./client_rsock_Darwin -d en0 --taddr=x.x.x.x -l 127.0.0.1:30000`
`sudo ./client_rsock_Darwin --taddr=x.x.x.x -l 127.0.0.1:30000`

Parameter explanation:

-d en0. name of network interface card of Internet, not LAN, e.g. eth0. For mac, it is typically en0 for wifi, eth1 for ethernet.

-t x.x.x.x , Address of rsock server。Attention. This is different from server. It only contains ip.

-l , local listened udp address, aka target address of kcptun client(the address specified by -t).

####NOTE
#### NOTE

1. If rsock doesn't work, you have to check whether your NIC supoorts winpcap. And routers may also filter packets, especially when you use Windows.

Expand All @@ -76,6 +72,8 @@ Parameter explanation:

4. For Windows users, rsock doesn't behave very well like it does on Linux and Mac. e.g. On Mac/Linux, rsock can support to watch 1080P youtube video smoothly. For windows users, rsock can only support 720P youtube video.

5. For Windows users, if your are running virtuam machines, you'd specify -d parameter as explained below.

### Exit

`ps axu|grep rsock`
Expand All @@ -87,12 +85,13 @@ Parameter explanation:
### Parameters in detail

```
-d, --dev=[device] name of network interface card of Internet.e.g,eth0,en0,eth1. Required.
-t, --taddr=[addr] target address. e.g. 8.8.8.8:88,7.7.7.7. Required.
-l, --ludp=[addr] local listened udp address. Only valid for client. Required by client.
-d, --dev=[device] name of network interface card of Internet.e.g,eth0, en0. rsock can auto detect right device to work on. Use this when the default can't work.
-h, --help Display help menu. Not available now.
-f json config file
--lcapIp=[ip] Internet IP. Can omit -d if this parameter sepcified.
--lcapIp=[ip] Internet IP. Can omit the -d if this parameter sepcified. rsock can auto detect right device to work on. Use this when the default can't work.
--unPath Local unix domain socket. Not available now.
-p, --ports=[...] tcp/udp port list for rsock server. e.g.10001,10010(2 ports); 10001-10010(11 ports); 80,443,10001-10010(12 ports). **NO** white spaces allowed. Default value: 10001-10010
--duration=[timeSec] Time for app connection to persist if no data is transfered in the app connection. unit: seconds. defalt 30s
Expand Down Expand Up @@ -225,6 +224,10 @@ If servers run normally, try to restart kcptun client(turn shadowsocks on/off, t

### TODO

1. Refactor code.

1. Auto detect network change

1. Add randomize port listening.

1. Add idle mode. Don't repeatedly connect to server if no data for a period.
Expand Down
70 changes: 39 additions & 31 deletions bean/RConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <iostream>
#include <fstream>
#include <os_util.h>

#include "plog/Log.h"

Expand All @@ -20,20 +21,25 @@ using namespace json11;

int RConfig::Parse(bool is_server, int argc, const char *const *argv) {
this->isServer = is_server;
ArgumentParser parser("This software is for study purpose only.", BuildExampleString());
ArgumentParser parser("This software is for study purpose only.",
BuildExampleString() + "version: " + param.version + "\n");


Group required(parser, "Required arguments");
ValueFlag<std::string> dev(required, "deviceName", "The network interface to work around.", {'d', "dev"});
ValueFlag<std::string> targetAddr(required, "target udp address",
"The target address.(e.g. client, 8.8.8.8 . server, 7.7.7.7:80. "
"Port is ignored if it's client.)", {'t', "taddr"}, "127.0.0.1:10030");
"Port is ignored if it's client.)", {'t', "taddr"}, "127.0.0.1:10030");

Group opt(parser, "Optional arguments");
ValueFlag<std::string> dev(opt, "deviceName",
"Specify the network interface to work around if default device can't work.",
{'d', "dev"});

HelpFlag help(opt, "help", "Display this help menu. You can see example usage below for help.", {'h', "help"});
ValueFlag<std::string> json(opt, "/path/to/config_file", "json config file path", {'f'});
ValueFlag<std::string> selfCapIp(opt, "", "Optional. Local capture IP. e.g: 192.168.1.4", {"lcapIp"});
ValueFlag<std::string> selfCapIp(opt, "",
"Specify local capture IP. e.g: 192.168.1.4, if default device can't work, especially for Windows users",
{"lcapIp"});
ValueFlag<std::string> localUn(opt, "", "Local listening unix domain socket path.(disabled currenty)", {"unPath"});

Group *groupForClient = &required;
Expand All @@ -46,23 +52,25 @@ int RConfig::Parse(bool is_server, int argc, const char *const *argv) {
{'l', "ludp"});

ValueFlag<std::string> capPorts(opt, "", "Capture port list. default(tcp: 10001-10005) "
"(e.g.3000,3001,4000-4050. No blank spaces or other characters allowed)", {'p', "ports"});
"(e.g.3000,3001,4000-4050. No blank spaces or other characters allowed)",
{'p', "ports"});
ValueFlag<uint32_t> duration(opt, "",
"Interval(sec) to invalid connection. Client need to set to same value with server. "
"(default 30s. min: 10s, max: 60s.)", {"duration"});
"(default 30s. min: 10s, max: 60s.)", {"duration"});
ValueFlag<std::string> key(opt, "HashKey", "Key to check validation of packet. (default hello1235)", {"hash"});
ValueFlag<std::string> type(opt, "tcp|udp|all",
"Type used to communicate with server. tcp for tcp only mode, udp for udp only mode. "
"all for both tcp and udp ", {"type"});
"all for both tcp and udp ", {"type"});
args::ValueFlag<int> daemon(opt, "daemon", "1 for running as daemon, 0 for not. (default 1)",
{"daemon"});
args::Flag verbose(opt, "verbose", "enable verbose mode", {'v'});
args::ValueFlag<std::string> flog(opt, "/path/to/log_file", "log file. default /var/log/rsock/", {"log"});

args::ValueFlag<uint16_t> cap_timeout(opt, "", "pcap timeout(ms). > 0 and <= 50", {"cap_timeout"});

args::ValueFlag<int> keepAlive(opt, "keepalive interval", "interval used to send keepalive request. default 5s."
, {"keepalive"});
args::ValueFlag<int> keepAlive(opt, "keepalive interval",
"interval used to send keepalive request. default 5s. no use right know",
{"keepalive"});
try {
parser.ParseCLI(argc, argv);
do {
Expand All @@ -78,14 +86,18 @@ int RConfig::Parse(bool is_server, int argc, const char *const *argv) {
if (dev) {
param.dev = dev.Get();
} else {
LOGI << "use default device: ", param.dev.c_str();
if (!selfCapIp) {
int nret = DefaultDev(param.dev);
if (nret || param.dev.empty()) {
throw args::Error("unable to find default device");
}
LOGI << "use default device: ", param.dev.c_str();
}
}

if (selfCapIp) {
param.selfCapIp = selfCapIp.Get();
if (!dev) {
devWithIpv4(param.dev, param.selfCapIp);
}
devWithIpv4(param.dev, param.selfCapIp);
}

if (capPorts) {
Expand Down Expand Up @@ -153,7 +165,6 @@ int RConfig::Parse(bool is_server, int argc, const char *const *argv) {
throw args::Error("keepalive must > 0: " + std::to_string(this->param.keepAliveInterval));
}
}

} while (false);

if (param.selfCapIp.empty()) {
Expand Down Expand Up @@ -182,7 +193,10 @@ int RConfig::Parse(bool is_server, int argc, const char *const *argv) {

void RConfig::CheckValidation(const RConfig &c) {
const RParam &p = c.param;
assert(!c.param.dev.empty());
if (c.param.dev.empty()) {
throw args::Error("device empty. Please specify a device!");
}
// assert(!c.param.dev.empty());

if (!c.isServer) {
assert(!p.localUdpIp.empty());;
Expand Down Expand Up @@ -263,9 +277,9 @@ void RConfig::parseJsonString(RConfig &c, const std::string &content, std::strin
}
if (o["lcapIp"].is_string()) {
p.selfCapIp = o["lcapIp"].string_value();
if (!o["dev"].is_string()) {
devWithIpv4(p.dev, p.selfCapIp);
}
if (!o["dev"].is_string()) {
devWithIpv4(p.dev, p.selfCapIp);
}
}
if (o["ports"].is_string()) {
auto s = o["ports"].string_value();
Expand Down Expand Up @@ -319,13 +333,13 @@ void RConfig::parseJsonString(RConfig &c, const std::string &content, std::strin
}

json11::Json RConfig::to_json() const {
auto j = Json::object {
auto j = Json::object{
{"daemon", isDaemon},
{"server", isServer},
{"verbose", log_level == plog::verbose},
{"log", log_path},
{
"param", Json::object {
"param", Json::object{
{"dev", param.dev},
{"unPath", param.selfUnPath},
{"ludp", isServer ? param.localUdpIp :
Expand Down Expand Up @@ -416,23 +430,17 @@ std::string RConfig::BuildExampleString() {
std::ostringstream out;
out << "Example usages:\n";
out << "server:\n";
out << "sudo ./server_rsock_Linux -d eth0" << " -t 127.0.0.1:8388 \n"
"###(note:replace 127.0.0.1:8388 with client kcptun target adddress)\n";
out << "sudo ./server_rsock_Linux" << " -t 127.0.0.1:8388 \n"
"###(note:replace 127.0.0.1:8388 with client kcptun target adddress)\n";

out << "client:\n";
#ifdef __MACH__
out << "sudo ./client_rsock_Darwin -d en0";
#elif _WIN32
out << "./client_rsock_Windows.exe --lcapIp=127.0.0.1:30000 ";
#else
out << "sudo ./client_rsock_Linux -d wlan0";
#endif
out << "sudo ./client_rsock_Darwin";

out << " -t x.x.x.x -l 127.0.0.1:8388\n";
out << "### (note:replace x.x.x.x with real server ip. "
"replace 127.0.0.1:8388 with your client kcptun target address.";
"replace 127.0.0.1:8388 with your client kcptun target address.";
out << " replace en0/wlan0 with your Internet(WAN) network interface card"
"(typically wlan0/eth0 for linux wireless/ethernet, en0 for macOS wireless, en1 for macOS ethernet)"
"(typically wlan0/eth0 for linux wireless/ethernet, en0 for macOS wireless, en1 for macOS ethernet)"
<< "\n";
out << "For more, please visit: https://github.com/iceonsun/rsock" << std::endl;

Expand Down
2 changes: 2 additions & 0 deletions bean/RConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ struct RConfig {
uint16_t cap_timeout = OM_PCAP_TIMEOUT;

int keepAliveInterval = 5; // default 5s, 3 times

const std::string version = RSOCK_BUILD_TIME;
};

// if turned to debug, speed of rsock will be very slow on macOS.
Expand Down
4 changes: 2 additions & 2 deletions build_release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function build_cross_binaries {

get_num_core
local num_core=$?
for chainfile in ${BUILD_DIR}/cmake/*.toolchain.cmake; do
for chainfile in ${BUILD_DIR}/cmake/Darwin_x86_64.toolchain.cmake ${BUILD_DIR}/cmake/Linux_x86_64.toolchain.cmake; do
echo "toolchain file: ${chainfile}"
local filename=$(basename "$chainfile")

Expand Down Expand Up @@ -90,4 +90,4 @@ function build_cross_binaries {
cd ${TOP_DIR}
}

build_cross_binaries
build_cross_binaries
6 changes: 2 additions & 4 deletions callbacks/ConnReset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,12 @@ int ConnReset::Input(uint8_t cmd, ssize_t nread, const rbuf_t &rbuf) {
}
return -1;
} else if (EncHead::TYPE_NETCONN_RST == cmd) {
if (nread > sizeof(IntKeyType)) {
if (nread >= sizeof(IntKeyType)) {
IntKeyType key;
auto p = base;
p = decode_uint32(&key, p);
LOGD << "intKey: " << key;
if (p) {
return mHelper->OnRecvNetconnRst(*info, key);
}
return mHelper->OnRecvNetconnRst(*info, key);
}
return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion callbacks/NetConnKeepAliveHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void NetConnKeepAliveHelper::onFlush() {
auto aCopy = mReqMap;
for (auto &e: aCopy) {
if (e.second >= MAX_RETRY) { // keep alive timeout
LOGE << "keepalive timeout";
LOGE << "keepalive timeout, key: " << e.first;
mAppGroup->onNetconnDead(e.first);
RemoveRequest(e.first);
}
Expand Down
4 changes: 3 additions & 1 deletion callbacks/NetConnKeepAliveHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class NetConnKeepAliveHelper : public INetConnKeepAlive::INetConnAliveHelper {
private:
const int MAX_RETRY = 3;
const uint32_t FLUSH_INTERVAL = 5000; // every 2sec
const uint32_t FIRST_FLUSH_DELAY = 5000; // on app start
// a problem is that, before first flush, if no data sent, this initial keepalive will
// result server reset sent to client, because server doesn't have record
const uint32_t FIRST_FLUSH_DELAY = 30000; // same with RConfig.keepAlive
IAppGroup *mAppGroup = nullptr;
uv_timer_t *mFlushTimer = nullptr;
std::map<IntKeyType, int> mReqMap;
Expand Down
11 changes: 4 additions & 7 deletions cap/RCap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ RCap::RCap(const std::string &dev, const std::string &selfIp, const RPortList &s
mDev = dev;
mSrcIp = srcIp;
mDstIp = selfIp;
mSrc = srcPorts;
mDest = selfPorts;
mSrcPorts = srcPorts;
mDestPorts = selfPorts;
mIsServer = server;
}

Expand Down Expand Up @@ -47,7 +47,7 @@ int RCap::Init() {
}
}

auto filterStr = BuildFilterStr("tcp", mSrcIp, mDstIp, mSrc, mDest, mIsServer);
auto filterStr = BuildFilterStr("tcp", mSrcIp, mDstIp, mSrcPorts, mDestPorts, mIsServer);
LOGD << "filter : " << filterStr;
if (filterStr.empty()) {
LOGE << "failed to build capture filter";
Expand Down Expand Up @@ -133,6 +133,7 @@ int RCap::Close() {
pcap_close(mCap);
mCap = nullptr;
}
mHandler = nullptr;
mDone = true;
return 0;
}
Expand All @@ -148,14 +149,10 @@ void RCap::SetCapHandler(pcap_handler handler, u_char *args) {
}

void RCap::HandlePkt(u_char *args, const struct pcap_pkthdr *hdr, const u_char *pkt) {
#ifndef NNDEBUG
assert(mHandler != nullptr);
#else
if (!mHandler) {
LOGE << "handler cannot be null";
return;
}
#endif
mHandler(args, hdr, pkt);
}

Expand Down
4 changes: 2 additions & 2 deletions cap/RCap.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class RCap {
std::string mDstIp;
std::string mDev;
pcap_t *mCap = nullptr;
RPortList mSrc;
RPortList mDest;
RPortList mSrcPorts;
RPortList mDestPorts;
bool mDone = false;
const int TIMEOUT;

Expand Down
Loading

0 comments on commit 4708238

Please sign in to comment.