websocket-based lrcproto server

add nonces to init message based on secret/uri option

+35 -3
+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 5 require ( 6 github.com/gorilla/websocket v1.5.3 7 - github.com/rachel-mp4/lrcproto v0.0.0-20250527205756-58da8216f98c 8 google.golang.org/protobuf v1.36.6 9 )
··· 4 5 require ( 6 github.com/gorilla/websocket v1.5.3 7 + github.com/rachel-mp4/lrcproto v0.0.0-20250720164211-c6162669b709 8 google.golang.org/protobuf v1.36.6 9 )
+2 -2
go.sum
··· 2 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 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= 7 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 8 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 9 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
··· 2 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 3 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 4 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 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 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= 8 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 9 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+10
options.go
··· 9 ) 10 11 type options struct { 12 welcome *string 13 writer *io.Writer 14 verbose bool ··· 66 return nil 67 } 68 }
··· 9 ) 10 11 type options struct { 12 + uri string 13 + secret string 14 welcome *string 15 writer *io.Writer 16 verbose bool ··· 68 return nil 69 } 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 ) 15 16 type Server struct { 17 eventBus chan clientEvent 18 ctx context.Context 19 cancel context.CancelFunc ··· 88 if options.initialID != nil { 89 s.lastID = *options.initialID 90 } 91 92 s.clients = make(map[*client]bool) 93 s.clientsMu = sync.Mutex{} ··· 331 msg.Init.Color = client.color 332 echoed := false 333 msg.Init.Echoed = &echoed 334 if s.initChan != nil { 335 select { 336 case s.initChan <- *msg: ··· 348 stdData, _ := proto.Marshal(stdEvent) 349 echoed := true 350 msg.Init.Echoed = &echoed 351 echoEvent := &lrcpb.Event{Msg: msg} 352 echoData, _ := proto.Marshal(echoEvent) 353 muteEvent := &lrcpb.Event{Msg: &lrcpb.Event_Mute{Mute: &lrcpb.Mute{Id: msg.Init.GetId()}}}
··· 14 ) 15 16 type Server struct { 17 + secret string 18 + uri string 19 eventBus chan clientEvent 20 ctx context.Context 21 cancel context.CancelFunc ··· 90 if options.initialID != nil { 91 s.lastID = *options.initialID 92 } 93 + s.uri = options.uri 94 + s.secret = options.secret 95 96 s.clients = make(map[*client]bool) 97 s.clientsMu = sync.Mutex{} ··· 335 msg.Init.Color = client.color 336 echoed := false 337 msg.Init.Echoed = &echoed 338 + msg.Init.Nonce = nil 339 if s.initChan != nil { 340 select { 341 case s.initChan <- *msg: ··· 353 stdData, _ := proto.Marshal(stdEvent) 354 echoed := true 355 msg.Init.Echoed = &echoed 356 + msg.Init.Nonce = GenerateNonce(*msg.Init.Id, s.uri, s.secret) 357 echoEvent := &lrcpb.Event{Msg: msg} 358 echoData, _ := proto.Marshal(echoEvent) 359 muteEvent := &lrcpb.Event{Msg: &lrcpb.Event_Mute{Mute: &lrcpb.Mute{Id: msg.Init.GetId()}}}