Skip to content

Commit 77dabc1

Browse files
bmwillgitster
authored andcommitted
pkt-line: allow peeking a packet line without consuming it
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 2153d47 commit 77dabc1

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

pkt-line.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,53 @@ ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out)
400400
}
401401
return sb_out->len - orig_len;
402402
}
403+
404+
/* Packet Reader Functions */
405+
void packet_reader_init(struct packet_reader *reader, int fd,
406+
char *src_buffer, size_t src_len,
407+
int options)
408+
{
409+
memset(reader, 0, sizeof(*reader));
410+
411+
reader->fd = fd;
412+
reader->src_buffer = src_buffer;
413+
reader->src_len = src_len;
414+
reader->buffer = packet_buffer;
415+
reader->buffer_size = sizeof(packet_buffer);
416+
reader->options = options;
417+
}
418+
419+
enum packet_read_status packet_reader_read(struct packet_reader *reader)
420+
{
421+
if (reader->line_peeked) {
422+
reader->line_peeked = 0;
423+
return reader->status;
424+
}
425+
426+
reader->status = packet_read_with_status(reader->fd,
427+
&reader->src_buffer,
428+
&reader->src_len,
429+
reader->buffer,
430+
reader->buffer_size,
431+
&reader->pktlen,
432+
reader->options);
433+
434+
if (reader->status == PACKET_READ_NORMAL)
435+
reader->line = reader->buffer;
436+
else
437+
reader->line = NULL;
438+
439+
return reader->status;
440+
}
441+
442+
enum packet_read_status packet_reader_peek(struct packet_reader *reader)
443+
{
444+
/* Only allow peeking a single line */
445+
if (reader->line_peeked)
446+
return reader->status;
447+
448+
/* Peek a line by reading it and setting peeked flag */
449+
packet_reader_read(reader);
450+
reader->line_peeked = 1;
451+
return reader->status;
452+
}

pkt-line.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,64 @@ char *packet_read_line_buf(char **src_buf, size_t *src_len, int *size);
112112
*/
113113
ssize_t read_packetized_to_strbuf(int fd_in, struct strbuf *sb_out);
114114

115+
struct packet_reader {
116+
/* source file descriptor */
117+
int fd;
118+
119+
/* source buffer and its size */
120+
char *src_buffer;
121+
size_t src_len;
122+
123+
/* buffer that pkt-lines are read into and its size */
124+
char *buffer;
125+
unsigned buffer_size;
126+
127+
/* options to be used during reads */
128+
int options;
129+
130+
/* status of the last read */
131+
enum packet_read_status status;
132+
133+
/* length of data read during the last read */
134+
int pktlen;
135+
136+
/* the last line read */
137+
const char *line;
138+
139+
/* indicates if a line has been peeked */
140+
int line_peeked;
141+
};
142+
143+
/*
144+
* Initialize a 'struct packet_reader' object which is an
145+
* abstraction around the 'packet_read_with_status()' function.
146+
*/
147+
extern void packet_reader_init(struct packet_reader *reader, int fd,
148+
char *src_buffer, size_t src_len,
149+
int options);
150+
151+
/*
152+
* Perform a packet read and return the status of the read.
153+
* The values of 'pktlen' and 'line' are updated based on the status of the
154+
* read as follows:
155+
*
156+
* PACKET_READ_ERROR: 'pktlen' is set to '-1' and 'line' is set to NULL
157+
* PACKET_READ_NORMAL: 'pktlen' is set to the number of bytes read
158+
* 'line' is set to point at the read line
159+
* PACKET_READ_FLUSH: 'pktlen' is set to '0' and 'line' is set to NULL
160+
*/
161+
extern enum packet_read_status packet_reader_read(struct packet_reader *reader);
162+
163+
/*
164+
* Peek the next packet line without consuming it and return the status.
165+
* The next call to 'packet_reader_read()' will perform a read of the same line
166+
* that was peeked, consuming the line.
167+
*
168+
* Peeking multiple times without calling 'packet_reader_read()' will return
169+
* the same result.
170+
*/
171+
extern enum packet_read_status packet_reader_peek(struct packet_reader *reader);
172+
115173
#define DEFAULT_PACKET_MAX 1000
116174
#define LARGE_PACKET_MAX 65520
117175
#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - 4)

0 commit comments

Comments
 (0)