2020-06-02 18:19:19 +00:00
|
|
|
package pogs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"net"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
capnp "zombiezen.com/go/capnproto2"
|
|
|
|
"zombiezen.com/go/capnproto2/rpc"
|
|
|
|
|
2024-05-14 04:22:06 +00:00
|
|
|
"github.com/cloudflare/cloudflared/tunnelrpc/proto"
|
2020-06-02 18:19:19 +00:00
|
|
|
)
|
|
|
|
|
2020-06-12 02:47:40 +00:00
|
|
|
const testAccountTag = "abc123"
|
|
|
|
|
2020-06-02 18:19:19 +00:00
|
|
|
func TestMarshalConnectionOptions(t *testing.T) {
|
|
|
|
clientID := uuid.New()
|
|
|
|
orig := ConnectionOptions{
|
|
|
|
Client: ClientInfo{
|
|
|
|
ClientID: clientID[:],
|
|
|
|
Features: []string{"a", "b"},
|
|
|
|
Version: "1.2.3",
|
|
|
|
Arch: "macos",
|
|
|
|
},
|
|
|
|
OriginLocalIP: []byte{10, 2, 3, 4},
|
|
|
|
ReplaceExisting: false,
|
|
|
|
CompressionQuality: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
_, seg, err := capnp.NewMessage(capnp.SingleSegment(nil))
|
|
|
|
require.NoError(t, err)
|
2024-05-14 04:22:06 +00:00
|
|
|
capnpOpts, err := proto.NewConnectionOptions(seg)
|
2020-06-02 18:19:19 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
err = orig.MarshalCapnproto(capnpOpts)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
var pogsOpts ConnectionOptions
|
|
|
|
err = pogsOpts.UnmarshalCapnproto(capnpOpts)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
|
|
|
assert.Equal(t, orig, pogsOpts)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConnectionRegistrationRPC(t *testing.T) {
|
|
|
|
p1, p2 := net.Pipe()
|
2020-06-12 02:47:40 +00:00
|
|
|
|
2020-06-02 18:19:19 +00:00
|
|
|
t1, t2 := rpc.StreamTransport(p1), rpc.StreamTransport(p2)
|
|
|
|
|
|
|
|
// Server-side
|
|
|
|
testImpl := testConnectionRegistrationServer{}
|
2024-05-20 23:09:25 +00:00
|
|
|
srv := RegistrationServer_ServerToClient(&testImpl)
|
2020-06-02 18:19:19 +00:00
|
|
|
serverConn := rpc.NewConn(t1, rpc.MainInterface(srv.Client))
|
|
|
|
defer serverConn.Wait()
|
|
|
|
|
|
|
|
ctx := context.Background()
|
|
|
|
clientConn := rpc.NewConn(t2)
|
|
|
|
defer clientConn.Close()
|
2024-05-20 23:09:25 +00:00
|
|
|
client := RegistrationServer_PogsClient{
|
2020-06-02 18:19:19 +00:00
|
|
|
Client: clientConn.Bootstrap(ctx),
|
|
|
|
Conn: clientConn,
|
|
|
|
}
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
clientID := uuid.New()
|
|
|
|
options := &ConnectionOptions{
|
|
|
|
Client: ClientInfo{
|
|
|
|
ClientID: clientID[:],
|
|
|
|
Features: []string{"foo"},
|
|
|
|
Version: "1.2.3",
|
|
|
|
Arch: "macos",
|
|
|
|
},
|
|
|
|
OriginLocalIP: net.IP{10, 20, 30, 40},
|
|
|
|
ReplaceExisting: true,
|
|
|
|
CompressionQuality: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedDetails := ConnectionDetails{
|
|
|
|
UUID: uuid.New(),
|
|
|
|
Location: "TEST",
|
|
|
|
}
|
|
|
|
testImpl.details = &expectedDetails
|
|
|
|
testImpl.err = nil
|
|
|
|
|
2020-06-12 02:47:40 +00:00
|
|
|
auth := TunnelAuth{
|
|
|
|
AccountTag: testAccountTag,
|
|
|
|
TunnelSecret: []byte{1, 2, 3, 4},
|
|
|
|
}
|
|
|
|
|
2020-06-02 18:19:19 +00:00
|
|
|
// success
|
|
|
|
tunnelID := uuid.New()
|
2020-06-12 02:47:40 +00:00
|
|
|
details, err := client.RegisterConnection(ctx, auth, tunnelID, 2, options)
|
2020-06-02 18:19:19 +00:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedDetails, *details)
|
|
|
|
|
|
|
|
// regular error
|
|
|
|
testImpl.details = nil
|
|
|
|
testImpl.err = errors.New("internal")
|
|
|
|
|
2020-06-12 02:47:40 +00:00
|
|
|
_, err = client.RegisterConnection(ctx, auth, tunnelID, 2, options)
|
2020-06-02 18:19:19 +00:00
|
|
|
assert.EqualError(t, err, "internal")
|
|
|
|
|
|
|
|
// retriable error
|
|
|
|
testImpl.details = nil
|
2020-06-12 02:47:40 +00:00
|
|
|
const delay = 27 * time.Second
|
2020-06-02 18:19:19 +00:00
|
|
|
testImpl.err = RetryErrorAfter(errors.New("retryable"), delay)
|
|
|
|
|
2020-06-12 02:47:40 +00:00
|
|
|
_, err = client.RegisterConnection(ctx, auth, tunnelID, 2, options)
|
2020-06-02 18:19:19 +00:00
|
|
|
assert.EqualError(t, err, "retryable")
|
|
|
|
|
|
|
|
re, ok := err.(*RetryableError)
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, delay, re.Delay)
|
|
|
|
}
|
|
|
|
|
|
|
|
type testConnectionRegistrationServer struct {
|
|
|
|
details *ConnectionDetails
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
2022-04-20 16:52:55 +00:00
|
|
|
func (t *testConnectionRegistrationServer) UpdateLocalConfiguration(ctx context.Context, config []byte) error {
|
|
|
|
// do nothing at this point
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-06-12 02:47:40 +00:00
|
|
|
func (t *testConnectionRegistrationServer) RegisterConnection(ctx context.Context, auth TunnelAuth, tunnelID uuid.UUID, connIndex byte, options *ConnectionOptions) (*ConnectionDetails, error) {
|
|
|
|
if auth.AccountTag != testAccountTag {
|
|
|
|
panic("bad account tag: " + auth.AccountTag)
|
|
|
|
}
|
2020-06-02 18:19:19 +00:00
|
|
|
if t.err != nil {
|
|
|
|
return nil, t.err
|
|
|
|
}
|
|
|
|
if t.details != nil {
|
|
|
|
return t.details, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
panic("either details or err mush be set")
|
|
|
|
}
|
2024-05-20 23:09:25 +00:00
|
|
|
|
|
|
|
func (t *testConnectionRegistrationServer) UnregisterConnection(ctx context.Context) {
|
|
|
|
panic("unimplemented: UnregisterConnection")
|
|
|
|
}
|