Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nanopb/nanopb.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetteri Aimonen <jpa@git.mail.kapsi.fi>2017-09-16 13:40:57 +0300
committerPetteri Aimonen <jpa@git.mail.kapsi.fi>2017-09-16 13:40:57 +0300
commite21e78c67cbd6566fe9d8368eeaf3298ae22b75d (patch)
treecb2a44a3a93b3d6b9fb049219adcf6dcd003235c
parent03a7f76ef6df8ecfdf493c732a67a8e2f687bb90 (diff)
Add pb_en/decode_nullterminated() (part of #278)
Nanopb has traditionally supported messages to be terminated with a zero tag. However, this is not really standard protobuf behaviour, so it makes sense to separate it into a different function. Because it is a breaking change, it will happen in 0.4.0 release. But I add the functions here early so that new code can start using them now. Also changed the network_server example to use en/decode_delimited(), which is the more common protobuf method of simple message framing.
-rw-r--r--examples/network_server/client.c8
-rw-r--r--examples/network_server/server.c8
-rw-r--r--pb_decode.c6
-rw-r--r--pb_decode.h7
-rw-r--r--pb_encode.c10
-rw-r--r--pb_encode.h6
6 files changed, 37 insertions, 8 deletions
diff --git a/examples/network_server/client.c b/examples/network_server/client.c
index 00f6dab..ca0c68e 100644
--- a/examples/network_server/client.c
+++ b/examples/network_server/client.c
@@ -49,7 +49,6 @@ bool listdir(int fd, char *path)
{
ListFilesRequest request = {};
pb_ostream_t output = pb_ostream_from_socket(fd);
- uint8_t zero = 0;
/* In our protocol, path is optional. If it is not given,
* the server will list the root directory. */
@@ -71,14 +70,11 @@ bool listdir(int fd, char *path)
/* Encode the request. It is written to the socket immediately
* through our custom stream. */
- if (!pb_encode(&output, ListFilesRequest_fields, &request))
+ if (!pb_encode_delimited(&output, ListFilesRequest_fields, &request))
{
fprintf(stderr, "Encoding failed: %s\n", PB_GET_ERROR(&output));
return false;
}
-
- /* We signal the end of request with a 0 tag. */
- pb_write(&output, &zero, 1);
}
/* Read back the response from server */
@@ -90,7 +86,7 @@ bool listdir(int fd, char *path)
* filenames as they arrive. */
response.file.funcs.decode = &printfile_callback;
- if (!pb_decode(&input, ListFilesResponse_fields, &response))
+ if (!pb_decode_delimited(&input, ListFilesResponse_fields, &response))
{
fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&input));
return false;
diff --git a/examples/network_server/server.c b/examples/network_server/server.c
index 46a5f38..f500dcd 100644
--- a/examples/network_server/server.c
+++ b/examples/network_server/server.c
@@ -50,6 +50,10 @@ bool listdir_callback(pb_ostream_t *stream, const pb_field_t *field, void * cons
return false;
}
+ /* Because the main program uses pb_encode_delimited(), this callback will be
+ * called twice. Rewind the directory for the next call. */
+ rewinddir(dir);
+
return true;
}
@@ -66,7 +70,7 @@ void handle_connection(int connfd)
ListFilesRequest request = {};
pb_istream_t input = pb_istream_from_socket(connfd);
- if (!pb_decode(&input, ListFilesRequest_fields, &request))
+ if (!pb_decode_delimited(&input, ListFilesRequest_fields, &request))
{
printf("Decode failed: %s\n", PB_GET_ERROR(&input));
return;
@@ -98,7 +102,7 @@ void handle_connection(int connfd)
response.file.arg = directory;
}
- if (!pb_encode(&output, ListFilesResponse_fields, &response))
+ if (!pb_encode_delimited(&output, ListFilesResponse_fields, &response))
{
printf("Encoding failed: %s\n", PB_GET_ERROR(&output));
}
diff --git a/pb_decode.c b/pb_decode.c
index 4a65758..391d463 100644
--- a/pb_decode.c
+++ b/pb_decode.c
@@ -1032,6 +1032,12 @@ bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *
return status;
}
+bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct)
+{
+ /* This behaviour will be separated in nanopb-0.4.0, see issue #278. */
+ return pb_decode(stream, fields, dest_struct);
+}
+
#ifdef PB_ENABLE_MALLOC
/* Given an oneof field, if there has already been a field inside this oneof,
* release it before overwriting with a different one. */
diff --git a/pb_decode.h b/pb_decode.h
index 4fe7995..d51ce39 100644
--- a/pb_decode.h
+++ b/pb_decode.h
@@ -85,6 +85,13 @@ bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *des
*/
bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
+/* Same as pb_decode, except allows the message to be terminated with a null byte.
+ * NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour
+ * is not supported in most other protobuf implementations, so pb_decode_delimited()
+ * is a better option for compatibility.
+ */
+bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
+
#ifdef PB_ENABLE_MALLOC
/* Release any allocated pointer fields. If you use dynamic allocation, you should
* call this for any successfully decoded message when you are done with it. If
diff --git a/pb_encode.c b/pb_encode.c
index 2ff8f1d..e957d42 100644
--- a/pb_encode.c
+++ b/pb_encode.c
@@ -511,6 +511,16 @@ bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const
return pb_encode_submessage(stream, fields, src_struct);
}
+bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct)
+{
+ const pb_byte_t zero = 0;
+
+ if (!pb_encode(stream, fields, src_struct))
+ return false;
+
+ return pb_write(stream, &zero, 1);
+}
+
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct)
{
pb_ostream_t stream = PB_OSTREAM_SIZING;
diff --git a/pb_encode.h b/pb_encode.h
index d18a72d..8bf78dd 100644
--- a/pb_encode.h
+++ b/pb_encode.h
@@ -71,6 +71,12 @@ bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_
*/
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
+/* Same as pb_encode, but appends a null byte to the message for termination.
+ * NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited()
+ * is a better option for compatibility.
+ */
+bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
+
/* Encode the message to get the size of the encoded data, but do not store
* the data. */
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct);