package icecast import ( "fmt" "encoding/base64" "net" "net/http" "net/url" "bufio" "strings" "time" "errors" "strconv" "io/ioutil" "../config" "../socket" ) var connected bool = false var stream_socket net.Conn var status int = 0 var server_msg string var pln = fmt.Println var spf = fmt.Sprintf func Connect() (net.Conn, error){ if connected { return stream_socket, nil } var sock net.Conn host := config.Xcfg.Server.ADDR + ":" + strconv.Itoa(config.Xcfg.Server.PORT) sock, err := net.Dial("tcp", host) if err != nil { connected = false return sock, err } time.Sleep(time.Second) // doing connection BUTT style (i.e. multiple sends) // icecast only for now // try PUT method mount := config.Xcfg.Server.MOUNT s := spf("PUT %s HTTP/1.1\r\n", mount) if mount[0] != '/' { s = spf("PUT /%s HTTP/1.1\r\n", mount) } err = socket.Send(sock, []byte(s)) s = spf("%s:%s", config.Xcfg.Server.USR, config.Xcfg.Server.PWD) sb64 := "Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(s)) + "\r\n" err = socket.Send(sock, []byte(sb64)) s = "User-Agent: radiodiodio/v0.0\r\n" err = socket.Send(sock, []byte(s)) s = "Content-Type: audio/mp3\r\n" err = socket.Send(sock, []byte(s)) s = spf("ice-name: %s\r\n", config.Xcfg.Ice.NAME) err = socket.Send(sock, []byte(s)) s = spf("ice-public: %s\r\n", config.Xcfg.Ice.PUB) err = socket.Send(sock, []byte(s)) s = spf("ice-url: %s\r\n", config.Xcfg.Ice.URL) err = socket.Send(sock, []byte(s)) s = spf("ice-genre: %s\r\n", config.Xcfg.Ice.GENRE) err = socket.Send(sock, []byte(s)) s = spf("ice-description: %s\r\n", config.Xcfg.Ice.DESC) err = socket.Send(sock, []byte(s)) s = "ice-audio-info: ice-bitrate=192000; ice-channels=2; ice-samplerate=44100\r\n" err = socket.Send(sock, []byte(s)) s = "\r\n" err = socket.Send(sock, []byte(s)) if err != nil { pln("error: sending PUT to the icecast server") connected = false return sock, err } time.Sleep(time.Second) resp, err := socket.Recv(sock) if err != nil { pln("error: receiving response from the icecast server") connected = false return sock, err } status, server_msg, err := read_http_response(resp) if status != 200 { connected = false return sock, errors.New("Icecast connection failed: " + strconv.Itoa(status) + " - " + server_msg) } pln("YAYAY!!") connected = true stream_socket = sock return sock, nil } func Disconnect() { stream_socket.Close() connected = false } func Send(buff []byte) error { if !connected { return errors.New("Not connected to Icecast server") } err := socket.Send(stream_socket, buff) return err } func Update() error { host := config.Xcfg.Server.ADDR + ":" + strconv.Itoa(config.Xcfg.Server.PORT) track := url.QueryEscape(config.Xcfg.Track.NAME) mount := config.Xcfg.Server.MOUNT if mount[0] != '/' { mount = "/" + mount } s := spf("%s:%s", config.Xcfg.Server.USR, config.Xcfg.Server.PWD) sb64 := "Basic " + base64.StdEncoding.EncodeToString([]byte(s)) header := "GET /admin/metadata?mode=updinfo&mount=" + mount + "&song=" + track + " HTTP/1.0\r\n" + "User-Agent: radiodiodio/v0.0\r\n" + "Authorization: " + sb64 + "\r\n" + "\r\n" pln(host) pln(header) var sock net.Conn sock, err := net.Dial("tcp", host) if err != nil { return err } time.Sleep(time.Second) err = socket.Send(sock, []byte(header)) time.Sleep(time.Second) defer sock.Close() resp, err := socket.Recv(sock) if err != nil { pln("error: receiving response from the icecast server") connected = false return err } status, server_msg, err := read_http_response(resp) if status != 200 { connected = false return errors.New("Icecast connection failed: " + strconv.Itoa(status) + " - " + server_msg) } else { pln(server_msg) } return err } func read_http_response(raw_resp []byte) (int, string, error) { reader := bufio.NewReader(strings.NewReader(string(raw_resp))) resp, err := http.ReadResponse(reader, nil) if err != nil { return 0, "", err } status := resp.StatusCode defer resp.Body.Close() body, er := ioutil.ReadAll(resp.Body) if er != nil { return status, "", er } return status, string(body), nil }