mirror of
https://github.com/openlibrecommunity/olcrtc.git
synced 2026-06-02 06:23:37 +02:00
Update olcRTC mobile bridge
This commit is contained in:
@@ -32,6 +32,10 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Run(ctx context.Context, roomURL, keyHex string, socksPort int, duo bool, socksUser, socksPass string) error {
|
func Run(ctx context.Context, roomURL, keyHex string, socksPort int, duo bool, socksUser, socksPass string) error {
|
||||||
|
return RunWithReady(ctx, roomURL, keyHex, socksPort, duo, socksUser, socksPass, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunWithReady(ctx context.Context, roomURL, keyHex string, socksPort int, duo bool, socksUser, socksPass string, onReady func()) error {
|
||||||
runCtx, cancel := context.WithCancel(ctx)
|
runCtx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -159,7 +163,7 @@ func Run(ctx context.Context, roomURL, keyHex string, socksPort int, duo bool, s
|
|||||||
log.Printf("Sent reset signal to server (clientID=%d)", c.clientID)
|
log.Printf("Sent reset signal to server (clientID=%d)", c.clientID)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.runSOCKS5(runCtx, socksPort, socksUser, socksPass)
|
err = c.runSOCKS5(runCtx, socksPort, socksUser, socksPass, onReady)
|
||||||
|
|
||||||
log.Println("Waiting for client goroutines...")
|
log.Println("Waiting for client goroutines...")
|
||||||
c.wg.Wait()
|
c.wg.Wait()
|
||||||
@@ -178,13 +182,16 @@ func (c *Client) onData(data []byte) {
|
|||||||
c.mux.HandleFrame(plaintext)
|
c.mux.HandleFrame(plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) runSOCKS5(ctx context.Context, port int, username, password string) error {
|
func (c *Client) runSOCKS5(ctx context.Context, port int, username, password string, onReady func()) error {
|
||||||
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
listener, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("SOCKS5 proxy listening on 127.0.0.1:%d (auth=%v)", port, username != "")
|
log.Printf("SOCKS5 proxy listening on 127.0.0.1:%d (auth=%v)", port, username != "")
|
||||||
|
if onReady != nil {
|
||||||
|
onReady()
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
<-ctx.Done()
|
<-ctx.Done()
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
package mux
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseControlFrame(t *testing.T) {
|
|
||||||
frame := BuildControlFrame(42, ControlResetClient)
|
|
||||||
|
|
||||||
control, ok := ParseControlFrame(frame)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("expected control frame")
|
|
||||||
}
|
|
||||||
if control.ClientID != 42 {
|
|
||||||
t.Fatalf("ClientID = %d, want 42", control.ClientID)
|
|
||||||
}
|
|
||||||
if control.Type != ControlResetClient {
|
|
||||||
t.Fatalf("Type = %d, want %d", control.Type, ControlResetClient)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHandleControlResetClient(t *testing.T) {
|
|
||||||
m := New(0, func([]byte) error { return nil })
|
|
||||||
|
|
||||||
dataFrame := make([]byte, 13)
|
|
||||||
binary.BigEndian.PutUint32(dataFrame[0:4], 42)
|
|
||||||
binary.BigEndian.PutUint16(dataFrame[4:6], 7)
|
|
||||||
binary.BigEndian.PutUint16(dataFrame[6:8], 1)
|
|
||||||
binary.BigEndian.PutUint32(dataFrame[8:12], 0)
|
|
||||||
dataFrame[12] = 0xAA
|
|
||||||
|
|
||||||
m.HandleFrame(dataFrame)
|
|
||||||
if stream := m.GetStream(7); stream == nil {
|
|
||||||
t.Fatal("expected data stream before reset")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.HandleFrame(BuildControlFrame(42, ControlResetClient))
|
|
||||||
if stream := m.GetStream(7); stream != nil {
|
|
||||||
t.Fatal("expected data stream to be removed by client reset")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSendClientReset(t *testing.T) {
|
|
||||||
var sent []byte
|
|
||||||
m := New(99, func(frame []byte) error {
|
|
||||||
sent = append([]byte(nil), frame...)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := m.SendClientReset(); err != nil {
|
|
||||||
t.Fatalf("SendClientReset failed: %v", err)
|
|
||||||
}
|
|
||||||
control, ok := ParseControlFrame(sent)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("expected sent control frame")
|
|
||||||
}
|
|
||||||
if control.ClientID != 99 || control.Type != ControlResetClient {
|
|
||||||
t.Fatalf("control = %#v", control)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package names
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestGenerateFallsBackWhenListsAreEmpty(t *testing.T) {
|
|
||||||
oldFirst := firstNames
|
|
||||||
oldLast := lastNames
|
|
||||||
defer func() {
|
|
||||||
firstNames = oldFirst
|
|
||||||
lastNames = oldLast
|
|
||||||
}()
|
|
||||||
|
|
||||||
firstNames = nil
|
|
||||||
lastNames = nil
|
|
||||||
|
|
||||||
if got := Generate(); got == "" {
|
|
||||||
t.Fatal("Generate returned an empty display name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package telemost
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestIsConferenceEndMessage(t *testing.T) {
|
|
||||||
tests := []map[string]interface{}{
|
|
||||||
{"conferenceEnded": map[string]interface{}{}},
|
|
||||||
{"conference": map[string]interface{}{"state": "closed"}},
|
|
||||||
{"conferenceState": map[string]interface{}{"state": "TERMINATED"}},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
if !isConferenceEndMessage(tt) {
|
|
||||||
t.Fatalf("expected end message for %#v", tt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIsConferenceEndMessageIgnoresActiveState(t *testing.T) {
|
|
||||||
msg := map[string]interface{}{
|
|
||||||
"conference": map[string]interface{}{"state": "active"},
|
|
||||||
}
|
|
||||||
if isConferenceEndMessage(msg) {
|
|
||||||
t.Fatal("active conference state must not be treated as ended")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+65
-4
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/openlibrecommunity/olcrtc/internal/client"
|
"github.com/openlibrecommunity/olcrtc/internal/client"
|
||||||
"github.com/openlibrecommunity/olcrtc/internal/logger"
|
"github.com/openlibrecommunity/olcrtc/internal/logger"
|
||||||
@@ -27,7 +28,9 @@ type LogWriter interface {
|
|||||||
var (
|
var (
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
done chan error
|
done chan struct{}
|
||||||
|
ready chan struct{}
|
||||||
|
runErr error
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetProtector sets the Android VPN socket protector.
|
// SetProtector sets the Android VPN socket protector.
|
||||||
@@ -84,19 +87,77 @@ func Start(roomID, keyHex string, socksPort int, duo bool, socksUser, socksPass
|
|||||||
|
|
||||||
ctx, c := context.WithCancel(context.Background())
|
ctx, c := context.WithCancel(context.Background())
|
||||||
cancel = c
|
cancel = c
|
||||||
done = make(chan error, 1)
|
done = make(chan struct{})
|
||||||
|
ready = make(chan struct{})
|
||||||
|
localReady := ready
|
||||||
|
runErr = nil
|
||||||
|
|
||||||
|
var readyOnce sync.Once
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
err := client.Run(ctx, roomURL, keyHex, socksPort, duo, socksUser, socksPass)
|
err := client.RunWithReady(ctx, roomURL, keyHex, socksPort, duo, socksUser, socksPass, func() {
|
||||||
|
readyOnce.Do(func() {
|
||||||
|
close(localReady)
|
||||||
|
})
|
||||||
|
})
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
cancel = nil
|
cancel = nil
|
||||||
|
runErr = err
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
done <- err
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WaitReady blocks until the Telemost peers are connected and the local SOCKS5 listener is ready.
|
||||||
|
func WaitReady(timeoutMillis int) error {
|
||||||
|
mu.Lock()
|
||||||
|
r := ready
|
||||||
|
d := done
|
||||||
|
err := runErr
|
||||||
|
running := cancel != nil
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
|
if r == nil {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("olcRTC is not running")
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-r:
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
if !running {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("olcRTC stopped before becoming ready")
|
||||||
|
}
|
||||||
|
|
||||||
|
timer := time.NewTimer(time.Duration(timeoutMillis) * time.Millisecond)
|
||||||
|
defer timer.Stop()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-r:
|
||||||
|
return nil
|
||||||
|
case <-d:
|
||||||
|
mu.Lock()
|
||||||
|
err := runErr
|
||||||
|
mu.Unlock()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return fmt.Errorf("olcRTC stopped before becoming ready")
|
||||||
|
case <-timer.C:
|
||||||
|
return fmt.Errorf("olcRTC start timed out")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Stop gracefully stops the olcRTC client.
|
// Stop gracefully stops the olcRTC client.
|
||||||
func Stop() {
|
func Stop() {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
|
|||||||
Reference in New Issue
Block a user