Send books using a streaming protocol instead of the request/response one.

This commit is contained in:
Charles Haley 2012-08-22 11:31:59 +02:00
parent 774a56c1fa
commit e00f4cf936

View File

@ -168,6 +168,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self.noop_counter = 0 self.noop_counter = 0
self.debug_start_time = time.time() self.debug_start_time = time.time()
self.debug_time = time.time() self.debug_time = time.time()
self.client_can_stream_books = False
def _debug(self, *args): def _debug(self, *args):
if not DEBUG: if not DEBUG:
@ -343,7 +344,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
# recv seems to return a pointer into some internal buffer. # recv seems to return a pointer into some internal buffer.
# Things get trashed if we don't make a copy of the data. # Things get trashed if we don't make a copy of the data.
self.device_socket.settimeout(self.MAX_CLIENT_COMM_TIMEOUT) self.device_socket.settimeout(self.MAX_CLIENT_COMM_TIMEOUT)
v = self.device_socket.recv(self.BASE_PACKET_LEN) v = self.device_socket.recv(2)
self.device_socket.settimeout(None) self.device_socket.settimeout(None)
if len(v) == 0: if len(v) == 0:
return '' # documentation says the socket is broken permanently. return '' # documentation says the socket is broken permanently.
@ -382,7 +383,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
raise raise
time.sleep(0.1) # lets not hammer the OS too hard time.sleep(0.1) # lets not hammer the OS too hard
def _call_client(self, op, arg, print_debug_info=True): def _call_client(self, op, arg, print_debug_info=True, wait_for_response=True):
if op != 'NOOP': if op != 'NOOP':
self.noop_counter = 0 self.noop_counter = 0
extra_debug = self.settings().extra_customization[self.OPT_EXTRA_DEBUG] extra_debug = self.settings().extra_customization[self.OPT_EXTRA_DEBUG]
@ -399,6 +400,27 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self._debug('send string', s) self._debug('send string', s)
self.device_socket.settimeout(self.MAX_CLIENT_COMM_TIMEOUT) self.device_socket.settimeout(self.MAX_CLIENT_COMM_TIMEOUT)
self._send_byte_string((b'%d' % len(s)) + s) self._send_byte_string((b'%d' % len(s)) + s)
if not wait_for_response:
return None, None
return self._receive_from_client(print_debug_info=print_debug_info)
except socket.timeout:
self._debug('timeout communicating with device')
self._close_device_socket()
raise TimeoutError('Device did not respond in reasonable time')
except socket.error:
self._debug('device went away')
self._close_device_socket()
raise ControlError(desc='Device closed the network connection')
except:
self._debug('other exception')
traceback.print_exc()
self._close_device_socket()
raise
raise ControlError(desc='Device responded with incorrect information')
def _receive_from_client(self, print_debug_info=True):
extra_debug = self.settings().extra_customization[self.OPT_EXTRA_DEBUG]
try:
v = self._read_string_from_net() v = self._read_string_from_net()
self.device_socket.settimeout(None) self.device_socket.settimeout(None)
if print_debug_info and extra_debug: if print_debug_info and extra_debug:
@ -434,9 +456,13 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
book_metadata.size = length book_metadata.size = length
infile.seek(0) infile.seek(0)
self._debug(lpath, length) self._debug(lpath, length)
self._call_client('SEND_BOOK', {'lpath': lpath, 'length': length, opcode, result = self._call_client('SEND_BOOK', {'lpath': lpath, 'length': length,
'metadata': book_metadata, 'thisBook': this_book, 'metadata': book_metadata, 'thisBook': this_book,
'totalBooks': total_books}, print_debug_info=False) 'totalBooks': total_books,
'willStreamBooks': self.client_can_stream_books},
print_debug_info=False,
wait_for_response=(not self.client_can_stream_books))
self._set_known_metadata(book_metadata) self._set_known_metadata(book_metadata)
pos = 0 pos = 0
failed = False failed = False
@ -449,9 +475,10 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
b = b64encode(b) b = b64encode(b)
opcode, result = self._call_client('BOOK_DATA', opcode, result = self._call_client('BOOK_DATA',
{'lpath': lpath, 'position': pos, 'data': b}, {'lpath': lpath, 'position': pos, 'data': b},
print_debug_info=False) print_debug_info=False,
wait_for_response=(not self.client_can_stream_books))
pos += blen pos += blen
if opcode != 'OK': if not self.client_can_stream_books and opcode != 'OK':
self._debug('protocol error', opcode) self._debug('protocol error', opcode)
failed = True failed = True
break break
@ -619,6 +646,8 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self._close_device_socket() self._close_device_socket()
return False return False
self._debug('CC version #:', result.get('ccVersionNumber', 'unknown')) self._debug('CC version #:', result.get('ccVersionNumber', 'unknown'))
self.client_can_stream_books = result.get('canStreamBooks', False)
self._debug('CC can stream', self.client_can_stream_books);
self.max_book_packet_len = result.get('maxBookContentPacketLen', self.max_book_packet_len = result.get('maxBookContentPacketLen',
self.BASE_PACKET_LEN) self.BASE_PACKET_LEN)
exts = result.get('acceptedExtensions', None) exts = result.get('acceptedExtensions', None)
@ -725,11 +754,15 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self._debug(oncard) self._debug(oncard)
if oncard is not None: if oncard is not None:
return CollectionsBookList(None, None, None) return CollectionsBookList(None, None, None)
opcode, result = self._call_client('GET_BOOK_COUNT', {}) opcode, result = self._call_client('GET_BOOK_COUNT', {'canStream':True})
bl = CollectionsBookList(None, self.PREFIX, self.settings) bl = CollectionsBookList(None, self.PREFIX, self.settings)
if opcode == 'OK': if opcode == 'OK':
count = result['count'] count = result['count']
will_stream = 'willStream' in result;
for i in range(0, count): for i in range(0, count):
if will_stream:
opcode, result = self._receive_from_client(print_debug_info=False)
else:
opcode, result = self._call_client('GET_BOOK_METADATA', {'index': i}, opcode, result = self._call_client('GET_BOOK_METADATA', {'index': i},
print_debug_info=False) print_debug_info=False)
if opcode == 'OK': if opcode == 'OK':
@ -764,7 +797,6 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
for i, book in enumerate(booklists[0]): for i, book in enumerate(booklists[0]):
if not self._metadata_already_on_device(book): if not self._metadata_already_on_device(book):
self._set_known_metadata(book) self._set_known_metadata(book)
self._debug('syncing book', book.lpath)
opcode, result = self._call_client('SEND_BOOK_METADATA', opcode, result = self._call_client('SEND_BOOK_METADATA',
{'index': i, 'data': book}, {'index': i, 'data': book},
print_debug_info=False) print_debug_info=False)
@ -904,6 +936,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self.max_book_packet_len = 0 self.max_book_packet_len = 0
self.noop_counter = 0 self.noop_counter = 0
self.connection_attempts = {} self.connection_attempts = {}
self.client_can_stream_books = False
try: try:
self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except: except: