def _parseHeaders(self, data): "Given a control frame data block, return a list of (name, value) tuples." # TODO: separate null-delimited into separate instances data = decompress(data, dictionary=dictionary) # FIXME: catch errors cursor = 2 (num_hdrs,) = struct.unpack("!h", data[:cursor]) # FIXME: catch errors hdrs = [] while cursor < len(data): try: (name_len,) = struct.unpack("!h", data[cursor:cursor+2]) # FIXME: catch errors cursor += 2 name = data[cursor:cursor+name_len] # FIXME: catch errors cursor += name_len except IndexError: raise except struct.error: raise try: (val_len,) = struct.unpack("!h", data[cursor:cursor+2]) # FIXME: catch errors cursor += 2 value = data[cursor:cursor+val_len] # FIXME: catch errors cursor += val_len except IndexError: raise except struct.error: print len(data), cursor, data # FIXME raise self.addRawHeader(name, value)
def _parse_header_chunk(self, compressed_data, version): #chunk = self.inflater.decompress(compressed_data) chunk = decompress(compressed_data, dictionary=HEADER_ZLIB_DICT_2) #print 'decompressed_headers', repr(chunk) length_size = 2 if version == 2 else 4 length_fmt = '>H' if length_size == 2 else '>L' headers = {} #first two bytes: number of pairs #num_values = int.from_bytes(chunk[0:length_size], 'big') num_values = struct.unpack(length_fmt, chunk[0:length_size])[0] #after that... cursor = length_size for _ in range(num_values): #two/four bytes: length of name #name_length = int.from_bytes(chunk[cursor:cursor+length_size], 'big') name_length = struct.unpack(length_fmt, chunk[cursor:cursor+length_size])[0] cursor += length_size #next name_length bytes: name name = chunk[cursor:cursor+name_length].decode('UTF-8') cursor += name_length #two/four bytes: length of value #value_length = int.from_bytes(chunk[cursor:cursor+length_size], 'big') value_length = struct.unpack(length_fmt, chunk[cursor:cursor+length_size])[0] cursor += length_size #next value_length bytes: value value = chunk[cursor:cursor+value_length].decode('UTF-8') cursor += value_length if name_length == 0 or value_length == 0: raise SpdyProtocolError("zero-length name or value in n/v block") if name in headers: raise SpdyProtocolError("duplicate name in n/v block") headers[name] = value return headers