Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    Logout button in popup window works but user gets no feedback

    Scheduled Pinned Locked Moved Captive Portal
    14 Posts 3 Posters 13.2k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • E
      eri--
      last edited by

      I am not sure to understand why the ipfw call impacts the flushing of the socket?

      1 Reply Last reply Reply Quote 0
      • L
        lsoltero
        last edited by

        But it does… try this...

        in the LAN enable the captive portal.  Make sure that the anti-lockout rule is in place which should allow connectivity to the box even if the captive portal is enabled.

        Ssh to the box and spawn a shell...  You should be able to get in because the web anti-lock rule allows you in.  Fire up the a web browser and try to go to a website... You should see the captive protal login. Login... now logout...

        you will notice that your ssh session will die... it will just hang there.  The socket is not closed properly to the shell does not see that there has been a disconnect. IP packets to the box are dropped...

        you have to do a ~. to disconnect and then you can ssh back to the box.

        I believe the same thing is happening to the client browser.  If you execute a logout page (not using the popup) which does a POST to index.php you will notice that the browser will just site there waiting... If you run firebug you will see that the HTML logout mesg does make it to the browser but since the socket is never closes and IP packets are just being dropped by the box the browser just goes into a "wait"... This happens in all browsers that I have tested.

        Mozilla is nice because it will display the HTML text as it arrives so even though it goes into a wait state the "Disconnecting..." mesg gets displayed.  Safari and other webkit friends do not display the text although I have confirmed that they have received it.

        I am about to do more testing on this.. My approach is to move the disconnect code to a shell script and then execute it with mwexe_bg and then continue with an exit in index.php. The shell script will sleep for 1 second and then execute the php code to do the disconnect...

        I will let you know how that test turns out. If my theory is correct the logout button should start to work properly since the HTML disconnect text is sent to the browser and the socket is closed before ipfw is called to close things off.

        --luis

        1 Reply Last reply Reply Quote 0
        • L
          lsoltero
          last edited by

          and guess what… my theory was correct and the following works beautifully and fixes the logout issue on ** ALL ** browsers including the popup logout window.

          Here is what I did... i created the following file in /usr/local/captiveportal/captiveportal-disconnect.php

          #!/usr/local/bin/php -f
          require_once("functions.inc");
          global $g, $config;

          $sessionid = $argv[1];
          $logoutReason = $argv[2];
          $term_cause = $argv[3];

          if ( $argc != 4 ||  $sessionid == "" || logoutReason == "" || $term_cause == "" )
             exit;

          $cplock = lock('captiveportal');

          /* read database */
          $cpdb = captiveportal_read_db();

          $radiusservers = captiveportal_get_radius_servers();

          /* find entry */
          for ($i = 0; $i < count($cpdb); $i++) {
             if ($cpdb[$i][5] == $sessionid) {
                 captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause);
                 captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
                 unset($cpdb[$i]);
                 break;
             }
          }

          /* write database */
          captiveportal_write_db($cpdb);

          unlock($cplock);

          ?>

          then I modified disconnect_client in index.php as follows

          function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) {
             mwexec_bg("/usr/local/captiveportal/captiveportal-disconnect.php $sessionid $logoutReason $term_cause");
          }

          the time it takes to the shell to spawn php and execute the logout is more than enough time for the HTML Disconnect mesg to make it back to the browser and for httpd to close the socket.

          One more thing… its probably better to move the call to disconnect_client in index.php to after the echo of the HTML Disconnect mesg. This way the mesg gets sent to the browser before the disconnect is started. Since mwexec is the very last thing that gets executed before index.php exits there is very little chance that the captive portal disconnect will happen before socket to the client is closed.

          Here is the code.

          if ($_POST['logout_id']) {
             echo << <eod<br><title>Disconnecting…</title>

          You have been disconnected.

          EOD;
             disconnect_client($_POST['logout_id']);
             exit;

          The logout is now ** VERY ** clean.

          Take care.

          –luis</eod<br>

          1 Reply Last reply Reply Quote 0
          • E
            eri--
            last edited by

            I put the client disconnect after the html is sent.
            It might need some php buffer flushing too but should be ok for now.

            Thank you for tracing.

            1 Reply Last reply Reply Quote 0
            • L
              lsoltero
              last edited by

              I see that all you did was move the call to disconnect_client() to after the html code. In our experimentation here that does nothing for solving the LOGOUT button issue that is discussed in the post.  As stated in my postings the HTML is making it to the web browser.  So… that is not the issue.  Running the console in Chrome, for example, shows that the LOGOUT HTML code made it to the browser. The problem is that the browser does not render the code until after the socket is closed by the server. The socket is never closed because ipfw shuts down the connection and from then on all IP  packets are dropped.  The connection is left hanging and the browser just spins away waiting for a response from the server.  The only way we have found to solve the problem is have the calls to ipfw happen in another process which executes after index.php exits and the sever closes the socket.

              So... your code change is pretty much a NOP.

              Let me know if you need further info.

              Take care.

              --luis

              1 Reply Last reply Reply Quote 0
              • jimpJ
                jimp Rebel Alliance Developer Netgate
                last edited by

                Try adding

                ob_flush();
                

                Just before the disconnect, maybe even

                ob_flush();
                sleep(1);
                

                To see if that makes a difference.

                Remember: Upvote with the 👍 button for any user/post you find to be helpful, informative, or deserving of recognition!

                Need help fast? Netgate Global Support!

                Do not Chat/PM for help!

                1 Reply Last reply Reply Quote 0
                • L
                  lsoltero
                  last edited by

                  I will try it but i doubt it will make any difference. As stated previously I am seeing the HTML code in the browser.  When you do this with mozilla the "Disconnected…." mesg actually is displayed.  But in all browsers the page just sits there with the rotating wait i am busy signal waiting for the server to close the socket.

                  ob_flush() just flushes the output buffers. It does not close the socket.  So... it doesn't help given that all of the HMTL code with the "Disconnect..." message has already made it the browser. As stated numerous times the problem with web browsers based in webkit is that these browsers will not render the HTML code until the socket is closed.  The socket is Never closed properly because the calls to ipfw are done synchronously before the index.php exits.   Once the ipfw calls are made the socket becomes unresponsive and all traffic between the client and pfsense are dropped. The as far as the browser is concerned the socket is open and it continues to wait for data which never arrives.  Hence the busy wait signal in ** ALL *** the browsers tested to date.

                  The only solution found so far is to execute the ipfw commands asynchronously after index.php has exited. As stated previously in this thread that works perfectly...

                  --luis

                  1 Reply Last reply Reply Quote 0
                  • E
                    eri--
                    last edited by

                    Can you try putting a closing php://output
                    Either with fclose() or stream_close().

                    1 Reply Last reply Reply Quote 0
                    • L
                      lsoltero
                      last edited by

                      I assume you mean as in

                      fclose(STDOUT);

                      that might work.  I will give that a shot and report back to you.

                      –luis

                      1 Reply Last reply Reply Quote 0
                      • L
                        lsoltero
                        last edited by

                        Hi have tried…

                        EOD;
                            fclose("php://stdin");
                            fclose("php://stdout");
                            fclose("php://stderr");
                            disconnect_client($_POST['logout_id']);

                        and

                        EOD;
                            fclose("STDIN");
                            fclose("STDOUT");
                            fclose("STDERR");
                            disconnect_client($_POST['logout_id']);

                        And neither work…

                        so far the only that works for me is the solution listed earlier in the post where the pfctl statements are done in another process.

                        --luis

                        1 Reply Last reply Reply Quote 0
                        • E
                          eri--
                          last edited by

                          how about in the case we discover logout action before calling exit just do

                          
                          register_shutdown_function(disconnect_client, $_POST['logout_id']);
                          
                          

                          That should do as well.

                          1 Reply Last reply Reply Quote 0
                          • L
                            lsoltero
                            last edited by

                            I will give it a try… the 64,000 question is... does php execute the function before or after it closes the descriptors. If it executes the function before closing the descriptors then it will not work...

                            --luis

                            1 Reply Last reply Reply Quote 0
                            • L
                              lsoltero
                              last edited by

                              This does not work…


                              if ($_POST['logout_id']) {
                                 echo << <eod<br><title>Disconnecting…</title>

                              You have been disconnected.

                              EOD;
                                 register_shutdown_function(disconnect_client,$_POST['logout_id']);
                                 exit;
                              –-

                              As stated before the only thing that I have been able to make work is this...

                              --- index.php 2011-02-06 16:24:13.000000000 +0000
                              +++ index.php.new 2011-02-06 16:16:27.000000000 +0000
                              @@ -412,29 +412,7 @@
                               */
                              function disconnect_client($sessionid, $logoutReason = "LOGOUT", $term_cause = 1) {

                              • global $g, $config;
                              • $cplock = lock('captiveportal');
                              • /* read database */
                              • $cpdb = captiveportal_read_db();
                              • $radiusservers = captiveportal_get_radius_servers();
                              • /* find entry */
                              • for ($i = 0; $i < count($cpdb); $i++) {
                              • if ($cpdb[$i][5] == $sessionid) {
                              • captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause);
                              • captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
                              • unset($cpdb[$i]);
                              • break;
                              • }
                              • }
                              • /* write database */
                              • captiveportal_write_db($cpdb);
                              • unlock($cplock);
                              • mwexec_bg("/usr/local/captiveportal/captiveportal-disconnect.php $sessionid $logoutReason $term_cause");

                              }

                              Where /usr/local/www/captiveportal/captiveportal-disconnect.php contains the following
                              –-
                              #!/usr/local/bin/php -f
                              require_once("functions.inc");
                              global $g, $config;

                              $sessionid = $argv[1];
                              $logoutReason = $argv[2];
                              $term_cause = $argv[3];

                              if ( $argc != 4 ||  $sessionid == "" || logoutReason == "" || $term_cause == "" )
                                 exit;

                              echo "$sessionid $logoutReason $term_cause";

                              $cplock = lock('captiveportal');

                              /* read database */
                              $cpdb = captiveportal_read_db();

                              $radiusservers = captiveportal_get_radius_servers();

                              /* find entry */
                              for ($i = 0; $i < count($cpdb); $i++) {
                                 if ($cpdb[$i][5] == $sessionid) {
                                     captiveportal_disconnect($cpdb[$i],$radiusservers, $term_cause);
                                     captiveportal_logportalauth($cpdb[$i][4],$cpdb[$i][3],$cpdb[$i][2],$logoutReason);
                                     unset($cpdb[$i]);
                                     break;
                                 }
                              }

                              /* write database */
                              captiveportal_write_db($cpdb);

                              unlock($cplock);

                              ?>
                              –-</eod<br>

                              1 Reply Last reply Reply Quote 0
                              • First post
                                Last post
                              Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.