git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH] pkt-line: extract out PACKET_HEADER_SIZE
@ 2020-06-13 13:43 Denton Liu
  2020-06-13 14:23 ` Đoàn Trần Công Danh
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
  0 siblings, 2 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-13 13:43 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King

In pkt-line and remote-curl, we have many instances of magic `4`
literals floating around which represent the number of bytes in the
packet line length header. Instead of using these magic numbers, replace
them with constant expressions.

In most cases, replace the `4` with `PACKET_HEADER_SIZE`. However, in
the case where there's a `char array[PACKET_HEADER_SIZE]`  and we are
reading data into it, replace the `4` with a `sizeof(array)` so that
it's clear that the logic has something to do with that array.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 pkt-line.c    | 50 +++++++++++++++++++++++++-------------------------
 pkt-line.h    |  6 ++++--
 remote-curl.c | 30 +++++++++++++++---------------
 3 files changed, 44 insertions(+), 42 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index 8f9bc68ee2..245a56712f 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -87,43 +87,43 @@ static void packet_trace(const char *buf, unsigned int len, int write)
  */
 void packet_flush(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
+	packet_trace("0000", PACKET_HEADER_SIZE, 1);
+	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
 		die_errno(_("unable to write flush packet"));
 }
 
 void packet_delim(int fd)
 {
-	packet_trace("0001", 4, 1);
-	if (write_in_full(fd, "0001", 4) < 0)
+	packet_trace("0001", PACKET_HEADER_SIZE, 1);
+	if (write_in_full(fd, "0001", PACKET_HEADER_SIZE) < 0)
 		die_errno(_("unable to write delim packet"));
 }
 
 void packet_response_end(int fd)
 {
-	packet_trace("0002", 4, 1);
-	if (write_in_full(fd, "0002", 4) < 0)
+	packet_trace("0002", PACKET_HEADER_SIZE, 1);
+	if (write_in_full(fd, "0002", PACKET_HEADER_SIZE) < 0)
 		die_errno(_("unable to write stateless separator packet"));
 }
 
 int packet_flush_gently(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
+	packet_trace("0000", PACKET_HEADER_SIZE, 1);
+	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
 		return error(_("flush packet write failed"));
 	return 0;
 }
 
 void packet_buf_flush(struct strbuf *buf)
 {
-	packet_trace("0000", 4, 1);
-	strbuf_add(buf, "0000", 4);
+	packet_trace("0000", PACKET_HEADER_SIZE, 1);
+	strbuf_add(buf, "0000", PACKET_HEADER_SIZE);
 }
 
 void packet_buf_delim(struct strbuf *buf)
 {
-	packet_trace("0001", 4, 1);
-	strbuf_add(buf, "0001", 4);
+	packet_trace("0001", PACKET_HEADER_SIZE, 1);
+	strbuf_add(buf, "0001", PACKET_HEADER_SIZE);
 }
 
 void set_packet_header(char *buf, int size)
@@ -153,7 +153,7 @@ static void format_packet(struct strbuf *out, const char *prefix,
 		die(_("protocol error: impossibly long line"));
 
 	set_packet_header(&out->buf[orig_len], n);
-	packet_trace(out->buf + orig_len + 4, n - 4, 1);
+	packet_trace(out->buf + orig_len + PACKET_HEADER_SIZE, n - PACKET_HEADER_SIZE, 1);
 }
 
 static int packet_write_fmt_1(int fd, int gently, const char *prefix,
@@ -199,13 +199,13 @@ static int packet_write_gently(const int fd_out, const char *buf, size_t size)
 	static char packet_write_buffer[LARGE_PACKET_MAX];
 	size_t packet_size;
 
-	if (size > sizeof(packet_write_buffer) - 4)
+	if (size > sizeof(packet_write_buffer) - PACKET_HEADER_SIZE)
 		return error(_("packet write failed - data exceeds max packet size"));
 
 	packet_trace(buf, size, 1);
-	packet_size = size + 4;
+	packet_size = size + PACKET_HEADER_SIZE;
 	set_packet_header(packet_write_buffer, packet_size);
-	memcpy(packet_write_buffer + 4, buf, size);
+	memcpy(packet_write_buffer + PACKET_HEADER_SIZE, buf, size);
 	if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
 		return error(_("packet write failed"));
 	return 0;
@@ -313,7 +313,7 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
 	return ret;
 }
 
-int packet_length(const char lenbuf_hex[4])
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE])
 {
 	int val = hex2chr(lenbuf_hex);
 	return (val < 0) ? val : (val << 8) | hex2chr(lenbuf_hex + 2);
@@ -325,9 +325,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 						int options)
 {
 	int len;
-	char linelen[4];
+	char linelen[PACKET_HEADER_SIZE];
 
-	if (get_packet_data(fd, src_buffer, src_len, linelen, 4, options) < 0) {
+	if (get_packet_data(fd, src_buffer, src_len, linelen, sizeof(linelen), options) < 0) {
 		*pktlen = -1;
 		return PACKET_READ_EOF;
 	}
@@ -337,22 +337,22 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 	if (len < 0) {
 		die(_("protocol error: bad line length character: %.4s"), linelen);
 	} else if (!len) {
-		packet_trace("0000", 4, 0);
+		packet_trace("0000", PACKET_HEADER_SIZE, 0);
 		*pktlen = 0;
 		return PACKET_READ_FLUSH;
 	} else if (len == 1) {
-		packet_trace("0001", 4, 0);
+		packet_trace("0001", PACKET_HEADER_SIZE, 0);
 		*pktlen = 0;
 		return PACKET_READ_DELIM;
 	} else if (len == 2) {
-		packet_trace("0002", 4, 0);
+		packet_trace("0002", PACKET_HEADER_SIZE, 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
-	} else if (len < 4) {
+	} else if (len < PACKET_HEADER_SIZE) {
 		die(_("protocol error: bad line length %d"), len);
 	}
 
-	len -= 4;
+	len -= sizeof(linelen);
 	if ((unsigned)len >= size)
 		die(_("protocol error: bad line length %d"), len);
 
@@ -370,7 +370,7 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 
 	if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
 	    starts_with(buffer, "ERR "))
-		die(_("remote error: %s"), buffer + 4);
+		die(_("remote error: %s"), buffer + PACKET_HEADER_SIZE);
 
 	*pktlen = len;
 	return PACKET_READ_NORMAL;
diff --git a/pkt-line.h b/pkt-line.h
index 5b373fe4cd..d6121b8044 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -5,6 +5,8 @@
 #include "strbuf.h"
 #include "sideband.h"
 
+#define PACKET_HEADER_SIZE 4
+
 /*
  * Write a packetized stream, where each line is preceded by
  * its length (including the header) as a 4-byte hex number.
@@ -82,7 +84,7 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, char
  * If lenbuf_hex contains non-hex characters, return -1. Otherwise, return the
  * numeric value of the length header.
  */
-int packet_length(const char lenbuf_hex[4]);
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE]);
 
 /*
  * Read a packetized line into a buffer like the 'packet_read()' function but
@@ -211,7 +213,7 @@ 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)
+#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - PACKET_HEADER_SIZE)
 extern char packet_buffer[LARGE_PACKET_MAX];
 
 struct packet_writer {
diff --git a/remote-curl.c b/remote-curl.c
index 75532a8bae..bac295c5bc 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -536,7 +536,7 @@ struct rpc_state {
 	unsigned initial_buffer : 1;
 
 	/*
-	 * Whenever a pkt-line is read into buf, append the 4 characters
+	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE characters
 	 * denoting its length before appending the payload.
 	 */
 	unsigned write_line_lengths : 1;
@@ -556,7 +556,7 @@ struct rpc_state {
  * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
  * enough space, 0 otherwise.
  *
- * If rpc->write_line_lengths is true, appends the line length as a 4-byte
+ * If rpc->write_line_lengths is true, appends the line length as a PACKET_HEADER_SIZE-byte
  * hexadecimal string before appending the result described above.
  *
  * Writes the total number of bytes appended into appended.
@@ -569,8 +569,8 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	int pktlen_raw;
 
 	if (rpc->write_line_lengths) {
-		left = rpc->alloc - rpc->len - 4;
-		buf = rpc->buf + rpc->len + 4;
+		left = rpc->alloc - rpc->len - PACKET_HEADER_SIZE;
+		buf = rpc->buf + rpc->len + PACKET_HEADER_SIZE;
 	} else {
 		left = rpc->alloc - rpc->len;
 		buf = rpc->buf + rpc->len;
@@ -582,7 +582,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	*status = packet_read_with_status(rpc->out, NULL, NULL, buf,
 			left, &pktlen_raw, options);
 	if (*status != PACKET_READ_EOF) {
-		*appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
+		*appended = pktlen_raw + (rpc->write_line_lengths ? PACKET_HEADER_SIZE : 0);
 		rpc->len += *appended;
 	}
 
@@ -593,13 +593,13 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 				die(_("shouldn't have EOF when not gentle on EOF"));
 			break;
 		case PACKET_READ_NORMAL:
-			set_packet_header(buf - 4, *appended);
+			set_packet_header(buf - PACKET_HEADER_SIZE, *appended);
 			break;
 		case PACKET_READ_DELIM:
-			memcpy(buf - 4, "0001", 4);
+			memcpy(buf - PACKET_HEADER_SIZE, "0001", PACKET_HEADER_SIZE);
 			break;
 		case PACKET_READ_FLUSH:
-			memcpy(buf - 4, "0000", 4);
+			memcpy(buf - PACKET_HEADER_SIZE, "0000", PACKET_HEADER_SIZE);
 			break;
 		case PACKET_READ_RESPONSE_END:
 			die(_("remote server sent stateless separator"));
@@ -682,7 +682,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
 #endif
 
 struct check_pktline_state {
-	char len_buf[4];
+	char len_buf[PACKET_HEADER_SIZE];
 	int len_filled;
 	int remaining;
 };
@@ -691,7 +691,7 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 {
 	while (size) {
 		if (!state->remaining) {
-			int digits_remaining = 4 - state->len_filled;
+			int digits_remaining = sizeof(state->len_buf) - state->len_filled;
 			if (digits_remaining > size)
 				digits_remaining = size;
 			memcpy(&state->len_buf[state->len_filled], ptr, digits_remaining);
@@ -699,16 +699,16 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 			ptr += digits_remaining;
 			size -= digits_remaining;
 
-			if (state->len_filled == 4) {
+			if (state->len_filled == sizeof(state->len_buf)) {
 				state->remaining = packet_length(state->len_buf);
 				if (state->remaining < 0) {
 					die(_("remote-curl: bad line length character: %.4s"), state->len_buf);
 				} else if (state->remaining == 2) {
 					die(_("remote-curl: unexpected response end packet"));
-				} else if (state->remaining < 4) {
+				} else if (state->remaining < sizeof(state->len_buf)) {
 					state->remaining = 0;
 				} else {
-					state->remaining -= 4;
+					state->remaining -= sizeof(state->len_buf);
 				}
 				state->len_filled = 0;
 			}
@@ -804,7 +804,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
 	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
-	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, PACKET_HEADER_SIZE);
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
@@ -1469,7 +1469,7 @@ int cmd_main(int argc, const char **argv)
 			parse_fetch(&buf);
 
 		} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
-			int for_push = !!strstr(buf.buf + 4, "for-push");
+			int for_push = !!strstr(buf.buf + PACKET_HEADER_SIZE, "for-push");
 			output_refs(get_refs(for_push));
 
 		} else if (starts_with(buf.buf, "push ")) {
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-13 13:43 [PATCH] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
@ 2020-06-13 14:23 ` Đoàn Trần Công Danh
  2020-06-13 14:39   ` Denton Liu
  2020-06-13 16:51   ` Junio C Hamano
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
  1 sibling, 2 replies; 22+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-13 14:23 UTC (permalink / raw)
  To: Denton Liu; +Cc: Git Mailing List, Jeff King

