Пример #1
0
	json_call::json_call(http::context &c) 
	{
		if(c.request().content_type()!="application/json")
			throw call_error("Invalid content type"); 
		if(c.request().request_method()!="POST")
			throw call_error("Invalid request method"); 
		std::pair<void *,size_t> post_data = c.request().raw_post_data();
		std::istringstream ss(std::string(reinterpret_cast<char const *>(post_data.first),post_data.second));
		json::value request;
		if(!request.load(ss,true))
			throw call_error("Invalid JSON");
		if(	request.type("method")!=json::is_string 
			|| request.type("params")!=json::is_array
			|| request.type("id")==json::is_undefined)
		{
			throw call_error("Invalid JSON-RPC");
		}
		if(request.type("id")==json::is_null) {
			notification_ = true;
		}
		else {
			notification_ = false;
			id_.swap(request["id"]);
			params_.swap(request["params"].array());
			method_ = request.get<std::string>("method");
		}
	}
Пример #2
0
void timeout_callback(void *arg)
{
    module_data_t *mod = arg;

    asc_timer_destroy(mod->timeout_timer);
    mod->timeout_timer = NULL;

    switch(mod->is_connected)
    {
        case 0:
            call_error(mod, "connection timeout");
            break;
        case 1:
            call_error(mod, "connection failed");
            break;
        case 2:
            call_error(mod, "response timeout");
            break;
        default:
            call_error(mod, "unknown error");
            break;
    }

    on_close(mod);
}
Пример #3
0
		R call_member_impl(lua_State* L, std::false_type /*void*/, meta::index_list<Indices...>, Args&&... args)
		{
			// don't count the function and self-reference
			// since those will be popped by pcall
			int top = lua_gettop(L) - 2;

			// pcall will pop the function and self reference
			// and all the parameters

			meta::expand_calls_hack((
				specialized_converter_policy_n<Indices, PolicyList, typename unwrapped<Args>::type, cpp_to_lua>().to_lua(L, unwrapped<Args>::get(std::forward<Args>(args))), 0)...
				);

			if (pcall(L, sizeof...(Args) +1, 1))
			{
				assert(lua_gettop(L) == top + 1);
				call_error(L);
			}
			// pops the return values from the function
			stack_pop pop(L, lua_gettop(L) - top);

			specialized_converter_policy_n<0, PolicyList, R, lua_to_cpp> converter;
			if (converter.match(L, decorated_type<R>(), -1) < 0) {
				cast_error<R>(L);
			}

			return converter.to_cpp(L, decorated_type<R>(), -1);
		}
