bec2f11b4ea5a110231c9a5eca71d4f0b2e93874
[reposerve] / server / src / client.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include "client.h"
6 #include "proto.h"
7 #include "repo.h"
8
9 static int proc_request(struct client *c);
10 static int proc_flist(struct client *c, char *data, int datasz);
11 static int proc_push(struct client *c, char *data, int datasz);
12 static int proc_pull(struct client *c, char *data, int datasz);
13
14 const char *repo_path;
15
16 int handle_client(struct client *c)
17 {
18         char buf[512];
19         int sz, left;
20
21         while((sz = read(c->s, buf, sizeof buf)) > 0) {
22                 left = sizeof c->buf - c->bsz;
23                 if(sz > left) sz = left;
24                 memcpy(c->buf + c->bsz, buf, sz);
25                 c->bsz += sz;
26         }
27
28         if(proc_request(c) == -1) {
29                 return -1;
30         }
31         return 0;
32 }
33
34 static int proc_request(struct client *c)
35 {
36         char *endp = c->buf;
37         char *reqdata;
38         int reqdata_len;
39
40         while(endp < c->buf + c->bsz) {
41                 if(*endp == '\n') break;
42         }
43         if(endp >= c->buf + c->bsz) {
44                 return 0;
45         }
46         *endp = 0;
47
48         reqdata = endp + 1;
49         reqdata_len = c->bsz - (reqdata - c->buf);
50
51         c->bsz = 0;
52
53         if(strcmp(c->buf, "flist") == 0) {
54                 return proc_flist(c, reqdata, reqdata_len);
55         } else if(strcmp(c->buf, "push") == 0) {
56                 return proc_push(c, reqdata, reqdata_len);
57         } else if(strcmp(c->buf, "pull") == 0) {
58                 return proc_pull(c, reqdata, reqdata_len);
59         } else if(strcmp(c->buf, "dos") == 0) {
60                 c->flags |= CLIENT_DOS;
61                 send_ok(c, 0);
62                 return 0;
63         }
64
65         send_err(c);
66         return 0;
67 }
68
69 void send_string(struct client *c, const char *s)
70 {
71         write(c->s, s, strlen(s));
72 }
73
74 void send_ok(struct client *c, int resp_sz)
75 {
76         char buf[32];
77         sprintf(buf, "OK %d\n", resp_sz < 0 ? 0 : resp_sz);
78         send_string(c, buf);
79 }
80
81 void send_err(struct client *c)
82 {
83         send_string(c, "ERR\n");
84 }
85
86 static struct flist *gen_flist(int contents)
87 {
88         int i, count;
89         struct flist *flist;
90
91         if(!(flist = flist_create())) {
92                 return 0;
93         }
94
95         if(repo_init(repo_path) == -1) {
96                 return 0;
97         }
98         count = repo_num_files();
99
100         for(i=0; i<count; i++) {
101                 flist_add(flist, repo_file(i)->path, contents);
102         }
103         repo_cleanup();
104
105         return flist;
106 }
107
108 static int proc_flist(struct client *c, char *data, int datasz)
109 {
110         struct flist *flist;
111
112         if(!(flist = gen_flist(0))) {
113                 send_err(c);
114                 return -1;
115         }
116         flist_finalize(flist);
117
118         send_ok(c, flist->final_size);
119         write(c->s, flist->flist, flist->final_size);
120
121         flist_destroy(flist);
122         return 0;
123 }
124
125 static int proc_push(struct client *c, char *data, int datasz)
126 {
127         send_err(c);
128         return 0;
129 }
130
131 static int proc_pull(struct client *c, char *data, int datasz)
132 {
133         send_err(c);
134         return 0;
135 }