add-enable-nofork-config-option.patch
authorAndy Green <andy@warmcat.com>
Thu, 20 Jan 2011 10:23:50 +0000 (10:23 +0000)
committerAndy Green <andy@warmcat.com>
Thu, 20 Jan 2011 10:23:50 +0000 (10:23 +0000)
Signed-off-by: Andy Green <andy@warmcat.com>
README-test-server
configure
configure.ac
lib/libwebsockets.c
lib/private-libwebsockets.h
test-server/test-server.c

index 2f14e17..4b30fab 100644 (file)
@@ -15,6 +15,9 @@ $ libwebsockets-test-server
 
 should be enough to get a test server listening on port 7861.
 
+Testing
+-------
+
 If you point your browser (eg, Chrome) to
 
   http://127.0.0.1:7681
@@ -23,6 +26,9 @@ It will fetch a script in the form of test.html, and then run the
 script in there on the browser to open a websocket connection.
 Incrementing numbers should appear in the browser display.
 
+Using SSL
+---------
+
 To test it using SSL/WSS, just run the test server with
 
 $ libwebsockets-test-server --ssl
@@ -41,5 +47,23 @@ same.
 test-server.c is all that is needed to use libwebsockets for
 serving both the script html over http and websockets.
 
-2010-11-08  Andy Green <andy@warmcat.com>
+Forkless operation
+------------------
+
+If your target device does not offer fork(), you can use
+libwebsockets from your own main loop instead.  Use the
+configure option --nofork and simply call libwebsocket_service()
+from your own main loop as shown in the test app sources.
+
+
+Websocket version supported
+---------------------------
+
+Right now this is tested and working on websockets protocol 76/00
+Untested code is in for 04 support, there is no browser support
+available yet to test it with.  Libwebsockets should autoselect
+between the supported versions according to what the browser
+asks for.
+
+2011-01-20  Andy Green <andy@warmcat.com>
 
index 03e9e84..123de5b 100755 (executable)
--- a/configure
+++ b/configure
@@ -735,6 +735,7 @@ with_gnu_ld
 with_sysroot
 enable_libtool_lock
 enable_openssl
+enable_nofork
 '
       ac_precious_vars='build_alias
 host_alias
@@ -1378,6 +1379,7 @@ Optional Features:
   --enable-dependency-tracking   do not reject slow dependency extractors
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --enable-openssl  Enables https support and needs openssl libs
+  --enable-nofork  Disables fork-related options
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1739,6 +1741,60 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_func
 
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+        return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+           return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
 # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
 # -------------------------------------------------------
 # Tests whether HEADER exists, giving a warning if it cannot be compiled using
@@ -1829,60 +1885,6 @@ fi
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_mongrel
-
-# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
-# -------------------------------------------
-# Tests whether TYPE exists after having included INCLUDES, setting cache
-# variable VAR accordingly.
-ac_fn_c_check_type ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=no"
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof ($2))
-        return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-int
-main ()
-{
-if (sizeof (($2)))
-           return 0;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  eval "$3=yes"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_type
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 CFLAGS="$CFLAGS -DLWS_OPENSSL_SUPPORT"
 fi
 
-
-
-# Checks for header files.
-for ac_header in fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+# Check whether --enable-nofork was given.
+if test "${enable_nofork+set}" = set; then :
+  enableval=$enable_nofork;  nofork=yes
 
 fi
 
-done
-
-
-# Checks for typedefs, structures, and compiler characteristics.
-ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
-if test "x$ac_cv_type_size_t" = xyes; then :
 
+if test "x$nofork" = "xyes" ; then
+CFLAGS="$CFLAGS -DLWS_NO_FORK"
 else
-
-cat >>confdefs.h <<_ACEOF
-#define size_t unsigned int
-_ACEOF
-
-fi
-
-
-# Checks for library functions.
 ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
 if test "x$ac_cv_type_pid_t" = xyes; then :
 
@@ -12269,6 +12250,40 @@ $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
 
 fi
 
+fi
+
+
+
+# Checks for header files.
+for ac_header in fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+
+# Checks for library functions.
+
 for ac_header in stdlib.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
index d3a407b..2ccdd68 100644 (file)
@@ -28,6 +28,17 @@ AC_CHECK_LIB([ssl], [SSL_library_init])
 CFLAGS="$CFLAGS -DLWS_OPENSSL_SUPPORT"
 fi
 
+AC_ARG_ENABLE(nofork,
+ [  --enable-nofork  Disables fork-related options],
+ [ nofork=yes
+ ])
+
+if test "x$nofork" = "xyes" ; then
+CFLAGS="$CFLAGS -DLWS_NO_FORK"
+else
+AC_FUNC_FORK
+fi
+
 
 
 # Checks for header files.
@@ -37,7 +48,7 @@ AC_CHECK_HEADERS([fcntl.h netinet/in.h stdlib.h string.h sys/socket.h unistd.h])
 AC_TYPE_SIZE_T
 
 # Checks for library functions.
-AC_FUNC_FORK
+
 AC_FUNC_MALLOC
 AC_FUNC_REALLOC
 AC_CHECK_FUNCS([bzero memset socket strerror])
index 1ba4410..5aa7c26 100644 (file)
@@ -617,6 +617,8 @@ libwebsocket_create_server(int port,
        return this;
 }
 
+#ifndef LWS_NO_FORK
+
 /**
  * libwebsockets_fork_service_loop() - Optional helper function forks off
  *                               a process for the websocket server loop.
@@ -635,29 +637,38 @@ libwebsockets_fork_service_loop(struct libwebsocket_context *this)
        struct sockaddr_in cli_addr;
        int n;
 
-       if (fork())
-               return 0;
+       n = fork();
+       if (n < 0)
+               return n;
 
-       for (client = 1; client < this->count_protocols + 1; client++) {
-               fd = socket(AF_INET, SOCK_STREAM, 0);
-               if (fd < 0) {
-                       fprintf(stderr, "Unable to create socket\n");
-                       return -1;
-               }
-               cli_addr.sin_family = AF_INET;
-               cli_addr.sin_port = htons(
-                          this->protocols[client - 1].broadcast_socket_port);
-               cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
-               n = connect(fd, (struct sockaddr *)&cli_addr,
-                                                      sizeof cli_addr);
-               if (n < 0) {
-                       fprintf(stderr, "Unable to connect to "
-                                       "broadcast socket %d, %s\n",
-                                       client, strerror(errno));
-                       return -1;
+       if (!n) {
+
+               /* main process context */
+
+               for (client = 1; client < this->count_protocols + 1; client++) {
+                       fd = socket(AF_INET, SOCK_STREAM, 0);
+                       if (fd < 0) {
+                               fprintf(stderr, "Unable to create socket\n");
+                               return -1;
+                       }
+                       cli_addr.sin_family = AF_INET;
+                       cli_addr.sin_port = htons(
+                                  this->protocols[client - 1].broadcast_socket_port);
+                       cli_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+                       n = connect(fd, (struct sockaddr *)&cli_addr,
+                                                              sizeof cli_addr);
+                       if (n < 0) {
+                               fprintf(stderr, "Unable to connect to "
+                                               "broadcast socket %d, %s\n",
+                                               client, strerror(errno));
+                               return -1;
+                       }
+
+                       this->protocols[client - 1].broadcast_socket_user_fd = fd;
                }
 
-               this->protocols[client - 1].broadcast_socket_user_fd = fd;
+
+               return 0;
        }
 
        /* we want a SIGHUP when our parent goes down */
