Example #1
0
// 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()
}