Skip to content

Commit 92b44ef

Browse files
Merge branch 'celzero:n2' into icmp-hack
2 parents 212044f + 5aa390b commit 92b44ef

30 files changed

Lines changed: 416 additions & 330 deletions

File tree

.github/workflows/go.yml

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ jobs:
2222
with:
2323
go-version: '>=1.24'
2424

25+
- name: 🐍 Python3
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: '3.10'
29+
2530
- name: 🏗️ Make
2631
run: |
2732
# outputs firestack.aar and firestack-arm.aar; also see: "Obj" below
@@ -35,27 +40,6 @@ jobs:
3540
# go test -v -race -bench=. -benchtime=100ms ./...
3641
echo "::notice::success"
3742
38-
- name: 🔮 Vet
39-
run: |
40-
# github.com/actions/setup-go/issues/27
41-
export PATH=${PATH}:`go env GOPATH`/bin
42-
43-
# vet: fails: archive.is/XcDl6
44-
go vet ./...
45-
# staticcheck
46-
# go install honnef.co/go/tools/cmd/staticcheck@latest
47-
# staticcheck ./...
48-
go install go.uber.org/nilaway/cmd/nilaway@latest
49-
nilaway ./...
50-
go install golang.org/x/vuln/cmd/govulncheck@latest
51-
govulncheck -show verbose -test ./...
52-
shell: bash
53-
54-
- name: 🐍 Python3
55-
uses: actions/setup-python@v5
56-
with:
57-
python-version: '3.10'
58-
5943
- name: 💿 Obj
6044
run: |
6145
wget --tries=2 --waitretry=3 --no-dns-cache https://github.com/Zxilly/go-size-analyzer/releases/download/v1.0.8/go-size-analyzer_1.0.8_linux_amd64.deb -O gsa.deb
@@ -135,7 +119,24 @@ jobs:
135119
echo "====================="
136120
shell: bash
137121

122+
- name: 🔮 Vet
123+
run: |
124+
# github.com/actions/setup-go/issues/27
125+
export PATH=${PATH}:`go env GOPATH`/bin
126+
127+
# vet: fails: archive.is/XcDl6
128+
go vet ./...
129+
# staticcheck
130+
# go install honnef.co/go/tools/cmd/staticcheck@latest
131+
# staticcheck ./...
132+
go install go.uber.org/nilaway/cmd/nilaway@latest
133+
nilaway ./...
134+
go install golang.org/x/vuln/cmd/govulncheck@latest
135+
govulncheck -show verbose -test ./...
136+
shell: bash
137+
138138
- name: 🛸 Env
139+
if: success()
139140
run: |
140141
# docs.github.com/en/actions/reference/workflows-and-actions/contexts#github-context
141142
GROUP_GITHUB="com.github.${{ github.repository_owner }}"
@@ -185,6 +186,7 @@ jobs:
185186
shell: bash
186187

187188
- name: 🏷️ Setup for GitHub Packages
189+
if: success() && github.event_name == 'push'
188190
uses: actions/setup-java@v4
189191
with:
190192
java-version: '17'
@@ -193,6 +195,7 @@ jobs:
193195
# docs.github.com/en/actions/tutorials/build-and-test-code/java-with-maven
194196
# docs.github.com/en/actions/tutorials/publish-packages/publish-java-packages-with-maven#publishing-packages-to-github-packages
195197
- name: 📦 Publish
198+
if: success() && github.event_name == 'push'
196199
shell: bash
197200
run: |
198201
# uploaded at:
@@ -217,6 +220,7 @@ jobs:
217220
# github.com/slsa-framework/slsa-github-generator/blob/4876e96b8268/actions/maven/publish/action.yml#L49
218221
# docs.github.com/en/actions/tutorials/publish-packages/publish-java-packages-with-maven#publishing-packages-to-the-maven-central-repository-and-github-packages
219222
- name: 🏛️ Setup for Maven Central
223+
if: success() && github.event_name == 'push'
220224
uses: actions/setup-java@v4
221225
with:
222226
java-version: '17'
@@ -228,6 +232,7 @@ jobs:
228232
gpg-passphrase: ${{ secrets.OSSRH_CELZERO_GPG_PASSPHRASE }}
229233

230234
- name: 📦 Publish to Maven Central
235+
if: success() && github.event_name == 'push'
231236
shell: bash
232237
run: |
233238
mvn -f ${POM_OSSRH} versions:set -DnewVersion=${VCSVER} -DgenerateBackupPoms=false
@@ -260,8 +265,8 @@ jobs:
260265

