// NewHandler returns a new http.ServeMux which automatically spawn a new // instance of GDB and offers HTTP mount points to interact with. It is assumed // that only one client at a time access this multiplexer. func NewHandler() (*http.ServeMux, error) { handler := http.NewServeMux() notificationsChan := make(chan []byte) // start a new GDB instance gdb, err := gdb.New(func(notification map[string]interface{}) { // notifications are converted to JSON and sent through the channel notificationText, err := json.Marshal(notification) if err != nil { log.Fatal(err) } notificationsChan <- notificationText log.Print(">>> ", string(notificationText)) }) if err != nil { return nil, err } // notifications WebSocket handler.Handle(NotificationsUrl, websocket.Handler(func(ws *websocket.Conn) { // deliver the notifications through the WebSocket for notification := range notificationsChan { ws.Write(notification) } })) // terminal WebSocket handler.Handle(TerminalUrl, websocket.Handler(func(ws *websocket.Conn) { // copy GDB to WS and WS to GDB go io.Copy(gdb, ws) io.Copy(ws, gdb) })) // send command action handler.HandleFunc(CommandsUrl, func(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Print("### invalid method") w.WriteHeader(http.StatusInternalServerError) return } data, err := ioutil.ReadAll(req.Body) if err != nil { die(err, w) return } log.Print("<<< ", string(data)) command := []string{} err = json.Unmarshal(data, &command) if err != nil { die(err, w) return } result, err := gdb.Send(command[0], command[1:]...) if err != nil { die(err, w) return } reply, err := json.Marshal(result) if err != nil { die(err, w) return } io.WriteString(w, string(reply)) log.Print(">>> ", string(reply)) }) // send interrupt action handler.HandleFunc(InterruptUrl, func(w http.ResponseWriter, req *http.Request) { if req.Method != "POST" { log.Print("### invalid method") w.WriteHeader(http.StatusInternalServerError) return } if err := gdb.Interrupt(); err != nil { die(err, w) return } log.Print("<<< interrupt") }) return handler, nil }
import ( "encoding/json" "github.com/cyrus-and/gdb" "github.com/gorilla/websocket" "log" "net" "net/http" "sync" ) var messages = make(chan []byte) var Gdb, _ = gdb.New(func(gdbMessages map[string]interface{}) { gdbMessagesText, err := json.Marshal(gdbMessages) if err != nil { log.Fatal(err) } messages <- gdbMessagesText }) var ActiveClients = make(map[ClientConn]int) var ActiveClientsRWMutex sync.RWMutex type ClientConn struct { websocket *websocket.Conn clientIP net.Addr } func die(err error, w http.ResponseWriter) { log.Print("### ", err) w.WriteHeader(http.StatusInternalServerError)