Mult Port + TCP Calibration (SSH DEAD)
This commit is contained in:
@@ -14,12 +14,13 @@ import (
|
||||
)
|
||||
|
||||
type streamSession struct {
|
||||
sid wire.SessionID
|
||||
target net.Conn
|
||||
targetName string
|
||||
maxChunk int
|
||||
maxBuffer int
|
||||
debug *serverDebug
|
||||
sid wire.SessionID
|
||||
target net.Conn
|
||||
targetName string
|
||||
maxChunk int
|
||||
maxBuffer int
|
||||
debug *serverDebug
|
||||
bulkCoalesce bool
|
||||
|
||||
mu sync.Mutex
|
||||
notify chan struct{}
|
||||
@@ -33,16 +34,17 @@ type streamSession struct {
|
||||
expectedUp uint64
|
||||
}
|
||||
|
||||
func newStreamSession(sid wire.SessionID, target net.Conn, targetName string, maxChunk, maxBuffer int, debug *serverDebug) *streamSession {
|
||||
func newStreamSession(sid wire.SessionID, target net.Conn, targetName string, maxChunk, maxBuffer int, bulkCoalesce bool, debug *serverDebug) *streamSession {
|
||||
s := &streamSession{
|
||||
sid: sid,
|
||||
target: target,
|
||||
targetName: targetName,
|
||||
maxChunk: maxChunk,
|
||||
maxBuffer: maxBuffer,
|
||||
debug: debug,
|
||||
notify: make(chan struct{}),
|
||||
lastSeen: time.Now(),
|
||||
sid: sid,
|
||||
target: target,
|
||||
targetName: targetName,
|
||||
maxChunk: maxChunk,
|
||||
maxBuffer: maxBuffer,
|
||||
debug: debug,
|
||||
bulkCoalesce: bulkCoalesce,
|
||||
notify: make(chan struct{}),
|
||||
lastSeen: time.Now(),
|
||||
}
|
||||
go s.readTarget()
|
||||
return s
|
||||
@@ -155,14 +157,34 @@ func (s *streamSession) readAt(offset uint64, limit int, wait time.Duration) ([]
|
||||
if firstDataAt.IsZero() {
|
||||
firstDataAt = time.Now()
|
||||
}
|
||||
// Coalesce tiny target reads briefly. This prevents a 1-2 byte
|
||||
// producer read from becoming a permanent tiny tunnel record.
|
||||
if available < limit && !s.eof && wait > 0 && time.Since(firstDataAt) < 2*time.Millisecond {
|
||||
// SSH packetization naturally feeds this stream in ~tens-of-KiB
|
||||
// bursts. Returning the first burst turns a DragonTCP download into
|
||||
// one SSH packet per WAN RTT. Internal carrier sessions therefore
|
||||
// get a slightly wider coalescing window and can accumulate at least
|
||||
// 512 KiB before the pull response is emitted. Ordinary destinations
|
||||
// retain the original 2 ms latency-oriented behavior.
|
||||
coalesceDelay := 2 * time.Millisecond
|
||||
coalesceGoal := limit
|
||||
if s.bulkCoalesce {
|
||||
coalesceDelay = 25 * time.Millisecond
|
||||
coalesceGoal = 512 * 1024
|
||||
if coalesceGoal > limit {
|
||||
coalesceGoal = limit
|
||||
}
|
||||
}
|
||||
elapsed := time.Since(firstDataAt)
|
||||
if available < limit && available < coalesceGoal && !s.eof && wait > 0 && elapsed < coalesceDelay {
|
||||
ch := s.notify
|
||||
remaining := coalesceDelay - elapsed
|
||||
if untilDeadline := time.Until(deadline); untilDeadline < remaining {
|
||||
remaining = untilDeadline
|
||||
}
|
||||
s.mu.Unlock()
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(2 * time.Millisecond):
|
||||
if remaining > 0 {
|
||||
select {
|
||||
case <-ch:
|
||||
case <-time.After(remaining):
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -339,6 +361,23 @@ func probePattern(n int) []byte {
|
||||
return out
|
||||
}
|
||||
|
||||
func validateIperfUploadPayload(payload []byte, token string, candidate int) bool {
|
||||
base := 11 + len(token)
|
||||
wantLen := candidate
|
||||
if wantLen < base {
|
||||
wantLen = base
|
||||
}
|
||||
if len(payload) != wantLen {
|
||||
return false
|
||||
}
|
||||
for i := base; i < len(payload); i++ {
|
||||
if payload[i] != byte((i*31+17)&0xff) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func parseOpen(payload []byte) (token, host string, port int, err error) {
|
||||
if len(payload) < 6 {
|
||||
return "", "", 0, fmt.Errorf("bad OPEN payload")
|
||||
@@ -395,6 +434,32 @@ func processWireRequest(conn net.Conn, req wire.Request, token string, allowPriv
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case wire.ProbeIperfUpload:
|
||||
if value < 1 || value > maxChunk || len(req.Payload) > maxChunk {
|
||||
return wire.WriteResponse(conn, wire.StatusError, []byte("iperf upload chunk too large"))
|
||||
}
|
||||
if !validateIperfUploadPayload(req.Payload, supplied, value) {
|
||||
return wire.WriteResponse(conn, wire.StatusError, []byte("iperf upload validation failed"))
|
||||
}
|
||||
if debug != nil && debug.enabled {
|
||||
debug.logf("CALIBRATION fake_iperf=upload peer=%s chunk=%d bytes=%d seq=%d pollers=1 outstanding=1", conn.RemoteAddr(), value, len(req.Payload), req.Seq)
|
||||
}
|
||||
return wire.WriteResponse(conn, wire.StatusOK, nil)
|
||||
case wire.ProbeIperfDownload:
|
||||
if value < 1 || value > maxChunk {
|
||||
return wire.WriteResponse(conn, wire.StatusError, []byte("iperf download chunk too large"))
|
||||
}
|
||||
count := wire.ProbeBurstCount(value)
|
||||
if debug != nil && debug.enabled {
|
||||
debug.logf("CALIBRATION fake_iperf=download peer=%s chunk=%d records=%d bytes=%d pollers=1 outstanding=1", conn.RemoteAddr(), value, count, value*count)
|
||||
}
|
||||
data := probePattern(value)
|
||||
for i := 0; i < count; i++ {
|
||||
if err := wire.WriteMaskedResponse(conn, wire.StatusData, data, req.Session, wire.ModeProbe, req.Seq+uint64(i)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
default:
|
||||
return wire.WriteResponse(conn, wire.StatusError, []byte("unknown probe kind"))
|
||||
}
|
||||
@@ -418,7 +483,8 @@ func processWireRequest(conn net.Conn, req wire.Request, token string, allowPriv
|
||||
if err != nil {
|
||||
return wire.WriteResponse(conn, wire.StatusError, []byte(err.Error()))
|
||||
}
|
||||
session := newStreamSession(req.Session, target, fmt.Sprintf("%s:%d", host, port), maxChunk, maxBuffer, debug)
|
||||
_, internalCarrier := lookupInternalTarget(host, port)
|
||||
session := newStreamSession(req.Session, target, fmt.Sprintf("%s:%d", host, port), maxChunk, maxBuffer, internalCarrier, debug)
|
||||
_, created := manager.addOrGet(req.Session, session)
|
||||
if created && debug != nil && debug.enabled {
|
||||
debug.sessionsOpened.Add(1)
|
||||
|
||||
Reference in New Issue
Block a user