From 6a69a658603bfc312555017df5dea1a5f6bb4083 Mon Sep 17 00:00:00 2001 From: Niels Freier Date: Mon, 4 May 2015 09:47:26 +0400 Subject: [PATCH] WebSocket layer to be able to connect "web" client Currently working with a mini irc js implem, the flow: * PASS * NICK * USER * JOIN * PRIVMSG works and the ping/pong timeout keep the communication open. --- ergonomadic.conf | 3 ++- irc/config.go | 1 + irc/server.go | 36 +++++++++++++++++++++++++++++++ irc/websocket.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 irc/websocket.go diff --git a/ergonomadic.conf b/ergonomadic.conf index fd08218f..fb9b7d2a 100644 --- a/ergonomadic.conf +++ b/ergonomadic.conf @@ -1,8 +1,9 @@ [server] -name = "irc.example.com" ; required, usually a hostname +name = "localhost" ; required, usually a hostname database = "ergonomadic.db" ; path relative to this file listen = "localhost:6667" ; see `net.Listen` for examples listen = "[::1]:6667" ; multiple `listen`s are allowed. +wslisten = ":8080" ; websocket listen log = "debug" ; error, warn, info, debug motd = "motd.txt" ; path relative to this file password = "JDJhJDA0JHJzVFFlNXdOUXNhLmtkSGRUQVVEVHVYWXRKUmdNQ3FKVTRrczRSMTlSWGRPZHRSMVRzQmtt" ; 'test' diff --git a/irc/config.go b/irc/config.go index 5a3c2e44..f3db3ea9 100644 --- a/irc/config.go +++ b/irc/config.go @@ -23,6 +23,7 @@ type Config struct { PassConfig Database string Listen []string + Wslisten string Log string MOTD string Name string diff --git a/irc/server.go b/irc/server.go index f21812dd..7152bf0b 100644 --- a/irc/server.go +++ b/irc/server.go @@ -6,6 +6,7 @@ import ( "fmt" "log" "net" + "net/http" "os" "os/signal" "strings" @@ -72,6 +73,10 @@ func NewServer(config *Config) *Server { server.listen(addr) } + if config.Server.Wslisten != "" { + server.wslisten(config.Server.Wslisten) + } + signal.Notify(server.signals, SERVER_SIGNALS...) return server @@ -203,6 +208,37 @@ func (s *Server) listen(addr string) { }() } +// +// websocket listen goroutine +// + +func (s *Server) wslisten(addr string) { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + Log.error.Printf("%s method not allowed", s) + return + } + ws, err := upgrader.Upgrade(w, r, nil) + if err != nil { + Log.error.Printf("%s websocket upgrade error: %s", s, err) + return + } + + wsc := WSContainer{ + conn: ws, + } + + s.newConns <- wsc + }) + go func() { + Log.info.Printf("%s listening on %s", s, addr) + err := http.ListenAndServe(addr, nil) + if err != nil { + Log.error.Printf("%s listenAndServe error: %s", s, err) + } + }() +} + // // server functionality // diff --git a/irc/websocket.go b/irc/websocket.go new file mode 100644 index 00000000..e385ca08 --- /dev/null +++ b/irc/websocket.go @@ -0,0 +1,56 @@ +package irc + +import ( + "github.com/gorilla/websocket" + "net" + "net/http" + "time" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { return true }, +} + +type WSContainer struct { + conn *websocket.Conn +} + +func (this WSContainer) Close() error { + return this.conn.Close() +} + +func (this WSContainer) LocalAddr() net.Addr { + return this.conn.LocalAddr() +} + +func (this WSContainer) RemoteAddr() net.Addr { + return this.conn.RemoteAddr() +} + +func (this WSContainer) Read(msg []byte) (int, error) { + _, tmp, err := this.conn.ReadMessage() + str := (string)(tmp) + n := copy(msg, ([]byte)(str+CRLF+CRLF)) + return n, err +} + +func (this WSContainer) Write(msg []byte) (int, error) { + err := this.conn.WriteMessage(1, msg) + return len(msg), err +} + +func (this WSContainer) SetDeadline(t time.Time) error { + err := this.conn.SetWriteDeadline(t) + err = this.conn.SetReadDeadline(t) + return err +} + +func (this WSContainer) SetReadDeadline(t time.Time) error { + return this.conn.SetReadDeadline(t) +} + +func (this WSContainer) SetWriteDeadline(t time.Time) error { + return this.conn.SetWriteDeadline(t) +}