@@ -672,6 +683,8 @@ libwebsockets_fork_service_loop(struct libwebsocket_context *this)
        return 0;
 }
 
+#endif
+
 /**
  * libwebsockets_get_protocol() - Returns a protocol pointer from a websocket
  *                               connection.
index 327e09c..a63d902 100644 (file)
@@ -32,7 +32,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
+#ifndef LWS_NO_FORK
 #include <sys/prctl.h>
+#endif
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
index 3365c0f..36a1978 100644 (file)
@@ -264,12 +264,15 @@ int main(int argc, char **argv)
                return -1;
        }
 
+       buf[LWS_SEND_BUFFER_PRE_PADDING] = 'x';
+
+#ifdef LWS_NO_FORK
+
        /*
-        * After initializing and creating the websocket server in its own fork
-        * we return to the main process here
+        * This example shows how to work with no forked service loop
         */
 
-       buf[LWS_SEND_BUFFER_PRE_PADDING] = 'x';
+       fprintf(stderr, " Using no-fork service loop\n");
 
        while (1) {
                
@@ -297,14 +300,54 @@ int main(int argc, char **argv)
                 * we have to give the websockets an opportunity to service
                 * "manually".
                 *
-                * There's an optional call libwebsockets_fork_service_loop()
-                * we could have used before this while loop, then the
-                * websockets would have been serviced in a forked process
-                * and we would not have to do the call below inside our loop.
+                * If no socket is needing service, the call below returns
+                * immediately and quickly.
                 */
 
                libwebsocket_service(server, 0);
        }
 
+#else
+
+       /*
+        * This example shows how to work with the forked websocket service loop
+        */
+
+       fprintf(stderr, " Using forked service loop\n");
+
+       /*
+        * This forks the websocket service action into a subprocess so we
+        * don't have to take care about it.
+        */
+
+       n = libwebsockets_fork_service_loop(server);
+       if (n < 0) {
+               fprintf(stderr, "Unable to fork service loop %d\n", n);
+               return 1;
+       }
+
+       while (1) {
+               
+               usleep(50000);
+
+               /*
+                * This broadcasts to all dumb-increment-protocol connections
+                * at 20Hz.
+                * 
+                * We're just sending a character 'x', in these examples the
+                * callbacks send their own per-connection content.
+                *
+                * You have to send something with nonzero length to get the
+                * callback actions delivered.
+                *
+                * We take care of pre-and-post padding allocation.
+                */
+
+               libwebsockets_broadcast(&protocols[PROTOCOL_DUMB_INCREMENT],
+                                       &buf[LWS_SEND_BUFFER_PRE_PADDING], 1);
+       }
+
+#endif
+
        return 0;
 }