diff options
author | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-18 21:30:21 +0000 |
---|---|---|
committer | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-18 21:30:21 +0000 |
commit | 93784d6aba5d188f972a4b6e42c9a72516df47ea (patch) | |
tree | dded0ad5aae38fbaffb393c272a6d210d4d7c3a0 /main/manager.c | |
parent | d57f0c668b8d56a8f5658942d1dc9400da1de2ed (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.c | 75 |
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; } |