mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
Merge pull request #14 from edmund-huber/websocket
add support for WebSocket connections
This commit is contained in:
commit
67a6247377
@ -3,6 +3,7 @@ name = "irc.example.com" ; required, usually a hostname
|
|||||||
database = "ergonomadic.db" ; path relative to this file
|
database = "ergonomadic.db" ; path relative to this file
|
||||||
listen = "localhost:6667" ; see `net.Listen` for examples
|
listen = "localhost:6667" ; see `net.Listen` for examples
|
||||||
listen = "[::1]:6667" ; multiple `listen`s are allowed.
|
listen = "[::1]:6667" ; multiple `listen`s are allowed.
|
||||||
|
wslisten = ":8080" ; websocket listen
|
||||||
log = "debug" ; error, warn, info, debug
|
log = "debug" ; error, warn, info, debug
|
||||||
motd = "motd.txt" ; path relative to this file
|
motd = "motd.txt" ; path relative to this file
|
||||||
password = "JDJhJDA0JHJzVFFlNXdOUXNhLmtkSGRUQVVEVHVYWXRKUmdNQ3FKVTRrczRSMTlSWGRPZHRSMVRzQmtt" ; 'test'
|
password = "JDJhJDA0JHJzVFFlNXdOUXNhLmtkSGRUQVVEVHVYWXRKUmdNQ3FKVTRrczRSMTlSWGRPZHRSMVRzQmtt" ; 'test'
|
||||||
|
@ -23,6 +23,7 @@ type Config struct {
|
|||||||
PassConfig
|
PassConfig
|
||||||
Database string
|
Database string
|
||||||
Listen []string
|
Listen []string
|
||||||
|
Wslisten string
|
||||||
Log string
|
Log string
|
||||||
MOTD string
|
MOTD string
|
||||||
Name string
|
Name string
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
@ -72,6 +73,10 @@ func NewServer(config *Config) *Server {
|
|||||||
server.listen(addr)
|
server.listen(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Server.Wslisten != "" {
|
||||||
|
server.wslisten(config.Server.Wslisten)
|
||||||
|
}
|
||||||
|
|
||||||
signal.Notify(server.signals, SERVER_SIGNALS...)
|
signal.Notify(server.signals, SERVER_SIGNALS...)
|
||||||
|
|
||||||
return server
|
return server
|
||||||
@ -203,6 +208,41 @@ 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't have any subprotocols, so if someone attempts to `new
|
||||||
|
// WebSocket(server, "subprotocol")` they'll break here, instead of
|
||||||
|
// getting the default, ambiguous, response from gorilla.
|
||||||
|
if v, ok := r.Header["Sec-Websocket-Protocol"]; ok {
|
||||||
|
http.Error(w, fmt.Sprintf("WebSocket subprocotols (e.g. %s) not supported", v), 400)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws, err := upgrader.Upgrade(w, r, nil)
|
||||||
|
if err != nil {
|
||||||
|
Log.error.Printf("%s websocket upgrade error: %s", s, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.newConns <- WSContainer{ws}
|
||||||
|
})
|
||||||
|
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
|
// server functionality
|
||||||
//
|
//
|
||||||
|
47
irc/websocket.go
Normal file
47
irc/websocket.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package irc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var upgrader = websocket.Upgrader{
|
||||||
|
ReadBufferSize: 1024,
|
||||||
|
WriteBufferSize: 1024,
|
||||||
|
// If a WS session contains sensitive information, and you choose to use
|
||||||
|
// cookies for authentication (during the HTTP(S) upgrade request), then
|
||||||
|
// you should check that Origin is a domain under your control. If it
|
||||||
|
// isn't, then it is possible for users of your site, visiting a naughty
|
||||||
|
// Origin, to have a WS opened using their credentials. See
|
||||||
|
// http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html#main.
|
||||||
|
// We don't care about Origin because the (IRC) authentication is contained
|
||||||
|
// in the WS stream -- the WS session is not privileged when it is opened.
|
||||||
|
CheckOrigin: func(r *http.Request) bool { return true },
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSContainer struct {
|
||||||
|
*websocket.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this WSContainer) Read(msg []byte) (int, error) {
|
||||||
|
ty, bytes, err := this.ReadMessage()
|
||||||
|
if ty == websocket.TextMessage {
|
||||||
|
n := copy(msg, []byte(string(bytes)+CRLF+CRLF))
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
// Binary, and other kinds of messages, are thrown away.
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this WSContainer) Write(msg []byte) (int, error) {
|
||||||
|
err := this.WriteMessage(websocket.TextMessage, msg)
|
||||||
|
return len(msg), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this WSContainer) SetDeadline(t time.Time) error {
|
||||||
|
if err := this.SetWriteDeadline(t); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return this.SetReadDeadline(t)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user