From 7b13c92e931eef032d77f067b8d077dd39e2bcab Mon Sep 17 00:00:00 2001 From: Michael Quigley Date: Tue, 17 Mar 2020 14:48:14 -0400 Subject: [PATCH] Roughed in transwarp implementation for 'transwarp:'. We'll see how the listener side of this plays out. (#44) --- transwarp/address.go | 74 +++++++++++++++++++++++++++++++++++++++++ transwarp/connection.go | 72 +++++++++++++++++++++++++++++++++++++++ transwarp/dialer.go | 46 +++++++++++++++++++++++++ transwarp/listener.go | 37 +++++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 transwarp/address.go create mode 100644 transwarp/connection.go create mode 100644 transwarp/dialer.go create mode 100644 transwarp/listener.go diff --git a/transwarp/address.go b/transwarp/address.go new file mode 100644 index 000000000..b61c696fc --- /dev/null +++ b/transwarp/address.go @@ -0,0 +1,74 @@ +/* + (c) Copyright NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package transwarp + +import ( + "fmt" + "github.com/netfoundry/ziti-foundation/identity/identity" + "github.com/netfoundry/ziti-foundation/transport" + "io" + "strconv" + "strings" +) + +func (self address) Dial(name string, _ *identity.TokenId) (transport.Connection, error) { + return Dial(self.bindableAddress(), name) +} + +func (self address) Listen(_ string, _ *identity.TokenId, _ chan transport.Connection) (io.Closer, error) { + return Listen(self.bindableAddress()) +} + +func (self address) MustListen(name string, _ *identity.TokenId, _ chan transport.Connection) io.Closer { + closer, err := self.Listen(name, nil, nil) + if err != nil { + panic(fmt.Errorf("cannot listen (%w)", err)) + } + return closer +} + +func (self address) String() string { + return fmt.Sprintf("transwarp:%s", self.bindableAddress()) +} + +func (self address) bindableAddress() string { + return fmt.Sprintf("%s:%d", self.hostname, self.port) +} + +type address struct { + hostname string + port uint16 +} + +type AddressParser struct{} + +func (_ AddressParser) Parse(s string) (transport.Address, error) { + tokens := strings.Split(s, ":") + if len(tokens) != 3 { + return nil, fmt.Errorf("invalid format") + } + + if tokens[0] == "transwarp" { + port, err := strconv.ParseUint(tokens[2], 10, 16) + if err != nil { + return nil, err + } + return &address{hostname: tokens[1], port: uint16(port)}, nil + } + + return nil, fmt.Errorf("invalid format") +} diff --git a/transwarp/connection.go b/transwarp/connection.go new file mode 100644 index 000000000..c24db6cd8 --- /dev/null +++ b/transwarp/connection.go @@ -0,0 +1,72 @@ +/* + (c) Copyright NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package transwarp + +import ( + "crypto/x509" + "github.com/netfoundry/ziti-foundation/transport" + "io" + "net" + "time" +) + +func (self *connection) Detail() *transport.ConnectionDetail { + return self.detail +} + +func (_ *connection) PeerCertificates() []*x509.Certificate { + return nil +} + +func (self *connection) Reader() io.Reader { + return self.socket +} + +func (self *connection) Writer() io.Writer { + return self.socket +} + +func (self *connection) Conn() net.Conn { + return self.socket +} + +func (self *connection) SetReadTimeout(t time.Duration) error { + return self.socket.SetReadDeadline(time.Now().Add(t)) +} + +func (self *connection) SetWriteTimeout(t time.Duration) error { + return self.socket.SetWriteDeadline(time.Now().Add(t)) +} + +func (self *connection) Close() error { + return self.socket.Close() +} + +func newConnection(detail *transport.ConnectionDetail, socket net.Conn) *connection { + return &connection{ + detail: detail, + socket: socket, + buffer: make([]byte, 4096), + } +} + +type connection struct { + detail *transport.ConnectionDetail + socket net.Conn + buffer []byte + copy []byte +} diff --git a/transwarp/dialer.go b/transwarp/dialer.go new file mode 100644 index 000000000..8a82df4ce --- /dev/null +++ b/transwarp/dialer.go @@ -0,0 +1,46 @@ +/* + (c) Copyright NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package transwarp + +import ( + "fmt" + "github.com/netfoundry/ziti-foundation/transport" + "net" +) + +func Dial(destination, name string) (transport.Connection, error) { + destinationAddress, err := net.ResolveUDPAddr("udp", destination) + if err != nil { + return nil, fmt.Errorf("error resolving destination address (%w)", err) + } + + localAddress, err := net.ResolveUDPAddr("udp", ":0") + if err != nil { + return nil, fmt.Errorf("error resolving local address (%w)", err) + } + + conn, err := net.DialUDP("udp", localAddress, destinationAddress) + if err != nil { + return nil, fmt.Errorf("error dialing (%w)", err) + } + + return newConnection(&transport.ConnectionDetail{ + Address: "transwarp" + destination, + InBound: false, + Name: name, + }, conn), nil +} diff --git a/transwarp/listener.go b/transwarp/listener.go new file mode 100644 index 000000000..fd933fda8 --- /dev/null +++ b/transwarp/listener.go @@ -0,0 +1,37 @@ +/* + (c) Copyright NetFoundry, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package transwarp + +import ( + "fmt" + "io" + "net" +) + +func Listen(bindAddress string) (io.Closer, error) { + listenAddress, err := net.ResolveUDPAddr("udp", bindAddress) + if err != nil { + return nil, fmt.Errorf("error resolving bind address (%w)", err) + } + + socket, err := net.ListenUDP("udp", listenAddress) + if err != nil { + return nil, fmt.Errorf("error listening (%w)", err) + } + + return socket, nil +} \ No newline at end of file