github.com/ssetin/penguincast@v0.2.0/src/client/client.go (about) 1 // Package iceclient - simple client for icecast server 2 package iceclient 3 4 import ( 5 "bufio" 6 "errors" 7 "log" 8 "net" 9 "net/textproto" 10 "os" 11 "strconv" 12 "strings" 13 ) 14 15 // ================================== PenguinClient ======================================== 16 const ( 17 cClientName = "penguinClient" 18 cVersion = "0.2" 19 ) 20 21 // PenguinClient ... 22 type PenguinClient struct { 23 urlMount string 24 host string 25 mount string 26 bitRate int 27 dumpFileName string 28 29 dumpFile *os.File 30 conn net.Conn 31 } 32 33 // Init - initialize client 34 func (p *PenguinClient) Init(host string, mount string, dump string) error { 35 p.urlMount = "http://" + host + "/" + mount 36 p.host = host 37 p.mount = mount 38 p.dumpFileName = dump 39 p.bitRate = 0 40 41 if dump > "" { 42 var err error 43 p.dumpFile, err = os.OpenFile(p.dumpFileName, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) 44 if err != nil { 45 return err 46 } 47 } 48 49 return nil 50 } 51 52 func (p *PenguinClient) sayHello(writer *bufio.Writer) error { 53 writer.WriteString("GET /") 54 writer.WriteString(p.mount) 55 writer.WriteString(" HTTP/1.0\r\nicy-metadata: 1\r\nuser-agent: ") 56 writer.WriteString(cClientName) 57 writer.WriteString("/") 58 writer.WriteString(cVersion) 59 writer.WriteString("\r\naccept: */*\r\n\r\n") 60 writer.Flush() 61 return nil 62 } 63 64 func (p *PenguinClient) getMountInfo(reader *bufio.Reader) error { 65 tp := textproto.NewReader(reader) 66 67 for { 68 line, err := tp.ReadLine() 69 if err != nil { 70 return err 71 } 72 if line == "" { 73 break 74 } 75 params := strings.Split(line, ":") 76 if len(params) == 2 { 77 if params[0] == "X-Audiocast-Bitrate" { 78 p.bitRate, err = strconv.Atoi(strings.TrimSpace(params[1])) 79 if err != nil { 80 return err 81 } 82 } 83 } 84 85 } 86 87 return nil 88 } 89 90 // Listen - start to listen the stream during secToListen seconds 91 func (p *PenguinClient) Listen(secToListen int) error { 92 var err error 93 //var beginIteration time.Time 94 //var iterTime time.Duration 95 p.conn, err = net.Dial("tcp", p.host) 96 97 if err != nil { 98 return err 99 } 100 defer p.conn.Close() 101 102 if p.dumpFile != nil { 103 defer p.dumpFile.Close() 104 } 105 106 reader := bufio.NewReader(p.conn) 107 writer := bufio.NewWriter(p.conn) 108 109 err = p.sayHello(writer) 110 if err != nil { 111 return err 112 } 113 114 err = p.getMountInfo(reader) 115 if err != nil { 116 log.Println(err.Error()) 117 return err 118 } 119 //p.bitRate = 96 120 if p.bitRate == 0 { 121 return errors.New("Unknown bitrate") 122 } 123 124 bytesToFinish := secToListen * p.bitRate * 1024 / 8 125 readedBytes := 0 126 sndBuff := make([]byte, 1024*p.bitRate/8) 127 128 for readedBytes <= bytesToFinish { 129 //beginIteration = time.Now() 130 n, err := p.conn.Read(sndBuff) 131 if err != nil { 132 return err 133 } 134 135 if p.dumpFile != nil && n > 0 { 136 p.dumpFile.Write(sndBuff[:n]) 137 } 138 readedBytes += n 139 140 //iterTime = time.Since(beginIteration) 141 142 //if iterTime > time.Millisecond*2000 { 143 // log.Printf("Speed: %f Kbit/sec", float64(n)*8/1024/iterTime.Seconds()) 144 //} 145 } 146 147 return nil 148 }