Home | History | Annotate | Download | only in examples
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 /* <DESC>
     23  * An example demonstrating how an application can pass in a custom
     24  * socket to libcurl to use. This example also handles the connect itself.
     25  * </DESC>
     26  */
     27 #include <stdio.h>
     28 #include <string.h>
     29 #include <stdlib.h>
     30 #include <curl/curl.h>
     31 
     32 #ifdef WIN32
     33 #include <windows.h>
     34 #include <winsock2.h>
     35 #include <ws2tcpip.h>
     36 #define close closesocket
     37 #else
     38 #include <sys/types.h>        /*  socket types              */
     39 #include <sys/socket.h>       /*  socket definitions        */
     40 #include <netinet/in.h>
     41 #include <arpa/inet.h>        /*  inet (3) functions         */
     42 #include <unistd.h>           /*  misc. Unix functions      */
     43 #endif
     44 
     45 #include <errno.h>
     46 
     47 /* The IP address and port number to connect to */
     48 #define IPADDR "127.0.0.1"
     49 #define PORTNUM 80
     50 
     51 #ifndef INADDR_NONE
     52 #define INADDR_NONE 0xffffffff
     53 #endif
     54 
     55 static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
     56 {
     57   size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
     58   return written;
     59 }
     60 
     61 static int closecb(void *clientp, curl_socket_t item)
     62 {
     63   (void)clientp;
     64   printf("libcurl wants to close %d now\n", (int)item);
     65   return 0;
     66 }
     67 
     68 static curl_socket_t opensocket(void *clientp,
     69                                 curlsocktype purpose,
     70                                 struct curl_sockaddr *address)
     71 {
     72   curl_socket_t sockfd;
     73   (void)purpose;
     74   (void)address;
     75   sockfd = *(curl_socket_t *)clientp;
     76   /* the actual externally set socket is passed in via the OPENSOCKETDATA
     77      option */
     78   return sockfd;
     79 }
     80 
     81 static int sockopt_callback(void *clientp, curl_socket_t curlfd,
     82                             curlsocktype purpose)
     83 {
     84   (void)clientp;
     85   (void)curlfd;
     86   (void)purpose;
     87   /* This return code was added in libcurl 7.21.5 */
     88   return CURL_SOCKOPT_ALREADY_CONNECTED;
     89 }
     90 
     91 int main(void)
     92 {
     93   CURL *curl;
     94   CURLcode res;
     95   struct sockaddr_in servaddr;  /*  socket address structure  */
     96   curl_socket_t sockfd;
     97 
     98 #ifdef WIN32
     99   WSADATA wsaData;
    100   int initwsa = WSAStartup(MAKEWORD(2, 0), &wsaData);
    101   if(initwsa != 0) {
    102     printf("WSAStartup failed: %d\n", initwsa);
    103     return 1;
    104   }
    105 #endif
    106 
    107   curl = curl_easy_init();
    108   if(curl) {
    109     /*
    110      * Note that libcurl will internally think that you connect to the host
    111      * and port that you specify in the URL option.
    112      */
    113     curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
    114 
    115     /* Create the socket "manually" */
    116     sockfd = socket(AF_INET, SOCK_STREAM, 0);
    117     if(sockfd == CURL_SOCKET_BAD) {
    118       printf("Error creating listening socket.\n");
    119       return 3;
    120     }
    121 
    122     memset(&servaddr, 0, sizeof(servaddr));
    123     servaddr.sin_family = AF_INET;
    124     servaddr.sin_port   = htons(PORTNUM);
    125 
    126     servaddr.sin_addr.s_addr = inet_addr(IPADDR);
    127     if(INADDR_NONE == servaddr.sin_addr.s_addr)
    128       return 2;
    129 
    130     if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) ==
    131        -1) {
    132       close(sockfd);
    133       printf("client error: connect: %s\n", strerror(errno));
    134       return 1;
    135     }
    136 
    137     /* no progress meter please */
    138     curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
    139 
    140     /* send all data to this function  */
    141     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
    142 
    143     /* call this function to get a socket */
    144     curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
    145     curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
    146 
    147     /* call this function to close sockets */
    148     curl_easy_setopt(curl, CURLOPT_CLOSESOCKETFUNCTION, closecb);
    149     curl_easy_setopt(curl, CURLOPT_CLOSESOCKETDATA, &sockfd);
    150 
    151     /* call this function to set options for the socket */
    152     curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
    153 
    154     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
    155 
    156     res = curl_easy_perform(curl);
    157 
    158     curl_easy_cleanup(curl);
    159 
    160     if(res) {
    161       printf("libcurl error: %d\n", res);
    162       return 4;
    163     }
    164   }
    165   return 0;
    166 }
    167