1 /* This is a simple TCP server that listens on port 1234 and provides lists 2 * of files to clients, using a protocol defined in file_server.proto. 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 26 bool listdir_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) 27 { 28 DIR *dir = (DIR*) *arg; 29 struct dirent *file; 30 FileInfo fileinfo; 31 32 while ((file = readdir(dir)) != NULL) 33 { 34 fileinfo.inode = file->d_ino; 35 strncpy(fileinfo.name, file->d_name, sizeof(fileinfo.name)); 36 fileinfo.name[sizeof(fileinfo.name) - 1] = '\0'; 37 38 if (!pb_encode_tag_for_field(stream, field)) 39 return false; 40 41 if (!pb_encode_submessage(stream, FileInfo_fields, &fileinfo)) 42 return false; 43 } 44 45 return true; 46 } 47 48 void handle_connection(int connfd) 49 { 50 ListFilesRequest request; 51 ListFilesResponse response; 52 pb_istream_t input = pb_istream_from_socket(connfd); 53 pb_ostream_t output = pb_ostream_from_socket(connfd); 54 DIR *directory; 55 56 if (!pb_decode(&input, ListFilesRequest_fields, &request)) 57 { 58 printf("Decode failed: %s\n", PB_GET_ERROR(&input)); 59 return; 60 } 61 62 directory = opendir(request.path); 63 64 printf("Listing directory: %s\n", request.path); 65 66 if (directory == NULL) 67 { 68 perror("opendir"); 69 70 response.has_path_error = true; 71 response.path_error = true; 72 response.file.funcs.encode = NULL; 73 } 74 else 75 { 76 response.has_path_error = false; 77 response.file.funcs.encode = &listdir_callback; 78 response.file.arg = directory; 79 } 80 81 if (!pb_encode(&output, ListFilesResponse_fields, &response)) 82 { 83 printf("Encoding failed.\n"); 84 } 85 } 86 87 int main(int argc, char **argv) 88 { 89 int listenfd, connfd; 90 struct sockaddr_in servaddr; 91 int reuse = 1; 92 93 listenfd = socket(AF_INET, SOCK_STREAM, 0); 94 95 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); 96 97 memset(&servaddr, 0, sizeof(servaddr)); 98 servaddr.sin_family = AF_INET; 99 servaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 100 servaddr.sin_port = htons(1234); 101 if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0) 102 { 103 perror("bind"); 104 return 1; 105 } 106 107 if (listen(listenfd, 5) != 0) 108 { 109 perror("listen"); 110 return 1; 111 } 112 113 for(;;) 114 { 115 connfd = accept(listenfd, NULL, NULL); 116 117 if (connfd < 0) 118 { 119 perror("accept"); 120 return 1; 121 } 122 123 printf("Got connection.\n"); 124 125 handle_connection(connfd); 126 127 printf("Closing connection.\n"); 128 129 close(connfd); 130 } 131 } 132