sendf.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*****************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 2002, Daniel Stenberg, <[email protected]>, et al.
  9. *
  10. * In order to be useful for every potential user, curl and libcurl are
  11. * dual-licensed under the MPL and the MIT/X-derivate licenses.
  12. *
  13. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  14. * copies of the Software, and permit persons to whom the Software is
  15. * furnished to do so, under the terms of the MPL or the MIT/X-derivate
  16. * licenses. You may pick one of these licenses.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. * $Id$
  22. *****************************************************************************/
  23. #include "setup.h"
  24. #include <stdio.h>
  25. #include <stdarg.h>
  26. #include <stdlib.h>
  27. #include <errno.h>
  28. #ifdef HAVE_SYS_TYPES_H
  29. #include <sys/types.h>
  30. #endif
  31. #ifdef HAVE_SYS_SOCKET_H
  32. #include <sys/socket.h> /* required for send() & recv() prototypes */
  33. #endif
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
  38. #include <winsock.h>
  39. #endif
  40. #include <curl/curl.h>
  41. #include "urldata.h"
  42. #include "sendf.h"
  43. #define _MPRINTF_REPLACE /* use the internal *printf() functions */
  44. #include <curl/mprintf.h>
  45. #ifdef KRB4
  46. #include "security.h"
  47. #endif
  48. #include <string.h>
  49. /* The last #include file should be: */
  50. #ifdef MALLOCDEBUG
  51. #include "memdebug.h"
  52. #endif
  53. /* returns last node in linked list */
  54. static struct curl_slist *slist_get_last(struct curl_slist *list)
  55. {
  56. struct curl_slist *item;
  57. /* if caller passed us a NULL, return now */
  58. if (!list)
  59. return NULL;
  60. /* loop through to find the last item */
  61. item = list;
  62. while (item->next) {
  63. item = item->next;
  64. }
  65. return item;
  66. }
  67. /* append a struct to the linked list. It always retunrs the address of the
  68. * first record, so that you can sure this function as an initialization
  69. * function as well as an append function. If you find this bothersome,
  70. * then simply create a separate _init function and call it appropriately from
  71. * within the proram. */
  72. struct curl_slist *curl_slist_append(struct curl_slist *list,
  73. const char *data)
  74. {
  75. struct curl_slist *last;
  76. struct curl_slist *new_item;
  77. new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
  78. if (new_item) {
  79. new_item->next = NULL;
  80. new_item->data = strdup(data);
  81. }
  82. else {
  83. fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
  84. return NULL;
  85. }
  86. if (list) {
  87. last = slist_get_last(list);
  88. last->next = new_item;
  89. return list;
  90. }
  91. /* if this is the first item, then new_item *is* the list */
  92. return new_item;
  93. }
  94. /* be nice and clean up resources */
  95. void curl_slist_free_all(struct curl_slist *list)
  96. {
  97. struct curl_slist *next;
  98. struct curl_slist *item;
  99. if (!list)
  100. return;
  101. item = list;
  102. do {
  103. next = item->next;
  104. if (item->data) {
  105. free(item->data);
  106. }
  107. free(item);
  108. item = next;
  109. } while (next);
  110. }
  111. /* Curl_infof() is for info message along the way */
  112. void Curl_infof(struct SessionHandle *data, const char *fmt, ...)
  113. {
  114. va_list ap;
  115. if(data->set.verbose) {
  116. va_start(ap, fmt);
  117. fputs("* ", data->set.err);
  118. vfprintf(data->set.err, fmt, ap);
  119. va_end(ap);
  120. }
  121. }
  122. /* Curl_failf() is for messages stating why we failed.
  123. * The message SHALL NOT include any LF or CR.
  124. */
  125. void Curl_failf(struct SessionHandle *data, const char *fmt, ...)
  126. {
  127. va_list ap;
  128. va_start(ap, fmt);
  129. if(data->set.errorbuffer && !data->state.errorbuf) {
  130. vsnprintf(data->set.errorbuffer, CURL_ERROR_SIZE, fmt, ap);
  131. data->state.errorbuf = TRUE; /* wrote error string */
  132. }
  133. va_end(ap);
  134. }
  135. /* Curl_sendf() sends formated data to the server */
  136. CURLcode Curl_sendf(int sockfd, struct connectdata *conn,
  137. const char *fmt, ...)
  138. {
  139. struct SessionHandle *data = conn->data;
  140. ssize_t bytes_written;
  141. CURLcode result;
  142. char *s;
  143. va_list ap;
  144. va_start(ap, fmt);
  145. s = vaprintf(fmt, ap); /* returns an allocated string */
  146. va_end(ap);
  147. if(!s)
  148. return 0; /* failure */
  149. if(data->set.verbose)
  150. fprintf(data->set.err, "> %s", s);
  151. /* Write the buffer to the socket */
  152. result = Curl_write(conn, sockfd, s, strlen(s), &bytes_written);
  153. free(s); /* free the output string */
  154. return result;
  155. }
  156. /*
  157. * Curl_write() is an internal write function that sends plain (binary) data
  158. * to the server. Works with plain sockets, SSL or kerberos.
  159. *
  160. */
  161. CURLcode Curl_write(struct connectdata *conn, int sockfd,
  162. void *mem, size_t len,
  163. ssize_t *written)
  164. {
  165. ssize_t bytes_written;
  166. #ifdef USE_SSLEAY
  167. /* SSL_write() is said to return 'int' while write() and send() returns
  168. 'size_t' */
  169. if (conn->ssl.use) {
  170. int err;
  171. int rc = SSL_write(conn->ssl.handle, mem, len);
  172. if(rc < 0) {
  173. err = SSL_get_error(conn->ssl.handle, rc);
  174. switch(err) {
  175. case SSL_ERROR_WANT_READ:
  176. case SSL_ERROR_WANT_WRITE:
  177. /* this is basicly the EWOULDBLOCK equivalent */
  178. *written = 0;
  179. return CURLE_OK;
  180. }
  181. /* a true error */
  182. failf(conn->data, "SSL_write() return error %d\n", err);
  183. return CURLE_WRITE_ERROR;
  184. }
  185. bytes_written = rc;
  186. }
  187. else {
  188. #endif
  189. #ifdef KRB4
  190. if(conn->sec_complete) {
  191. bytes_written = Curl_sec_write(conn, sockfd, mem, len);
  192. }
  193. else
  194. #endif /* KRB4 */
  195. {
  196. bytes_written = swrite(sockfd, mem, len);
  197. }
  198. if(-1 == bytes_written) {
  199. #ifdef WIN32
  200. if(WSAEWOULDBLOCK == GetLastError())
  201. #else
  202. if(EWOULDBLOCK == errno)
  203. #endif
  204. {
  205. /* this is just a case of EWOULDBLOCK */
  206. *written=0;
  207. return CURLE_OK;
  208. }
  209. }
  210. #ifdef USE_SSLEAY
  211. }
  212. #endif
  213. *written = bytes_written;
  214. return (-1 != bytes_written)?CURLE_OK:CURLE_WRITE_ERROR;
  215. }
  216. /* client_write() sends data to the write callback(s)
  217. The bit pattern defines to what "streams" to write to. Body and/or header.
  218. The defines are in sendf.h of course.
  219. */
  220. CURLcode Curl_client_write(struct SessionHandle *data,
  221. int type,
  222. char *ptr,
  223. size_t len)
  224. {
  225. size_t wrote;
  226. if(0 == len)
  227. len = strlen(ptr);
  228. if(type & CLIENTWRITE_BODY) {
  229. wrote = data->set.fwrite(ptr, 1, len, data->set.out);
  230. if(wrote != len) {
  231. failf (data, "Failed writing body");
  232. return CURLE_WRITE_ERROR;
  233. }
  234. }
  235. if((type & CLIENTWRITE_HEADER) &&
  236. (data->set.fwrite_header || data->set.writeheader) ) {
  237. /*
  238. * Write headers to the same callback or to the especially setup
  239. * header callback function (added after version 7.7.1).
  240. */
  241. curl_write_callback writeit=
  242. data->set.fwrite_header?data->set.fwrite_header:data->set.fwrite;
  243. wrote = writeit(ptr, 1, len, data->set.writeheader);
  244. if(wrote != len) {
  245. failf (data, "Failed writing header");
  246. return CURLE_WRITE_ERROR;
  247. }
  248. }
  249. return CURLE_OK;
  250. }
  251. /*
  252. * Internal read-from-socket function. This is meant to deal with plain
  253. * sockets, SSL sockets and kerberos sockets.
  254. *
  255. * If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
  256. * a regular CURLcode value.
  257. */
  258. int Curl_read(struct connectdata *conn,
  259. int sockfd,
  260. char *buf,
  261. size_t buffersize,
  262. ssize_t *n)
  263. {
  264. ssize_t nread;
  265. #ifdef USE_SSLEAY
  266. if (conn->ssl.use) {
  267. bool loop=TRUE;
  268. int err;
  269. do {
  270. nread = SSL_read(conn->ssl.handle, buf, buffersize);
  271. if(nread >= 0)
  272. /* successful read */
  273. break;
  274. err = SSL_get_error(conn->ssl.handle, nread);
  275. switch(err) {
  276. case SSL_ERROR_NONE: /* this is not an error */
  277. case SSL_ERROR_ZERO_RETURN: /* no more data */
  278. loop=0; /* get out of loop */
  279. break;
  280. case SSL_ERROR_WANT_READ:
  281. case SSL_ERROR_WANT_WRITE:
  282. /* if there's data pending, then we re-invoke SSL_read() */
  283. break;
  284. }
  285. } while(loop);
  286. if(loop && SSL_pending(conn->ssl.handle))
  287. return -1; /* basicly EWOULDBLOCK */
  288. }
  289. else {
  290. #endif
  291. #ifdef KRB4
  292. if(conn->sec_complete)
  293. nread = Curl_sec_read(conn, sockfd, buf, buffersize);
  294. else
  295. #endif
  296. nread = sread (sockfd, buf, buffersize);
  297. if(-1 == nread) {
  298. #ifdef WIN32
  299. if(WSAEWOULDBLOCK == GetLastError())
  300. #else
  301. if(EWOULDBLOCK == errno)
  302. #endif
  303. return -1;
  304. }
  305. #ifdef USE_SSLEAY
  306. }
  307. #endif /* USE_SSLEAY */
  308. *n = nread;
  309. return CURLE_OK;
  310. }
  311. /*
  312. * local variables:
  313. * eval: (load-file "../curl-mode.el")
  314. * end:
  315. * vim600: fdm=marker
  316. * vim: et sw=2 ts=2 sts=2 tw=78
  317. */