Ejemplo n.º 1
0
func TestInitiateHandshakes(t *testing.T) {
	Convey("Sends out handshake request to every IP in list", t, func() {
		s := NewBTService(port, []byte(peerIDRemote))
		mc := NewMockConnectionFetcher()
		s.ConnectionFetcher = mc
		s.AddHash(hash)
		_ = s.StartListening()

		// TODO: check that peer data is saved within service data structure
		peers := make([]structure.Peer, 2)
		peers[0] = structure.Peer{IP: net.IPv4(192, 168, 1, 1), Port: 55556}
		peers[1] = structure.Peer{IP: net.IPv4(192, 168, 1, 2), Port: 55557}
		s.InitiateHandshakes(hash, peers)

		for _, p := range peers {
			c0 := mc.Conns[p.AddrString()].Conn.(*MockConnection)
			hs, err := structure.ReadHandshake(bytes.NewReader(<-c0.ReceiveBytesChan))
			So(hs, ShouldNotBeNil)
			So(err, ShouldBeNil)
			hs, _ = structure.NewHandshake(hash, []byte(peerIDClient))
			c0.SendMessage(hs)
		}

		time.Sleep(time.Millisecond)
		So(len(s.Peers), ShouldEqual, len(peers))

		_ = s.StopListening()
		time.Sleep(time.Millisecond)
		So(s.Listening, ShouldBeFalse)
	})
}
Ejemplo n.º 2
0
func TestConversation(t *testing.T) {
	Convey("Receives Bitfield message and sends Interested message", t, func(ctx C) {
		s := NewBTService(port, []byte(peerIDRemote))
		mc := NewMockConnectionFetcher()
		s.ConnectionFetcher = mc
		s.AddHash(hash)
		_ = s.StartListening()

		// TODO: check that peer data is saved within service data structure
		peers := make([]structure.Peer, 1)
		peers[0] = structure.Peer{IP: net.IPv4(192, 168, 1, 1), Port: 55556}
		//		peers[1] = structure.Peer{IP: net.IPv4(192, 168, 1, 2), Port: 55557}
		s.InitiateHandshakes(hash, peers)

		wg := sync.WaitGroup{}
		wg.Add(len(peers))
		for _, p := range peers {
			go func(pp structure.Peer) {
				c0 := mc.Conns[pp.AddrString()].Conn.(*MockConnection)
				hs, err := structure.ReadHandshake(bytes.NewReader(<-c0.ReceiveBytesChan))
				ctx.So(hs, ShouldNotBeNil)
				ctx.So(err, ShouldBeNil)

				hs, _ = structure.NewHandshake(hash, []byte(peerIDClient))
				t.Log("---TEST--- Send Handshake")
				c0.SendMessage(hs)

				bf := structure.BitFieldFromHexString("\xff\xff\xff\x01")
				msg0 := structure.NewBitFieldMessage(bf)
				c0.SendMessage(msg0)

				m, err := ReadMessageOrTimeout(c0, ctx)
				ctx.So(err, ShouldBeNil)
				ctx.So(m.GetType(), ShouldEqual, structure.MessageTypeInterested)

				// TODO: Check why byte equality doesn't work
				btc := s.LookupConn(pp.AddrString())
				t.Logf("BTC: %q\n", btc.BitField.String())
				t.Logf("BF : %q\n", bf.String())
				ctx.So(bf.String(), ShouldEqual, btc.BitField.String())

				ctx.So(btc.PeerChoking, ShouldBeTrue)
				msg1 := structure.NewUnchokeMessage()
				c0.SendMessage(msg1)

				m, err = ReadMessageOrTimeout(c0, ctx)
				ctx.So(btc.PeerChoking, ShouldBeFalse)
				ctx.So(err, ShouldBeNil)
				ctx.So(m.GetType(), ShouldEqual, structure.MessageTypeRequest)

				wg.Done()
			}(p)
		}
		wg.Wait()

		_ = s.StopListening()
	})
}
Ejemplo n.º 3
0
func TestHave(t *testing.T) {
	Convey("Receives Have Messages and update BitField", t, func(ctx C) {
		s := NewBTService(port, []byte(peerIDRemote))
		mc := NewMockConnectionFetcher()
		s.ConnectionFetcher = mc
		s.AddHash(hash)
		_ = s.StartListening()

		// TODO: check that peer data is saved within service data structure
		peers := make([]structure.Peer, 1)
		peers[0] = structure.Peer{IP: net.IPv4(192, 168, 1, 1), Port: 55557}
		//		peers[1] = structure.Peer{IP: net.IPv4(192, 168, 1, 2), Port: 55557}
		s.InitiateHandshakes(hash, peers)

		wg := sync.WaitGroup{}
		wg.Add(len(peers))
		for _, p := range peers {
			go func(pp structure.Peer) {
				c0 := mc.Conns[pp.AddrString()].Conn.(*MockConnection)
				hs, err := structure.ReadHandshake(bytes.NewReader(<-c0.ReceiveBytesChan))
				ctx.So(hs, ShouldNotBeNil)
				ctx.So(err, ShouldBeNil)

				hs, _ = structure.NewHandshake(hash, []byte(peerIDClient))
				c0.SendMessage(hs)

				bf := structure.BitFieldFromHexString("\x00\x00\x00\x01")
				msg0 := structure.NewBitFieldMessage(bf)
				c0.SendMessage(msg0)

				m, err := ReadMessageOrTimeout(c0, ctx)
				ctx.So(err, ShouldBeNil)
				ctx.So(m.GetType(), ShouldEqual, structure.MessageTypeInterested)

				haveMsg := structure.NewHaveMessage(0)
				c0.SendMessage(haveMsg)

				time.Sleep(time.Millisecond)

				// TODO: Check why byte equality doesn't work
				btc := s.LookupConn(pp.AddrString())
				ctx.Printf("BTC: %q\n", btc.BitField.String())
				ctx.Printf("BF : %q\n", bf.String())
				updatedBF := structure.BitFieldFromHexString("\x80\x00\x00\x01")
				ctx.Printf("UBF: %q\n", updatedBF.String())
				isEqual := updatedBF.String() == btc.BitField.String()
				ctx.So(isEqual, ShouldBeTrue)

				wg.Done()
			}(p)
		}
		wg.Wait()

		_ = s.StopListening()
		time.Sleep(time.Millisecond)
	})
}
Ejemplo n.º 4
0
func (s *BTService) InitiateHandshakes(hash []byte, peers []structure.Peer) {
	for _, peer := range peers {
		addr := fmt.Sprintf("%q:%d", peer.IP, peer.Port)
		log.Printf("[InitiateHandshakes] Address: %q", addr)
		btc, err := s.ConnectionFetcher.Dial(addr)
		if err != nil {
			// TODO: Try more than once before giving up?
			continue
		}
		hs, _ := structure.NewHandshake(hash, s.PeerID)
		btc.Write(hs.Bytes())
		btc.Hash = string(hash)
		btc.State = BTStateWaitingForHandshake
		btc.handleConnection(s)
		btc.HandshakeChan <- true
	}
}
Ejemplo n.º 5
0
func (btc *BTConn) readLoop(addChan, leaveChan chan<- *BTConn) {
	for {
		select {
		case _ = <-btc.HandshakeChan:
			log.Printf("[readLoop] Waiting for Handshake\n")
			peerHs, err := handleHandshake(btc)
			if err != nil {
				log.Printf("[readLoop] Error: %q", err.Error())
				btc.Close()
				leaveChan <- btc
				continue
			}

			log.Printf("[readLoop] State: %q", btc.State)

			switch btc.State {
			case BTStateWaitingForHandshake:
				log.Printf("[readLoop] HashMatch? %q === %q?", btc.Hash, string(peerHs.Hash))
				if btc.Hash != string(peerHs.Hash) {
					// TODO: What if same connection is handling multiple hashes?
					log.Printf("[readLoop] Hash mismatch\n")
					btc.Close()
					leaveChan <- btc
					continue
				}
			case BTStateStartListening:
				log.Printf("Writing byte %q\n", btc)
				respHs, err := structure.NewHandshake(peerHs.Hash, []byte(btc.PeerID))
				log.Println("[readLoop] respHS ", respHs)
				if err != nil {
					log.Printf("[readLoop] %q\n", err.Error())
					btc.Close()
					leaveChan <- btc
					continue
				}
				btc.Write(respHs.Bytes())
			default:
				log.Printf("[readLoop] BAD STATE: %d", btc.State)
				btc.Close()
				leaveChan <- btc
				continue
			}

			addChan <- btc
			log.Printf("AAAAAAAAAAAAAAAAAAAAAAAA: %q", btc.Addr)
			btc.State = BTStateReadyForMessages
			btc.MessageChan <- true
		case _ = <-btc.MessageChan:
			log.Printf("[readLoop] Reading from MessageChan: %q", btc)
			m, err := structure.ReadMessage(btc)
			if err != nil {
				log.Printf("[readLoop] Error reading message: %s", err)
				btc.Close()
				leaveChan <- btc
				continue
			}
			log.Printf("[readLoop] Did Read from MessageChan: %q", m)

			switch m.(type) {
			case *structure.KeepAliveMessage:
				log.Println("[readLoop] Received: KeepAlive MESSAGE")
				// TODO: reset disconnect timer
				break
			case *structure.ChokeMessage:
				break
			case *structure.UnchokeMessage:
				log.Println("[readLoop] Received: Unchoke MESSAGE")
				btc.PeerChoking = false
				btc.WriteChan <- structure.NewRequestMessage(0x00000bb0, 0x00024000, 0x00004000)
			case *structure.BitFieldMessage:
				log.Println("[readLoop] Received: Bit Field MESSAGE")
				btc.BitField = m.(*structure.BitFieldMessage).BitField
				btc.WriteChan <- structure.NewInterestedMessage()
			case *structure.HaveMessage:
				log.Println("[readLoop] Received: Have MESSAGE")
				pi := m.(*structure.HaveMessage).PieceIndex
				log.Printf("[readLoop] Have Message Index: %q", pi)
				log.Printf("BIT 0: %q", btc.BitField.Get(0))
				btc.BitField.Set(uint32(pi), 1)
				log.Printf("BIT 0: %q", btc.BitField.Get(0))

			//			case *structure.PieceMessage:
			//				log.Println("[readLoop] Received: Piece MESSAGE")
			default:
				log.Println("[readLoop] Received: OTHER MESSAGE")
			}
			log.Println("[readLoop] Received Message: ", m)
			btc.MessageChan <- true
		}
	}
}