This commit is contained in:
arm64v8a
2022-09-27 12:39:40 +08:00
parent 94c893b194
commit e44279742c
12 changed files with 193 additions and 101 deletions

View File

@@ -52,12 +52,10 @@ namespace NekoRay::fmt {
outbound["server"] = serverAddress; outbound["server"] = serverAddress;
outbound["server_port"] = serverPort; outbound["server_port"] = serverPort;
QJsonArray users; if (!username.isEmpty() && !password.isEmpty()) {
QJsonObject user; outbound["username"] = username;
user["username"] = username; outbound["password"] = password;
user["password"] = password; }
users.push_back(user);
if (!username.isEmpty() && !password.isEmpty()) outbound["users"] = users;
stream->BuildStreamSettingsSingBox(&outbound); stream->BuildStreamSettingsSingBox(&outbound);
result.outbound = outbound; result.outbound = outbound;

View File

@@ -2,15 +2,13 @@ package main
import ( import (
"context" "context"
"fmt" "io"
"log" "log"
"math/rand"
"neko/pkg/neko_common" "neko/pkg/neko_common"
"neko/pkg/neko_log"
"net" "net"
"net/http" "net/http"
"os"
"reflect" "reflect"
"strings"
"time" "time"
"unsafe" "unsafe"
@@ -27,8 +25,10 @@ var instance_cancel context.CancelFunc
// Use sing-box instead of libcore & v2ray // Use sing-box instead of libcore & v2ray
func setupCore() { func setupCore() {
neko_log.SetupLog(50*1024, "./neko.log")
//
log.SetFlags(log.LstdFlags) log.SetFlags(log.LstdFlags)
log.SetOutput(os.Stdout) log.SetOutput(neko_log.LogWriter)
// //
neko_common.GetProxyHttpClient = func() *http.Client { neko_common.GetProxyHttpClient = func() *http.Client {
return getProxyHttpClient(instance) return getProxyHttpClient(instance)
@@ -67,45 +67,19 @@ func getProxyHttpClient(box *box.Box) *http.Client {
return client return client
} }
// TODO move type logWriter struct {
func UrlTestSingBox(box *box.Box, link string, timeout int32) (int32, error) { files []io.Writer
client := getProxyHttpClient(box) }
if client == nil {
return 0, fmt.Errorf("no client") func (w *logWriter) Write(p []byte) (n int, err error) {
} for _, file := range w.files {
if file == nil {
// Test handshake time continue
var time_start time.Time }
var times = 1 n, err = file.Write(p)
var rtt_times = 1 if err != nil {
return
// Test RTT "true delay" }
if link2 := strings.TrimLeft(link, "true"); link != link2 { }
link = link2 return
times = 3
rtt_times = 2
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", link, nil)
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%84, rand.Int()%2))
if err != nil {
return 0, err
}
for i := 0; i < times; i++ {
if i == 1 || times == 1 {
time_start = time.Now()
}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Url test failed:", err)
return 0, err
}
resp.Body.Close()
}
return int32(time.Since(time_start).Milliseconds() / int64(rtt_times)), nil
} }

View File

@@ -3,13 +3,16 @@ package main
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"log" "log"
"neko/gen" "neko/gen"
"neko/pkg/grpc_server" "neko/pkg/grpc_server"
"neko/pkg/neko_common" "neko/pkg/neko_common"
"neko/pkg/neko_log"
"neko/pkg/speedtest"
"nekobox_core/box_main" "nekobox_core/box_main"
"net" "reflect"
"time" "unsafe"
box "github.com/sagernet/sing-box" box "github.com/sagernet/sing-box"
) )
@@ -39,6 +42,17 @@ func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.Err
} }
instance, instance_cancel, err = box_main.Create([]byte(in.CoreConfig), true) instance, instance_cancel, err = box_main.Create([]byte(in.CoreConfig), true)
// Logger
if instance != nil {
logFactory_ := reflect.Indirect(reflect.ValueOf(instance)).FieldByName("logFactory")
logFactory_ = reflect.NewAt(logFactory_.Type(), unsafe.Pointer(logFactory_.UnsafeAddr())).Elem() // get unexported logFactory
logFactory_ = logFactory_.Elem().Elem() // get struct
writer_ := logFactory_.FieldByName("writer")
writer_ = reflect.NewAt(writer_.Type(), unsafe.Pointer(writer_.UnsafeAddr())).Elem() // get unexported io.Writer
writer_.Set(reflect.ValueOf(neko_log.LogWriter))
}
return return
} }
@@ -93,27 +107,11 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
} }
} }
// Latency // Latency
out.Ms, err = UrlTestSingBox(i, in.Url, in.Timeout) out.Ms, err = speedtest.UrlTest(getProxyHttpClient(i), in.Url, in.Timeout)
} else if in.Mode == gen.TestMode_TcpPing { } else if in.Mode == gen.TestMode_TcpPing {
host, port, err := net.SplitHostPort(in.Address) out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout)
if err != nil {
out.Error = err.Error()
return
}
ip, err := net.ResolveIPAddr("ip", host)
if err != nil {
out.Error = err.Error()
return
}
//
startTime := time.Now()
_, err = net.DialTimeout("tcp", net.JoinHostPort(ip.String(), port), time.Duration(in.Timeout)*time.Millisecond)
endTime := time.Now()
if err == nil {
out.Ms = int32(endTime.Sub(startTime).Milliseconds())
}
} else { } else {
// TODO copy err = fmt.Errorf("not available")
} }
return return

