lib582.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 #include "test.h"
00023 
00024 #include <fcntl.h>
00025 
00026 #include "testutil.h"
00027 #include "warnless.h"
00028 #include "memdebug.h"
00029 
00030 #define TEST_HANG_TIMEOUT 60 * 1000
00031 
00032 struct Sockets
00033 {
00034   curl_socket_t *sockets;
00035   int count;      /* number of sockets actually stored in array */
00036   int max_count;  /* max number of sockets that fit in allocated array */
00037 };
00038 
00039 struct ReadWriteSockets
00040 {
00041   struct Sockets read, write;
00042 };
00043 
00047 static void removeFd(struct Sockets* sockets, curl_socket_t fd, int mention)
00048 {
00049   int i;
00050 
00051   if(mention)
00052     fprintf(stderr, "Remove socket fd %d\n", (int) fd);
00053 
00054   for(i = 0; i < sockets->count; ++i) {
00055     if(sockets->sockets[i] == fd) {
00056       if(i < sockets->count - 1)
00057         memmove(&sockets->sockets[i], &sockets->sockets[i + 1],
00058               sizeof(curl_socket_t) * (sockets->count - (i + 1)));
00059       --sockets->count;
00060     }
00061   }
00062 }
00063 
00067 static void addFd(struct Sockets* sockets, curl_socket_t fd, const char *what)
00068 {
00073   fprintf(stderr, "Add socket fd %d for %s\n", (int) fd, what);
00074   removeFd(sockets, fd, 0);
00075   /*
00076    * Allocate array storage when required.
00077    */
00078   if(!sockets->sockets) {
00079     sockets->sockets = malloc(sizeof(curl_socket_t) * 20U);
00080     if(!sockets->sockets)
00081       return;
00082     sockets->max_count = 20;
00083   }
00084   else if(sockets->count + 1 > sockets->max_count) {
00085     curl_socket_t *oldptr = sockets->sockets;
00086     sockets->sockets = realloc(oldptr, sizeof(curl_socket_t) *
00087                                (sockets->max_count + 20));
00088     if(!sockets->sockets) {
00089       /* cleanup in test_cleanup */
00090       sockets->sockets = oldptr;
00091       return;
00092     }
00093     sockets->max_count += 20;
00094   }
00095   /*
00096    * Add file descriptor to array.
00097    */
00098   sockets->sockets[sockets->count] = fd;
00099   ++sockets->count;
00100 }
00101 
00105 static int curlSocketCallback(CURL *easy, curl_socket_t s, int action,
00106                               void *userp, void *socketp)
00107 {
00108   struct ReadWriteSockets* sockets = userp;
00109 
00110   (void)easy; /* unused */
00111   (void)socketp; /* unused */
00112 
00113   if(action == CURL_POLL_IN || action == CURL_POLL_INOUT)
00114     addFd(&sockets->read, s, "read");
00115 
00116   if(action == CURL_POLL_OUT || action == CURL_POLL_INOUT)
00117     addFd(&sockets->write, s, "write");
00118 
00119   if(action == CURL_POLL_REMOVE) {
00120     removeFd(&sockets->read, s, 1);
00121     removeFd(&sockets->write, s, 0);
00122   }
00123 
00124   return 0;
00125 }
00126 
00130 static int curlTimerCallback(CURLM *multi, long timeout_ms, void *userp)
00131 {
00132   struct timeval* timeout = userp;
00133 
00134   (void)multi; /* unused */
00135   if(timeout_ms != -1) {
00136     *timeout = tutil_tvnow();
00137     timeout->tv_usec += timeout_ms * 1000;
00138   }
00139   else {
00140     timeout->tv_sec = -1;
00141   }
00142   return 0;
00143 }
00144 
00148 static int checkForCompletion(CURLM *curl, int *success)
00149 {
00150   int numMessages;
00151   CURLMsg *message;
00152   int result = 0;
00153   *success = 0;
00154   while((message = curl_multi_info_read(curl, &numMessages)) != NULL) {
00155     if(message->msg == CURLMSG_DONE) {
00156       result = 1;
00157       if(message->data.result == CURLE_OK)
00158         *success = 1;
00159       else
00160         *success = 0;
00161     }
00162     else {
00163       fprintf(stderr, "Got an unexpected message from curl: %i\n",
00164               (int)message->msg);
00165       result = 1;
00166       *success = 0;
00167     }
00168   }
00169   return result;
00170 }
00171 
00172 static int getMicroSecondTimeout(struct timeval* timeout)
00173 {
00174   struct timeval now;
00175   ssize_t result;
00176   now = tutil_tvnow();
00177   result = (timeout->tv_sec - now.tv_sec) * 1000000 +
00178     timeout->tv_usec - now.tv_usec;
00179   if(result < 0)
00180     result = 0;
00181 
00182   return curlx_sztosi(result);
00183 }
00184 
00188 static void updateFdSet(struct Sockets* sockets, fd_set* fdset,
00189                         curl_socket_t *maxFd)
00190 {
00191   int i;
00192   for(i = 0; i < sockets->count; ++i) {
00193     FD_SET(sockets->sockets[i], fdset);
00194     if(*maxFd < sockets->sockets[i] + 1) {
00195       *maxFd = sockets->sockets[i] + 1;
00196     }
00197   }
00198 }
00199 
00200 static void notifyCurl(CURLM *curl, curl_socket_t s, int evBitmask,
00201                        const char *info)
00202 {
00203   int numhandles = 0;
00204   CURLMcode result = curl_multi_socket_action(curl, s, evBitmask, &numhandles);
00205   if(result != CURLM_OK) {
00206     fprintf(stderr, "Curl error on %s: %i (%s)\n",
00207             info, result, curl_multi_strerror(result));
00208   }
00209 }
00210 
00214 static void checkFdSet(CURLM *curl, struct Sockets *sockets, fd_set *fdset,
00215                        int evBitmask, const char *name)
00216 {
00217   int i;
00218   for(i = 0; i < sockets->count; ++i) {
00219     if(FD_ISSET(sockets->sockets[i], fdset)) {
00220       notifyCurl(curl, sockets->sockets[i], evBitmask, name);
00221     }
00222   }
00223 }
00224 
00225 int test(char *URL)
00226 {
00227   int res = 0;
00228   CURL *curl = NULL;
00229   FILE *hd_src = NULL;
00230   int hd;
00231   int error;
00232   struct_stat file_info;
00233   CURLM *m = NULL;
00234   struct ReadWriteSockets sockets = {{NULL, 0, 0}, {NULL, 0, 0}};
00235   struct timeval timeout = {-1, 0};
00236   int success = 0;
00237 
00238   start_test_timing();
00239 
00240   if(!libtest_arg3) {
00241     fprintf(stderr, "Usage: lib582 [url] [filename] [username]\n");
00242     return TEST_ERR_USAGE;
00243   }
00244 
00245   hd_src = fopen(libtest_arg2, "rb");
00246   if(NULL == hd_src) {
00247     error = ERRNO;
00248     fprintf(stderr, "fopen() failed with error: %d (%s)\n",
00249             error, strerror(error));
00250     fprintf(stderr, "Error opening file: (%s)\n", libtest_arg2);
00251     return TEST_ERR_FOPEN;
00252   }
00253 
00254   /* get the file size of the local file */
00255   hd = fstat(fileno(hd_src), &file_info);
00256   if(hd == -1) {
00257     /* can't open file, bail out */
00258     error = ERRNO;
00259     fprintf(stderr, "fstat() failed with error: %d (%s)\n",
00260             error, strerror(error));
00261     fprintf(stderr, "ERROR: cannot open file (%s)\n", libtest_arg2);
00262     fclose(hd_src);
00263     return TEST_ERR_FSTAT;
00264   }
00265   fprintf(stderr, "Set to upload %d bytes\n", (int)file_info.st_size);
00266 
00267   res_global_init(CURL_GLOBAL_ALL);
00268   if(res) {
00269     fclose(hd_src);
00270     return res;
00271   }
00272 
00273   easy_init(curl);
00274 
00275   /* enable uploading */
00276   easy_setopt(curl, CURLOPT_UPLOAD, 1L);
00277 
00278   /* specify target */
00279   easy_setopt(curl, CURLOPT_URL, URL);
00280 
00281   /* go verbose */
00282   easy_setopt(curl, CURLOPT_VERBOSE, 1L);
00283 
00284   /* now specify which file to upload */
00285   easy_setopt(curl, CURLOPT_READDATA, hd_src);
00286 
00287   easy_setopt(curl, CURLOPT_USERPWD, libtest_arg3);
00288   easy_setopt(curl, CURLOPT_SSH_PUBLIC_KEYFILE, "curl_client_key.pub");
00289   easy_setopt(curl, CURLOPT_SSH_PRIVATE_KEYFILE, "curl_client_key");
00290 
00291   easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
00292 
00293   multi_init(m);
00294 
00295   multi_setopt(m, CURLMOPT_SOCKETFUNCTION, curlSocketCallback);
00296   multi_setopt(m, CURLMOPT_SOCKETDATA, &sockets);
00297 
00298   multi_setopt(m, CURLMOPT_TIMERFUNCTION, curlTimerCallback);
00299   multi_setopt(m, CURLMOPT_TIMERDATA, &timeout);
00300 
00301   multi_add_handle(m, curl);
00302 
00303   while(!checkForCompletion(m, &success)) {
00304     fd_set readSet, writeSet;
00305     curl_socket_t maxFd = 0;
00306     struct timeval tv = {10, 0};
00307 
00308     FD_ZERO(&readSet);
00309     FD_ZERO(&writeSet);
00310     updateFdSet(&sockets.read, &readSet, &maxFd);
00311     updateFdSet(&sockets.write, &writeSet, &maxFd);
00312 
00313     if(timeout.tv_sec != -1) {
00314       int usTimeout = getMicroSecondTimeout(&timeout);
00315       tv.tv_sec = usTimeout / 1000000;
00316       tv.tv_usec = usTimeout % 1000000;
00317     }
00318     else if(maxFd <= 0) {
00319       tv.tv_sec = 0;
00320       tv.tv_usec = 100000;
00321     }
00322 
00323     select_test(maxFd, &readSet, &writeSet, NULL, &tv);
00324 
00325     /* Check the sockets for reading / writing */
00326     checkFdSet(m, &sockets.read, &readSet, CURL_CSELECT_IN, "read");
00327     checkFdSet(m, &sockets.write, &writeSet, CURL_CSELECT_OUT, "write");
00328 
00329     if(timeout.tv_sec != -1 && getMicroSecondTimeout(&timeout) == 0) {
00330       /* Curl's timer has elapsed. */
00331       notifyCurl(m, CURL_SOCKET_TIMEOUT, 0, "timeout");
00332     }
00333 
00334     abort_on_test_timeout();
00335   }
00336 
00337   if(!success) {
00338     fprintf(stderr, "Error uploading file.\n");
00339     res = TEST_ERR_MAJOR_BAD;
00340   }
00341 
00342 test_cleanup:
00343 
00344   /* proper cleanup sequence - type PB */
00345 
00346   curl_multi_remove_handle(m, curl);
00347   curl_easy_cleanup(curl);
00348   curl_multi_cleanup(m);
00349   curl_global_cleanup();
00350 
00351   /* close the local file */
00352   fclose(hd_src);
00353 
00354   /* free local memory */
00355   free(sockets.read.sockets);
00356   free(sockets.write.sockets);
00357 
00358   return res;
00359 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:05