Пример #4
0
static void
read_array(ParseInfo pi, const char *key) {
    if (pi->has_array_start) {
	call_no_value(pi->handler, oj_array_start_id, key);
    }
    pi->s++;
    next_non_white(pi);
    if (']' == *pi->s) {
	pi->s++;
    } else {
	while (1) {
	    read_next(pi, 0);
	    next_non_white(pi);
	    if (',' == *pi->s) {
		pi->s++;
	    } else if (']' == *pi->s) {
		pi->s++;
		break;
	    } else {
		if (pi->has_error) {
		    call_error("invalid format, expected , or ] while in an array", pi, __FILE__, __LINE__);
		}
		raise_error("invalid format, expected , or ] while in an array", pi->str, pi->s);
	    }
	}
    }
    if (pi->has_array_end) {
	call_no_value(pi->handler, oj_array_end_id, key);
    }
}
Пример #5
0
static void
read_hash(ParseInfo pi, const char *key) {
    const char	*ks;
    
    if (pi->has_hash_start) {
	call_no_value(pi->handler, oj_hash_start_id, key);
    }
    pi->s++;
    next_non_white(pi);
    if ('}' == *pi->s) {
	pi->s++;
    } else {
	while (1) {
	    next_non_white(pi);
	    ks = read_quoted_value(pi);
	    next_non_white(pi);
	    if (':' == *pi->s) {
		pi->s++;
	    } else {
		if (pi->has_error) {
		    call_error("invalid format, expected :", pi, __FILE__, __LINE__);
		}
		raise_error("invalid format, expected :", pi->str, pi->s);
	    }
	    read_next(pi, ks);
	    next_non_white(pi);
	    if ('}' == *pi->s) {
		pi->s++;
		break;
	    } else if (',' == *pi->s) {
		pi->s++;
	    } else {
		if (pi->has_error) {
		    call_error("invalid format, expected , or } while in an object", pi, __FILE__, __LINE__);
		}
		raise_error("invalid format, expected , or } while in an object", pi->str, pi->s);
	    }
	}
    }
    if (pi->has_hash_end) {
	call_no_value(pi->handler, oj_hash_end_id, key);
    }
}
Пример #6
0
static void
read_nil(ParseInfo pi, const char *key) {
    pi->s++;
    if ('u' != *pi->s || 'l' != *(pi->s + 1) || 'l' != *(pi->s + 2)) {
	if (pi->has_error) {
	    call_error("invalid format, expected 'null'", pi, __FILE__, __LINE__);
	}
	raise_error("invalid format, expected 'null'", pi->str, pi->s);
    }
    pi->s += 3;
    if (pi->has_add_value) {
	call_add_value(pi->handler, Qnil, key);
    }
}
Пример #7
0
static void
read_false(ParseInfo pi, const char *key) {
    pi->s++;
    if ('a' != *pi->s || 'l' != *(pi->s + 1) || 's' != *(pi->s + 2) || 'e' != *(pi->s + 3)) {
	if (pi->has_error) {
	    call_error("invalid format, expected 'false'", pi, __FILE__, __LINE__);
	}
	raise_error("invalid format, expected 'false'", pi->str, pi->s);
    }
    pi->s += 4;
    if (pi->has_add_value) {
	call_add_value(pi->handler, Qfalse, key);
    }
}
Пример #8
0
static void
skip_comment(ParseInfo pi) {
    pi->s++; /* skip first / */
    if ('*' == *pi->s) {
	pi->s++;
	for (; '\0' != *pi->s; pi->s++) {
	    if ('*' == *pi->s && '/' == *(pi->s + 1)) {
		pi->s++;
		return;
	    } else if ('\0' == *pi->s) {
		if (pi->has_error) {
		    call_error("comment not terminated", pi, __FILE__, __LINE__);
		} else {
		    raise_error("comment not terminated", pi->str, pi->s);
		}
	    }
	}
    } else if ('/' == *pi->s) {
	for (; 1; pi->s++) {
	    switch (*pi->s) {
	    case '\n':
	    case '\r':
	    case '\f':
	    case '\0':
		return;
	    default:
		break;
	    }
	}
    } else {
	if (pi->has_error) {
	    call_error("invalid comment", pi, __FILE__, __LINE__);
	} else {
	    raise_error("invalid comment", pi->str, pi->s);
	}
    }
}
Пример #9
0
static uint32_t
read_hex(ParseInfo pi, char *h) {
    uint32_t	b = 0;
    int		i;

    /* TBD this can be made faster with a table */
    for (i = 0; i < 4; i++, h++) {
	b = b << 4;
	if ('0' <= *h && *h <= '9') {
	    b += *h - '0';
	} else if ('A' <= *h && *h <= 'F') {
	    b += *h - 'A' + 10;
	} else if ('a' <= *h && *h <= 'f') {
	    b += *h - 'a' + 10;
	} else {
	    pi->s = h;
	    if (pi->has_error) {
		call_error("invalid hex character", pi, __FILE__, __LINE__);
	    }
	    raise_error("invalid hex character", pi->str, pi->s);
	}
    }
    return b;
}
Пример #10
0
	void json_call::check_not_notification()
	{
		if(notification())
			throw call_error("Notification method should not return response");
	}
