[svn-commits] rizzo: trunk r48338 - /trunk/main/manager.c

svn-commits at lists.digium.com svn-commits at lists.digium.com
Wed Dec 6 13:46:02 MST 2006


Author: rizzo
Date: Wed Dec  6 14:46:01 2006
New Revision: 48338

URL: http://svn.digium.com/view/asterisk?view=rev&rev=48338
Log:
remove duplicated code to start the server threads, use
the infrastructure exposed in http.c earlier today.

As a bonus, now we can restart the session on a different
port just reloading the module.

On passing, fix a bug in the handling of 'enabled' in the configuration
file - previously, a missing "enabled=" line in manager.conf meant
"whatever the state was before" instead of a specific value.


Modified:
    trunk/main/manager.c

Modified: trunk/main/manager.c
URL: http://svn.digium.com/view/asterisk/trunk/main/manager.c?view=diff&rev=48338&r1=48337&r2=48338
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Wed Dec  6 14:46:01 2006
@@ -105,9 +105,7 @@
 
 static AST_LIST_HEAD_STATIC(all_events, eventqent);
 
-static int enabled = 0;
 static int portno = DEFAULT_MANAGER_PORT;
-static int asock = -1;	/* the accept socket */
 static int displayconnects = 1;
 static int timestampevents = 0;
 static int httptimeout = 60;
@@ -2138,11 +2136,39 @@
  */
 static void *session_do(void *data)
 {
-	struct mansession *s = data;
 	struct message m;	/* XXX watch out, this is 20k of memory! */
-
+	struct server_instance *ser = data;
+	struct mansession *s = ast_calloc(1, sizeof(*s));
+	int flags;
+
+	if (s == NULL)
+		goto done;
+
+	s->writetimeout = 100;
+	s->waiting_thread = AST_PTHREADT_NULL;
+
+	flags = fcntl(ser->fd, F_GETFL);
+	if (!block_sockets) /* make sure socket is non-blocking */
+		flags |= O_NONBLOCK;
+	else
+		flags &= ~O_NONBLOCK;
+	fcntl(ser->fd, F_SETFL, flags);
+
+	ast_mutex_init(&s->__lock);
+	s->send_events = -1;
+	/* these fields duplicate those in the 'ser' structure */
+	s->fd = ser->fd;
+	s->f = ser->f;
+	s->sin = ser->requestor;
+
+	ast_atomic_fetchadd_int(&num_sessions, 1);
+	AST_LIST_LOCK(&sessions);
+	AST_LIST_INSERT_HEAD(&sessions, s, list);
+	AST_LIST_UNLOCK(&sessions);
+	/* Hook to the tail of the event queue */
+	s->last_ev = grab_last();
 	ast_mutex_lock(&s->__lock);
-	s->f = fdopen(s->fd, "w+");
+	s->f = ser->f;
 	astman_append(s, "Asterisk Call Manager/1.0\r\n");	/* welcome prompt */
 	ast_mutex_unlock(&s->__lock);
 	memset(&m, 0, sizeof(m));
@@ -2176,6 +2202,9 @@
 		ast_log(LOG_EVENT, "Failed attempt from %s\n", ast_inet_ntoa(s->sin.sin_addr));
 	}
 	destroy_session(s);
+
+done:
+	free(ser);
 	return NULL;
 }
 
