Newer
Older
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
***************************************************************************/
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifndef HAVE_SELECT
#error "We can't compile without select() support!"
#endif
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
#endif
#include "urldata.h"
#include <curl/curl.h>
#include <curl/types.h>
#include "netrc.h"
#include "content_encoding.h" /* content encoding support. 08/27/02 jhrg */
#include "transfer.h"
#include "sendf.h"
#include "speedcheck.h"
#include "getpass.h"
#include "progress.h"
#include "getdate.h"
#include "url.h"
#include "getinfo.h"
#include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
Daniel Stenberg
committed
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
enum {
KEEP_NONE,
KEEP_READ,
KEEP_WRITE
};
/* We keep this static and global since this is read-only and NEVER
changed. It should just remain a blanked-out timeout value. */
static struct timeval notimeout={0,0};
CURLcode Curl_readwrite(struct connectdata *conn,
bool *done)
struct Curl_transfer_keeper *k = &conn->keep;
struct SessionHandle *data = conn->data;
int result;
ssize_t nread; /* number of bytes read */
int didwhat=0;
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* These two are used only if no other select() or _fdset() have been
invoked before this. This typicly happens if you use the multi interface
and call curl_multi_perform() without calling curl_multi_fdset()
first. */
fd_set extrareadfd;
fd_set extrawritefd;
fd_set *readfdp = k->readfdp;
fd_set *writefdp = k->writefdp;
if((k->keepon & KEEP_READ) && !readfdp) {
/* reading is requested, but no socket descriptor pointer was set */
FD_ZERO(&extrareadfd);
FD_SET(conn->sockfd, &extrareadfd);
readfdp = &extrareadfd;
/* no write, no exceptions, no timeout */
select(conn->sockfd+1, readfdp, NULL, NULL, ¬imeout);
}
if((k->keepon & KEEP_WRITE) && !writefdp) {
/* writing is requested, but no socket descriptor pointer was set */
FD_ZERO(&extrawritefd);
FD_SET(conn->writesockfd, &extrawritefd);
writefdp = &extrawritefd;
/* no read, no exceptions, no timeout */
select(conn->writesockfd+1, NULL, writefdp, NULL, ¬imeout);
}
Daniel Stenberg
committed
/* If we still have reading to do, we check if we have a readable
socket. Sometimes the reafdp is NULL, it no fd_set was done using
the multi interface and then we can do nothing but to attempt a
read to be sure. */
if((k->keepon & KEEP_READ) &&
(FD_ISSET(conn->sockfd, readfdp))) {
/* read! */
result = Curl_read(conn, conn->sockfd, k->buf,
data->set.buffer_size?
data->set.buffer_size:BUFSIZE -1,
&nread);
if(0>result)
break; /* get out of loop */
if(result>0)
if ((k->bytecount == 0) && (k->writebytecount == 0))
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
didwhat |= KEEP_READ;
/* NULL terminate, allowing string ops to be used */
if (0 < nread)
/* if we receive 0 or less here, the server closed the connection and
we bail out from this! */
else if (0 >= nread) {
k->keepon &= ~KEEP_READ;
FD_ZERO(&k->rkeepfd);
break;
/* Default buffer to use when we write the buffer, it may be changed
in the flow below before the actual storing is done. */
k->str = k->buf;
/* Since this is a two-state thing, we check if we are parsing
headers at the moment or not. */
Loading
Loading full blame…