async www read write
This commit is contained in:
parent
4e0ba79dd9
commit
6bb83ddbcb
@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
type server_t struct {
|
type ice_server_t struct {
|
||||||
NAME string
|
NAME string
|
||||||
ADDR string
|
ADDR string
|
||||||
PORT int
|
PORT int
|
||||||
@ -14,7 +14,7 @@ type server_t struct {
|
|||||||
STYPE int
|
STYPE int
|
||||||
}
|
}
|
||||||
|
|
||||||
type ice_t struct {
|
type ice_stream_t struct {
|
||||||
NAME string
|
NAME string
|
||||||
DESC string
|
DESC string
|
||||||
GENRE string
|
GENRE string
|
||||||
@ -49,9 +49,10 @@ type archive_t struct {
|
|||||||
|
|
||||||
type config_t struct {
|
type config_t struct {
|
||||||
Track Track_t
|
Track Track_t
|
||||||
Server server_t
|
IceServer ice_server_t
|
||||||
Ice ice_t
|
IceStream ice_stream_t
|
||||||
Archive archive_t
|
Archive archive_t
|
||||||
|
WWWport string
|
||||||
}
|
}
|
||||||
|
|
||||||
var Xcfg config_t
|
var Xcfg config_t
|
||||||
@ -63,23 +64,24 @@ func Loadconfig(filename string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
Xcfg.Server.NAME = ini.Section("server").Key("name").Value()
|
Xcfg.IceServer.NAME = ini.Section("ice-server").Key("name").Value()
|
||||||
Xcfg.Server.ADDR = ini.Section("server").Key("addr").Value()
|
Xcfg.IceServer.ADDR = ini.Section("ice-server").Key("addr").Value()
|
||||||
Xcfg.Server.PORT, _ = ini.Section("server").Key("port").Int()
|
Xcfg.IceServer.PORT, _ = ini.Section("ice-server").Key("port").Int()
|
||||||
Xcfg.Server.MOUNT = ini.Section("server").Key("mount").Value()
|
Xcfg.IceServer.MOUNT = ini.Section("ice-server").Key("mount").Value()
|
||||||
Xcfg.Server.USR = ini.Section("server").Key("usr").Value()
|
Xcfg.IceServer.USR = ini.Section("ice-server").Key("usr").Value()
|
||||||
Xcfg.Server.PWD = ini.Section("server").Key("pwd").Value()
|
Xcfg.IceServer.PWD = ini.Section("ice-server").Key("pwd").Value()
|
||||||
|
|
||||||
Xcfg.Ice.NAME = ini.Section("ice").Key("name").Value()
|
Xcfg.IceStream.NAME = ini.Section("ice-stream").Key("name").Value()
|
||||||
Xcfg.Ice.DESC = ini.Section("ice").Key("desc").Value()
|
Xcfg.IceStream.DESC = ini.Section("ice-stream").Key("desc").Value()
|
||||||
Xcfg.Ice.GENRE = ini.Section("ice").Key("genre").Value()
|
Xcfg.IceStream.GENRE = ini.Section("ice-stream").Key("genre").Value()
|
||||||
Xcfg.Ice.URL = ini.Section("ice").Key("url").Value()
|
Xcfg.IceStream.URL = ini.Section("ice-stream").Key("url").Value()
|
||||||
Xcfg.Ice.IRC = ini.Section("ice").Key("irc").Value()
|
Xcfg.IceStream.IRC = ini.Section("ice-stream").Key("irc").Value()
|
||||||
Xcfg.Ice.AIM = ini.Section("ice").Key("aim").Value()
|
Xcfg.IceStream.AIM = ini.Section("ice-stream").Key("aim").Value()
|
||||||
Xcfg.Ice.PUB = ini.Section("ice").Key("pub").Value()
|
Xcfg.IceStream.PUB = ini.Section("ice-stream").Key("pub").Value()
|
||||||
|
|
||||||
Xcfg.Archive.PATH = ini.Section("archive").Key("path").Value()
|
Xcfg.Archive.PATH = ini.Section("archive").Key("path").Value()
|
||||||
|
|
||||||
|
Xcfg.WWWport = ini.Section("www-server").Key("port").Value()
|
||||||
|
|
||||||
Xcfg.Archive.ALBUMS = make(map[uint32]Album_t)
|
Xcfg.Archive.ALBUMS = make(map[uint32]Album_t)
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ func Connect() (net.Conn, error){
|
|||||||
// ips, err := net.LookupIP("www.google.ca")
|
// ips, err := net.LookupIP("www.google.ca")
|
||||||
|
|
||||||
var sock net.Conn
|
var sock net.Conn
|
||||||
host := config.Xcfg.Server.ADDR + ":" + strconv.Itoa(config.Xcfg.Server.PORT)
|
host := config.Xcfg.IceServer.ADDR + ":" + strconv.Itoa(config.Xcfg.IceServer.PORT)
|
||||||
sock, err := net.Dial("tcp", host)
|
sock, err := net.Dial("tcp", host)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -48,14 +48,14 @@ func Connect() (net.Conn, error){
|
|||||||
// icecast only for now
|
// icecast only for now
|
||||||
// try PUT method
|
// try PUT method
|
||||||
|
|
||||||
mount := config.Xcfg.Server.MOUNT
|
mount := config.Xcfg.IceServer.MOUNT
|
||||||
s := spf("PUT %s HTTP/1.1\r\n", mount)
|
s := spf("PUT %s HTTP/1.1\r\n", mount)
|
||||||
if mount[0] != '/' {
|
if mount[0] != '/' {
|
||||||
s = spf("PUT /%s HTTP/1.1\r\n", mount)
|
s = spf("PUT /%s HTTP/1.1\r\n", mount)
|
||||||
}
|
}
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("%s:%s", config.Xcfg.Server.USR, config.Xcfg.Server.PWD)
|
s = spf("%s:%s", config.Xcfg.IceServer.USR, config.Xcfg.IceServer.PWD)
|
||||||
sb64 := "Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(s)) + "\r\n"
|
sb64 := "Authorization: Basic " + base64.StdEncoding.EncodeToString([]byte(s)) + "\r\n"
|
||||||
err = socket.Send(sock, []byte(sb64))
|
err = socket.Send(sock, []byte(sb64))
|
||||||
|
|
||||||
@ -65,19 +65,19 @@ func Connect() (net.Conn, error){
|
|||||||
s = "Content-Type: audio/mp3\r\n"
|
s = "Content-Type: audio/mp3\r\n"
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("ice-name: %s\r\n", config.Xcfg.Ice.NAME)
|
s = spf("ice-name: %s\r\n", config.Xcfg.IceStream.NAME)
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("ice-public: %s\r\n", config.Xcfg.Ice.PUB)
|
s = spf("ice-public: %s\r\n", config.Xcfg.IceStream.PUB)
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("ice-url: %s\r\n", config.Xcfg.Ice.URL)
|
s = spf("ice-url: %s\r\n", config.Xcfg.IceStream.URL)
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("ice-genre: %s\r\n", config.Xcfg.Ice.GENRE)
|
s = spf("ice-genre: %s\r\n", config.Xcfg.IceStream.GENRE)
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = spf("ice-description: %s\r\n", config.Xcfg.Ice.DESC)
|
s = spf("ice-description: %s\r\n", config.Xcfg.IceStream.DESC)
|
||||||
err = socket.Send(sock, []byte(s))
|
err = socket.Send(sock, []byte(s))
|
||||||
|
|
||||||
s = "ice-audio-info: ice-bitrate=192000; ice-channels=2; ice-samplerate=44100\r\n"
|
s = "ice-audio-info: ice-bitrate=192000; ice-channels=2; ice-samplerate=44100\r\n"
|
||||||
@ -132,14 +132,14 @@ func Send(buff []byte) error {
|
|||||||
|
|
||||||
func Update() error {
|
func Update() error {
|
||||||
|
|
||||||
host := config.Xcfg.Server.ADDR + ":" + strconv.Itoa(config.Xcfg.Server.PORT)
|
host := config.Xcfg.IceServer.ADDR + ":" + strconv.Itoa(config.Xcfg.IceServer.PORT)
|
||||||
track := url.QueryEscape(config.Xcfg.Track.NAME)
|
track := url.QueryEscape(config.Xcfg.Track.NAME)
|
||||||
mount := config.Xcfg.Server.MOUNT
|
mount := config.Xcfg.IceServer.MOUNT
|
||||||
if mount[0] != '/' {
|
if mount[0] != '/' {
|
||||||
mount = "/" + mount
|
mount = "/" + mount
|
||||||
}
|
}
|
||||||
|
|
||||||
s := spf("%s:%s", config.Xcfg.Server.USR, config.Xcfg.Server.PWD)
|
s := spf("%s:%s", config.Xcfg.IceServer.USR, config.Xcfg.IceServer.PWD)
|
||||||
sb64 := "Basic " + base64.StdEncoding.EncodeToString([]byte(s))
|
sb64 := "Basic " + base64.StdEncoding.EncodeToString([]byte(s))
|
||||||
|
|
||||||
header := "GET /admin/metadata?mode=updinfo&mount=" + mount + "&song=" + track + " HTTP/1.0\r\n" +
|
header := "GET /admin/metadata?mode=updinfo&mount=" + mount + "&song=" + track + " HTTP/1.0\r\n" +
|
||||||
|
|||||||
@ -63,12 +63,12 @@ func MakeRandom(name string, max int) (*Playlist, error) {
|
|||||||
return p, nil;
|
return p, nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Playlist) Encode() string {
|
func (mp *MinimalPlaylist) Encode() []byte {
|
||||||
|
res, err := json.Marshal(mp)
|
||||||
pp := p.Pretty()
|
if err != nil {
|
||||||
res, _ := json.Marshal(pp)
|
return nil
|
||||||
return string(res)
|
}
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func Decode(jsonstr string) (*Playlist, error) {
|
func Decode(jsonstr string) (*Playlist, error) {
|
||||||
|
|||||||
2
serve.go
2
serve.go
@ -25,5 +25,5 @@ func main() {
|
|||||||
|
|
||||||
go audio.Start(p.Pop)
|
go audio.Start(p.Pop)
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(":8718", nil))
|
log.Fatal(http.ListenAndServe(":" + config.Xcfg.WWWport, nil))
|
||||||
}
|
}
|
||||||
|
|||||||
73
www/socket.go
Normal file
73
www/socket.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package www
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Socket struct {
|
||||||
|
wsc *websocket.Conn
|
||||||
|
send chan []byte
|
||||||
|
bundle *Bundle
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeSocket(c *websocket.Conn, b *Bundle) *Socket {
|
||||||
|
s := &Socket {
|
||||||
|
wsc: c,
|
||||||
|
send: make(chan []byte, 1024),
|
||||||
|
bundle: b,
|
||||||
|
closed: false,
|
||||||
|
}
|
||||||
|
s.bundle.add <- s
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Socket) close() {
|
||||||
|
if !s.closed {
|
||||||
|
pln("socket - close")
|
||||||
|
close(s.send)
|
||||||
|
s.wsc.Close()
|
||||||
|
s.bundle.remove <- s
|
||||||
|
s.closed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bundle struct {
|
||||||
|
socks map[*Socket]bool
|
||||||
|
broadcast chan []byte
|
||||||
|
add chan *Socket
|
||||||
|
remove chan *Socket
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func makeBundle() *Bundle {
|
||||||
|
return &Bundle {
|
||||||
|
socks: make(map[*Socket]bool),
|
||||||
|
broadcast: make(chan []byte, 1024),
|
||||||
|
add: make(chan *Socket),
|
||||||
|
remove: make(chan *Socket),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bundle) process() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case sock := <-b.add:
|
||||||
|
b.socks[sock] = true
|
||||||
|
case sock := <-b.remove:
|
||||||
|
if b.socks[sock] {
|
||||||
|
delete(b.socks, sock)
|
||||||
|
}
|
||||||
|
case data := <-b.broadcast:
|
||||||
|
for s := range b.socks {
|
||||||
|
select {
|
||||||
|
case s.send <- data:
|
||||||
|
default:
|
||||||
|
pln("bundle -- socket close")
|
||||||
|
s.close()
|
||||||
|
delete(b.socks, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
89
www/www.go
89
www/www.go
@ -3,6 +3,7 @@ package www
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
@ -16,6 +17,9 @@ var p *playlist.Playlist
|
|||||||
var pp *playlist.PrettyPlaylist
|
var pp *playlist.PrettyPlaylist
|
||||||
var mp *playlist.MinimalPlaylist
|
var mp *playlist.MinimalPlaylist
|
||||||
|
|
||||||
|
var bundle *Bundle
|
||||||
|
var mutex = &sync.Mutex{}
|
||||||
|
|
||||||
var pln = log.Println
|
var pln = log.Println
|
||||||
|
|
||||||
type op_t struct {
|
type op_t struct {
|
||||||
@ -26,7 +30,7 @@ type op_t struct {
|
|||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
ReadBufferSize: 512,
|
ReadBufferSize: 512,
|
||||||
WriteBufferSize: 512,
|
WriteBufferSize: 1024,
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(playlist *playlist.Playlist) {
|
func Init(playlist *playlist.Playlist) {
|
||||||
@ -34,6 +38,9 @@ func Init(playlist *playlist.Playlist) {
|
|||||||
p.CALLB = pop_callback
|
p.CALLB = pop_callback
|
||||||
pp = p.Pretty()
|
pp = p.Pretty()
|
||||||
mp = p.Minimal()
|
mp = p.Minimal()
|
||||||
|
bundle = makeBundle()
|
||||||
|
go bundle.process()
|
||||||
|
|
||||||
http.HandleFunc("/pp", pp_handler)
|
http.HandleFunc("/pp", pp_handler)
|
||||||
http.HandleFunc("/ppop", pp_operations)
|
http.HandleFunc("/ppop", pp_operations)
|
||||||
}
|
}
|
||||||
@ -49,36 +56,64 @@ func pp_handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func pp_operations(w http.ResponseWriter, r *http.Request) {
|
func pp_operations(w http.ResponseWriter, r *http.Request) {
|
||||||
pln("x")
|
pln("new connection")
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
c, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pln(err)
|
pln(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wsc = c // this should be hub
|
|
||||||
go readop(c)
|
// pln("GGGG")
|
||||||
|
// s := &Socket{wsc: c, send: make(chan []byte, 1024), bundle: bundle}
|
||||||
|
// s.bundle.add <- s
|
||||||
|
|
||||||
|
s := makeSocket(c, bundle)
|
||||||
|
|
||||||
|
go s.read()
|
||||||
|
go s.write()
|
||||||
|
|
||||||
|
// // this should be hub
|
||||||
|
// go readop(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readop(c *websocket.Conn) {
|
func (s *Socket) read() {
|
||||||
|
defer s.close()
|
||||||
for {
|
for {
|
||||||
opdata := &op_t{}
|
opdata := &op_t{}
|
||||||
if err := c.ReadJSON(&opdata); err != nil {
|
if err := s.wsc.ReadJSON(&opdata); err != nil {
|
||||||
pln(err)
|
pln("0")
|
||||||
return //connection lost?
|
// if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||||
|
pln("connection closed - read")
|
||||||
|
break
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if opdata.OP == "move" {
|
if opdata.OP == "move" {
|
||||||
if id, err := strconv.ParseUint(opdata.ID, 10, 32); err == nil {
|
if id, err := strconv.ParseUint(opdata.ID, 10, 32); err == nil {
|
||||||
|
mutex.Lock()
|
||||||
p.Move(uint32(id), opdata.INDEX)
|
p.Move(uint32(id), opdata.INDEX)
|
||||||
pp = p.Pretty()
|
pp = p.Pretty()
|
||||||
mp = p.Minimal()
|
mp = p.Minimal()
|
||||||
// pp.Print()
|
mutex.Unlock()
|
||||||
|
s.bundle.broadcast <- mp.Encode() /// crap this nees to be []byte
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.WriteJSON(mp); err != nil {
|
func (s *Socket) write() {
|
||||||
pln(err)
|
for {
|
||||||
return //connection lost?
|
select {
|
||||||
|
case mp, _ := <-s.send:
|
||||||
|
w, err := s.wsc.NextWriter(websocket.TextMessage);
|
||||||
|
if err != nil {
|
||||||
|
// if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||||
|
pln("connection closed - write")
|
||||||
|
return
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
w.Write(mp)
|
||||||
|
// is there queued messages?
|
||||||
|
w.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,8 +122,30 @@ func pop_callback(list *playlist.Playlist) {
|
|||||||
if list == p {
|
if list == p {
|
||||||
pp = p.Pretty()
|
pp = p.Pretty()
|
||||||
mp = p.Minimal()
|
mp = p.Minimal()
|
||||||
if wsc != nil {
|
bundle.broadcast <- mp.Encode()
|
||||||
wsc.WriteJSON(mp) // this should be hub broadcasted
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func readop(c *websocket.Conn) {
|
||||||
|
// for {
|
||||||
|
// opdata := &op_t{}
|
||||||
|
// if err := c.ReadJSON(&opdata); err != nil {
|
||||||
|
// pln(err)
|
||||||
|
// return //connection lost?
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if opdata.OP == "move" {
|
||||||
|
// if id, err := strconv.ParseUint(opdata.ID, 10, 32); err == nil {
|
||||||
|
// p.Move(uint32(id), opdata.INDEX)
|
||||||
|
// pp = p.Pretty()
|
||||||
|
// mp = p.Minimal()
|
||||||
|
// // pp.Print()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if err := c.WriteJSON(mp); err != nil {
|
||||||
|
// pln(err)
|
||||||
|
// return //connection lost?
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user