|  | @@ -92,6 +92,12 @@
 | 
	
		
			
				|  |  |  #define PATH_MAX MAX_PATH
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#ifndef _IN_PORT_T
 | 
	
		
			
				|  |  | +#ifndef in_port_t
 | 
	
		
			
				|  |  | +#define in_port_t u_short
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #ifndef _WIN32_WCE
 | 
	
		
			
				|  |  |  #include <process.h>
 | 
	
		
			
				|  |  |  #include <direct.h>
 | 
	
	
		
			
				|  | @@ -568,6 +574,7 @@ struct mg_context {
 | 
	
		
			
				|  |  |      void *user_data;                /* User-defined data */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      struct socket *listening_sockets;
 | 
	
		
			
				|  |  | +    in_port_t *listening_ports;
 | 
	
		
			
				|  |  |      int num_listening_sockets;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      volatile int num_threads;  /* Number of threads */
 | 
	
	
		
			
				|  | @@ -700,6 +707,15 @@ const char *mg_get_option(const struct mg_context *ctx, const char *name)
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +    for (int i = 0; i < size && i < ctx->num_listening_sockets; i++)
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        ssl[i] = ctx->listening_sockets[i].is_ssl;
 | 
	
		
			
				|  |  | +        ports[i] = ctx->listening_ports[i];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void sockaddr_to_string(char *buf, size_t len,
 | 
	
		
			
				|  |  |                                 const union usa *usa)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -5206,6 +5222,13 @@ static int set_ports_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |      struct vec vec;
 | 
	
		
			
				|  |  |      struct socket so, *ptr;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    in_port_t *portPtr;
 | 
	
		
			
				|  |  | +    struct sockaddr_in sin;
 | 
	
		
			
				|  |  | +    socklen_t len;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    memset(&sin, 0, sizeof(sin));
 | 
	
		
			
				|  |  | +    len = sizeof(sin);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      while (success && (list = next_option(list, &vec, NULL)) != NULL) {
 | 
	
		
			
				|  |  |          if (!parse_port_string(&vec, &so)) {
 | 
	
		
			
				|  |  |              mg_cry(fc(ctx), "%s: %.*s: invalid port spec. Expecting list of: %s",
 | 
	
	
		
			
				|  | @@ -5227,7 +5250,8 @@ static int set_ports_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |                     bind(so.sock, &so.lsa.sa, so.lsa.sa.sa_family == AF_INET ?
 | 
	
		
			
				|  |  |                          sizeof(so.lsa.sin) : sizeof(so.lsa)) != 0 ||
 | 
	
		
			
				|  |  | -                   listen(so.sock, SOMAXCONN) != 0) {
 | 
	
		
			
				|  |  | +                   listen(so.sock, SOMAXCONN) != 0 ||
 | 
	
		
			
				|  |  | +                   getsockname(so.sock, (struct sockaddr *)&sin, &len) != 0) {
 | 
	
		
			
				|  |  |              mg_cry(fc(ctx), "%s: cannot bind to %.*s: %d (%s)", __func__,
 | 
	
		
			
				|  |  |                     (int) vec.len, vec.ptr, ERRNO, strerror(errno));
 | 
	
		
			
				|  |  |              if (so.sock != INVALID_SOCKET) {
 | 
	
	
		
			
				|  | @@ -5239,10 +5263,18 @@ static int set_ports_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |                            sizeof(ctx->listening_sockets[0]))) == NULL) {
 | 
	
		
			
				|  |  |              closesocket(so.sock);
 | 
	
		
			
				|  |  |              success = 0;
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | +        } else if ((portPtr = (in_port_t*) realloc(ctx->listening_ports,
 | 
	
		
			
				|  |  | +                          (ctx->num_listening_sockets + 1) *
 | 
	
		
			
				|  |  | +                          sizeof(ctx->listening_ports[0]))) == NULL) {
 | 
	
		
			
				|  |  | +            closesocket(so.sock);
 | 
	
		
			
				|  |  | +            success = 0;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  |              set_close_on_exec(so.sock, fc(ctx));
 | 
	
		
			
				|  |  |              ctx->listening_sockets = ptr;
 | 
	
		
			
				|  |  |              ctx->listening_sockets[ctx->num_listening_sockets] = so;
 | 
	
		
			
				|  |  | +            ctx->listening_ports = portPtr;
 | 
	
		
			
				|  |  | +            ctx->listening_ports[ctx->num_listening_sockets] = ntohs(sin.sin_port);
 | 
	
		
			
				|  |  |              ctx->num_listening_sockets++;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 |