Skip to content

Commit

Permalink
Renaming of configs to sessions, some improved error handing, better …
Browse files Browse the repository at this point in the history
…use of shared session struct
  • Loading branch information
maxmcd committed Nov 12, 2018
1 parent a8d8275 commit 1f1f2e1
Show file tree
Hide file tree
Showing 11 changed files with 257 additions and 294 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
version: 2
jobs:
build:
test:
docker:
- image: maxmcd/webrtty-node-go:latest
working_directory: /go/src/github.com/maxmcd/webrtty
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.DS_Store
/webrtty
coverage.out
mutterings.md

3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ FROM golang:1.11.2-stretch

RUN apt-get update && \
curl -sL https://deb.nodesource.com/setup_11.x | bash -\
&& apt-get install -y nodejs libssl-dev build-essential
&& apt-get install -y nodejs libssl-dev

103 changes: 45 additions & 58 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,10 @@ import (
"golang.org/x/crypto/ssh/terminal"
)

type clientConfig struct {
dc *webrtc.RTCDataChannel
errChan chan error
isTerminal bool
oldTerminalState *terminal.State
pc *webrtc.RTCPeerConnection
offer sd.SessionDescription
type clientSession struct {
session
dc *webrtc.RTCDataChannel
offerString string
}

func sendTermSize(term *os.File, dcSend func(p datachannel.Payload) error) error {
Expand All @@ -36,131 +33,119 @@ func sendTermSize(term *os.File, dcSend func(p datachannel.Payload) error) error
return dcSend(datachannel.PayloadString{Data: []byte(size)})
}

func (cc *clientConfig) dataChannelOnOpen() func() {
func (cs *clientSession) dataChannelOnOpen() func() {
return func() {
log.Printf("Data channel '%s'-'%d'='%d' open.\n", cc.dc.Label, cc.dc.ID, *cc.dc.MaxPacketLifeTime)
log.Printf("Data channel '%s'-'%d'='%d' open.\n", cs.dc.Label, cs.dc.ID, *cs.dc.MaxPacketLifeTime)
colorstring.Println("[bold]Terminal session started:")
oldTerminalState, err := terminal.MakeRaw(int(os.Stdin.Fd()))
if err != nil {

if err := cs.makeRawTerminal(); err != nil {
log.Println(err)
cc.errChan <- err
cs.errChan <- err
}
defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldTerminalState) }() // Best effort.

ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGWINCH)
go func() {
for range ch {
err := sendTermSize(os.Stdin, cc.dc.Send)
err := sendTermSize(os.Stdin, cs.dc.Send)
if err != nil {
log.Println(err)
cc.errChan <- err
cs.errChan <- err
}
}
}()
ch <- syscall.SIGWINCH // Initial resize.
clearTerminal()
buf := make([]byte, 1024)
for {
nr, err := os.Stdin.Read(buf)
if err != nil {
log.Println(err)
cc.errChan <- err
cs.errChan <- err
}
err = cc.dc.Send(datachannel.PayloadBinary{Data: buf[0:nr]})
err = cs.dc.Send(datachannel.PayloadBinary{Data: buf[0:nr]})
if err != nil {
log.Println(err)
cc.errChan <- err
cs.errChan <- err
}
}
}
}