261266
# github.com/actions/upload-artifact
262267
- name: 🚀 Upload
268+
if: success() && github.event_name == 'push'
263269
uses: actions/upload-artifact@v4
264-
if: success()
265270
with:
266271
name: firestack-aar-${{ github.sha }} # must be unique
267272
path: firestack*.aar # see: make-aar

intra/backend/dnsx.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ const ( // from dnsx/queryerror.go
7070
TransportError
7171
// ClientError: Client has issues
7272
ClientError
73+
// Paused: Transport is paused
74+
Paused
7375
// DEnd: Transport stopped
7476
DEnd
7577
)

intra/common.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ func (h *baseHandler) forward(local, remote net.Conn, smm *SocketSummary) {
279279
remote = r.Unwrap() // c may be *net.TCPConn or *demuxconn or *retrier or *splitter
280280
}
281281
}
282-
log.I("com: %s: forward: new conn %s rwext? %t (%T), sockopt? %t (%ds); %s for %s",
282+
log.I("com: %s: forward: new conn %s rwext? %t (%T), optset? %t (%ds); %s for %s",
283283
h.proto, via, isrwext, remote, didSet, timeoutsecs, tup, uid)
284284

285285
uploadch := make(chan ioinfo)

intra/core/async.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ func Periodic(id string, pctx context.Context, d time.Duration, f func()) contex
225225
}
226226

