connection.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package core
  2. import (
  3. "io"
  4. "net/http"
  5. "reflect"
  6. "sync/atomic"
  7. )
  8. func NewID() uint32 {
  9. return id.Add(1)
  10. }
  11. // Deprecated: use NewID instead
  12. func ID(v any) uint32 {
  13. p := uintptr(reflect.ValueOf(v).UnsafePointer())
  14. return 0x8000_0000 | uint32(p)
  15. }
  16. var id atomic.Uint32
  17. type Info interface {
  18. SetProtocol(string)
  19. SetRemoteAddr(string)
  20. SetSource(string)
  21. SetURL(string)
  22. WithRequest(*http.Request)
  23. }
  24. // Connection just like webrtc.PeerConnection
  25. // - ID and RemoteAddr used for building Connection(s) graph
  26. // - FormatName, Protocol, RemoteAddr, Source, URL, SDP, UserAgent used for info about Connection
  27. // - FormatName and Protocol has FFmpeg compatible names
  28. // - Transport used for auto closing on Stop
  29. type Connection struct {
  30. ID uint32 `json:"id,omitempty"`
  31. FormatName string `json:"format_name,omitempty"` // rtsp, webrtc, mp4, mjpeg, mpjpeg...
  32. Protocol string `json:"protocol,omitempty"` // tcp, udp, http, ws, pipe...
  33. RemoteAddr string `json:"remote_addr,omitempty"` // host:port other info
  34. Source string `json:"source,omitempty"`
  35. URL string `json:"url,omitempty"`
  36. SDP string `json:"sdp,omitempty"`
  37. UserAgent string `json:"user_agent,omitempty"`
  38. Medias []*Media `json:"medias,omitempty"`
  39. Receivers []*Receiver `json:"receivers,omitempty"`
  40. Senders []*Sender `json:"senders,omitempty"`
  41. Recv int `json:"bytes_recv,omitempty"`
  42. Send int `json:"bytes_send,omitempty"`
  43. Transport any `json:"-"`
  44. }
  45. func (c *Connection) GetMedias() []*Media {
  46. return c.Medias
  47. }
  48. func (c *Connection) GetTrack(media *Media, codec *Codec) (*Receiver, error) {
  49. for _, receiver := range c.Receivers {
  50. if receiver.Codec == codec {
  51. return receiver, nil
  52. }
  53. }
  54. receiver := NewReceiver(media, codec)
  55. c.Receivers = append(c.Receivers, receiver)
  56. return receiver, nil
  57. }
  58. func (c *Connection) Stop() error {
  59. for _, receiver := range c.Receivers {
  60. receiver.Close()
  61. }
  62. for _, sender := range c.Senders {
  63. sender.Close()
  64. }
  65. if closer, ok := c.Transport.(io.Closer); ok {
  66. return closer.Close()
  67. }
  68. return nil
  69. }
  70. // Deprecated:
  71. func (c *Connection) Codecs() []*Codec {
  72. codecs := make([]*Codec, len(c.Senders))
  73. for i, sender := range c.Senders {
  74. codecs[i] = sender.Codec
  75. }
  76. return codecs
  77. }
  78. func (c *Connection) SetProtocol(s string) {
  79. c.Protocol = s
  80. }
  81. func (c *Connection) SetRemoteAddr(s string) {
  82. if c.RemoteAddr == "" {
  83. c.RemoteAddr = s
  84. } else {
  85. c.RemoteAddr += " forwarded " + s
  86. }
  87. }
  88. func (c *Connection) SetSource(s string) {
  89. c.Source = s
  90. }
  91. func (c *Connection) SetURL(s string) {
  92. c.URL = s
  93. }
  94. func (c *Connection) WithRequest(r *http.Request) {
  95. if r.Header.Get("Upgrade") == "websocket" {
  96. c.Protocol = "ws"
  97. } else {
  98. c.Protocol = "http"
  99. }
  100. c.RemoteAddr = r.RemoteAddr
  101. if remote := r.Header.Get("X-Forwarded-For"); remote != "" {
  102. c.RemoteAddr += " forwarded " + remote
  103. }
  104. c.UserAgent = r.UserAgent()
  105. }
  106. // Create like os.Create, init Consumer with existing Transport
  107. func Create(w io.Writer) (*Connection, error) {
  108. return &Connection{Transport: w}, nil
  109. }
  110. // Open like os.Open, init Producer from existing Transport
  111. func Open(r io.Reader) (*Connection, error) {
  112. return &Connection{Transport: r}, nil
  113. }
  114. // Dial like net.Dial, init Producer via Dialing
  115. func Dial(rawURL string) (*Connection, error) {
  116. return &Connection{}, nil
  117. }