44 "errors"
55 "log"
66 "net/http"
7- "strings"
87 "time"
9- "unicode"
108)
119
1210// HandleWS handles WebSocket connection upgrades and message processing.
@@ -68,9 +66,7 @@ func (h *Hub) HandleWS(w http.ResponseWriter, r *http.Request) {
6866func (h * Hub ) handleMessage (client * Client , msg Message ) error {
6967 // Rate limit check
7068 if ! client .checkRateLimit () {
71- if err := client .sendError (ErrRateLimited ); err != nil {
72- log .Printf ("signal: failed to send rate_limited error to conn=%d: %v" , client .connID , err )
73- }
69+ _ = client .sendErrorAndLog (ErrRateLimited )
7470 return errors .New ("rate limited" )
7571 }
7672
@@ -85,143 +81,7 @@ func (h *Hub) handleMessage(client *Client, msg Message) error {
8581 case MsgTypeOffer , MsgTypeAnswer , MsgTypeCandidate , MsgTypeHangup :
8682 return h .forward (client , msg )
8783 default :
88- if err := client .sendError (ErrUnknownType ); err != nil {
89- log .Printf ("signal: failed to send unknown_type error to conn=%d: %v" , client .connID , err )
90- }
84+ _ = client .sendErrorAndLog (ErrUnknownType )
9185 return errors .New ("unknown message type" )
9286 }
9387}
94-
95- // handleJoin processes a join request.
96- func (h * Hub ) handleJoin (c * Client , msg Message ) error {
97- id := normalizeClientID (msg .From , MaxClientIDLength )
98- if id == "" {
99- if err := c .sendError (ErrInvalidID ); err != nil {
100- log .Printf ("signal: failed to send invalid_id error to conn=%d: %v" , c .connID , err )
101- }
102- return errors .New ("invalid client id" )
103- }
104- room := normalizeRoomName (msg .Room , MaxRoomIDLength )
105- if room == "" {
106- if err := c .sendError (ErrInvalidRoom ); err != nil {
107- log .Printf ("signal: failed to send invalid_room error to conn=%d: %v" , c .connID , err )
108- }
109- return errors .New ("invalid room" )
110- }
111-
112- boundID , currentRoom := c .identity ()
113- if boundID != "" && boundID != id {
114- if err := c .sendError (ErrIdentityLocked ); err != nil {
115- log .Printf ("signal: failed to send identity_locked error to conn=%d: %v" , c .connID , err )
116- }
117- return errors .New ("identity mismatch" )
118- }
119- if currentRoom != "" && currentRoom != room {
120- if err := c .sendError (ErrAlreadyJoined ); err != nil {
121- log .Printf ("signal: failed to send already_joined error to conn=%d: %v" , c .connID , err )
122- }
123- return errors .New ("already joined" )
124- }
125-
126- c .setIdentity (id , room )
127- if err := h .addClient (c ); err != nil {
128- c .setIdentity ("" , "" ) // Clear both id and room on failure
129- if sendErr := c .sendError (err ); sendErr != nil {
130- log .Printf ("signal: failed to send %s error to conn=%d: %v" , err .Code , c .connID , sendErr )
131- }
132- return err
133- }
134- if err := c .enqueue (Message {Type : MsgTypeJoined , Room : room , From : id }); err != nil {
135- return err
136- }
137- h .broadcastMembers (room )
138- return nil
139- }
140-
141- // forward routes signaling messages between clients.
142- func (h * Hub ) forward (sender * Client , msg Message ) error {
143- id , room := sender .identity ()
144- if id == "" || room == "" {
145- if err := sender .sendError (ErrNotJoined ); err != nil {
146- log .Printf ("signal: failed to send not_joined error to conn=%d: %v" , sender .connID , err )
147- }
148- return errors .New ("sender not joined" )
149- }
150- to := normalizeClientID (msg .To , MaxClientIDLength )
151- if to == "" || to == id {
152- if err := sender .sendError (ErrInvalidTarget ); err != nil {
153- log .Printf ("signal: failed to send invalid_target error to conn=%d: %v" , sender .connID , err )
154- }
155- return errors .New ("invalid target" )
156- }
157-
158- h .mu .RLock ()
159- m , ok := h .rooms [room ]
160- if ! ok {
161- h .mu .RUnlock ()
162- if err := sender .sendError (ErrRoomMissing ); err != nil {
163- log .Printf ("signal: failed to send room_missing error to conn=%d: %v" , sender .connID , err )
164- }
165- return errors .New ("room missing" )
166- }
167- current , ok := m [id ]
168- if ! ok || current != sender {
169- h .mu .RUnlock ()
170- if err := sender .sendError (ErrMembershipLost ); err != nil {
171- log .Printf ("signal: failed to send membership_lost error to conn=%d: %v" , sender .connID , err )
172- }
173- return errors .New ("sender not registered" )
174- }
175- dst , ok := m [to ]
176- h .mu .RUnlock ()
177- if ! ok || dst == nil {
178- if err := sender .sendError (ErrTargetNotFound ); err != nil {
179- log .Printf ("signal: failed to send target_not_found error to conn=%d: %v" , sender .connID , err )
180- }
181- return errors .New ("target not found" )
182- }
183-
184- msg .Room = room
185- msg .From = id
186- msg .To = to
187- if err := dst .enqueue (msg ); err != nil {
188- log .Printf ("signal: forward failed room=%s from=%s to=%s: %v" , room , id , to , err )
189- h .removeClient (dst )
190- dst .close ()
191- return err
192- }
193- return nil
194- }
195-
196- // normalizeClientID validates and normalizes a client ID.
197- func normalizeClientID (raw string , maxLen int ) string {
198- trimmed := strings .TrimSpace (raw )
199- if trimmed == "" || len (trimmed ) > maxLen {
200- return ""
201- }
202- for _ , r := range trimmed {
203- switch {
204- case r >= 'a' && r <= 'z' :
205- case r >= 'A' && r <= 'Z' :
206- case r >= '0' && r <= '9' :
207- case r == '-' , r == '_' :
208- default :
209- return ""
210- }
211- }
212- return trimmed
213- }
214-
215- // normalizeRoomName validates and normalizes a room name.
216- func normalizeRoomName (raw string , maxLen int ) string {
217- trimmed := strings .TrimSpace (raw )
218- if trimmed == "" || len (trimmed ) > maxLen {
219- return ""
220- }
221- for _ , r := range trimmed {
222- if unicode .IsControl (r ) {
223- return ""
224- }
225- }
226- return trimmed
227- }
0 commit comments