mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-25 17:18:02 +01:00
187 lines
5.0 KiB
Go
187 lines
5.0 KiB
Go
package sstore
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
var MainBus *UpdateBus = MakeUpdateBus()
|
|
|
|
const PtyDataUpdateStr = "pty"
|
|
const ModelUpdateStr = "model"
|
|
const UpdateChSize = 100
|
|
|
|
type UpdatePacket interface {
|
|
UpdateType() string
|
|
}
|
|
|
|
type PtyDataUpdate struct {
|
|
SessionId string `json:"sessionid,omitempty"`
|
|
CmdId string `json:"cmdid,omitempty"`
|
|
RemoteId string `json:"remoteid,omitempty"`
|
|
PtyPos int64 `json:"ptypos"`
|
|
PtyData64 string `json:"ptydata64"`
|
|
PtyDataLen int64 `json:"ptydatalen"`
|
|
}
|
|
|
|
func (PtyDataUpdate) UpdateType() string {
|
|
return PtyDataUpdateStr
|
|
}
|
|
|
|
type ModelUpdate struct {
|
|
Sessions []*SessionType `json:"sessions,omitempty"`
|
|
ActiveSessionId string `json:"activesessionid,omitempty"`
|
|
Window *WindowType `json:"window,omitempty"`
|
|
ScreenWindows []*ScreenWindowType `json:"screenwindows,omitempty"`
|
|
Line *LineType `json:"line,omitempty"`
|
|
Cmd *CmdType `json:"cmd,omitempty"`
|
|
CmdLine *CmdLineType `json:"cmdline,omitempty"`
|
|
Info *InfoMsgType `json:"info,omitempty"`
|
|
ClearInfo bool `json:"clearinfo,omitempty"`
|
|
Remotes []interface{} `json:"remotes,omitempty"` // []*remote.RemoteState
|
|
History *HistoryInfoType `json:"history,omitempty"`
|
|
Interactive bool `json:"interactive"`
|
|
Connect bool `json:"connect,omitempty"`
|
|
}
|
|
|
|
func (ModelUpdate) UpdateType() string {
|
|
return ModelUpdateStr
|
|
}
|
|
|
|
func ReadHistoryDataFromUpdate(update UpdatePacket) (string, string, *RemotePtrType) {
|
|
modelUpdate, ok := update.(ModelUpdate)
|
|
if !ok {
|
|
return "", "", nil
|
|
}
|
|
if modelUpdate.Line == nil {
|
|
return "", "", nil
|
|
}
|
|
var rptr *RemotePtrType
|
|
if modelUpdate.Cmd != nil {
|
|
rptr = &modelUpdate.Cmd.Remote
|
|
}
|
|
return modelUpdate.Line.LineId, modelUpdate.Line.CmdId, rptr
|
|
}
|
|
|
|
func InfoMsgUpdate(infoMsgFmt string, args ...interface{}) *ModelUpdate {
|
|
msg := fmt.Sprintf(infoMsgFmt, args...)
|
|
return &ModelUpdate{
|
|
Info: &InfoMsgType{InfoMsg: msg},
|
|
}
|
|
}
|
|
|
|
type RemoteEditType struct {
|
|
RemoteEdit bool `json:"remoteedit"`
|
|
RemoteId string `json:"remoteid,omitempty"`
|
|
ErrorStr string `json:"errorstr,omitempty"`
|
|
InfoStr string `json:"infostr,omitempty"`
|
|
KeyStr string `json:"keystr,omitempty"`
|
|
HasPassword bool `json:"haspassword,omitempty"`
|
|
}
|
|
|
|
type InfoMsgType struct {
|
|
InfoTitle string `json:"infotitle"`
|
|
InfoError string `json:"infoerror,omitempty"`
|
|
InfoMsg string `json:"infomsg,omitempty"`
|
|
InfoComps []string `json:"infocomps,omitempty"`
|
|
InfoCompsMore bool `json:"infocompssmore,omitempty"`
|
|
InfoLines []string `json:"infolines,omitempty"`
|
|
TimeoutMs int64 `json:"timeoutms,omitempty"`
|
|
PtyRemoteId string `json:"ptyremoteid,omitempty"`
|
|
RemoteShowAll bool `json:"remoteshowall,omitempty"`
|
|
RemoteEdit *RemoteEditType `json:"remoteedit,omitempty"`
|
|
}
|
|
|
|
type HistoryInfoType struct {
|
|
HistoryType string `json:"historytype"`
|
|
SessionId string `json:"sessionid,omitempty"`
|
|
WindowId string `json:"windowid,omitempty"`
|
|
Items []*HistoryItemType `json:"items"`
|
|
Show bool `json:"show"`
|
|
}
|
|
|
|
type CmdLineType struct {
|
|
CmdLine string `json:"cmdline"`
|
|
CursorPos int `json:"cursorpos"`
|
|
}
|
|
|
|
type UpdateChannel struct {
|
|
SessionId string
|
|
ClientId string
|
|
Ch chan interface{}
|
|
}
|
|
|
|
func (uch UpdateChannel) Match(sessionId string) bool {
|
|
if sessionId == "" {
|
|
return true
|
|
}
|
|
return sessionId == uch.SessionId
|
|
}
|
|
|
|
type UpdateBus struct {
|
|
Lock *sync.Mutex
|
|
Channels map[string]UpdateChannel
|
|
}
|
|
|
|
func MakeUpdateBus() *UpdateBus {
|
|
return &UpdateBus{
|
|
Lock: &sync.Mutex{},
|
|
Channels: make(map[string]UpdateChannel),
|
|
}
|
|
}
|
|
|
|
// always returns a new channel
|
|
func (bus *UpdateBus) RegisterChannel(clientId string, sessionId string) chan interface{} {
|
|
bus.Lock.Lock()
|
|
defer bus.Lock.Unlock()
|
|
uch, found := bus.Channels[clientId]
|
|
if found {
|
|
close(uch.Ch)
|
|
uch.SessionId = sessionId
|
|
uch.Ch = make(chan interface{}, UpdateChSize)
|
|
} else {
|
|
uch = UpdateChannel{
|
|
ClientId: clientId,
|
|
SessionId: sessionId,
|
|
Ch: make(chan interface{}, UpdateChSize),
|
|
}
|
|
}
|
|
bus.Channels[clientId] = uch
|
|
return uch.Ch
|
|
}
|
|
|
|
func (bus *UpdateBus) UnregisterChannel(clientId string) {
|
|
bus.Lock.Lock()
|
|
defer bus.Lock.Unlock()
|
|
uch, found := bus.Channels[clientId]
|
|
if found {
|
|
close(uch.Ch)
|
|
delete(bus.Channels, clientId)
|
|
}
|
|
}
|
|
|
|
func (bus *UpdateBus) SendUpdate(sessionId string, update interface{}) {
|
|
bus.Lock.Lock()
|
|
defer bus.Lock.Unlock()
|
|
for _, uch := range bus.Channels {
|
|
if uch.Match(sessionId) {
|
|
select {
|
|
case uch.Ch <- update:
|
|
|
|
default:
|
|
log.Printf("[error] dropped update on updatebus uch clientid=%s\n", uch.ClientId)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func MakeSessionsUpdateForRemote(sessionId string, ri *RemoteInstance) []*SessionType {
|
|
return []*SessionType{
|
|
&SessionType{
|
|
SessionId: sessionId,
|
|
Remotes: []*RemoteInstance{ri},
|
|
},
|
|
}
|
|
}
|