Skip to content

Instantly share code, notes, and snippets.

@bnoordhuis
Created February 16, 2011 00:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bnoordhuis/828613 to your computer and use it in GitHub Desktop.
Save bnoordhuis/828613 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/select.h>
#include <curl/curl.h>
#define IMAP_URL "imap://testuser:testuser@localhost/Drafts"
#define IMAPS_URL "imaps://testuser:testuser@localhost/Drafts"
static long timeout_ = -1;
static int sockfd_ = -1;
static int events_ = -1;
static int socket_callback(CURL *c, curl_socket_t sockfd, int events, void *userp, void *socketp) {
sockfd_ = sockfd;
events_ = events;
return CURLM_OK;
}
static int multi_timer_callback(CURLM *m, long timeout, void *userp) {
timeout_ = timeout;
return CURLM_OK;
}
static void test_multi(const char *url, int use_ssl) {
struct timeval tv;
fd_set readfds;
fd_set writefds;
CURLMcode status;
CURLM *m;
CURL *c;
int n_fds;
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
m = curl_multi_init();
c = curl_easy_init();
assert(m != NULL);
assert(c != NULL);
curl_multi_setopt(m, CURLMOPT_TIMERFUNCTION, multi_timer_callback);
curl_multi_setopt(m, CURLMOPT_SOCKETFUNCTION, socket_callback);
curl_easy_setopt(c, CURLOPT_URL, url);
curl_easy_setopt(c, CURLOPT_USE_SSL, use_ssl);
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
status = curl_multi_add_handle(m, c);
assert(status == CURLM_OK);
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
assert(n_fds > 0);
assert(sockfd_ != -1);
assert(events_ != -1);
assert(timeout_ != -1);
do {
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (events_ & CURL_POLL_IN) {
FD_SET(sockfd_, &readfds);
}
if (events_ & CURL_POLL_OUT) {
FD_SET(sockfd_, &writefds);
}
if (timeout_ == -1) {
// 100 ms timeout
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
}
else {
tv.tv_sec = timeout_ / 1000;
tv.tv_usec = (timeout_ % 1000) * 1000;
}
if (-1 == select(sockfd_ + 1, &readfds, &writefds, NULL, &tv)) {
perror("select");
abort();
}
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
}
while (n_fds > 0);
assert(events_ == CURL_POLL_REMOVE);
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
}
static void test_easy(const char *url, int use_ssl) {
CURLcode status;
CURL *c;
c = curl_easy_init();
assert(c != NULL);
curl_easy_setopt(c, CURLOPT_URL, url);
curl_easy_setopt(c, CURLOPT_USE_SSL, use_ssl);
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
status = curl_easy_perform(c);
assert(status == CURLE_OK);
curl_easy_cleanup(c);
}
int main(void) {
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
test_easy(IMAP_URL, 0); // plain IMAP
test_easy(IMAP_URL, 1); // upgrade to TLS
test_easy(IMAPS_URL, 0); // start with TLS
test_multi(IMAP_URL, 0); // plain IMAP
test_multi(IMAP_URL, 1); // upgrade to TLS
test_multi(IMAPS_URL, 0); // start with TLS
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/select.h>
#include <curl/curl.h>
#define POP3_URL "pop3://testuser:testuser@localhost/"
#define POP3S_URL "pop3s://testuser:testuser@localhost/"
static long timeout_ = -1;
static int sockfd_ = -1;
static int events_ = -1;
static int socket_callback(CURL *c, curl_socket_t sockfd, int events, void *userp, void *socketp) {
sockfd_ = sockfd;
events_ = events;
return CURLM_OK;
}
static int multi_timer_callback(CURLM *m, long timeout, void *userp) {
timeout_ = timeout;
return CURLM_OK;
}
static void test_multi(const char *url, int use_ssl) {
struct timeval tv;
fd_set readfds;
fd_set writefds;
CURLMcode status;
CURLM *m;
CURL *c;
int n_fds;
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
m = curl_multi_init();
c = curl_easy_init();
assert(m != NULL);
assert(c != NULL);
curl_multi_setopt(m, CURLMOPT_TIMERFUNCTION, multi_timer_callback);
curl_multi_setopt(m, CURLMOPT_SOCKETFUNCTION, socket_callback);
curl_easy_setopt(c, CURLOPT_URL, url);
curl_easy_setopt(c, CURLOPT_VERBOSE, 1);
curl_easy_setopt(c, CURLOPT_USE_SSL, use_ssl);
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
status = curl_multi_add_handle(m, c);
assert(status == CURLM_OK);
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
assert(n_fds > 0);
assert(sockfd_ != -1);
assert(events_ != -1);
assert(timeout_ != -1);
do {
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (events_ & CURL_POLL_IN) {
FD_SET(sockfd_, &readfds);
}
if (events_ & CURL_POLL_OUT) {
FD_SET(sockfd_, &writefds);
}
if (timeout_ == -1) {
// 100 ms timeout
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
}
else {
tv.tv_sec = timeout_ / 1000;
tv.tv_usec = (timeout_ % 1000) * 1000;
}
if (-1 == select(sockfd_ + 1, &readfds, &writefds, NULL, &tv)) {
perror("select");
abort();
}
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
}
while (n_fds > 0);
assert(events_ == CURL_POLL_REMOVE);
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
}
static void test_easy(const char *url, int use_ssl) {
CURLcode status;
CURL *c;
c = curl_easy_init();
assert(c != NULL);
curl_easy_setopt(c, CURLOPT_URL, url);
curl_easy_setopt(c, CURLOPT_VERBOSE, 1);
curl_easy_setopt(c, CURLOPT_USE_SSL, use_ssl);
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
status = curl_easy_perform(c);
assert(status == CURLE_OK);
curl_easy_cleanup(c);
}
int main(void) {
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
test_easy(POP3_URL, 0); // plain POP3
test_easy(POP3_URL, 1); // upgrade to TLS
test_easy(POP3S_URL, 0); // start with TLS
test_multi(POP3_URL, 0); // plain POP3
test_multi(POP3_URL, 1); // upgrade to TLS
test_multi(POP3S_URL, 0); // start with TLS
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/select.h>
#include <curl/curl.h>
#define SMTP_URL "smtp://localhost/"
#define SMTPS_URL "smtps://localhost/"
#define CRLF "\r\n"
typedef struct {
const char *p, *pe;
} READER;
static long timeout_ = -1;
static int sockfd_ = -1;
static int events_ = -1;
static int socket_callback(CURL *c, curl_socket_t sockfd, int events, void *userp, void *socketp) {
sockfd_ = sockfd;
events_ = events;
return CURLM_OK;
}
static int multi_timer_callback(CURLM *m, long timeout, void *userp) {
timeout_ = timeout;
return CURLM_OK;
}
static size_t read_callback(char *buffer, size_t size, size_t nitems, void *userp) {
READER *r = userp;
if (r->p >= r->pe) {
return 0;
}
size_t len = size * nitems;
size_t left = r->pe - r->p;
if (len > left) {
len = left;
}
memcpy(buffer, r->p, len);
r->p += len;
return len;
}
// this function leaks memory but we don't care because it's only a test
static CURL *create_easy_handle(const char *url, int use_ssl) {
#define CRLF "\r\n"
static const char data[] =
"Subject: Test 1,2,3" CRLF
CRLF
"This is a test message." CRLF
;
struct curl_slist *recipients;
READER *r;
CURL *c;
recipients = curl_slist_append(NULL, "\"Q.A. Tester\" <testuser@localhost>");
c = curl_easy_init();
assert(c != NULL);
curl_easy_setopt(c, CURLOPT_URL, url);
curl_easy_setopt(c, CURLOPT_VERBOSE, 1);
curl_easy_setopt(c, CURLOPT_USE_SSL, use_ssl);
curl_easy_setopt(c, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(c, CURLOPT_MAIL_FROM, "\"Q.A. Tester\" <testuser@localhost>");
curl_easy_setopt(c, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(c, CURLOPT_READFUNCTION, read_callback);
r = malloc(sizeof *r);
r->p = data;
r->pe = data + sizeof(data) - 1;
curl_easy_setopt(c, CURLOPT_READDATA, r);
return c;
}
static void test_multi(const char *url, int use_ssl) {
struct timeval tv;
fd_set readfds;
fd_set writefds;
CURLMcode status;
CURLM *m;
CURL *c;
int n_fds;
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
m = curl_multi_init();
assert(m != NULL);
curl_multi_setopt(m, CURLMOPT_TIMERFUNCTION, multi_timer_callback);
curl_multi_setopt(m, CURLMOPT_SOCKETFUNCTION, socket_callback);
c = create_easy_handle(url, use_ssl);
status = curl_multi_add_handle(m, c);
assert(status == CURLM_OK);
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
assert(n_fds > 0);
assert(sockfd_ != -1);
assert(events_ != -1);
assert(timeout_ != -1);
do {
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (events_ & CURL_POLL_IN) {
FD_SET(sockfd_, &readfds);
}
if (events_ & CURL_POLL_OUT) {
FD_SET(sockfd_, &writefds);
}
if (timeout_ == -1) {
// 100 ms timeout
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
}
else {
tv.tv_sec = timeout_ / 1000;
tv.tv_usec = (timeout_ % 1000) * 1000;
}
if (-1 == select(sockfd_ + 1, &readfds, &writefds, NULL, &tv)) {
perror("select");
abort();
}
status = curl_multi_socket_all(m, &n_fds);
assert(status == CURLM_OK);
}
while (n_fds > 0);
assert(events_ == CURL_POLL_REMOVE);
curl_multi_remove_handle(m, c);
curl_multi_cleanup(m);
curl_easy_cleanup(c);
}
static void test_easy(const char *url, int use_ssl) {
CURLcode status;
CURL *c;
c = create_easy_handle(url, use_ssl);
status = curl_easy_perform(c);
puts(curl_easy_strerror(status));
assert(status == CURLE_OK);
curl_easy_cleanup(c);
}
int main(void) {
if (curl_global_init(CURL_GLOBAL_ALL)) {
abort();
}
atexit(curl_global_cleanup);
test_easy(SMTP_URL, 0); // plain SMTP
test_easy(SMTP_URL, 1); // upgrade to TLS
test_easy(SMTPS_URL, 0); // start with TLS
test_multi(SMTP_URL, 0); // plain SMTP
test_multi(SMTP_URL, 1); // upgrade to TLS
test_multi(SMTPS_URL, 0); // start with TLS
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment