git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v6 02/35] pkt-line: allow peeking a packet line without consuming it

From
BWBrandon Williams <bmwill@google.com>
Date
Mar 15, 2018, 17:31 UTC
Message-ID
<20180315173142.176023-3-bmwill@google.com>
In-Reply-To
<20180315173142.176023-1-bmwill@google.com>

Sometimes it is advantageous to be able to peek the next packet line without consuming it (e.g. to be able to determine the protocol version a server is speaking). In order to do that introduce 'struct packet_reader' which is an abstraction around the normal packet reading logic. This enables a caller to be able to peek a single line at a time using 'packet_reader_peek()' and having a caller consume a line by calling 'packet_reader_read()'.

Signed-off-by: Brandon Williams <bmwill@google.com>
---
 pkt-line.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 pkt-line.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
diff --git a/pkt-line.c b/pkt-line.c
index db2fb29ac3..1881dc8813 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -400,3 +400,53 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
 	}
 	return sb_out->len - orig_len;
 }
+
+/* Packet Reader Functions */
+void packet_reader_init(struct packet_reader *reader, int fd,
+			char *src_buffer, size_t src_len,
+			int options)
+{
+	memset(reader, 0, sizeof(*reader));
+
+	reader->fd = fd;
+	reader->src_buffer = src_buffer;
+	reader->src_len = src_len;
+	reader->buffer = packet_buffer;
+	reader->buffer_size = sizeof(packet_buffer);
+	reader->options = options;
+}
+
+enum packet_read_status packet_reader_read(struct packet_reader *reader)
+{
+	if (reader->line_peeked) {
+		reader->line_peeked = 0;
+		return reader->status;
+	}
+
+	reader->status = packet_read_with_status(reader->fd,
+						 &reader->src_buffer,
+						 &reader->src_len,
+						 reader->buffer,
+						 reader->buffer_size,
+						 &reader->pktlen,
+						 reader->options);
+
+	if (reader->status == PACKET_READ_NORMAL)
+		reader->line = reader->buffer;
+	else
+		reader->line = NULL;
+
+	return reader->status;
+}
+
+enum packet_read_status packet_reader_peek(struct packet_reader *reader)
+{
+	/* Only allow peeking a single line */
+	if (reader->line_peeked)
+		return reader->status;
+
+	/* Peek a line by reading it and setting peeked flag */
+	packet_reader_read(reader);
+	reader->line_peeked = 1;
+	return reader->status;
+}
diff --git a/pkt-line.h b/pkt-line.h
index 099b26b95f..11b04f026f 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -112,6 +112,64 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size);
  */
 ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
 
+struct packet_reader {
+	/* source file descriptor */
+	int fd;
+
+	/* source buffer and its size */
+	char *src_buffer;
+	size_t src_len;
+
+	/* buffer that pkt-lines are read into and its size */
+	char *buffer;
+	unsigned buffer_size;
+
+	/* options to be used during reads */
+	int options;
+
+	/* status of the last read */
+	enum packet_read_status status;
+
+	/* length of data read during the last read */
+	int pktlen;
+
+	/* the last line read */
+	const char *line;
+
+	/* indicates if a line has been peeked */
+	int line_peeked;
+};
+
+/*
+ * Initialize a 'struct packet_reader' object which is an
+ * abstraction around the 'packet_read_with_status()' function.
+ */
+extern void packet_reader_init(struct packet_reader *reader, int fd,
+			       char *src_buffer, size_t src_len,
+			       int options);
+
+/*
+ * Perform a packet read and return the status of the read.
+ * The values of 'pktlen' and 'line' are updated based on the status of the
+ * read as follows:
+ *
+ * PACKET_READ_ERROR: 'pktlen' is set to '-1' and 'line' is set to NULL
+ * PACKET_READ_NORMAL: 'pktlen' is set to the number of bytes read
+ *		       'line' is set to point at the read line
+ * PACKET_READ_FLUSH: 'pktlen' is set to '0' and 'line' is set to NULL
+ */
+extern enum packet_read_status packet_reader_read(struct packet_reader *reader);
+
+/*
+ * Peek the next packet line without consuming it and return the status.
+ * The next call to 'packet_reader_read()' will perform a read of the same line
+ * that was peeked, consuming the line.
+ *
+ * Peeking multiple times without calling 'packet_reader_read()' will return
+ * the same result.
+ */
+extern enum packet_read_status packet_reader_peek(struct packet_reader *reader);
+
 #define DEFAULT_PACKET_MAX 1000
 #define LARGE_PACKET_MAX 65520
 #define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4)
