Пример #1
0
/* See section 4.2 of RFC 2616 for header format. */
int http_parse_header(struct http_header **result, const char *header)
{
    const char *p, *q;
    size_t value_len, value_offset;
    struct http_header *node, **prev;

    *result = NULL;
    prev = result;

    p = header;
    while (*p != '\0' && !is_crlf(p)) {
        /* Get the field name. */
        q = p;
        while (*q != '\0' && is_token_char(*q))
            q++;
        if (*q != ':') {
            http_header_free(*result);
            return 400;
        }

        node = (struct http_header *) safe_malloc(sizeof(*node));
        node->name = mkstr(p, q);
        node->value = NULL;
        node->next = NULL;
        value_len = 0;
        value_offset = 0;

        /* Copy the header field value until we hit a CRLF. */
        p = q + 1;
        p = skip_lws(p);
        for (;;) {
            q = p;
            while (*q != '\0' && !is_space_char(*q) && !is_crlf(q)) {
                /* Section 2.2 of RFC 2616 disallows control characters. */
                if (iscntrl((int) (unsigned char) *q)) {
                    http_header_node_free(node);
                    return 400;
                }
                q++;
            }
            strbuf_append(&node->value, &value_len, &value_offset, p, q - p);
            p = skip_lws(q);
            if (is_crlf(p))
                break;
            /* Replace LWS with a single space. */
            strbuf_append_str(&node->value, &value_len, &value_offset, " ");
        }
        *prev = node;
        prev = &node->next;

        p = skip_crlf(p);
    }

    return 0;
}
Пример #2
0
/* Returns 0 on success and nonzero on failure. */
int http_parse_status_line(const char *line, struct http_response *response)
{
    const char *p, *q;

    http_response_init(response);

    /* Version. */
    p = parse_http_version(line, &response->version);
    if (p == line)
        return -1;
    while (*p == ' ')
        p++;

    /* Status code. */
    errno = 0;
    response->code = parse_long(p, (char **) &q);
    if (errno != 0 || q == p)
        return -1;
    p = q;

    /* Reason phrase. */
    while (*p == ' ')
        p++;
    q = p;
    while (!is_crlf(q))
        q++;
    /* We expect that the CRLF ends the string. */
    if (*skip_crlf(q) != '\0')
        return -1;
    response->phrase = mkstr(p, q);

    return 0;
}
Пример #3
0
int http_read_header(struct socket_buffer *buf, char **result)
{
    char *line = NULL;
    char *header;
    size_t n = 0;
    size_t count;
    int blank;

    header = NULL;

    do {
        line = socket_buffer_readline(buf, &count, MAX_HEADER_LENGTH);
        if (line == NULL) {
            free(header);
            if (n >= MAX_HEADER_LENGTH)
                /* Request Entity Too Large. */
                return 413;
            else
                return 400;
        }
        blank = is_crlf(line);

        if (n + count >= MAX_HEADER_LENGTH) {
            free(line);
            free(header);
            /* Request Entity Too Large. */
            return 413;
        }

        header = (char *) safe_realloc(header, n + count + 1);
        memcpy(header + n, line, count);
        n += count;
        free(line);
    } while (!blank);
    header[n] = '\0';

    *result = header;

    return 0;
}
Пример #4
0
int http_read_request_line(struct socket_buffer *buf, char **line)
{
    size_t n;

    *line = NULL;

    /* Section 4.1 of RFC 2616 says "servers SHOULD ignore any empty line(s)
       received where a Request-Line is expected." */
    do {
        free(*line);
        *line = socket_buffer_readline(buf, &n, MAX_REQUEST_LINE_LENGTH);
        if (*line == NULL) {
            if (n >= MAX_REQUEST_LINE_LENGTH)
                /* Request Entity Too Large. */
                return 413;
            else
                return 400;
        }
    } while (is_crlf(*line));

    return 0;
}
Пример #5
0
Файл: server.c Проект: chfr/sow
int main(/*int argc, char *argv[]*/) {
	INFO("Started\n");
	int server_socket, client_socket, port, res, client_len, n;
	struct sockaddr_in srv_addr, client_addr;
	int iSetOption = 1;

	port = SRVPORT;

	server_socket = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&iSetOption,
        sizeof(iSetOption));
        
	if (server_socket < 0) {
		ERROR("Error opening socket\n");
		IFERROR(perror(""));
	}
	INFO("Made server socket\n");

	memset((char *) &srv_addr, 0, sizeof(srv_addr));
	
	srv_addr.sin_family = AF_INET;
	srv_addr.sin_port = htons(port);
	srv_addr.sin_addr.s_addr = INADDR_ANY;

	while ((res = bind(server_socket,
			   (struct sockaddr *) &srv_addr,
			   sizeof(srv_addr))) < 0) {
		ERROR("Error binding socket\n");
		IFERROR(perror(""));
	}

	listen(server_socket, 5);
	INFO("Listening on port %d\n", port);

	client_len = sizeof(client_addr);

	if (chdir("content")) {
		ERROR("Could not chdir to the content directory\n");
		IFERROR(perror(""));
		exit(1);
	}

	do {
		client_socket = accept(server_socket,
							   (struct sockaddr *) &client_addr,
							   (socklen_t *) &client_len);

		INFO("Accepted client socket\n");

		if (client_socket < 0) {
			ERROR("Error on client accept\n");
			IFERROR(perror(""));
		}

		request *req = request_new();
		char line[MAXLEN];

		while ((n = fd_readline(client_socket, line, MAXLEN)) > 0) {
			if (n == MAXLEN-1 && line[MAXLEN-1] != '\n') {
				WARN("Line length exceeded MAXLEN %d\n", MAXLEN);
				char c;
				int dropped = 0;
				while ((n = read(client_socket, &c, 1)) > 0) {
					dropped += 1;
					if (c == '\n')
						break;
				}
				WARN("Skipped to the next line, dropped %d characters\n", dropped);	
			}

			if (is_crlf(line)) { // We've reached the end of the headers
				int left_to_read = request_get_content_length(req);
				int total_read = 0, len;
				
				if (left_to_read > 0) {
					DEBUG("There's %d chars of body to read\n", left_to_read);
					// There's a Content-Length so there must be a body
					req->body = malloc(sizeof(char) * (left_to_read+1));
					
					len = MAXLEN < left_to_read ? MAXLEN : left_to_read;
					len += 1;
					
					while (left_to_read && (n = fd_readline(client_socket, line, len)) > 0) {
						DEBUG("Read %d characters of body: %s\n", n, line);
						strcpy(&req->body[total_read], line);
						total_read += n;
						left_to_read -= n;
						DEBUG("total_read: %d, left_to_read: %d\n", total_read, left_to_read);
						len = MAXLEN < left_to_read ? MAXLEN : left_to_read;
					}
					req->body[total_read+1] = '\0';
					DEBUG("Done reading body in %d chars:\n", total_read);
					DEBUG("%s\n", req->body);
					respond(&req, client_socket);
					continue;
				} else {
					DEBUG("No body to read, generating response\n");
					respond(&req, client_socket);
					continue;
				}
			}

			if (request_parse(req, line)) {
				WARN("An error occurred while parsing the previous line\n");
			}
		}
		DEBUG("Done with this request! n = %d\n", n);
	} while (1);

	close(server_socket);
	close(client_socket);

	return 0;
}