Package Anomos :: Package Protocol :: Module AnomosEndPointProtocol
[hide private]
[frames] | no frames]

Source Code for Module Anomos.Protocol.AnomosEndPointProtocol

  1  # AnomosNeighborProtocol.py 
  2  # 
  3  # This program is free software: you can redistribute it and/or modify 
  4  # it under the terms of the GNU General Public License as published by 
  5  # the Free Software Foundation, either version 3 of the License, or 
  6  # (at your option) any later version. 
  7  # 
  8  # This program is distributed in the hope that it will be useful, 
  9  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 10  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 11  # GNU General Public License for more details. 
 12  # 
 13  # You should have received a copy of the GNU General Public License 
 14  # along with this program.  If not, see <http://www.gnu.org/licenses/>. 
 15   
 16  # Written by John Schanck 
 17   
 18  from Anomos.Protocol import CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED, \ 
 19                              HAVE, BITFIELD, REQUEST, PIECE, CANCEL, \ 
 20                              TCODE, CONFIRM, ENCRYPTED, RELAY, BREAK, PARTIAL, \ 
 21                              ACKBREAK 
 22  from Anomos.Protocol import tobinary, toint, AnomosProtocol 
 23  from Anomos.bitfield import Bitfield 
 24  from Anomos import log_on_call, LOG as log 
 25   
26 -class AnomosEndPointProtocol(AnomosProtocol):
27 ## EndPointProtocol is intended to be implemented by EndPoint ##
28 - def __init__(self):
29 AnomosProtocol.__init__(self) 30 #msgmap := Lookup table for methods to use when responding to message types 31 self.msgmap.update({CHOKE: self.got_choke,\ 32 UNCHOKE: self.got_unchoke,\ 33 INTERESTED: self.got_interested,\ 34 NOT_INTERESTED: self.got_not_interested,\ 35 HAVE: self.got_have,\ 36 BITFIELD: self.got_bitfield,\ 37 REQUEST: self.got_request,\ 38 PIECE: self.got_piece,\ 39 CANCEL: self.got_cancel,\ 40 CONFIRM: self.got_confirm, \ 41 ENCRYPTED: self.got_encrypted, \ 42 RELAY: self.got_relay, \ 43 BREAK: self.got_break, \ 44 PARTIAL: self.got_partial, \ 45 ACKBREAK: self.got_ack_break})
46 - def invalid_message(self, t):
47 log.warning("Invalid message of type %02x on %s. Closing stream."% \ 48 (ord(t), self.uniq_id())) 49 self.close()
50 - def transfer_ctl_msg(self, type, message=""):
51 """ Send method for file transfer messages. 52 ie. CHOKE, INTERESTED, PIECE """ 53 payload = ENCRYPTED + self.e2e_key.encrypt(type + message) 54 self.neighbor.queue_message(self.stream_id, RELAY + payload)
55 #if self.should_queue(): 56 # self.ratelimiter.queue(self) 57 58 # Message receiving calls #
59 - def got_confirm(self):
60 if not self.complete: 61 self.connection_completed()
62 - def got_relay(self, message):
63 self.got_message(message[1:])
64 - def got_encrypted(self, message):
65 if self.e2e_key is not None: 66 m = self.e2e_key.decrypt(message[1:]) 67 self.got_message(m) 68 else: 69 raise RuntimeError("Received encrypted data before we were ready")
70 - def got_break(self):
71 self.send_ack_break() 72 if not self.closed: 73 self.shutdown() 74 self.neighbor.end_stream(self.stream_id) 75 self.neighbor = None
76 - def got_ack_break(self):
77 if self.sent_break: 78 if not self.closed: 79 self.shutdown() 80 self.neighbor.end_stream(self.stream_id) 81 self.neighbor = None
82 - def got_partial(self, message):
83 p_remain = toint(message[1:5]) 84 payload = message[5:] 85 self.partial_recv += payload 86 if len(self.partial_recv) > self.neighbor.config['max_message_length']: 87 log.error("Received message longer than max length, %d"%l) 88 return 89 if len(payload) == p_remain: 90 self.got_message(self.partial_recv) 91 self.partial_recv = ''
92 - def got_choke(self):
93 if self.download: 94 self.download.got_choke()
95 - def got_unchoke(self):
96 if self.download: 97 self.download.got_unchoke()
98 - def got_interested(self):
99 if self.upload: 100 self.upload.got_interested()
101 - def got_not_interested(self):
102 if self.upload: 103 self.upload.got_not_interested()
104 - def got_have(self, message):
105 i = toint(message[1:]) 106 if i >= self.torrent.numpieces: 107 log.error("Piece index out of range") 108 self.fatal_error() 109 return 110 self.download.got_have(i)
111 - def got_bitfield(self, message):
112 try: 113 b = Bitfield(self.torrent.numpieces, message[1:]) 114 except ValueError: 115 self.fatal_error("Bad Bitfield") 116 return 117 self.download.got_have_bitfield(b)
118 - def got_request(self, message):
119 i = toint(message[1:5]) 120 if i >= self.torrent.numpieces: 121 self.fatal_error("Piece index out of range") 122 return 123 if self.upload: 124 self.upload.got_request(i, toint(message[5:9]), toint(message[9:]))
125 - def got_cancel(self, message):
126 i = toint(message[1:5]) 127 if i >= self.torrent.numpieces: 128 self.fatal_error("Piece index out of range") 129 return 130 if self.upload: 131 self.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
132 - def got_piece(self, message):
133 i = toint(message[1:5]) 134 if i >= self.torrent.numpieces: 135 self.fatal_error("Piece index out of range") 136 return 137 if self.download.got_piece(i, toint(message[5:9]), message[9:]): 138 for ep in self.torrent.active_streams: 139 ep.send_have(i)
140 141 # Message sending calls #
142 - def send_break(self):
143 self.network_ctl_msg(BREAK) 144 self.sent_break = True
145 - def send_ack_break(self):
147 - def send_confirm(self):
149 - def send_interested(self):
151 - def send_not_interested(self):
153 - def send_choke(self):
154 self.transfer_ctl_msg(CHOKE) 155 self.choke_sent = True 156 if self.upload: 157 self.upload.sent_choke()
158 - def send_unchoke(self):
159 self.transfer_ctl_msg(UNCHOKE) 160 self.choke_sent = False
161 - def send_request(self, index, begin, length):
162 self.transfer_ctl_msg(REQUEST, tobinary(index) + 163 tobinary(begin) + tobinary(length))
164 - def send_cancel(self, index, begin, length):
165 self.transfer_ctl_msg(CANCEL, tobinary(index) + 166 tobinary(begin) + tobinary(length))
167 - def send_bitfield(self, bitfield):
169 - def send_have(self, index):
170 self.transfer_ctl_msg(HAVE, tobinary(index))
171 - def send_tracking_code(self, trackcode):
172 self.network_ctl_msg(TCODE, trackcode)
173 #self.neighbor.queue_message(self.stream_id, TCODE+trackcode) 174 #if self.should_queue(): 175 # self.ratelimiter.queue(self)
176 - def send_piece(self, index, begin, piece):
177 msg = "".join([tobinary(index), tobinary(begin), piece]) 178 self.transfer_ctl_msg(PIECE, msg)
179