Blame src/testcurl/test_callback.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2009, 2011 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 2, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
/**
Packit 875988
 * @file test_callback.c
Packit 875988
 * @brief Testcase for MHD not calling the callback too often
Packit 875988
 * @author Jan Seeger
Packit 875988
 * @author Christian Grothoff
Packit 875988
 */
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <curl/curl.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
Packit 875988
struct callback_closure
Packit 875988
{
Packit 875988
  unsigned int called;
Packit 875988
};
Packit 875988
Packit 875988
Packit 875988
static ssize_t
Packit 875988
called_twice(void *cls, uint64_t pos, char *buf, size_t max)
Packit 875988
{
Packit 875988
  struct callback_closure *cls2 = cls;
Packit 875988
  (void)pos;    /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (cls2->called == 0)
Packit 875988
    {
Packit 875988
      memset(buf, 0, max);
Packit 875988
      strcat(buf, "test");
Packit 875988
      cls2->called = 1;
Packit 875988
      return strlen(buf);
Packit 875988
    }
Packit 875988
  if (cls2->called == 1)
Packit 875988
    {
Packit 875988
      cls2->called = 2;
Packit 875988
      return MHD_CONTENT_READER_END_OF_STREAM;
Packit 875988
    }
Packit 875988
  fprintf(stderr,
Packit 875988
	  "Handler called after returning END_OF_STREAM!\n");
Packit 875988
  return MHD_CONTENT_READER_END_WITH_ERROR;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
callback(void *cls,
Packit 875988
         struct MHD_Connection *connection,
Packit 875988
         const char *url,
Packit 875988
	 const char *method,
Packit 875988
         const char *version,
Packit 875988
         const char *upload_data,
Packit 875988
	 size_t *upload_data_size,
Packit 875988
         void **con_cls)
Packit 875988
{
Packit 875988
  struct callback_closure *cbc = calloc(1, sizeof(struct callback_closure));
Packit 875988
  struct MHD_Response *r;
Packit 875988
  int ret;
Packit 875988
  (void)cls;(void)url;                          /* Unused. Silent compiler warning. */
Packit 875988
  (void)method;(void)version;(void)upload_data; /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data_size;(void)con_cls;         /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  r = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN, 1024,
Packit 875988
					 &called_twice, cbc,
Packit 875988
					 &free);
Packit 875988
  if (NULL == r)
Packit 875988
  {
Packit 875988
    free (cbc);
Packit 875988
    return MHD_NO;
Packit 875988
  }
Packit 875988
  ret = MHD_queue_response (connection,
Packit 875988
                            MHD_HTTP_OK,
Packit 875988
                            r);
Packit 875988
  MHD_destroy_response (r);
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static size_t
Packit 875988
discard_buffer (void *ptr,
Packit 875988
                size_t size,
Packit 875988
                size_t nmemb,
Packit 875988
                void *ctx)
Packit 875988
{
Packit 875988
  (void)ptr;(void)ctx;  /* Unused. Silent compiler warning. */
Packit 875988
  return size * nmemb;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main(int argc, char **argv)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  fd_set rs;
Packit 875988
  fd_set ws;
Packit 875988
  fd_set es;
Packit 875988
  MHD_socket maxsock;
Packit 875988
#ifdef MHD_WINSOCK_SOCKETS
Packit 875988
  int maxposixs; /* Max socket number unused on W32 */
Packit 875988
#else  /* MHD_POSIX_SOCKETS */
Packit 875988
#define maxposixs maxsock
Packit 875988
#endif /* MHD_POSIX_SOCKETS */
Packit 875988
  CURL *c;
Packit 875988
  CURLM *multi;
Packit 875988
  CURLMcode mret;
Packit 875988
  struct CURLMsg *msg;
Packit 875988
  int running;
Packit 875988
  struct timeval tv;
Packit 875988
  int extra;
Packit 875988
  int port;
Packit 875988
  (void)argc; (void)argv; /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    port = 1140;
Packit 875988
Packit 875988
  d = MHD_start_daemon(0,
Packit 875988
		       port,
Packit 875988
		       NULL,
Packit 875988
		       NULL,
Packit 875988
		       &callback,
Packit 875988
		       NULL,
Packit 875988
		       MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 32;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 48; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, "http://127.0.0.1/");
Packit 875988
  curl_easy_setopt (c, CURLOPT_PORT, (long)port);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &discard_buffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
  multi = curl_multi_init ();
Packit 875988
  if (multi == NULL)
Packit 875988
    {
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
  mret = curl_multi_add_handle (multi, c);
Packit 875988
  if (mret != CURLM_OK)
Packit 875988
    {
Packit 875988
      curl_multi_cleanup (multi);
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 2;
Packit 875988
    }
Packit 875988
  extra = 10;
Packit 875988
  while ( (c != NULL) || (--extra > 0) )
Packit 875988
    {
Packit 875988
      maxsock = MHD_INVALID_SOCKET;
Packit 875988
      maxposixs = -1;
Packit 875988
      FD_ZERO(&ws);
Packit 875988
      FD_ZERO(&rs);
Packit 875988
      FD_ZERO(&es);
Packit 875988
      curl_multi_perform (multi, &running);
Packit 875988
      if (NULL != multi)
Packit 875988
	{
Packit 875988
	  mret = curl_multi_fdset (multi, &rs, &ws, &es, &maxposixs);
Packit 875988
	  if (mret != CURLM_OK)
Packit 875988
	    {
Packit 875988
	      curl_multi_remove_handle (multi, c);
Packit 875988
	      curl_multi_cleanup (multi);
Packit 875988
	      curl_easy_cleanup (c);
Packit 875988
	      MHD_stop_daemon (d);
Packit 875988
	      return 3;
Packit 875988
	    }
Packit 875988
	}
Packit 875988
      if (MHD_YES !=
Packit 875988
	  MHD_get_fdset(d, &rs, &ws, &es, &maxsock))
Packit 875988
	{
Packit 875988
          curl_multi_remove_handle (multi, c);
Packit 875988
          curl_multi_cleanup (multi);
Packit 875988
          curl_easy_cleanup (c);
Packit 875988
          MHD_stop_daemon (d);
Packit 875988
	  return 4;
Packit 875988
	}
Packit 875988
      tv.tv_sec = 0;
Packit 875988
      tv.tv_usec = 1000;
Packit 875988
      if (-1 == select (maxposixs + 1, &rs, &ws, &es, &tv))
Packit 875988
        {
Packit 875988
#ifdef MHD_POSIX_SOCKETS
Packit 875988
              if (EINTR != errno)
Packit 875988
                abort ();
Packit 875988
#else
Packit 875988
              if (WSAEINVAL != WSAGetLastError() || 0 != rs.fd_count || 0 != ws.fd_count || 0 != es.fd_count)
Packit 875988
                abort ();
Packit 875988
              Sleep (1000);
Packit 875988
#endif
Packit 875988
        }
Packit 875988
      if (NULL != multi)
Packit 875988
	{
Packit 875988
	  curl_multi_perform (multi, &running);
Packit 875988
	  if (running == 0)
Packit 875988
	    {
Packit 875988
	      msg = curl_multi_info_read (multi, &running);
Packit 875988
	      if (msg == NULL)
Packit 875988
		break;
Packit 875988
	      if (msg->msg == CURLMSG_DONE)
Packit 875988
		{
Packit 875988
		  if (msg->data.result != CURLE_OK)
Packit 875988
		    printf ("%s failed at %s:%d: `%s'\n",
Packit 875988
			    "curl_multi_perform",
Packit 875988
			    __FILE__,
Packit 875988
			    __LINE__, curl_easy_strerror (msg->data.result));
Packit 875988
		  curl_multi_remove_handle (multi, c);
Packit 875988
		  curl_multi_cleanup (multi);
Packit 875988
		  curl_easy_cleanup (c);
Packit 875988
		  c = NULL;
Packit 875988
		  multi = NULL;
Packit 875988
		}
Packit 875988
	    }
Packit 875988
	}
Packit 875988
      MHD_run(d);
Packit 875988
    }
Packit 875988
  MHD_stop_daemon(d);
Packit 875988
  return 0;
Packit 875988
}