Example #1
0
func singleConn(t *testing.T, tr smux.Transport) echoSetup {
	swarm := ps.NewSwarm(tr)
	swarm.SetStreamHandler(func(s *ps.Stream) {
		defer s.Close()
		log("accepted stream")
		io.Copy(s, s) // echo everything
		log("closing stream")
	})

	log("listening at %s", "localhost:0")
	l, err := net.Listen("tcp", "localhost:0")
	checkErr(t, err)

	_, err = swarm.AddListener(l)
	checkErr(t, err)

	log("dialing to %s", l.Addr())
	nc1, err := net.Dial("tcp", l.Addr().String())
	checkErr(t, err)

	c1, err := swarm.AddConn(nc1)
	checkErr(t, err)

	return echoSetup{
		swarm: swarm,
		conns: []*ps.Conn{c1},
	}
}
Example #2
0
// NewSwarm constructs a Swarm, with a Chan.
func NewSwarm(ctx context.Context, listenAddrs []ma.Multiaddr,
	local peer.ID, peers peer.Peerstore, bwc metrics.Reporter) (*Swarm, error) {

	listenAddrs, err := filterAddrs(listenAddrs)
	if err != nil {
		return nil, err
	}

	s := &Swarm{
		swarm:   ps.NewSwarm(PSTransport),
		local:   local,
		peers:   peers,
		ctx:     ctx,
		dialT:   DialTimeout,
		notifs:  make(map[inet.Notifiee]ps.Notifiee),
		bwc:     bwc,
		Filters: filter.NewFilters(),
	}

	// configure Swarm
	s.proc = goprocessctx.WithContextAndTeardown(ctx, s.teardown)
	s.SetConnHandler(nil) // make sure to setup our own conn handler.

	// setup swarm metrics
	prom.MustRegisterOrGet(peersTotal)
	s.Notify((*metricsNotifiee)(s))

	return s, s.listen(listenAddrs)
}
Example #3
0
func main() {
	// create a new Swarm
	swarm := ps.NewSwarm(spdy.Transport)
	defer swarm.Close()

	// tell swarm what to do with a new incoming streams.
	// EchoHandler just echos back anything they write.
	swarm.SetStreamHandler(ps.EchoHandler)

	l, err := net.Listen("tcp", "localhost:8001")
	if err != nil {
		die(err)
	}

	if _, err := swarm.AddListener(l); err != nil {
		die(err)
	}

	nc, err := net.Dial("tcp", "localhost:8001")
	if err != nil {
		die(err)
	}

	c, err := swarm.AddConn(nc)
	if err != nil {
		die(err)
	}

	nRcvStream := 0
	bio := bufio.NewReader(os.Stdin)
	swarm.SetStreamHandler(func(s *ps.Stream) {
		log("handling new stream %d", nRcvStream)
		nRcvStream++

		line, err := bio.ReadString('\n')
		if err != nil {
			die(err)
		}
		_ = line
		// line = "read: " + line
		// s.Write([]byte(line))
		s.Close()
	})

	nSndStream := 0
	for {
		<-time.After(200 * time.Millisecond)
		_, err := swarm.NewStreamWithConn(c)
		if err != nil {
			die(err)
		}
		log("sender got new stream %d", nSndStream)
		nSndStream++
	}
}
Example #4
0
func SubtestSimpleWrite(t *testing.T, tr smux.Transport) {
	swarm := ps.NewSwarm(tr)
	defer swarm.Close()

	piper, pipew := io.Pipe()
	swarm.SetStreamHandler(func(s *ps.Stream) {
		defer s.Close()
		log("accepted stream")
		w := io.MultiWriter(s, pipew)
		io.Copy(w, s) // echo everything and write it to pipew
		log("closing stream")
	})

	log("listening at %s", "localhost:0")
	l, err := net.Listen("tcp", "localhost:0")
	checkErr(t, err)

	_, err = swarm.AddListener(l)
	checkErr(t, err)

	log("dialing to %s", l.Addr().String())
	nc1, err := net.Dial("tcp", l.Addr().String())
	checkErr(t, err)

	c1, err := swarm.AddConn(nc1)
	checkErr(t, err)
	defer c1.Close()

	log("creating stream")
	s1, err := c1.NewStream()
	checkErr(t, err)
	defer s1.Close()

	buf1 := randBuf(4096)
	log("writing %d bytes to stream", len(buf1))
	_, err = s1.Write(buf1)
	checkErr(t, err)

	buf2 := make([]byte, len(buf1))
	log("reading %d bytes from stream (echoed)", len(buf2))
	_, err = s1.Read(buf2)
	checkErr(t, err)
	if string(buf2) != string(buf1) {
		t.Error("buf1 and buf2 not equal: %s != %s", string(buf1), string(buf2))
	}

	buf3 := make([]byte, len(buf1))
	log("reading %d bytes from pipe (tee)", len(buf3))
	_, err = piper.Read(buf3)
	checkErr(t, err)
	if string(buf3) != string(buf1) {
		t.Error("buf1 and buf3 not equal: %s != %s", string(buf1), string(buf3))
	}
}
Example #5
0
func makeSwarm(t *testing.T, tr smux.Transport, nListeners int) *ps.Swarm {
	swarm := ps.NewSwarm(tr)
	swarm.SetStreamHandler(func(s *ps.Stream) {
		defer s.Close()
		log("accepted stream")
		io.Copy(s, s) // echo everything
		log("closing stream")
	})

	for i := 0; i < nListeners; i++ {
		log("%p listening at %s", swarm, "localhost:0")
		l, err := net.Listen("tcp", "localhost:0")
		checkErr(t, err)
		_, err = swarm.AddListener(l)
		checkErr(t, err)
	}

	return swarm
}
Example #6
0
func SubtestConstructSwarm(t *testing.T, tr smux.Transport) {
	ps.NewSwarm(tr)
}
Example #7
0
func main() {

	log("creating a new swarm with spdystream transport") // create a new Swarm
	swarm := ps.NewSwarm(spdy.Transport)
	defer swarm.Close()

	// tell swarm what to do with a new incoming streams.
	// EchoHandler just echos back anything they write.
	log("setup EchoHandler")
	swarm.SetStreamHandler(ps.EchoHandler)

	// Okay, let's try listening on some transports
	log("listening at localhost:8001")
	l1, err := net.Listen("tcp", "localhost:8001")
	if err != nil {
		panic(err)
	}

	log("listening at localhost:8002")
	l2, err := net.Listen("tcp", "localhost:8002")
	if err != nil {
		panic(err)
	}

	// tell swarm to accept incoming connections on these
	// listeners. Swarm will start accepting new connections.
	if _, err := swarm.AddListener(l1); err != nil {
		panic(err)
	}
	if _, err := swarm.AddListener(l2); err != nil {
		panic(err)
	}

	// ok, let's try some outgoing connections
	log("dialing localhost:8001")
	nc1, err := net.Dial("tcp", "localhost:8001")
	if err != nil {
		panic(err)
	}

	log("dialing localhost:8002")
	nc2, err := net.Dial("tcp", "localhost:8002")
	if err != nil {
		panic(err)
	}

	// add them to the swarm
	c1, err := swarm.AddConn(nc1)
	if err != nil {
		panic(err)
	}
	c2, err := swarm.AddConn(nc2)
	if err != nil {
		panic(err)
	}

	// Swarm treats listeners as sources of new connections and does
	// not distinguish between outgoing or incoming connections.
	// It provides the net.Conn to the StreamHandler so you can
	// distinguish between them however you wish.

	// now let's try opening some streams!
	// You can specify what connection you want to use
	log("opening stream with NewStreamWithConn(c1)")
	s1, err := swarm.NewStreamWithConn(c1)
	if err != nil {
		panic(err)
	}

	// Or, you can specify a SelectConn function that picks between all
	// (it calls NewStreamWithConn underneath the hood)
	log("opening stream with NewStreamSelectConn(.)")
	s2, err := swarm.NewStreamSelectConn(func(conns []*ps.Conn) *ps.Conn {
		if len(conns) > 0 {
			return conns[0]
		}
		return nil
	})
	if err != nil {
		panic(err)
	}

	// Or, you can bind connections to ConnGroup ids. You can bind a conn to
	// multiple groups. And, if conn wasn't in swarm, it calls swarm.AddConn.
	// You can use any Go `KeyType` as a group A `KeyType` as in maps...)
	swarm.AddConnToGroup(c2, 1)

	// And then use that group to select a connection. Swarm will use any
	// connection it finds in that group, using a SelectConn you can rebind:
	//   swarm.SetGroupSelectConn(1, SelectConn)
	//   swarm.SetDegaultGroupSelectConn(SelectConn)
	log("opening stream with NewStreamWithGroup(1)")
	s3, err := swarm.NewStreamWithGroup(1)
	if err != nil {
		panic(err)
	}

	// Why groups? It's because with many connections, and many transports,
	// and many Servers (or Protocols), we can use the Swarm to associate
	// a different StreamHandlers per group, and to let us create NewStreams
	// on a given group.

	// Ok, we have streams. now what. Use them! Our Streams are basically
	// streams from github.com/docker/spdystream, so they work the same
	// way:

	log("preparing the streams")
	for i, stream := range []*ps.Stream{s1, s2, s3} {
		str := "stream %d ready:"
		fmt.Fprintf(stream, str, i)

		buf := make([]byte, len(str))
		log(fmt.Sprintf("reading from stream %d", i))
		stream.Read(buf)
		fmt.Println(string(buf))
	}

	log("let's test the streams")
	log("enter some text below:\n")
	go io.Copy(os.Stdout, s1)
	go io.Copy(os.Stdout, s2)
	go io.Copy(os.Stdout, s3)
	io.Copy(io.MultiWriter(s1, s2, s3), os.Stdin)
}