musique/server/router/router.go

73 lines
1.5 KiB
Go

package router
import (
"encoding/json"
"musique/server/proto"
"net"
"log"
"fmt"
)
type Route func(incoming net.Conn, request proto.Request) interface{}
type Router struct {
routes map[string]Route
port int
baseIP string
}
func (router *Router) Add(name string, route Route) {
if router.routes == nil {
router.routes = make(map[string]Route)
}
router.routes[name] = route
}
func (router *Router) Run(ip string, port *int) (<-chan struct{}, error) {
router.port = *port
router.baseIP = ip
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", router.baseIP, router.port))
if err != nil {
return nil, err
}
_, actualPort, err := net.SplitHostPort(listener.Addr().String())
if err != nil {
return nil, err
}
fmt.Sscan(actualPort, port)
exit := make(chan struct{})
go func() {
defer listener.Close()
defer close(exit)
for {
incoming, err := listener.Accept()
if err != nil {
log.Println("failed to accept connection:", err)
}
go router.handleIncoming(incoming)
}
}()
return exit, nil
}
func (router *Router) handleIncoming(incoming net.Conn) {
defer incoming.Close()
request := proto.Request{}
json.NewDecoder(incoming).Decode(&request)
log.Printf("%s: %+v\n", incoming.RemoteAddr(), request)
if handler, ok := router.routes[request.Type]; ok {
if response := handler(incoming, request); response != nil {
json.NewEncoder(incoming).Encode(response)
}
} else {
log.Printf("unrecongized route: %v\n", request.Type)
}
}