add DialConnRaw + RecvRaw for direct transport access in WASM

This commit is contained in:
realrasengan
2026-03-30 20:55:37 -07:00
parent 8d9bc2eba0
commit f70f18fc3f
2 changed files with 48 additions and 6 deletions
+42
View File
@@ -106,6 +106,48 @@ func DialConnManual(conn Conn, ocb *OCB) (*Client, error) {
return c, nil
}
// DialConnRaw creates a mosh client with no internal goroutines.
// The caller must call Tick() for sending AND RecvRaw() for receiving.
// Use this when the caller needs raw transport diffs (e.g., for
// framebuffer state tracking in the WASM client).
func DialConnRaw(conn Conn, ocb *OCB) (*Client, error) {
c := &Client{
conn: conn,
transport: NewTransport(ocb, false),
ocb: ocb,
outputC: make(chan struct{}, 1),
done: make(chan struct{}),
sentActionCounts: make(map[uint64]int),
}
c.transport.ForceNextSend()
c.tick()
return c, nil
}
// RecvRaw reads one datagram from the connection and processes it
// through the transport. Returns the raw diff payload, or nil if
// no complete message was received (timeout, fragment, replay).
// The caller can use Transport().LastRecvOldNum()/LastRecvNewNum()
// to get the state numbers for this diff.
func (c *Client) RecvRaw(timeout time.Duration) []byte {
buf := make([]byte, maxPayload+64)
c.conn.SetReadDeadline(time.Now().Add(timeout))
n, err := c.conn.Read(buf)
if err != nil {
return nil
}
if n < minDatagram {
return nil
}
data := make([]byte, n)
copy(data, buf[:n])
return c.transport.Recv(data)
}
// Send sends keystrokes to the server.
func (c *Client) Send(keys []byte) {
c.actionsMu.Lock()
+6 -6
View File
@@ -73,7 +73,7 @@ func newSession(url, key string, cols, rows int) (*session, error) {
return nil, err
}
client, err := mosh.DialConnManual(conn, ocb)
client, err := mosh.DialConnRaw(conn, ocb)
if err != nil {
conn.Close()
return nil, err
@@ -141,12 +141,12 @@ func (s *session) jsObject() js.Value {
return obj
}
// recvLoop reads raw diffs from the mosh client and feeds them
// to the state tracker for framebuffer-based processing.
// recvLoop reads raw transport diffs and feeds them to the state
// tracker for framebuffer-based processing.
func (s *session) recvLoop() {
for {
out := s.client.Recv(60 * time.Second)
if out == nil {
diff := s.client.RecvRaw(1 * time.Second)
if diff == nil {
s.mu.Lock()
closed := s.closed
s.mu.Unlock()
@@ -158,7 +158,7 @@ func (s *session) recvLoop() {
t := s.client.Transport()
oldNum := t.LastRecvOldNum()
newNum := t.LastRecvNewNum()
s.tracker.applyDiff(out, oldNum, newNum)
s.tracker.applyDiff(diff, oldNum, newNum)
}
}