func (cc *clientConfig) dataChannelOnMessage() func(payload datachannel.Payload) {
func (cs *clientSession) dataChannelOnMessage() func(payload datachannel.Payload) {
return func(payload datachannel.Payload) {
switch p := payload.(type) {
case *datachannel.PayloadString:
if string(p.Data) == "quit" {
if cc.isTerminal {
terminal.Restore(int(os.Stdin.Fd()), cc.oldTerminalState)
if cs.isTerminal {
terminal.Restore(int(os.Stdin.Fd()), cs.oldTerminalState)
}
cc.errChan <- nil
cs.errChan <- nil
return
}
cc.errChan <- fmt.Errorf(`Unmatched string message: "%s"`, string(p.Data))
cs.errChan <- fmt.Errorf(`Unmatched string message: "%s"`, string(p.Data))
case *datachannel.PayloadBinary:
f := bufio.NewWriter(os.Stdout)
f.Write(p.Data)
f.Flush()
// fmt.Printf("Message '%s' from DataChannel '%s' payload '% 02x'\n", p.PayloadType().String(), dc.Label, p.Data)
default:
fmt.Printf("Message '%s' from DataChannel no payload \n", p.PayloadType().String())
cs.errChan <- fmt.Errorf(
"Message with type %s from DataChannel has no payload",
p.PayloadType().String())
}
}
}

func (cc *clientConfig) runClient(offerString string) (err error) {
cc.isTerminal = terminal.IsTerminal(int(os.Stdin.Fd()))
if cc.pc, err = createPeerConnection(); err != nil {
log.Println(err)
func (cs *clientSession) run() (err error) {
if err = cs.init(); err != nil {
return
}
// Set the remote SessionDescription
maxPacketLifeTime := uint16(1000)

maxPacketLifeTime := uint16(1000) // Arbitrary
ordered := true
if cc.dc, err = cc.pc.CreateDataChannel("data", &webrtc.RTCDataChannelInit{
if cs.dc, err = cs.pc.CreateDataChannel("data", &webrtc.RTCDataChannelInit{
Ordered: &ordered,
MaxPacketLifeTime: &maxPacketLifeTime,
}); err != nil {
log.Println(err)
return
}

cc.errChan = make(chan error, 1)

if cc.isTerminal {
if cc.oldTerminalState, err = terminal.GetState(int(os.Stdin.Fd())); err != nil {
log.Println(err)
return err
}
}

cc.dc.Lock()
cc.dc.OnOpen = cc.dataChannelOnOpen()
cc.dc.Onmessage = cc.dataChannelOnMessage()
cc.dc.Unlock()
cs.dc.Lock()
cs.dc.OnOpen = cs.dataChannelOnOpen()
cs.dc.Onmessage = cs.dataChannelOnMessage()
cs.dc.Unlock()

if cc.offer, err = sd.Decode(offerString); err != nil {
if cs.offer, err = sd.Decode(cs.offerString); err != nil {
log.Println(err)
return
}
if cc.offer.Key != "" {
if err = cc.offer.Decrypt(); err != nil {
if cs.offer.Key != "" {
if err = cs.offer.Decrypt(); err != nil {
log.Println(err)
return
}
}
offer := webrtc.RTCSessionDescription{
Type: webrtc.RTCSdpTypeOffer,
Sdp: cc.offer.Sdp,
Sdp: cs.offer.Sdp,
}

if err = cc.pc.SetRemoteDescription(offer); err != nil {
if err = cs.pc.SetRemoteDescription(offer); err != nil {
log.Println(err)
return err
}
// Sets the LocalDescription, and starts our UDP listeners
answer, err := cc.pc.CreateAnswer(nil)
answer, err := cs.pc.CreateAnswer(nil)
if err != nil {
log.Println(err)
return
}
answerSd := sd.SessionDescription{
Sdp: answer.Sdp,
Key: cc.offer.Key,
Nonce: cc.offer.Nonce,
Key: cs.offer.Key,
Nonce: cs.offer.Nonce,
}
if cc.offer.Key != "" {
if cs.offer.Key != "" {
// Encrypt with the shared keys from the offer
_ = answerSd.Encrypt()

Expand All @@ -170,14 +155,16 @@ func (cc *clientConfig) runClient(offerString string) (err error) {
}

encodedAnswer := sd.Encode(answerSd)
if cc.offer.TenKbSiteLoc == "" {
if cs.offer.TenKbSiteLoc == "" {
// Get the LocalDescription and take it to base64 so we can paste in browser
fmt.Printf("Answer created. Send the following answer to the host:\n\n")
fmt.Println(encodedAnswer)
} else {
if err := create10kbFile(cc.offer.TenKbSiteLoc, encodedAnswer); err != nil {
if err := create10kbFile(cs.offer.TenKbSiteLoc, encodedAnswer); err != nil {
return err
}
}
return <-cc.errChan
err = <-cs.errChan
cs.cleanup()
return err
}
26 changes: 13 additions & 13 deletions client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import (
)

func TestClientDataChannelOnMessage(t *testing.T) {
cc := clientConfig{}
cc.errChan = make(chan error, 1)
cc.oldTerminalState = &terminal.State{}
onMessage := cc.dataChannelOnMessage()
cs := clientSession{}
cs.errChan = make(chan error, 1)
cs.oldTerminalState = &terminal.State{}
onMessage := cs.dataChannelOnMessage()
quitPayload := datachannel.PayloadString{Data: []byte("quit")}
onMessage(&quitPayload)

select {
case err := <-cc.errChan:
case err := <-cs.errChan:
if err != nil {
t.Error(err)
}
Expand All @@ -45,14 +45,14 @@ func TestClientDataChannelOnMessage(t *testing.T) {
}

func TestSendTermSize(t *testing.T) {
hc := hostConfig{ptmxReady: true}
hs := hostSession{ptmxReady: true}
c := exec.Command("sh")
var err error
hc.ptmx, err = pty.Start(c)
hs.ptmx, err = pty.Start(c)
if err != nil {
t.Error(err)
}
if err := pty.Setsize(hc.ptmx, &pty.Winsize{
if err := pty.Setsize(hs.ptmx, &pty.Winsize{
Rows: 19,
Cols: 29,
X: 9,
Expand All @@ -64,8 +64,8 @@ func TestSendTermSize(t *testing.T) {
dcSend := func(payload datachannel.Payload) error {
switch p := payload.(type) {
case datachannel.PayloadString:
onMessage, hc := makeShPty(t)
size, err := pty.GetsizeFull(hc.ptmx)
onMessage, hs := makeShPty(t)
size, err := pty.GetsizeFull(hs.ptmx)
if err != nil {
t.Error(err)
}
Expand All @@ -74,14 +74,14 @@ func TestSendTermSize(t *testing.T) {
}
onMessage(&datachannel.PayloadString{Data: p.Data})
select {
case err := <-hc.errChan:
case err := <-hs.errChan:
if err != nil {
t.Error(err)
}
default:

}
size, err = pty.GetsizeFull(hc.ptmx)
size, err = pty.GetsizeFull(hs.ptmx)
if err != nil {
t.Error(err)
}
Expand All @@ -94,7 +94,7 @@ func TestSendTermSize(t *testing.T) {
}
return nil
}
if err := sendTermSize(hc.ptmx, dcSend); err != nil {
if err := sendTermSize(hs.ptmx, dcSend); err != nil {
t.Error(err)
}

Expand Down
24 changes: 0 additions & 24 deletions config.go

This file was deleted.

Loading

0 comments on commit 1f1f2e1

Please sign in to comment.