session.go (1778B)
1 package rtp 2 3 import ( 4 "fmt" 5 "math/rand" 6 "net" 7 "time" 8 ) 9 10 func Dial(network, addr string) (*Session, error) { 11 conn, err := net.Dial(network, addr) 12 if err != nil { 13 return nil, err 14 } 15 s := Session{conn: conn} 16 s.init() 17 return &s, nil 18 } 19 20 // Session represents a RTP session... 21 // When a Session is established with Dial(), ... 22 // TODO(otl): what does session automatically handle? what do we not 23 // need to set in each packets header? 24 type Session struct { 25 // Clock is the rate of the... in hertz. 26 // If zero, automatic detection attempted... 27 Clock int 28 29 conn net.Conn 30 sequence uint16 31 timestamp uint32 32 previous time.Time 33 syncSource uint32 34 } 35 36 func (s *Session) init() { 37 s.sequence = uint16(rand.Intn(0xffff)) // max uint16 38 s.syncSource = rand.Uint32() 39 s.timestamp = rand.Uint32() 40 } 41 42 // Transmit sends the packet to the destination address in s. 43 // 44 // TODO(otl): some fields in packet's header are set by Transmit. 45 // Which ones? Otherwise people are going to get surprised! 46 func (s *Session) Transmit(packet *Packet) error { 47 if packet.Header.Version == 0 { 48 packet.Header.Version = VersionRFC3550 49 } 50 51 s.sequence++ 52 packet.Header.Sequence = s.sequence 53 54 ticks := ticksSince(s.previous, s.Clock) 55 packet.Header.Timestamp = s.timestamp + ticks 56 s.previous = time.Now() 57 s.timestamp += ticks 58 59 packet.Header.SyncSource = s.syncSource 60 61 b, err := Marshal(packet) 62 if err != nil { 63 return fmt.Errorf("marshal packet: %w", err) 64 } 65 n, err := s.conn.Write(b) 66 if n != len(b) { 67 if err != nil { 68 return fmt.Errorf("short write %d bytes: %w", n, err) 69 } 70 return fmt.Errorf("short write (%d bytes)", n) 71 } 72 return err 73 } 74 75 func ticksSince(t time.Time, clockRate int) (ticks uint32) { 76 dur := int(time.Since(t)/time.Second) * clockRate 77 return uint32(dur) 78 }