2 * rs-serve - (c) 2013 Niklas E. Cathor
4 * This program is distributed in the hope that it will be useful,
5 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7 * GNU Affero General Public License for more details.
9 * You should have received a copy of the GNU Affero General Public License
10 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 void start_storage_process(uid_t uid, int initial_fd, char *initial_buf, int initial_buf_len) {
16 struct rs_process_info *storage_process = malloc(sizeof(struct rs_process_info));
17 if(storage_process == NULL) {
18 log_error("malloc() failed: %s", strerror(errno));
21 storage_process->uid = uid;
22 if(start_process(storage_process, storage_main,
23 initial_fd, initial_buf, initial_buf_len) != 0) {
24 free(storage_process);
29 static char *my_strtok(char *string, char *delim, char **saveptr) {
30 char *ptr = string ? string : *saveptr, *dp;
32 if(*delim == 0) { // empty delimiter => return entire string.
33 log_debug("returning start: %s", start);
36 for(;*ptr != 0; ptr++) {
37 for(dp = delim; *dp != 0; dp++) {
40 log_debug("found newline, previous char is: %d (%d)", *(ptr - 1), '\r');
51 int dispatch_request(struct evbuffer *buffer, int fd) {
52 size_t buf_len = evbuffer_get_length(buffer);
53 char *buf = malloc(buf_len + 1);
55 log_error("malloc() failed: %s", strerror(errno));
58 evbuffer_remove(buffer, buf, buf_len);
59 buf[buf_len] = 0; // terminate string.
63 log_debug("Got data buf (%d): %s", buf_len, buf);
66 char *verb = my_strtok(buf, " ", &saveptr);
67 saveptr++; // skip initial slash
68 char *username = my_strtok(NULL, "/ ", &saveptr);
69 char *file_path = my_strtok(NULL, " ", &saveptr);
70 char *http_version = my_strtok(NULL, "\r", &saveptr);
72 char *rest = my_strtok(NULL, "", &saveptr);
74 log_debug("verb: %s\nusername: %s\nfile_path: %s\nhttp_version: %s\nrest: %s", verb, username, file_path, http_version, rest);
75 if(verb == NULL || username == NULL || file_path == NULL ||
76 http_version == NULL) {
77 //log_debug("verb: %s, username: %s, file_path: %s, http_version: %s, rest: %s", verb, username, file_path, http_version);
81 if(strncmp(http_version, "HTTP/1.", 7) != 0) {
82 log_error("Invalid request (HTTP version specified as \"%s\")", http_version);
86 /* log_debug("Parsed something. Let's see:\n verb: %s\n username: %s\n path: %s\n http version: %s\n rest: %s", */
87 /* verb, username, file_path, http_version, rest); */
89 uid_t uid = user_get_uid(username);
92 // TODO: send 404 response here
93 log_error("User not found: %s", username);
96 } else if(uid == -2) {
97 // TODO: send 500 response here
98 log_error("Failed to get uid for user: %s", username);
103 // TODO: add check for UID > MIN_UID
104 // (we don't want to fork storage workers for system users)
106 // rewrite first line to only include file path
108 int new_len = sprintf(buf, "%s /%s %s\r\n%s", verb, file_path, http_version, rest);
109 log_debug("reallocating to %d bytes", new_len + 1);
110 buf = realloc(buf, new_len + 1);
112 log_error("BUG: realloc() failed to shrink buffer from %d to %d bytes: %s",
113 buf_len + 1, new_len + 1, strerror(errno));
117 struct rs_process_info *storage_process = process_find_uid(uid);
118 if(storage_process == NULL) {
119 start_storage_process(uid, fd, buf, buf_len + 1);
121 send_fd_to_process(storage_process, fd, buf, buf_len + 1);