Author | Message | Time |
---|---|---|
Topaz | [code]import socket import struct class packetbuffer: def __init__(self): self.buffer = list() #declares self.buffer as a list def insertData(self, data): self.buffer.append(data) def sendPacket(self, sock): tmp = '' for i in self.buffer: tmp += str(i) tmp = struct.pack('H', len(tmp) + 2) + tmp sock.send(tmp) print sock.recv(1024) self.clear() def clear(self): #clears the buffer self.buffer = list() sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('useast.battle.net', 6112)) sock.send(chr(2)) pBuffer = packetbuffer() pBuffer.insertData(0) pBuffer.insertData(1) pBuffer.insertData('68XIRATS') pBuffer.insertData(0) pBuffer.insertData(0) pBuffer.insertData(0) pBuffer.insertData(0) pBuffer.insertData(0) pBuffer.insertData('icons.bni') pBuffer.sendPacket(sock) print sock.recv(1024) [/code] [s]Problem is, though, it simply sits there. Does anyone have any ideas as to what I did wrong?[/s] see below | June 2, 2006, 1:30 AM |
l2k-Shadow | I'm not very familiar with python but it seems to me that you are not waiting for it to actually connect, you just tell it to connect and send your chr(2) right away.. without getting a callback that the socket connected. | June 2, 2006, 2:11 AM |
K | most likely the default connect() is blocking, so that's not the issue. | June 2, 2006, 2:24 AM |
Topaz | [quote author=l2k-Shadow link=topic=15108.msg153636#msg153636 date=1149214299] I'm not very familiar with python but it seems to me that you are not waiting for it to actually connect, you just tell it to connect and send your chr(2) right away.. without getting a callback that the socket connected. [/quote] It would throw an error if the socket wasn't connected. | June 2, 2006, 2:29 AM |
Yegg | Try doing something like: [code]while 1: received = sock.recv(1024) print received[/code] | June 2, 2006, 7:08 PM |
Topaz | [quote author=Yegg link=topic=15108.msg153700#msg153700 date=1149275285] Try doing something like: [code]while 1: received = sock.recv(1024) print received[/code] [/quote] Useless... | June 2, 2006, 7:44 PM |
Yegg | [quote author=Topaz link=topic=15108.msg153706#msg153706 date=1149277471] [quote author=Yegg link=topic=15108.msg153700#msg153700 date=1149275285] Try doing something like: [code]while 1: received = sock.recv(1024) print received[/code] [/quote] Useless... [/quote] Wasn't thinking :). | June 2, 2006, 8:16 PM |
Topaz | Hah! Been a couple of months since I've looked at this, and fixed all the bugs (it was the '.' over '\x00' issue I had in another project, since I used the same packet sending buffer) bnftp.py [code] """ Notes: This is BnFTP v1, which means it'll work for all products except WAR3 and W3XP. When ctypes starts to want to work with BNCSUtil, I'll write one for BnFTP v2. Thanks to: #python on irc.freenode.net, for their help with my problem with integer division (and the resulting use of __future__ to get the desired results) """ __author__ = 'topaz' __copyright__ = 'BSD License' from __future__ import division import pbuffer import socket import sys class bnftpv1: def __init__(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) def connect(self, server_address, file_name): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_address = (server_address, 6112,) self.file_name = file_name self.socket.connect(self.server_address) self.socket.send(chr(2)) print 'Connecting to BnFTP (server: %s)...' %self.socket.getpeername()[0] send_buffer = pbuffer.send_buffer(self.socket) send_buffer.insert_byte(0) send_buffer.insert_byte(1) send_buffer.insert_string('68XIRATS') send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_nt_string(self.file_name) send_buffer.send_packet() def parse_socket(self): while True: data = self.socket.recv(1024) if data.find(file_name) <> -1: downloaded_file = open('./' + self.file_name, 'w') total_downloaded = 0 recv_buffer = pbuffer.recv_buffer(data) recv_buffer.next_word() recv_buffer.next_word() file_size = recv_buffer.next_dword() file_time = recv_buffer.next_data(22) recv_buffer.jump(22) recv_buffer.next_string() data = recv_buffer.get_rest() print 'Filesize for %s is %d bytes' %(self.file_name, file_size) try: total_downloaded = total_downloaded + len(data) except NameError: print 'Cannot download file %s (does not exist?).' %self.file_name print 'Connection to BnFTP (server: %s) closed.' %self.socket.getpeername()[0] self.socket.close() break downloaded_file.write(data) print 'Downloaded & wrote %d bytes to file "%s": %.1f%%.' %(total_downloaded, self.file_name, (total_downloaded / file_size) * 100) if total_downloaded == file_size: print 'Download complete!' downloaded_file.close() self.socket.close() break def main(file_name, server_address): bnftp = bnftpv1() bnftp.connect(server_address, file_name) bnftp.parse_socket() [/code] pbuffer.py [code]import struct class send_buffer: def __init__(self, sock): self.buffer = [] self.sock = sock def insert_data(self, data): self.buffer.append(data) def insert_string(self, data): self.buffer.append(data) def insert_nt_string(self, data): self.buffer.append(data + chr(0)) def insert_dword(self, data): data = self.make_dword(data) self.buffer.append(data) def insert_dword_list(self, data): self.buffer.extend(data) def insert_byte(self, data): self.buffer.append(chr(data)) def make_dword(self, data): return struct.pack('I', data) def make_word(self, data): return struct.pack('H', data) def send_packet(self): tmp = "".join([str(x) for x in self.buffer]) packet_len = self.make_word(len(tmp) + 2) self.sock.send(packet_len) self.sock.send(tmp) self.clear() def clear(self): self.buffer = [] class recv_buffer: def __init__(self, raw_buffer): self.raw_buffer = raw_buffer self.position = 0 def get_dword(self, data): return struct.unpack('<I', data) def get_word(self, data): return struct.unpack('<H', data) def increment(self): self.position = self.position + 1 def jump(self, bytes): self.position += bytes def back(self, bytes): self.position -= bytes def set_pos(self, position): self.position = position def next_byte(self): param = self.raw_buffer[self.position:self.position + 1] byte = struct.unpack('b', param)[0] self.increment() return byte def next_string(self): pos = self.raw_buffer.find(chr(0), self.position) string = self.raw_buffer[self.position:pos] self.set_pos(pos + 1) return string def next_dword(self): param = self.raw_buffer[self.position:self.position + 4] dword = struct.unpack('I', param)[0] self.jump(4) return dword def next_word(self): param = self.raw_buffer[self.position:self.position + 2] word = struct.unpack('H', param)[0] self.jump(2) return word def next_data(self, bytes): return self.raw_buffer[self.position: self.position + bytes] def get_rest(self): data = self.raw_buffer[self.position:] self.set_pos(0) return data[/code] http://advancedcontent.net/topaz/sources/bnftp-python.zip Edit: Cleaned up the code a bit, more verbose, error handling for nonexistent files on the FTP. sample output: [quote]Connecting to BnFTP (server: 63.240.202.129)... Filesize for ver-ix86-0.mpq is 6894 bytes Downloaded and wrote 0 bytes to file "ver-ix86-0.mpq": 0.0% complete Downloaded and wrote 536 bytes to file "ver-ix86-0.mpq": 7.8% complete Downloaded and wrote 1560 bytes to file "ver-ix86-0.mpq": 22.6% complete Downloaded and wrote 2144 bytes to file "ver-ix86-0.mpq": 31.1% complete Downloaded and wrote 3168 bytes to file "ver-ix86-0.mpq": 46.0% complete Downloaded and wrote 3752 bytes to file "ver-ix86-0.mpq": 54.4% complete Downloaded and wrote 4776 bytes to file "ver-ix86-0.mpq": 69.3% complete Downloaded and wrote 4824 bytes to file "ver-ix86-0.mpq": 70.0% complete Downloaded and wrote 5848 bytes to file "ver-ix86-0.mpq": 84.8% complete Downloaded and wrote 6432 bytes to file "ver-ix86-0.mpq": 93.3% complete Downloaded and wrote 6894 bytes to file "ver-ix86-0.mpq": 100.0% complete Download complete![/quote] 2: [quote]Connecting to BnFTP (server: 63.240.202.129)... Cannot download file Fefe.mpq (does not exist?). Connection to BnFTP (server: 63.240.202.129) closed.[/quote] Edit 3: put all the code together into a class, can be used like such: [code]if __name__ == '__main__': try: file_name, server_address = sys.argv[1:3] except ValueError: print 'Error: probably not enough arguments:' print 'Format is bnftp.py file server (ex: bnftp.py icons.bni useast.battle.net)' main(file_name, server_address)[/code] and then: [quote] bnftp.py lockdown-IX86-00.mpq useast.battle.net [/quote] | October 9, 2006, 2:51 AM |
JoeTheOdd | I just noticed a weird thing in the BNFTP protocol. [code]send_buffer = pbuffer.send_buffer(sock) send_buffer.insert_byte(0) send_buffer.insert_byte(1) send_buffer.insert_string('68XIRATS') send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_dword(0) send_buffer.insert_nt_string(file_name) send_buffer.send_packet()[/code] That must be horrid on their processors for DWORD alignment, although the two bytes in the beginning followed by "icons.bni\x00" do line up to 8 bytes. | October 9, 2006, 12:11 PM |
Kp | [quote author=topaz link=topic=15108.msg159580#msg159580 date=1160362297] main.py [code] __author__ = 'topaz' __copyright__ = 'BSD License'[/code][/quote] Is that BSD-with-attribution or revised BSD? | October 15, 2006, 9:18 PM |
Topaz | [quote author=Kp link=topic=15108.msg159851#msg159851 date=1160947139] [quote author=topaz link=topic=15108.msg159580#msg159580 date=1160362297] main.py [code] __author__ = 'topaz' __copyright__ = 'BSD License'[/code][/quote] Is that BSD-with-attribution or revised BSD? [/quote] http://www.gnu.org/licenses/info/BSD_3Clause.html | October 15, 2006, 9:25 PM |
Myndfyr | [quote author=Joe[x86] link=topic=15108.msg159591#msg159591 date=1160395916] That must be horrid on their processors for DWORD alignment, although the two bytes in the beginning followed by "icons.bni\x00" do line up to 8 bytes. [/quote] Have you noticed that most of the Battle.net protocol isn't word-aligned? The thing about this protocol is that it's not like there's a time-sensitive requirement on it. A nuclear reactor isn't going to fail, nor do we need to worry about a dropped frame if the structure isn't padded precisely. The processor doesn't do anything while it's waiting for aligned memory. The memory controller is what's doing the work for non-aligned memory. | October 15, 2006, 9:37 PM |