@@ -2203,80 +2232,6 @@
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 	AST_LIST_UNLOCK(&sessions);
-}
-
-/*! \brief The thread accepting connections on the manager interface port.
- * As a side effect, it purges stale sessions, one per each iteration,
- * which is at least every 5 seconds.
- */
-static void *accept_thread(void *ignore)
-{
-	pthread_attr_t attr;
-
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-	for (;;) {
-		struct mansession *s;
-		int as;
-		struct sockaddr_in sin;
-		socklen_t sinlen;
-		struct protoent *p;
-		int flags;
-
-		purge_sessions(1);
-		purge_events();
-
-		/* Wait for something to happen, but timeout every few seconds so
-		   we can ditch any old manager sessions */
-		if (ast_wait_for_input(asock, 5000) < 1)
-			continue;
-		sinlen = sizeof(sin);
-		as = accept(asock, (struct sockaddr *)&sin, &sinlen);
-		if (as < 0) {
-			ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
-			continue;
-		}
-		p = getprotobyname("tcp");
-		if (p) {
-			int arg = 1;
-			if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
-				ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
-			}
-		}
-		s = ast_calloc(1, sizeof(*s));	/* allocate a new record */
-		if (!s) {
-			close(as);
-			continue;
-		}
-
-
-		s->sin = sin;
-		s->writetimeout = 100;
-		s->waiting_thread = AST_PTHREADT_NULL;
-
-		flags = fcntl(as, F_GETFL);
-		if (!block_sockets) /* For safety, make sure socket is non-blocking */
-			flags |= O_NONBLOCK;
-		else
-			flags &= ~O_NONBLOCK;
-		fcntl(as, F_SETFL, flags);
-
-		ast_mutex_init(&s->__lock);
-		s->fd = as;
-		s->send_events = -1;
-
-		ast_atomic_fetchadd_int(&num_sessions, 1);
-		AST_LIST_LOCK(&sessions);
-		AST_LIST_INSERT_HEAD(&sessions, s, list);
-		AST_LIST_UNLOCK(&sessions);
-		/* Hook to the tail of the event queue */
-		s->last_ev = grab_last();
-		if (ast_pthread_create_background(&s->ms_t, &attr, session_do, s))
-			destroy_session(s);
-	}
-	pthread_attr_destroy(&attr);
-	return NULL;
 }
 
 /*
@@ -2904,16 +2859,33 @@
 static int registered = 0;
 static int webregged = 0;
 
+/*! \brief cleanup code called at each iteration of server_root,
+ * guaranteed to happen every 5 seconds at most
+ */
+static void purge_old_stuff(void *data)
+{
+	purge_sessions(1);
+	purge_events();
+}
+
+static struct server_args ami_desc = {
+        .accept_fd = -1,
+        .master = AST_PTHREADT_NULL,
+        .is_ssl = 0, 
+        .poll_timeout = 5000,	/* wake up every 5 seconds */
+	.periodic_fn = purge_old_stuff,
+        .name = "AMI server",
+        .accept_fn = server_root,	/* thread doing the accept() */
+        .worker_fn = session_do,	/* thread handling the session */
+};
+
 int init_manager(void)
 {
 	struct ast_config *cfg = NULL;
 	const char *val;
 	char *cat = NULL;
-	int oldportno = portno;
-	static struct sockaddr_in ba;
-	int x = 1;
-	int flags;
 	int webenabled = 0;
+	int enabled = 0;
 	int newhttptimeout = 60;
 	struct ast_manager_user *user = NULL;
 
@@ -2986,26 +2958,16 @@
 	if ((val = ast_variable_retrieve(cfg, "general", "httptimeout")))
 		newhttptimeout = atoi(val);
 
-	memset(&ba, 0, sizeof(ba));
-	ba.sin_family = AF_INET;
-	ba.sin_port = htons(portno);
+	memset(&ami_desc.sin, 0, sizeof(struct sockaddr_in));
+	if (enabled)
+		ami_desc.sin.sin_family = AF_INET;
+	ami_desc.sin.sin_port = htons(portno);
 
 	if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
-		if (!inet_aton(val, &ba.sin_addr)) {
+		if (!inet_aton(val, &ami_desc.sin.sin_addr)) {
 			ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
-			memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
-		}
-	}
-
-
-	if ((asock > -1) && ((portno != oldportno) || !enabled)) {
-#if 0
-		/* Can't be done yet */
-		close(asock);
-		asock = -1;
-#else
-		ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
-#endif
+			memset(&ami_desc.sin.sin_addr, 0, sizeof(ami_desc.sin.sin_addr));
+		}
 	}
 
 	AST_LIST_LOCK(&users);
@@ -3107,35 +3069,7 @@
 	if (newhttptimeout > 0)
 		httptimeout = newhttptimeout;
 
-	/* If not enabled, do nothing */
-	if (!enabled)
-		return 0;
-
-	if (asock < 0) {
-		asock = socket(AF_INET, SOCK_STREAM, 0);
-		if (asock < 0) {
-			ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
-			return -1;
-		}
-		setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
-		if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) {
-			ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
-			close(asock);
-			asock = -1;
-			return -1;
-		}
-		if (listen(asock, 2)) {
-			ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
-			close(asock);
-			asock = -1;
-			return -1;
-		}
-		flags = fcntl(asock, F_GETFL);
-		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(&accept_thread_ptr, NULL, accept_thread, NULL);
-	}
+	server_start(&ami_desc);
 	return 0;
 }
 



More information about the svn-commits mailing list