1# Written by Arno Bakker 2# see LICENSE.txt for license information 3# 4# Python implementation of the on-the-wire part of the swift protocol 5# (PPSP-04 draft) for simple tests. 6# 7 8import sys 9import socket 10import struct 11import os 12 13import binascii 14 15 16HASH_ZERO = '\x00' * 20 17 18 19TSBYTES_LEN = 8 20 21IPV4BYTES_LEN = (32/8)+2 22IPV6BYTES_LEN = (128/8)+2 23 24 25CHUNK_SPEC_ID_BIN32 = '\x00' 26CHUNK_SPEC_ID_BYTE64 = '\x01' 27CHUNK_SPEC_ID_CHUNK32 = '\x02' 28CHUNK_SPEC_ID_BIN64 = '\x03' 29CHUNK_SPEC_ID_CHUNK64 = '\x04' 30 31 32class Encodable: 33 def to_bytes(self): 34 pass 35 def from_bytes(bytes): 36 pass 37 from_bytes = staticmethod(from_bytes) 38 def get_bytes_length(): 39 pass 40 def __repr__(self): 41 return self.__str__() 42 43# 44# Chunk Addressing 45# 46 47class Bin(Encodable): 48 def __init__(self,i): 49 self.i = i 50 #print >>sys.stderr,"Bin: set:",self.i 51 def to_bytes(self): 52 return struct.pack(">I",self.i) 53 def from_bytes(bytes): 54 [i] = struct.unpack(">I",bytes) 55 return Bin(i) 56 from_bytes = staticmethod(from_bytes) 57 def get_bytes_length(): 58 return 4 59 get_bytes_length = staticmethod(get_bytes_length) 60 def get_id(): 61 return CHUNK_SPEC_ID_BIN32 62 get_id = staticmethod(get_id) 63 def __str__(self): 64 return "Bin("+str(self.i)+")" 65 66 67BIN_ALL = Bin(0x7fffffff) 68BIN_NONE = Bin(0xffffffff) 69 70 71class ChunkRange(Encodable): 72 def __init__(self,s,e): 73 self.s = s 74 self.e = e 75 #print >>sys.stderr,"ChunkRange: set:",s,e 76 def to_bytes(self): 77 return struct.pack(">II",self.s,self.e) 78 def from_bytes(bytes): 79 [s,e] = struct.unpack(">II",bytes) 80 return ChunkRange(s,e) 81 from_bytes = staticmethod(from_bytes) 82 def get_bytes_length(): 83 return 8 84 get_bytes_length = staticmethod(get_bytes_length) 85 def get_id(): 86 return CHUNK_SPEC_ID_CHUNK32 87 get_id = staticmethod(get_id) 88 def __str__(self): 89 return "ChunkRange("+str(self.s)+","+str(self.e)+")" 90 91# 92# TimeStamp 93# 94 95class TimeStamp(Encodable): 96 def __init__(self,ts): 97 self.ts = ts 98 def to_bytes(self): 99 return struct.pack(">Q",self.ts) 100 def from_bytes(bytes): 101 [ts] = struct.unpack(">Q",bytes) 102 return TimeStamp(ts) 103 from_bytes = staticmethod(from_bytes) 104 def get_bytes_length(): 105 return 8 106 get_bytes_length = staticmethod(get_bytes_length) 107 def get_id(): 108 return None 109 get_id = staticmethod(get_id) 110 def __str__(self): 111 return "TimeStamp("+str(self.s)+","+str(self.e)+")" 112 113 114class IPv4Port(Encodable): 115 def __init__(self,ipport): # Python tuple 116 self.ipport = ipport 117 def to_bytes(self): 118 ipbytes = socket.inet_aton(self.ipport[0]) 119 portbytes = struct.pack(">H",self.ipport[1]) 120 chain = [ipbytes,portbytes] 121 return "".join(chain) 122 def from_bytes(bytes): 123 ipbytes = bytes[0:4] 124 ip = socket.inet_ntoa(ipbytes) 125 portbytes = bytes[4:6] 126 [port] = struct.unpack(">H",portbytes) 127 return IPv4Port((ip,port)) 128 from_bytes = staticmethod(from_bytes) 129 def get_bytes_length(): 130 return 6 131 get_bytes_length = staticmethod(get_bytes_length) 132 def get_id(): 133 return None 134 get_id = staticmethod(get_id) 135 def __str__(self): 136 return str(self.ipport) 137 138 139class IPv6Port(Encodable): 140 def __init__(self,ipport): # Python tuple 141 self.ipport = ipport 142 def to_bytes(self): 143 if sys.platform == "win32": 144 ipbytes = inet_pton6(self.ipport[0]) 145 else: 146 ipbytes = socket.inet_pton(socket.AF_INET6, self.ipport[0]) 147 148 portbytes = struct.pack(">H",self.ipport[1]) 149 chain = [ipbytes,portbytes] 150 return "".join(chain) 151 def from_bytes(bytes): 152 ipbytes = bytes[0:16] 153 ip = socket.inet_ntop(socket.AF_INET6, ipbytes) 154 portbytes = bytes[16:18] 155 [port] = struct.unpack(">H",portbytes) 156 return IPv4Port((ip,port)) 157 from_bytes = staticmethod(from_bytes) 158 def get_bytes_length(): 159 return 18 160 get_bytes_length = staticmethod(get_bytes_length) 161 def get_id(): 162 return None 163 get_id = staticmethod(get_id) 164 def __str__(self): 165 return str(self.ipport) 166 167 168# Known deficiency: don't handle :: in the middle right. 169def inet_pton6(p): 170 #print >>sys.stderr,"inet_pton: Input",p,len(p) 171 if '.' in p: 172 # IPv4 mapped 173 idx = p.rfind(':') 174 p4 = p[idx+1:] 175 n4 = socket.inet_aton(p4) 176 n = '\x00' * 10 177 n += '\xff' * 2 178 n += n4 179 #print >>sys.stderr,"inet_pton: IPv4mapped",binascii.hexlify(n) 180 return n 181 182 s = '' 183 q = p 184 sidx = len(q) 185 while sidx > 0: 186 sidx = q.rfind(':') 187 if sidx == -1: 188 sidx = -1 189 diff = len(q)-1 - sidx 190 #print >>sys.stderr,"sidx",sidx 191 elem = q[sidx+1:] 192 #print >>sys.stderr,"inet_pton: elem",elem,diff 193 if diff < 4: 194 pad = '0' * (4-diff) 195 newelem = pad+elem 196 else: 197 newelem = elem 198 s = newelem+s 199 200 #print >>sys.stderr,"inet_pton: while s",s 201 q = q[0:sidx] 202 203 if len(s) != 32: 204 diff = 32-len(s) 205 ndiff = diff / 4 206 pre = '0000' * ndiff 207 s = pre+s 208 209 #print >>sys.stderr,"inet_pton: s",s 210 return binascii.unhexlify(s) 211 212# 213# ProtocolOptions 214# 215 216POPT_VER_TYPE = '\x00' 217POPT_VER_SWIFT = '\x00' 218POPT_VER_PPSP = '\x01' 219 220POPT_MIN_VER_TYPE = '\x01' 221POPT_SWARMID_TYPE = '\x02' 222POPT_CIPM_TYPE = '\x03' 223POPT_MHF_TYPE = '\x04' 224POPT_LSA_TYPE = '\x05' 225POPT_CAM_TYPE = '\x06' 226POPT_LDW_TYPE = '\x07' 227POPT_MSGS_TYPE = '\x08' 228POPT_END_TYPE = '\xff' 229 230POPT_CIPM_NONE = '\x00' 231POPT_CIPM_MERKLE = '\x01' 232POPT_CIPM_SIGNALL = '\x02' 233POPT_CIPM_UNIFIED_MERKLE = '\x03' 234 235POPT_MHF_SHA1 = '\x00' 236POPT_MHF_SHA224 = '\x01' 237POPT_MHF_SHA256 = '\x02' 238POPT_MHF_SHA384 = '\x03' 239POPT_MHF_SHA512 = '\x04' 240 241# POPT_CHUNK_ADDR_BIN32, see CHUNK_SPEC_ID_BIN32 242 243POPT_LSA_DH = '\x02' 244POPT_LSA_DSA = '\x03' 245POPT_LSA_RSASHA1 = '\x05' 246POPT_LSA_DSA_NSEC3_SHA1 = '\x06' 247POPT_LSA_RSASHA1_NSEC3_SHA1 = '\x07' 248POPT_LSA_RSASHA256 = '\x08' 249POPT_LSA_RSASHA512 = '\x0a' 250POPT_LSA_ECC_GOST = '\x0c' 251POPT_LSA_ECDSAP256SHA256 = '\x0d' 252POPT_LSA_ECDSAP384SHA384 = '\x0e' 253POPT_LSA_PRIVATEDNS = '\xfd' 254 255POPT_LDW_ALL_CHUNK32 = '\xff\xff\xff\xff' 256 257# SIGNPEAKTODO 258DUMMY_DEFAULT_SIG_LENGTH = 20 259 260# 261# Messages 262# 263 264 265MSG_ID_HANDSHAKE = '\x00' 266MSG_ID_DATA = '\x01' 267MSG_ID_ACK = '\x02' 268MSG_ID_HAVE = '\x03' 269MSG_ID_INTEGRITY = '\x04' 270MSG_ID_PEX_RESv4 = '\x05' 271MSG_ID_PEX_REQ = '\x06' 272MSG_ID_SIGNED_INTEGRITY = '\x07' 273MSG_ID_REQUEST = '\x08' 274MSG_ID_CANCEL = '\x09' 275MSG_ID_CHOKE = '\x0a' 276MSG_ID_UNCHOKE = '\x0b' 277MSG_ID_PEX_RESv6 = '\x0c' 278MSG_ID_PEX_REScert = '\x0d' 279 280 281 282 283 284class HandshakeMessage(Encodable): 285 def __init__(self,chanid,ver,minver=None,swarmid=None,cipm=None,mhf=None,lsa=None,cam=None,ldw=None,msgdata=None): 286 self.chanid = chanid 287 self.ver = ver 288 self.minver = minver 289 self.swarmid = swarmid 290 self.cipm = cipm 291 self.mhf = mhf 292 self.lsa = lsa 293 self.cam = cam 294 self.ldw = ldw 295 self.msgdata = msgdata 296 def to_bytes(self): 297 chain = [] 298 chain.append(HandshakeMessage.get_id()) 299 chain.append(self.chanid.to_bytes()) 300 if self.ver == POPT_VER_PPSP: 301 # TODO, make each ProtocolOption an Encodable 302 chain.append(POPT_VER_TYPE) 303 chain.append(self.ver) 304 if self.minver is not None: 305 chain.append(POPT_MIN_VER_TYPE) 306 chain.append(self.minver) 307 if self.swarmid is not None: 308 chain.append(POPT_SWARMID_TYPE) 309 s = len(self.swarmid) 310 sbytes = struct.pack(">H",s) 311 if len(sbytes) != 2: 312 print >>sys.stderr,"HandshakeMessage: SWARM SIZE WRONG PACK" 313 chain.append(sbytes) 314 chain.append(self.swarmid) 315 if self.cipm is not None: 316 chain.append(POPT_CIPM_TYPE) 317 chain.append(self.cipm) 318 if self.mhf is not None: 319 chain.append(POPT_MHF_TYPE) 320 chain.append(self.mhf) 321 if self.lsa is not None: 322 chain.append(POPT_LSA_TYPE) 323 chain.append(self.lsa) 324 if self.cam is not None: 325 chain.append(POPT_CAM_TYPE) 326 chain.append(self.cam) 327 if self.ldw is not None: 328 chain.append(POPT_LDW_TYPE) 329 chain.append(self.ldw) 330 if self.msgdata is not None: 331 chain.append(POPT_MSGDATA_TYPE) 332 s = len(msgdata) 333 sbytes = struct.pack(">H",s) 334 chain.append(sbytes) 335 chain.append(self.msgdata) 336 chain.append(POPT_END_TYPE) 337 return "".join(chain) 338 #print >>sys.stderr,"HS ON THE WIRE",binascii.hexlify(ret) 339 #return ret 340 341 def from_bytes(t,bytes,off): 342 off += 1 343 chanid = ChannelID.from_bytes( bytes[off:off+ChannelID.get_bytes_length()]) 344 #print >>sys.stderr,"hs:",`chanid` 345 off += chanid.get_bytes_length() 346 ver = None 347 minver = None 348 swarmid = None 349 cipm = None 350 mhf = None 351 lsa = None 352 cam = None 353 ldw = None 354 msgdata = None 355 if t.get_version() == POPT_VER_PPSP: 356 while off < len(bytes): 357 popt = bytes[off] 358 359 #print >>sys.stderr,"hs: popt is",`popt` 360 off += 1 361 if popt == POPT_VER_TYPE: 362 ver = bytes[off] 363 off += 1 364 elif popt == POPT_MIN_VER_TYPE: 365 minver = bytes[off] 366 off += 1 367 elif popt == POPT_SWARMID_TYPE: 368 sbytes = bytes[off:off+2] 369 off += len(sbytes) 370 [s] = struct.unpack(">H",sbytes) 371 swarmid = bytes[off:off+s] 372 off += len(swarmid) 373 elif popt == POPT_CIPM_TYPE: 374 cipm = bytes[off] 375 off += 1 376 elif popt == POPT_MHF_TYPE: 377 mhf = bytes[off] 378 off += 1 379 elif popt == POPT_LSA_TYPE: 380 lsa = bytes[off] 381 off += 1 382 elif popt == POPT_CAM_TYPE: 383 cam = bytes[off] 384 off += 1 385 elif popt == POPT_LDW_TYPE: 386 ldwsize = 8 387 if cam == CHUNK_SPEC_ID_BIN32 or cam == CHUNK_SPEC_ID_CHUNK32: 388 ldwsize = 4 389 ldw = bytes[off:off+ldwsize] 390 off += ldwsize 391 elif popt == POPT_MSGS_TYPE: 392 sbytes = bytes[off:off+1] 393 off += len(sbytes) 394 [s] = struct.unpack(">H",sbytes) 395 msgdata = bytes[off:off+s] 396 off += len(msgdata) 397 elif popt == POPT_END_TYPE: 398 break 399 400 return [HandshakeMessage(chanid,ver,minver,swarmid,cipm,mhf,lsa,cam,ldw,msgdata),off] 401 402 from_bytes = staticmethod(from_bytes) 403 def get_bytes_length(): 404 return None # variable 405 get_bytes_length = staticmethod(get_bytes_length) 406 def get_id(): 407 return MSG_ID_HANDSHAKE 408 get_id = staticmethod(get_id) 409 def __str__(self): 410 return "HANDSHAKE(ver="+`self.ver`+"minver="+`self.minver`+",sid="+`self.swarmid`+",cam="+`self.cam`+")" 411 412 413 414 415 416class DataMessage(Encodable): 417 def __init__(self,chunkspec,timestamp,chunk): # timestamp MUST be None for POPT_VER_SWIFT 418 self.chunkspec = chunkspec 419 self.ts = timestamp 420 self.chunk = chunk 421 def to_bytes(self): 422 if self.ts is None: 423 chain = [DataMessage.get_id(),self.chunkspec.to_bytes(),self.chunk] 424 else: 425 chain = [DataMessage.get_id(),self.chunkspec.to_bytes(),self.ts.to_bytes(),self.chunk] 426 return "".join(chain) 427 def from_bytes(t,bytes,off): 428 off += 1 429 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 430 off += len(cabytes) 431 chunkspec = t.chunkspec.from_bytes(cabytes) 432 tsbytes = bytes[off:off+TimeStamp.get_bytes_length()] 433 ts = TimeStamp.from_bytes(tsbytes) 434 off += len(tsbytes) 435 chunk = bytes[off:] 436 off = len(bytes) 437 return [DataMessage(chunkspec,ts,chunk),off] 438 from_bytes = staticmethod(from_bytes) 439 def get_bytes_length(): 440 return None # variable 441 get_bytes_length = staticmethod(get_bytes_length) 442 def get_id(): 443 return MSG_ID_DATA 444 get_id = staticmethod(get_id) 445 def __str__(self): 446 return "DATA("+`self.chunkspec`+",ts,chunk)" 447 448 449class AckMessage(Encodable): 450 def __init__(self,chunkspec,timestamp): 451 self.chunkspec = chunkspec 452 self.ts = timestamp 453 def to_bytes(self): 454 chain = [AckMessage.get_id(),self.chunkspec.to_bytes(),self.ts.to_bytes()] 455 return "".join(chain) 456 def from_bytes(t,bytes,off): 457 off += 1 458 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 459 off += len(cabytes) 460 chunkspec = t.chunkspec.from_bytes(cabytes) 461 tsbytes = bytes[off:off+TimeStamp.get_bytes_length()] 462 ts = TimeStamp.from_bytes(tsbytes) 463 off += len(tsbytes) 464 return [AckMessage(chunkspec,ts),off] 465 from_bytes = staticmethod(from_bytes) 466 def get_bytes_length(): 467 return None # variable due to chunkspec 468 get_bytes_length = staticmethod(get_bytes_length) 469 def get_id(): 470 return MSG_ID_ACK 471 get_id = staticmethod(get_id) 472 def __str__(self): 473 return "ACK("+`self.chunkspec`+",ts)" 474 475 476class HaveMessage(Encodable): 477 def __init__(self,chunkspec): 478 self.chunkspec = chunkspec 479 def to_bytes(self): 480 chain = [HaveMessage.get_id(),self.chunkspec.to_bytes()] 481 return "".join(chain) 482 def from_bytes(t,bytes,off): 483 off += 1 484 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 485 off += len(cabytes) 486 chunkspec = t.chunkspec.from_bytes(cabytes) 487 return [HaveMessage(chunkspec),off] 488 from_bytes = staticmethod(from_bytes) 489 def get_bytes_length(): 490 return None # variable due to chunkspec 491 get_bytes_length = staticmethod(get_bytes_length) 492 def get_id(): 493 return MSG_ID_HAVE 494 get_id = staticmethod(get_id) 495 def __str__(self): 496 return "HAVE("+`self.chunkspec`+")" 497 498 499class IntegrityMessage(Encodable): 500 def __init__(self,chunkspec,intbytes): 501 self.chunkspec = chunkspec 502 self.intbytes = intbytes 503 def to_bytes(self): 504 chain = [IntegrityMessage.get_id(),self.chunkspec.to_bytes(),self.intbytes] 505 return "".join(chain) 506 def from_bytes(t,bytes,off): 507 off += 1 508 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 509 off += len(cabytes) 510 chunkspec = t.chunkspec.from_bytes(cabytes) 511 intbytes = bytes[off:off+t.get_hash_length()] 512 off += len(intbytes) 513 return [IntegrityMessage(chunkspec,intbytes),off] 514 from_bytes = staticmethod(from_bytes) 515 def get_bytes_length(): 516 return None # variable 517 get_bytes_length = staticmethod(get_bytes_length) 518 def get_id(): 519 return MSG_ID_INTEGRITY 520 get_id = staticmethod(get_id) 521 def __str__(self): 522 return "INTEGRITY("+`self.chunkspec`+",intbytes)" 523 524class PexResv4Message(Encodable): 525 def __init__(self,ipp): 526 self.ipp = ipp 527 def to_bytes(self): 528 chain = [PexResv4Message.get_id(),self.ipp.to_bytes()] 529 return "".join(chain) 530 def from_bytes(t,bytes,off): 531 off += 1 532 ippbytes = bytes[off:off+IPv4Port.get_bytes_length()] 533 off += len(ippbytes) 534 ipp = IPv4Port.from_bytes(ippbytes) 535 return [PexResv4Message(ipp),off] 536 from_bytes = staticmethod(from_bytes) 537 def get_bytes_length(): 538 return None # variable due to chunkspec 539 get_bytes_length = staticmethod(get_bytes_length) 540 def get_id(): 541 return MSG_ID_PEX_RESv4 542 get_id = staticmethod(get_id) 543 def __str__(self): 544 return "PEX_RESv4("+`self.ipp`+")" 545 546class PexReqMessage(Encodable): 547 def __init__(self): 548 pass 549 def to_bytes(self): 550 chain = [PexReqMessage.get_id()] 551 return "".join(chain) 552 def from_bytes(t,bytes,off): 553 off += 1 554 return [PexReqMessage(),off] 555 from_bytes = staticmethod(from_bytes) 556 def get_bytes_length(): 557 return 1 # just MSG_ID 558 get_bytes_length = staticmethod(get_bytes_length) 559 def get_id(): 560 return MSG_ID_PEX_REQ 561 get_id = staticmethod(get_id) 562 def __str__(self): 563 return "PEX_REQ()" 564 565 566class SignedIntegrityMessage(Encodable): 567 def __init__(self,t,chunkspec,timestamp,intbytes): 568 self.chunkspec = chunkspec 569 self.timestamp = timestamp 570 self.intbytes = intbytes 571 def to_bytes(self): 572 chain = [SignedIntegrity.get_id(),self.chunkspec.to_bytes(),self.timestamp,self.intbytes] 573 return "".join(chain) 574 def from_bytes(t,bytes,off): 575 off += 1 576 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 577 off += len(cabytes) 578 chunkspec = t.chunkspec.from_bytes(cabytes) 579 timestamp = bytes[off:off+8] 580 off += 8 581 if t.lsa == POPT_LSA_ECDSAP256SHA256: 582 siglen = 64 583 elif t.lsa == POPT_LSA_ECDSAP384SHA384: 584 siglen = 96 585 else: 586 print >>sys.stderr,"swiftconn: SignedIntegrityMessage: LSA not implemented",ord(t.lsa) 587 os._exit(-1) 588 intbytes = bytes[off:off+siglen] 589 off += len(intbytes) 590 return [SignedIntegrityMessage(t,chunkspec,timestamp,intbytes),off] 591 from_bytes = staticmethod(from_bytes) 592 def get_bytes_length(): 593 return None # variable 594 get_bytes_length = staticmethod(get_bytes_length) 595 def get_id(): 596 return MSG_ID_SIGNED_INTEGRITY 597 get_id = staticmethod(get_id) 598 def __str__(self): 599 return "SIGNED_INTEGRITY("+`self.chunkspec`+",intbytes)" 600 601 602class RequestMessage(Encodable): 603 def __init__(self,chunkspec): 604 self.chunkspec = chunkspec 605 def to_bytes(self): 606 chain = [RequestMessage.get_id(),self.chunkspec.to_bytes()] 607 return "".join(chain) 608 def from_bytes(t,bytes,off): 609 off += 1 610 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 611 off += len(cabytes) 612 chunkspec = t.chunkspec.from_bytes(cabytes) 613 return [RequestMessage(chunkspec),off] 614 from_bytes = staticmethod(from_bytes) 615 def get_bytes_length(): 616 return None # variable due to chunkspec 617 get_bytes_length = staticmethod(get_bytes_length) 618 def get_id(): 619 return MSG_ID_REQUEST 620 get_id = staticmethod(get_id) 621 def __str__(self): 622 return "REQUEST("+`self.chunkspec`+")" 623 624class CancelMessage(Encodable): 625 def __init__(self,chunkspec): 626 self.chunkspec = chunkspec 627 def to_bytes(self): 628 chain = [CancelMessage.get_id(),self.chunkspec.to_bytes()] 629 return "".join(chain) 630 def from_bytes(t,bytes,off): 631 off += 1 632 cabytes = bytes[off:off+t.get_chunkspec().get_bytes_length()] 633 off += len(cabytes) 634 chunkspec = t.chunkspec.from_bytes(cabytes) 635 return [CancelMessage(chunkspec),off] 636 from_bytes = staticmethod(from_bytes) 637 def get_bytes_length(): 638 return None # variable due to chunkspec 639 get_bytes_length = staticmethod(get_bytes_length) 640 def get_id(): 641 return MSG_ID_CANCEL 642 get_id = staticmethod(get_id) 643 def __str__(self): 644 return "CANCEL("+`self.chunkspec`+")" 645 646 647class ChokeMessage(Encodable): 648 def __init__(self): 649 pass 650 def to_bytes(self): 651 chain = [ChokeMessage.get_id()] 652 return "".join(chain) 653 def from_bytes(t,bytes,off): 654 off += 1 655 return [ChokeMessage(),off] 656 from_bytes = staticmethod(from_bytes) 657 def get_bytes_length(): 658 return 1 # just MSG_ID 659 get_bytes_length = staticmethod(get_bytes_length) 660 def get_id(): 661 return MSG_ID_CHOKE 662 get_id = staticmethod(get_id) 663 def __str__(self): 664 return "CHOKE()" 665 666 667class UnchokeMessage(Encodable): 668 def __init__(self): 669 pass 670 def to_bytes(self): 671 chain = [UnchokeMessage.get_id()] 672 return "".join(chain) 673 def from_bytes(t,bytes,off): 674 off += 1 675 return [UnchokeMessage(),off] 676 from_bytes = staticmethod(from_bytes) 677 def get_bytes_length(): 678 return 1 # just MSG_ID 679 get_bytes_length = staticmethod(get_bytes_length) 680 def get_id(): 681 return MSG_ID_UNCHOKE 682 get_id = staticmethod(get_id) 683 def __str__(self): 684 return "UNCHOKE()" 685 686 687 688class PexResv6Message(Encodable): 689 def __init__(self,ipp): 690 self.ipp = ipp 691 def to_bytes(self): 692 chain = [PexResv6Message.get_id(),self.ipp.to_bytes()] 693 return "".join(chain) 694 def from_bytes(t,bytes,off): 695 ippbytes = bytes[off:off+IPv6Port.get_bytes_length()] 696 off += len(ippbytes) 697 ipp = IPv6Port.from_bytes(cabytes) 698 return [PexResv6Message(ipp),off] 699 from_bytes = staticmethod(from_bytes) 700 def get_bytes_length(): 701 return None # variable due to chunkspec 702 get_bytes_length = staticmethod(get_bytes_length) 703 def get_id(): 704 return MSG_ID_PEX_RESv6 705 get_id = staticmethod(get_id) 706 def __str__(self): 707 return "PEX_RESv6("+`self.ipp`+")" 708 709 710class PexResCertMessage(Encodable): 711 def __init__(self,certbytes): 712 self.certbytes = certbytes 713 def to_bytes(self): 714 sbytes = struct.pack(">H",len(self.certbytes)) 715 chain = [PexResCertMessage.get_id(),sbytes,self.certbytes] 716 return "".join(chain) 717 def from_bytes(t,bytes,off): 718 sbytes = bytes[off:off+1] 719 off += len(sbytes) 720 [s] = struct.unpack(">H",sbytes) 721 certbytes = bytes[2:2+s] 722 off += len(certbytes) 723 return [PexRescertMessage(certbytes),off] 724 from_bytes = staticmethod(from_bytes) 725 def get_bytes_length(): 726 return None # variable due to certificate 727 get_bytes_length = staticmethod(get_bytes_length) 728 def get_id(): 729 return MSG_ID_PEX_REScert 730 get_id = staticmethod(get_id) 731 def __str__(self): 732 return "PEX_REScert(cert)" 733 734 735class KeepAliveMessage(Encodable): 736 def __init__(self): 737 pass 738 def to_bytes(self): 739 return "" 740 def from_bytes(t,bytes,off): 741 return [KeepAliveMessage(),off] 742 from_bytes = staticmethod(from_bytes) 743 def get_bytes_length(): 744 return 0 745 get_bytes_length = staticmethod(get_bytes_length) 746 def get_id(): 747 return -1 748 get_id = staticmethod(get_id) 749 def __str__(self): 750 return "KEEPALIVE" 751 752 753# 754# Transfer 755# 756 757 758class Transfer: 759 760 def __init__(self,swarmid,version,chunkspec,cipm,lsa,socket): 761 self.swarmid = swarmid 762 self.version = version 763 self.chunkspec = chunkspec 764 self.cipm = cipm 765 self.lsa = lsa 766 self.socket = socket 767 768 def get_swarm_id(self): 769 return self.swarmid 770 771 def get_version(self): 772 return self.version 773 774 def get_hash_length(self): 775 return len(HASH_ZERO) 776 777 def get_chunkspec(self): 778 return self.chunkspec 779 780 def get_socket(self): 781 return self.socket 782 783 784 785class ChannelID(Encodable): 786 def __init__(self,id): 787 self.id = id 788 def to_bytes(self): 789 return self.id 790 def from_bytes(bytes): 791 id = bytes[0:4] 792 return ChannelID(id) 793 from_bytes = staticmethod(from_bytes) 794 def get_bytes_length(): 795 return 4 796 get_bytes_length = staticmethod(get_bytes_length) 797 def get_id(): 798 return None 799 get_id = staticmethod(get_id) 800 def __str__(self): 801 return "ChannelID("+`self.id`+")" 802 803 804# 805# Datagram 806# 807 808class Datagram(Encodable): 809 """ Serialization """ 810 def __init__(self,t=None,data=None): 811 self.t = t 812 if data is None: # send 813 self.chain = [] 814 else: 815 self.data = data 816 self.off = 0 817 818 def set_t(self,t): 819 self.t = t 820 821 def add(self,e): 822 self.chain.append(e) 823 824 def to_bytes(self): 825 wire = '' 826 for e in self.chain: 827 #print >>sys.stderr,"dgram: Add",`e` 828 wire += e.to_bytes() 829 return wire 830 831 def get_channel_id(self): 832 #print >>sys.stderr,"dgram: get_channel_id" 833 x = ChannelID.from_bytes( self.data[0:ChannelID.get_bytes_length()]) 834 self.off += ChannelID.get_bytes_length() 835 return x 836 837 def get_message(self): 838 if self.off == len(self.data): 839 return None 840 841 msgid = self.data[self.off:self.off+len(MSG_ID_HANDSHAKE)] 842 print >>sys.stderr,"dgram: get_message: GOT msgid",`msgid`,"off",self.off 843 844 if msgid == MSG_ID_HANDSHAKE: 845 [msg,self.off] = HandshakeMessage.from_bytes(self.t,self.data,self.off) 846 elif msgid == MSG_ID_DATA: 847 [msg,self.off] = DataMessage.from_bytes(self.t,self.data,self.off) 848 elif msgid == MSG_ID_ACK: 849 [msg,self.off] = AckMessage.from_bytes(self.t,self.data,self.off) 850 elif msgid == MSG_ID_HAVE: 851 [msg,self.off] = HaveMessage.from_bytes(self.t,self.data,self.off) 852 elif msgid == MSG_ID_INTEGRITY: 853 [msg,self.off] = IntegrityMessage.from_bytes(self.t,self.data,self.off) 854 elif msgid == MSG_ID_PEX_RESv4: 855 [msg,self.off] = PexResv4Message.from_bytes(self.t,self.data,self.off) 856 elif msgid == MSG_ID_PEX_REQ: 857 [msg,self.off] = PexReqMessage.from_bytes(self.t,self.data,self.off) 858 elif msgid == MSG_ID_SIGNED_INTEGRITY: 859 [msg,self.off] = SignedIntegrityMessage.from_bytes(self.t,self.data,self.off) 860 elif msgid == MSG_ID_REQUEST: 861 [msg,self.off] = RequestMessage.from_bytes(self.t,self.data,self.off) 862 elif msgid == MSG_ID_CANCEL: 863 [msg,self.off] = CancelMessage.from_bytes(self.t,self.data,self.off) 864 elif msgid == MSG_ID_CHOKE: 865 [msg,self.off] = ChokeMessage.from_bytes(self.t,self.data,self.off) 866 elif msgid == MSG_ID_UNCHOKE: 867 [msg,self.off] = UnchokeMessage.from_bytes(self.t,self.data,self.off) 868 elif msgid == MSG_ID_PEX_RESv6: 869 [msg,self.off] = PexResv6Message.from_bytes(self.t,self.data,self.off) 870 elif msgid == MSG_ID_PEX_REScert: 871 [msg,self.off] = PexRescertMessage.from_bytes(self.t,self.data,self.off) 872 else: 873 print >>sys.stderr,"dgram: get_message: unknown msgid",`msgid`,"off",self.off,"bytes left",len(self.data)-self.off 874 msg = None 875 return msg 876 877 878CONN_STATE_INIT = 0 879CONN_STATE_WAIT4HIS = 1 880CONN_STATE_WAIT4MINE = 2 881CONN_STATE_ESTABLISHED = 3 882 883CHAN_ID_ZERO = ChannelID.from_bytes('\x00' * 4) 884 885 886DGRAM_MAX_RECV = 65536 887 888class Channel: 889 def __init__(self,t,addr,localinit): 890 self.t = t 891 self.addr = addr 892 self.localinit = localinit 893 self.mychanid = ChannelID.from_bytes('6778') 894 self.hischanid = CHAN_ID_ZERO 895 896 def send(self,d): 897 self.t.get_socket().sendto(d,self.addr) 898 899 def recv(self,d): 900 while True: 901 msg = d.get_message() 902 if msg is None: 903 break 904 print >>sys.stderr,"chan: Parsed",`msg` 905 if msg.get_id() == MSG_ID_HANDSHAKE: 906 self.hischanid = msg.chanid 907 908 def get_my_chanid(self): 909 return self.mychanid 910 911 def get_his_chanid(self): 912 return self.hischanid 913 914 def set_his_chanid(self,chanid): 915 self.hischanid = chanid 916 917 918 919class Socket: 920 def __init__(self,myaddr,family=socket.AF_INET): 921 self.myaddr = myaddr 922 socket.setdefaulttimeout(10.0) 923 self.sock = socket.socket(family, socket.SOCK_DGRAM) 924 print >>sys.stderr,"Socket: __init__: bind",myaddr,family 925 self.sock.bind(myaddr) 926 927 def recv(self): 928 [data,addr] = self.sock.recvfrom(DGRAM_MAX_RECV) 929 print >>sys.stderr,"Socket: recv len",len(data) 930 931 return [addr,Datagram(None,data)] 932 933 def sendto(self,d,addr): 934 data = d.to_bytes() 935 return self.sock.sendto(data,addr) 936 937 def listen(self,swarmid,autochanid=True,hs=True): 938 [addr,d] = self.recv() 939 s = SwiftConnection(self.myaddr,addr,swarmid,listensock=self,hs=hs) 940 if autochanid: 941 chanid = d.get_channel_id() 942 print >>sys.stderr,"Socket: listen: Got ChannelID",`chanid` 943 d.set_t(s.t) 944 return [s,d] 945 946 947class SwiftConnection: 948 def __init__(self,myaddr,hisaddr,swarmid,listensock=None,hs=True,ver=POPT_VER_PPSP,minver=POPT_VER_PPSP,cipm=POPT_CIPM_MERKLE,mhf=POPT_MHF_SHA1,lsa=None,cam=CHUNK_SPEC_ID_CHUNK32,ldw=None,msgdata=None,chunkspec=ChunkRange(0,0)): 949 950 if listensock is None: 951 self.s = Socket(myaddr) 952 else: 953 self.s = listensock 954 #t = Transfer(swarmid,POPT_VER_PPSP,BIN_ALL,self.s) 955 self.t = Transfer(swarmid,ver,chunkspec,cipm,lsa,self.s) 956 self.c = Channel(self.t,hisaddr,listensock is None) 957 958 if hs: 959 d = Datagram(self.t) 960 if self.t.version == POPT_VER_SWIFT: 961 d.add( self.c.get_his_chanid() ) 962 d.add( IntegrityMessage(BIN_ALL,self.t.get_swarm_id()) ) 963 d.add( HandshakeMessage(self.c.get_my_chanid(),POPT_VER_SWIFT) ) 964 self.c.send(d) 965 else: 966 d.add( self.c.get_his_chanid() ) 967 d.add( HandshakeMessage(self.c.get_my_chanid(),ver=ver,minver=minver,swarmid=self.t.get_swarm_id(),cipm=cipm,mhf=mhf,lsa=lsa,cam=cam,ldw=ldw,msgdata=msgdata) ) 968 self.c.send(d) 969 970 def makeDatagram(self,autochanid=True): 971 d = Datagram(self.t) 972 if autochanid: 973 d.add( self.c.get_his_chanid() ) 974 return d 975 976 def send(self,d): 977 self.c.send(d) 978 979 def recv(self,autochanid=True): 980 [addr,d] = self.s.recv() 981 d.set_t(self.t) 982 if autochanid: 983 chanid = d.get_channel_id() 984 return d 985 986 987 988if __name__ == "__main__": 989 990 x = inet_pton6("::1") 991 print >>sys.stderr,"FINAL",`x` 992 993 #x = inet_pton6("2001:0:5ef5:79fb:385c:2235:3f57:ff99") 994 #print >>sys.stderr,"FINAL",`x` 995 996 #x = inet_pton6("fe80::385c:2235:3f57:ff99") 997 #print >>sys.stderr,"FINAL",x 998 999 #x = inet_pton6("::ffff:130.37.193.64") 1000 #print >>sys.stderr,"FINAL",x 1001 1002 1003