1e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/*************************************************************************** 2e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * _ _ ____ _ 3e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Project ___| | | | _ \| | 4e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * / __| | | | |_) | | 5e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * | (__| |_| | _ <| |___ 6e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * \___|\___/|_| \_\_____| 7e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 88f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. 9e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 10e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is licensed as described in the file COPYING, which 11e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * you should have received as part of this distribution. The terms 128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html. 13e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 14e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * copies of the Software, and permit persons to whom the Software is 16e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * furnished to do so, under the terms of the COPYING file. 17e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 18e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * KIND, either express or implied. 20e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 21e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET ***************************************************************************/ 228f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 238f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo/* <DESC> 248f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * POP3 example using the multi interface 258f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * </DESC> 268f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo */ 278f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo 28e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <stdio.h> 298f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo#include <string.h> 30e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include <curl/curl.h> 31e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 32e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET/* This is a simple example showing how to retrieve mail using libcurl's POP3 33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * capabilities. It builds on the pop3-retr.c example to demonstrate how to use 34e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * libcurl's multi interface. 35e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * 36e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Note that this example requires libcurl 7.20.0 or above. 37e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET */ 38e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 39e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000 40e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 41e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic struct timeval tvnow(void) 42e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 43e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval now; 44e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 45e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* time() returns the value of time in seconds since the epoch */ 46e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET now.tv_sec = (long)time(NULL); 47e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET now.tv_usec = 0; 48e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return now; 50e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 51e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 52e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic long tvdiff(struct timeval newer, struct timeval older) 53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 54e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return (newer.tv_sec - older.tv_sec) * 1000 + 55e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET (newer.tv_usec - older.tv_usec) / 1000; 56e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 57e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 58e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETint main(void) 59e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET{ 60e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURL *curl; 61e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLM *mcurl; 62e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int still_running = 1; 63e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval mp_start; 64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 65e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_global_init(CURL_GLOBAL_DEFAULT); 66e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 67e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl = curl_easy_init(); 68e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!curl) 69e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 1; 70e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 71e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET mcurl = curl_multi_init(); 72e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(!mcurl) 73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 2; 74e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 75e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Set username and password */ 76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_USERNAME, "user"); 77e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret"); 78e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* This will retrieve message 1 from the user's mailbox */ 80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_setopt(curl, CURLOPT_URL, "pop3://pop.example.com/1"); 81e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 82e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Tell the multi stack about our easy handle */ 83e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_add_handle(mcurl, curl); 84e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Record the start time which we can use later */ 86e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET mp_start = tvnow(); 87e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 88e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* We start some action by calling perform right away */ 89e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_perform(mcurl, &still_running); 90e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 91e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET while(still_running) { 92e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval timeout; 93e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fd_set fdread; 94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fd_set fdwrite; 95e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fd_set fdexcep; 96e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int maxfd = -1; 97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET int rc; 98e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET CURLMcode mc; /* curl_multi_fdset() return code */ 99e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET long curl_timeo = -1; 101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 102e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Initialise the file descriptors */ 103e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FD_ZERO(&fdread); 104e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FD_ZERO(&fdwrite); 105e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET FD_ZERO(&fdexcep); 106e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 107e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Set a suitable timeout to play around with */ 108e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout.tv_sec = 1; 109e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout.tv_usec = 0; 110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_timeout(mcurl, &curl_timeo); 112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(curl_timeo >= 0) { 113e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout.tv_sec = curl_timeo / 1000; 114e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(timeout.tv_sec > 1) 115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout.tv_sec = 1; 116e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else 117e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET timeout.tv_usec = (curl_timeo % 1000) * 1000; 118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 119e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 120e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* get file descriptors from the transfers */ 121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd); 122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 1238f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo if(mc != CURLM_OK) { 124e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); 125e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 126e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 128e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* On success the value of maxfd is guaranteed to be >= -1. We call 129e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET select(maxfd + 1, ...); specially in case of (maxfd == -1) there are 130e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET no fds ready yet so we call select(0, ...) --or Sleep() on Windows-- 131e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET to sleep 100ms, which is the minimum suggested value in the 132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_fdset() doc. */ 133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(maxfd == -1) { 135e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#ifdef _WIN32 136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET Sleep(100); 137e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rc = 0; 138e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#else 139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Portable sleep for platforms other than Windows. */ 140e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET struct timeval wait = { 0, 100 * 1000 }; /* 100ms */ 141e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rc = select(0, NULL, NULL, NULL, &wait); 142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#endif 143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 144e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET else { 145e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Note that on some platforms 'timeout' may be modified by select(). 146e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET If you need access to the original value save a copy beforehand. */ 147e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); 148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 149e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 150e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { 151e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET fprintf(stderr, 152e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET "ABORTING: Since it seems that we would have run forever.\n"); 153e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 154e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 155e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 156e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET switch(rc) { 157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case -1: /* select error */ 158e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 159e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET case 0: /* timeout */ 160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET default: /* action */ 161e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_perform(mcurl, &still_running); 162e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET break; 163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET } 165e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET /* Always cleanup */ 167e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_remove_handle(mcurl, curl); 168e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_multi_cleanup(mcurl); 169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_easy_cleanup(curl); 170e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET curl_global_cleanup(); 171e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET 172e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET return 0; 173e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET} 174