mirror of
https://github.com/MatsuriDayo/NekoBoxForAndroid.git
synced 2025-12-19 06:30:05 +08:00
optimize subscription import
This commit is contained in:
parent
893ba090f6
commit
0127c60906
@ -29,6 +29,7 @@ import kotlinx.coroutines.DEBUG_PROPERTY_NAME
|
|||||||
import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON
|
import kotlinx.coroutines.DEBUG_PROPERTY_VALUE_ON
|
||||||
import libcore.Libcore
|
import libcore.Libcore
|
||||||
import moe.matsuri.nb4a.NativeInterface
|
import moe.matsuri.nb4a.NativeInterface
|
||||||
|
import moe.matsuri.nb4a.net.LocalResolverImpl
|
||||||
import moe.matsuri.nb4a.utils.JavaUtil
|
import moe.matsuri.nb4a.utils.JavaUtil
|
||||||
import moe.matsuri.nb4a.utils.cleanWebview
|
import moe.matsuri.nb4a.utils.cleanWebview
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -78,7 +79,7 @@ class SagerNet : Application(),
|
|||||||
externalAssets.absolutePath + "/",
|
externalAssets.absolutePath + "/",
|
||||||
DataStore.logBufSize,
|
DataStore.logBufSize,
|
||||||
DataStore.logLevel > 0,
|
DataStore.logLevel > 0,
|
||||||
nativeInterface, nativeInterface
|
nativeInterface, nativeInterface, LocalResolverImpl
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isMainProcess) {
|
if (isMainProcess) {
|
||||||
|
|||||||
@ -58,6 +58,7 @@ object RawUpdater : GroupUpdater() {
|
|||||||
|
|
||||||
val response = Libcore.newHttpClient().apply {
|
val response = Libcore.newHttpClient().apply {
|
||||||
trySocks5(DataStore.mixedPort)
|
trySocks5(DataStore.mixedPort)
|
||||||
|
tryH3Direct()
|
||||||
when (DataStore.appTLSVersion) {
|
when (DataStore.appTLSVersion) {
|
||||||
"1.3" -> restrictedTLS()
|
"1.3" -> restrictedTLS()
|
||||||
}
|
}
|
||||||
@ -73,6 +74,17 @@ object RawUpdater : GroupUpdater() {
|
|||||||
|
|
||||||
subscription.subscriptionUserinfo =
|
subscription.subscriptionUserinfo =
|
||||||
Util.getStringBox(response.getHeader("Subscription-Userinfo"))
|
Util.getStringBox(response.getHeader("Subscription-Userinfo"))
|
||||||
|
|
||||||
|
// 修改默认名字
|
||||||
|
if (proxyGroup.name?.startsWith("Subscription #") == true) {
|
||||||
|
var remoteName = Util.getStringBox(response.getHeader("content-disposition"))
|
||||||
|
if (remoteName.isNotBlank()) {
|
||||||
|
remoteName = Util.decodeFilename(remoteName)
|
||||||
|
if (remoteName.isNotBlank()) {
|
||||||
|
proxyGroup.name = remoteName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val proxiesMap = LinkedHashMap<String, AbstractBean>()
|
val proxiesMap = LinkedHashMap<String, AbstractBean>()
|
||||||
|
|||||||
@ -216,7 +216,6 @@ class AboutFragment : ToolbarFragment(R.layout.layout_about) {
|
|||||||
try {
|
try {
|
||||||
val client = Libcore.newHttpClient().apply {
|
val client = Libcore.newHttpClient().apply {
|
||||||
modernTLS()
|
modernTLS()
|
||||||
keepAlive()
|
|
||||||
trySocks5(DataStore.mixedPort)
|
trySocks5(DataStore.mixedPort)
|
||||||
}
|
}
|
||||||
val response = client.newRequest().apply {
|
val response = client.newRequest().apply {
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import android.content.Context
|
|||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import libcore.StringBox
|
import libcore.StringBox
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.Deflater
|
import java.util.zip.Deflater
|
||||||
@ -188,4 +190,11 @@ object Util {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun decodeFilename(headerValue: String): String {
|
||||||
|
val regex = Regex("filename\\*=[^']*''(.+)")
|
||||||
|
val match = regex.find(headerValue)
|
||||||
|
val encoded = match?.groupValues?.get(1) ?: ""
|
||||||
|
return URLDecoder.decode(encoded, StandardCharsets.UTF_8.name())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,8 @@ type LocalDNSTransport interface {
|
|||||||
Exchange(ctx *ExchangeContext, message []byte) error
|
Exchange(ctx *ExchangeContext, message []byte) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var gLocalDNSTransport *platformLocalDNSTransport = nil
|
||||||
|
|
||||||
type platformLocalDNSTransport struct {
|
type platformLocalDNSTransport struct {
|
||||||
iif LocalDNSTransport
|
iif LocalDNSTransport
|
||||||
tag string
|
tag string
|
||||||
|
|||||||
83
libcore/ech/ech.go
Normal file
83
libcore/ech/ech.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package ech
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/base64"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
mDNS "github.com/miekg/dns"
|
||||||
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
"github.com/sagernet/sing-box/dns"
|
||||||
|
"github.com/sagernet/sing/common/exceptions"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ECHClientConfig struct {
|
||||||
|
*tls.Config
|
||||||
|
domain string
|
||||||
|
localDnsTransport adapter.DNSTransport
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewECHClientConfig(domain string, tlsConfig *tls.Config, localDnsTransport adapter.DNSTransport) *ECHClientConfig {
|
||||||
|
config := tlsConfig.Clone()
|
||||||
|
config.ServerName = domain
|
||||||
|
return &ECHClientConfig{
|
||||||
|
Config: config,
|
||||||
|
domain: domain,
|
||||||
|
localDnsTransport: localDnsTransport,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClientHandshake 封装 TLS 握手
|
||||||
|
func (s *ECHClientConfig) ClientHandshake(ctx context.Context, conn net.Conn) (*tls.Conn, error) {
|
||||||
|
tlsConn, err := s.fetchAndHandshake(ctx, conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = tlsConn.HandshakeContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return tlsConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchAndHandshake 查询 ECHConfigList 并完成 TLS 连接
|
||||||
|
func (s *ECHClientConfig) fetchAndHandshake(ctx context.Context, conn net.Conn) (*tls.Conn, error) {
|
||||||
|
message := &mDNS.Msg{
|
||||||
|
MsgHdr: mDNS.MsgHdr{
|
||||||
|
RecursionDesired: true,
|
||||||
|
},
|
||||||
|
Question: []mDNS.Question{
|
||||||
|
{
|
||||||
|
Name: mDNS.Fqdn(s.domain),
|
||||||
|
Qtype: mDNS.TypeHTTPS,
|
||||||
|
Qclass: mDNS.ClassINET,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if s.localDnsTransport == nil {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
response, err := s.localDnsTransport.Exchange(ctx, message)
|
||||||
|
if err != nil {
|
||||||
|
return nil, exceptions.Cause(err, "fetch ECH config list")
|
||||||
|
}
|
||||||
|
if response.Rcode != mDNS.RcodeSuccess {
|
||||||
|
return nil, exceptions.Cause(dns.RcodeError(response.Rcode), "fetch ECH config list")
|
||||||
|
}
|
||||||
|
for _, rr := range response.Answer {
|
||||||
|
switch resource := rr.(type) {
|
||||||
|
case *mDNS.HTTPS:
|
||||||
|
for _, value := range resource.Value {
|
||||||
|
if value.Key().String() == "ech" {
|
||||||
|
echConfigList, err := base64.StdEncoding.DecodeString(value.String())
|
||||||
|
if err == nil {
|
||||||
|
s.Config.EncryptedClientHelloConfigList = echConfigList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tls.Client(conn, s.Config), nil
|
||||||
|
}
|
||||||
@ -8,6 +8,7 @@ require (
|
|||||||
github.com/matsuridayo/libneko v1.0.0 // replaced
|
github.com/matsuridayo/libneko v1.0.0 // replaced
|
||||||
github.com/miekg/dns v1.1.67
|
github.com/miekg/dns v1.1.67
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1
|
github.com/oschwald/maxminddb-golang v1.13.1
|
||||||
|
github.com/sagernet/quic-go v0.52.0-beta.1
|
||||||
github.com/sagernet/sing v0.7.6-0.20250825114712-2aeec120ce28
|
github.com/sagernet/sing v0.7.6-0.20250825114712-2aeec120ce28
|
||||||
github.com/sagernet/sing-box v1.0.0 // replaced
|
github.com/sagernet/sing-box v1.0.0 // replaced
|
||||||
github.com/sagernet/sing-tun v0.7.0-beta.1
|
github.com/sagernet/sing-tun v0.7.0-beta.1
|
||||||
@ -51,7 +52,6 @@ require (
|
|||||||
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb // indirect
|
github.com/sagernet/gvisor v0.0.0-20250325023245-7a9c0f5725fb // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||||
github.com/sagernet/quic-go v0.52.0-beta.1 // indirect
|
|
||||||
github.com/sagernet/sing-mux v0.3.3 // indirect
|
github.com/sagernet/sing-mux v0.3.3 // indirect
|
||||||
github.com/sagernet/sing-quic v0.5.0 // indirect
|
github.com/sagernet/sing-quic v0.5.0 // indirect
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.8 // indirect
|
github.com/sagernet/sing-shadowsocks v0.2.8 // indirect
|
||||||
|
|||||||
176
libcore/http.go
176
libcore/http.go
@ -10,24 +10,34 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"libcore/device"
|
||||||
|
"libcore/ech"
|
||||||
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/quic-go"
|
||||||
|
"github.com/sagernet/quic-go/http3"
|
||||||
"github.com/sagernet/sing/common/metadata"
|
"github.com/sagernet/sing/common/metadata"
|
||||||
"github.com/sagernet/sing/protocol/socks"
|
"github.com/sagernet/sing/protocol/socks"
|
||||||
"github.com/sagernet/sing/protocol/socks/socks5"
|
"github.com/sagernet/sing/protocol/socks/socks5"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errFailConnectSocks5 = errors.New("fail connect socks5")
|
||||||
|
|
||||||
type HTTPClient interface {
|
type HTTPClient interface {
|
||||||
RestrictedTLS()
|
RestrictedTLS()
|
||||||
ModernTLS()
|
ModernTLS()
|
||||||
PinnedTLS12()
|
PinnedTLS12()
|
||||||
PinnedSHA256(sumHex string)
|
PinnedSHA256(sumHex string)
|
||||||
TrySocks5(port int32)
|
TrySocks5(port int32)
|
||||||
|
TryH3Direct()
|
||||||
KeepAlive()
|
KeepAlive()
|
||||||
NewRequest() HTTPRequest
|
NewRequest() HTTPRequest
|
||||||
Close()
|
Close()
|
||||||
@ -58,16 +68,18 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type httpClient struct {
|
type httpClient struct {
|
||||||
tls tls.Config
|
tls tls.Config
|
||||||
client http.Client
|
h1h2Transport http.Transport
|
||||||
transport http.Transport
|
h1h2Client http.Client
|
||||||
|
trySocks5 bool
|
||||||
|
tryH3Direct bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHttpClient() HTTPClient {
|
func NewHttpClient() HTTPClient {
|
||||||
client := new(httpClient)
|
client := new(httpClient)
|
||||||
client.client.Transport = &client.transport
|
client.h1h2Client.Transport = &client.h1h2Transport
|
||||||
client.transport.TLSClientConfig = &client.tls
|
client.h1h2Transport.TLSClientConfig = &client.tls
|
||||||
client.transport.DisableKeepAlives = true
|
client.h1h2Transport.DisableKeepAlives = true
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,25 +116,36 @@ func (c *httpClient) PinnedSHA256(sumHex string) {
|
|||||||
|
|
||||||
func (c *httpClient) TrySocks5(port int32) {
|
func (c *httpClient) TrySocks5(port int32) {
|
||||||
dialer := new(net.Dialer)
|
dialer := new(net.Dialer)
|
||||||
c.transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
c.h1h2Transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
for {
|
for {
|
||||||
socksConn, err := dialer.DialContext(ctx, "tcp", "127.0.0.1:"+strconv.Itoa(int(port)))
|
socksConn, err := dialer.DialContext(ctx, "tcp", "127.0.0.1:"+strconv.Itoa(int(port)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.tryH3Direct {
|
||||||
|
return nil, errFailConnectSocks5
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
_, err = socks.ClientHandshake5(socksConn, socks5.CommandConnect, metadata.ParseSocksaddr(addr), "", "")
|
_, err = socks.ClientHandshake5(socksConn, socks5.CommandConnect, metadata.ParseSocksaddr(addr), "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if c.tryH3Direct {
|
||||||
|
return nil, errFailConnectSocks5
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return socksConn, err
|
return socksConn, err
|
||||||
}
|
}
|
||||||
return dialer.DialContext(ctx, network, addr)
|
return dialer.DialContext(ctx, network, addr)
|
||||||
}
|
}
|
||||||
|
c.trySocks5 = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *httpClient) TryH3Direct() {
|
||||||
|
c.tryH3Direct = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) KeepAlive() {
|
func (c *httpClient) KeepAlive() {
|
||||||
c.transport.ForceAttemptHTTP2 = true
|
c.h1h2Transport.ForceAttemptHTTP2 = true
|
||||||
c.transport.DisableKeepAlives = false
|
c.h1h2Transport.DisableKeepAlives = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) NewRequest() HTTPRequest {
|
func (c *httpClient) NewRequest() HTTPRequest {
|
||||||
@ -135,7 +158,7 @@ func (c *httpClient) NewRequest() HTTPRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) Close() {
|
func (c *httpClient) Close() {
|
||||||
c.transport.CloseIdleConnections()
|
c.h1h2Transport.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRequest struct {
|
type httpRequest struct {
|
||||||
@ -184,8 +207,16 @@ func (r *httpRequest) SetContentString(content string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *httpRequest) Execute() (HTTPResponse, error) {
|
func (r *httpRequest) Execute() (HTTPResponse, error) {
|
||||||
response, err := r.client.Do(&r.request)
|
// full direct
|
||||||
|
if r.tryH3Direct && !r.trySocks5 {
|
||||||
|
return r.doH3Direct()
|
||||||
|
}
|
||||||
|
response, err := r.h1h2Client.Do(&r.request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// trySocks5 && tryH3Direct
|
||||||
|
if r.tryH3Direct && errors.Is(err, errFailConnectSocks5) {
|
||||||
|
return r.doH3Direct()
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
httpResp := &httpResponse{Response: response}
|
httpResp := &httpResponse{Response: response}
|
||||||
@ -195,6 +226,129 @@ func (r *httpRequest) Execute() (HTTPResponse, error) {
|
|||||||
return httpResp, nil
|
return httpResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type requestFunc func() (response *http.Response, err error)
|
||||||
|
|
||||||
|
func (r *httpRequest) doH3Direct() (HTTPResponse, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
successCh := make(chan *http.Response, 1)
|
||||||
|
var finalErr error
|
||||||
|
var failedCount atomic.Uint32
|
||||||
|
var successCount atomic.Uint32
|
||||||
|
var mu sync.Mutex
|
||||||
|
|
||||||
|
funcs := []requestFunc{
|
||||||
|
// 普通,不再重试 socks5
|
||||||
|
func() (response *http.Response, err error) {
|
||||||
|
request := r.request.Clone(context.Background())
|
||||||
|
h1h2Client := &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return h1h2Client.Do(request)
|
||||||
|
},
|
||||||
|
// ECH HTTPS
|
||||||
|
func() (response *http.Response, err error) {
|
||||||
|
request := r.request.Clone(context.Background())
|
||||||
|
echClient := &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
var d net.Dialer
|
||||||
|
c, err := d.DialContext(ctx, network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
domain := addr
|
||||||
|
if host, _, _ := net.SplitHostPort(addr); host != "" {
|
||||||
|
domain = host
|
||||||
|
}
|
||||||
|
echTls := ech.NewECHClientConfig(domain, &r.tls, gLocalDNSTransport)
|
||||||
|
return echTls.ClientHandshake(ctx, c)
|
||||||
|
},
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return echClient.Do(request)
|
||||||
|
},
|
||||||
|
// H3
|
||||||
|
func() (response *http.Response, err error) {
|
||||||
|
request := r.request.Clone(context.Background())
|
||||||
|
h3Client := &http.Client{
|
||||||
|
Transport: &http3.Transport{
|
||||||
|
TLSClientConfig: r.tls.Clone(),
|
||||||
|
QUICConfig: &quic.Config{
|
||||||
|
MaxIdleTimeout: time.Second,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return h3Client.Do(request)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, f := range funcs {
|
||||||
|
go func(f requestFunc) {
|
||||||
|
defer device.DeferPanicToError("http", func(err error) {
|
||||||
|
log.Println(err)
|
||||||
|
})
|
||||||
|
defer func() {
|
||||||
|
if successCount.Load() == 0 {
|
||||||
|
if failedCount.Add(1) >= uint32(len(funcs)) {
|
||||||
|
// 全部失败了
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var t string
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
t = "h1h2"
|
||||||
|
case 1:
|
||||||
|
t = "ech"
|
||||||
|
case 2:
|
||||||
|
t = "h3"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行HTTP请求
|
||||||
|
rsp, err := f()
|
||||||
|
if rsp == nil || err != nil {
|
||||||
|
mu.Lock()
|
||||||
|
finalErr = errors.Join(finalErr, fmt.Errorf("%s: %w", t, err))
|
||||||
|
mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理 HTTP 状态码
|
||||||
|
if rsp.StatusCode != http.StatusOK {
|
||||||
|
hr := &httpResponse{Response: rsp}
|
||||||
|
err = errors.Join(finalErr, fmt.Errorf("%s: %s", t, hr.errorString()))
|
||||||
|
mu.Lock()
|
||||||
|
finalErr = err
|
||||||
|
mu.Unlock()
|
||||||
|
rsp.Body.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case successCh <- rsp:
|
||||||
|
// 第一个成功的请求,不要关闭 body
|
||||||
|
successCount.Add(1)
|
||||||
|
default:
|
||||||
|
rsp.Body.Close()
|
||||||
|
}
|
||||||
|
}(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case result := <-successCh:
|
||||||
|
return &httpResponse{Response: result}, nil
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, finalErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type httpResponse struct {
|
type httpResponse struct {
|
||||||
*http.Response
|
*http.Response
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ func ForceGc() {
|
|||||||
|
|
||||||
func InitCore(process, cachePath, internalAssets, externalAssets string,
|
func InitCore(process, cachePath, internalAssets, externalAssets string,
|
||||||
maxLogSizeKb int32, logEnable bool,
|
maxLogSizeKb int32, logEnable bool,
|
||||||
if1 NB4AInterface, if2 BoxPlatformInterface,
|
if1 NB4AInterface, if2 BoxPlatformInterface, if3 LocalDNSTransport,
|
||||||
) {
|
) {
|
||||||
defer device.DeferPanicToError("InitCore", func(err error) { log.Println(err) })
|
defer device.DeferPanicToError("InitCore", func(err error) { log.Println(err) })
|
||||||
isBgProcess = strings.HasSuffix(process, ":bg")
|
isBgProcess = strings.HasSuffix(process, ":bg")
|
||||||
@ -43,6 +43,7 @@ func InitCore(process, cachePath, internalAssets, externalAssets string,
|
|||||||
intfNB4A = if1
|
intfNB4A = if1
|
||||||
intfBox = if2
|
intfBox = if2
|
||||||
useProcfs = intfBox.UseProcFS()
|
useProcfs = intfBox.UseProcFS()
|
||||||
|
gLocalDNSTransport = &platformLocalDNSTransport{iif: if3}
|
||||||
|
|
||||||
// Working dir
|
// Working dir
|
||||||
tmp := filepath.Join(cachePath, "../no_backup")
|
tmp := filepath.Join(cachePath, "../no_backup")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user