Ejemplo n.º 1
0
void read_handler(aeEventLoop *el, int fd, void *privdata, int mask)
{
	int err;
	int nread;
	(void) mask;
	char buf[BUF_SIZE]={0};
	struct request *req = (struct request*)privdata;

	nread = read(fd, buf, BUF_SIZE);

	if (nread < 1) {
		request_free(req);
		aeDeleteFileEvent(el, fd, AE_WRITABLE);
		aeDeleteFileEvent(el, fd, AE_READABLE);
		close(fd);
		_clicount--;
		return;
	} else {
		request_append(req, buf, nread);
		err = request_parse(req);
		if (err == -1) {
			request_free(req);
			aeDeleteFileEvent(el, fd, AE_WRITABLE);
			aeDeleteFileEvent(el, fd, AE_READABLE);
			close(fd);
			_clicount--;
			return;
		}

		if (err == 1) {
			_process_cmd(fd, req);
			request_clean(req);
		}
	}
}
Ejemplo n.º 2
0
/*
 * Core function to append messages to a mailbox.
 */
static int
ifcore_append(lua_State *lua)
{
	int r;

	if (lua_gettop(lua) != 5)
		luaL_error(lua, "wrong number of arguments");
	luaL_checktype(lua, 1, LUA_TLIGHTUSERDATA);
	luaL_checktype(lua, 2, LUA_TSTRING);
	luaL_checktype(lua, 3, LUA_TSTRING);
	if (lua_type(lua, 4) != LUA_TNIL)
		luaL_checktype(lua, 4, LUA_TSTRING);
	if (lua_type(lua, 5) != LUA_TNIL)
		luaL_checktype(lua, 5, LUA_TSTRING);

	while ((r = request_append((session *)(lua_topointer(lua, 1)),
	    lua_tostring(lua, 2), lua_tostring(lua, 3),
#if LUA_VERSION_NUM < 502
	    lua_objlen(lua, 3),
#else
	    lua_rawlen(lua, 3),
#endif
	    lua_type(lua, 4) == LUA_TSTRING ?
	    lua_tostring(lua, 4) : NULL, lua_type(lua, 5) == LUA_TSTRING ?
	    lua_tostring(lua, 5) : NULL)) == STATUS_NONE);

	lua_pop(lua, lua_gettop(lua));

	if (r == -1)
		return 0;

	lua_pushboolean(lua, (r == STATUS_OK));

	return 1;
}
Ejemplo n.º 3
0
/*
 * Core function to append messages to a mailbox.
 */
