1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, 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) funtions */ 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 curl_socket_t opensocket(void *clientp, 62 curlsocktype purpose, 63 struct curl_sockaddr *address) 64 { 65 curl_socket_t sockfd; 66 (void)purpose; 67 (void)address; 68 sockfd = *(curl_socket_t *)clientp; 69 /* the actual externally set socket is passed in via the OPENSOCKETDATA 70 option */ 71 return sockfd; 72 } 73 74 static int sockopt_callback(void *clientp, curl_socket_t curlfd, 75 curlsocktype purpose) 76 { 77 (void)clientp; 78 (void)curlfd; 79 (void)purpose; 80 /* This return code was added in libcurl 7.21.5 */ 81 return CURL_SOCKOPT_ALREADY_CONNECTED; 82 } 83 84 int main(void) 85 { 86 CURL *curl; 87 CURLcode res; 88 struct sockaddr_in servaddr; /* socket address structure */ 89 curl_socket_t sockfd; 90 91 #ifdef WIN32 92 WSADATA wsaData; 93 int initwsa; 94 95 if((initwsa = WSAStartup(MAKEWORD(2, 0), &wsaData)) != 0) { 96 printf("WSAStartup failed: %d\n", initwsa); 97 return 1; 98 } 99 #endif 100 101 curl = curl_easy_init(); 102 if(curl) { 103 /* 104 * Note that libcurl will internally think that you connect to the host 105 * and port that you specify in the URL option. 106 */ 107 curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999"); 108 109 /* Create the socket "manually" */ 110 if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == CURL_SOCKET_BAD) { 111 printf("Error creating listening socket.\n"); 112 return 3; 113 } 114 115 memset(&servaddr, 0, sizeof(servaddr)); 116 servaddr.sin_family = AF_INET; 117 servaddr.sin_port = htons(PORTNUM); 118 119 if(INADDR_NONE == (servaddr.sin_addr.s_addr = inet_addr(IPADDR))) 120 return 2; 121 122 if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == 123 -1) { 124 close(sockfd); 125 printf("client error: connect: %s\n", strerror(errno)); 126 return 1; 127 } 128 129 /* no progress meter please */ 130 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); 131 132 /* send all data to this function */ 133 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); 134 135 /* call this function to get a socket */ 136 curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket); 137 curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd); 138 139 /* call this function to set options for the socket */ 140 curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); 141 142 curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); 143 144 res = curl_easy_perform(curl); 145 146 curl_easy_cleanup(curl); 147 148 if(res) { 149 printf("libcurl error: %d\n", res); 150 return 4; 151 } 152 } 153 return 0; 154 } 155