diff --git a/docs/UserManual.md b/docs/UserManual.md index 825b5300..f237b90f 100644 --- a/docs/UserManual.md +++ b/docs/UserManual.md @@ -278,6 +278,11 @@ an IP address and a colon must be pre-pended to the port number. For example, to bind to a loopback interface on port 80 and to all interfaces on HTTPS port 443, use `127.0.0.1:80,443s`. +If the server is built with IPv6 support, `[::]:8080` can be used to +listen to connections to port 8080 from both, IPv4 and IPv6. +IPv6 addresses of network interfaces can be specified as well, +e.g. `[::1]:8080` for the IPv6 loopback interface. + ### document\_root `.` A directory to serve. By default, the current working directory is served. The current directory is commonly referenced as dot (`.`). diff --git a/examples/embedded_c/embedded_c.c b/examples/embedded_c/embedded_c.c index 57e0f590..d45b2e7a 100644 --- a/examples/embedded_c/embedded_c.c +++ b/examples/embedded_c/embedded_c.c @@ -17,7 +17,7 @@ #define DOCUMENT_ROOT "." #ifdef USE_IPV6 -#define PORT "8888,[::]:8886" +#define PORT "[::]:8888" #else #define PORT "8888" #endif @@ -28,284 +28,351 @@ int exitNow = 0; int ExampleHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, ""); - mg_printf(conn, "

This is an example text from a C handler

"); - mg_printf(conn, "

To see a page from the A handler click A

"); - mg_printf(conn, "

To see a page from the A handler click A/A

"); - mg_printf(conn, "

To see a page from the A/B handler click A/B

"); - mg_printf(conn, "

To see a page from the B handler (0) click B

"); - mg_printf(conn, "

To see a page from the B handler (1) click B/A

"); - mg_printf(conn, "

To see a page from the B handler (2) click B/B

"); - mg_printf(conn, "

To see a page from the *.foo handler click xy.foo

"); + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, ""); + mg_printf(conn, "

This is an example text from a C handler

"); + mg_printf( + conn, + "

To see a page from the A handler click A

"); + mg_printf(conn, "

To see a page from the A handler click " + "A/A

"); + mg_printf(conn, "

To see a page from the A/B handler click A/B

"); + mg_printf(conn, "

To see a page from the B handler (0) click B

"); + mg_printf(conn, "

To see a page from the B handler (1) click B/A

"); + mg_printf(conn, "

To see a page from the B handler (2) click B/B

"); + mg_printf(conn, "

To see a page from the *.foo handler click xy.foo

"); #ifdef USE_WEBSOCKET - mg_printf(conn, "

To test websocket handler click websocket

"); + mg_printf(conn, "

To test websocket handler click " + "websocket

"); #endif - mg_printf(conn, "

To exit click exit

", EXIT_URI); - mg_printf(conn, "\n"); - return 1; + mg_printf(conn, "

To exit click exit

", EXIT_URI); + mg_printf(conn, "\n"); + return 1; } int ExitHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"); - mg_printf(conn, "Bye!\n"); - exitNow = 1; - return 1; + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"); + mg_printf(conn, "Bye!\n"); + exitNow = 1; + return 1; } int AHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, ""); - mg_printf(conn, "

This is the A handler!!!

"); - mg_printf(conn, "\n"); - return 1; + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, ""); + mg_printf(conn, "

This is the A handler!!!

"); + mg_printf(conn, "\n"); + return 1; } int ABHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, ""); - mg_printf(conn, "

This is the AB handler!!!

"); - mg_printf(conn, "\n"); - return 1; + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, ""); + mg_printf(conn, "

This is the AB handler!!!

"); + mg_printf(conn, "\n"); + return 1; } int BXHandler(struct mg_connection *conn, void *cbdata) { - /* Handler may access the request info using mg_get_request_info */ - const struct mg_request_info * req_info = mg_get_request_info(conn); + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, ""); - mg_printf(conn, "

This is the BX handler %p!!!

", cbdata); - mg_printf(conn, "

The actual uri is %s

", req_info->uri); - mg_printf(conn, "\n"); - return 1; + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, ""); + mg_printf(conn, "

This is the BX handler %p!!!

", cbdata); + mg_printf(conn, "

The actual uri is %s

", req_info->uri); + mg_printf(conn, "\n"); + return 1; } int FooHandler(struct mg_connection *conn, void *cbdata) { - /* Handler may access the request info using mg_get_request_info */ - const struct mg_request_info * req_info = mg_get_request_info(conn); + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, ""); - mg_printf(conn, "

This is the Foo handler!!!

"); - mg_printf(conn, "

The request was:

%s %s HTTP/%s

", - req_info->request_method, req_info->uri, req_info->http_version); - mg_printf(conn, "\n"); - return 1; + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, ""); + mg_printf(conn, "

This is the Foo handler!!!

"); + mg_printf(conn, + "

The request was:

%s %s HTTP/%s