On 2020-06-13 09:43:22-0400, Denton Liu <liu.denton@gmail.com> wrote:
> In pkt-line and remote-curl, we have many instances of magic `4`
> literals floating around which represent the number of bytes in the
> packet line length header. Instead of using these magic numbers, replace
> them with constant expressions.
> 
> In most cases, replace the `4` with `PACKET_HEADER_SIZE`. However, in
> the case where there's a `char array[PACKET_HEADER_SIZE]`  and we are
> reading data into it, replace the `4` with a `sizeof(array)` so that
> it's clear that the logic has something to do with that array.
> 
> Signed-off-by: Denton Liu <liu.denton@gmail.com>
> ---
>  pkt-line.c    | 50 +++++++++++++++++++++++++-------------------------
>  pkt-line.h    |  6 ++++--
>  remote-curl.c | 30 +++++++++++++++---------------
>  3 files changed, 44 insertions(+), 42 deletions(-)
> 
> diff --git a/pkt-line.c b/pkt-line.c
> index 8f9bc68ee2..245a56712f 100644
> --- a/pkt-line.c
> +++ b/pkt-line.c
> @@ -87,43 +87,43 @@ static void packet_trace(const char *buf, unsigned int len, int write)
>   */
>  void packet_flush(int fd)
>  {
> -	packet_trace("0000", 4, 1);
> -	if (write_in_full(fd, "0000", 4) < 0)
> +	packet_trace("0000", PACKET_HEADER_SIZE, 1);
> +	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)

I think the magic number 4 is easier to follow than some macro
PACKET_HEADER_SIZE defined elsewhere. Because reader may judge that is
the size of "0000"

How about (this ugly code):

	packet_trace("0000", sizeof "0000" - 1, 1);
	if (write_in_full(fd, "0000", sizeof "0000" - 1) < 0)


