radiodiodio/icecast/icecast.go

208 lines
4.2 KiB
Go
Raw Permalink Normal View History

2019-01-02 16:11:22 +01:00
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
}
2019-01-03 14:38:05 +01:00
// ips, err := net.LookupIP("www.google.ca")
2019-01-02 16:11:22 +01:00
var sock net.Conn
2019-01-04 09:59:01 +01:00
host := config.Xcfg.IceServer.ADDR + ":" + strconv.Itoa(config.Xcfg.IceServer.PORT)
2019-01-02 16:11:22 +01:00
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
2019-01-04 09:59:01 +01:00
mount := config.Xcfg.IceServer.MOUNT
2019-01-02 16:11:22 +01:00
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))
2019-01-04 09:59:01 +01:00
s = spf("%s:%s", config.Xcfg.IceServer.USR, config.Xcfg.IceServer.PWD)
2019-01-02 16:11:22 +01:00
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))
2019-01-04 09:59:01 +01:00
s = spf("ice-name: %s\r\n", config.Xcfg.IceStream.NAME)
2019-01-02 16:11:22 +01:00
err = socket.Send(sock, []byte(s))
2019-01-04 09:59:01 +01:00
s = spf("ice-public: %s\r\n", config.Xcfg.IceStream.PUB)
2019-01-02 16:11:22 +01:00
err = socket.Send(sock, []byte(s))
2019-01-04 09:59:01 +01:00
s = spf("ice-url: %s\r\n", config.Xcfg.IceStream.URL)
2019-01-02 16:11:22 +01:00
err = socket.Send(sock, []byte(s))
2019-01-04 09:59:01 +01:00
s = spf("ice-genre: %s\r\n", config.Xcfg.IceStream.GENRE)
2019-01-02 16:11:22 +01:00
err = socket.Send(sock, []byte(s))
2019-01-04 09:59:01 +01:00
s = spf("ice-description: %s\r\n", config.Xcfg.IceStream.DESC)
2019-01-02 16:11:22 +01:00
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 {
2019-01-04 09:59:01 +01:00
host := config.Xcfg.IceServer.ADDR + ":" + strconv.Itoa(config.Xcfg.IceServer.PORT)
2019-01-02 16:11:22 +01:00
track := url.QueryEscape(config.Xcfg.Track.NAME)
2019-01-04 09:59:01 +01:00
mount := config.Xcfg.IceServer.MOUNT
2019-01-02 16:11:22 +01:00
if mount[0] != '/' {
mount = "/" + mount
}
2019-01-04 09:59:01 +01:00
s := spf("%s:%s", config.Xcfg.IceServer.USR, config.Xcfg.IceServer.PWD)
2019-01-02 16:11:22 +01:00
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
}