", + req_info->request_method, + req_info->uri, + req_info->http_version); + mg_printf(conn, "\n"); + return 1; } int WebSocketStartHandler(struct mg_connection *conn, void *cbdata) { - mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"); - mg_printf(conn, "\n"); - mg_printf(conn, "\n\n"); - mg_printf(conn, "\n"); - mg_printf(conn, "Embedded websocket example\n"); + mg_printf(conn, "\n"); + mg_printf(conn, "\n\n"); + mg_printf(conn, "\n"); + mg_printf(conn, "Embedded websocket example\n"); #ifdef USE_WEBSOCKET - /* mg_printf(conn, "\n"); ... xhtml style */ - mg_printf(conn, "\n"); - mg_printf(conn, "\n\n"); - mg_printf(conn, "
No websocket connection yet
\n"); + /* mg_printf(conn, "\n"); ... xhtml style */ + mg_printf(conn, "\n"); + mg_printf(conn, "\n\n"); + mg_printf( + conn, + "
No websocket connection yet
\n"); #else - mg_printf(conn, "\n\n"); - mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n"); + mg_printf(conn, "\n\n"); + mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n"); #endif - mg_printf(conn, "\n\n"); - return 1; + mg_printf(conn, "\n\n"); + return 1; } #ifdef USE_WEBSOCKET -#define MAX_WS_CLIENTS 5 /* just for the test: a small number that can be reached */ - /* a real server should use a much higher number here */ +#define MAX_WS_CLIENTS \ + 5 /* just for the test: a small number that can be reached */ + /* a real server should use a much higher number here */ struct t_ws_client { - struct mg_connection * conn; - int state; + struct mg_connection *conn; + int state; } static ws_clients[MAX_WS_CLIENTS]; -#define ASSERT(x) {if (!(x)) {fprintf(stderr, "Assertion failed in line %u\n", (unsigned)__LINE__);}} +#define ASSERT(x) \ + { \ + if (!(x)) { \ + fprintf( \ + stderr, "Assertion failed in line %u\n", (unsigned)__LINE__); \ + } \ + } static unsigned long cnt; -int WebSocketConnectHandler(const struct mg_connection * conn, void *cbdata) +int WebSocketConnectHandler(const struct mg_connection *conn, void *cbdata) { - struct mg_context *ctx = mg_get_context(conn); - int reject = 1; - int i; + struct mg_context *ctx = mg_get_context(conn); + int reject = 1; + int i; - mg_lock_context(ctx); - for (i=0; iconn == conn); - ASSERT(client->state == 1); + mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text)); + fprintf(stdout, "Greeting message sent to websocket client\r\n\r\n"); + ASSERT(client->conn == conn); + ASSERT(client->state == 1); - client->state = 2; + client->state = 2; } -int WebsocketDataHandler(struct mg_connection * conn, int bits, char * data, size_t len, void *cbdata) +int WebsocketDataHandler(struct mg_connection *conn, + int bits, + char *data, + size_t len, + void *cbdata) { - struct t_ws_client * client = mg_get_user_connection_data(conn); - ASSERT(client->conn == conn); - ASSERT(client->state >= 1); + struct t_ws_client *client = mg_get_user_connection_data(conn); + ASSERT(client->conn == conn); + ASSERT(client->state >= 1); - fprintf(stdout, "Websocket got data:\r\n"); - fwrite(data, len, 1, stdout); - fprintf(stdout, "\r\n\r\n"); + fprintf(stdout, "Websocket got data:\r\n"); + fwrite(data, len, 1, stdout); + fprintf(stdout, "\r\n\r\n"); - return 1; + return 1; } -void WebSocketCloseHandler(const struct mg_connection * conn, void *cbdata) +void WebSocketCloseHandler(const struct mg_connection *conn, void *cbdata) { - struct mg_context *ctx = mg_get_context(conn); - struct t_ws_client * client = mg_get_user_connection_data(conn); - ASSERT(client->conn == conn); - ASSERT(client->state >= 1); + struct mg_context *ctx = mg_get_context(conn); + struct t_ws_client *client = mg_get_user_connection_data(conn); + ASSERT(client->conn == conn); + ASSERT(client->state >= 1); - mg_lock_context(ctx); - client->state = 0; - client->conn = NULL; - mg_unlock_context(ctx); + mg_lock_context(ctx); + client->state = 0; + client->conn = NULL; + mg_unlock_context(ctx); - fprintf(stdout, "Client droped from the set of webserver connections\r\n\r\n"); + fprintf(stdout, + "Client droped from the set of webserver connections\r\n\r\n"); } void InformWebsockets(struct mg_context *ctx) { - char text[32]; - int i; + char text[32]; + int i; - sprintf(text, "%lu", ++cnt); + sprintf(text, "%lu", ++cnt); - mg_lock_context(ctx); - for (i=0; ilistening_sockets[i].lsa.sa.sa_family == AF_INET6) { /* IPv6 */ - ports[cnt].protocol = 2; + ports[cnt].protocol = 3; cnt++; } }