transport.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package ice
  4. import (
  5. "context"
  6. "net"
  7. "sync/atomic"
  8. "time"
  9. "github.com/pion/stun"
  10. )
  11. // Dial connects to the remote agent, acting as the controlling ice agent.
  12. // Dial blocks until at least one ice candidate pair has successfully connected.
  13. func (a *Agent) Dial(ctx context.Context, remoteUfrag, remotePwd string) (*Conn, error) {
  14. return a.connect(ctx, true, remoteUfrag, remotePwd)
  15. }
  16. // Accept connects to the remote agent, acting as the controlled ice agent.
  17. // Accept blocks until at least one ice candidate pair has successfully connected.
  18. func (a *Agent) Accept(ctx context.Context, remoteUfrag, remotePwd string) (*Conn, error) {
  19. return a.connect(ctx, false, remoteUfrag, remotePwd)
  20. }
  21. // Conn represents the ICE connection.
  22. // At the moment the lifetime of the Conn is equal to the Agent.
  23. type Conn struct {
  24. bytesReceived uint64
  25. bytesSent uint64
  26. agent *Agent
  27. }
  28. // BytesSent returns the number of bytes sent
  29. func (c *Conn) BytesSent() uint64 {
  30. return atomic.LoadUint64(&c.bytesSent)
  31. }
  32. // BytesReceived returns the number of bytes received
  33. func (c *Conn) BytesReceived() uint64 {
  34. return atomic.LoadUint64(&c.bytesReceived)
  35. }
  36. func (a *Agent) connect(ctx context.Context, isControlling bool, remoteUfrag, remotePwd string) (*Conn, error) {
  37. err := a.ok()
  38. if err != nil {
  39. return nil, err
  40. }
  41. err = a.startConnectivityChecks(isControlling, remoteUfrag, remotePwd) //nolint:contextcheck
  42. if err != nil {
  43. return nil, err
  44. }
  45. // Block until pair selected
  46. select {
  47. case <-a.done:
  48. return nil, a.getErr()
  49. case <-ctx.Done():
  50. return nil, ErrCanceledByCaller
  51. case <-a.onConnected:
  52. }
  53. return &Conn{
  54. agent: a,
  55. }, nil
  56. }
  57. // Read implements the Conn Read method.
  58. func (c *Conn) Read(p []byte) (int, error) {
  59. err := c.agent.ok()
  60. if err != nil {
  61. return 0, err
  62. }
  63. n, err := c.agent.buf.Read(p)
  64. atomic.AddUint64(&c.bytesReceived, uint64(n))
  65. return n, err
  66. }
  67. // Write implements the Conn Write method.
  68. func (c *Conn) Write(p []byte) (int, error) {
  69. err := c.agent.ok()
  70. if err != nil {
  71. return 0, err
  72. }
  73. if stun.IsMessage(p) {
  74. return 0, errWriteSTUNMessageToIceConn
  75. }
  76. pair := c.agent.getSelectedPair()
  77. if pair == nil {
  78. if err = c.agent.run(c.agent.context(), func(ctx context.Context, a *Agent) {
  79. pair = a.getBestValidCandidatePair()
  80. }); err != nil {
  81. return 0, err
  82. }
  83. if pair == nil {
  84. return 0, err
  85. }
  86. }
  87. atomic.AddUint64(&c.bytesSent, uint64(len(p)))
  88. return pair.Write(p)
  89. }
  90. // Close implements the Conn Close method. It is used to close
  91. // the connection. Any calls to Read and Write will be unblocked and return an error.
  92. func (c *Conn) Close() error {
  93. return c.agent.Close()
  94. }
  95. // LocalAddr returns the local address of the current selected pair or nil if there is none.
  96. func (c *Conn) LocalAddr() net.Addr {
  97. pair := c.agent.getSelectedPair()
  98. if pair == nil {
  99. return nil
  100. }
  101. return pair.Local.addr()
  102. }
  103. // RemoteAddr returns the remote address of the current selected pair or nil if there is none.
  104. func (c *Conn) RemoteAddr() net.Addr {
  105. pair := c.agent.getSelectedPair()
  106. if pair == nil {
  107. return nil
  108. }
  109. return pair.Remote.addr()
  110. }
  111. // SetDeadline is a stub
  112. func (c *Conn) SetDeadline(time.Time) error {
  113. return nil
  114. }
  115. // SetReadDeadline is a stub
  116. func (c *Conn) SetReadDeadline(time.Time) error {
  117. return nil
  118. }
  119. // SetWriteDeadline is a stub
  120. func (c *Conn) SetWriteDeadline(time.Time) error {
  121. return nil
  122. }