Mult Port + TCP Calibration (SSH DEAD)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -37,6 +38,7 @@ type bpLane struct {
|
||||
tcpBuffer int
|
||||
reconnectEvery int
|
||||
timeout time.Duration
|
||||
headerMask byte
|
||||
coverProfile cover.Profile
|
||||
autoReconnect bool
|
||||
pc *bpPhysicalConn
|
||||
@@ -44,6 +46,10 @@ type bpLane struct {
|
||||
}
|
||||
|
||||
func newBPLane(serverAddr string, tcpBuffer, reconnectEvery int, timeout time.Duration, coverProfile cover.Profile) *bpLane {
|
||||
return newBPLaneWithMask(serverAddr, tcpBuffer, reconnectEvery, timeout, coverProfile.HeaderMask, coverProfile)
|
||||
}
|
||||
|
||||
func newBPLaneWithMask(serverAddr string, tcpBuffer, reconnectEvery int, timeout time.Duration, headerMask byte, coverProfile cover.Profile) *bpLane {
|
||||
autoReconnect := reconnectEvery == 1
|
||||
if autoReconnect {
|
||||
reconnectEvery = 0
|
||||
@@ -53,6 +59,7 @@ func newBPLane(serverAddr string, tcpBuffer, reconnectEvery int, timeout time.Du
|
||||
tcpBuffer: tcpBuffer,
|
||||
reconnectEvery: reconnectEvery,
|
||||
timeout: timeout,
|
||||
headerMask: headerMask,
|
||||
coverProfile: coverProfile,
|
||||
autoReconnect: autoReconnect,
|
||||
}
|
||||
@@ -172,7 +179,7 @@ func (l *bpLane) single(mode byte, sid wire.SessionID, seq uint64, payload []byt
|
||||
}
|
||||
reused := l.pc.requests > 0
|
||||
_ = l.pc.conn.SetDeadline(time.Now().Add(timeout))
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, seq, payload, downloadHint, l.coverProfile.HeaderMask, l.coverProfile.Clear); err != nil {
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, seq, payload, downloadHint, l.headerMask, l.coverProfile.Clear); err != nil {
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return 0, nil, err
|
||||
@@ -180,7 +187,7 @@ func (l *bpLane) single(mode byte, sid wire.SessionID, seq uint64, payload []byt
|
||||
lastErr = err
|
||||
continue
|
||||
}
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, seq, l.coverProfile.HeaderMask, l.coverProfile.Clear)
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, seq, l.headerMask, l.coverProfile.Clear)
|
||||
if err != nil {
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
@@ -197,6 +204,31 @@ func (l *bpLane) single(mode byte, sid wire.SessionID, seq uint64, payload []byt
|
||||
return 0, nil, fmt.Errorf("BP request failed after reconnect: %w", lastErr)
|
||||
}
|
||||
|
||||
// probeBPProfile validates one BP header/cover profile with a single small
|
||||
// BHP1 echo transaction. It deliberately does not register/open a target
|
||||
// session; authenticated DTP2 calibration runs immediately after profile
|
||||
// selection and remains authoritative for the configured server token.
|
||||
func probeBPProfile(serverAddr string, opts chunkClientOptions) bool {
|
||||
sid, err := randomSessionID()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
timeout := opts.txnTimeout
|
||||
if timeout <= 0 || timeout > profileProbeTimeout {
|
||||
timeout = profileProbeTimeout
|
||||
}
|
||||
lane := newBPLaneWithMask(serverAddr, opts.tcpBuffer, 1, timeout, opts.headerMask, opts.coverProfile)
|
||||
defer lane.Close()
|
||||
|
||||
payload := make([]byte, 10)
|
||||
copy(payload[:4], []byte("BHP1"))
|
||||
payload[4] = 1
|
||||
payload[5] = bpModeUpload
|
||||
binary.BigEndian.PutUint32(payload[6:10], 0)
|
||||
status, body, err := lane.single(bpModeProbe, sid, 0, payload, 0)
|
||||
return err == nil && status == wire.StatusOK && bytes.Equal(body, payload)
|
||||
}
|
||||
|
||||
func decodeBPData(body []byte) ([]byte, error) {
|
||||
if len(body) < 4 {
|
||||
return nil, fmt.Errorf("short BP DATA body")
|
||||
@@ -240,7 +272,7 @@ func (l *bpLane) download(sid wire.SessionID, offset uint64, maxChunk, count int
|
||||
}
|
||||
reused := l.pc.requests > 0
|
||||
_ = l.pc.conn.SetDeadline(time.Now().Add(timeout))
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, offset, payload, hint, l.coverProfile.HeaderMask, l.coverProfile.Clear); err != nil {
|
||||
if err := writeBPRequest(l.pc.conn, mode, sid, offset, payload, hint, l.headerMask, l.coverProfile.Clear); err != nil {
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
return nil, 0, err
|
||||
@@ -252,7 +284,7 @@ func (l *bpLane) download(sid wire.SessionID, offset uint64, maxChunk, count int
|
||||
out := make([][]byte, 0, responses)
|
||||
lastStatus := wire.StatusOK
|
||||
for i := 0; i < responses; i++ {
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, offset, l.coverProfile.HeaderMask, l.coverProfile.Clear)
|
||||
status, body, err := readBPResponse(l.pc.conn, sid, mode, offset, l.headerMask, l.coverProfile.Clear)
|
||||
if err != nil {
|
||||
l.transportFailureLocked(reused)
|
||||
if isTransportTimeout(err) {
|
||||
@@ -327,9 +359,15 @@ func openBPTunnel(serverAddr, token, targetHost string, targetPort int, opts chu
|
||||
if opts.startSize < opts.minSize || opts.startSize > opts.maxSize {
|
||||
opts.startSize = opts.maxSize
|
||||
}
|
||||
if opts.forceMaxStart {
|
||||
opts.startSize = opts.maxSize
|
||||
}
|
||||
if opts.txnTimeout <= 0 {
|
||||
opts.txnTimeout = 5 * time.Second
|
||||
}
|
||||
if opts.shrinkAfter < 1 {
|
||||
opts.shrinkAfter = 1
|
||||
}
|
||||
if opts.maxPipeline < 1 {
|
||||
opts.maxPipeline = 1
|
||||
}
|
||||
@@ -347,11 +385,24 @@ func openBPTunnel(serverAddr, token, targetHost string, targetPort int, opts chu
|
||||
reconnect = 0
|
||||
}
|
||||
|
||||
profile := pathProfile{
|
||||
upload: opts.startSize,
|
||||
download: opts.startSize,
|
||||
persistent: false,
|
||||
at: time.Now(),
|
||||
}
|
||||
if !opts.skipPathProbe {
|
||||
// BP uses the same binary framing sizes and cover preface as the native B
|
||||
// transport. Reuse the authenticated DTP2 probe machinery to calibrate
|
||||
// the carrier before BP starts moving SSH/application data.
|
||||
profile = getPathProfile(serverAddr, token, opts)
|
||||
}
|
||||
|
||||
sid, err := randomSessionID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uploadLane := newBPLane(serverAddr, opts.tcpBuffer, reconnect, opts.txnTimeout, opts.coverProfile)
|
||||
uploadLane := newBPLaneWithMask(serverAddr, opts.tcpBuffer, reconnect, opts.txnTimeout, opts.headerMask, opts.coverProfile)
|
||||
status, body, err := uploadLane.single(bpModeUpload, sid, 0, nil, 0)
|
||||
if err != nil {
|
||||
uploadLane.Close()
|
||||
@@ -389,11 +440,25 @@ func openBPTunnel(serverAddr, token, targetHost string, targetPort int, opts chu
|
||||
sid: sid,
|
||||
opts: opts,
|
||||
uploadLane: uploadLane,
|
||||
downloadLane: newBPLane(serverAddr, opts.tcpBuffer, reconnect, opts.txnTimeout, opts.coverProfile),
|
||||
downloadLane: newBPLaneWithMask(serverAddr, opts.tcpBuffer, reconnect, opts.txnTimeout, opts.headerMask, opts.coverProfile),
|
||||
pipeline: opts.maxPipeline,
|
||||
}
|
||||
c.upSizer = newAdaptiveSizer("BP upload", opts.startSize, opts)
|
||||
c.downSizer = newAdaptiveSizer("BP download", opts.startSize, opts)
|
||||
upStart := minInt(profile.upload, opts.maxSize)
|
||||
downStart := minInt(profile.download, opts.maxSize)
|
||||
if upStart < opts.minSize {
|
||||
upStart = opts.minSize
|
||||
}
|
||||
if downStart < opts.minSize {
|
||||
downStart = opts.minSize
|
||||
}
|
||||
upSizerOpts := opts
|
||||
downSizerOpts := opts
|
||||
if !opts.skipPathProbe {
|
||||
upSizerOpts.maxSize = upStart
|
||||
downSizerOpts.maxSize = downStart
|
||||
}
|
||||
c.upSizer = newAdaptiveSizer("BP upload", upStart, upSizerOpts)
|
||||
c.downSizer = newAdaptiveSizer("BP download", downStart, downSizerOpts)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user