|
7 | 7 | "testing" |
8 | 8 | "time" |
9 | 9 |
|
| 10 | + B "github.com/sagernet/sing/common/buf" |
| 11 | + M "github.com/sagernet/sing/common/metadata" |
10 | 12 | "github.com/xtls/xray-core/app/connectiontracker" |
11 | 13 | ) |
12 | 14 |
|
@@ -370,3 +372,120 @@ func TestWrapConnUpdatesLastActivity(t *testing.T) { |
370 | 372 | t.Errorf("LastActivity not updated: before=%v after=%v", before, after) |
371 | 373 | } |
372 | 374 | } |
| 375 | + |
| 376 | +// fakePacketConn is a minimal N.PacketConn for WrapPacketConn tests. |
| 377 | +type fakePacketConn struct { |
| 378 | + readPacketData *B.Buffer |
| 379 | + readPacketErr error |
| 380 | + writePacketErr error |
| 381 | +} |
| 382 | + |
| 383 | +func (f *fakePacketConn) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) { |
| 384 | + if f.readPacketErr != nil { |
| 385 | + return M.Socksaddr{}, f.readPacketErr |
| 386 | + } |
| 387 | + if f.readPacketData != nil { |
| 388 | + buffer.Write(f.readPacketData.Bytes()) |
| 389 | + } |
| 390 | + return M.Socksaddr{}, nil |
| 391 | +} |
| 392 | + |
| 393 | +func (f *fakePacketConn) WritePacket(buffer *B.Buffer, _ M.Socksaddr) error { |
| 394 | + return f.writePacketErr |
| 395 | +} |
| 396 | + |
| 397 | +func (f *fakePacketConn) Close() error { |
| 398 | + return nil |
| 399 | +} |
| 400 | + |
| 401 | +func (f *fakePacketConn) LocalAddr() net.Addr { |
| 402 | + return nil |
| 403 | +} |
| 404 | + |
| 405 | +func (f *fakePacketConn) SetDeadline(_ time.Time) error { |
| 406 | + return nil |
| 407 | +} |
| 408 | + |
| 409 | +func (f *fakePacketConn) SetReadDeadline(_ time.Time) error { |
| 410 | + return nil |
| 411 | +} |
| 412 | + |
| 413 | +func (f *fakePacketConn) SetWriteDeadline(_ time.Time) error { |
| 414 | + return nil |
| 415 | +} |
| 416 | + |
| 417 | +func TestWrapPacketConnCountsUplinkOnReadPacket(t *testing.T) { |
| 418 | + tracker := connectiontracker.New() |
| 419 | + _, entry := tracker.RegisterWithMeta("user@example.com", func() {}, "", "") |
| 420 | + |
| 421 | + data := B.New() |
| 422 | + data.Write([]byte("hello world")) |
| 423 | + |
| 424 | + fpc := &fakePacketConn{readPacketData: data} |
| 425 | + wrapped := connectiontracker.WrapPacketConn(fpc, entry) |
| 426 | + |
| 427 | + buf := B.New() |
| 428 | + defer buf.Release() |
| 429 | + if _, err := wrapped.ReadPacket(buf); err != nil { |
| 430 | + t.Fatal(err) |
| 431 | + } |
| 432 | + |
| 433 | + conns := tracker.ListConnections() |
| 434 | + if len(conns) != 1 { |
| 435 | + t.Fatalf("expected 1 connection") |
| 436 | + } |
| 437 | + if conns[0].Uplink != 11 { |
| 438 | + t.Errorf("Uplink: got %d, want 11", conns[0].Uplink) |
| 439 | + } |
| 440 | + if conns[0].Downlink != 0 { |
| 441 | + t.Errorf("Downlink should be 0, got %d", conns[0].Downlink) |
| 442 | + } |
| 443 | +} |
| 444 | + |
| 445 | +func TestWrapPacketConnCountsDownlinkOnWritePacket(t *testing.T) { |
| 446 | + tracker := connectiontracker.New() |
| 447 | + _, entry := tracker.RegisterWithMeta("user@example.com", func() {}, "", "") |
| 448 | + |
| 449 | + fpc := &fakePacketConn{} |
| 450 | + wrapped := connectiontracker.WrapPacketConn(fpc, entry) |
| 451 | + |
| 452 | + buf := B.New() |
| 453 | + buf.Write([]byte("goodbye world")) |
| 454 | + if err := wrapped.WritePacket(buf, M.Socksaddr{}); err != nil { |
| 455 | + t.Fatal(err) |
| 456 | + } |
| 457 | + |
| 458 | + conns := tracker.ListConnections() |
| 459 | + if len(conns) != 1 { |
| 460 | + t.Fatalf("expected 1 connection") |
| 461 | + } |
| 462 | + if conns[0].Downlink != 13 { |
| 463 | + t.Errorf("Downlink: got %d, want 13", conns[0].Downlink) |
| 464 | + } |
| 465 | + if conns[0].Uplink != 0 { |
| 466 | + t.Errorf("Uplink should be 0, got %d", conns[0].Uplink) |
| 467 | + } |
| 468 | +} |
| 469 | + |
| 470 | +func TestWrapPacketConnUpdatesLastActivity(t *testing.T) { |
| 471 | + tracker := connectiontracker.New() |
| 472 | + _, entry := tracker.RegisterWithMeta("user@example.com", func() {}, "", "") |
| 473 | + |
| 474 | + before := tracker.ListConnections()[0].LastActivity |
| 475 | + |
| 476 | + time.Sleep(time.Millisecond) |
| 477 | + |
| 478 | + data := B.New() |
| 479 | + data.Write([]byte("x")) |
| 480 | + |
| 481 | + fpc := &fakePacketConn{readPacketData: data} |
| 482 | + wrapped := connectiontracker.WrapPacketConn(fpc, entry) |
| 483 | + buf := B.New() |
| 484 | + defer buf.Release() |
| 485 | + wrapped.ReadPacket(buf) //nolint:errcheck |
| 486 | + |
| 487 | + after := tracker.ListConnections()[0].LastActivity |
| 488 | + if !after.After(before) { |
| 489 | + t.Errorf("LastActivity not updated: before=%v after=%v", before, after) |
| 490 | + } |
| 491 | +} |
0 commit comments