/*
  This file is part of libmicrohttpd
  Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
 * @file lib/action_suspend.c
 * @brief implementation of MHD_action_suspend()
 * @author Christian Grothoff
 */
#include "internal.h"


/**
 * The suspend action is being run.  Suspend handling
 * of the given request.
 *
 * @param cls NULL
 * @param request the request to apply the action to
 * @return #MHD_SC_OK on success
 */
static enum MHD_StatusCode
suspend_action (void *cls,
                struct MHD_Request *request)
{
  (void) cls;
  struct MHD_Connection *connection = request->connection;
  struct MHD_Daemon *daemon = connection->daemon;

  MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
  if (connection->resuming)
  {
    /* suspending again while we didn't even complete resuming yet */
    connection->resuming = false;
    MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
    return MHD_SC_OK;
  }
  if (daemon->threading_mode != MHD_TM_THREAD_PER_CONNECTION)
  {
    if (connection->connection_timeout ==
        daemon->connection_default_timeout)
      XDLL_remove (daemon->normal_timeout_head,
                   daemon->normal_timeout_tail,
                   connection);
    else
      XDLL_remove (daemon->manual_timeout_head,
                   daemon->manual_timeout_tail,
                   connection);
  }
  DLL_remove (daemon->connections_head,
              daemon->connections_tail,
              connection);
  mhd_assert (! connection->suspended);
  DLL_insert (daemon->suspended_connections_head,
              daemon->suspended_connections_tail,
              connection);
  connection->suspended = true;
#ifdef EPOLL_SUPPORT
  if (MHD_ELS_EPOLL == daemon->event_loop_syscall)
  {
    if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL))
    {
      EDLL_remove (daemon->eready_head,
                   daemon->eready_tail,
                   connection);
      connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
    }
    if (0 != (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET))
    {
      if (0 != epoll_ctl (daemon->epoll_fd,
                          EPOLL_CTL_DEL,
                          connection->socket_fd,
                          NULL))
        MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
      connection->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET;
    }
    connection->epoll_state |= MHD_EPOLL_STATE_SUSPENDED;
  }
#endif
  MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
  return MHD_SC_OK;
}


/**
 * Suspend handling of network data for a given request.  This can
 * be used to dequeue a request from MHD's event loop for a while.
 *
 * If you use this API in conjunction with a internal select or a
 * thread pool, you must set the option #MHD_USE_ITC to
 * ensure that a resumed request is immediately processed by MHD.
 *
 * Suspended requests continue to count against the total number of
 * requests allowed (per daemon, as well as per IP, if such limits
 * are set).  Suspended requests will NOT time out; timeouts will
 * restart when the request handling is resumed.  While a
 * request is suspended, MHD will not detect disconnects by the
 * client.
 *
 * The only safe time to suspend a request is from either a
 * #MHD_RequestHeaderCallback, #MHD_UploadCallback, or a
 * #MHD_RequestfetchResponseCallback.  Suspending a request
 * at any other time will cause an assertion failure.
 *
 * Finally, it is an API violation to call #MHD_daemon_stop() while
 * having suspended requests (this will at least create memory and
 * socket leaks or lead to undefined behavior).  You must explicitly
 * resume all requests before stopping the daemon.
 *
 * @return action to cause a request to be suspended.
 */
const struct MHD_Action *
MHD_action_suspend (void)
{
  static const struct MHD_Action suspend = {
    .action = &suspend_action,
    .action_cls = NULL
  };

  return &suspend;
}


/* end of action_suspend.c */
