// handle receives messages on the given websocket connection, decoding them // from JSON to a Msg object. It adds a channel to listeners, encoding messages // received on the listener channel as JSON, then sending it over the connection. func (r *Router) HandleWebsocket(c *websocket.Conn) { u, err := url.Parse(c.LocalAddr().String()) if err != nil { log.Println(err) return } // split url path into components, e.g. // url: http://leeps.ucsc.edu/redwood/session/1/[email protected] // path: /redwood/session/1/[email protected] // -> [redwood, session, 1, [email protected]] components := strings.Split(u.Path, "/") // map components into instance_prefix, session_id, and subject_name var instance, session_id_string, subject_name string if len(components) >= 4 { instance = components[1] session_id_string = components[2] subject_name = components[3] } else { session_id_string = components[1] subject_name = components[2] } session_id, err := strconv.Atoi(session_id_string) if err != nil { log.Println(err) return } var subject *Subject if subject_name == "admin" || subject_name == "listener" { subject = &Subject{name: subject_name, period: -1, group: -1} } else { // put in a request to the server loop for the given subject object // this ensures only one subject object exists per session/name pair request := &SubjectRequest{instance: instance, session: session_id, name: subject_name, response: make(chan *Subject)} r.requestSubject <- request subject = <-request.response } if subject == nil { log.Panicln("nil subject") } listener := NewListener(r, instance, session_id, subject, c) ack := make(chan bool) r.newListeners <- &ListenerRequest{listener, ack} // wait for listener to be registered before starting sync <-ack log.Printf("STARTED SYNC: %s\n", subject.name) listener.Sync() log.Printf("FINISHED SYNC: %s\n", subject.name) go listener.SendLoop() listener.ReceiveLoop() }