/*********************************************************************** * * pop3_regular_transfer() * * The input argument is already checked for validity. * * Performs all commands done before a regular transfer between a local and a * remote host. * */ static CURLcode pop3_regular_transfer(struct connectdata *conn, bool *dophase_done) { CURLcode result=CURLE_OK; bool connected=FALSE; struct SessionHandle *data = conn->data; data->req.size = -1; /* make sure this is unknown at this point */ Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); Curl_pgrsSetUploadSize(data, 0); Curl_pgrsSetDownloadSize(data, 0); result = pop3_perform(conn, &connected, /* have we connected after PASV/PORT */ dophase_done); /* all commands in the DO-phase done? */ if(CURLE_OK == result) { if(!*dophase_done) /* the DO phase has not completed yet */ return CURLE_OK; result = pop3_dophase_done(conn, connected); if(result) return result; } return result; }
/*********************************************************************** * * smtp_regular_transfer() * * The input argument is already checked for validity. * * Performs all commands done before a regular transfer between a local and a * remote host. */ static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; struct SessionHandle *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); Curl_pgrsSetUploadSize(data, 0); Curl_pgrsSetDownloadSize(data, 0); result = smtp_perform(conn, &connected, dophase_done); if(CURLE_OK == result) { if(!*dophase_done) /* The DO phase has not completed yet */ return CURLE_OK; result = smtp_dophase_done(conn, connected); if(result) return result; } return result; }
/*********************************************************************** * * smtp_regular_transfer() * * The input argument is already checked for validity. * * Performs all commands done before a regular transfer between a local and a * remote host. */ static CURLcode smtp_regular_transfer(struct connectdata *conn, bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; struct Curl_easy *data = conn->data; /* Make sure size is unknown at this point */ data->req.size = -1; /* Set the progress data */ Curl_pgrsSetUploadCounter(data, 0); Curl_pgrsSetDownloadCounter(data, 0); Curl_pgrsSetUploadSize(data, -1); Curl_pgrsSetDownloadSize(data, -1); /* Carry out the perform */ result = smtp_perform(conn, &connected, dophase_done); /* Perform post DO phase operations if necessary */ if(!result && *dophase_done) result = smtp_dophase_done(conn, connected); return result; }
static CURLcode file_upload(struct connectdata *conn) { struct FILEPROTO *file = conn->data->state.proto.file; const char *dir = strchr(file->path, DIRSEP); FILE *fp; CURLcode res=CURLE_OK; struct SessionHandle *data = conn->data; char *buf = data->state.buffer; size_t nread; size_t nwrite; curl_off_t bytecount = 0; struct timeval now = Curl_tvnow(); struct_stat file_stat; const char* buf2; /* * Since FILE: doesn't do the full init, we need to provide some extra * assignments here. */ conn->fread_func = data->set.fread_func; conn->fread_in = data->set.in; conn->data->req.upload_fromhere = buf; if(!dir) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ if(!dir[1]) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ if(data->state.resume_from) fp = fopen( file->path, "ab" ); else { int fd; #ifdef DOS_FILESYSTEM fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, conn->data->set.new_file_perms); #else fd = open(file->path, O_WRONLY|O_CREAT|O_TRUNC, conn->data->set.new_file_perms); #endif if(fd < 0) { failf(data, "Can't open %s for writing", file->path); return CURLE_WRITE_ERROR; } close(fd); fp = fopen(file->path, "wb"); } if(!fp) { failf(data, "Can't open %s for writing", file->path); return CURLE_WRITE_ERROR; } if(-1 != data->set.infilesize) /* known size of data to "upload" */ Curl_pgrsSetUploadSize(data, data->set.infilesize); /* treat the negative resume offset value as the case of "-" */ if(data->state.resume_from < 0) { if(fstat(fileno(fp), &file_stat)) { fclose(fp); failf(data, "Can't get the size of %s", file->path); return CURLE_WRITE_ERROR; } else data->state.resume_from = (curl_off_t)file_stat.st_size; } while(res == CURLE_OK) { int readcount; res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); if(res) break; if(readcount <= 0) /* fix questionable compare error. curlvms */ break; nread = (size_t)readcount; /*skip bytes before resume point*/ if(data->state.resume_from) { if( (curl_off_t)nread <= data->state.resume_from ) { data->state.resume_from -= nread; nread = 0; buf2 = buf; } else { buf2 = buf + data->state.resume_from; nread -= (size_t)data->state.resume_from; data->state.resume_from = 0; } } else buf2 = buf; /* write the data to the target */ nwrite = fwrite(buf2, 1, nread, fp); if(nwrite != nread) { res = CURLE_SEND_ERROR; break; } bytecount += nread; Curl_pgrsSetUploadCounter(data, bytecount); if(Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; else res = Curl_speedcheck(data, now); } if(!res && Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; fclose(fp); return res; }
static CURLcode rtsp_do(struct connectdata *conn, bool *done) { struct Curl_easy *data = conn->data; CURLcode result = CURLE_OK; Curl_RtspReq rtspreq = data->set.rtspreq; struct RTSP *rtsp = data->req.protop; struct HTTP *http; Curl_send_buffer *req_buffer; curl_off_t postsize = 0; /* for ANNOUNCE and SET_PARAMETER */ curl_off_t putsize = 0; /* for ANNOUNCE and SET_PARAMETER */ const char *p_request = NULL; const char *p_session_id = NULL; const char *p_accept = NULL; const char *p_accept_encoding = NULL; const char *p_range = NULL; const char *p_referrer = NULL; const char *p_stream_uri = NULL; const char *p_transport = NULL; const char *p_uagent = NULL; const char *p_proxyuserpwd = NULL; const char *p_userpwd = NULL; *done = TRUE; http = &(rtsp->http_wrapper); /* Assert that no one has changed the RTSP struct in an evil way */ DEBUGASSERT((void *)http == (void *)rtsp); rtsp->CSeq_sent = data->state.rtsp_next_client_CSeq; rtsp->CSeq_recv = 0; /* Setup the 'p_request' pointer to the proper p_request string * Since all RTSP requests are included here, there is no need to * support custom requests like HTTP. **/ data->set.opt_no_body = TRUE; /* most requests don't contain a body */ switch(rtspreq) { default: failf(data, "Got invalid RTSP request"); return CURLE_BAD_FUNCTION_ARGUMENT; case RTSPREQ_OPTIONS: p_request = "OPTIONS"; break; case RTSPREQ_DESCRIBE: p_request = "DESCRIBE"; data->set.opt_no_body = FALSE; break; case RTSPREQ_ANNOUNCE: p_request = "ANNOUNCE"; break; case RTSPREQ_SETUP: p_request = "SETUP"; break; case RTSPREQ_PLAY: p_request = "PLAY"; break; case RTSPREQ_PAUSE: p_request = "PAUSE"; break; case RTSPREQ_TEARDOWN: p_request = "TEARDOWN"; break; case RTSPREQ_GET_PARAMETER: /* GET_PARAMETER's no_body status is determined later */ p_request = "GET_PARAMETER"; data->set.opt_no_body = FALSE; break; case RTSPREQ_SET_PARAMETER: p_request = "SET_PARAMETER"; break; case RTSPREQ_RECORD: p_request = "RECORD"; break; case RTSPREQ_RECEIVE: p_request = ""; /* Treat interleaved RTP as body*/ data->set.opt_no_body = FALSE; break; case RTSPREQ_LAST: failf(data, "Got invalid RTSP request: RTSPREQ_LAST"); return CURLE_BAD_FUNCTION_ARGUMENT; } if(rtspreq == RTSPREQ_RECEIVE) { Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, -1, NULL); return result; } p_session_id = data->set.str[STRING_RTSP_SESSION_ID]; if(!p_session_id && (rtspreq & ~(RTSPREQ_OPTIONS | RTSPREQ_DESCRIBE | RTSPREQ_SETUP))) { failf(data, "Refusing to issue an RTSP request [%s] without a session ID.", p_request); return CURLE_BAD_FUNCTION_ARGUMENT; } /* TODO: proxy? */ /* Stream URI. Default to server '*' if not specified */ if(data->set.str[STRING_RTSP_STREAM_URI]) { p_stream_uri = data->set.str[STRING_RTSP_STREAM_URI]; } else { p_stream_uri = "*"; } /* Transport Header for SETUP requests */ p_transport = Curl_checkheaders(conn, "Transport:"); if(rtspreq == RTSPREQ_SETUP && !p_transport) { /* New Transport: setting? */ if(data->set.str[STRING_RTSP_TRANSPORT]) { Curl_safefree(conn->allocptr.rtsp_transport); conn->allocptr.rtsp_transport = aprintf("Transport: %s\r\n", data->set.str[STRING_RTSP_TRANSPORT]); if(!conn->allocptr.rtsp_transport) return CURLE_OUT_OF_MEMORY; } else { failf(data, "Refusing to issue an RTSP SETUP without a Transport: header."); return CURLE_BAD_FUNCTION_ARGUMENT; } p_transport = conn->allocptr.rtsp_transport; } /* Accept Headers for DESCRIBE requests */ if(rtspreq == RTSPREQ_DESCRIBE) { /* Accept Header */ p_accept = Curl_checkheaders(conn, "Accept:")? NULL:"Accept: application/sdp\r\n"; /* Accept-Encoding header */ if(!Curl_checkheaders(conn, "Accept-Encoding:") && data->set.str[STRING_ENCODING]) { Curl_safefree(conn->allocptr.accept_encoding); conn->allocptr.accept_encoding = aprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); if(!conn->allocptr.accept_encoding) return CURLE_OUT_OF_MEMORY; p_accept_encoding = conn->allocptr.accept_encoding; } } /* The User-Agent string might have been allocated in url.c already, because it might have been used in the proxy connect, but if we have got a header with the user-agent string specified, we erase the previously made string here. */ if(Curl_checkheaders(conn, "User-Agent:") && conn->allocptr.uagent) { Curl_safefree(conn->allocptr.uagent); conn->allocptr.uagent = NULL; } else if(!Curl_checkheaders(conn, "User-Agent:") && data->set.str[STRING_USERAGENT]) { p_uagent = conn->allocptr.uagent; } /* setup the authentication headers */ result = Curl_http_output_auth(conn, p_request, p_stream_uri, FALSE); if(result) return result; p_proxyuserpwd = conn->allocptr.proxyuserpwd; p_userpwd = conn->allocptr.userpwd; /* Referrer */ Curl_safefree(conn->allocptr.ref); if(data->change.referer && !Curl_checkheaders(conn, "Referer:")) conn->allocptr.ref = aprintf("Referer: %s\r\n", data->change.referer); else conn->allocptr.ref = NULL; p_referrer = conn->allocptr.ref; /* * Range Header * Only applies to PLAY, PAUSE, RECORD * * Go ahead and use the Range stuff supplied for HTTP */ if(data->state.use_range && (rtspreq & (RTSPREQ_PLAY | RTSPREQ_PAUSE | RTSPREQ_RECORD))) { /* Check to see if there is a range set in the custom headers */ if(!Curl_checkheaders(conn, "Range:") && data->state.range) { Curl_safefree(conn->allocptr.rangeline); conn->allocptr.rangeline = aprintf("Range: %s\r\n", data->state.range); p_range = conn->allocptr.rangeline; } } /* * Sanity check the custom headers */ if(Curl_checkheaders(conn, "CSeq:")) { failf(data, "CSeq cannot be set as a custom header."); return CURLE_RTSP_CSEQ_ERROR; } if(Curl_checkheaders(conn, "Session:")) { failf(data, "Session ID cannot be set as a custom header."); return CURLE_BAD_FUNCTION_ARGUMENT; } /* Initialize a dynamic send buffer */ req_buffer = Curl_add_buffer_init(); if(!req_buffer) return CURLE_OUT_OF_MEMORY; result = Curl_add_bufferf(req_buffer, "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ "CSeq: %ld\r\n", /* CSeq */ p_request, p_stream_uri, rtsp->CSeq_sent); if(result) return result; /* * Rather than do a normal alloc line, keep the session_id unformatted * to make comparison easier */ if(p_session_id) { result = Curl_add_bufferf(req_buffer, "Session: %s\r\n", p_session_id); if(result) return result; } /* * Shared HTTP-like options */ result = Curl_add_bufferf(req_buffer, "%s" /* transport */ "%s" /* accept */ "%s" /* accept-encoding */ "%s" /* range */ "%s" /* referrer */ "%s" /* user-agent */ "%s" /* proxyuserpwd */ "%s" /* userpwd */ , p_transport ? p_transport : "", p_accept ? p_accept : "", p_accept_encoding ? p_accept_encoding : "", p_range ? p_range : "", p_referrer ? p_referrer : "", p_uagent ? p_uagent : "", p_proxyuserpwd ? p_proxyuserpwd : "", p_userpwd ? p_userpwd : ""); /* * Free userpwd now --- cannot reuse this for Negotiate and possibly NTLM * with basic and digest, it will be freed anyway by the next request */ Curl_safefree(conn->allocptr.userpwd); conn->allocptr.userpwd = NULL; if(result) return result; if((rtspreq == RTSPREQ_SETUP) || (rtspreq == RTSPREQ_DESCRIBE)) { result = Curl_add_timecondition(data, req_buffer); if(result) return result; } result = Curl_add_custom_headers(conn, FALSE, req_buffer); if(result) return result; if(rtspreq == RTSPREQ_ANNOUNCE || rtspreq == RTSPREQ_SET_PARAMETER || rtspreq == RTSPREQ_GET_PARAMETER) { if(data->set.upload) { putsize = data->state.infilesize; data->set.httpreq = HTTPREQ_PUT; } else { postsize = (data->state.infilesize != -1)? data->state.infilesize: (data->set.postfields? (curl_off_t)strlen(data->set.postfields):0); data->set.httpreq = HTTPREQ_POST; } if(putsize > 0 || postsize > 0) { /* As stated in the http comments, it is probably not wise to * actually set a custom Content-Length in the headers */ if(!Curl_checkheaders(conn, "Content-Length:")) { result = Curl_add_bufferf(req_buffer, "Content-Length: %" CURL_FORMAT_CURL_OFF_T"\r\n", (data->set.upload ? putsize : postsize)); if(result) return result; } if(rtspreq == RTSPREQ_SET_PARAMETER || rtspreq == RTSPREQ_GET_PARAMETER) { if(!Curl_checkheaders(conn, "Content-Type:")) { result = Curl_add_bufferf(req_buffer, "Content-Type: text/parameters\r\n"); if(result) return result; } } if(rtspreq == RTSPREQ_ANNOUNCE) { if(!Curl_checkheaders(conn, "Content-Type:")) { result = Curl_add_bufferf(req_buffer, "Content-Type: application/sdp\r\n"); if(result) return result; } } data->state.expect100header = FALSE; /* RTSP posts are simple/small */ } else if(rtspreq == RTSPREQ_GET_PARAMETER) { /* Check for an empty GET_PARAMETER (heartbeat) request */ data->set.httpreq = HTTPREQ_HEAD; data->set.opt_no_body = TRUE; } } /* RTSP never allows chunked transfer */ data->req.forbidchunk = TRUE; /* Finish the request buffer */ result = Curl_add_buffer(req_buffer, "\r\n", 2); if(result) return result; if(postsize > 0) { result = Curl_add_buffer(req_buffer, data->set.postfields, (size_t)postsize); if(result) return result; } /* issue the request */ result = Curl_add_buffer_send(req_buffer, conn, &data->info.request_size, 0, FIRSTSOCKET); if(result) { failf(data, "Failed sending RTSP request"); return result; } Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount, putsize?FIRSTSOCKET:-1, putsize?&http->writebytecount:NULL); /* Increment the CSeq on success */ data->state.rtsp_next_client_CSeq++; if(http->writebytecount) { /* if a request-body has been sent off, we make sure this progress is noted properly */ Curl_pgrsSetUploadCounter(data, http->writebytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; } return result; }
static CURLcode file_upload(struct connectdata *conn) { struct FILEPROTO *file = conn->data->req.protop; const char *dir = strchr(file->path, DIRSEP); int fd; int mode; CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; char *buf = data->state.buffer; size_t nread; size_t nwrite; curl_off_t bytecount = 0; struct timeval now = Curl_tvnow(); struct_stat file_stat; const char* buf2; /* * Since FILE: doesn't do the full init, we need to provide some extra * assignments here. */ conn->data->req.upload_fromhere = buf; if(!dir) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ if(!dir[1]) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ #ifdef O_BINARY #define MODE_DEFAULT O_WRONLY|O_CREAT|O_BINARY #else #define MODE_DEFAULT O_WRONLY|O_CREAT #endif if(data->state.resume_from) mode = MODE_DEFAULT|O_APPEND; else mode = MODE_DEFAULT|O_TRUNC; fd = open(file->path, mode, conn->data->set.new_file_perms); if(fd < 0) { failf(data, "Can't open %s for writing", file->path); return CURLE_WRITE_ERROR; } if(-1 != data->state.infilesize) /* known size of data to "upload" */ Curl_pgrsSetUploadSize(data, data->state.infilesize); /* treat the negative resume offset value as the case of "-" */ if(data->state.resume_from < 0) { if(fstat(fd, &file_stat)) { close(fd); failf(data, "Can't get the size of %s", file->path); return CURLE_WRITE_ERROR; } else data->state.resume_from = (curl_off_t)file_stat.st_size; } while(!result) { int readcount; result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); if(result) break; if(readcount <= 0) /* fix questionable compare error. curlvms */ break; nread = (size_t)readcount; /*skip bytes before resume point*/ if(data->state.resume_from) { if((curl_off_t)nread <= data->state.resume_from) { data->state.resume_from -= nread; nread = 0; buf2 = buf; } else { buf2 = buf + data->state.resume_from; nread -= (size_t)data->state.resume_from; data->state.resume_from = 0; } } else buf2 = buf; /* write the data to the target */ nwrite = write(fd, buf2, nread); if(nwrite != nread) { result = CURLE_SEND_ERROR; break; } bytecount += nread; Curl_pgrsSetUploadCounter(data, bytecount); if(Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; else result = Curl_speedcheck(data, now); } if(!result && Curl_pgrsUpdate(conn)) result = CURLE_ABORTED_BY_CALLBACK; close(fd); return result; }
static CURLcode telnet_do(struct connectdata *conn, bool *done) { CURLcode result; struct SessionHandle *data = conn->data; curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; #ifdef USE_WINSOCK HMODULE wsock2; WSOCK2_FUNC close_event_func; WSOCK2_FUNC create_event_func; WSOCK2_FUNC event_select_func; WSOCK2_FUNC enum_netevents_func; WSAEVENT event_handle; WSANETWORKEVENTS events; HANDLE stdin_handle; HANDLE objs[2]; DWORD obj_count; DWORD wait_timeout; DWORD waitret; DWORD readfile_read; int err; #else int interval_ms; struct pollfd pfd[2]; int poll_cnt; curl_off_t total_dl = 0; curl_off_t total_ul = 0; #endif ssize_t nread; struct timeval now; bool keepon = TRUE; char *buf = data->state.buffer; struct TELNET *tn; *done = TRUE; /* unconditionally */ result = init_telnet(conn); if(result) return result; tn = (struct TELNET *)data->req.protop; result = check_telnet_options(conn); if(result) return result; #ifdef USE_WINSOCK /* ** This functionality only works with WinSock >= 2.0. So, ** make sure have it. */ result = check_wsock2(data); if(result) return result; /* OK, so we have WinSock 2.0. We need to dynamically */ /* load ws2_32.dll and get the function pointers we need. */ wsock2 = LoadLibrary(TEXT("WS2_32.DLL")); if(wsock2 == NULL) { failf(data, "failed to load WS2_32.DLL (%d)", ERRNO); return CURLE_FAILED_INIT; } /* Grab a pointer to WSACreateEvent */ create_event_func = GetProcAddress(wsock2, "WSACreateEvent"); if(create_event_func == NULL) { failf(data, "failed to find WSACreateEvent function (%d)", ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSACloseEvent */ close_event_func = GetProcAddress(wsock2, "WSACloseEvent"); if(close_event_func == NULL) { failf(data, "failed to find WSACloseEvent function (%d)", ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSAEventSelect */ event_select_func = GetProcAddress(wsock2, "WSAEventSelect"); if(event_select_func == NULL) { failf(data, "failed to find WSAEventSelect function (%d)", ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* And WSAEnumNetworkEvents */ enum_netevents_func = GetProcAddress(wsock2, "WSAEnumNetworkEvents"); if(enum_netevents_func == NULL) { failf(data, "failed to find WSAEnumNetworkEvents function (%d)", ERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* We want to wait for both stdin and the socket. Since ** the select() function in winsock only works on sockets ** we have to use the WaitForMultipleObjects() call. */ /* First, create a sockets event object */ event_handle = (WSAEVENT)create_event_func(); if(event_handle == WSA_INVALID_EVENT) { failf(data, "WSACreateEvent failed (%d)", SOCKERRNO); FreeLibrary(wsock2); return CURLE_FAILED_INIT; } /* Tell winsock what events we want to listen to */ if(event_select_func(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { close_event_func(event_handle); FreeLibrary(wsock2); return CURLE_OK; } /* The get the Windows file handle for stdin */ stdin_handle = GetStdHandle(STD_INPUT_HANDLE); /* Create the list of objects to wait for */ objs[0] = event_handle; objs[1] = stdin_handle; /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, else use the old WaitForMultipleObjects() way */ if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || data->set.is_fread_set) { /* Don't wait for stdin_handle, just wait for event_handle */ obj_count = 1; /* Check stdin_handle per 100 milliseconds */ wait_timeout = 100; } else { obj_count = 2; wait_timeout = 1000; } /* Keep on listening and act on events */ while(keepon) { waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); switch(waitret) { case WAIT_TIMEOUT: { for(;;) { if(data->set.is_fread_set) { /* read from user-supplied method */ result = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, data->state.in); if(result == CURL_READFUNC_ABORT) { keepon = FALSE; result = CURLE_READ_ERROR; break; } if(result == CURL_READFUNC_PAUSE) break; if(result == 0) /* no bytes */ break; readfile_read = result; /* fall thru with number of bytes read */ } else { /* read from stdin */ if(!PeekNamedPipe(stdin_handle, NULL, 0, NULL, &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; break; } if(!readfile_read) break; if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; break; } } result = send_telnet_data(conn, buf, readfile_read); if(result) { keepon = FALSE; break; } } } break; case WAIT_OBJECT_0 + 1: { if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; break; } result = send_telnet_data(conn, buf, readfile_read); if(result) { keepon = FALSE; break; } } break; case WAIT_OBJECT_0: events.lNetworkEvents = 0; if(SOCKET_ERROR == enum_netevents_func(sockfd, event_handle, &events)) { if((err = SOCKERRNO) != EINPROGRESS) { infof(data, "WSAEnumNetworkEvents failed (%d)", err); keepon = FALSE; result = CURLE_READ_ERROR; } break; } if(events.lNetworkEvents & FD_READ) { /* read data from network */ result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; /* returned not-zero, this an error */ else if(result) { keepon = FALSE; break; } /* returned zero but actually received 0 or less here, the server closed the connection and we bail out */ else if(nread <= 0) { keepon = FALSE; break; } result = telrcv(conn, (unsigned char *) buf, nread); if(result) { keepon = FALSE; break; } /* Negotiate if the peer has started negotiating, otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ if(tn->please_negotiate && !tn->already_negotiated) { negotiate(conn); tn->already_negotiated = 1; } } if(events.lNetworkEvents & FD_CLOSE) { keepon = FALSE; } break; } if(data->set.timeout) { now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { failf(data, "Time-out"); result = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; } } } /* We called WSACreateEvent, so call WSACloseEvent */ if(!close_event_func(event_handle)) { infof(data, "WSACloseEvent failed (%d)", SOCKERRNO); } /* "Forget" pointers into the library we're about to free */ create_event_func = NULL; close_event_func = NULL; event_select_func = NULL; enum_netevents_func = NULL; /* We called LoadLibrary, so call FreeLibrary */ if(!FreeLibrary(wsock2)) infof(data, "FreeLibrary(wsock2) failed (%d)", ERRNO); #else pfd[0].fd = sockfd; pfd[0].events = POLLIN; if(data->set.is_fread_set) { poll_cnt = 1; interval_ms = 100; /* poll user-supplied read function */ } else { /* really using fread, so infile is a FILE* */ pfd[1].fd = fileno((FILE *)data->state.in); pfd[1].events = POLLIN; poll_cnt = 2; interval_ms = 1 * 1000; } while(keepon) { switch (Curl_poll(pfd, poll_cnt, interval_ms)) { case -1: /* error, stop reading */ keepon = FALSE; continue; case 0: /* timeout */ pfd[0].revents = 0; pfd[1].revents = 0; /* fall through */ default: /* read! */ if(pfd[0].revents & POLLIN) { /* read data from network */ result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); /* read would've blocked. Loop again */ if(result == CURLE_AGAIN) break; /* returned not-zero, this an error */ else if(result) { keepon = FALSE; break; } /* returned zero but actually received 0 or less here, the server closed the connection and we bail out */ else if(nread <= 0) { keepon = FALSE; break; } total_dl += nread; Curl_pgrsSetDownloadCounter(data, total_dl); result = telrcv(conn, (unsigned char *)buf, nread); if(result) { keepon = FALSE; break; } /* Negotiate if the peer has started negotiating, otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ if(tn->please_negotiate && !tn->already_negotiated) { negotiate(conn); tn->already_negotiated = 1; } } nread = 0; if(poll_cnt == 2) { if(pfd[1].revents & POLLIN) { /* read from in file */ nread = read(pfd[1].fd, buf, BUFSIZE - 1); } } else { /* read from user-supplied method */ nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1, data->state.in); if(nread == CURL_READFUNC_ABORT) { keepon = FALSE; break; } if(nread == CURL_READFUNC_PAUSE) break; } if(nread > 0) { result = send_telnet_data(conn, buf, nread); if(result) { keepon = FALSE; break; } total_ul += nread; Curl_pgrsSetUploadCounter(data, total_ul); } else if(nread < 0) keepon = FALSE; break; } /* poll switch statement */ if(data->set.timeout) { now = Curl_tvnow(); if(Curl_tvdiff(now, conn->created) >= data->set.timeout) { failf(data, "Time-out"); result = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; } } if(Curl_pgrsUpdate(conn)) { result = CURLE_ABORTED_BY_CALLBACK; break; } } #endif /* mark this as "no further transfer wanted" */ Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL); return result; }
static CURLcode file_upload(struct connectdata *conn) { struct FILEPROTO *file = conn->proto.file; char *dir = strchr(file->path, DIRSEP); FILE *fp; CURLcode res=CURLE_OK; struct SessionHandle *data = conn->data; char *buf = data->state.buffer; size_t nread; size_t nwrite; curl_off_t bytecount = 0; struct timeval now = Curl_tvnow(); /* * Since FILE: doesn't do the full init, we need to provide some extra * assignments here. */ conn->fread = data->set.fread; conn->fread_in = data->set.in; conn->upload_fromhere = buf; if(!dir) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ if(!dir[1]) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ fp = fopen(file->path, "wb"); if(!fp) { failf(data, "Can't open %s for writing", file->path); return CURLE_WRITE_ERROR; } if(-1 != data->set.infilesize) /* known size of data to "upload" */ Curl_pgrsSetUploadSize(data, data->set.infilesize); while (res == CURLE_OK) { int readcount; res = Curl_fillreadbuffer(conn, BUFSIZE, &readcount); if(res) break; nread = (size_t)readcount; if (nread <= 0) break; /* write the data to the target */ nwrite = fwrite(buf, 1, nread, fp); if(nwrite != nread) { res = CURLE_SEND_ERROR; break; } bytecount += nread; Curl_pgrsSetUploadCounter(data, bytecount); if(Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; else res = Curl_speedcheck(data, now); } if(!res && Curl_pgrsUpdate(conn)) res = CURLE_ABORTED_BY_CALLBACK; fclose(fp); return res; }