1
0

Uploader.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # Written by Bram Cohen
  2. # see LICENSE.txt for license information
  3. from BitTornado.CurrentRateMeasure import Measure
  4. try:
  5. True
  6. except:
  7. True = 1
  8. False = 0
  9. class Upload:
  10. def __init__(self, connection, ratelimiter, totalup, choker, storage,
  11. picker, config):
  12. self.connection = connection
  13. self.ratelimiter = ratelimiter
  14. self.totalup = totalup
  15. self.choker = choker
  16. self.storage = storage
  17. self.picker = picker
  18. self.config = config
  19. self.max_slice_length = config['max_slice_length']
  20. self.choked = True
  21. self.cleared = True
  22. self.interested = False
  23. self.super_seeding = False
  24. self.buffer = []
  25. self.measure = Measure(config['max_rate_period'], config['upload_rate_fudge'])
  26. self.was_ever_interested = False
  27. if storage.get_amount_left() == 0:
  28. if choker.super_seed:
  29. self.super_seeding = True # flag, and don't send bitfield
  30. self.seed_have_list = [] # set from piecepicker
  31. self.skipped_count = 0
  32. else:
  33. if config['breakup_seed_bitfield']:
  34. bitfield, msgs = storage.get_have_list_cloaked()
  35. connection.send_bitfield(bitfield)
  36. for have in msgs:
  37. connection.send_have(have)
  38. else:
  39. connection.send_bitfield(storage.get_have_list())
  40. else:
  41. if storage.do_I_have_anything():
  42. connection.send_bitfield(storage.get_have_list())
  43. self.piecedl = None
  44. self.piecebuf = None
  45. def got_not_interested(self):
  46. if self.interested:
  47. self.interested = False
  48. del self.buffer[:]
  49. self.piecedl = None
  50. if self.piecebuf:
  51. self.piecebuf.release()
  52. self.piecebuf = None
  53. self.choker.not_interested(self.connection)
  54. def got_interested(self):
  55. if not self.interested:
  56. self.interested = True
  57. self.was_ever_interested = True
  58. self.choker.interested(self.connection)
  59. def get_upload_chunk(self):
  60. if self.choked or not self.buffer:
  61. return None
  62. index, begin, length = self.buffer.pop(0)
  63. if self.config['buffer_reads']:
  64. if index != self.piecedl:
  65. if self.piecebuf:
  66. self.piecebuf.release()
  67. self.piecedl = index
  68. self.piecebuf = self.storage.get_piece(index, 0, -1)
  69. try:
  70. piece = self.piecebuf[begin:begin+length]
  71. assert len(piece) == length
  72. except: # fails if storage.get_piece returns None or if out of range
  73. self.connection.close()
  74. return None
  75. else:
  76. if self.piecebuf:
  77. self.piecebuf.release()
  78. self.piecedl = None
  79. piece = self.storage.get_piece(index, begin, length)
  80. if piece is None:
  81. self.connection.close()
  82. return None
  83. self.measure.update_rate(len(piece))
  84. self.totalup.update_rate(len(piece))
  85. return (index, begin, piece)
  86. def got_request(self, index, begin, length):
  87. if ( (self.super_seeding and not index in self.seed_have_list)
  88. or not self.interested or length > self.max_slice_length ):
  89. self.connection.close()
  90. return
  91. if not self.cleared:
  92. self.buffer.append((index, begin, length))
  93. if not self.choked and self.connection.next_upload is None:
  94. self.ratelimiter.queue(self.connection)
  95. def got_cancel(self, index, begin, length):
  96. try:
  97. self.buffer.remove((index, begin, length))
  98. except ValueError:
  99. pass
  100. def choke(self):
  101. if not self.choked:
  102. self.choked = True
  103. self.connection.send_choke()
  104. self.piecedl = None
  105. if self.piecebuf:
  106. self.piecebuf.release()
  107. self.piecebuf = None
  108. def choke_sent(self):
  109. del self.buffer[:]
  110. self.cleared = True
  111. def unchoke(self):
  112. if self.choked:
  113. self.choked = False
  114. self.cleared = False
  115. self.connection.send_unchoke()
  116. def disconnected(self):
  117. if self.piecebuf:
  118. self.piecebuf.release()
  119. self.piecebuf = None
  120. def is_choked(self):
  121. return self.choked
  122. def is_interested(self):
  123. return self.interested
  124. def has_queries(self):
  125. return not self.choked and len(self.buffer) > 0
  126. def get_rate(self):
  127. return self.measure.get_rate()