func notificationWSHandler(w http.ResponseWriter, r *http.Request) { sid := r.URL.Query()["sid"][0] cSession := coditorSessions.get(sid) if nil == cSession { return } conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"notification": "Notification initialized", "cmd": "init-notification"} err := wsChan.WriteJSON(&ret) if nil != err { return } notificationWS[sid] = &wsChan logger.Tracef("Open a new [Notification] with session [%s], %d", sid, len(notificationWS)) // add user event handler cSession.EventQueue.addHandler(eventHandleFunc(event2Notification)) input := map[string]interface{}{} for { if err := wsChan.ReadJSON(&input); err != nil { return } } }
// WSHandler handles request of creating editor channel. // XXX: NOT used at present func WSHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") if httpSession.IsNew { http.Error(w, "Forbidden", http.StatusForbidden) return } sid := httpSession.Values["id"].(string) conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) editorChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"output": "Editor initialized", "cmd": "init-editor"} err := editorChan.WriteJSON(&ret) if nil != err { return } session.EditorWS[sid] = &editorChan logger.Tracef("Open a new [Editor] with session [%s], %d", sid, len(session.EditorWS)) args := map[string]interface{}{} for { if err := session.EditorWS[sid].ReadJSON(&args); err != nil { return } code := args["code"].(string) line := int(args["cursorLine"].(float64)) ch := int(args["cursorCh"].(float64)) offset := getCursorOffset(code, line, ch) logger.Tracef("offset: %d", offset) gocode := util.Go.GetExecutableInGOBIN("gocode") argv := []string{"-f=json", "autocomplete", strconv.Itoa(offset)} var output bytes.Buffer cmd := exec.Command(gocode, argv...) cmd.Stdout = &output stdin, _ := cmd.StdinPipe() cmd.Start() stdin.Write([]byte(code)) stdin.Close() cmd.Wait() ret = map[string]interface{}{"output": string(output.Bytes()), "cmd": "autocomplete"} if err := session.EditorWS[sid].WriteJSON(&ret); err != nil { logger.Error("Editor WS ERROR: " + err.Error()) return } } }
// WSHandler handles request of creating output channel. func WSHandler(w http.ResponseWriter, r *http.Request) { sid := r.URL.Query()["sid"][0] conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"output": "Ouput initialized", "cmd": "init-output"} err := wsChan.WriteJSON(&ret) if nil != err { return } session.OutputWS[sid] = &wsChan logger.Tracef("Open a new [Output] with session [%s], %d", sid, len(session.OutputWS)) }
// WSHandler handles request of creating session channel. // // When a channel closed, releases all resources associated with it. func WSHandler(w http.ResponseWriter, r *http.Request) { sid := r.URL.Query()["sid"][0] conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"output": "Session initialized", "cmd": "init-session"} err := wsChan.WriteJSON(&ret) if nil != err { return } SessionWS[sid] = &wsChan wSession := WideSessions.Get(sid) if nil == wSession { httpSession, _ := HTTPSession.Get(r, "wide-session") if httpSession.IsNew { return } httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Save(r, w) wSession = WideSessions.new(httpSession, sid) logger.Tracef("Created a wide session [%s] for websocket reconnecting, user [%s]", sid, wSession.Username) } logger.Tracef("Open a new [Session Channel] with session [%s], %d", sid, len(SessionWS)) input := map[string]interface{}{} for { if err := wsChan.ReadJSON(&input); err != nil { logger.Tracef("[Session Channel] of session [%s] disconnected, releases all resources with it, user [%s]", sid, wSession.Username) WideSessions.Remove(sid) return } ret = map[string]interface{}{"output": "", "cmd": "session-output"} if err := wsChan.WriteJSON(&ret); err != nil { logger.Error("Session WS ERROR: " + err.Error()) return } wsChan.Time = time.Now() } }
// WSHandler handles request of creating Shell channel. func WSHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := session.HTTPSession.Get(r, "wide-session") if httpSession.IsNew { http.Error(w, "Forbidden", http.StatusForbidden) return } username := httpSession.Values["username"].(string) sid := r.URL.Query()["sid"][0] conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"output": "Shell initialized", "cmd": "init-shell"} err := wsChan.WriteJSON(&ret) if nil != err { return } ShellWS[sid] = &wsChan logger.Debugf("Open a new [Shell] with session [%s], %d", sid, len(ShellWS)) input := map[string]interface{}{} for { if err := wsChan.ReadJSON(&input); err != nil { logger.Error("Shell WS ERROR: " + err.Error()) return } inputCmd := input["cmd"].(string) cmds := strings.Split(inputCmd, "|") commands := []*exec.Cmd{} for _, cmdWithArgs := range cmds { cmdWithArgs = strings.TrimSpace(cmdWithArgs) cmdWithArgs := strings.Split(cmdWithArgs, " ") args := []string{} if len(cmdWithArgs) > 1 { args = cmdWithArgs[1:] } cmd := exec.Command(cmdWithArgs[0], args...) commands = append(commands, cmd) } output := "" if !strings.Contains(inputCmd, "clear") { output = pipeCommands(username, commands...) } ret = map[string]interface{}{"output": output, "cmd": "shell-output"} if err := wsChan.WriteJSON(&ret); err != nil { logger.Error("Shell WS ERROR: " + err.Error()) return } wsChan.Refresh() } }
// WSHandler handles request of creating session channel. // // When a channel closed, releases all resources associated with it. func WSHandler(w http.ResponseWriter, r *http.Request) { sid := r.URL.Query()["sid"][0] conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"output": "Session initialized", "cmd": "init-session"} err := wsChan.WriteJSON(&ret) if nil != err { return } SessionWS[sid] = &wsChan wSession := WideSessions.Get(sid) if nil == wSession { httpSession, _ := HTTPSession.Get(r, "wide-session") if httpSession.IsNew { return } httpSession.Options.MaxAge = conf.Wide.HTTPSessionMaxAge httpSession.Save(r, w) wSession = WideSessions.new(httpSession, sid) logger.Tracef("Created a wide session [%s] for websocket reconnecting, user [%s]", sid, wSession.Username) } logger.Tracef("Open a new [Session Channel] with session [%s], %d", sid, len(SessionWS)) input := map[string]interface{}{} wsChan.Conn.SetReadDeadline(time.Now().Add(pongWait)) wsChan.Conn.SetPongHandler(func(string) error { wsChan.Conn.SetReadDeadline(time.Now().Add(pongWait)); return nil }) ticker := time.NewTicker(pingPeriod) defer func() { WideSessions.Remove(sid) ticker.Stop() wsChan.Close() }() // send websocket ping message. go func(t *time.Ticker, channel util.WSChannel) { for { select { case <-t.C: if err := channel.Conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil { return } } } }(ticker, wsChan) for { if err := wsChan.ReadJSON(&input); err != nil { logger.Tracef("[Session Channel] of session [%s] disconnected, releases all resources with it, user [%s]", sid, wSession.Username) return } ret = map[string]interface{}{"output": "", "cmd": "session-output"} if err := wsChan.WriteJSON(&ret); err != nil { logger.Error("Session WS ERROR: " + err.Error()) return } wsChan.Time = time.Now() } }
func editorWSHandler(w http.ResponseWriter, r *http.Request) { httpSession, _ := httpSessionStore.Get(r, "coditor-session") userSession := httpSession.Values[user_session] if nil == userSession { http.Error(w, "Forbidden", http.StatusForbidden) return } sid := r.URL.Query()["sid"][0] cSession := coditorSessions.get(sid) if nil == cSession { return } conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()} ret := map[string]interface{}{"editor": "Editor initialized", "cmd": "init-editor"} err := wsChan.WriteJSON(&ret) if nil != err { return } editorWS[sid] = &wsChan logger.Tracef("Open a new [Editor] with session [%s], %d", sid, len(editorWS)) input := map[string]interface{}{} userName := coditorSessions.get(sid).Username for { if err := wsChan.ReadJSON(&input); err != nil { return } //logger.Trace(input) docName := input["docName"].(string) docName = filepath.Clean(docName) doc := documentHolder.getDoc(docName) err := doc.setContent(input["content"].(string), userName) if err != nil { // TODO maybe should send error here logger.Errorf("set document error %v", err) continue } for _, cursor := range doc.cursors { if cursor.Sid == sid { // skip the current session itself continue } content := input["content"].(string) ret = map[string]interface{}{"content": content, "cmd": "changes", "docName": docName, "user": input["user"], "cursor": input["cursor"], "color": input["color"]} if err := editorWS[cursor.Sid].WriteJSON(&ret); err != nil { logger.Error("[Editor Channel] ERROR: " + err.Error()) return } } wsChan.Time = time.Now() } }