예제 #1
0
SWITCH_DECLARE(char *) switch_limit_status(const char *backend) {
	switch_limit_interface_t *limit = NULL;
	char *status = NULL;
	
	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(strdup("-ERR"), end);
	}
	
	status = limit->status();
	
end:
	release_backend(limit);
	return status;
}
예제 #2
0
SWITCH_DECLARE(switch_status_t) switch_limit_reset(const char *backend) {
	switch_limit_interface_t *limit = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(SWITCH_STATUS_GENERR, end);
	}
	
	status = limit->reset();
	
end:
	release_backend(limit);
	return status;
}
예제 #3
0
SWITCH_DECLARE(int) switch_limit_usage(const char *backend, const char *realm, const char *resource, uint32_t *rcount) {
	switch_limit_interface_t *limit = NULL;
	int usage = 0;
	
	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		goto end;
	}
	
	usage = limit->usage(realm, resource, rcount);
	
end:
	release_backend(limit);
	return usage;
}
예제 #4
0
SWITCH_DECLARE(switch_status_t) switch_limit_release(const char *backend, switch_core_session_t *session, const char *realm, const char *resource) {
	switch_limit_interface_t *limit = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(SWITCH_STATUS_GENERR, end);
	}
	
	status = limit->release(session, realm, resource);
	
end:
	release_backend(limit);
	return status;
}
예제 #5
0
SWITCH_DECLARE(switch_status_t) switch_limit_incr(const char *backend, switch_core_session_t *session, const char *realm, const char *resource, const int max, const int interval) {
	switch_limit_interface_t *limit = NULL;
	switch_channel_t *channel = NULL;
	int status = SWITCH_STATUS_SUCCESS;
	
	if (session) {
		channel = switch_core_session_get_channel(session);
	}

	/* locate impl, call appropriate func */
	if (!(limit = get_backend(backend))) {
		switch_limit_log(session, SWITCH_LOG_ERROR, "Limit subsystem %s not found!\n", backend);
		switch_goto_status(SWITCH_STATUS_GENERR, end);
	}

	switch_limit_log(session, SWITCH_LOG_INFO, "incr called: %s_%s max:%d, interval:%d\n",
					  realm, resource, max, interval);
	
	if ((status = limit->incr(session, realm, resource, max, interval)) == SWITCH_STATUS_SUCCESS) {
		if (session) {
			/* race condition? what if another leg is doing the same thing? */
			const char *existing = switch_channel_get_variable(channel, LIMIT_BACKEND_VARIABLE);
			if (existing) {
				if (!strstr(existing, backend)) {
					switch_channel_set_variable_printf(channel, LIMIT_BACKEND_VARIABLE, "%s,%s", existing, backend);
				}
			} else {
				switch_channel_set_variable(channel, LIMIT_BACKEND_VARIABLE, backend);
				switch_core_event_hook_add_state_change(session, limit_state_handler);
			}
		}
	}
	
	release_backend(limit);
	
end:
	return status;
}
예제 #6
0
static void ev_handler(struct ns_connection *nc, int ev, void *ev_data) {
    struct conn_data *conn = (struct conn_data *) nc->user_data;
    const time_t now = time(NULL);
#ifdef DEBUG
    write_log("%d conn=%p nc=%p ev=%d ev_data=%p bec=%p bec_nc=%p\n", now, conn,
              nc, ev, ev_data, conn != NULL ? conn->be_conn : NULL,
              conn != NULL && conn->be_conn != NULL ? conn->be_conn->nc : NULL);
#endif

    if (conn == NULL) {
        if (ev == NS_ACCEPT) {
            conn = calloc(1, sizeof(*conn));
            if (conn == NULL) {
                send_http_err(nc, s_error_500);
            } else {
                memset(conn, 0, sizeof(*conn));
                nc->user_data = conn;
                conn->client.nc = nc;
                conn->client.body_len = -1;
                conn->backend.body_len = -1;
                conn->last_activity = now;
            }
            return;
        } else {
            nc->flags |= NSF_CLOSE_IMMEDIATELY;
            return;
        }
    }

    if (ev != NS_POLL) conn->last_activity = now;

    switch (ev) {
    case NS_HTTP_REQUEST: { /* From client */
        assert(conn != NULL);
        assert(conn->be_conn == NULL);
        struct http_message *hm = (struct http_message *) ev_data;
        conn->client.flags.keep_alive = is_keep_alive(hm);

        if (!connect_backend(conn, hm)) {
            respond_with_error(conn, s_error_500);
            break;
        }

        if (conn->backend.nc == NULL) {
            /* This is a redirect, we're done. */
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
            break;
        }

        forward(conn, hm, &conn->client, &conn->backend);
        break;
    }

    case NS_CONNECT: { /* To backend */
        assert(conn != NULL);
        assert(conn->be_conn != NULL);
        int status = *(int *) ev_data;
        if (status != 0) {
            write_log("Error connecting to %s: %d (%s)\n",
                      conn->be_conn->be->host_port, status, strerror(status));
            /* TODO(lsm): mark backend as defunct, try it later on */
            respond_with_error(conn, s_error_500);
            conn->be_conn->nc = NULL;
            release_backend(conn);
            break;
        }
        break;
    }

    case NS_HTTP_REPLY: { /* From backend */
        assert(conn != NULL);
        struct http_message *hm = (struct http_message *) ev_data;
        conn->backend.flags.keep_alive = s_backend_keepalive && is_keep_alive(hm);
        forward(conn, hm, &conn->backend, &conn->client);
        release_backend(conn);
        if (!conn->client.flags.keep_alive) {
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
        } else {
#ifdef DEBUG
            write_log("conn=%p remains open\n", conn);
#endif
        }
        break;
    }

    case NS_POLL: {
        assert(conn != NULL);
        if (now - conn->last_activity > CONN_IDLE_TIMEOUT &&
                conn->backend.nc == NULL /* not waiting for backend */) {
#ifdef DEBUG
            write_log("conn=%p has been idle for too long\n", conn);
            conn->client.nc->flags |= NSF_SEND_AND_CLOSE;
#endif
        }
        break;
    }

    case NS_CLOSE: {
        assert(conn != NULL);
        if (nc == conn->client.nc) {
#ifdef DEBUG
            write_log("conn=%p nc=%p client closed, body_sent=%d\n", conn, nc,
                      conn->backend.body_sent);
#endif
            conn->client.nc = NULL;
            if (conn->backend.nc != NULL) {
                conn->backend.nc->flags |= NSF_CLOSE_IMMEDIATELY;
            }
        } else if (nc == conn->backend.nc) {
#ifdef DEBUG
            write_log("conn=%p nc=%p backend closed\n", conn, nc);
#endif
            conn->backend.nc = NULL;
            if (conn->client.nc != NULL &&
                    (conn->backend.body_len < 0 ||
                     conn->backend.body_sent < conn->backend.body_len)) {
                write_log("Backend %s disconnected.\n", conn->be_conn->be->host_port);
                respond_with_error(conn, s_error_500);
            }
        }
        if (conn->client.nc == NULL && conn->backend.nc == NULL) {
            free(conn);
        }
        break;
    }
    }
}