static int
ifcore_append(lua_State *lua)
{
	const char *s, *u, *p;
	int r;

	if (lua_gettop(lua) != 5)
		luaL_error(lua, "wrong number of arguments");

	luaL_checktype(lua, 1, LUA_TTABLE);
	luaL_checktype(lua, 2, LUA_TSTRING);
	luaL_checktype(lua, 3, LUA_TSTRING);
	if (lua_type(lua, 4) != LUA_TNIL)
		luaL_checktype(lua, 4, LUA_TSTRING);
	if (lua_type(lua, 5) != LUA_TNIL)
		luaL_checktype(lua, 5, LUA_TSTRING);

	lua_pushvalue(lua, 1);
	if (!(s = get_table_string("server")))
		luaL_error(lua, "no mail server specified");
	if (!(u = get_table_string("username")))
		luaL_error(lua, "no username specified");
	p = DISCOVER_PORT(get_table_string("port"), get_table_string("ssl"));
	lua_pop(lua, 1);

	r = request_append(s, p, u, lua_tostring(lua, 2), lua_tostring(lua, 3),
#if LUA_VERSION_NUM < 502
	    lua_objlen(lua, 3),
#else
	    lua_rawlen(lua, 3),
#endif
	    lua_type(lua, 4) == LUA_TSTRING ?
	    lua_tostring(lua, 4) : NULL, lua_type(lua, 5) == LUA_TSTRING ?
	    lua_tostring(lua, 5) : NULL);

	lua_pop(lua, lua_gettop(lua));

	lua_pushboolean(lua, (r == STATUS_RESPONSE_OK));

	return 1;
}
Ejemplo n.º 4
0
int parseRequest(int client, request_t* req, response_t* resp)
{
        enum {
                REQ_METHOD,
                REQ_PATH,
                REQ_HTTPVERSION,
                REQ_ARGS_NAME,
                REQ_ARGS_VALUE,
                REQ_REQLINE_LF,
                REQ_HEADER_NAME,
                REQ_HEADER_VALUE_START,
                REQ_HEADER_VALUE,
                REQ_HEADER_LF,
                REQ_HEADERS_END_LF,
                REQ_BODY,
        };

#define BUFLEN 512
        int state = REQ_METHOD;
        char buffer[BUFLEN];
        int count = 0;
        char c;
        int r;
        pair_t* p;

        while (1) {

                if (state == REQ_BODY)
                        break;
                
                r = read(client, &c, 1);
                
                if (r == 0) {
                        if (state == REQ_BODY)
                                return 0;
                        else {
                                log_err("Daemon: Unexpected end of request");
                                resp->status = 400;
                                return -1;
                        }
                }
                if (r == -1) {
                        log_err("Daemon: Failed to parse the request");
                        resp->status = 400;
                        return -1;
                }
                
                switch (state) {

                case REQ_METHOD: 
                        if (c == ' ') {
                                buffer[count] = 0;
                                if (strcmp(buffer, "GET") == 0)
                                        req->method = HTTP_GET;
                                else if (strcmp(buffer, "PUT") == 0)
                                        req->method = HTTP_PUT;
                                else if (strcmp(buffer, "POST") == 0)
                                        req->method = HTTP_POST;
                                else
                                        req->method = HTTP_UNKNOWN;
                                count = 0;
                                state = REQ_PATH;

                        } else if ((c == '\r') || (c == '\n')) {
                                log_warn("Daemon: Bad request: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                                
                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;

                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Request line too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;

                case REQ_PATH: 
                        if (c == ' ') {
                                buffer[count++] = 0;
                                req->path = (char *)malloc(count);
                                if (req->path == NULL) {
                                        log_err("Out of memory");
                                        return -1;
                                }
                                memcpy(req->path, buffer, count);
                                count = 0;
                                state = REQ_HTTPVERSION;

                        } else if (c == '?') {
                                buffer[count++] = 0;
                                req->path = (char *) malloc(count);
                                memcpy(req->path, buffer, count);
                                count = 0;
                                state = REQ_ARGS_NAME;

                        } else if ((c == '\r') || (c == '\n')) {
                                log_warn("Daemon: Bad request: %s\n", buffer);
                                resp->status = 400;
                                return -1;

                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;
                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Requested path too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;

                case REQ_ARGS_NAME: 
                        if (c == ' ') {
                                buffer[count++] = 0;
                                count = 0;
                                p = new_pair_dup(buffer, NULL);
                                req->args = list_append(req->args, p);
                                state = REQ_HTTPVERSION;
                                
                        } else if (c == '=') {
                                buffer[count++] = 0;
                                count = 0;
                                p = new_pair_dup(buffer, NULL);
                                state = REQ_ARGS_VALUE;

                        } else if (c == '&') {
                                buffer[count++] = 0;
                                count = 0;
                                p = new_pair_dup(buffer, NULL);
                                req->args = list_append(req->args, p);
                                state = REQ_ARGS_NAME;

                        } else if ((c == '\r') || (c == '\n')) {
                                log_warn("Daemon: Bad request: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;
                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Requested path too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;

                case REQ_ARGS_VALUE: 
                        if (c == ' ') {
                                if (count > 0) {
                                        buffer[count++] = 0;
                                        count = 0;
                                        p->value = strdup(buffer);
                                        if (p->value == NULL) {
                                                log_err("Out of memory");
                                        }
                                } else {
                                        log_warn("Args: missing value for name: %s\n", p->name);
                                        p->value = NULL;
                                        buffer[count++] = 0;
                                        count = 0;
                                }
                                req->args = list_append(req->args, p);
                                state = REQ_HTTPVERSION;
                                
                        } else if (c == '&') {
                                if (count > 0) {
                                        buffer[count++] = 0;
                                        count = 0;
                                        p->value = strdup(buffer);
                                        if (p->value == NULL) {
                                                log_err("Out of memory");
                                        }
                                } else {
                                        log_warn("Args: missing value for name: %s\n", p->name);
                                        p->value = NULL;
                                        buffer[count++] = 0;
                                        count = 0;
                                }
                                req->args = list_append(req->args, p);
                                state = REQ_ARGS_NAME;

                        } else if ((c == '\r') || (c == '\n')) {
                                log_warn("Daemon: Bad request: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;
                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Requested path too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;

                case REQ_HTTPVERSION: 
                        if (c == '\n') {
                                buffer[count] = 0;
                                // check HTTP version? Not needed in this app...
                                count = 0;
                                state = REQ_HEADER_NAME;
                        } else if (c == '\r') {
                                buffer[count] = 0;
                                // check HTTP version? Not needed in this app...
                                count = 0;
                                state = REQ_REQLINE_LF;
                        } else if (strchr("HTTP/1.0", c) == NULL) {
                                log_warn("Daemon: Invalid HTTP version string\n");
                                resp->status = 400;
                                return -1;
                        } else {
                                buffer[count++] = (char) c;
                        }
                        break;

                case REQ_REQLINE_LF: 
                        if (c != '\n') {
                                log_warn("Daemon: Invalid HTTP version string\n");
                                resp->status = 400;
                                return -1;
                        } else {
                                count = 0;
                                state = REQ_HEADER_NAME;
                        }
                        break;

                case REQ_HEADER_NAME: 
                        if ((c == '\n') && (count == 0)) {
                                state = REQ_BODY;
                                
                        } else if ((c == '\r') && (count == 0)) {
                                state = REQ_HEADERS_END_LF;
                                
                        } else if (c == ':') {
                                buffer[count++] = 0;
                                count = 0;
                                p = new_pair_dup(buffer, NULL);
                                state = REQ_HEADER_VALUE_START;

                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;

                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Header name too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;

                case REQ_HEADER_VALUE_START: 
                        if ((c == ' ') || (c == '\t')) {
                                // Do nothing

                        } else if (c == '\r') {
                                log_warn("Daemon: Bad header: %s\n", p->name);
                                resp->status = 400;
                                return -1;

                        } else if (c == '\n') {
                                log_warn("Daemon: Bad header: %s\n", p->name);
                                resp->status = 400;
                                return -1;
                                
                        } else if (count < BUFLEN-1) {
                                buffer[0] = (char) c;
                                count = 1;
                                state = REQ_HEADER_VALUE;
                        }
                        break;

                case REQ_HEADER_VALUE: 
                        if (c == '\r') {
                                buffer[count++] = 0;
                                count = 0;
                                p->value = strdup(buffer);
                                req->headers = list_append(req->headers, p);
                                state = REQ_HEADER_LF;

                        } else if (c == '\n') {
                                buffer[count++] = 0;
                                count = 0;
                                p->value = strdup(buffer);
                                req->headers = list_append(req->headers, p);
                                state = REQ_HEADER_NAME;
                                
                        } else if (count < BUFLEN-1) {
                                buffer[count++] = (char) c;

                        } else {
                                buffer[BUFLEN-1] = 0;
                                log_warn("Daemon: Header value too long: %s\n", buffer);
                                resp->status = 400;
                                return -1;
                        }
                        break;
 
                case REQ_HEADER_LF: 
                        if (c != '\n') {
                                log_warn("Daemon: Invalid HTTP header\n");
                                resp->status = 400;
                                return -1;
                        } else {
                                count = 0;
                                state = REQ_HEADER_NAME;
                        }
                        break;

                case REQ_HEADERS_END_LF: 
                        if (c != '\n') {
                                log_warn("Daemon: Invalid HTTP header\n");
                                resp->status = 400;
                                return -1;
                        } else {
                                count = 0;
                                state = REQ_BODY;
                        }
                        break;
                }
       }

        r = path_parse(req->path, &req->pathnodes);
        if (r != 0) {
                resp->status = 400;
                return -1;
        }

        int content_length = request_content_length(req);
        if (content_length == -1) {
                log_err("Failed to determine the content length");
                resp->status = 400;
                return -1;
        }

        for (int i = 0; i < content_length; i++) {
                r = read(client, &c, 1);
                if (request_append(req, c) != 0)
                        return -1;
        }

        return 0;
}