Esempio n. 1
0
func (o *Overlay) tunneler(ip net.IP, live chan struct{}, quit chan chan error) {
	// Listen for incoming streams on the given interface and random port.
	addr, err := net.ResolveTCPAddr("tcp", net.JoinHostPort(ip.String(), "0"))
	if err != nil {
		panic(fmt.Sprintf("failed to resolve interface (%v): %v.", ip, err))
	}
	sock, err := stream.Listen(addr)
	if err != nil {
		panic(fmt.Sprintf("failed to start stream listener: %v.", err))
	}
	sock.Accept(config.IrisTunnelAcceptTimeout)

	// Save the new listener address into the local (sorted) address list
	o.lock.Lock()
	o.tunAddrs = append(o.tunAddrs, addr.String())
	sort.Strings(o.tunAddrs)
	o.lock.Unlock()

	// Notify the overlay of the successful listen
	live <- struct{}{}

	// Process incoming connection until termination is requested
	var errc chan error
	for errc == nil {
		select {
		case errc = <-quit:
			// Terminating, close and return
			continue
		case strm := <-sock.Sink:
			// There's a hidden panic possibility here: the listener socket can fail
			// if the system is overloaded with open connections. Alas, solving it is
			// not trivial as it would require restarting the whole listener. Figure it
			// out eventually.

			// Initialize and authorize the inbound tunnel
			if err := o.initServerTunnel(strm); err != nil {
				log.Printf("iris: failed to initialize server tunnel: %v.", err)
				if err := strm.Close(); err != nil {
					log.Printf("iris: failed to terminate uninitialized tunnel stream: %v.", err)
				}
			}
		}
	}
	// Terminate the peer listener
	errv := sock.Close()
	if errv != nil {
		log.Printf("iris: failed to terminate tunnel listener: %v.", err)
	}
	errc <- errv
}
Esempio n. 2
0
// Starts a TCP listener to accept incoming sessions, returning the socket ready
// to accept. If an auto-port (0) is requested, the port is updated in the arg.
func Listen(addr *net.TCPAddr, key *rsa.PrivateKey) (*Listener, error) {
	// Open the stream listener socket
	sock, err := stream.Listen(addr)
	if err != nil {
		return nil, err
	}
	// Assemble and return the session listener
	return &Listener{
		Sink:   make(chan *Session),
		pends:  make(map[int64]chan *stream.Stream),
		socket: sock,
		key:    key,
		quit:   make(chan chan error),
	}, nil
}
Esempio n. 3
0
func server(live, quit chan struct{}) {
	// Open a TCP port to accept incoming stream connections
	addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		fmt.Println("Failed to resolve local address:", err)
		return
	}
	sock, err := stream.Listen(addr)
	if err != nil {
		fmt.Println("Failed to listen for incoming streams:", err)
		return
	}
	sock.Accept(time.Second)
	live <- struct{}{}

	// While not exiting, process stream connections
	for {
		select {
		case <-quit:
			if err = sock.Close(); err != nil {
				fmt.Println("Failed to terminate stream listener:", err)
			}
			return
		case strm := <-sock.Sink:
			defer strm.Close()

			// Receive and echo back a string
			var data string
			if err = strm.Recv(&data); err != nil {
				fmt.Println("Failed to receive a string object:", err)
				continue
			}
			if err = strm.Send(&data); err != nil {
				fmt.Println("Failed to send back a string object:", err)
				continue
			}
			if err = strm.Flush(); err != nil {
				fmt.Println("Failed to flush the response:", err)
				return
			}
		}
	}
}
Esempio n. 4
0
// Tests the low level send and receive methods.
func TestDirectSendRecv(t *testing.T) {
	t.Parallel()

	// Start a stream listener
	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
	if err != nil {
		t.Fatalf("failed to resolve local address: %v.", err)
	}
	listener, err := stream.Listen(addr)
	if err != nil {
		t.Fatalf("failed to listen for incoming streams: %v.", err)
	}
	listener.Accept(10 * time.Millisecond)
	defer listener.Close()

	// Establish a stream connection to the listener
	host := fmt.Sprintf("%s:%d", "localhost", addr.Port)
	clientStrm, err := stream.Dial(host, time.Millisecond)
	if err != nil {
		t.Fatalf("failed to connect to stream listener: %v.", err)
	}
	serverStrm := <-listener.Sink

	defer clientStrm.Close()
	defer serverStrm.Close()

	// Initialize the stream based encrypted links
	secret := make([]byte, 16)
	io.ReadFull(rand.Reader, secret)

	clientHKDF := hkdf.New(sha1.New, secret, []byte("HKDF salt"), []byte("HKDF info"))
	serverHKDF := hkdf.New(sha1.New, secret, []byte("HKDF salt"), []byte("HKDF info"))

	clientLink := New(clientStrm, clientHKDF, false)
	serverLink := New(serverStrm, serverHKDF, true)

	// Generate some random messages and pass around both ways
	for i := 0; i < 1000; i++ {
		// Generate the message to send
		send := &proto.Message{
			Head: proto.Header{
				Meta: make([]byte, 32),
			},
			Data: make([]byte, 32),
		}
		io.ReadFull(rand.Reader, send.Head.Meta.([]byte))
		io.ReadFull(rand.Reader, send.Data)
		send.Encrypt()

		// Send the message from client to server
		if err := clientLink.SendDirect(send); err != nil {
			t.Fatalf("failed to send message to server: %v.", err)
		}
		if recv, err := serverLink.RecvDirect(); err != nil {
			t.Fatalf("failed to receive message from client: %v.", err)
		} else if bytes.Compare(send.Head.Meta.([]byte), recv.Head.Meta.([]byte)) != 0 || bytes.Compare(send.Data, recv.Data) != 0 {
			t.Fatalf("send/receive mismatch: have %+v, want %+v.", recv, send)
		}
		// Send the message from server to client
		if err := serverLink.SendDirect(send); err != nil {
			t.Fatalf("failed to send message to client: %v.", err)
		}
		if recv, err := clientLink.RecvDirect(); err != nil {
			t.Fatalf("failed to receive message from server: %v.", err)
		} else if bytes.Compare(send.Head.Meta.([]byte), recv.Head.Meta.([]byte)) != 0 || bytes.Compare(send.Data, recv.Data) != 0 {
			t.Fatalf("send/receive mismatch: have %+v, want %+v.", recv, send)
		}
	}
}