A bit more logging to debug WebSocket issues
This commit is contained in:
parent
b82ca3d34b
commit
a55b4b2b49
|
@ -31,6 +31,7 @@ On first run it will create the default settings.toml file for you which you may
|
|||
Title = "BareRTC"
|
||||
Branding = "BareRTC"
|
||||
WebsiteURL = "https://www.example.com"
|
||||
UseXForwardedFor = true
|
||||
|
||||
[JWT]
|
||||
Enabled = false
|
||||
|
@ -57,6 +58,7 @@ A description of the config directives includes:
|
|||
* **WebsiteURL** is the base URL of your actual website which is used in a couple of places:
|
||||
* The About page will link to your website.
|
||||
* If using [JWT authentication](#authentication), avatar and profile URLs may be relative (beginning with a "/") and will append to your website URL to safe space on the JWT token size!
|
||||
* **UseXForwardedFor**: set it to true and (for logging) the user's remote IP will use the X-Real-IP header or the first address in X-Forwarded-For. Set this if you run the app behind a proxy like nginx if you want IPs not to be all localhost.
|
||||
* **JWT**: settings for JWT [Authentication](#authentication).
|
||||
* Enabled (bool): activate the JWT token authentication feature.
|
||||
* Strict (bool): if true, **only** valid signed JWT tokens may log in. If false, users with no/invalid token can enter their own username without authentication.
|
||||
|
|
|
@ -10,8 +10,14 @@ import (
|
|||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
// Version of the config format - when new fields are added, it will attempt
|
||||
// to write the settings.toml to disk so new defaults populate.
|
||||
var currentVersion = 1
|
||||
|
||||
// Config for your BareRTC app.
|
||||
type Config struct {
|
||||
Version int // will re-save your settings.toml on migrations
|
||||
|
||||
JWT struct {
|
||||
Enabled bool
|
||||
Strict bool
|
||||
|
@ -22,6 +28,8 @@ type Config struct {
|
|||
Branding string
|
||||
WebsiteURL string
|
||||
|
||||
UseXForwardedFor bool
|
||||
|
||||
PublicChannels []Channel
|
||||
}
|
||||
|
||||
|
@ -88,6 +96,16 @@ func LoadSettings() error {
|
|||
}
|
||||
|
||||
_, err = toml.Decode(string(data), &Current)
|
||||
|
||||
// Have we added new config fields? Save the settings.toml.
|
||||
if Current.Version < currentVersion {
|
||||
log.Warn("New options are available for your settings.toml file. Your settings will be re-saved now.")
|
||||
Current.Version = currentVersion
|
||||
if err := WriteSettings(); err != nil {
|
||||
log.Error("Couldn't write your settings.toml file: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,14 @@ func (s *Server) OnLogin(sub *Subscriber, msg Message) {
|
|||
sub.JWTClaims = claims
|
||||
}
|
||||
|
||||
log.Info("JWT claims: %+v", claims)
|
||||
if claims.Subject != "" {
|
||||
log.Debug("JWT claims: %+v", claims)
|
||||
}
|
||||
|
||||
// Somehow no username?
|
||||
if msg.Username == "" {
|
||||
msg.Username = "anonymous"
|
||||
}
|
||||
|
||||
// Ensure the username is unique, or rename it.
|
||||
var duplicate bool
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/barertc/pkg/config"
|
||||
"git.kirsle.net/apps/barertc/pkg/jwt"
|
||||
|
@ -71,7 +72,12 @@ func IndexPage() http.HandlerFunc {
|
|||
}
|
||||
// END load the template
|
||||
|
||||
log.Info("Index route hit")
|
||||
log.Info("GET / [%s] %s", r.RemoteAddr, strings.Join([]string{
|
||||
r.Header.Get("X-Forwarded-For"),
|
||||
r.Header.Get("X-Real-IP"),
|
||||
r.Header.Get("User-Agent"),
|
||||
util.IPAddress(r),
|
||||
}, " "))
|
||||
tmpl.ExecuteTemplate(w, "index", values)
|
||||
})
|
||||
}
|
||||
|
|
23
pkg/util/ip_address.go
Normal file
23
pkg/util/ip_address.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.kirsle.net/apps/barertc/pkg/config"
|
||||
)
|
||||
|
||||
/*
|
||||
IPAddress returns the best guess at the user's IP address, as a string for logging.
|
||||
*/
|
||||
func IPAddress(r *http.Request) string {
|
||||
if config.Current.UseXForwardedFor {
|
||||
if realIP := r.Header.Get("X-Real-IP"); realIP != "" {
|
||||
return realIP
|
||||
}
|
||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||||
return strings.SplitN(xff, " ", 1)[0]
|
||||
}
|
||||
}
|
||||
return r.RemoteAddr
|
||||
}
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"git.kirsle.net/apps/barertc/pkg/jwt"
|
||||
"git.kirsle.net/apps/barertc/pkg/log"
|
||||
"git.kirsle.net/apps/barertc/pkg/util"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
|
@ -35,14 +36,18 @@ func (sub *Subscriber) ReadLoop(s *Server) {
|
|||
for {
|
||||
msgType, data, err := sub.conn.Read(sub.ctx)
|
||||
if err != nil {
|
||||
log.Error("ReadLoop error(%s): %+v", sub.Username, err)
|
||||
log.Error("ReadLoop error(%d=%s): %+v", sub.ID, sub.Username, err)
|
||||
s.DeleteSubscriber(sub)
|
||||
s.Broadcast(Message{
|
||||
Action: ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has exited the room!",
|
||||
})
|
||||
s.SendWhoList()
|
||||
|
||||
// Notify if this user was auth'd
|
||||
if sub.authenticated {
|
||||
s.Broadcast(Message{
|
||||
Action: ActionPresence,
|
||||
Username: sub.Username,
|
||||
Message: "has exited the room!",
|
||||
})
|
||||
s.SendWhoList()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -53,9 +58,9 @@ func (sub *Subscriber) ReadLoop(s *Server) {
|
|||
|
||||
// Read the user's posted message.
|
||||
var msg Message
|
||||
log.Debug("Read(%s): %s", sub.Username, data)
|
||||
log.Debug("Read(%d=%s): %s", sub.ID, sub.Username, data)
|
||||
if err := json.Unmarshal(data, &msg); err != nil {
|
||||
log.Error("Message error: %s", err)
|
||||
log.Error("Read(%d=%s) Message error: %s", sub.ID, sub.Username, err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -90,7 +95,7 @@ func (sub *Subscriber) SendJSON(v interface{}) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debug("SendJSON(%s): %s", sub.Username, data)
|
||||
log.Debug("SendJSON(%d=%s): %s", sub.ID, sub.Username, data)
|
||||
return sub.conn.Write(sub.ctx, websocket.MessageText, data)
|
||||
}
|
||||
|
||||
|
@ -115,15 +120,18 @@ func (sub *Subscriber) ChatServer(message string, v ...interface{}) {
|
|||
// WebSocket handles the /ws websocket connection.
|
||||
func (s *Server) WebSocket() http.HandlerFunc {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ip := util.IPAddress(r)
|
||||
log.Info("WebSocket connection from %s - %s", ip, r.Header.Get("User-Agent"))
|
||||
log.Debug("Headers: %+v", r.Header)
|
||||
c, err := websocket.Accept(w, r, nil)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
fmt.Fprintf(w, "Websocket error: %s", err)
|
||||
fmt.Fprintf(w, "Could not accept websocket connection: %s", err)
|
||||
return
|
||||
}
|
||||
defer c.Close(websocket.StatusInternalError, "the sky is falling")
|
||||
|
||||
log.Debug("WebSocket: %s has connected", r.RemoteAddr)
|
||||
log.Debug("WebSocket: %s has connected", ip)
|
||||
|
||||
// CloseRead starts a goroutine that will read from the connection
|
||||
// until it is closed.
|
||||
|
@ -141,7 +149,7 @@ func (s *Server) WebSocket() http.HandlerFunc {
|
|||
}
|
||||
|
||||
s.AddSubscriber(sub)
|
||||
// defer s.DeleteSubscriber(sub)
|
||||
defer s.DeleteSubscriber(sub)
|
||||
|
||||
go sub.ReadLoop(s)
|
||||
pinger := time.NewTicker(PingInterval)
|
||||
|
@ -174,7 +182,7 @@ func (s *Server) AddSubscriber(sub *Subscriber) {
|
|||
// Assign a unique ID.
|
||||
SubscriberID++
|
||||
sub.ID = SubscriberID
|
||||
log.Debug("AddSubscriber: %s", sub.ID)
|
||||
log.Debug("AddSubscriber: ID #%d", sub.ID)
|
||||
|
||||
s.subscribersMu.Lock()
|
||||
s.subscribers[sub] = struct{}{}
|
||||
|
@ -210,13 +218,10 @@ func (s *Server) DeleteSubscriber(sub *Subscriber) {
|
|||
// IterSubscribers loops over the subscriber list with a read lock. If the
|
||||
// caller already holds a lock, pass the optional `true` parameter for isLocked.
|
||||
func (s *Server) IterSubscribers(isLocked ...bool) []*Subscriber {
|
||||
log.Debug("IterSubscribers START..")
|
||||
|
||||
var result = []*Subscriber{}
|
||||
|
||||
// Has the caller already taken the read lock or do we get it?
|
||||
if locked := len(isLocked) > 0 && isLocked[0]; !locked {
|
||||
log.Debug("Taking the lock")
|
||||
s.subscribersMu.RLock()
|
||||
defer s.subscribersMu.RUnlock()
|
||||
}
|
||||
|
@ -225,7 +230,6 @@ func (s *Server) IterSubscribers(isLocked ...bool) []*Subscriber {
|
|||
result = append(result, sub)
|
||||
}
|
||||
|
||||
log.Debug("IterSubscribers STOP..")
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
@ -347,7 +347,8 @@ const app = Vue.createApp({
|
|||
|
||||
// Dial the WebSocket connection.
|
||||
dial() {
|
||||
// console.log("Dialing WebSocket...");
|
||||
this.ChatClient("Establishing connection to server...");
|
||||
|
||||
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
const conn = new WebSocket(`${proto}://${location.host}/ws`);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user