View File

@@ -16,6 +16,7 @@ import (
var instance *libcore.V2RayInstance var instance *libcore.V2RayInstance
func setupCore() { func setupCore() {
// TODO del
device.IsNekoray = true device.IsNekoray = true
libcore.SetConfig("", false, true) libcore.SetConfig("", false, true)
libcore.InitCore("", "", "", nil, ".", "moe.nekoray.pc:bg", true, 50) libcore.InitCore("", "", "", nil, ".", "moe.nekoray.pc:bg", true, 50)

View File

@@ -11,6 +11,7 @@ import (
"neko/gen" "neko/gen"
"neko/pkg/grpc_server" "neko/pkg/grpc_server"
"neko/pkg/neko_common" "neko/pkg/neko_common"
"neko/pkg/speedtest"
"net" "net"
"strings" "strings"
"time" "time"
@@ -121,31 +122,15 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
// Latency // Latency
var t int32 var t int32
t, err = libcore.UrlTestV2ray(i, in.Inbound, in.Url, in.Timeout) t, err = speedtest.UrlTest(getProxyHttpClient(i), in.Address, in.Timeout)
out.Ms = t // sn: ms==0 是错误 out.Ms = t // sn: ms==0 是错误
} else if in.Mode == gen.TestMode_TcpPing { } else if in.Mode == gen.TestMode_TcpPing {
host, port, err := net.SplitHostPort(in.Address) out.Ms, err = speedtest.TcpPing(in.Address, in.Timeout)
if err != nil {
out.Error = err.Error()
return
}
ip, err := net.ResolveIPAddr("ip", host)
if err != nil {
out.Error = err.Error()
return
}
//
startTime := time.Now()
_, err = net.DialTimeout("tcp", net.JoinHostPort(ip.String(), port), time.Duration(in.Timeout)*time.Millisecond)
endTime := time.Now()
if err == nil {
out.Ms = int32(endTime.Sub(startTime).Milliseconds())
}
} else if in.Mode == gen.TestMode_FullTest { } else if in.Mode == gen.TestMode_FullTest {
if in.Config == nil { if in.Config == nil {
return return
} }
// TODO del
// Test instance // Test instance
i := libcore.NewV2rayInstance() i := libcore.NewV2rayInstance()
i.ForTest = true i.ForTest = true
@@ -164,7 +149,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
// Latency // Latency
var latency string var latency string
if in.FullLatency { if in.FullLatency {
t, _ := libcore.UrlTestV2ray(i, in.Inbound, in.Url, in.Timeout) t, _ := speedtest.UrlTest(getProxyHttpClient(i), in.Address, in.Timeout)
out.Ms = t out.Ms = t
if t > 0 { if t > 0 {
latency = fmt.Sprint(t, "ms") latency = fmt.Sprint(t, "ms")

51
go/pkg/neko_log/log.go Normal file
View File

@@ -0,0 +1,51 @@
package neko_log
import (
"fmt"
"io"
"os"
)
var f_neko_log *os.File
var LogWriter *logWriter
func SetupLog(maxSize int, path string) {
if f_neko_log != nil && LogWriter != nil {
return
}
// mod from libcore, simplify because only 1 proccess.
oldBytes, err := os.ReadFile(path)
if err == nil && len(oldBytes) > maxSize {
if os.Truncate(path, 0) == nil {
oldBytes = oldBytes[len(oldBytes)-maxSize:]
}
}
f_neko_log, err = os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0644)
if err == nil {
f_neko_log.Write(oldBytes)
} else {
fmt.Println("error open log", err)
}
//
LogWriter = &logWriter{
files: []io.Writer{os.Stdout, f_neko_log},
}
}
type logWriter struct {
files []io.Writer
}
func (w *logWriter) Write(p []byte) (n int, err error) {
for _, file := range w.files {
if file == nil {
continue
}
n, err = file.Write(p)
if err != nil {
return
}
}
return
}

View File

@@ -0,0 +1,72 @@
package speedtest
import (
"context"
"fmt"
"math/rand"
"net"
"net/http"
"strings"
"time"
)
func UrlTest(client *http.Client, link string, timeout int32) (int32, error) {
if client == nil {
return 0, fmt.Errorf("no client")
}
// Test handshake time
var time_start time.Time
var times = 1
var rtt_times = 1
// Test RTT "true delay"
if link2 := strings.TrimLeft(link, "true"); link != link2 {
link = link2
times = 3
rtt_times = 2
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", link, nil)
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%84, rand.Int()%2))
if err != nil {
return 0, err
}
for i := 0; i < times; i++ {
if i == 1 || times == 1 {
time_start = time.Now()
}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Url test failed:", err)
return 0, err
}
resp.Body.Close()
}
return int32(time.Since(time_start).Milliseconds() / int64(rtt_times)), nil
}
func TcpPing(address string, timeout int32) (ms int32, err error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return
}
ip, err := net.ResolveIPAddr("ip", host)
if err != nil {
return
}
//
startTime := time.Now()
c, err := net.DialTimeout("tcp", net.JoinHostPort(ip.String(), port), time.Duration(timeout)*time.Millisecond)
endTime := time.Now()
if err == nil {
ms = int32(endTime.Sub(startTime).Milliseconds())
c.Close()
}
return
}

View File

@@ -85,7 +85,7 @@ namespace NekoRay {
// Socks & HTTP Inbound // Socks & HTTP Inbound
QString inbound_address = "127.0.0.1"; QString inbound_address = "127.0.0.1";
int inbound_socks_port = 2080; int inbound_socks_port = 2080; // or Mixed
int inbound_http_port = -2081; int inbound_http_port = -2081;
QString custom_inbound = "{\"inbounds\": []}"; QString custom_inbound = "{\"inbounds\": []}";

View File

@@ -36,7 +36,10 @@ int main(int argc, char *argv[]) {
// Clean // Clean
QDir::setCurrent(QApplication::applicationDirPath()); QDir::setCurrent(QApplication::applicationDirPath());
if (QFile::exists("updater.old")) {
QFile::remove("updater.old"); QFile::remove("updater.old");
QFile::remove("sing-box.exe"); // v1.11
}
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
if (!QFile::exists("updater")) { if (!QFile::exists("updater")) {
QFile::link("launcher", "updater"); QFile::link("launcher", "updater");

View File

@@ -185,7 +185,7 @@ namespace NekoRay::rpc {
QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &request) { QString Client::Start(bool *rpcOK, const libcore::LoadConfigReq &request) {
libcore::ErrorResp reply; libcore::ErrorResp reply;
auto status = grpc_channel->Call("Start", request, &reply); auto status = grpc_channel->Call("Start", request, &reply, 3000);
if (status == QNetworkReply::NoError) { if (status == QNetworkReply::NoError) {
*rpcOK = true; *rpcOK = true;

View File

@@ -585,9 +585,13 @@ void MainWindow::neko_set_spmode(int mode, bool save) {
return; return;
} }
#endif #endif
SetSystemProxy("127.0.0.1", auto socks_port = NekoRay::dataStore->inbound_socks_port;
NekoRay::dataStore->inbound_http_port, auto http_port = NekoRay::dataStore->inbound_http_port;
NekoRay::dataStore->inbound_socks_port); if (IS_NEKO_BOX) {
http_port = socks_port;
socks_port = -1;
}
SetSystemProxy("127.0.0.1", http_port, socks_port);
} else if (mode == NekoRay::SystemProxyMode::VPN) { } else if (mode == NekoRay::SystemProxyMode::VPN) {
if (!StartVPNProcess()) { if (!StartVPNProcess()) {
refresh_status(); refresh_status();
@@ -974,7 +978,10 @@ void MainWindow::on_menu_profile_debug_info_triggered() {
} }
void MainWindow::on_menu_copy_links_triggered() { void MainWindow::on_menu_copy_links_triggered() {
if (ui->masterLogBrowser->hasFocus()) return; if (ui->masterLogBrowser->hasFocus()) {
ui->masterLogBrowser->copy();
return;
};
auto ents = get_now_selected(); auto ents = get_now_selected();
QStringList links; QStringList links;
for (const auto &ent: ents) { for (const auto &ent: ents) {
@@ -1227,6 +1234,9 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
case Qt::Key_Escape: case Qt::Key_Escape:
// take over by shortcut_esc // take over by shortcut_esc
break; break;
case Qt::Key_Enter:
neko_start();
break;
default: default:
QMainWindow::keyPressEvent(event); QMainWindow::keyPressEvent(event);
} }

View File

@@ -21,7 +21,7 @@ void MainWindow::setup_grpc() {
#ifndef NKR_NO_GRPC #ifndef NKR_NO_GRPC
// Setup Connection // Setup Connection
defaultClient = new Client([=](const QString &errStr) { defaultClient = new Client([=](const QString &errStr) {
showLog("gRPC Error: " + errStr); showLog("[Error] gRPC: " + errStr);
}, "127.0.0.1:" + Int2String(NekoRay::dataStore->core_port), NekoRay::dataStore->core_token); }, "127.0.0.1:" + Int2String(NekoRay::dataStore->core_port), NekoRay::dataStore->core_token);
auto t = new QTimer(); auto t = new QTimer();
connect(t, &QTimer::timeout, this, [=]() { connect(t, &QTimer::timeout, this, [=]() {