source: trunk/third/libghttp/http_trans.c @ 15592

Revision 15592, 7.6 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15591, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * http_trans.c -- Functions for doing transport related stuff including
3 * automatically extending buffers and whatnot.
4 * Created: Christopher Blizzard <blizzard@appliedtheory.com>, 5-Aug-1998
5 *
6 * Copyright (C) 1998 Free Software Foundation
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <sys/time.h>
24#include <sys/types.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include <string.h>
28#include <errno.h>
29#include "http_trans.h"
30#include "http_global.h"
31
32static int
33http_trans_buf_free(http_trans_conn *a_conn);
34
35int
36http_trans_connect(http_trans_conn *a_conn)
37{
38  if ((a_conn == NULL) || (a_conn->host == NULL))
39    goto ec;
40  if (a_conn->hostinfo == NULL)
41    {
42      /* look up the name of the proxy if it's there. */
43      if (a_conn->proxy_host)
44        {
45          if ((a_conn->hostinfo = gethostbyname(a_conn->proxy_host)) == NULL)
46            {
47              a_conn->error_type = http_trans_err_type_host;
48              a_conn->error = h_errno;
49              goto ec;
50            }
51        }
52      else
53        {
54          /* look up the name */
55          if ((a_conn->hostinfo = gethostbyname(a_conn->host)) == NULL)
56            {
57              a_conn->error_type = http_trans_err_type_host;
58              a_conn->error = h_errno;
59              goto ec;
60            }
61        }
62      /* set up the saddr */
63      a_conn->saddr.sin_family = AF_INET;
64      /* set the proxy port */
65      if (a_conn->proxy_host)
66        a_conn->saddr.sin_port = htons(a_conn->proxy_port);
67      else
68        a_conn->saddr.sin_port = htons(a_conn->port);
69      /* copy the name info */
70      memcpy(&a_conn->saddr.sin_addr.s_addr,
71             a_conn->hostinfo->h_addr_list[0],
72             sizeof(unsigned long));
73    }
74  /* set up the socket */
75  if ((a_conn->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
76    {
77      a_conn->error_type = http_trans_err_type_errno;
78      a_conn->error = errno;
79      goto ec;
80    }
81  /* set up the socket */
82  if (connect(a_conn->sock,
83              (struct sockaddr *)&a_conn->saddr,
84              sizeof(struct sockaddr)) < 0)
85    {
86      a_conn->error_type = http_trans_err_type_errno;
87      a_conn->error = errno;
88      goto ec;
89    }
90 
91  return 0;
92 ec:
93  return -1;
94}
95
96http_trans_conn *
97http_trans_conn_new(void)
98{
99  http_trans_conn *l_return = NULL;
100
101  /* allocate a new connection struct */
102  l_return = (http_trans_conn *)malloc(sizeof(http_trans_conn));
103  memset(l_return, 0, sizeof(http_trans_conn));
104  /* default to 80 */
105  l_return->port = 80;
106  /* default to 1000 bytes at a time */
107  l_return->io_buf_chunksize = 1024;
108  /* allocate a new trans buffer */
109  l_return->io_buf = malloc(l_return->io_buf_chunksize);
110  memset(l_return->io_buf, 0, l_return->io_buf_chunksize);
111  l_return->io_buf_len = l_return->io_buf_chunksize;
112  /* make sure the socket looks like it's closed */
113  l_return->sock = -1;
114  return l_return;
115}
116
117void
118http_trans_conn_destroy(http_trans_conn *a_conn)
119{
120  /* destroy the connection structure. */
121  if (a_conn == NULL)
122    return;
123  if (a_conn->io_buf)
124    free(a_conn->io_buf);
125  if (a_conn->sock != -1)
126    close(a_conn->sock);
127  free(a_conn);
128  return;
129}
130
131const char *
132http_trans_get_host_error(int a_herror)
133{
134  switch (a_herror)
135    {
136    case HOST_NOT_FOUND:
137      return "Host not found";
138    case NO_ADDRESS:
139      return "An address is not associated with that host";
140    case NO_RECOVERY:
141      return "An unrecoverable name server error occured";
142    case TRY_AGAIN:
143      return "A temporary error occurred on an authoritative name server.  Please try again later.";
144    default:
145      return "No error or error not known.";
146    }
147}
148
149int
150http_trans_append_data_to_buf(http_trans_conn *a_conn,
151                              char *a_data,
152                              int   a_data_len)
153{
154  if (http_trans_buf_free(a_conn) < a_data_len)
155    {
156      a_conn->io_buf = realloc(a_conn->io_buf, a_conn->io_buf_len + a_data_len);
157      a_conn->io_buf_len += a_data_len;
158    }
159  memcpy(&a_conn->io_buf[a_conn->io_buf_alloc], a_data, a_data_len);
160  a_conn->io_buf_alloc += a_data_len;
161  return 1;
162}
163
164int
165http_trans_read_into_buf(http_trans_conn *a_conn)
166{
167  int l_read = 0;
168  int l_bytes_to_read = 0;
169
170  /* set the length if this is the first time */
171  if (a_conn->io_buf_io_left == 0)
172    {
173      a_conn->io_buf_io_left = a_conn->io_buf_chunksize;
174      a_conn->io_buf_io_done = 0;
175    }
176  /* make sure there's enough space */
177  if (http_trans_buf_free(a_conn) < a_conn->io_buf_io_left)
178    {
179      a_conn->io_buf = realloc(a_conn->io_buf,
180                               a_conn->io_buf_len + a_conn->io_buf_io_left);
181      a_conn->io_buf_len += a_conn->io_buf_io_left;
182    }
183  /* check to see how much we should try to read */
184  if (a_conn->io_buf_io_left > a_conn->io_buf_chunksize)
185    l_bytes_to_read = a_conn->io_buf_chunksize;
186  else
187    l_bytes_to_read = a_conn->io_buf_io_left;
188  /* read in some data */
189  if ((a_conn->last_read = l_read = read(a_conn->sock,
190                                         &a_conn->io_buf[a_conn->io_buf_alloc],
191                                         l_bytes_to_read)) < 0)
192    {
193      if (errno == EINTR)
194        l_read = 0;
195      else
196        return HTTP_TRANS_ERR;
197    }
198  else if (l_read == 0)
199    return HTTP_TRANS_DONE;
200  /* mark the buffer */
201  a_conn->io_buf_io_left -= l_read;
202  a_conn->io_buf_io_done += l_read;
203  a_conn->io_buf_alloc += l_read;
204  /* generate the result */
205  if (a_conn->io_buf_io_left == 0)
206    return HTTP_TRANS_DONE;
207  return HTTP_TRANS_NOT_DONE;
208}
209
210int
211http_trans_write_buf(http_trans_conn *a_conn)
212{
213  int l_written = 0;
214
215  if (a_conn->io_buf_io_left == 0)
216    {
217      a_conn->io_buf_io_left = a_conn->io_buf_alloc;
218      a_conn->io_buf_io_done = 0;
219    }
220  /* write out some data */
221  if ((a_conn->last_read = l_written = write (a_conn->sock,
222                                              &a_conn->io_buf[a_conn->io_buf_io_done],
223                                              a_conn->io_buf_io_left)) <= 0)
224    {
225      if (errno == EINTR)
226        l_written = 0;
227      else
228        return HTTP_TRANS_ERR;
229    }
230  if (l_written == 0)
231    return HTTP_TRANS_DONE;
232  /* advance the counters */
233  a_conn->io_buf_io_left -= l_written;
234  a_conn->io_buf_io_done += l_written;
235  if (a_conn->io_buf_io_left == 0)
236    return HTTP_TRANS_DONE;
237  return HTTP_TRANS_NOT_DONE;
238}
239
240void
241http_trans_buf_reset(http_trans_conn *a_conn)
242{
243  if (a_conn->io_buf)
244    free(a_conn->io_buf);
245  a_conn->io_buf = malloc(a_conn->io_buf_chunksize);
246  memset(a_conn->io_buf, 0, a_conn->io_buf_chunksize);
247  a_conn->io_buf_len = a_conn->io_buf_chunksize;
248  a_conn->io_buf_alloc = 0;
249  a_conn->io_buf_io_done = 0;
250  a_conn->io_buf_io_left = 0;
251}
252
253void
254http_trans_buf_clip(http_trans_conn *a_conn, char *a_clip_to)
255{
256  int l_bytes = 0;
257 
258  /* get the number of bytes to clip off of the front */
259  l_bytes = a_clip_to - a_conn->io_buf;
260  if (l_bytes > 0)
261    {
262      memmove(a_conn->io_buf, a_clip_to, a_conn->io_buf_alloc - l_bytes);
263      a_conn->io_buf_alloc -= l_bytes;
264    }
265  a_conn->io_buf_io_done = 0;
266  a_conn->io_buf_io_left = 0;
267}
268
269char *
270http_trans_buf_has_patt(char *a_buf, int a_len,
271                        char *a_pat, int a_patlen)
272{
273  int i = 0;
274  for ( ; i <= ( a_len - a_patlen ); i++ )
275    {
276      if (a_buf[i] == a_pat[0])
277        {
278          if (memcmp(&a_buf[i], a_pat, a_patlen) == 0)
279            return &a_buf[i];
280        }
281    }
282  return NULL;
283}
284
285/* static functions */
286
287static int
288http_trans_buf_free(http_trans_conn *a_conn)
289{
290  return (a_conn->io_buf_len - a_conn->io_buf_alloc);
291}
Note: See TracBrowser for help on using the repository browser.