aboutsummaryrefslogtreecommitdiffstats
path: root/main/manager.c
diff options
context:
space:
mode:
authorrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-18 21:30:21 +0000
committerrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-10-18 21:30:21 +0000
commit93784d6aba5d188f972a4b6e42c9a72516df47ea (patch)
treedded0ad5aae38fbaffb393c272a6d210d4d7c3a0 /main/manager.c
parentd57f0c668b8d56a8f5658942d1dc9400da1de2ed (diff)
+ move output_format variables in the http section of the file;
+ more comments on struct mansession and global variables; + small improvements to the session matching code so it supports multiple sessions from the same IP git-svn-id: http://svn.digium.com/svn/asterisk/trunk@45597 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'main/manager.c')
-rw-r--r--main/manager.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/main/manager.c b/main/manager.c
index 6e55db640..d3026ba07 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -83,26 +83,14 @@ struct eventqent {
char eventdata[1]; /* really variable size, allocated by append_event() */
};
-enum output_format {
- FORMAT_RAW,
- FORMAT_HTML,
- FORMAT_XML,
-};
-
-static char *contenttype[] = {
- [FORMAT_RAW] = "plain",
- [FORMAT_HTML] = "html",
- [FORMAT_XML] = "xml",
-};
-
static int enabled = 0;
static int portno = DEFAULT_MANAGER_PORT;
-static int asock = -1;
+static int asock = -1; /* the accept socket */
static int displayconnects = 1;
static int timestampevents = 0;
static int httptimeout = 60;
-static pthread_t t;
+static pthread_t accept_thread_ptr; /* the accept thread */
static int block_sockets = 0;
static int num_sessions = 0;
@@ -121,17 +109,19 @@ AST_THREADSTORAGE(astman_append_buf, astman_append_buf_init);
/*! \brief Descriptor for an AMI session, either a regular one
* or one over http.
+ * For AMI sessions, the entry is created upon a connect, and destroyed
+ * with the socket.
*/
struct mansession {
- pthread_t t; /*! Execution thread */
+ pthread_t ms_t; /*! Execution thread, basically useless */
ast_mutex_t __lock; /*! Thread lock -- don't use in action callbacks, it's already taken care of */
/* XXX need to document which fields it is protecting */
- struct sockaddr_in sin; /*! socket address */
+ struct sockaddr_in sin; /*! address we are connecting from */
int fd; /*! descriptor used for output. Either the socket (AMI) or a temporary file (HTTP) */
- int inuse; /*! Whether an HTTP (XXX or AMI ?) manager is in use */
+ int inuse; /*! number of HTTP sessions using this entry */
int needdestroy; /*! Whether an HTTP session should be destroyed */
pthread_t waiting_thread; /*! Whether an HTTP session has someone waiting on events */
- unsigned long managerid; /*! Unique manager identifer */
+ unsigned long managerid; /*! Unique manager identifer, 0 for AMI sessions */
time_t sessiontimeout; /*! Session timeout if HTTP */
struct ast_dynamic_str *outputstr; /*! Output from manager interface */
char username[80]; /*! Logged in username */
@@ -511,7 +501,7 @@ static struct ast_cli_entry cli_manager[] = {
static void unuse_eventqent(struct eventqent *e)
{
if (ast_atomic_dec_and_test(&e->usecount) && e->next)
- pthread_kill(t, SIGURG);
+ pthread_kill(accept_thread_ptr, SIGURG);
}
static void free_session(struct mansession *s)
@@ -532,6 +522,7 @@ static void free_session(struct mansession *s)
static void destroy_session(struct mansession *s)
{
AST_LIST_LOCK(&sessions);
+ ast_verbose("destroy session %lx\n", s->managerid);
AST_LIST_REMOVE(&sessions, s, list);
AST_LIST_UNLOCK(&sessions);
@@ -1938,6 +1929,8 @@ static void *accept_thread(void *ignore)
AST_LIST_LOCK(&sessions);
AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
+ ast_verbose("destroy session[2] %lx now %lu to %lu\n",
+ s->managerid, now, s->sessiontimeout);
AST_LIST_REMOVE_CURRENT(&sessions, list);
ast_atomic_fetchadd_int(&num_sessions, -1);
if (s->authenticated && (option_verbose > 1) && displayconnects) {
@@ -2010,7 +2003,7 @@ static void *accept_thread(void *ignore)
s->eventq = s->eventq->next;
AST_LIST_UNLOCK(&sessions);
ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
- if (ast_pthread_create_background(&s->t, &attr, session_do, s))
+ if (ast_pthread_create_background(&s->ms_t, &attr, session_do, s))
destroy_session(s);
}
pthread_attr_destroy(&attr);
@@ -2189,15 +2182,31 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse
* then fed back to the client over the original socket.
*/
+enum output_format {
+ FORMAT_RAW,
+ FORMAT_HTML,
+ FORMAT_XML,
+};
+
+static char *contenttype[] = {
+ [FORMAT_RAW] = "plain",
+ [FORMAT_HTML] = "html",
+ [FORMAT_XML] = "xml",
+};
+
+/* locate an http session in the list using the cookie as a key */
static struct mansession *find_session(unsigned long ident)
{
struct mansession *s;
+ if (ident == 0)
+ return NULL;
+
AST_LIST_LOCK(&sessions);
AST_LIST_TRAVERSE(&sessions, s, list) {
ast_mutex_lock(&s->__lock);
if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
- s->inuse++;
+ ast_atomic_fetchadd_int(&s->inuse, 1);
break;
}
ast_mutex_unlock(&s->__lock);
@@ -2408,25 +2417,26 @@ static char *generic_http_callback(enum output_format format,
for (v = params; v; v = v->next) {
if (!strcasecmp(v->name, "mansession_id")) {
sscanf(v->value, "%lx", &ident);
- ast_verbose("session is <%lx>\n", ident);
break;
}
}
-
+
if (!(s = find_session(ident))) {
- /* Create new session */
+ /* Create new session.
+ * While it is not in the list we don't need any locking
+ */
if (!(s = ast_calloc(1, sizeof(*s)))) {
*status = 500;
goto generic_callback_out;
}
- memcpy(&s->sin, requestor, sizeof(s->sin));
+ s->sin = *requestor;
s->fd = -1;
s->waiting_thread = AST_PTHREADT_NULL;
s->send_events = 0;
ast_mutex_init(&s->__lock);
ast_mutex_lock(&s->__lock);
s->inuse = 1;
- s->managerid = rand() | (unsigned long)s;
+ s->managerid = rand() | 1; /* make sure it is non-zero */
AST_LIST_LOCK(&sessions);
AST_LIST_INSERT_HEAD(&sessions, s, list);
/* Hook into the last spot in the event queue */
@@ -2438,14 +2448,7 @@ static char *generic_http_callback(enum output_format format,
ast_atomic_fetchadd_int(&num_sessions, 1);
}
- /* Reset HTTP timeout. If we're not yet authenticated, keep it extremely short */
- time(&s->sessiontimeout);
- if (!s->authenticated && (httptimeout > 5))
- s->sessiontimeout += 5;
- else
- s->sessiontimeout += httptimeout;
ast_mutex_unlock(&s->__lock);
-
memset(&m, 0, sizeof(m));
{
char tmp[80];
@@ -2542,6 +2545,10 @@ static char *generic_http_callback(enum output_format format,
ast_build_string(&c, &len, "</table></body>\r\n");
ast_mutex_lock(&s->__lock);
+ /* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
+ s->sessiontimeout = time(NULL) + ((s->authenticated || httptimeout < 5) ? httptimeout : 5);
+ ast_verbose("die in %d seconds\n",
+ (int)(s->sessiontimeout - time(NULL)) );
if (s->needdestroy) {
if (s->inuse == 1) {
if (option_debug)
@@ -2831,7 +2838,7 @@ int init_manager(void)
fcntl(asock, F_SETFL, flags | O_NONBLOCK);
if (option_verbose)
ast_verbose("Asterisk Management interface listening on port %d\n", portno);
- ast_pthread_create_background(&t, NULL, accept_thread, NULL);
+ ast_pthread_create_background(&accept_thread_ptr, NULL, accept_thread, NULL);
}
return 0;
}