Пример #11
0
static void on_read(void *arg)
{
    module_data_t *mod = arg;

    asc_timer_destroy(mod->timeout_timer);
    mod->timeout_timer = NULL;

    char *buffer = mod->buffer;

    int skip = mod->ts_len_in_buf;
    int r = asc_socket_recv(mod->sock, buffer + skip, HTTP_BUFFER_SIZE - skip);
    if(r <= 0)
    {
        on_close(mod);
        return;
    }
    r += mod->ts_len_in_buf;// Imagine that we've received more (+ previous part)

    int response = 0;

    parse_match_t m[4];

    // parse response
    if(mod->ready_state == 0)
    {
        if(!http_parse_response(buffer, m))
        {
            call_error(mod, "invalid response");
            on_close(mod);
            return;
        }

        lua_newtable(lua);
        response = lua_gettop(lua);

        lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
        lua_pushvalue(lua, -2); // duplicate table
        lua_setfield(lua, -2, __response);
        lua_pop(lua, 1); // options

        lua_pushnumber(lua, atoi(&buffer[m[2].so]));
        lua_setfield(lua, response, __code);
        lua_pushlstring(lua, &buffer[m[3].so], m[3].eo - m[3].so);
        lua_setfield(lua, response, __message);

        skip = m[0].eo;
        mod->ready_state = 1;

        if(skip >= r)
        {
            lua_pop(lua, 1); // response
            return;
        }
    }

    // parse headers
    if(mod->ready_state == 1)
    {
        if(!response)
        {
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
            lua_getfield(lua, -1, __response);
            lua_remove(lua, -2);
            response = lua_gettop(lua);
        }

        int headers_count = 0;
        lua_getfield(lua, response, __headers);
        if(lua_isnil(lua, -1))
        {
            lua_pop(lua, 1);
            lua_newtable(lua);
            lua_pushvalue(lua, -1);
            lua_setfield(lua, response, __headers);
        }
        else
        {
            headers_count = luaL_len(lua, -1);
        }
        const int headers = lua_gettop(lua);

        while(skip < r && http_parse_header(&buffer[skip], m))
        {
            const size_t so = m[1].so;
            const size_t length = m[1].eo - so;
            if(!length)
            {
                skip += m[0].eo;
                mod->ready_state = 2;
                break;
            }
            const char *header = &buffer[skip + so];

            if(!strncasecmp(header, __transfer_encoding, sizeof(__transfer_encoding) - 1))
            {
                const char *val = &header[sizeof(__transfer_encoding) - 1];
                if(!strncasecmp(val, __chunked, sizeof(__chunked) - 1))
                    mod->is_chunked = 1;
            }
            else if(!strncasecmp(header, __connection, sizeof(__connection) - 1))
            {
                const char *val = &header[sizeof(__connection) - 1];
                if(!strncasecmp(val, __close, sizeof(__close) - 1))
                    mod->is_close = 1;
                else if(!strncasecmp(val, __keep_alive, sizeof(__keep_alive) - 1))
                    mod->is_keep_alive = 1;
            }
            else if(!strncasecmp(header, __content_length, sizeof(__content_length) - 1))
            {
                const char *val = &header[sizeof(__content_length) - 1];
                mod->is_content_length = 1;
                mod->chunk_left = strtoul(val, NULL, 10);
            }

            ++headers_count;
            lua_pushnumber(lua, headers_count);
            lua_pushlstring(lua, header, length);
            lua_settable(lua, headers);
            skip += m[0].eo;
        }

        lua_pop(lua, 1); // headers

        if(mod->ready_state == 2)
        {
            get_lua_callback(mod);
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
            lua_pushvalue(lua, response);
            lua_call(lua, 2, 0);

            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->__lua.oref);
            lua_pushnil(lua);
            lua_setfield(lua, -2, __response);
            lua_pop(lua, 1); // options
        }

        lua_pop(lua, 1); // response

        if(skip >= r)
            return;
    }

    // content
    if(mod->ready_state == 2)
    {
        /* Push to stream */
        if (mod->is_ts)
        {
            int pos = skip - mod->ts_len_in_buf;// buffer rewind
            while (r - pos >= TS_PACKET_SIZE)
            {
                module_stream_send(mod, (uint8_t*)&mod->buffer[pos]);
                pos += TS_PACKET_SIZE;
            }
            int left = r - pos;
            if (left > 0)
            {//there is something usefull in the end of buffer, move it to begin
                if (pos > 0) memmove(&mod->buffer[0], &mod->buffer[pos], left);
                mod->ts_len_in_buf = left;
            } else
            {//all data is processed
                mod->ts_len_in_buf = 0;
            }
        }

        // Transfer-Encoding: chunked
        else if(mod->is_chunked)
        {
            while(skip < r)
            {
                if(!mod->chunk_left)
                {
                    if(!http_parse_chunk(&buffer[skip], m))
                    {
                        call_error(mod, "invalid chunk");
                        on_close(mod);
                        return;
                    }

                    char cs_str[] = "00000000";
                    const size_t cs_size = m[1].eo - m[1].so;
                    const size_t cs_skip = 8 - cs_size;
                    memcpy(&cs_str[cs_skip], &buffer[skip], cs_size);

                    uint8_t cs_hex[4];
                    str_to_hex(cs_str, cs_hex, sizeof(cs_hex));
                    mod->chunk_left = (cs_hex[0] << 24)
                                    | (cs_hex[1] << 16)
                                    | (cs_hex[2] <<  8)
                                    | (cs_hex[3]      );
                    skip += m[0].eo;

                    if(!mod->chunk_left)
                    {
                        if(mod->is_keep_alive)
                        {
                            // keep-alive connection
                            get_lua_callback(mod);
                            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                            lua_pushstring(lua, "");
                            lua_call(lua, 2, 0);
                        }
                        else
                        {
                            // close connection
                            on_close(mod);
                        }
                        return;
                    }
                }

                const size_t r_skip = r - skip;
                get_lua_callback(mod);
                lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                if(mod->chunk_left < r_skip)
                {
                    lua_pushlstring(lua, &buffer[skip], mod->chunk_left);
                    lua_call(lua, 2, 0);
                    skip += mod->chunk_left;
                    mod->chunk_left = 0;
                    if(buffer[skip] == '\r')
                        ++skip;
                    if(buffer[skip] == '\n')
                        ++skip;
                    else
                    {
                        call_error(mod, "invalid chunk");
                        on_close(mod);
                        return;
                    }
                }
                else
                {
                    lua_pushlstring(lua, &buffer[skip], r_skip);
                    lua_call(lua, 2, 0);
                    mod->chunk_left -= r_skip;
                    break;
                }
            }
        }

        // Content-Length
        else if(mod->is_content_length)
        {
            if(mod->chunk_left > 0)
            {
                const size_t r_skip = r - skip;
                get_lua_callback(mod);
                lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                if(mod->chunk_left > r_skip)
                {
                    lua_pushlstring(lua, &buffer[skip], r_skip);
                    lua_call(lua, 2, 0);
                    mod->chunk_left -= r_skip;
                }
                else
                {
                    lua_pushlstring(lua, &buffer[skip], mod->chunk_left);
                    lua_call(lua, 2, 0);
                    mod->chunk_left = 0;

                    if(mod->is_keep_alive)
                    {
                        // keep-alive connection
                        get_lua_callback(mod);
                        lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
                        lua_pushstring(lua, "");
                        lua_call(lua, 2, 0);
                    }
                    else
                    {
                        // close connection
                        on_close(mod);
                    }
                    return;
                }
            }
        }

        // Stream
        else
        {
            get_lua_callback(mod);
            lua_rawgeti(lua, LUA_REGISTRYINDEX, mod->idx_self);
            lua_pushlstring(lua, &buffer[skip], r - skip);
            lua_call(lua, 2, 0);
        }
    }
} /* on_read */
Пример #12
0
static void
read_num(ParseInfo pi, const char *key) {
    char	*start = pi->s;
    int64_t	n = 0;
    long	a = 0;
    long	div = 1;
    long	e = 0;
    int		neg = 0;
    int		eneg = 0;
    int		big = 0;

    if ('-' == *pi->s) {
	pi->s++;
	neg = 1;
    } else if ('+' == *pi->s) {
	pi->s++;
    }
    if ('I' == *pi->s) {
	if (0 != strncmp("Infinity", pi->s, 8)) {
	    if (pi->has_error) {
		call_error("number or other value", pi, __FILE__, __LINE__);
	    }
	    raise_error("number or other value", pi->str, pi->s);
	}
	pi->s += 8;
	if (neg) {
	    if (pi->has_add_value) {
		call_add_value(pi->handler, rb_float_new(-OJ_INFINITY), key);
	    }
	} else {
	    if (pi->has_add_value) {
		call_add_value(pi->handler, rb_float_new(OJ_INFINITY), key);
	    }
	}
	return;
    }
    for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
	if (big) {
	    big++;
	} else {
	    n = n * 10 + (*pi->s - '0');
	    if (NUM_MAX <= n) {
		big = 1;
	    }
	}
    }
    if ('.' == *pi->s) {
	pi->s++;
	for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
	    a = a * 10 + (*pi->s - '0');
	    div *= 10;
	    if (NUM_MAX <= div) {
		big = 1;
	    }
	}
    }
    if ('e' == *pi->s || 'E' == *pi->s) {
	pi->s++;
	if ('-' == *pi->s) {
	    pi->s++;
	    eneg = 1;
	} else if ('+' == *pi->s) {
	    pi->s++;
	}
	for (; '0' <= *pi->s && *pi->s <= '9'; pi->s++) {
	    e = e * 10 + (*pi->s - '0');
	    if (NUM_MAX <= e) {
		big = 1;
	    }
	}
    }
    if (0 == e && 0 == a && 1 == div) {
	if (big) {
	    char	c = *pi->s;
	
	    *pi->s = '\0';
	    if (pi->has_add_value) {
		call_add_value(pi->handler, rb_funcall(oj_bigdecimal_class, oj_new_id, 1, rb_str_new2(start)), key);
	    }
	    *pi->s = c;
	} else {
	    if (neg) {
		n = -n;
	    }
	    if (pi->has_add_value) {
		call_add_value(pi->handler, LONG2NUM(n), key);
	    }
	}
	return;
    } else { /* decimal */
	if (big) {
	    char	c = *pi->s;
	
	    *pi->s = '\0';
	    if (pi->has_add_value) {
		call_add_value(pi->handler, rb_funcall(oj_bigdecimal_class, oj_new_id, 1, rb_str_new2(start)), key);
	    }
	    *pi->s = c;
	} else {
	    double	d = (double)n + (double)a / (double)div;

	    if (neg) {
		d = -d;
	    }
	    if (1 < big) {
		e += big - 1;
	    }
	    if (0 != e) {
		if (eneg) {
		    e = -e;
		}
		d *= pow(10.0, e);
	    }
	    if (pi->has_add_value) {
		call_add_value(pi->handler, rb_float_new(d), key);
	    }
	}
    }
}