-- 
2.16.2.804.g6dcf76e118-goog
Previous: Brandon WilliamsNext: Brandon Williams
Message 44 of 85 in “protocol version 2”
  1. 00/35 protocol version 2Brandon Williams, Mar 14, 2018
  2. 01/35 pkt-line: introduce packet_read_with_statusBrandon Williams, Mar 14, 2018
  3. Junio C HamanoMar 14, 2018
  4. Brandon WilliamsMar 15, 2018
  5. Junio C HamanoMar 15, 2018
  6. 02/35 pkt-line: allow peeking a packet line without consuming itBrandon Williams, Mar 14, 2018
  7. 03/35 pkt-line: add delim packet supportBrandon Williams, Mar 14, 2018
  8. 04/35 upload-pack: convert to a builtinBrandon Williams, Mar 14, 2018
  9. 07/35 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Mar 14, 2018
  10. 10/35 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Mar 14, 2018
  11. 11/35 test-pkt-line: introduce a packet-line test helperBrandon Williams, Mar 14, 2018
  12. 12/35 serve: introduce git-serveBrandon Williams, Mar 14, 2018
  13. Junio C HamanoMar 14, 2018
  14. Brandon WilliamsMar 15, 2018
  15. 14/35 connect: request remote refs using v2Brandon Williams, Mar 14, 2018
  16. 13/35 ls-refs: introduce ls-refs server commandBrandon Williams, Mar 14, 2018
  17. 18/35 fetch: pass ref prefixes when fetchingBrandon Williams, Mar 14, 2018
  18. 17/35 ls-remote: pass ref prefixes when requesting a remote's refsBrandon Williams, Mar 14, 2018
  19. 19/35 push: pass ref prefixes when pushingBrandon Williams, Mar 14, 2018
  20. 21/35 fetch-pack: perform a fetch using v2Brandon Williams, Mar 14, 2018
  21. 22/35 fetch-pack: support shallow requestsBrandon Williams, Mar 14, 2018
  22. 26/35 transport-helper: refactor process_connect_serviceBrandon Williams, Mar 14, 2018
  23. 27/35 transport-helper: introduce stateless-connectBrandon Williams, Mar 14, 2018
  24. 28/35 pkt-line: add packet_buf_write_len functionBrandon Williams, Mar 14, 2018
  25. 31/35 http: allow providing extra headers for http requestsBrandon Williams, Mar 14, 2018
  26. 29/35 remote-curl: create copy of the service nameBrandon Williams, Mar 14, 2018
  27. 32/35 http: don't always add Git-Protocol headerBrandon Williams, Mar 14, 2018
  28. 33/35 http: eliminate "# service" line when using protocol v2Brandon Williams, Mar 14, 2018
  29. 35/35 remote-curl: don't request v2 when pushingBrandon Williams, Mar 14, 2018
  30. 34/35 remote-curl: implement stateless-connect commandBrandon Williams, Mar 14, 2018
  31. 23/35 connect: refactor git_connect to only get the protocol version onceBrandon Williams, Mar 14, 2018
  32. 25/35 transport-helper: remove name parameterBrandon Williams, Mar 14, 2018
  33. 30/35 remote-curl: store the protocol version the server responded withBrandon Williams, Mar 14, 2018
  34. 20/35 upload-pack: introduce fetch server commandBrandon Williams, Mar 14, 2018
  35. 24/35 connect: don't request v2 when pushingBrandon Williams, Mar 14, 2018
  36. 15/35 transport: convert get_refs_list to take a list of ref prefixesBrandon Williams, Mar 14, 2018
  37. 16/35 transport: convert transport_get_remote_refs to take a list of ref prefixesBrandon Williams, Mar 14, 2018
  38. 08/35 connect: discover protocol version outside of get_remote_headsBrandon Williams, Mar 14, 2018
  39. 09/35 transport: store protocol versionBrandon Williams, Mar 14, 2018
  40. 05/35 upload-pack: factor out processing linesBrandon Williams, Mar 14, 2018
  41. 06/35 transport: use get_refs_via_connect to get refsBrandon Williams, Mar 14, 2018
  42. 00/35 protocol version 2Brandon Williams, Mar 15, 2018
  43. 01/35 pkt-line: introduce packet_read_with_statusBrandon Williams, Mar 15, 2018
  44. 02/35 pkt-line: allow peeking a packet line without consuming itBrandon Williams, Mar 15, 2018
  45. 03/35 pkt-line: add delim packet supportBrandon Williams, Mar 15, 2018
  46. 06/35 transport: use get_refs_via_connect to get refsBrandon Williams, Mar 15, 2018
  47. 07/35 connect: convert get_remote_heads to use struct packet_readerBrandon Williams, Mar 15, 2018
  48. Duy NguyenMar 27, 2018
  49. Jeff KingMar 27, 2018
  50. Duy NguyenMar 27, 2018
  51. Duy NguyenMar 27, 2018
  52. Brandon WilliamsMar 27, 2018
  53. 08/35 connect: discover protocol version outside of get_remote_headsBrandon Williams, Mar 15, 2018
  54. 09/35 transport: store protocol versionBrandon Williams, Mar 15, 2018
  55. 10/35 protocol: introduce enum protocol_version value protocol_v2Brandon Williams, Mar 15, 2018
  56. 11/35 test-pkt-line: introduce a packet-line test helperBrandon Williams, Mar 15, 2018
  57. 12/35 serve: introduce git-serveBrandon Williams, Mar 15, 2018
  58. 13/35 ls-refs: introduce ls-refs server commandBrandon Williams, Mar 15, 2018
  59. 16/35 transport: convert transport_get_remote_refs to take a list of ref prefixesBrandon Williams, Mar 15, 2018
  60. 17/35 ls-remote: pass ref prefixes when requesting a remote's refsBrandon Williams, Mar 15, 2018
  61. 18/35 fetch: pass ref prefixes when fetchingBrandon Williams, Mar 15, 2018
  62. 20/35 upload-pack: introduce fetch server commandBrandon Williams, Mar 15, 2018
  63. 19/35 push: pass ref prefixes when pushingBrandon Williams, Mar 15, 2018
  64. 22/35 fetch-pack: support shallow requestsBrandon Williams, Mar 15, 2018
  65. 27/35 transport-helper: introduce stateless-connectBrandon Williams, Mar 15, 2018
  66. 26/35 transport-helper: refactor process_connect_serviceBrandon Williams, Mar 15, 2018
  67. 29/35 remote-curl: create copy of the service nameBrandon Williams, Mar 15, 2018
  68. 30/35 remote-curl: store the protocol version the server responded withBrandon Williams, Mar 15, 2018
  69. 33/35 http: eliminate "# service" line when using protocol v2Brandon Williams, Mar 15, 2018
  70. 34/35 remote-curl: implement stateless-connect commandBrandon Williams, Mar 15, 2018
  71. 35/35 remote-curl: don't request v2 when pushingBrandon Williams, Mar 15, 2018
  72. 31/35 http: allow providing extra headers for http requestsBrandon Williams, Mar 15, 2018
  73. 32/35 http: don't always add Git-Protocol headerBrandon Williams, Mar 15, 2018
  74. 28/35 pkt-line: add packet_buf_write_len functionBrandon Williams, Mar 15, 2018
  75. 23/35 connect: refactor git_connect to only get the protocol version onceBrandon Williams, Mar 15, 2018
  76. 25/35 transport-helper: remove name parameterBrandon Williams, Mar 15, 2018
  77. 24/35 connect: don't request v2 when pushingBrandon Williams, Mar 15, 2018
  78. 21/35 fetch-pack: perform a fetch using v2Brandon Williams, Mar 15, 2018
  79. 14/35 connect: request remote refs using v2Brandon Williams, Mar 15, 2018
  80. 15/35 transport: convert get_refs_list to take a list of ref prefixesBrandon Williams, Mar 15, 2018
  81. 04/35 upload-pack: convert to a builtinBrandon Williams, Mar 15, 2018
  82. 05/35 upload-pack: factor out processing linesBrandon Williams, Mar 15, 2018
  83. {fetch,upload}-pack: clearly mark unreachable v2 codeÆvar Arnfjörð Bjarmason, Mar 30, 2018
  84. Brandon WilliamsMar 30, 2018
  85. Stefan BellerMar 30, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.