websocket-based lrcproto server

add nonces to init message based on secret/uri option

+16
crypto.go
··· 1 + package lrcd 2 + 3 + import ( 4 + "crypto/sha256" 5 + "encoding/binary" 6 + ) 7 + 8 + func GenerateNonce(messageID uint32, channelURI string, secret string) []byte { 9 + h := sha256.New() 10 + idBytes := make([]byte, 4) 11 + binary.LittleEndian.PutUint32(idBytes, messageID) 12 + h.Write(idBytes) 13 + h.Write([]byte(channelURI)) 14 + h.Write([]byte(secret)) 15 + return h.Sum(nil) 16 + }
+1 -1
go.mod
··· 4 4 5 5 require ( 6 6 github.com/gorilla/websocket v1.5.3 7 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c 7 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709 8 8 google.golang.org/protobuf v1.36.6 9 9 )
+2 -2
go.sum
··· 2 2 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 3 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 4 4 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 5 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c h1:nOWeKeE7wph0IcwUyUBi0YBynUnAo4JW/J5DM88x4KM= 6 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw= 5 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709 h1:P//gJE0zFv9Qvfn8dvp9ZrnG0FZh2MVcAX+uOP2flRw= 6 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709/go.mod h1:hQzO36tQELGbkmRnUtKeM6NMU34t79ZcTlhM+MO7pHw= 7 7 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 8 8 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 9 9 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+10
options.go
··· 9 9 ) 10 10 11 11 type options struct { 12 + uri string 13 + secret string 12 14 welcome *string 13 15 writer *io.Writer 14 16 verbose bool ··· 66 68 return nil 67 69 } 68 70 } 71 + 72 + func WithServerURIAndSecret(uri string, secret string) Option { 73 + return func(options *options) error { 74 + options.secret = secret 75 + options.uri = uri 76 + return nil 77 + } 78 + }
+6
server.go
··· 14 14 ) 15 15 16 16 type Server struct { 17 + secret string 18 + uri string 17 19 eventBus chan clientEvent 18 20 ctx context.Context 19 21 cancel context.CancelFunc ··· 88 90 if options.initialID != nil { 89 91 s.lastID = *options.initialID 90 92 } 93 + s.uri = options.uri 94 + s.secret = options.secret 91 95 92 96 s.clients = make(map[*client]bool) 93 97 s.clientsMu = sync.Mutex{} ··· 331 335 msg.Init.Color = client.color 332 336 echoed := false 333 337 msg.Init.Echoed = &echoed 338 + msg.Init.Nonce = nil 334 339 if s.initChan != nil { 335 340 select { 336 341 case s.initChan <- *msg: ··· 348 353 stdData, _ := proto.Marshal(stdEvent) 349 354 echoed := true 350 355 msg.Init.Echoed = &echoed 356 + msg.Init.Nonce = GenerateNonce(*msg.Init.Id, s.uri, s.secret) 351 357 echoEvent := &lrcpb.Event{Msg: msg} 352 358 echoData, _ := proto.Marshal(echoEvent) 353 359 muteEvent := &lrcpb.Event{Msg: &lrcpb.Event_Mute{Mute: &lrcpb.Mute{Id: msg.Init.GetId()}}}