transport.go 3.3 KB

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