Home | History | Annotate | Download | only in network_server
      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