func client(whole net.Conn) (ErrorCodeRWC, error) { sconn, _ := transport.NewConn(whole, false) go sconn.Serve(func(smux.Stream) {}) mainPeel, err := sconn.OpenStream() if err != nil { return nil, err } err = sroute.SelectProtoOrFail("/main", mainPeel) if err != nil { return nil, err } ecPeel, err := sconn.OpenStream() if err != nil { return nil, err } err = sroute.SelectProtoOrFail("/ec", ecPeel) if err != nil { return nil, err } ecCh := make(chan byte) go readToCh(ecPeel, ecCh) return &errorCodeRWC{whole, mainPeel, ecPeel, ecCh}, nil }
func (ids *IDService) IdentifyConn(c inet.Conn) { ids.currmu.Lock() if wait, found := ids.currid[c]; found { ids.currmu.Unlock() log.Debugf("IdentifyConn called twice on: %s", c) <-wait // already identifying it. wait for it. return } ch := make(chan struct{}) ids.currid[c] = ch ids.currmu.Unlock() defer close(ch) s, err := c.NewStream() if err != nil { log.Debugf("error opening initial stream for %s: %s", ID, err) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) c.Close() return } defer s.Close() s.SetProtocol(ID) if ids.Reporter != nil { s = mstream.WrapStream(s, ids.Reporter) } // ok give the response to our handler. if err := msmux.SelectProtoOrFail(ID, s); err != nil { log.Debugf("error writing stream header for %s", ID) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) return } ids.ResponseHandler(s) ids.currmu.Lock() _, found := ids.currid[c] delete(ids.currid, c) ids.currmu.Unlock() if !found { log.Debugf("IdentifyConn failed to find channel (programmer error) for %s", c) return } }
func Client(target string, proto string) error { con, err := net.Dial("tcp", target) if err != nil { return err } defer con.Close() err = mss.SelectProtoOrFail(proto, con) if err != nil { return err } data := make([]byte, 4096) rand.Read(data) errs := make(chan error) go func() { _, err := con.Write(data) errs <- err }() go func() { resp := make([]byte, 4096) _, err := io.ReadFull(con, resp) if err != nil { errs <- err return } if !bytes.Equal(resp, data) { errs <- fmt.Errorf("data wasnt the same!!") } errs <- nil }() err = <-errs if err != nil { return err } err = <-errs if err != nil { return err } return nil }
func (gw *Gateway) Dial(dest pnet.Peer, proto string) (io.ReadWriteCloser, error) { // See if we already have a connection with this peer. s, err := gw.conns.NewStreamWithGroup(dest.Id()) if err != nil { // We don't, let's create a new connection. //TODO: Dial many/all addrs, use earliest. Like here: //https://github.com/ipfs/go-ipfs/blob/master/p2p/net/swarm/swarm_dial.go p, ok := dest.(*PeerInfo) if !ok { return nil, errors.New("Unknown pnet.Peer type") } m, err := ma.NewMultiaddrBytes(p.MAddrs[0]) if err != nil { return nil, err } nc, err := manet.Dial(m) if err != nil { return nil, err } c, err := gw.conns.AddConn(nc) if err != nil { nc.Close() return nil, err } gw.conns.AddConnToGroup(c, p.Id()) s, err = gw.conns.NewStreamWithGroup(p.Id()) if err != nil { return nil, err } } // Select the protocol on the new stream. err = ms.SelectProtoOrFail(proto, s) if err != nil { s.Close() } return s, err }
func (ids *IDService) IdentifyConn(c inet.Conn) { ids.currmu.Lock() if wait, found := ids.currid[c]; found { ids.currmu.Unlock() log.Debugf("IdentifyConn called twice on: %s", c) <-wait // already identifying it. wait for it. return } ids.currid[c] = make(chan struct{}) ids.currmu.Unlock() s, err := c.NewStream() if err != nil { log.Debugf("error opening initial stream for %s", ID) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) c.Close() return } else { bwc := ids.Host.GetBandwidthReporter() s = mstream.WrapStream(s, ID, bwc) // ok give the response to our handler. if err := msmux.SelectProtoOrFail(ID, s); err != nil { log.Debugf("error writing stream header for %s", ID) log.Event(context.TODO(), "IdentifyOpenFailed", c.RemotePeer()) s.Close() return } else { ids.ResponseHandler(s) } } ids.currmu.Lock() ch, found := ids.currid[c] delete(ids.currid, c) ids.currmu.Unlock() if !found { log.Debugf("IdentifyConn failed to find channel (programmer error) for %s", c) return } close(ch) // release everyone waiting. }
func TestRelayStress(t *testing.T) { buflen := 1 << 18 iterations := 10 ctx := context.Background() // these networks have the relay service wired in already. n1 := testutil.GenHostSwarm(t, ctx) n2 := testutil.GenHostSwarm(t, ctx) n3 := testutil.GenHostSwarm(t, ctx) n1p := n1.ID() n2p := n2.ID() n3p := n3.ID() n2pi := n2.Peerstore().PeerInfo(n2p) if err := n1.Connect(ctx, n2pi); err != nil { t.Fatalf("Failed to dial:", err) } if err := n3.Connect(ctx, n2pi); err != nil { t.Fatalf("Failed to dial:", err) } // setup handler on n3 to copy everything over to the pipe. piper, pipew := io.Pipe() n3.SetStreamHandler(protocol.TestingID, func(s inet.Stream) { log.Debug("relay stream opened to n3!") log.Debug("piping and echoing everything") w := io.MultiWriter(s, pipew) io.Copy(w, s) log.Debug("closing stream") s.Close() }) // ok, now we can try to relay n1--->n2--->n3. log.Debug("open relay stream") s, err := n1.NewStream(ctx, n2p, relay.ID) if err != nil { t.Fatal(err) } // ok first thing we write the relay header n1->n3 log.Debug("write relay header") if err := relay.WriteHeader(s, n1p, n3p); err != nil { t.Fatal(err) } // ok now the header's there, we can write the next protocol header. log.Debug("write testing header") if err := msmux.SelectProtoOrFail(string(protocol.TestingID), s); err != nil { t.Fatal(err) } // okay, now write lots of text and read it back out from both // the pipe and the stream. buf1 := make([]byte, buflen) buf2 := make([]byte, len(buf1)) buf3 := make([]byte, len(buf1)) fillbuf := func(buf []byte, b byte) { for i := range buf { buf[i] = b } } for i := 0; i < iterations; i++ { fillbuf(buf1, byte(int('a')+i)) log.Debugf("writing %d bytes (%d/%d)", len(buf1), i, iterations) if _, err := s.Write(buf1); err != nil { t.Fatal(err) } log.Debug("read it out from the pipe.") if _, err := io.ReadFull(piper, buf2); err != nil { t.Fatal(err) } if string(buf1) != string(buf2) { t.Fatal("should've gotten that text out of the pipe") } // read it out from the stream (echoed) log.Debug("read it out from the stream (echoed).") if _, err := io.ReadFull(s, buf3); err != nil { t.Fatal(err) } if string(buf1) != string(buf3) { t.Fatal("should've gotten that text out of the stream") } } log.Debug("sweet, relay works under stress.") s.Close() }
func TestRelaySimple(t *testing.T) { ctx := context.Background() // these networks have the relay service wired in already. n1 := testutil.GenHostSwarm(t, ctx) n2 := testutil.GenHostSwarm(t, ctx) n3 := testutil.GenHostSwarm(t, ctx) n1p := n1.ID() n2p := n2.ID() n3p := n3.ID() n2pi := n2.Peerstore().PeerInfo(n2p) if err := n1.Connect(ctx, n2pi); err != nil { t.Fatal("Failed to connect:", err) } if err := n3.Connect(ctx, n2pi); err != nil { t.Fatal("Failed to connect:", err) } // setup handler on n3 to copy everything over to the pipe. piper, pipew := io.Pipe() n3.SetStreamHandler(protocol.TestingID, func(s inet.Stream) { log.Debug("relay stream opened to n3!") log.Debug("piping and echoing everything") w := io.MultiWriter(s, pipew) io.Copy(w, s) log.Debug("closing stream") s.Close() }) // ok, now we can try to relay n1--->n2--->n3. log.Debug("open relay stream") s, err := n1.NewStream(ctx, n2p, relay.ID) if err != nil { t.Fatal(err) } // ok first thing we write the relay header n1->n3 log.Debug("write relay header") if err := relay.WriteHeader(s, n1p, n3p); err != nil { t.Fatal(err) } // ok now the header's there, we can write the next protocol header. log.Debug("write testing header") if err := msmux.SelectProtoOrFail(string(protocol.TestingID), s); err != nil { t.Fatal(err) } // okay, now we should be able to write text, and read it out. buf1 := []byte("abcdefghij") buf2 := make([]byte, 10) buf3 := make([]byte, 10) log.Debug("write in some text.") if _, err := s.Write(buf1); err != nil { t.Fatal(err) } // read it out from the pipe. log.Debug("read it out from the pipe.") if _, err := io.ReadFull(piper, buf2); err != nil { t.Fatal(err) } if string(buf1) != string(buf2) { t.Fatal("should've gotten that text out of the pipe") } // read it out from the stream (echoed) log.Debug("read it out from the stream (echoed).") if _, err := io.ReadFull(s, buf3); err != nil { t.Fatal(err) } if string(buf1) != string(buf3) { t.Fatal("should've gotten that text out of the stream") } // sweet. relay works. log.Debug("sweet, relay works.") s.Close() }