>  		die_errno(_("unable to write flush packet"));
>  }
>  
>  void packet_delim(int fd)
>  {
> -	packet_trace("0001", 4, 1);
> -	if (write_in_full(fd, "0001", 4) < 0)
> +	packet_trace("0001", PACKET_HEADER_SIZE, 1);
> +	if (write_in_full(fd, "0001", PACKET_HEADER_SIZE) < 0)
>  		die_errno(_("unable to write delim packet"));
>  }
>  
>  void packet_response_end(int fd)
>  {
> -	packet_trace("0002", 4, 1);
> -	if (write_in_full(fd, "0002", 4) < 0)
> +	packet_trace("0002", PACKET_HEADER_SIZE, 1);
> +	if (write_in_full(fd, "0002", PACKET_HEADER_SIZE) < 0)
>  		die_errno(_("unable to write stateless separator packet"));
>  }
>  
>  int packet_flush_gently(int fd)
>  {
> -	packet_trace("0000", 4, 1);
> -	if (write_in_full(fd, "0000", 4) < 0)
> +	packet_trace("0000", PACKET_HEADER_SIZE, 1);
> +	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
>  		return error(_("flush packet write failed"));
>  	return 0;
>  }
>  
>  void packet_buf_flush(struct strbuf *buf)
>  {
> -	packet_trace("0000", 4, 1);
> -	strbuf_add(buf, "0000", 4);
> +	packet_trace("0000", PACKET_HEADER_SIZE, 1);
> +	strbuf_add(buf, "0000", PACKET_HEADER_SIZE);
>  }
>  
>  void packet_buf_delim(struct strbuf *buf)
>  {
> -	packet_trace("0001", 4, 1);
> -	strbuf_add(buf, "0001", 4);
> +	packet_trace("0001", PACKET_HEADER_SIZE, 1);
> +	strbuf_add(buf, "0001", PACKET_HEADER_SIZE);
>  }
>  
>  void set_packet_header(char *buf, int size)
> @@ -153,7 +153,7 @@ static void format_packet(struct strbuf *out, const char *prefix,
>  		die(_("protocol error: impossibly long line"));
>  
>  	set_packet_header(&out->buf[orig_len], n);
> -	packet_trace(out->buf + orig_len + 4, n - 4, 1);
> +	packet_trace(out->buf + orig_len + PACKET_HEADER_SIZE, n - PACKET_HEADER_SIZE, 1);
>  }
>  
>  static int packet_write_fmt_1(int fd, int gently, const char *prefix,
> @@ -199,13 +199,13 @@ static int packet_write_gently(const int fd_out, const char *buf, size_t size)
>  	static char packet_write_buffer[LARGE_PACKET_MAX];
>  	size_t packet_size;
>  
> -	if (size > sizeof(packet_write_buffer) - 4)
> +	if (size > sizeof(packet_write_buffer) - PACKET_HEADER_SIZE)
>  		return error(_("packet write failed - data exceeds max packet size"));
>  
>  	packet_trace(buf, size, 1);
> -	packet_size = size + 4;
> +	packet_size = size + PACKET_HEADER_SIZE;
>  	set_packet_header(packet_write_buffer, packet_size);
> -	memcpy(packet_write_buffer + 4, buf, size);
> +	memcpy(packet_write_buffer + PACKET_HEADER_SIZE, buf, size);
>  	if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
>  		return error(_("packet write failed"));
>  	return 0;
> @@ -313,7 +313,7 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
>  	return ret;
>  }
>  
> -int packet_length(const char lenbuf_hex[4])
> +int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE])
>  {
>  	int val = hex2chr(lenbuf_hex);
>  	return (val < 0) ? val : (val << 8) | hex2chr(lenbuf_hex + 2);
> @@ -325,9 +325,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
>  						int options)
>  {
>  	int len;
> -	char linelen[4];
> +	char linelen[PACKET_HEADER_SIZE];
>  
> -	if (get_packet_data(fd, src_buffer, src_len, linelen, 4, options) < 0) {
> +	if (get_packet_data(fd, src_buffer, src_len, linelen, sizeof(linelen), options) < 0) {
>  		*pktlen = -1;
>  		return PACKET_READ_EOF;
>  	}
> @@ -337,22 +337,22 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
>  	if (len < 0) {
>  		die(_("protocol error: bad line length character: %.4s"), linelen);
>  	} else if (!len) {
> -		packet_trace("0000", 4, 0);
> +		packet_trace("0000", PACKET_HEADER_SIZE, 0);
>  		*pktlen = 0;
>  		return PACKET_READ_FLUSH;
>  	} else if (len == 1) {
> -		packet_trace("0001", 4, 0);
> +		packet_trace("0001", PACKET_HEADER_SIZE, 0);
>  		*pktlen = 0;
>  		return PACKET_READ_DELIM;
>  	} else if (len == 2) {
> -		packet_trace("0002", 4, 0);
> +		packet_trace("0002", PACKET_HEADER_SIZE, 0);
>  		*pktlen = 0;
>  		return PACKET_READ_RESPONSE_END;
> -	} else if (len < 4) {
> +	} else if (len < PACKET_HEADER_SIZE) {
>  		die(_("protocol error: bad line length %d"), len);
>  	}
>  
> -	len -= 4;
> +	len -= sizeof(linelen);
>  	if ((unsigned)len >= size)
>  		die(_("protocol error: bad line length %d"), len);
>  
> @@ -370,7 +370,7 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
>  
>  	if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
>  	    starts_with(buffer, "ERR "))
> -		die(_("remote error: %s"), buffer + 4);
> +		die(_("remote error: %s"), buffer + PACKET_HEADER_SIZE);
>  
>  	*pktlen = len;
>  	return PACKET_READ_NORMAL;
> diff --git a/pkt-line.h b/pkt-line.h
> index 5b373fe4cd..d6121b8044 100644
> --- a/pkt-line.h
> +++ b/pkt-line.h
> @@ -5,6 +5,8 @@
>  #include "strbuf.h"
>  #include "sideband.h"
>  
> +#define PACKET_HEADER_SIZE 4
> +
>  /*
>   * Write a packetized stream, where each line is preceded by
>   * its length (including the header) as a 4-byte hex number.
> @@ -82,7 +84,7 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, char
>   * If lenbuf_hex contains non-hex characters, return -1. Otherwise, return the
>   * numeric value of the length header.
>   */
> -int packet_length(const char lenbuf_hex[4]);
> +int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE]);
>  
>  /*
>   * Read a packetized line into a buffer like the 'packet_read()' function but
> @@ -211,7 +213,7 @@ 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)
> +#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - PACKET_HEADER_SIZE)
>  extern char packet_buffer[LARGE_PACKET_MAX];
>  
>  struct packet_writer {
> diff --git a/remote-curl.c b/remote-curl.c
> index 75532a8bae..bac295c5bc 100644
> --- a/remote-curl.c
> +++ b/remote-curl.c
> @@ -536,7 +536,7 @@ struct rpc_state {
>  	unsigned initial_buffer : 1;
>  
>  	/*
> -	 * Whenever a pkt-line is read into buf, append the 4 characters
> +	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE characters
>  	 * denoting its length before appending the payload.
>  	 */
>  	unsigned write_line_lengths : 1;
> @@ -556,7 +556,7 @@ struct rpc_state {
>   * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
>   * enough space, 0 otherwise.
>   *
> - * If rpc->write_line_lengths is true, appends the line length as a 4-byte
> + * If rpc->write_line_lengths is true, appends the line length as a PACKET_HEADER_SIZE-byte
>   * hexadecimal string before appending the result described above.
>   *
>   * Writes the total number of bytes appended into appended.
> @@ -569,8 +569,8 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
>  	int pktlen_raw;
>  
>  	if (rpc->write_line_lengths) {
> -		left = rpc->alloc - rpc->len - 4;
> -		buf = rpc->buf + rpc->len + 4;
> +		left = rpc->alloc - rpc->len - PACKET_HEADER_SIZE;
> +		buf = rpc->buf + rpc->len + PACKET_HEADER_SIZE;
>  	} else {
>  		left = rpc->alloc - rpc->len;
>  		buf = rpc->buf + rpc->len;
> @@ -582,7 +582,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
>  	*status = packet_read_with_status(rpc->out, NULL, NULL, buf,
>  			left, &pktlen_raw, options);
>  	if (*status != PACKET_READ_EOF) {
> -		*appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
> +		*appended = pktlen_raw + (rpc->write_line_lengths ? PACKET_HEADER_SIZE : 0);
>  		rpc->len += *appended;
>  	}
>  
> @@ -593,13 +593,13 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
>  				die(_("shouldn't have EOF when not gentle on EOF"));
>  			break;
>  		case PACKET_READ_NORMAL:
> -			set_packet_header(buf - 4, *appended);
> +			set_packet_header(buf - PACKET_HEADER_SIZE, *appended);
>  			break;
>  		case PACKET_READ_DELIM:
> -			memcpy(buf - 4, "0001", 4);
> +			memcpy(buf - PACKET_HEADER_SIZE, "0001", PACKET_HEADER_SIZE);
>  			break;
>  		case PACKET_READ_FLUSH:
> -			memcpy(buf - 4, "0000", 4);
> +			memcpy(buf - PACKET_HEADER_SIZE, "0000", PACKET_HEADER_SIZE);
>  			break;
>  		case PACKET_READ_RESPONSE_END:
>  			die(_("remote server sent stateless separator"));
> @@ -682,7 +682,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
>  #endif
>  
>  struct check_pktline_state {
> -	char len_buf[4];
> +	char len_buf[PACKET_HEADER_SIZE];
>  	int len_filled;
>  	int remaining;
>  };
> @@ -691,7 +691,7 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
>  {
>  	while (size) {
>  		if (!state->remaining) {
> -			int digits_remaining = 4 - state->len_filled;
> +			int digits_remaining = sizeof(state->len_buf) - state->len_filled;
>  			if (digits_remaining > size)
>  				digits_remaining = size;
>  			memcpy(&state->len_buf[state->len_filled], ptr, digits_remaining);
> @@ -699,16 +699,16 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
>  			ptr += digits_remaining;
>  			size -= digits_remaining;
>  
> -			if (state->len_filled == 4) {
> +			if (state->len_filled == sizeof(state->len_buf)) {
>  				state->remaining = packet_length(state->len_buf);
>  				if (state->remaining < 0) {
>  					die(_("remote-curl: bad line length character: %.4s"), state->len_buf);
>  				} else if (state->remaining == 2) {
>  					die(_("remote-curl: unexpected response end packet"));
> -				} else if (state->remaining < 4) {
> +				} else if (state->remaining < sizeof(state->len_buf)) {
>  					state->remaining = 0;
>  				} else {
> -					state->remaining -= 4;
> +					state->remaining -= sizeof(state->len_buf);
>  				}
>  				state->len_filled = 0;
>  			}
> @@ -804,7 +804,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
>  	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
>  	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
>  	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
> -	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
> +	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, PACKET_HEADER_SIZE);
>  	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
>  	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
>  	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
> @@ -1469,7 +1469,7 @@ int cmd_main(int argc, const char **argv)
>  			parse_fetch(&buf);
>  
>  		} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
> -			int for_push = !!strstr(buf.buf + 4, "for-push");
> +			int for_push = !!strstr(buf.buf + PACKET_HEADER_SIZE, "for-push");
>  			output_refs(get_refs(for_push));
>  
>  		} else if (starts_with(buf.buf, "push ")) {
> -- 
> 2.27.0.132.g321788e831
> 

-- 
Danh

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-13 14:23 ` Đoàn Trần Công Danh
@ 2020-06-13 14:39   ` Denton Liu
  2020-06-13 16:51   ` Junio C Hamano
  1 sibling, 0 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-13 14:39 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: Git Mailing List, Jeff King, Chris Torek

On Sat, Jun 13, 2020 at 09:23:06PM +0700, Đoàn Trần Công Danh wrote:
> > diff --git a/pkt-line.c b/pkt-line.c
> > index 8f9bc68ee2..245a56712f 100644
> > --- a/pkt-line.c
> > +++ b/pkt-line.c
> > @@ -87,43 +87,43 @@ static void packet_trace(const char *buf, unsigned int len, int write)
> >   */
> >  void packet_flush(int fd)
> >  {
> > -	packet_trace("0000", 4, 1);
> > -	if (write_in_full(fd, "0000", 4) < 0)
> > +	packet_trace("0000", PACKET_HEADER_SIZE, 1);
> > +	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
> 
> I think the magic number 4 is easier to follow than some macro
> PACKET_HEADER_SIZE defined elsewhere. Because reader may judge that is
> the size of "0000"
> 
> How about (this ugly code):
> 
> 	packet_trace("0000", sizeof "0000" - 1, 1);
> 	if (write_in_full(fd, "0000", sizeof "0000" - 1) < 0)

Chris Torek mentioned something similar off-list:
> This seems sensible, but at the same time, the string literals must
> have the right size.  For instance:
> 
[...the diff above...]
> 
> So if you're going to do this, it might be a good idea to replace
> the string literals "0000", "0001", etc, with defined values as well.

Between the two suggested approaches, with your approach, it's
immediately obvious what the values of the packets are but, on the other
hand, with Chris's approach, we can consolidate the "magic" string
literals together into a definition in a single-place.

In this case, the strings don't seem too magical and I think that the
people on this list are generally against over-abstracting and would
consider it more readable to leave the literals in place. (If this were
my own project, I'd take Chris's approach, though, since I try to avoid
bare literals like the plague.)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-13 14:23 ` Đoàn Trần Công Danh
  2020-06-13 14:39   ` Denton Liu
@ 2020-06-13 16:51   ` Junio C Hamano
  2020-06-14 18:24     ` Junio C Hamano
  1 sibling, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2020-06-13 16:51 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: Denton Liu, Git Mailing List, Jeff King

Đoàn Trần Công Danh  <congdanhqx@gmail.com> writes:

>>  void packet_flush(int fd)
>>  {
>> -	packet_trace("0000", 4, 1);
>> -	if (write_in_full(fd, "0000", 4) < 0)
>> +	packet_trace("0000", PACKET_HEADER_SIZE, 1);
>> +	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
>
> I think the magic number 4 is easier to follow than some macro
> PACKET_HEADER_SIZE defined elsewhere. Because reader may judge that is
> the size of "0000"

I hate to admit it immensely, but I tend to agree with you.  In the
context of this single call,

	write_in_full(fd, "0000", 4)
	write_in_full(fd, "0000", PACKET_HEADER_SIZE)

I find the former vastly easier.

> How about (this ugly code):
>
> 	packet_trace("0000", sizeof "0000" - 1, 1);
> 	if (write_in_full(fd, "0000", sizeof "0000" - 1) < 0)

Yeah, that is ugly.  I was thinking more in the direction of
replacing these three-argument write_in_full with something like

#define write_constant(fd, constant_string) \
	write_in_full((fd), (constant_string), strlen(constant_string))

with some preprocessor magic to make the compilation break when the
second parameter to the macro is not a string constant.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2 0/3] pkt-line: war on magical `4` literal
  2020-06-13 13:43 [PATCH] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
  2020-06-13 14:23 ` Đoàn Trần Công Danh
@ 2020-06-14  7:31 ` Denton Liu
  2020-06-14  7:31   ` [PATCH v2 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
                     ` (4 more replies)
  1 sibling, 5 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-14  7:31 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King

There are many instances of the literal `4` in packet line-related code.
This series replaces these instances with either functions that can
generate the number or an appropriately-named constant.

Changes since v1:

* Introduce patch 1-2 so that the string length is used to generate the
  `4` where appropriate

Denton Liu (3):
  remote-curl: use strlen() instead of magic numbers
  pkt-line: use string versions of functions
  pkt-line: extract out PACKET_HEADER_SIZE

 pkt-line.c    | 66 +++++++++++++++++++++++++++++----------------------
 pkt-line.h    |  6 +++--
 remote-curl.c | 35 ++++++++++++++-------------
 3 files changed, 60 insertions(+), 47 deletions(-)

Interdiff against v1:
diff --git a/pkt-line.c b/pkt-line.c
index 245a56712f..f1fe0888c1 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -81,49 +81,59 @@ static void packet_trace(const char *buf, unsigned int len, int write)
 	strbuf_release(&out);
 }
 
+static inline void packet_trace_str(const char *buf, int write)
+{
+	packet_trace(buf, strlen(buf), write);
+}
+
+static inline void control_packet_write(int fd, const char *s, const char *type)
+{
+	packet_trace_str(s, 1);
+	if (write_str_in_full(fd, s) < 0)
+		die_errno(_("unable to write %s packet"), type);
+}
+
 /*
  * If we buffered things up above (we don't, but we should),
  * we'd flush it here
  */
 void packet_flush(int fd)
 {
-	packet_trace("0000", PACKET_HEADER_SIZE, 1);
-	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
-		die_errno(_("unable to write flush packet"));
+	control_packet_write(fd, "0000", "flush");
 }
 
 void packet_delim(int fd)
 {
-	packet_trace("0001", PACKET_HEADER_SIZE, 1);
-	if (write_in_full(fd, "0001", PACKET_HEADER_SIZE) < 0)
-		die_errno(_("unable to write delim packet"));
+	control_packet_write(fd, "0001", "delim");
 }
 
 void packet_response_end(int fd)
 {
-	packet_trace("0002", PACKET_HEADER_SIZE, 1);
-	if (write_in_full(fd, "0002", PACKET_HEADER_SIZE) < 0)
-		die_errno(_("unable to write stateless separator packet"));
+	control_packet_write(fd, "0002", "stateless separator");
 }
 
 int packet_flush_gently(int fd)
 {
-	packet_trace("0000", PACKET_HEADER_SIZE, 1);
-	if (write_in_full(fd, "0000", PACKET_HEADER_SIZE) < 0)
+	packet_trace_str("0000", 1);
+	if (write_str_in_full(fd, "0000") < 0)
 		return error(_("flush packet write failed"));
 	return 0;
 }
 
+static inline void control_packet_buf_write(struct strbuf *buf, const char *s)
+{
+	packet_trace_str(s, 1);
+	strbuf_addstr(buf, s);
+}
+
 void packet_buf_flush(struct strbuf *buf)
 {
-	packet_trace("0000", PACKET_HEADER_SIZE, 1);
-	strbuf_add(buf, "0000", PACKET_HEADER_SIZE);
+	control_packet_buf_write(buf, "0000");
 }
 
 void packet_buf_delim(struct strbuf *buf)
 {
-	packet_trace("0001", PACKET_HEADER_SIZE, 1);
-	strbuf_add(buf, "0001", PACKET_HEADER_SIZE);
+	control_packet_buf_write(buf, "0001");
 }
 
 void set_packet_header(char *buf, int size)
@@ -337,15 +347,15 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 	if (len < 0) {
 		die(_("protocol error: bad line length character: %.4s"), linelen);
 	} else if (!len) {
-		packet_trace("0000", PACKET_HEADER_SIZE, 0);
+		packet_trace_str("0000", 0);
 		*pktlen = 0;
 		return PACKET_READ_FLUSH;
 	} else if (len == 1) {
-		packet_trace("0001", PACKET_HEADER_SIZE, 0);
+		packet_trace_str("0001", 0);
 		*pktlen = 0;
 		return PACKET_READ_DELIM;
 	} else if (len == 2) {
-		packet_trace("0002", PACKET_HEADER_SIZE, 0);
+		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
 	} else if (len < PACKET_HEADER_SIZE) {
diff --git a/remote-curl.c b/remote-curl.c
index bac295c5bc..7ba1280a41 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -536,8 +536,8 @@ struct rpc_state {
 	unsigned initial_buffer : 1;
 
 	/*
-	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE characters
-	 * denoting its length before appending the payload.
+	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE
+	 * characters denoting its length before appending the payload.
 	 */
 	unsigned write_line_lengths : 1;
 
@@ -556,8 +556,9 @@ struct rpc_state {
  * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
  * enough space, 0 otherwise.
  *
- * If rpc->write_line_lengths is true, appends the line length as a PACKET_HEADER_SIZE-byte
- * hexadecimal string before appending the result described above.
+ * If rpc->write_line_lengths is true, appends the line length as a
+ * PACKET_HEADER_SIZE-byte hexadecimal string before appending the result
+ * described above.
  *
  * Writes the total number of bytes appended into appended.
  */
@@ -596,10 +597,10 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 			set_packet_header(buf - PACKET_HEADER_SIZE, *appended);
 			break;
 		case PACKET_READ_DELIM:
-			memcpy(buf - PACKET_HEADER_SIZE, "0001", PACKET_HEADER_SIZE);
+			memcpy(buf - strlen("0001"), "0001", strlen("0001"));
 			break;
 		case PACKET_READ_FLUSH:
-			memcpy(buf - PACKET_HEADER_SIZE, "0000", PACKET_HEADER_SIZE);
+			memcpy(buf - strlen("0000"), "0000", strlen("0000"));
 			break;
 		case PACKET_READ_RESPONSE_END:
 			die(_("remote server sent stateless separator"));
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 1/3] remote-curl: use strlen() instead of magic numbers
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
@ 2020-06-14  7:31   ` Denton Liu
  2020-06-14  7:31   ` [PATCH v2 2/3] pkt-line: use string versions of functions Denton Liu
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-14  7:31 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King

When we are memcpy()ing the length header, we use the magic literal `4`,
representing the length of "0000" and "0001", the packet line length
headers. Use `strlen("000x")` so that we do not have to use the magic
literal.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 remote-curl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index 75532a8bae..5536372b34 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -596,10 +596,10 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 			set_packet_header(buf - 4, *appended);
 			break;
 		case PACKET_READ_DELIM:
-			memcpy(buf - 4, "0001", 4);
+			memcpy(buf - strlen("0001"), "0001", strlen("0001"));
 			break;
 		case PACKET_READ_FLUSH:
-			memcpy(buf - 4, "0000", 4);
+			memcpy(buf - strlen("0000"), "0000", strlen("0000"));
 			break;
 		case PACKET_READ_RESPONSE_END:
 			die(_("remote server sent stateless separator"));
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 2/3] pkt-line: use string versions of functions
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
  2020-06-14  7:31   ` [PATCH v2 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
@ 2020-06-14  7:31   ` Denton Liu
  2020-06-14  8:31     ` Đoàn Trần Công Danh
  2020-06-14  7:32   ` [PATCH v2 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 22+ messages in thread
From: Denton Liu @ 2020-06-14  7:31 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King

We have many cases where we are writing a control packet as a string
constant out and we need to specify the length of the string. Currently,
the length is specified as a magical `4` literal.

Change these instances to use a function that calls strlen() to
determine the length of the string removing the need to specify the
length at all. Since these functions are inline, the strlen()s should be
replaced with constants at compile-time so this should not result in any
performance penalty.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 pkt-line.c | 46 ++++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index 8f9bc68ee2..72c6c29e03 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -81,49 +81,59 @@ static void packet_trace(const char *buf, unsigned int len, int write)
 	strbuf_release(&out);
 }
 
+static inline void packet_trace_str(const char *buf, int write)
+{
+	packet_trace(buf, strlen(buf), write);
+}
+
+static inline void control_packet_write(int fd, const char *s, const char *type)
+{
+	packet_trace_str(s, 1);
+	if (write_str_in_full(fd, s) < 0)
+		die_errno(_("unable to write %s packet"), type);
+}
+
 /*
  * If we buffered things up above (we don't, but we should),
  * we'd flush it here
  */
 void packet_flush(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
-		die_errno(_("unable to write flush packet"));
+	control_packet_write(fd, "0000", "flush");
 }
 
 void packet_delim(int fd)
 {
-	packet_trace("0001", 4, 1);
-	if (write_in_full(fd, "0001", 4) < 0)
-		die_errno(_("unable to write delim packet"));
+	control_packet_write(fd, "0001", "delim");
 }
 
 void packet_response_end(int fd)
 {
-	packet_trace("0002", 4, 1);
-	if (write_in_full(fd, "0002", 4) < 0)
-		die_errno(_("unable to write stateless separator packet"));
+	control_packet_write(fd, "0002", "stateless separator");
 }
 
 int packet_flush_gently(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
+	packet_trace_str("0000", 1);
+	if (write_str_in_full(fd, "0000") < 0)
 		return error(_("flush packet write failed"));
 	return 0;
 }
 
+static inline void control_packet_buf_write(struct strbuf *buf, const char *s)
+{
+	packet_trace_str(s, 1);
+	strbuf_addstr(buf, s);
+}
+
 void packet_buf_flush(struct strbuf *buf)
 {
-	packet_trace("0000", 4, 1);
-	strbuf_add(buf, "0000", 4);
+	control_packet_buf_write(buf, "0000");
 }
 
 void packet_buf_delim(struct strbuf *buf)
 {
-	packet_trace("0001", 4, 1);
-	strbuf_add(buf, "0001", 4);
+	control_packet_buf_write(buf, "0001");
 }
 
 void set_packet_header(char *buf, int size)
@@ -337,15 +347,15 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 	if (len < 0) {
 		die(_("protocol error: bad line length character: %.4s"), linelen);
 	} else if (!len) {
-		packet_trace("0000", 4, 0);
+		packet_trace_str("0000", 0);
 		*pktlen = 0;
 		return PACKET_READ_FLUSH;
 	} else if (len == 1) {
-		packet_trace("0001", 4, 0);
+		packet_trace_str("0001", 0);
 		*pktlen = 0;
 		return PACKET_READ_DELIM;
 	} else if (len == 2) {
-		packet_trace("0002", 4, 0);
+		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
 	} else if (len < 4) {
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v2 3/3] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
  2020-06-14  7:31   ` [PATCH v2 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
  2020-06-14  7:31   ` [PATCH v2 2/3] pkt-line: use string versions of functions Denton Liu
@ 2020-06-14  7:32   ` Denton Liu
  2020-06-14 21:32   ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Junio C Hamano
  2020-06-23 17:55   ` [PATCH v3 " Denton Liu
  4 siblings, 0 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-14  7:32 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King

In pkt-line and remote-curl, we have many instances of magic `4`
literals floating around which represent the number of bytes in the
packet line length header. Instead of using these magic numbers, replace
them with constant expressions.

In most cases, replace the `4` with `PACKET_HEADER_SIZE`. However, in
the case where there's a `char array[PACKET_HEADER_SIZE]`  and we are
reading data into it, replace the `4` with a `sizeof(array)` so that
it's clear that the logic has something to do with that array.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 pkt-line.c    | 20 ++++++++++----------
 pkt-line.h    |  6 ++++--
 remote-curl.c | 31 ++++++++++++++++---------------
 3 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index 72c6c29e03..f1fe0888c1 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -163,7 +163,7 @@ static void format_packet(struct strbuf *out, const char *prefix,
 		die(_("protocol error: impossibly long line"));
 
 	set_packet_header(&out->buf[orig_len], n);
-	packet_trace(out->buf + orig_len + 4, n - 4, 1);
+	packet_trace(out->buf + orig_len + PACKET_HEADER_SIZE, n - PACKET_HEADER_SIZE, 1);
 }
 
 static int packet_write_fmt_1(int fd, int gently, const char *prefix,
@@ -209,13 +209,13 @@ static int packet_write_gently(const int fd_out, const char *buf, size_t size)
 	static char packet_write_buffer[LARGE_PACKET_MAX];
 	size_t packet_size;
 
-	if (size > sizeof(packet_write_buffer) - 4)
+	if (size > sizeof(packet_write_buffer) - PACKET_HEADER_SIZE)
 		return error(_("packet write failed - data exceeds max packet size"));
 
 	packet_trace(buf, size, 1);
-	packet_size = size + 4;
+	packet_size = size + PACKET_HEADER_SIZE;
 	set_packet_header(packet_write_buffer, packet_size);
-	memcpy(packet_write_buffer + 4, buf, size);
+	memcpy(packet_write_buffer + PACKET_HEADER_SIZE, buf, size);
 	if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
 		return error(_("packet write failed"));
 	return 0;
@@ -323,7 +323,7 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
 	return ret;
 }
 
-int packet_length(const char lenbuf_hex[4])
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE])
 {
 	int val = hex2chr(lenbuf_hex);
 	return (val < 0) ? val : (val << 8) | hex2chr(lenbuf_hex + 2);
@@ -335,9 +335,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 						int options)
 {
 	int len;
-	char linelen[4];
+	char linelen[PACKET_HEADER_SIZE];
 
-	if (get_packet_data(fd, src_buffer, src_len, linelen, 4, options) < 0) {
+	if (get_packet_data(fd, src_buffer, src_len, linelen, sizeof(linelen), options) < 0) {
 		*pktlen = -1;
 		return PACKET_READ_EOF;
 	}
@@ -358,11 +358,11 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
-	} else if (len < 4) {
+	} else if (len < PACKET_HEADER_SIZE) {
 		die(_("protocol error: bad line length %d"), len);
 	}
 
-	len -= 4;
+	len -= sizeof(linelen);
 	if ((unsigned)len >= size)
 		die(_("protocol error: bad line length %d"), len);
 
@@ -380,7 +380,7 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 
 	if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
 	    starts_with(buffer, "ERR "))
-		die(_("remote error: %s"), buffer + 4);
+		die(_("remote error: %s"), buffer + PACKET_HEADER_SIZE);
 
 	*pktlen = len;
 	return PACKET_READ_NORMAL;
diff --git a/pkt-line.h b/pkt-line.h
index 5b373fe4cd..d6121b8044 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -5,6 +5,8 @@
 #include "strbuf.h"
 #include "sideband.h"
 
+#define PACKET_HEADER_SIZE 4
+
 /*
  * Write a packetized stream, where each line is preceded by
  * its length (including the header) as a 4-byte hex number.
@@ -82,7 +84,7 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, char
  * If lenbuf_hex contains non-hex characters, return -1. Otherwise, return the
  * numeric value of the length header.
  */
-int packet_length(const char lenbuf_hex[4]);
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE]);
 
 /*
  * Read a packetized line into a buffer like the 'packet_read()' function but
@@ -211,7 +213,7 @@ 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)
+#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - PACKET_HEADER_SIZE)
 extern char packet_buffer[LARGE_PACKET_MAX];
 
 struct packet_writer {
diff --git a/remote-curl.c b/remote-curl.c
index 5536372b34..7ba1280a41 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -536,8 +536,8 @@ struct rpc_state {
 	unsigned initial_buffer : 1;
 
 	/*
-	 * Whenever a pkt-line is read into buf, append the 4 characters
-	 * denoting its length before appending the payload.
+	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE
+	 * characters denoting its length before appending the payload.
 	 */
 	unsigned write_line_lengths : 1;
 
@@ -556,8 +556,9 @@ struct rpc_state {
  * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
  * enough space, 0 otherwise.
  *
- * If rpc->write_line_lengths is true, appends the line length as a 4-byte
- * hexadecimal string before appending the result described above.
+ * If rpc->write_line_lengths is true, appends the line length as a
+ * PACKET_HEADER_SIZE-byte hexadecimal string before appending the result
+ * described above.
  *
  * Writes the total number of bytes appended into appended.
  */
@@ -569,8 +570,8 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	int pktlen_raw;
 
 	if (rpc->write_line_lengths) {
-		left = rpc->alloc - rpc->len - 4;
-		buf = rpc->buf + rpc->len + 4;
+		left = rpc->alloc - rpc->len - PACKET_HEADER_SIZE;
+		buf = rpc->buf + rpc->len + PACKET_HEADER_SIZE;
 	} else {
 		left = rpc->alloc - rpc->len;
 		buf = rpc->buf + rpc->len;
@@ -582,7 +583,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	*status = packet_read_with_status(rpc->out, NULL, NULL, buf,
 			left, &pktlen_raw, options);
 	if (*status != PACKET_READ_EOF) {
-		*appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
+		*appended = pktlen_raw + (rpc->write_line_lengths ? PACKET_HEADER_SIZE : 0);
 		rpc->len += *appended;
 	}
 
@@ -593,7 +594,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 				die(_("shouldn't have EOF when not gentle on EOF"));
 			break;
 		case PACKET_READ_NORMAL:
-			set_packet_header(buf - 4, *appended);
+			set_packet_header(buf - PACKET_HEADER_SIZE, *appended);
 			break;
 		case PACKET_READ_DELIM:
 			memcpy(buf - strlen("0001"), "0001", strlen("0001"));
@@ -682,7 +683,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
 #endif
 
 struct check_pktline_state {
-	char len_buf[4];
+	char len_buf[PACKET_HEADER_SIZE];
 	int len_filled;
 	int remaining;
 };
@@ -691,7 +692,7 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 {
 	while (size) {
 		if (!state->remaining) {
-			int digits_remaining = 4 - state->len_filled;
+			int digits_remaining = sizeof(state->len_buf) - state->len_filled;
 			if (digits_remaining > size)
 				digits_remaining = size;
 			memcpy(&state->len_buf[state->len_filled], ptr, digits_remaining);
@@ -699,16 +700,16 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 			ptr += digits_remaining;
 			size -= digits_remaining;
 
-			if (state->len_filled == 4) {
+			if (state->len_filled == sizeof(state->len_buf)) {
 				state->remaining = packet_length(state->len_buf);
 				if (state->remaining < 0) {
 					die(_("remote-curl: bad line length character: %.4s"), state->len_buf);
 				} else if (state->remaining == 2) {
 					die(_("remote-curl: unexpected response end packet"));
-				} else if (state->remaining < 4) {
+				} else if (state->remaining < sizeof(state->len_buf)) {
 					state->remaining = 0;
 				} else {
-					state->remaining -= 4;
+					state->remaining -= sizeof(state->len_buf);
 				}
 				state->len_filled = 0;
 			}
@@ -804,7 +805,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
 	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
-	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, PACKET_HEADER_SIZE);
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
@@ -1469,7 +1470,7 @@ int cmd_main(int argc, const char **argv)
 			parse_fetch(&buf);
 
 		} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
-			int for_push = !!strstr(buf.buf + 4, "for-push");
+			int for_push = !!strstr(buf.buf + PACKET_HEADER_SIZE, "for-push");
 			output_refs(get_refs(for_push));
 
 		} else if (starts_with(buf.buf, "push ")) {
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 2/3] pkt-line: use string versions of functions
  2020-06-14  7:31   ` [PATCH v2 2/3] pkt-line: use string versions of functions Denton Liu
@ 2020-06-14  8:31     ` Đoàn Trần Công Danh
  2020-06-14  9:07       ` [PATCH v2] " Denton Liu
  0 siblings, 1 reply; 22+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-14  8:31 UTC (permalink / raw)
  To: Denton Liu; +Cc: Git Mailing List, Jeff King

On 2020-06-14 03:31:59-0400, Denton Liu <liu.denton@gmail.com> wrote:
> We have many cases where we are writing a control packet as a string
> constant out and we need to specify the length of the string. Currently,
> the length is specified as a magical `4` literal.
> 
> Change these instances to use a function that calls strlen() to
> determine the length of the string removing the need to specify the
> length at all. Since these functions are inline, the strlen()s should be
> replaced with constants at compile-time so this should not result in any
> performance penalty.
> 
> Signed-off-by: Denton Liu <liu.denton@gmail.com>
> ---
>  pkt-line.c | 46 ++++++++++++++++++++++++++++------------------
>  1 file changed, 28 insertions(+), 18 deletions(-)
> 
> diff --git a/pkt-line.c b/pkt-line.c
> index 8f9bc68ee2..72c6c29e03 100644
> --- a/pkt-line.c
> +++ b/pkt-line.c
> @@ -81,49 +81,59 @@ static void packet_trace(const char *buf, unsigned int len, int write)
>  	strbuf_release(&out);
>  }
>  
> +static inline void packet_trace_str(const char *buf, int write)
> +{
> +	packet_trace(buf, strlen(buf), write);
> +}
> +
> +static inline void control_packet_write(int fd, const char *s, const char *type)
> +{
> +	packet_trace_str(s, 1);
> +	if (write_str_in_full(fd, s) < 0)
> +		die_errno(_("unable to write %s packet"), type);

This will create i10n problems:
- Translators don't have enough context to know what does %s mean.
  In some languages, depend on value of %s, it will be translated to
  different phases by the order of words, word choices, gender.
- `type' won't be translated with this marker

I think it's better to pass full translated phase into this
function. Something like:

	static inline void control_packet_write(int fd, const char *s, const char *errstr)
	{
		...
		if (...)
			die_errno(errstr);
	}

and call the function with:

	control_packet_write(fd, "0000", _("unable to write flush packet"));

Other than that, I like the idea of using preprocessor to check
compile time constant string, but I'm not sure how to write it with
standard C

-- 
Danh

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v2] pkt-line: use string versions of functions
  2020-06-14  8:31     ` Đoàn Trần Công Danh
@ 2020-06-14  9:07       ` Denton Liu
  2020-06-14 21:35         ` Junio C Hamano
  2020-06-15 12:32         ` Đoàn Trần Công Danh
  0 siblings, 2 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-14  9:07 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Jeff King, Đoàn Trần Công Danh

We have many cases where we are writing a control packet as a string
constant out and we need to specify the length of the string. Currently,
the length is specified as a magical `4` literal.

Change these instances to use a function that calls strlen() to
determine the length of the string removing the need to specify the
length at all. Since these functions are inline, the strlen()s should be
replaced with constants at compile-time so this should not result in any
performance penalty.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
Hi Đoàn,

Perhaps something like this?

 pkt-line.c | 48 ++++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index 8f9bc68ee2..022376f00f 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -81,49 +81,61 @@ static void packet_trace(const char *buf, unsigned int len, int write)
 	strbuf_release(&out);
 }
 
+static inline void packet_trace_str(const char *buf, int write)
+{
+	packet_trace(buf, strlen(buf), write);
+}
+
+#define control_packet_write(fd, s, errstr) \
+	do { \
+		(void)s"is a string constant"; \
+		packet_trace_str((s), 1); \
+		if (write_str_in_full((fd), (s)) < 0) \
+			die_errno((errstr)); \
+	} while (0)
+
 /*
  * If we buffered things up above (we don't, but we should),
  * we'd flush it here
  */
 void packet_flush(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
-		die_errno(_("unable to write flush packet"));
+	control_packet_write(fd, "0000", _("unable to write flush packet"));
 }
 
 void packet_delim(int fd)
 {
-	packet_trace("0001", 4, 1);
-	if (write_in_full(fd, "0001", 4) < 0)
-		die_errno(_("unable to write delim packet"));
+	control_packet_write(fd, "0001", _("unable to write delim packet"));
 }
 
 void packet_response_end(int fd)
 {
-	packet_trace("0002", 4, 1);
-	if (write_in_full(fd, "0002", 4) < 0)
-		die_errno(_("unable to write stateless separator packet"));
+	control_packet_write(fd, "0002", _("unable to write stateless separator packet"));
 }
 
 int packet_flush_gently(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
+	packet_trace_str("0000", 1);
+	if (write_str_in_full(fd, "0000") < 0)
 		return error(_("flush packet write failed"));
 	return 0;
 }
 
+#define control_packet_buf_write(buf, s) \
+	do { \
+		(void)s"is a string constant"; \
+		packet_trace_str((s), 1); \
+		strbuf_addstr((buf), (s)); \
+	} while (0)
+
 void packet_buf_flush(struct strbuf *buf)
 {
-	packet_trace("0000", 4, 1);
-	strbuf_add(buf, "0000", 4);
+	control_packet_buf_write(buf, "0000");
 }
 
 void packet_buf_delim(struct strbuf *buf)
 {
-	packet_trace("0001", 4, 1);
-	strbuf_add(buf, "0001", 4);
+	control_packet_buf_write(buf, "0001");
 }
 
 void set_packet_header(char *buf, int size)
@@ -337,15 +349,15 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 	if (len < 0) {
 		die(_("protocol error: bad line length character: %.4s"), linelen);
 	} else if (!len) {
-		packet_trace("0000", 4, 0);
+		packet_trace_str("0000", 0);
 		*pktlen = 0;
 		return PACKET_READ_FLUSH;
 	} else if (len == 1) {
-		packet_trace("0001", 4, 0);
+		packet_trace_str("0001", 0);
 		*pktlen = 0;
 		return PACKET_READ_DELIM;
 	} else if (len == 2) {
-		packet_trace("0002", 4, 0);
+		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
 	} else if (len < 4) {
-- 
2.27.0.132.g321788e831


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-13 16:51   ` Junio C Hamano
@ 2020-06-14 18:24     ` Junio C Hamano
  0 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2020-06-14 18:24 UTC (permalink / raw)
  To: Đoàn Trần Công Danh
  Cc: Denton Liu, Git Mailing List, Jeff King

Junio C Hamano <gitster@pobox.com> writes:

>> How about (this ugly code):
>>
>> 	packet_trace("0000", sizeof "0000" - 1, 1);
>> 	if (write_in_full(fd, "0000", sizeof "0000" - 1) < 0)
>
> Yeah, that is ugly.  I was thinking more in the direction of
> replacing these three-argument write_in_full with something like
>
> #define write_constant(fd, constant_string) \
> 	write_in_full((fd), (constant_string), strlen(constant_string))
>
> with some preprocessor magic to make the compilation break when the
> second parameter to the macro is not a string constant.

There is a bit of subtlety but I did mean C preprocessor macro and
not a helper function with the above.  With use of a macro defined
like above, the programmer can write

	write_constant(fd, "0000");

which would turn into

	write_in_full((fd), "0000", strlen("0000"));
	
Descent compilers know to produce identical code as

	write_in_full((fd), "0000", 4);

when seeing a literal constant string given to strlen().

But a helper function like this:

	static int write_constant(int fd, const char *string) {
		return write_in_full(fd, string, strlen(string));
	}

has less chance of getting the same kind of optimization (the helper
needs to be inlined before the compiler can realize that the
parameter to strlen() is a literal constant whose length can be
computed at the compile time).



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2 0/3] pkt-line: war on magical `4` literal
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
                     ` (2 preceding siblings ...)
  2020-06-14  7:32   ` [PATCH v2 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
@ 2020-06-14 21:32   ` Junio C Hamano
  2020-06-23 17:55   ` [PATCH v3 " Denton Liu
  4 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2020-06-14 21:32 UTC (permalink / raw)
  To: Denton Liu; +Cc: Git Mailing List, Jeff King

Denton Liu <liu.denton@gmail.com> writes:

> +static inline void control_packet_write(int fd, const char *s, const char *type)
> +{
> +	packet_trace_str(s, 1);
> +	if (write_str_in_full(fd, s) < 0)
> +		die_errno(_("unable to write %s packet"), type);

This construct, whether "type" is a localized string _("...")  or
English literal "...", would not translate well, would it?  The
former causes sentence lego and the latter injects untranslated
adjective that modifies the word "packet" in the final sentence.

As write_str_in_full() MUST count how long the string is at runtime,
without any possibility to offload the work to compiler, when these
strings that are sent with the "magical 4" are all compile-time
constant literal strings, I am not sure if this is something we
should be happy with---we should aim better for a solution that does
not require the runtime to count if possible.

Thanks.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2] pkt-line: use string versions of functions
  2020-06-14  9:07       ` [PATCH v2] " Denton Liu
@ 2020-06-14 21:35         ` Junio C Hamano
  2020-06-14 22:28           ` Denton Liu
  2020-06-15 12:32         ` Đoàn Trần Công Danh
  1 sibling, 1 reply; 22+ messages in thread
From: Junio C Hamano @ 2020-06-14 21:35 UTC (permalink / raw)
  To: Denton Liu
  Cc: Git Mailing List, Jeff King,
	Đoàn Trần Công Danh

Denton Liu <liu.denton@gmail.com> writes:

> +#define control_packet_write(fd, s, errstr) \
> +	do { \
> +		(void)s"is a string constant"; \
> +		packet_trace_str((s), 1); \
> +		if (write_str_in_full((fd), (s)) < 0) \
> +			die_errno((errstr)); \
> +	} while (0)
> +

Oh, that's much better.  If you go this route, drop your use of
write_str_in_full(), but count the length of s with strlen() here
to give the chance to the compilers to count the constant strings
at compile time.

>  /*
>   * If we buffered things up above (we don't, but we should),
>   * we'd flush it here
>   */
>  void packet_flush(int fd)
>  {
> -	packet_trace("0000", 4, 1);
> -	if (write_in_full(fd, "0000", 4) < 0)
> -		die_errno(_("unable to write flush packet"));
> +	control_packet_write(fd, "0000", _("unable to write flush packet"));

> +#define control_packet_buf_write(buf, s) \
> +	do { \
> +		(void)s"is a string constant"; \
> +		packet_trace_str((s), 1); \
> +		strbuf_addstr((buf), (s)); \
> +	} while (0)
> +

Likewise for strbuf_addstr().

>  void packet_buf_flush(struct strbuf *buf)
>  {
> -	packet_trace("0000", 4, 1);
> -	strbuf_add(buf, "0000", 4);
> +	control_packet_buf_write(buf, "0000");
>  }

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2] pkt-line: use string versions of functions
  2020-06-14 21:35         ` Junio C Hamano
@ 2020-06-14 22:28           ` Denton Liu
  0 siblings, 0 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-14 22:28 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git Mailing List, Jeff King,
	Đoàn Trần Công Danh

On Sun, Jun 14, 2020 at 02:35:06PM -0700, Junio C Hamano wrote:
> Denton Liu <liu.denton@gmail.com> writes:
> 
> > +#define control_packet_write(fd, s, errstr) \
> > +	do { \
> > +		(void)s"is a string constant"; \
> > +		packet_trace_str((s), 1); \
> > +		if (write_str_in_full((fd), (s)) < 0) \
> > +			die_errno((errstr)); \
> > +	} while (0)
> > +
> 
> Oh, that's much better.  If you go this route, drop your use of
> write_str_in_full(), but count the length of s with strlen() here
> to give the chance to the compilers to count the constant strings
> at compile time.
> 
> >  /*
> >   * If we buffered things up above (we don't, but we should),
> >   * we'd flush it here
> >   */
> >  void packet_flush(int fd)
> >  {
> > -	packet_trace("0000", 4, 1);
> > -	if (write_in_full(fd, "0000", 4) < 0)
> > -		die_errno(_("unable to write flush packet"));
> > +	control_packet_write(fd, "0000", _("unable to write flush packet"));
> 
> > +#define control_packet_buf_write(buf, s) \
> > +	do { \
> > +		(void)s"is a string constant"; \
> > +		packet_trace_str((s), 1); \
> > +		strbuf_addstr((buf), (s)); \
> > +	} while (0)
> > +
> 
> Likewise for strbuf_addstr().
> 
> >  void packet_buf_flush(struct strbuf *buf)
> >  {
> > -	packet_trace("0000", 4, 1);
> > -	strbuf_add(buf, "0000", 4);
> > +	control_packet_buf_write(buf, "0000");
> >  }

Checking the code, it seems like write_str_in_full() and strbuf_addstr()
are both inline defined. I was under the impression that the compiler
will optimise out these strlen()s to be compile-time constants. In fact,
strbuf_addstr() has this comment

	NOTE: This function will *always* be implemented as an inline or a macro
	using strlen, meaning that this is efficient to write things like:

so if my assumption isn't true, I suspect that we'd need to change the
comment.

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v2] pkt-line: use string versions of functions
  2020-06-14  9:07       ` [PATCH v2] " Denton Liu
  2020-06-14 21:35         ` Junio C Hamano
@ 2020-06-15 12:32         ` Đoàn Trần Công Danh
  1 sibling, 0 replies; 22+ messages in thread
From: Đoàn Trần Công Danh @ 2020-06-15 12:32 UTC (permalink / raw)
  To: Denton Liu; +Cc: Git Mailing List, Jeff King

On 2020-06-14 05:07:54-0400, Denton Liu <liu.denton@gmail.com> wrote:
> Hi Đoàn,

Sorry for this late reply, I have another stuff to work on.

> Perhaps something like this?

This looks better, but ...

> 
>  pkt-line.c | 48 ++++++++++++++++++++++++++++++------------------
>  1 file changed, 30 insertions(+), 18 deletions(-)
> 
> diff --git a/pkt-line.c b/pkt-line.c
> index 8f9bc68ee2..022376f00f 100644
> --- a/pkt-line.c
> +++ b/pkt-line.c
> @@ -81,49 +81,61 @@ static void packet_trace(const char *buf, unsigned int len, int write)
>  	strbuf_release(&out);
>  }
>  
> +static inline void packet_trace_str(const char *buf, int write)
> +{
> +	packet_trace(buf, strlen(buf), write);
> +}
> +
> +#define control_packet_write(fd, s, errstr) \
> +	do { \
> +		(void)s"is a string constant"; \

If we are going to not wrap s inside () here,

> +		packet_trace_str((s), 1); \

I see no point in wrapping it here.
And wrapping around "string" is not standard C,
some (or most) compilers support it as an extension.

See USE_PARENS_AROUND_GETTEXT_N

Can we just put it straight?

	packet_trace(s, strlen(s), 1);

> +		if (write_str_in_full((fd), (s)) < 0) \
> +			die_errno((errstr)); \
> +	} while (0)
> +

-- 
Danh

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v3 0/3] pkt-line: war on magical `4` literal
  2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
                     ` (3 preceding siblings ...)
  2020-06-14 21:32   ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Junio C Hamano
@ 2020-06-23 17:55   ` Denton Liu
  2020-06-23 17:55     ` [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
                       ` (2 more replies)
  4 siblings, 3 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-23 17:55 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Jeff King, Chris Torek, Đoàn Trần Công Danh,
	Junio C Hamano

There are many instances of the literal `4` in packet line-related code.
This series replaces these instances with either functions that can
generate the number or an appropriately-named constant.

Changes since v1:

* Introduce patch 1-2 so that the string length is used to generate the
  `4` where appropriate

Changes since v2:

* Replace some a couple of inline functions with macros that ensure they
  are string constants

* Use strlen() in one more instance over the PACKET_HEADER_SIZE

Denton Liu (3):
  remote-curl: use strlen() instead of magic numbers
  pkt-line: use string versions of functions
  pkt-line: extract out PACKET_HEADER_SIZE

 pkt-line.c    | 68 ++++++++++++++++++++++++++++++---------------------
 pkt-line.h    |  6 +++--
 remote-curl.c | 35 +++++++++++++-------------
 3 files changed, 62 insertions(+), 47 deletions(-)

Range-diff against v2:
1:  d2aaf15aa8 ! 1:  cb8683837c remote-curl: use strlen() instead of magic numbers
    @@ Metadata
      ## Commit message ##
         remote-curl: use strlen() instead of magic numbers
     
    -    When we are memcpy()ing the length header, we use the magic literal `4`,
    -    representing the length of "0000" and "0001", the packet line length
    -    headers. Use `strlen("000x")` so that we do not have to use the magic
    -    literal.
    +    When we are dealing with a packet-line length header, we use the magic
    +    literal `4`, representing the length of "0000" and "0001", the packet
    +    line length headers. Use `strlen("000x")` so that we do not have to use
    +    the magic literal.
     
      ## remote-curl.c ##
     @@ remote-curl.c: static int rpc_read_from_out(struct rpc_state *rpc, int options,
    @@ remote-curl.c: static int rpc_read_from_out(struct rpc_state *rpc, int options,
      			break;
      		case PACKET_READ_RESPONSE_END:
      			die(_("remote server sent stateless separator"));
    +@@ remote-curl.c: static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
    + 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
    + 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
    + 	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
    +-	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
    ++	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, strlen("0000"));
    + 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
    + 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
    + 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
2:  8cab5078b1 ! 2:  d283a1b514 pkt-line: use string versions of functions
    @@ Commit message
         replaced with constants at compile-time so this should not result in any
         performance penalty.
     
    +
    + ## Notes ##
    +    Junio, you mentioned in an earlier email[0] that write_str_in_full() and
    +    strbuf_addstr() each count the string length at runtime. However, I
    +    don't think that's true since they're both inline functions and
    +    strbuf_addstr() has the following comment:
    +
    +    	/**
    +    	 * Add a NUL-terminated string to the buffer.
    +    	 *
    +    	 * NOTE: This function will *always* be implemented as an inline or a macro
    +    	 * using strlen, meaning that this is efficient to write things like:
    +    	 *
    +    	 *     strbuf_addstr(sb, "immediate string");
    +    	 *
    +    	 */
    +
    +    so I believe that the lengths should be determined at compile-time.
    +
    +    [0]: https://lore.kernel.org/git/xmqqeeqhxred.fsf@gitster.c.googlers.com/
    +
      ## pkt-line.c ##
     @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int write)
      	strbuf_release(&out);
    @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int writ
     +	packet_trace(buf, strlen(buf), write);
     +}
     +
    -+static inline void control_packet_write(int fd, const char *s, const char *type)
    -+{
    -+	packet_trace_str(s, 1);
    -+	if (write_str_in_full(fd, s) < 0)
    -+		die_errno(_("unable to write %s packet"), type);
    -+}
    ++#define control_packet_write(fd, s, errstr) \
    ++	do { \
    ++		(void)s"is a string constant"; \
    ++		packet_trace_str(s, 1); \
    ++		if (write_str_in_full((fd), s) < 0) \
    ++			die_errno((errstr)); \
    ++	} while (0)
     +
      /*
       * If we buffered things up above (we don't, but we should),
    @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int writ
     -	packet_trace("0000", 4, 1);
     -	if (write_in_full(fd, "0000", 4) < 0)
     -		die_errno(_("unable to write flush packet"));
    -+	control_packet_write(fd, "0000", "flush");
    ++	control_packet_write(fd, "0000", _("unable to write flush packet"));
      }
      
      void packet_delim(int fd)
    @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int writ
     -	packet_trace("0001", 4, 1);
     -	if (write_in_full(fd, "0001", 4) < 0)
     -		die_errno(_("unable to write delim packet"));
    -+	control_packet_write(fd, "0001", "delim");
    ++	control_packet_write(fd, "0001", _("unable to write delim packet"));
      }
      
      void packet_response_end(int fd)
    @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int writ
     -	packet_trace("0002", 4, 1);
     -	if (write_in_full(fd, "0002", 4) < 0)
     -		die_errno(_("unable to write stateless separator packet"));
    -+	control_packet_write(fd, "0002", "stateless separator");
    ++	control_packet_write(fd, "0002", _("unable to write stateless separator packet"));
      }
      
      int packet_flush_gently(int fd)
    @@ pkt-line.c: static void packet_trace(const char *buf, unsigned int len, int writ
      	return 0;
      }
      
    -+static inline void control_packet_buf_write(struct strbuf *buf, const char *s)
    -+{
    -+	packet_trace_str(s, 1);
    -+	strbuf_addstr(buf, s);
    -+}
    ++#define control_packet_buf_write(buf, s) \
    ++	do { \
    ++		(void)s"is a string constant"; \
    ++		packet_trace_str(s, 1); \
    ++		strbuf_addstr((buf), s); \
    ++	} while (0)
     +
      void packet_buf_flush(struct strbuf *buf)
      {
3:  585d8892c3 ! 3:  00c19983fd pkt-line: extract out PACKET_HEADER_SIZE
    @@ remote-curl.c: static void check_pktline(struct check_pktline_state *state, cons
      				}
      				state->len_filled = 0;
      			}
    -@@ remote-curl.c: static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
    - 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
    - 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
    - 	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
    --	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
    -+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, PACKET_HEADER_SIZE);
    - 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
    - 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
    - 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
     @@ remote-curl.c: int cmd_main(int argc, const char **argv)
      			parse_fetch(&buf);
      
-- 
2.27.0.307.g7979e895e7


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers
  2020-06-23 17:55   ` [PATCH v3 " Denton Liu
@ 2020-06-23 17:55     ` Denton Liu
  2020-06-23 18:54       ` Jeff King
  2020-06-23 17:55     ` [PATCH v3 2/3] pkt-line: use string versions of functions Denton Liu
  2020-06-23 17:55     ` [PATCH v3 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
  2 siblings, 1 reply; 22+ messages in thread
From: Denton Liu @ 2020-06-23 17:55 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Jeff King, Chris Torek, Đoàn Trần Công Danh,
	Junio C Hamano

When we are dealing with a packet-line length header, we use the magic
literal `4`, representing the length of "0000" and "0001", the packet
line length headers. Use `strlen("000x")` so that we do not have to use
the magic literal.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 remote-curl.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index 75532a8bae..a2cbef546b 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -596,10 +596,10 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 			set_packet_header(buf - 4, *appended);
 			break;
 		case PACKET_READ_DELIM:
-			memcpy(buf - 4, "0001", 4);
+			memcpy(buf - strlen("0001"), "0001", strlen("0001"));
 			break;
 		case PACKET_READ_FLUSH:
-			memcpy(buf - 4, "0000", 4);
+			memcpy(buf - strlen("0000"), "0000", strlen("0000"));
 			break;
 		case PACKET_READ_RESPONSE_END:
 			die(_("remote server sent stateless separator"));
@@ -804,7 +804,7 @@ static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
 	curl_easy_setopt(slot->curl, CURLOPT_URL, rpc->service_url);
 	curl_easy_setopt(slot->curl, CURLOPT_ENCODING, NULL);
 	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, "0000");
-	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, 4);
+	curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDSIZE, strlen("0000"));
 	curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
 	curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
 	curl_easy_setopt(slot->curl, CURLOPT_FILE, &buf);
-- 
2.27.0.307.g7979e895e7


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 2/3] pkt-line: use string versions of functions
  2020-06-23 17:55   ` [PATCH v3 " Denton Liu
  2020-06-23 17:55     ` [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
@ 2020-06-23 17:55     ` Denton Liu
  2020-06-23 19:11       ` Jeff King
  2020-06-23 17:55     ` [PATCH v3 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
  2 siblings, 1 reply; 22+ messages in thread
From: Denton Liu @ 2020-06-23 17:55 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Jeff King, Chris Torek, Đoàn Trần Công Danh,
	Junio C Hamano

We have many cases where we are writing a control packet as a string
constant out and we need to specify the length of the string. Currently,
the length is specified as a magical `4` literal.

Change these instances to use a function that calls strlen() to
determine the length of the string removing the need to specify the
length at all. Since these functions are inline, the strlen()s should be
replaced with constants at compile-time so this should not result in any
performance penalty.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---

Notes:
    Junio, you mentioned in an earlier email[0] that write_str_in_full() and
    strbuf_addstr() each count the string length at runtime. However, I
    don't think that's true since they're both inline functions and
    strbuf_addstr() has the following comment:
    
    	/**
    	 * Add a NUL-terminated string to the buffer.
    	 *
    	 * NOTE: This function will *always* be implemented as an inline or a macro
    	 * using strlen, meaning that this is efficient to write things like:
    	 *
    	 *     strbuf_addstr(sb, "immediate string");
    	 *
    	 */
    
    so I believe that the lengths should be determined at compile-time.
    
    [0]: https://lore.kernel.org/git/xmqqeeqhxred.fsf@gitster.c.googlers.com/

 pkt-line.c | 48 ++++++++++++++++++++++++++++++------------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index 8f9bc68ee2..e29f427b19 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -81,49 +81,61 @@ static void packet_trace(const char *buf, unsigned int len, int write)
 	strbuf_release(&out);
 }
 
+static inline void packet_trace_str(const char *buf, int write)
+{
+	packet_trace(buf, strlen(buf), write);
+}
+
+#define control_packet_write(fd, s, errstr) \
+	do { \
+		(void)s"is a string constant"; \
+		packet_trace_str(s, 1); \
+		if (write_str_in_full((fd), s) < 0) \
+			die_errno((errstr)); \
+	} while (0)
+
 /*
  * If we buffered things up above (we don't, but we should),
  * we'd flush it here
  */
 void packet_flush(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
-		die_errno(_("unable to write flush packet"));
+	control_packet_write(fd, "0000", _("unable to write flush packet"));
 }
 
 void packet_delim(int fd)
 {
-	packet_trace("0001", 4, 1);
-	if (write_in_full(fd, "0001", 4) < 0)
-		die_errno(_("unable to write delim packet"));
+	control_packet_write(fd, "0001", _("unable to write delim packet"));
 }
 
 void packet_response_end(int fd)
 {
-	packet_trace("0002", 4, 1);
-	if (write_in_full(fd, "0002", 4) < 0)
-		die_errno(_("unable to write stateless separator packet"));
+	control_packet_write(fd, "0002", _("unable to write stateless separator packet"));
 }
 
 int packet_flush_gently(int fd)
 {
-	packet_trace("0000", 4, 1);
-	if (write_in_full(fd, "0000", 4) < 0)
+	packet_trace_str("0000", 1);
+	if (write_str_in_full(fd, "0000") < 0)
 		return error(_("flush packet write failed"));
 	return 0;
 }
 
+#define control_packet_buf_write(buf, s) \
+	do { \
+		(void)s"is a string constant"; \
+		packet_trace_str(s, 1); \
+		strbuf_addstr((buf), s); \
+	} while (0)
+
 void packet_buf_flush(struct strbuf *buf)
 {
-	packet_trace("0000", 4, 1);
-	strbuf_add(buf, "0000", 4);
+	control_packet_buf_write(buf, "0000");
 }
 
 void packet_buf_delim(struct strbuf *buf)
 {
-	packet_trace("0001", 4, 1);
-	strbuf_add(buf, "0001", 4);
+	control_packet_buf_write(buf, "0001");
 }
 
 void set_packet_header(char *buf, int size)
@@ -337,15 +349,15 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 	if (len < 0) {
 		die(_("protocol error: bad line length character: %.4s"), linelen);
 	} else if (!len) {
-		packet_trace("0000", 4, 0);
+		packet_trace_str("0000", 0);
 		*pktlen = 0;
 		return PACKET_READ_FLUSH;
 	} else if (len == 1) {
-		packet_trace("0001", 4, 0);
+		packet_trace_str("0001", 0);
 		*pktlen = 0;
 		return PACKET_READ_DELIM;
 	} else if (len == 2) {
-		packet_trace("0002", 4, 0);
+		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
 	} else if (len < 4) {
-- 
2.27.0.307.g7979e895e7


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH v3 3/3] pkt-line: extract out PACKET_HEADER_SIZE
  2020-06-23 17:55   ` [PATCH v3 " Denton Liu
  2020-06-23 17:55     ` [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
  2020-06-23 17:55     ` [PATCH v3 2/3] pkt-line: use string versions of functions Denton Liu
@ 2020-06-23 17:55     ` Denton Liu
  2 siblings, 0 replies; 22+ messages in thread
From: Denton Liu @ 2020-06-23 17:55 UTC (permalink / raw)
  To: Git Mailing List
  Cc: Jeff King, Chris Torek, Đoàn Trần Công Danh,
	Junio C Hamano

In pkt-line and remote-curl, we have many instances of magic `4`
literals floating around which represent the number of bytes in the
packet line length header. Instead of using these magic numbers, replace
them with constant expressions.

In most cases, replace the `4` with `PACKET_HEADER_SIZE`. However, in
the case where there's a `char array[PACKET_HEADER_SIZE]`  and we are
reading data into it, replace the `4` with a `sizeof(array)` so that
it's clear that the logic has something to do with that array.

Signed-off-by: Denton Liu <liu.denton@gmail.com>
---
 pkt-line.c    | 20 ++++++++++----------
 pkt-line.h    |  6 ++++--
 remote-curl.c | 29 +++++++++++++++--------------
 3 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index e29f427b19..d451f0b67c 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -165,7 +165,7 @@ static void format_packet(struct strbuf *out, const char *prefix,
 		die(_("protocol error: impossibly long line"));
 
 	set_packet_header(&out->buf[orig_len], n);
-	packet_trace(out->buf + orig_len + 4, n - 4, 1);
+	packet_trace(out->buf + orig_len + PACKET_HEADER_SIZE, n - PACKET_HEADER_SIZE, 1);
 }
 
 static int packet_write_fmt_1(int fd, int gently, const char *prefix,
@@ -211,13 +211,13 @@ static int packet_write_gently(const int fd_out, const char *buf, size_t size)
 	static char packet_write_buffer[LARGE_PACKET_MAX];
 	size_t packet_size;
 
-	if (size > sizeof(packet_write_buffer) - 4)
+	if (size > sizeof(packet_write_buffer) - PACKET_HEADER_SIZE)
 		return error(_("packet write failed - data exceeds max packet size"));
 
 	packet_trace(buf, size, 1);
-	packet_size = size + 4;
+	packet_size = size + PACKET_HEADER_SIZE;
 	set_packet_header(packet_write_buffer, packet_size);
-	memcpy(packet_write_buffer + 4, buf, size);
+	memcpy(packet_write_buffer + PACKET_HEADER_SIZE, buf, size);
 	if (write_in_full(fd_out, packet_write_buffer, packet_size) < 0)
 		return error(_("packet write failed"));
 	return 0;
@@ -325,7 +325,7 @@ static int get_packet_data(int fd, char **src_buf, size_t *src_size,
 	return ret;
 }
 
-int packet_length(const char lenbuf_hex[4])
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE])
 {
 	int val = hex2chr(lenbuf_hex);
 	return (val < 0) ? val : (val << 8) | hex2chr(lenbuf_hex + 2);
@@ -337,9 +337,9 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 						int options)
 {
 	int len;
-	char linelen[4];
+	char linelen[PACKET_HEADER_SIZE];
 
-	if (get_packet_data(fd, src_buffer, src_len, linelen, 4, options) < 0) {
+	if (get_packet_data(fd, src_buffer, src_len, linelen, sizeof(linelen), options) < 0) {
 		*pktlen = -1;
 		return PACKET_READ_EOF;
 	}
@@ -360,11 +360,11 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 		packet_trace_str("0002", 0);
 		*pktlen = 0;
 		return PACKET_READ_RESPONSE_END;
-	} else if (len < 4) {
+	} else if (len < PACKET_HEADER_SIZE) {
 		die(_("protocol error: bad line length %d"), len);
 	}
 
-	len -= 4;
+	len -= sizeof(linelen);
 	if ((unsigned)len >= size)
 		die(_("protocol error: bad line length %d"), len);
 
@@ -382,7 +382,7 @@ enum packet_read_status packet_read_with_status(int fd, char **src_buffer,
 
 	if ((options & PACKET_READ_DIE_ON_ERR_PACKET) &&
 	    starts_with(buffer, "ERR "))
-		die(_("remote error: %s"), buffer + 4);
+		die(_("remote error: %s"), buffer + PACKET_HEADER_SIZE);
 
 	*pktlen = len;
 	return PACKET_READ_NORMAL;
diff --git a/pkt-line.h b/pkt-line.h
index 5b373fe4cd..d6121b8044 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -5,6 +5,8 @@
 #include "strbuf.h"
 #include "sideband.h"
 
+#define PACKET_HEADER_SIZE 4
+
 /*
  * Write a packetized stream, where each line is preceded by
  * its length (including the header) as a 4-byte hex number.
@@ -82,7 +84,7 @@ int packet_read(int fd, char **src_buffer, size_t *src_len, char
  * If lenbuf_hex contains non-hex characters, return -1. Otherwise, return the
  * numeric value of the length header.
  */
-int packet_length(const char lenbuf_hex[4]);
+int packet_length(const char lenbuf_hex[PACKET_HEADER_SIZE]);
 
 /*
  * Read a packetized line into a buffer like the 'packet_read()' function but
@@ -211,7 +213,7 @@ 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)
+#define LARGE_PACKET_DATA_MAX (LARGE_PACKET_MAX - PACKET_HEADER_SIZE)
 extern char packet_buffer[LARGE_PACKET_MAX];
 
 struct packet_writer {
diff --git a/remote-curl.c b/remote-curl.c
index a2cbef546b..c99a2a514a 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -536,8 +536,8 @@ struct rpc_state {
 	unsigned initial_buffer : 1;
 
 	/*
-	 * Whenever a pkt-line is read into buf, append the 4 characters
-	 * denoting its length before appending the payload.
+	 * Whenever a pkt-line is read into buf, append the PACKET_HEADER_SIZE
+	 * characters denoting its length before appending the payload.
 	 */
 	unsigned write_line_lengths : 1;
 
@@ -556,8 +556,9 @@ struct rpc_state {
  * rpc->buf and rpc->len if there is enough space. Returns 1 if there was
  * enough space, 0 otherwise.
  *
- * If rpc->write_line_lengths is true, appends the line length as a 4-byte
- * hexadecimal string before appending the result described above.
+ * If rpc->write_line_lengths is true, appends the line length as a
+ * PACKET_HEADER_SIZE-byte hexadecimal string before appending the result
+ * described above.
  *
  * Writes the total number of bytes appended into appended.
  */
@@ -569,8 +570,8 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	int pktlen_raw;
 
 	if (rpc->write_line_lengths) {
-		left = rpc->alloc - rpc->len - 4;
-		buf = rpc->buf + rpc->len + 4;
+		left = rpc->alloc - rpc->len - PACKET_HEADER_SIZE;
+		buf = rpc->buf + rpc->len + PACKET_HEADER_SIZE;
 	} else {
 		left = rpc->alloc - rpc->len;
 		buf = rpc->buf + rpc->len;
@@ -582,7 +583,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 	*status = packet_read_with_status(rpc->out, NULL, NULL, buf,
 			left, &pktlen_raw, options);
 	if (*status != PACKET_READ_EOF) {
-		*appended = pktlen_raw + (rpc->write_line_lengths ? 4 : 0);
+		*appended = pktlen_raw + (rpc->write_line_lengths ? PACKET_HEADER_SIZE : 0);
 		rpc->len += *appended;
 	}
 
@@ -593,7 +594,7 @@ static int rpc_read_from_out(struct rpc_state *rpc, int options,
 				die(_("shouldn't have EOF when not gentle on EOF"));
 			break;
 		case PACKET_READ_NORMAL:
-			set_packet_header(buf - 4, *appended);
+			set_packet_header(buf - PACKET_HEADER_SIZE, *appended);
 			break;
 		case PACKET_READ_DELIM:
 			memcpy(buf - strlen("0001"), "0001", strlen("0001"));
@@ -682,7 +683,7 @@ static curlioerr rpc_ioctl(CURL *handle, int cmd, void *clientp)
 #endif
 
 struct check_pktline_state {
-	char len_buf[4];
+	char len_buf[PACKET_HEADER_SIZE];
 	int len_filled;
 	int remaining;
 };
@@ -691,7 +692,7 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 {
 	while (size) {
 		if (!state->remaining) {
-			int digits_remaining = 4 - state->len_filled;
+			int digits_remaining = sizeof(state->len_buf) - state->len_filled;
 			if (digits_remaining > size)
 				digits_remaining = size;
 			memcpy(&state->len_buf[state->len_filled], ptr, digits_remaining);
@@ -699,16 +700,16 @@ static void check_pktline(struct check_pktline_state *state, const char *ptr, si
 			ptr += digits_remaining;
 			size -= digits_remaining;
 
-			if (state->len_filled == 4) {
+			if (state->len_filled == sizeof(state->len_buf)) {
 				state->remaining = packet_length(state->len_buf);
 				if (state->remaining < 0) {
 					die(_("remote-curl: bad line length character: %.4s"), state->len_buf);
 				} else if (state->remaining == 2) {
 					die(_("remote-curl: unexpected response end packet"));
-				} else if (state->remaining < 4) {
+				} else if (state->remaining < sizeof(state->len_buf)) {
 					state->remaining = 0;
 				} else {
-					state->remaining -= 4;
+					state->remaining -= sizeof(state->len_buf);
 				}
 				state->len_filled = 0;
 			}
@@ -1469,7 +1470,7 @@ int cmd_main(int argc, const char **argv)
 			parse_fetch(&buf);
 
 		} else if (!strcmp(buf.buf, "list") || starts_with(buf.buf, "list ")) {
-			int for_push = !!strstr(buf.buf + 4, "for-push");
+			int for_push = !!strstr(buf.buf + PACKET_HEADER_SIZE, "for-push");
 			output_refs(get_refs(for_push));
 
 		} else if (starts_with(buf.buf, "push ")) {
-- 
2.27.0.307.g7979e895e7


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers
  2020-06-23 17:55     ` [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
@ 2020-06-23 18:54       ` Jeff King
  2020-06-23 19:39         ` Junio C Hamano
  0 siblings, 1 reply; 22+ messages in thread
From: Jeff King @ 2020-06-23 18:54 UTC (permalink / raw)
  To: Denton Liu
  Cc: Git Mailing List, Chris Torek,
	Đoàn Trần Công Danh, Junio C Hamano

On Tue, Jun 23, 2020 at 01:55:32PM -0400, Denton Liu wrote:

> When we are dealing with a packet-line length header, we use the magic
> literal `4`, representing the length of "0000" and "0001", the packet
> line length headers. Use `strlen("000x")` so that we do not have to use
> the magic literal.

I'm not a huge fan of using strlen() for this, because it's _still_
magical (you cannot change "0000" in one place without changing it in
another"). And while it helps with understanding that "4" matches the
length of that string, IMHO it's harder to read because now I have to
make sure that those much longer strings all match up.

This refactoring also implies to me that if you changed all of "0000" on
one line you'd be fine, but that's emphatically not true. The magic
number "4" is used to size the buffer earlier in the function, and would
have to match (and of course since this is a network protocol, it's not
like you could even change those in isolation).

So I dunno. I kind of think the raw "4" is the most readable. It's quite
obvious to me in the context of a memcpy() what's going on. I don't mind
memcpy_literal() or similar that hides the repetition, but I think it's
hard to do here because of the arithmetic on the destination.

-Peff

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 2/3] pkt-line: use string versions of functions
  2020-06-23 17:55     ` [PATCH v3 2/3] pkt-line: use string versions of functions Denton Liu
@ 2020-06-23 19:11       ` Jeff King
  0 siblings, 0 replies; 22+ messages in thread
From: Jeff King @ 2020-06-23 19:11 UTC (permalink / raw)
  To: Denton Liu
  Cc: Git Mailing List, Chris Torek,
	Đoàn Trần Công Danh, Junio C Hamano

On Tue, Jun 23, 2020 at 01:55:33PM -0400, Denton Liu wrote:

>  void packet_flush(int fd)
>  {
> -	packet_trace("0000", 4, 1);
> -	if (write_in_full(fd, "0000", 4) < 0)
> -		die_errno(_("unable to write flush packet"));
> +	control_packet_write(fd, "0000", _("unable to write flush packet"));
>  }

I like this kind of abstraction much more than what was going on in the
previous patch.

> +#define control_packet_write(fd, s, errstr) \
> +	do { \
> +		(void)s"is a string constant"; \

This is a neat trick. It might be nice to wrap in
BUILD_ASSERT_IS_STRING_LITERAL() or similar. (Though I wonder a bit if
we even really need to assert that; wouldn't it be OK to use this
function without it? We're using strlen(), after all, and not sizeof).

Would it also be useful to assert that the length of the control packet
is 4? And likewise that it's less than 4? That seems much more
interesting to me (as we'd be violating the protocol otherwise). And
that would be easy to do if the we passed the packet number as an
integer and formatted it ourselves.

But the result gets kind of ugly:

  void control_packet_write(int fd, unsigned packet_id, const char *errstr)
  {
	char buf[4 + 1];

	assert(packet_id < 4); /* >= 4 are actual data packets */
	vsnprintf(buf, sizeof(buf), "%04u", packet_id);
	if (write_in_full(fd, buf, 4))
		...;
  }

There are only 3 of these, and their whole point is to hide not just
this magic "4", but the whole idea of "this is what a control packet
looks like". I kind of wonder if the abstractions we need to reduce the
3 lines to 1 is really making anything more readable.

-Peff

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers
  2020-06-23 18:54       ` Jeff King
@ 2020-06-23 19:39         ` Junio C Hamano
  0 siblings, 0 replies; 22+ messages in thread
From: Junio C Hamano @ 2020-06-23 19:39 UTC (permalink / raw)
  To: Jeff King
  Cc: Denton Liu, Git Mailing List, Chris Torek,
	Đoàn Trần Công Danh

Jeff King <peff@peff.net> writes:

> On Tue, Jun 23, 2020 at 01:55:32PM -0400, Denton Liu wrote:
>
>> When we are dealing with a packet-line length header, we use the magic
>> literal `4`, representing the length of "0000" and "0001", the packet
>> line length headers. Use `strlen("000x")` so that we do not have to use
>> the magic literal.
>
> I'm not a huge fan of using strlen() for this, because it's _still_
> magical (you cannot change "0000" in one place without changing it in
> another"). And while it helps with understanding that "4" matches the
> length of that string, IMHO it's harder to read because now I have to
> make sure that those much longer strings all match up.

Yup.  There are two instances of recurring pattern with two memcpy,
where three copies of the same string must appear.  Unless the whole
thing is abstracted away so that these two instances are calls to
a macro/function that takes a single "0000" (and "0001"), I do not
think it is an improvement.

> This refactoring also implies to me that if you changed all of "0000" on
> one line you'd be fine, but that's emphatically not true. The magic
> number "4" is used to size the buffer earlier in the function, and would
> have to match (and of course since this is a network protocol, it's not
> like you could even change those in isolation).

Thanks.  That's even more important point.

> So I dunno. I kind of think the raw "4" is the most readable. It's quite
> obvious to me in the context of a memcpy() what's going on. I don't mind
> memcpy_literal() or similar that hides the repetition, but I think it's
> hard to do here because of the arithmetic on the destination.
>
> -Peff

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2020-06-23 19:39 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-13 13:43 [PATCH] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
2020-06-13 14:23 ` Đoàn Trần Công Danh
2020-06-13 14:39   ` Denton Liu
2020-06-13 16:51   ` Junio C Hamano
2020-06-14 18:24     ` Junio C Hamano
2020-06-14  7:31 ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Denton Liu
2020-06-14  7:31   ` [PATCH v2 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
2020-06-14  7:31   ` [PATCH v2 2/3] pkt-line: use string versions of functions Denton Liu
2020-06-14  8:31     ` Đoàn Trần Công Danh
2020-06-14  9:07       ` [PATCH v2] " Denton Liu
2020-06-14 21:35         ` Junio C Hamano
2020-06-14 22:28           ` Denton Liu
2020-06-15 12:32         ` Đoàn Trần Công Danh
2020-06-14  7:32   ` [PATCH v2 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu
2020-06-14 21:32   ` [PATCH v2 0/3] pkt-line: war on magical `4` literal Junio C Hamano
2020-06-23 17:55   ` [PATCH v3 " Denton Liu
2020-06-23 17:55     ` [PATCH v3 1/3] remote-curl: use strlen() instead of magic numbers Denton Liu
2020-06-23 18:54       ` Jeff King
2020-06-23 19:39         ` Junio C Hamano
2020-06-23 17:55     ` [PATCH v3 2/3] pkt-line: use string versions of functions Denton Liu
2020-06-23 19:11       ` Jeff King
2020-06-23 17:55     ` [PATCH v3 3/3] pkt-line: extract out PACKET_HEADER_SIZE Denton Liu

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).