浏览代码

Merge pull request #34 from keithel/getports

Add methods for returning the ports civetweb is listening on
sunsetbrew 11 年之前
父节点
当前提交
90df41cba3
共有 2 个文件被更改,包括 44 次插入2 次删除
  1. 8 0
      include/civetweb.h
  2. 36 2
      src/civetweb.c

+ 8 - 0
include/civetweb.h

@@ -224,6 +224,14 @@ const char *mg_get_option(const struct mg_context *ctx, const char *name);
    Array is NULL terminated. */
 const char **mg_get_valid_option_names(void);
 
+/* Get the list of ports that civetweb is listening on.
+   size is the size of the ports int array and ssl int array to fill.
+   It is the caller's responsibility to make sure ports and ssl each
+   contain at least size int elements worth of memory to write into.
+   Return value is the number of ports and ssl information filled in.
+   The value returned is read-only. Civetweb does not allow changing
+   configuration at run time. */
+size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl);
 
 /* Add, edit or delete the entry in the passwords file.
 

+ 36 - 2
src/civetweb.c

@@ -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>
@@ -589,6 +595,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 */
@@ -728,6 +735,17 @@ const char *mg_get_option(const struct mg_context *ctx, const char *name)
     }
 }
 
+size_t mg_get_ports(const struct mg_context *ctx, size_t size, int* ports, int* ssl)
+{
+    size_t i;
+    for (i = 0; i < size && i < (size_t)ctx->num_listening_sockets; i++)
+    {
+        ssl[i] = ctx->listening_sockets[i].is_ssl;
+        ports[i] = ctx->listening_ports[i];
+    }
+    return i;
+}
+
 static void sockaddr_to_string(char *buf, size_t len,
                                const union usa *usa)
 {
@@ -5340,6 +5358,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",
@@ -5361,7 +5386,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) {
@@ -5373,10 +5399,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++;
         }
     }