17ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen/* This is a simple TCP client that connects to port 1234 and prints a list 27ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * of files in a given directory. 37ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * 47ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * It directly deserializes and serializes messages from network, minimizing 57ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * memory use. 67ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * 77ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * For flexibility, this example is implemented using posix api. 87ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * In a real embedded system you would typically use some other kind of 97ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen * a communication and filesystem layer. 107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen */ 117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <sys/socket.h> 137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <sys/types.h> 147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <netinet/in.h> 157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <unistd.h> 167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <dirent.h> 177ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <stdio.h> 187ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <string.h> 197ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 207ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <pb_encode.h> 217ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include <pb_decode.h> 227ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 237ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "fileproto.pb.h" 247ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen#include "common.h" 257ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 267ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool printfile_callback(pb_istream_t *stream, const pb_field_t *field, void **arg) 277ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 287ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen FileInfo fileinfo; 297ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 307ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_decode(stream, FileInfo_fields, &fileinfo)) 317ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 327ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 337ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen printf("%-10lld %s\n", (long long)fileinfo.inode, fileinfo.name); 347ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 357ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 367ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 377ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 387ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenbool listdir(int fd, char *path) 397ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 407ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen ListFilesRequest request; 417ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen ListFilesResponse response; 427ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_istream_t input = pb_istream_from_socket(fd); 437ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_ostream_t output = pb_ostream_from_socket(fd); 447ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen uint8_t zero = 0; 457ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 467ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (path == NULL) 477ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 487ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen request.has_path = false; 497ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 507ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen else 517ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 527ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen request.has_path = true; 537ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (strlen(path) + 1 > sizeof(request.path)) 547ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 557ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen fprintf(stderr, "Too long path.\n"); 567ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 577ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 587ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 597ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen strcpy(request.path, path); 607ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 617ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 627ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_encode(&output, ListFilesRequest_fields, &request)) 637ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 647ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen fprintf(stderr, "Encoding failed.\n"); 657ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 667ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 677ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 687ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen /* We signal the end of request with a 0 tag. */ 697ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen pb_write(&output, &zero, 1); 707ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 717ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen response.file.funcs.decode = &printfile_callback; 727ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 737ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!pb_decode(&input, ListFilesResponse_fields, &response)) 747ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 757ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen fprintf(stderr, "Decode failed: %s\n", PB_GET_ERROR(&input)); 767ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 777ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 787ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 797ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (response.path_error) 807ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 817ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen fprintf(stderr, "Server reported error.\n"); 827ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return false; 837ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 847ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 857ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return true; 867ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 877ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 887ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohenint main(int argc, char **argv) 897ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen{ 907ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen int sockfd; 917ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen struct sockaddr_in servaddr; 927ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen char *path = NULL; 937ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 947ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (argc > 1) 957ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen path = argv[1]; 967ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 977ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen sockfd = socket(AF_INET, SOCK_STREAM, 0); 987ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 997ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen memset(&servaddr, 0, sizeof(servaddr)); 1007ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen servaddr.sin_family = AF_INET; 1017ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1027ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen servaddr.sin_port = htons(1234); 1037ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1047ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) != 0) 1057ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen { 1067ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen perror("connect"); 1077ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return 1; 1087ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen } 1097ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1107ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen if (!listdir(sockfd, path)) 1117ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return 2; 1127ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1137ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen close(sockfd); 1147ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen 1157ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen return 0; 1167ef855e462b9a18b7d330e4b40f350164a6ad9daEtan Cohen} 117