227227
// SigFin runs f in a goroutine and returns a channel that is closed when f returns.
228-
func SigFin(f func()) <-chan struct{} {
228+
func SigFin(id string, f func()) <-chan struct{} {
229229
done := make(chan struct{})
230-
Go("take", func() {
230+
Go("sigfin."+id, func() {
231231
defer close(done)
232232
f()
233233
})

intra/core/connmap.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,14 @@ func (h *cm) addByPidLocked(pid, cid string) {
110110
if len(pid) <= 0 || len(cid) <= 0 {
111111
return
112112
}
113-
// TODO: remove duplicates
114-
h.tracp[pid] = append(h.tracp[pid], cid)
113+
h.tracp[pid] = CopyUniq(h.tracp[pid], []string{cid})
115114
}
116115

117116
func (h *cm) addByUidLocked(uid, cid string) {
118117
if len(uid) <= 0 || len(cid) <= 0 {
119118
return
120119
}
121-
// TODO: remove duplicates
122-
h.tracu[uid] = append(h.tracu[uid], cid)
120+
h.tracu[uid] = CopyUniq(h.tracu[uid], []string{cid})
123121
}
124122

125123
func (h *cm) getLocked(cid string) *connstat {

intra/dialers/retrier.go

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ func (r *retrier) retryWriteReadLocked(buf []byte) (int, error) {
426426

427427
// all of buf was written to c
428428
// require a response within a short timeout on r.conn (same as newConn)
429-
r.shorterReadDeadlineForRetryLocked()
429+
newConn.SetReadDeadline(time.Now().Add(r.readTimeoutLocked()))
430430
return newConn.Read(buf)
431431
}
432432

@@ -489,12 +489,13 @@ func (r *retrier) Read(buf []byte) (n int, err error) {
489489
r.dialerID(), r.retryCount, len(r.dialers), c, r.nextDialerIdx, laddr(c), r.raddr, core.FmtPeriod(r.timeout), n, len(buf), retryReadErr)
490490
}
491491
if c != nil && core.IsNotNil(c) {
492-
// caller might have set read or write deadlines before the retry
492+
// caller might have set read or write deadlines before the retry;
493+
// if not, clear any deadlines set by the retrier
493494
_ = c.SetReadDeadline(r.readDeadline)
494495
_ = c.SetWriteDeadline(r.writeDeadline)
495496
}
496-
logeor(err, note)("retrier: read: %s: #%d + (mult? %d / %d) [%s<=%s]; t: %s; b: %d/%d; err? %v",
497-
r.dialerID(), r.retryCount, len(r.dialers), r.nextDialerIdx, laddr(c), r.raddr, core.FmtPeriod(r.timeout), n, len(buf), err)
497+
logeor(err, note)("retrier: read: %s: #%d + (mult? %d / %d) [%s<=%s]; rshortt: %s / rfullt: %s; b: %d/%d; err? %v",
498+
r.dialerID(), r.retryCount, len(r.dialers), r.nextDialerIdx, laddr(c), r.raddr, core.FmtPeriod(r.timeout), core.FmtTimeAsPeriod(r.readDeadline), n, len(buf), err)
498499
r.tee = nil // discard teed data
499500
return
500501
}
@@ -504,7 +505,7 @@ func (r *retrier) Read(buf []byte) (n int, err error) {
504505
return
505506
}
506507

507-
func (r *retrier) teedFirstWrite(b []byte) (n int, firstWrite, didAttemptWrite bool, src net.Addr, err error) {
508+
func (r *retrier) teedFirstWrite(b []byte) (n int, firstWrite, didAttemptWrite bool, readWait time.Duration, src net.Addr, err error) {
508509
r.mu.Lock()
509510
defer r.mu.Unlock()
510511

@@ -519,33 +520,24 @@ func (r *retrier) teedFirstWrite(b []byte) (n int, firstWrite, didAttemptWrite b
519520
}
520521

521522
src = laddr(c)
522-
if !r.retryCompleted() { // first write
523+
if !r.retryCompleted() { // may be first write
523524
_ = c.SetWriteDeadline(r.writeDeadline)
524525

525526
n, err = c.Write(b)
526527

527528
// capture first write, aka "hello"
528529
r.tee = append(r.tee, b...)
529530
didAttemptWrite = true
531+
readWait = r.readTimeoutLocked()
530532
// all of b was written to r.tee if not to c
531533
// require a response or another write within a short timeout.
532-
r.shorterReadDeadlineForRetryLocked()
534+
c.SetReadDeadline(time.Now().Add(readWait))
533535
}
534536

535537
return
536538
}
537539

538-
func (r *retrier) shorterReadDeadlineForRetryLocked() {
539-
c := r.conn
540-
if r.timeout > 0 {
541-
_ = c.SetReadDeadline(time.Now().Add(r.timeout))
542-
} else {
543-
// if timeout is set to 0, then use client requested deadline
544-
_ = c.SetReadDeadline(r.readDeadline)
545-
}
546-
}
547-
548-
func (r *retrier) readTimeout() time.Duration {
540+
func (r *retrier) readTimeoutLocked() time.Duration {
549541
if r.timeout > 0 {
550542
return r.timeout
551543
}
@@ -563,7 +555,7 @@ func (r *retrier) Write(b []byte) (int, error) {
563555
// empty at steady-state.
564556
if !r.retryCompleted() {
565557
// todo: what if sentAndCopied is false and err != nil?
566-
n, first, sentAndCopied, src, err := r.teedFirstWrite(b)
558+
n, first, sentAndCopied, until, src, err := r.teedFirstWrite(b)
567559

568560
note := log.D
569561
if sentAndCopied {
@@ -587,33 +579,31 @@ func (r *retrier) Write(b []byte) (int, error) {
587579
// by the retry procedure. Block until we have a final socket (which will
588580
// already have replayed r.tee), and retry.
589581
// ie, wait until first write is done on the final socket.
590-
until := r.readTimeout()
591582
maxUntil := max(until, until*maxRetryCount)
592583
if r.multidial {
593584
maxUntil = max(maxUntil, maxUntil*time.Duration(len(r.dialers)))
594585
}
595586
select {
596587
case <-r.retryDoneCh:
597588
case <-time.After(maxUntil): // arb high timeout; it should rarely if ever needed
598-
log.W("retrier: write: %s: 1st write timed-out waiting for %s [calc-rtt: %s] 1st read b/w [%s=>%s], mult: %d, b: %d/%d, err: %v",
589+
rerr := log.EE("retrier: write: %s: 1st write timed-out waiting for %s [calc-rtt: %s] 1st read b/w [%s=>%s], mult: %d, b: %d/%d, err: %v",
599590
r.dialerID(), core.FmtPeriod(maxUntil), core.FmtPeriod(r.timeout), src, r.raddr, len(r.dialers), n, len(b), err)
600-
return n, core.JoinErr(err, errRetryTimeout)
591+
return n, core.JoinErr(err, rerr, errRetryTimeout)
601592
}
602593

603594
r.mu.Lock()
604595
defer r.mu.Unlock()
605596

606-
elapsed := time.Since(start).Milliseconds()
607597
// r.conn may be nil or closed by the time we get here
608598
finalConn := r.conn
609599
noconn := finalConn == nil || core.IsNil(finalConn)
610600
if r.retryWriteErr != nil || noconn { // check if retried writes also failed
611601
if noconn {
612602
err = core.JoinErr(err, errNilConn)
613603
}
614-
log.E("retrier: write: %s: retry failed [%s=>%s] b: %d/%d (tee: %d) in %dms; old => new: %v => %v; noconn? %t",
615-
r.dialerID(), laddr(r.conn), r.raddr, n, len(b), len(r.tee), elapsed, err, r.retryWriteErr, noconn)
616-
return n, core.JoinErr(err, r.retryWriteErr) // pass on the og error, too
604+
werr := log.EE("retrier: write: %s: retry failed [%s=>%s] b: %d/%d (tee: %d) in %s; old => new: %v => %v; noconn? %t",
605+
r.dialerID(), laddr(r.conn), r.raddr, n, len(b), len(r.tee), core.FmtTimeAsPeriod(start), err, r.retryWriteErr, noconn)
606+
return n, core.JoinErr(err, r.retryWriteErr, werr) // pass on the og error, too
617607
}
618608

619609
// if len(leftover) > 0 {
@@ -629,9 +619,9 @@ func (r *retrier) Write(b []byte) (int, error) {
629619

630620
// retryCompleted() is true, so r.conn is final and doesn't need locking
631621
if c := r.conn; c == nil || core.IsNil(c) {
632-
log.E("retrier: write: %s: [] => %s (b: %d, tee: %d), not retrying, but no conn",
622+
cerr := log.EE("retrier: write: %s: [] => %s (b: %d, tee: %d), not retrying, but no conn",
633623
r.dialerID(), r.raddr, len(b), len(r.tee))
634-
return 0, errNilConn
624+
return 0, core.JoinErr(cerr, errNilConn)
635625
} else {
636626
return c.Write(b)
637627
}
@@ -672,16 +662,22 @@ func (r *retrier) ReadFrom(reader io.Reader) (bytes int64, err error) {
672662
}
673663
}
674664

665+
// disable read and write deadlines as io.ReaderFrom does not
666+
// rely on io.Read and io.Write semantics for "r.conn" from which
667+
// deadlines are extended to avoid timeouts (see also: rwconn.go)
675668
optimizedReadFrom := true
676669
var b int64
677670
switch x := c.(type) {
678671
case *net.TCPConn:
672+
r.SetDeadline(time.Time{})
679673
b, err = x.ReadFrom(reader)
680674
bytes += b
681675
case *splitter:
676+
r.SetDeadline(time.Time{})
682677
b, err = x.ReadFrom(reader)
683678
bytes += b
684679
case io.ReaderFrom:
680+
r.SetDeadline(time.Time{})
685681
b, err = x.ReadFrom(reader)
686682
bytes += b
687683
default: // net.UDPConn, net.PacketConn etc?
@@ -691,13 +687,6 @@ func (r *retrier) ReadFrom(reader io.Reader) (bytes int64, err error) {
691687
bytes += b
692688
}
693689

694-
if optimizedReadFrom {
695-
// disable read and write deadlines as io.ReaderFrom does not
696-
// rely on io.Read and io.Write semantics from which deadlines
697-
// are usually extended to avoid timeouts (see also: rwconn.go)
698-
r.SetDeadline(time.Time{})
699-
}
700-
701690
logeif(err)("retrier: readfrom: %s: (optimized? %t for %T) done (id: %s, pinned? %t); sz: %d; err: %v",
702691
r.dialerID(), optimizedReadFrom, c, pinnedID, pinned, bytes, err)
703692
return

intra/dns53/dot.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,7 @@ func (t *dot) doQuery(pid string, q *dns.Msg) (response *dns.Msg, rpid string, e
157157
return
158158
}
159159

160-
if t.status.Load() == dnsx.DEnd {
161-
qerr = dnsx.NewEndQueryError()
160+
if qerr = dnsx.WillErr(t); qerr != nil {
162161
return
163162
}
164163

@@ -408,6 +407,11 @@ func (t *dot) IPPorts() (ipps []netip.AddrPort) {
408407
}
409408

410409
func (t *dot) Status() int {
410+
if px := t.GetRelay(); px != nil {
411+
if px.Status() == ipn.TPU { // relay paused => transport paused
412+
return dnsx.Paused
413+
}
414+
}
411415
return t.status.Load()
412416
}
413417

intra/dns53/goos.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,7 @@ func (t *goosr) send(msg *dns.Msg) (ans *dns.Msg, elapsed time.Duration, qerr *d
8686
qerr = dnsx.NewBadQueryError(errQueryParse)
8787
return
8888
}
89-
if t.status.Load() == dnsx.DEnd {
90-
qerr = dnsx.NewEndQueryError()
89+
if qerr = dnsx.WillErr(t); qerr != nil {
9190
return
9291
}
9392

0 commit comments

Comments
 (0)