#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <curl/curl.h>


int
sockopt_callback(void *clientp, curl_socket_t curlfd, curlsocktype purpose)
{
	curl_socket_t openedsocket = *(curl_socket_t *) clientp;

	dup2(openedsocket, curlfd);
	return CURL_SOCKOPT_ALREADY_CONNECTED;
}


CURL *
new_handle(void)
{
  CURL *easy = curl_easy_init();

  curl_easy_setopt(easy, CURLOPT_URL, "http://www.example.com");
  curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L);
  return easy;
}


int
main(int argc, char **argv)
{
  CURL *hconnect;
  CURL *htalk;
  struct curl_slist *headers = NULL;
  curl_socket_t sock;
  struct sockaddr_storage locaddr;
  socklen_t lasize = sizeof(locaddr);
  struct sockaddr_in *la4 = (struct sockaddr_in *) &locaddr;
  struct sockaddr_in6 *la6 = (struct sockaddr_in6 *) &locaddr;
  char addrbuf[64];
  char hdrbuf[128];

  curl_global_init(CURL_GLOBAL_ALL);
  hconnect = new_handle();
  curl_easy_setopt(hconnect, CURLOPT_CONNECT_ONLY, 1L);
  curl_easy_perform(hconnect);

  curl_easy_getinfo(hconnect, CURLINFO_ACTIVESOCKET, &sock);
  getsockname(sock, (struct sockaddr *) &locaddr, &lasize);
  inet_ntop(la4->sin_family,
            la4->sin_family == AF_INET? (void *) &la4->sin_addr:
                                        (void *) &la6->sin6_addr,
            addrbuf, sizeof(addrbuf));
  snprintf(hdrbuf, sizeof(hdrbuf), "X-My-Address: %s", addrbuf);
  headers = curl_slist_append(headers, hdrbuf);

  htalk = new_handle();
  curl_easy_setopt(htalk, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
  curl_easy_setopt(htalk, CURLOPT_SOCKOPTDATA, &sock);
  curl_easy_setopt(htalk, CURLOPT_HTTPHEADER, headers);
  curl_easy_perform(htalk);

  curl_easy_cleanup(htalk);
  curl_easy_cleanup(hconnect);
  curl_slist_free_all(headers);
  curl_global_cleanup();
  exit(0);
}

