aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main/manager.c130
1 files changed, 67 insertions, 63 deletions
diff --git a/main/manager.c b/main/manager.c
index edcc8ccf6..18e6b9bfa 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -224,6 +224,7 @@ struct mansession {
struct mansession_session *session;
FILE *f;
int fd;
+ ast_mutex_t lock;
};
static struct ao2_container *sessions = NULL;
@@ -504,6 +505,13 @@ static void session_destructor(void *obj)
{
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);
@@ -519,7 +527,6 @@ static struct mansession_session *build_mansession(struct sockaddr_in sin)
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;
@@ -528,7 +535,7 @@ static struct mansession_session *build_mansession(struct sockaddr_in sin)
ao2_link(sessions, newsession);
- return unref_mansession(newsession);
+ return newsession;
}
static int mansession_cmp_fn(void *obj, void *arg, int flags)
@@ -540,6 +547,7 @@ 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);
}
@@ -547,11 +555,13 @@ static void session_destroy(struct mansession_session *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;
}
@@ -905,32 +915,6 @@ static void ref_event(struct eventqent *e)
}
/*
- * 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,
@@ -1124,6 +1108,17 @@ void astman_send_listack(struct mansession *s, const struct message *m, char *ms
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
@@ -1133,11 +1128,11 @@ static int set_eventmask(struct mansession *s, const char *eventmask)
{
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;
}
@@ -1693,7 +1688,7 @@ static int action_waitevent(struct mansession *s, const struct message *m)
/* 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);
}
@@ -1717,14 +1712,14 @@ static int action_waitevent(struct mansession *s, const struct message *m)
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;
}
@@ -1738,7 +1733,7 @@ static int action_waitevent(struct mansession *s, const struct message *m)
if (s->session->needdestroy) {
needexit = 1;
}
- ao2_unlock(s);
+ mansession_unlock(s);
if (needexit) {
break;
}
@@ -1752,7 +1747,7 @@ static int action_waitevent(struct mansession *s, const struct message *m)
}
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.");
@@ -1772,7 +1767,7 @@ static int action_waitevent(struct mansession *s, const struct message *m)
} else {
ast_debug(1, "Abandoning event request!\n");
}
- ao2_unlock(s);
+ mansession_unlock(s);
return 0;
}
@@ -1862,10 +1857,10 @@ static int action_challenge(struct mansession *s, const struct message *m)
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");
}
@@ -3191,16 +3186,16 @@ static int process_message(struct mansession *s, const struct message *m)
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;
}
@@ -3208,9 +3203,9 @@ static int process_message(struct mansession *s, const struct message *m)
(!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;
}
}
@@ -3237,9 +3232,9 @@ static int process_message(struct mansession *s, const struct message *m)
} 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;
@@ -3297,20 +3292,20 @@ static int get_input(struct mansession *s, char *output)
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
@@ -3323,7 +3318,7 @@ static int get_input(struct mansession *s, char *output)
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 */
@@ -3332,7 +3327,7 @@ static int get_input(struct mansession *s, char *output)
src[s->session->inlen] = '\0';
res = 0;
}
- ao2_unlock(s);
+ mansession_unlock(s);
return res;
}
@@ -3394,6 +3389,8 @@ static void *session_do(void *data)
/* 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;
@@ -3433,8 +3430,9 @@ static void *session_do(void *data)
*/
usleep(1);
- destroy_session(session);
+ session_destroy(session);
+ ast_mutex_destroy(&s.lock);
done:
ao2_ref(ser, -1);
ser = NULL;
@@ -3450,7 +3448,6 @@ static void purge_sessions(int n_max)
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)) {
@@ -3462,6 +3459,7 @@ static void purge_sessions(int n_max)
n_max--;
} else {
ao2_unlock(session);
+ unref_mansession(session);
}
}
}
@@ -3711,7 +3709,6 @@ static struct mansession_session *find_session(uint32_t ident, int incinuse)
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);
@@ -3744,11 +3741,9 @@ static struct mansession_session *find_session_by_nonce(const char *username, un
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);
@@ -3768,6 +3763,7 @@ int astman_is_authed(uint32_t ident)
authed = (session->authenticated != 0);
ao2_unlock(session);
+ unref_mansession(session);
return authed;
}
@@ -4113,6 +4109,8 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
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;
@@ -4249,6 +4247,8 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
http_header = out = NULL;
generic_callback_out:
+ ast_mutex_destroy(&s.lock);
+
/* Clear resource */
if (method == AST_HTTP_POST && params) {
@@ -4260,13 +4260,14 @@ generic_callback_out:
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;
}
@@ -4459,6 +4460,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
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);
@@ -4554,6 +4556,8 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
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);