//authority = [ userinfo "@" ] host [ ":" port ] TextCursor parse_authority(TextCursor cursor) { try { TextCursor cursor_copy(parse_userinfo(cursor)); if(get_char(cursor_copy) != '@') throw ParseError(); cursor = cursor_copy; } catch(ParseError) { } cursor = parse_host(cursor); try { TextCursor cursor_copy2(cursor); if(get_char(cursor_copy2) != ':') throw ParseError(); cursor = parse_port(cursor_copy2); } catch(ParseError) { } return cursor; }
enum proto_parse_status cursor_read_fixed_string(struct cursor *cursor, char **out_str, size_t str_len) { SLOG(LOG_DEBUG, "Reading string of size %zu", str_len); if (cursor->cap_len < str_len) return PROTO_PARSE_ERR; if (!out_str) { cursor_drop(cursor, str_len); return PROTO_OK; } char *str = tempstr(); unsigned copied_len = MIN(str_len, TEMPSTR_SIZE - 1); cursor_copy(str, cursor, copied_len); str[copied_len] = '\0'; if (copied_len < str_len) { cursor_drop(cursor, str_len - copied_len); } if(out_str) *out_str = str; return PROTO_OK; }
/* Read a string splitted in chunk prefixed by 1 byte size * Chunk have a maximum size of 0x40 bytes * If there are more than one chunk, a 0x00 end it * * a multi chunked string * * Size String--------- Size String End * 0x40 0x41 0x42 0x.. 0x01 0x49 0x00 * * a single chunked string * * Size String--------- * 0x20 0x41 0x42 0x.. * * The global size might be unknown, so we try to guess it. We will have a parse problem * for string of size 0x40 */ static enum proto_parse_status cursor_read_chunked_string(struct cursor *cursor, char **out_str, size_t max_chunk) { char *str = tempstr(); unsigned pos = 0; while (pos < TEMPSTR_SIZE) { CHECK(1); unsigned str_len = cursor_read_u8(cursor); SLOG(LOG_DEBUG, "Chunk of size of %u", str_len); CHECK(str_len); size_t copied_len = MIN(TEMPSTR_SIZE - (pos + str_len + 1), str_len); cursor_copy(str + pos, cursor, copied_len); pos += str_len; if (str_len < max_chunk) break; } // There seems to be an null terminator when string length is > 0x40 // However, it can be a flag after the string. Ignore it for now. if (out_str) *out_str = str; str[MIN(pos, TEMPSTR_SIZE)] = 0; SLOG(LOG_DEBUG, "Chunk parsed of size %u", pos); return PROTO_OK; }