1 /* This is a simple TCP client that connects to port 1234 and prints a list
2 * of files in a given directory.
3 *
4 * It directly deserializes and serializes messages from network, minimizing
5 * memory use.
6 *
7 * For flexibility, this example is implemented using posix api.
8 * In a real embedded system you would typically use some other kind of
9 * a communication and filesystem layer.
10 */
11
12 #include <sys/socket.h>
13 #include <sys/types.h>
14 #include <netinet/in.h>
15 #include <unistd.h>
16 #include <dirent.h>
17 #include <stdio.h>
18 #include <string.h>
19
20 #include <pb_encode.h>
21 #include <pb_decode.h>
22
23 #include "fileproto.pb.h"
24 #include "common.h"
25
printfile_callback(pb_istream_t * stream,const pb_field_t * field,void ** arg)26 bool printfile_callback(pb_istream_t *stream, const pb_field_t *field, void **arg)
27 {
28 FileInfo fileinfo;
29
30 if (!pb_decode(stream, FileInfo_fields, &fileinfo))
31 return false;
32
33 printf("%-10lld %s\n", (long long)fileinfo.inode, fileinfo.name);
34
35 return true;
36 }
37
listdir(int fd,char * path)38 bool listdir(int fd, char *path)
39 {
40 ListFilesRequest request;
41 ListFilesResponse response;
42 pb_istream_t input = pb_istream_from_socket(fd);
43 pb_ostream_t output = pb_ostream_from_socket(fd);
44 uint8_t zero = 0;
45
46 if (path == NULL)
47 {
48 request.has_path = false;
49 }
50 else
51 {
52 request.has_path = true;
53 if (strlen(path) + 1 > sizeof(request.path))
54 {
55 fprintf(stderr, "Too long path.\n");
56 return false;
57 }
58
59 strcpy(request.path, path);
60 }
61
62 if (!pb_encode(&output, ListFilesRequest_fields, &request))
63 {
64 fprintf(stderr, "Encoding failed.\n");
65 return false;
66 }
67
68 /* We signal the end of request with a 0 tag. */
69 pb_write(&output, &zero, 1);
70
71 response.file.funcs.decode = &printfile_callback;
72
73 if (!pb_decode(&input, ListFilesResponse_fields, &response))
74 {
75 fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&input));
76 return false;
77 }
78
79 if (response.path_error)
80 {
81 fprintf(stderr, "Server reported error.\n");
82 return false;
83 }
84
85 return true;
86 }
87
main(int argc,char ** argv)88 int main(int argc, char **argv)
89 {
90 int sockfd;
91 struct sockaddr_in servaddr;
92 char *path = NULL;
93
94 if (argc > 1)
95 path = argv[1];
96
97 sockfd = socket(AF_INET, SOCK_STREAM, 0);
98
99 memset(&servaddr, 0, sizeof(servaddr));
100 servaddr.sin_family = AF_INET;
101 servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
102 servaddr.sin_port = htons(1234);
103
104 if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0)
105 {
106 perror("connect");
107 return 1;
108 }
109
110 if (!listdir(sockfd, path))
111 return 2;
112
113 close(sockfd);
114
115 return 0;
116 }
117