8 "github.com/elliotchance/orderedmap"
10 "github.com/anacrolix/torrent"
11 pp "github.com/anacrolix/torrent/peer_protocol"
14 type peerData struct {
15 requested *orderedmap.OrderedMap
16 haveDeleted map[torrent.Request]bool
19 // Tracks the order that peers upload requests that we've sent them.
20 type PeerUploadOrder struct {
22 peers map[*torrent.Peer]*peerData
25 func (me *PeerUploadOrder) Init() {
26 me.peers = make(map[*torrent.Peer]*peerData)
29 func (me *PeerUploadOrder) onNewPeer(p *torrent.Peer) {
32 if _, ok := me.peers[p]; ok {
33 panic("already have peer")
35 me.peers[p] = &peerData{
36 requested: orderedmap.NewOrderedMap(),
37 haveDeleted: make(map[torrent.Request]bool),
41 func (me *PeerUploadOrder) onSentRequest(event torrent.PeerRequestEvent) {
44 if !me.peers[event.Peer].requested.Set(event.Request, nil) {
45 panic("duplicate request sent")
49 func (me *PeerUploadOrder) Install(cbs *torrent.Callbacks) {
50 cbs.NewPeer = append(cbs.NewPeer, me.onNewPeer)
51 cbs.SentRequest = append(cbs.SentRequest, me.onSentRequest)
52 cbs.ReceivedRequested = append(cbs.ReceivedRequested, me.onReceivedRequested)
53 cbs.DeletedRequest = append(cbs.DeletedRequest, me.deletedRequest)
56 func (me *PeerUploadOrder) report(desc string, req torrent.Request, peer *torrent.Peer) {
57 peerConn, ok := peer.TryAsPeerConn()
58 var peerId *torrent.PeerID
60 peerId = &peerConn.PeerID
62 log.Printf("%s: %v, %v", desc, req, peerId)
65 func (me *PeerUploadOrder) onReceivedRequested(event torrent.PeerMessageEvent) {
66 req := torrent.Request{
69 Begin: event.Message.Begin,
70 Length: pp.Integer(len(event.Message.Piece)),
73 makeLogMsg := func(desc string) string {
74 peerConn, ok := event.Peer.TryAsPeerConn()
75 var peerId *torrent.PeerID
77 peerId = &peerConn.PeerID
79 return fmt.Sprintf("%s: %q, %v", desc, peerId, req)
83 peerData := me.peers[event.Peer]
84 if peerData.requested.Front().Key.(torrent.Request) == req {
85 log.Print(makeLogMsg("got next requested piece"))
86 } else if _, ok := peerData.requested.Get(req); ok {
87 log.Print(makeLogMsg(fmt.Sprintf(
88 "got requested piece but not next (previous delete=%v)",
89 peerData.haveDeleted[req])))
91 panic(makeLogMsg("got unrequested piece"))
95 func (me *PeerUploadOrder) deletedRequest(event torrent.PeerRequestEvent) {
98 peerData := me.peers[event.Peer]
99 if !peerData.requested.Delete(event.Request) {
100 panic("nothing to delete")
102 peerData.haveDeleted[event.Request] = true