/***************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | * / __| | | | |_) | | * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is Curl. * * The Initial Developer of the Original Code is Daniel Stenberg. * * Portions created by the Initial Developer are Copyright (C) 1998. * All Rights Reserved. * * ------------------------------------------------------------ * Main author: * - Daniel Stenberg * * http://curl.haxx.nu * * $Source$ * $Revision$ * $Date$ * $Author$ * $State$ * $Locker$ * * ------------------------------------------------------------ ****************************************************************************/ #include "setup.h" #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef WIN32 #if !defined(__GNUC__) || defined(__MINGW32__) #include #endif #include /* for the time_t typedef! */ #if defined(__GNUC__) && defined(TIME_WITH_SYS_TIME) #include #endif #endif #include #ifdef __BEOS__ #include #endif #include "urldata.h" #include "speedcheck.h" #include "sendf.h" #include "progress.h" /* --- upload a stream to a socket --- */ UrgError Upload(struct UrlData *data, int sockfd, long *bytecountp) { fd_set writefd; fd_set keepfd; struct timeval interval; bool keepon=TRUE; char *buf = data->buffer; size_t nread; long bytecount=0; struct timeval start; struct timeval now; UrgError urg; char scratch[BUFSIZE * 2]; int i, si; /* timeout every X second - makes a better progressmeter (i.e even when no data is sent, the meter can be updated and reflect reality) - allows removal of the alarm() crap - variable timeout is easier */ myalarm(0); /* switch off the alarm-style timeout */ start = tvnow(); now = start; FD_ZERO(&writefd); /* clear it */ FD_SET(sockfd, &writefd); keepfd = writefd; while(keepon) { size_t bytes_written = 0; writefd = keepfd; /* set this every lap in the loop */ interval.tv_sec = 2; interval.tv_usec = 0; switch(select(sockfd+1, NULL, &writefd, NULL, &interval)) { case -1: /* error, stop writing */ keepon=FALSE; continue; case 0: /* timeout */ break; default: /* write! */ if(data->crlf) buf = data->buffer; /* put it back on the buffer */ nread = data->fread(buf, 1, BUFSIZE, data->in); bytecount += nread; if (nread==0) { /* done */ keepon = FALSE; break; } /* convert LF to CRLF if so asked */ if (data->crlf) { for(i = 0, si = 0; i < (int)nread; i++, si++) { if (buf[i] == 0x0a) { scratch[si++] = 0x0d; scratch[si] = 0x0a; } else { scratch[si] = buf[i]; } } nread = si; buf = scratch; /* point to the new buffer */ } /* write to socket */ #ifndef USE_SSLEAY bytes_written = swrite(sockfd, buf, nread); #else if (data->use_ssl) { bytes_written = SSL_write(data->ssl, buf, nread); } else { bytes_written = swrite(sockfd, buf, nread); } #endif /* USE_SSLEAY */ if(nread != bytes_written) { failf(data, "Failed uploading file"); return URG_FTP_WRITE_ERROR; } } now = tvnow(); ProgressShow(data, bytecount, start, now, FALSE); urg=speedcheck(data, now); if(urg) return urg; if(data->timeout && (tvdiff(now,start)>data->timeout)) { failf(data, "Upload timed out with %d bytes sent", bytecount); return URG_OPERATION_TIMEOUTED; } } ProgressShow(data, bytecount, start, now, TRUE); *bytecountp = bytecount; return URG_OK; }