Changeset 323 in code for trunk/server.go


Ignore:
Timestamp:
Jun 7, 2020, 12:13:46 PM (5 years ago)
Author:
contact
Message:

Add support for WebSocket connections

WebSocket connections allow web-based clients to connect to IRC. This
commit implements the WebSocket sub-protocol as specified by the pending
IRCv3 proposal [1].

WebSocket listeners can now be set up via a "wss" protocol in the
listen directive. The new http-origin directive allows the CORS
allowed origins to be configured.

[1]: https://github.com/ircv3/ircv3-specifications/pull/342

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/server.go

    r319 r323  
    55        "log"
    66        "net"
     7        "net/http"
    78        "sync"
     9        "sync/atomic"
    810        "time"
    911
    1012        "gopkg.in/irc.v3"
     13        "nhooyr.io/websocket"
    1114)
    1215
     
    4548        LogPath      string
    4649        Debug        bool
     50        HTTPOrigins  []string
    4751
    4852        db *DB
     
    9296}
    9397
     98var lastDownstreamID uint64 = 0
     99
     100func (s *Server) handle(ic ircConn, remoteAddr string) {
     101        id := atomic.AddUint64(&lastDownstreamID, 1)
     102        dc := newDownstreamConn(s, ic, remoteAddr, id)
     103        if err := dc.runUntilRegistered(); err != nil {
     104                dc.logger.Print(err)
     105        } else {
     106                dc.user.events <- eventDownstreamConnected{dc}
     107                if err := dc.readMessages(dc.user.events); err != nil {
     108                        dc.logger.Print(err)
     109                }
     110                dc.user.events <- eventDownstreamDisconnected{dc}
     111        }
     112        dc.Close()
     113}
     114
    94115func (s *Server) Serve(ln net.Listener) error {
    95         var nextDownstreamID uint64 = 1
    96116        for {
    97                 netConn, err := ln.Accept()
     117                conn, err := ln.Accept()
    98118                if err != nil {
    99119                        return fmt.Errorf("failed to accept connection: %v", err)
    100120                }
    101121
    102                 dc := newDownstreamConn(s, netConn, nextDownstreamID)
    103                 nextDownstreamID++
    104                 go func() {
    105                         if err := dc.runUntilRegistered(); err != nil {
    106                                 dc.logger.Print(err)
    107                         } else {
    108                                 dc.user.events <- eventDownstreamConnected{dc}
    109                                 if err := dc.readMessages(dc.user.events); err != nil {
    110                                         dc.logger.Print(err)
    111                                 }
    112                                 dc.user.events <- eventDownstreamDisconnected{dc}
    113                         }
    114                         dc.Close()
    115                 }()
     122                go s.handle(newNetIRCConn(conn), conn.RemoteAddr().String())
    116123        }
    117124}
     125
     126func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
     127        conn, err := websocket.Accept(w, req, &websocket.AcceptOptions{
     128                OriginPatterns: s.HTTPOrigins,
     129        })
     130        if err != nil {
     131                s.Logger.Printf("failed to serve HTTP connection: %v", err)
     132                return
     133        }
     134        s.handle(newWebsocketIRCConn(conn), req.RemoteAddr)
     135}
Note: See TracChangeset for help on using the changeset viewer.