doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sendf.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id: sendf.c,v 1.80 2004/03/10 09:50:12 bagder Exp $
22  ***************************************************************************/
23 
24 #include "setup.h"
25 
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
34 
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h> /* required for send() & recv() prototypes */
37 #endif
38 
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 
43 #include <curl/curl.h>
44 #include "urldata.h"
45 #include "sendf.h"
46 #include "connect.h" /* for the Curl_ourerrno() proto */
47 
48 #define _MPRINTF_REPLACE /* use the internal *printf() functions */
49 #include <curl/mprintf.h>
50 
51 #ifdef HAVE_KRB4
52 #include "security.h"
53 #endif
54 #include <string.h>
55 /* The last #include file should be: */
56 #ifdef CURLDEBUG
57 #include "memdebug.h"
58 #endif
59 
60 /* returns last node in linked list */
61 static struct curl_slist *slist_get_last(struct curl_slist *list)
62 {
63  struct curl_slist *item;
64 
65  /* if caller passed us a NULL, return now */
66  if (!list)
67  return NULL;
68 
69  /* loop through to find the last item */
70  item = list;
71  while (item->next) {
72  item = item->next;
73  }
74  return item;
75 }
76 
77 /* append a struct to the linked list. It always retunrs the address of the
78  * first record, so that you can sure this function as an initialization
79  * function as well as an append function. If you find this bothersome,
80  * then simply create a separate _init function and call it appropriately from
81  * within the proram. */
83  const char *data)
84 {
85  struct curl_slist *last;
86  struct curl_slist *new_item;
87 
88  new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
89  if (new_item) {
90  new_item->next = NULL;
91  new_item->data = strdup(data);
92  }
93  if (new_item == NULL || new_item->data == NULL) {
94  return NULL;
95  }
96 
97  if (list) {
98  last = slist_get_last(list);
99  last->next = new_item;
100  return list;
101  }
102 
103  /* if this is the first item, then new_item *is* the list */
104  return new_item;
105 }
106 
107 /* be nice and clean up resources */
108 void curl_slist_free_all(struct curl_slist *list)
109 {
110  struct curl_slist *next;
111  struct curl_slist *item;
112 
113  if (!list)
114  return;
115 
116  item = list;
117  do {
118  next = item->next;
119 
120  if (item->data) {
121  free(item->data);
122  }
123  free(item);
124  item = next;
125  } while (next);
126 }
127 
128 /* Curl_infof() is for info message along the way */
129 
130 void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
131 {
132  if(data && data->set.verbose) {
133  va_list ap;
134  char print_buffer[1024 + 1];
135  va_start(ap, fmt);
136  vsnprintf(print_buffer, 1024, fmt, ap);
137  va_end(ap);
138  Curl_debug(data, CURLINFO_TEXT, print_buffer, strlen(print_buffer));
139  }
140 }
141 
142 /* Curl_failf() is for messages stating why we failed.
143  * The message SHALL NOT include any LF or CR.
144  */
145 
146 void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
147 {
148  va_list ap;
149  va_start(ap, fmt);
150  if(data->set.errorbuffer && !data->state.errorbuf) {
151  vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
152  data->state.errorbuf = TRUE; /* wrote error string */
153 
154  if(data->set.verbose) {
155  size_t len = strlen(data->set.errorbuffer);
156  bool doneit=FALSE;
157  if(len < CURL_ERROR_SIZE - 1) {
158  doneit = TRUE;
159  data->set.errorbuffer[len] = '\n';
160  data->set.errorbuffer[++len] = '\0';
161  }
162  Curl_debug(data, CURLINFO_TEXT, data->set.errorbuffer, len);
163  if(doneit)
164  /* cut off the newline again */
165  data->set.errorbuffer[--len]=0;
166  }
167  }
168  va_end(ap);
169 }
170 
171 /* Curl_sendf() sends formated data to the server */
173  const char *fmt, ...)
174 {
175  struct SessionHandle *data = conn->data;
176  ssize_t bytes_written;
177  size_t write_len;
178  CURLcode res;
179  char *s;
180  char *sptr;
181  va_list ap;
182  va_start(ap, fmt);
183  s = vaprintf(fmt, ap); /* returns an allocated string */
184  va_end(ap);
185  if(!s)
186  return CURLE_OUT_OF_MEMORY; /* failure */
187 
188  bytes_written=0;
189  write_len = strlen(s);
190  sptr = s;
191 
192  while (1) {
193  /* Write the buffer to the socket */
194  res = Curl_write(conn, sockfd, sptr, write_len, &bytes_written);
195 
196  if(CURLE_OK != res)
197  break;
198 
199  if(data->set.verbose)
200  Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written);
201 
202  if((size_t)bytes_written != write_len) {
203  /* if not all was written at once, we must advance the pointer, decrease
204  the size left and try again! */
205  write_len -= bytes_written;
206  sptr += bytes_written;
207  }
208  else
209  break;
210  }
211 
212  free(s); /* free the output string */
213 
214  return res;
215 }
216 
217 /*
218  * Curl_write() is an internal write function that sends plain (binary) data
219  * to the server. Works with plain sockets, SSL or kerberos.
220  */
222  curl_socket_t sockfd,
223  void *mem,
224  size_t len,
225  ssize_t *written)
226 {
227  ssize_t bytes_written;
228  CURLcode retcode;
229 
230 #ifdef USE_SSLEAY
231  /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
232  If it is the second socket, we set num to 1. Otherwise to 0. This lets
233  us use the correct ssl handle. */
234  int num = (sockfd == conn->sock[SECONDARYSOCKET]);
235  /* SSL_write() is said to return 'int' while write() and send() returns
236  'size_t' */
237  if (conn->ssl[num].use) {
238  int err;
239  char error_buffer[120]; /* OpenSSL documents that this must be at least
240  120 bytes long. */
241  int sslerror;
242  int rc = SSL_write(conn->ssl[num].handle, mem, len);
243 
244  if(rc < 0) {
245  err = SSL_get_error(conn->ssl[num].handle, rc);
246 
247  switch(err) {
248  case SSL_ERROR_WANT_READ:
249  case SSL_ERROR_WANT_WRITE:
250  /* The operation did not complete; the same TLS/SSL I/O function
251  should be called again later. This is basicly an EWOULDBLOCK
252  equivalent. */
253  *written = 0;
254  return CURLE_OK;
255  case SSL_ERROR_SYSCALL:
256  failf(conn->data, "SSL_write() returned SYSCALL, errno = %d\n",
257  Curl_ourerrno());
258  return CURLE_SEND_ERROR;
259  case SSL_ERROR_SSL:
260  /* A failure in the SSL library occurred, usually a protocol error.
261  The OpenSSL error queue contains more information on the error. */
262  sslerror = ERR_get_error();
263  failf(conn->data, "SSL_write() error: %s\n",
264  ERR_error_string(sslerror, error_buffer));
265  return CURLE_SEND_ERROR;
266  }
267  /* a true error */
268  failf(conn->data, "SSL_write() return error %d\n", err);
269  return CURLE_SEND_ERROR;
270  }
271  bytes_written = rc;
272  }
273  else {
274 #else
275  (void)conn;
276 #endif
277 #ifdef HAVE_KRB4
278  if(conn->sec_complete) {
279  bytes_written = Curl_sec_write(conn, sockfd, mem, len);
280  }
281  else
282 #endif /* HAVE_KRB4 */
283  {
284  bytes_written = (ssize_t)swrite(sockfd, mem, len);
285  }
286  if(-1 == bytes_written) {
287  int err = Curl_ourerrno();
288 
289  if(
290 #ifdef WSAEWOULDBLOCK
291  /* This is how Windows does it */
292  (WSAEWOULDBLOCK == err)
293 #else
294  /* As pointed out by Christophe Demory on March 11 2003, errno
295  may be EWOULDBLOCK or on some systems EAGAIN when it returned
296  due to its inability to send off data without blocking. We
297  therefor treat both error codes the same here */
298  (EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
299 #endif
300  )
301  /* this is just a case of EWOULDBLOCK */
302  bytes_written=0;
303  }
304 #ifdef USE_SSLEAY
305  }
306 #endif
307 
308  *written = bytes_written;
309  retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
310 
311  return retcode;
312 }
313 
314 /* client_write() sends data to the write callback(s)
315 
316  The bit pattern defines to what "streams" to write to. Body and/or header.
317  The defines are in sendf.h of course.
318  */
320  int type,
321  char *ptr,
322  size_t len)
323 {
324  size_t wrote;
325 
326  if(0 == len)
327  len = strlen(ptr);
328 
329  if(type & CLIENTWRITE_BODY) {
330  wrote = data->set.fwrite(ptr, 1, len, data->set.out);
331  if(wrote != len) {
332  failf (data, "Failed writing body");
333  return CURLE_WRITE_ERROR;
334  }
335  }
336  if((type & CLIENTWRITE_HEADER) &&
337  (data->set.fwrite_header || data->set.writeheader) ) {
338  /*
339  * Write headers to the same callback or to the especially setup
340  * header callback function (added after version 7.7.1).
341  */
342  curl_write_callback writeit=
343  data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
344 
345  wrote = writeit(ptr, 1, len, data->set.writeheader);
346  if(wrote != len) {
347  failf (data, "Failed writing header");
348  return CURLE_WRITE_ERROR;
349  }
350  }
351 
352  return CURLE_OK;
353 }
354 
355 /*
356  * Internal read-from-socket function. This is meant to deal with plain
357  * sockets, SSL sockets and kerberos sockets.
358  *
359  * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
360  * a regular CURLcode value.
361  */
362 int Curl_read(struct connectdata *conn, /* connection data */
363  curl_socket_t sockfd, /* read from this socket */
364  char *buf, /* store read data here */
365  size_t buffersize, /* max amount to read */
366  ssize_t *n) /* amount bytes read */
367 {
368  ssize_t nread;
369 #ifdef USE_SSLEAY
370  /* Set 'num' to 0 or 1, depending on which socket that has been sent here.
371  If it is the second socket, we set num to 1. Otherwise to 0. This lets
372  us use the correct ssl handle. */
373  int num = (sockfd == conn->sock[SECONDARYSOCKET]);
374 
375  *n=0; /* reset amount to zero */
376 
377  if (conn->ssl[num].use) {
378  nread = SSL_read(conn->ssl[num].handle, buf, buffersize);
379 
380  if(nread < 0) {
381  /* failed SSL_read */
382  int err = SSL_get_error(conn->ssl[num].handle, nread);
383 
384  switch(err) {
385  case SSL_ERROR_NONE: /* this is not an error */
386  case SSL_ERROR_ZERO_RETURN: /* no more data */
387  break;
388  case SSL_ERROR_WANT_READ:
389  case SSL_ERROR_WANT_WRITE:
390  /* there's data pending, re-invoke SSL_read() */
391  return -1; /* basicly EWOULDBLOCK */
392  default:
393  /* openssl/ssl.h says "look at error stack/return value/errno" */
394  {
395  char error_buffer[120]; /* OpenSSL documents that this must be at
396  least 120 bytes long. */
397  int sslerror = ERR_get_error();
398  failf(conn->data, "SSL read: %s, errno %d",
399  ERR_error_string(sslerror, error_buffer),
400  Curl_ourerrno() );
401  }
402  return CURLE_RECV_ERROR;
403  }
404  }
405  }
406  else {
407 #else
408  (void)conn;
409 #endif
410  *n=0; /* reset amount to zero */
411 #ifdef HAVE_KRB4
412  if(conn->sec_complete)
413  nread = Curl_sec_read(conn, sockfd, buf, buffersize);
414  else
415 #endif
416  nread = sread(sockfd, buf, buffersize);
417 
418  if(-1 == nread) {
419  int err = Curl_ourerrno();
420  conn->sockerror = err;
421 #ifdef WIN32
422  if(WSAEWOULDBLOCK == err)
423 #else
424  if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
425 #endif
426  return -1;
427  }
428  else
429  conn->sockerror = 0; /* no error */
430 
431 #ifdef USE_SSLEAY
432  }
433 #endif /* USE_SSLEAY */
434  *n = nread;
435  return CURLE_OK;
436 }
437 
438 /* return 0 on success */
440  char *ptr, size_t size)
441 {
442  static const char * const s_infotype[CURLINFO_END] = {
443  "* ", "< ", "> ", "{ ", "} " };
444 
445  if(data->set.fdebug)
446  return (*data->set.fdebug)(data, type, ptr, size,
447  data->set.debugdata);
448 
449  switch(type) {
450  case CURLINFO_TEXT:
451  case CURLINFO_HEADER_OUT:
452  case CURLINFO_HEADER_IN:
453  fwrite(s_infotype[type], 2, 1, data->set.err);
454  fwrite(ptr, size, 1, data->set.err);
455  break;
456  default: /* nada */
457  break;
458  }
459  return 0;
460 }
#define sread(x, y, z)
Definition: setup.h:221
struct ssl_connect_data ssl[2]
Definition: urldata.h:459
#define CLIENTWRITE_BODY
Definition: sendf.h:34
void Curl_failf(struct SessionHandle *data, const char *fmt,...)
Definition: sendf.c:146
void curl_slist_free_all(struct curl_slist *list)
Definition: sendf.c:108
int curl_socket_t
Definition: setup.h:254
curl_write_callback fwrite_header
Definition: urldata.h:789
char * errorbuffer
Definition: urldata.h:759
GLenum GLsizei n
Definition: glext.h:3705
#define failf
Definition: sendf.h:32
char * data
Definition: curl.h:1062
CURLcode Curl_client_write(struct SessionHandle *data, int type, char *ptr, size_t len)
Definition: sendf.c:319
CURLcode
Definition: curl.h:209
int Curl_sec_write(struct connectdata *conn, int, char *, int)
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
#define SECONDARYSOCKET
Definition: urldata.h:395
GLdouble s
Definition: glext.h:2935
GLenum GLsizei len
Definition: glext.h:3472
struct UrlState state
Definition: urldata.h:903
size_t(* curl_write_callback)(char *buffer, size_t size, size_t nitems, void *outstream)
Definition: curl.h:169
int Curl_sec_read(struct connectdata *conn, int, void *, int)
FILE * err
Definition: urldata.h:757
int Curl_read(struct connectdata *conn, curl_socket_t sockfd, char *buf, size_t buffersize, ssize_t *n)
Definition: sendf.c:362
int Curl_ourerrno(void)
Definition: connect.c:98
GLuint GLuint num
Definition: glext.h:5390
#define ssize_t
Definition: config-win32.h:27
#define vsnprintf
CURLcode Curl_write(struct connectdata *conn, curl_socket_t sockfd, void *mem, size_t len, ssize_t *written)
Definition: sendf.c:221
struct curl_slist * curl_slist_append(struct curl_slist *list, const char *data)
Definition: sendf.c:82
void * out
Definition: urldata.h:764
bool errorbuf
Definition: urldata.h:695
void * writeheader
Definition: urldata.h:766
void * debugdata
Definition: urldata.h:758
#define NULL
Definition: Lib.h:88
struct curl_slist * next
Definition: curl.h:1063
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
#define CLIENTWRITE_HEADER
Definition: sendf.h:35
curl_debug_callback fdebug
Definition: urldata.h:792
Definition: curl.h:210
struct SessionHandle * data
Definition: urldata.h:403
char * strdup(char *s1)
Definition: main.c:183
int sockerror
Definition: urldata.h:573
int Curl_debug(struct SessionHandle *data, curl_infotype type, char *ptr, size_t size)
Definition: sendf.c:439
static WindowRef ValidModeCallbackProc inCallback OSStatus err
#define swrite(x, y, z)
Definition: setup.h:222
curl_socket_t sock[2]
Definition: urldata.h:454
void Curl_infof(struct SessionHandle *data, const char *fmt,...)
Definition: sendf.c:130
bool verbose
Definition: urldata.h:871
GLsizeiptr size
Definition: glext.h:3112
curl_write_callback fwrite
Definition: urldata.h:788
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
#define FALSE
Definition: mprintf.c:70
struct UserDefined set
Definition: urldata.h:898
#define CURL_ERROR_SIZE
Definition: curl.h:312
GLuint res
Definition: glext.h:5385
#define TRUE
Definition: mprintf.c:69
CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn, const char *fmt,...)
Definition: sendf.c:172
curl_infotype
Definition: curl.h:186
size_t fwrite(const void *, size_t, size_t, FILE *)