Blame view

examples/http.c 3.93 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2 3
   Copyright (C) 1999-2001, 2004, 2007, 2010-2012, 2014-2015 Free
   Software Foundation, Inc.
4

5
   GNU Mailutils is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3, or (at your option)
8 9
   any later version.

10
   GNU Mailutils is distributed in the hope that it will be useful,
11 12 13 14 15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
16
   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
17 18 19 20

/* This is an example program to illustrate the use of stream functions.
   It connects to a remote HTTP server and prints the contents of its
   index page */
21

22 23 24
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
25
#include <stdio.h>
Wojciech Polak authored
26
#include <stdlib.h>
27
#include <string.h>
Wojciech Polak authored
28
#include <errno.h>
29
#include <unistd.h>
30
#include <sys/time.h>
31 32 33

#include <mailutils/mailutils.h>

34
char wbuf[1024];
35 36
char rbuf[1024];

37 38 39
size_t io_timeout = 3;
size_t io_attempts = 3;

40
int
41
http_stream_wait (mu_stream_t stream, int flags, size_t *attempt)
42 43 44 45 46 47 48 49 50
{
  int rc;
  int oflags = flags;
  struct timeval tv;

  while (*attempt < io_attempts)
    {
      tv.tv_sec = io_timeout;
      tv.tv_usec = 0;
51
      rc = mu_stream_wait (stream, &oflags, &tv);
52 53 54 55 56 57 58 59 60 61 62 63 64 65
      switch (rc)
	{
	case 0:
	  if (flags & oflags)
	    return 0;
	  /* FALLTHROUGH */
	case EAGAIN:
	case EINPROGRESS:
	  ++*attempt;
	  continue;
	  
	default:
	  return rc;
	}
66 67 68 69 70 71
    }
  return ETIMEDOUT;
}

int
main (int argc, char **argv)
72
{
73
  int ret;
74
  mu_stream_t stream;
75
  size_t nb;
76 77 78 79 80 81 82 83
  size_t attempt;
  char *url = "www.gnu.org";

  if (argc > 3)
    {
      fprintf (stderr, "usage: %s [hostname [url]]\n", argv[0]);
      exit (1);
    }
84
  
85 86 87 88 89 90
  if (argc > 1)
    url = argv[1];
  
  snprintf (wbuf, sizeof wbuf, "GET %s HTTP/1.0\r\n\r\n",
	    argc == 3 ? argv[2] : "/");

91
  ret = mu_tcp_stream_create (&stream, url, 80, MU_STREAM_NONBLOCK);
92
  if (ret != 0 && !(ret == EAGAIN || ret == EINPROGRESS))
93
    {
94
      mu_error ("mu_tcp_stream_create: %s", mu_strerror (ret));
95 96 97
      exit (EXIT_FAILURE);
    }

98
  for (attempt = 0; ret; )
99
    {
100 101 102 103
      if ((ret == EAGAIN || ret == EINPROGRESS) && attempt < io_attempts)
	{
	  ret = http_stream_wait(stream, MU_STREAM_READY_WR, &attempt);
	  if (ret == 0)
Sergey Poznyakoff authored
104 105 106 107
	    {
	      ret = mu_stream_open (stream);
	      continue;
	    }
108
	}
109
      mu_error ("mu_stream_open: %s", mu_strerror (ret));
110 111 112
      exit (EXIT_FAILURE);
    }

113
  for (attempt = 0;; )
114
    {
115
      ret = mu_stream_write (stream, wbuf, strlen (wbuf), NULL);
116
      if (ret == 0)
117
	break;
118
      else if (ret == EAGAIN)
119
        {
120 121 122 123 124 125 126 127 128 129 130 131
	  if (attempt < io_attempts)
	    {
	      ret = http_stream_wait (stream, MU_STREAM_READY_WR, &attempt);
	      if (ret)
		{
		  mu_error ("http_wait failed: %s", mu_strerror (ret));
		  return -1;
		}
	      continue;
	    }
	  else
	    {
132
	      mu_error ("mu_stream_write timed out");
133 134 135 136 137
	      exit (EXIT_FAILURE);
	    }
	}
      else
	{
138
	  mu_error ("mu_stream_write: %s", mu_strerror (ret));
139 140
	  exit (EXIT_FAILURE);
	}
141 142
    }

143 144
  attempt = 0;
  for (;;)
145
    {
146
      ret = mu_stream_read (stream, rbuf, sizeof (rbuf), &nb);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
      if (ret == 0)
	{
	  if (nb == 0)
	    break;
	  write (1, rbuf, nb);
	}
      else if (ret == EAGAIN)
	{
	  if (attempt < io_attempts)
	    {
	      ret = http_stream_wait (stream, MU_STREAM_READY_RD, &attempt);
	      if (ret)
		{
		  mu_error ("http_stream_wait failed: %s", mu_strerror (ret));
		  exit (EXIT_FAILURE);
		}
	    }
	  else
	    {
166
	      mu_error ("mu_stream_read: %s", mu_strerror (ret));
167 168 169
	      exit (EXIT_FAILURE);
	    }
	}
170 171
    }

172
  ret = mu_stream_close (stream);
173 174
  if (ret != 0)
    {
175
      mu_error ("mu_stream_close: %s", mu_strerror (ret));
176 177 178
      exit (EXIT_FAILURE);
    }

179
  mu_stream_destroy (&stream);
180 181
  exit (EXIT_SUCCESS);
}