This commit is contained in:
parent
7c12459c5d
commit
c3b6be3124
|
@ -29,6 +29,7 @@ type conf struct {
|
|||
EditorChannel string
|
||||
OutputChannel string
|
||||
ShellChannel string
|
||||
SessionChannel string
|
||||
StaticResourceVersion string
|
||||
MaxProcs int
|
||||
RuntimeMode string
|
||||
|
@ -166,11 +167,14 @@ func Load() {
|
|||
}
|
||||
|
||||
glog.V(3).Infof("IP [%s]", ip)
|
||||
|
||||
// TODO: 弄个反射吧?
|
||||
Wide.Server = strings.Replace(Wide.Server, "{IP}", ip, 1)
|
||||
Wide.StaticServer = strings.Replace(Wide.StaticServer, "{IP}", ip, 1)
|
||||
Wide.EditorChannel = strings.Replace(Wide.EditorChannel, "{IP}", ip, 1)
|
||||
Wide.OutputChannel = strings.Replace(Wide.OutputChannel, "{IP}", ip, 1)
|
||||
Wide.ShellChannel = strings.Replace(Wide.ShellChannel, "{IP}", ip, 1)
|
||||
Wide.SessionChannel = strings.Replace(Wide.SessionChannel, "{IP}", ip, 1)
|
||||
|
||||
// 获取当前执行路径
|
||||
file, _ := exec.LookPath(os.Args[0])
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"EditorChannel": "ws://{IP}:7070",
|
||||
"OutputChannel": "ws://{IP}:7070",
|
||||
"ShellChannel": "ws://{IP}:7070",
|
||||
"SessionChannel": "ws://{IP}:7070",
|
||||
"StaticResourceVersion": "201409032040",
|
||||
"MaxProcs": 4,
|
||||
"RuntimeMode": "dev",
|
||||
|
|
|
@ -7,11 +7,10 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
for i := 0; i < 5; i++ {
|
||||
for i := 0; i < 50; i++ {
|
||||
fmt.Println("Hello, 世界", pkg.Now())
|
||||
|
||||
time.Sleep(time.Second)
|
||||
time.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -98,6 +98,7 @@ func main() {
|
|||
|
||||
// IDE 首页
|
||||
http.HandleFunc("/", indexHandler)
|
||||
http.HandleFunc("/session/ws", session.WSHandler)
|
||||
|
||||
// 运行相关
|
||||
http.HandleFunc("/build", output.BuildHandler)
|
||||
|
|
|
@ -105,9 +105,7 @@ func WSHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
output := ""
|
||||
|
||||
ret = map[string]interface{}{"output": output, "cmd": "notification-output"}
|
||||
ret = map[string]interface{}{"output": "", "cmd": "notification-output"}
|
||||
|
||||
if err := wsChan.Conn.WriteJSON(&ret); err != nil {
|
||||
glog.Error("Notification WS ERROR: " + err.Error())
|
||||
|
|
|
@ -8,20 +8,27 @@ package session
|
|||
|
||||
import (
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/b3log/wide/event"
|
||||
"github.com/b3log/wide/util"
|
||||
"github.com/golang/glog"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
const (
|
||||
SessionStateActive = iota // 会话状态:活的
|
||||
)
|
||||
|
||||
// 输出通道.
|
||||
// <sid, *util.WSChannel>
|
||||
var sessionWS = map[string]*util.WSChannel{}
|
||||
|
||||
// 用户 HTTP 会话,用于验证登录.
|
||||
var HTTPSession = sessions.NewCookieStore([]byte("BEYOND"))
|
||||
|
||||
|
@ -44,6 +51,65 @@ var WideSessions Sessions
|
|||
// 排它锁,防止并发修改.
|
||||
var mutex sync.Mutex
|
||||
|
||||
// 建立会话通道.
|
||||
// 通道断开时销毁会话状态,回收相关资源.
|
||||
func WSHandler(w http.ResponseWriter, r *http.Request) {
|
||||
sid := r.URL.Query()["sid"][0]
|
||||
wSession := WideSessions.Get(sid)
|
||||
if nil == wSession {
|
||||
glog.Errorf("Session [%s] not found", sid)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024)
|
||||
wsChan := util.WSChannel{Sid: sid, Conn: conn, Request: r, Time: time.Now()}
|
||||
|
||||
sessionWS[sid] = &wsChan
|
||||
|
||||
ret := map[string]interface{}{"output": "Ouput initialized", "cmd": "init-session"}
|
||||
wsChan.Conn.WriteJSON(&ret)
|
||||
|
||||
glog.V(4).Infof("Open a new [Session Channel] with session [%s], %d", sid, len(sessionWS))
|
||||
|
||||
input := map[string]interface{}{}
|
||||
|
||||
for {
|
||||
if err := wsChan.Conn.ReadJSON(&input); err != nil {
|
||||
glog.V(3).Infof("[Session Channel] of session [%s] disconnected, releases all resources with it", sid)
|
||||
|
||||
s := WideSessions.Get(sid)
|
||||
|
||||
// 关闭事件队列
|
||||
close(s.EventQueue.Queue)
|
||||
|
||||
// 杀进程
|
||||
for _, p := range s.Processes {
|
||||
if err := p.Kill(); nil != err {
|
||||
glog.Errorf("Can't kill process [%d] of session [%s]", p.Pid, sid)
|
||||
} else {
|
||||
glog.V(3).Infof("Killed a process [%d] of session [%s]", p.Pid, sid)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 回收相关通道
|
||||
|
||||
WideSessions.Remove(sid)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
ret = map[string]interface{}{"output": "", "cmd": "session-output"}
|
||||
|
||||
if err := wsChan.Conn.WriteJSON(&ret); err != nil {
|
||||
glog.Error("Session WS ERROR: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
wsChan.Time = time.Now()
|
||||
}
|
||||
}
|
||||
|
||||
// 设置会话关联的进程集.
|
||||
func (s *WideSession) SetProcesses(ps []*os.Process) {
|
||||
s.Processes = ps
|
||||
|
@ -105,7 +171,9 @@ func (sessions *Sessions) Remove(sid string) {
|
|||
if s.Id == sid {
|
||||
*sessions = append((*sessions)[:i], (*sessions)[i+1:]...)
|
||||
|
||||
glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions))
|
||||
glog.V(3).Infof("Removed a session [%s], has [%d] wide sessions currently", sid, len(*sessions))
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// 用于保持会话,如果该通道断开,则服务器端会销毁会话状态,回收相关资源.
|
||||
var sessionWS = new WebSocket(config.channel.session + '/session/ws?sid=' + config.wideSessionId);
|
||||
sessionWS.onopen = function () {
|
||||
console.log('[session onopen] connected');
|
||||
};
|
||||
|
||||
sessionWS.onmessage = function (e) {
|
||||
console.log('[session onmessage]' + e.data);
|
||||
var data = JSON.parse(e.data);
|
||||
|
||||
};
|
||||
sessionWS.onclose = function (e) {
|
||||
console.log('[session onclose] disconnected (' + e.code + ')');
|
||||
delete sessionWS;
|
||||
};
|
||||
sessionWS.onerror = function (e) {
|
||||
console.log('[session onerror] ' + JSON.parse(e));
|
||||
};
|
||||
|
|
@ -171,18 +171,19 @@
|
|||
channel: {
|
||||
editor: {{.conf.EditorChannel}},
|
||||
shell: {{.conf.ShellChannel}},
|
||||
output: {{.conf.OutputChannel}}
|
||||
output: {{.conf.OutputChannel}},
|
||||
session: {{.conf.SessionChannel}}
|
||||
},
|
||||
wideSessionId: {{.session.Id}}
|
||||
};
|
||||
// 发往 Wide 的所有 AJAX 请求需要使用该函数创建请求参数.
|
||||
function newWideRequest() {
|
||||
var ret = {
|
||||
function newWideRequest() {
|
||||
var ret = {
|
||||
sid: config.wideSessionId
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
|
||||
|
@ -225,6 +226,7 @@
|
|||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/notification.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/tree.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/wide.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/session.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/menu.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/hotkeys.js?{{.conf.StaticResourceVersion}}"></script>
|
||||
</body>
|
||||
|
|
Loading…
Reference in New Issue