On 4/26/2020 4:44 PM, Jean-Francois Dockes wrote:
Thanks for the CURLOPT_CONNECT_ONLY pointer.

Is there something to prevent me from using the resulting socket fd with
CURLOPT_OPENSOCKETFUNCTION / CURLOPT_SOCKOPTFUNCTION ? I see that this is a
bit convoluted, but it gains me the use of the libcurl URL parsing and
connect code instead of DIY. Does it make sense ? Performance is no big
issue in my use case.

Since you are not sensible on performance, I wrote a working example that does the job in 2 phases: 1 for the connect and 2 for the HTTP protocol, reusing the socket descriptor from 1. It is then possible to get the local address between the 2 phases. As it uses CURLOPT_CONNECT_ONLY, connection reuse does not apply.

Please find it in attachment.

#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);
}
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette:   https://curl.haxx.se/mail/etiquette.html

Reply via email to