struct mansession_session *session;
FILE *f;
int fd;
+ ast_mutex_t lock;
};
static struct ao2_container *sessions = NULL;
{
struct mansession_session *session = obj;
struct eventqent *eqe = session->last_ev;
+ struct ast_datastore *datastore;
+
+ /* Get rid of each of the data stores on the session */
+ while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
+ /* Free the data store */
+ ast_datastore_free(datastore);
+ }
if (session->f != NULL) {
fclose(session->f);
if (!(newsession = ao2_alloc(sizeof(*newsession), session_destructor))) {
return NULL;
}
- memset(newsession, 0, sizeof(*newsession));
newsession->fd = -1;
newsession->waiting_thread = AST_PTHREADT_NULL;
newsession->writetimeout = 100;
ao2_link(sessions, newsession);
- return unref_mansession(newsession);
+ return newsession;
}
static int mansession_cmp_fn(void *obj, void *arg, int flags)
static void session_destroy(struct mansession_session *s)
{
+ unref_mansession(s);
ao2_unlink(sessions, s);
}
static int check_manager_session_inuse(const char *name)
{
struct mansession_session *session = ao2_find(sessions, (char*) name, OBJ_POINTER);
+ int inuse = 0;
if (session) {
+ inuse = 1;
unref_mansession(session);
}
- return session ? 1 : 0;
+ return inuse;
}
}
/*
- * destroy a session, leaving the usecount
- */
-static void free_session(struct mansession_session *session)
-{
- struct eventqent *eqe = session->last_ev;
- struct ast_datastore *datastore;
-
- /* Get rid of each of the data stores on the session */
- while ((datastore = AST_LIST_REMOVE_HEAD(&session->datastores, entry))) {
- /* Free the data store */
- ast_datastore_free(datastore);
- }
-
- if (session->f != NULL)
- fclose(session->f);
- ast_free(session);
- unref_event(eqe);
-}
-
-static void destroy_session(struct mansession_session *session)
-{
- ao2_unlink(sessions, session);
- free_session(session);
-}
-
-/*
* Generic function to return either the first or the last matching header
* from a list of variables, possibly skipping empty strings.
* At the moment there is only one use of this function in this file,
astman_send_response_full(s, m, "Success", msg, listflag);
}
+/*! \brief Lock the 'mansession' structure. */
+static void mansession_lock(struct mansession *s)
+{
+ ast_mutex_lock(&s->lock);
+}
+
+/*! \brief Unlock the 'mansession' structure. */
+static void mansession_unlock(struct mansession *s)
+{
+ ast_mutex_unlock(&s->lock);
+}
/*! \brief
Rather than braindead on,off this now can also accept a specific int mask value
{
int maskint = strings_to_mask(eventmask);
- ao2_lock(s);
+ mansession_lock(s);
if (maskint >= 0) {
s->session->send_events = maskint;
}
- ao2_unlock(s);
+ mansession_unlock(s);
return maskint;
}
/* XXX maybe put an upper bound, or prevent the use of 0 ? */
}
- ao2_lock(s);
+ mansession_lock(s);
if (s->session->waiting_thread != AST_PTHREADT_NULL) {
pthread_kill(s->session->waiting_thread, SIGURG);
}
s->session->send_events = -1;
}
}
- ao2_unlock(s);
+ mansession_unlock(s);
/* XXX should this go inside the lock ? */
s->session->waiting_thread = pthread_self(); /* let new events wake up this thread */
ast_debug(1, "Starting waiting for an event!\n");
for (x = 0; x < timeout || timeout < 0; x++) {
- ao2_lock(s);
+ mansession_lock(s);
if (NEW_EVENT(s)) {
needexit = 1;
}
if (s->session->needdestroy) {
needexit = 1;
}
- ao2_unlock(s);
+ mansession_unlock(s);
if (needexit) {
break;
}
}
ast_debug(1, "Finished waiting for an event!\n");
- ao2_lock(s);
+ mansession_lock(s);
if (s->session->waiting_thread == pthread_self()) {
struct eventqent *eqe;
astman_send_response(s, m, "Success", "Waiting for Event completed.");
} else {
ast_debug(1, "Abandoning event request!\n");
}
- ao2_unlock(s);
+ mansession_unlock(s);
return 0;
}
if (ast_strlen_zero(s->session->challenge)) {
snprintf(s->session->challenge, sizeof(s->session->challenge), "%ld", ast_random());
}
- ao2_lock(s);
+ mansession_lock(s);
astman_start_ack(s, m);
astman_append(s, "Challenge: %s\r\n\r\n", s->session->challenge);
- ao2_unlock(s);
+ mansession_unlock(s);
} else {
astman_send_error(s, m, "Must specify AuthType");
}
ast_copy_string(action, __astman_get_header(m, "Action", GET_HEADER_SKIP_EMPTY), sizeof(action));
if (ast_strlen_zero(action)) {
- ao2_lock(s);
+ mansession_lock(s);
astman_send_error(s, m, "Missing action in request");
- ao2_unlock(s);
+ mansession_unlock(s);
return 0;
}
if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") && strcasecmp(action, "Challenge")) {
- ao2_lock(s);
+ mansession_lock(s);
astman_send_error(s, m, "Permission denied");
- ao2_unlock(s);
+ mansession_unlock(s);
return 0;
}
(!strcasecmp(action, "Login") || !strcasecmp(action, "Challenge"))) {
if (check_manager_session_inuse(user)) {
sleep(1);
- ao2_lock(s);
+ mansession_lock(s);
astman_send_error(s, m, "Login Already In Use");
- ao2_unlock(s);
+ mansession_unlock(s);
return -1;
}
}
} else {
char buf[512];
snprintf(buf, sizeof(buf), "Invalid/unknown command: %s. Use Action: ListCommands to show available commands.", action);
- ao2_lock(s);
+ mansession_lock(s);
astman_send_error(s, m, buf);
- ao2_unlock(s);
+ mansession_unlock(s);
}
if (ret) {
return ret;
res = 0;
while (res == 0) {
/* XXX do we really need this locking ? */
- ao2_lock(s);
+ mansession_lock(s);
if (s->session->pending_event) {
s->session->pending_event = 0;
- ao2_unlock(s);
+ mansession_unlock(s);
return 0;
}
s->session->waiting_thread = pthread_self();
- ao2_unlock(s);
+ mansession_unlock(s);
res = ast_wait_for_input(s->session->fd, -1); /* return 0 on timeout ? */
- ao2_lock(s);
+ mansession_lock(s);
s->session->waiting_thread = AST_PTHREADT_NULL;
- ao2_unlock(s);
+ mansession_unlock(s);
}
if (res < 0) {
/* If we get a signal from some other thread (typically because
return -1;
}
- ao2_lock(s);
+ mansession_lock(s);
res = fread(src + s->session->inlen, 1, maxlen - s->session->inlen, s->session->f);
if (res < 1) {
res = -1; /* error return */
src[s->session->inlen] = '\0';
res = 0;
}
- ao2_unlock(s);
+ mansession_unlock(s);
return res;
}
/* Hook to the tail of the event queue */
session->last_ev = grab_last();
+ ast_mutex_init(&s.lock);
+
/* these fields duplicate those in the 'ser' structure */
session->fd = s.fd = ser->fd;
session->f = s.f = ser->f;
*/
usleep(1);
- destroy_session(session);
+ session_destroy(session);
+ ast_mutex_destroy(&s.lock);
done:
ao2_ref(ser, -1);
ser = NULL;
i = ao2_iterator_init(sessions, 0);
while ((session = ao2_iterator_next(&i)) && n_max > 0) {
- unref_mansession(session);
ao2_lock(session);
if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
if (session->authenticated && (VERBOSITY_ATLEAST(2)) && manager_displayconnects(session)) {
n_max--;
} else {
ao2_unlock(session);
+ unref_mansession(session);
}
}
}
ao2_lock(session);
if (session->managerid == ident && !session->needdestroy) {
ast_atomic_fetchadd_int(&session->inuse, incinuse ? 1 : 0);
- unref_mansession(session);
break;
}
ao2_unlock(session);
ao2_lock(session);
if (!strcasecmp(session->username, username) && session->managerid == nonce) {
*stale = 0;
- unref_mansession(session);
break;
} else if (!strcasecmp(session->username, username) && session->oldnonce == nonce) {
*stale = 1;
- unref_mansession(session);
break;
}
ao2_unlock(session);
authed = (session->authenticated != 0);
ao2_unlock(session);
+ unref_mansession(session);
return authed;
}
http_header = ast_str_create(128);
out = ast_str_create(2048);
+ ast_mutex_init(&s.lock);
+
if (http_header == NULL || out == NULL) {
ast_http_error(ser, 500, "Server Error", "Internal Server Error (ast_str_create() out of memory)\n");
goto generic_callback_out;
http_header = out = NULL;
generic_callback_out:
+ ast_mutex_destroy(&s.lock);
+
/* Clear resource */
if (method == AST_HTTP_POST && params) {
if (out) {
ast_free(out);
}
- if (session->f) {
- fclose(session->f);
- }
- if (session != NULL && blastaway) {
+ if (session && blastaway) {
session_destroy(session);
+ } else if (session && session->f) {
+ fclose(session->f);
+ session->f = NULL;
}
+
return 0;
}
session->sessiontimeout = time(NULL) + (httptimeout > 5 ? httptimeout : 5);
ao2_unlock(session);
+ ast_mutex_init(&s.lock);
s.session = session;
s.fd = mkstemp(template); /* create a temporary file for command output */
unlink(template);
http_header = out = NULL;
auth_callback_out:
+ ast_mutex_destroy(&s.lock);
+
/* Clear resources and unlock manager session */
if (method == AST_HTTP_POST && params) {
ast_variables_destroy(params);