diff options
author | Max Dymond <max.dymond@microsoft.com> | 2021-07-22 15:32:30 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-09-27 17:16:43 +0200 |
commit | a517378de58358a85b7cfe9efecb56051268f629 (patch) | |
tree | 8b8b43685911d3cbc6450b8d7255f5a10d2b8795 | |
parent | 06981ba7f620364eba253f5afcd7ebfaefcc8694 (diff) | |
download | curl-a517378de58358a85b7cfe9efecb56051268f629.tar.gz |
CURLOPT_PREREQFUNCTION: add new callback
Triggered before a request is made but after a connection is set up
Changes:
- callback: Update docs and callback for pre-request callback
- Add documentation for CURLOPT_PREREQDATA and CURLOPT_PREREQFUNCTION,
- Add redirect test and callback failure test
- Note that the function may be called multiple times on a redirection
- Disable new 2086 test due to Windows weirdness
Closes #7477
-rw-r--r-- | docs/libcurl/curl_easy_setopt.3 | 4 | ||||
-rw-r--r-- | docs/libcurl/opts/CURLOPT_PREREQDATA.3 | 61 | ||||
-rw-r--r-- | docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 | 104 | ||||
-rw-r--r-- | docs/libcurl/opts/Makefile.inc | 2 | ||||
-rw-r--r-- | docs/libcurl/symbols-in-versions | 4 | ||||
-rw-r--r-- | include/curl/curl.h | 21 | ||||
-rw-r--r-- | lib/easyoptions.c | 2 | ||||
-rw-r--r-- | lib/multi.c | 22 | ||||
-rw-r--r-- | lib/setopt.c | 6 | ||||
-rw-r--r-- | lib/urldata.h | 2 | ||||
-rw-r--r-- | tests/data/DISABLED | 2 | ||||
-rw-r--r-- | tests/data/Makefile.inc | 2 | ||||
-rw-r--r-- | tests/data/test2082 | 51 | ||||
-rw-r--r-- | tests/data/test2083 | 45 | ||||
-rw-r--r-- | tests/data/test2084 | 54 | ||||
-rw-r--r-- | tests/data/test2085 | 64 | ||||
-rw-r--r-- | tests/data/test2086 | 52 | ||||
-rw-r--r-- | tests/libtest/.gitignore | 1 | ||||
-rw-r--r-- | tests/libtest/Makefile.inc | 8 | ||||
-rw-r--r-- | tests/libtest/libprereq.c | 98 | ||||
-rwxr-xr-x | tests/libtest/mk-lib1521.pl | 1 |
21 files changed, 602 insertions, 4 deletions
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 index 592692b94..b1abf43e3 100644 --- a/docs/libcurl/curl_easy_setopt.3 +++ b/docs/libcurl/curl_easy_setopt.3 @@ -144,6 +144,10 @@ Suppress proxy CONNECT response headers from user callbacks. See \fICURLOPT_SUPP Callback to be called before a new resolve request is started. See \fICURLOPT_RESOLVER_START_FUNCTION(3)\fP .IP CURLOPT_RESOLVER_START_DATA Data pointer to pass to resolver start callback. See \fICURLOPT_RESOLVER_START_DATA(3)\fP +.IP CURLOPT_PREREQFUNCTION +Callback to be called after a connection is established but before a request is made on that connection. See \fICURLOPT_PREREQFUNCTION(3)\fP +.IP CURLOPT_PREREQDATA +Data pointer to pass to the CURLOPT_PREREQFUNCTION callback. See \fICURLOPT_PREREQDATA(3)\fP .SH ERROR OPTIONS .IP CURLOPT_ERRORBUFFER Error message buffer. See \fICURLOPT_ERRORBUFFER(3)\fP diff --git a/docs/libcurl/opts/CURLOPT_PREREQDATA.3 b/docs/libcurl/opts/CURLOPT_PREREQDATA.3 new file mode 100644 index 000000000..07497a83b --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_PREREQDATA.3 @@ -0,0 +1,61 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 2021, Max Dymond, <max.dymond@microsoft.com>, et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at https://curl.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_PREREQDATA 3 "2 Aug 2021" "libcurl 7.80.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_PREREQDATA \- custom pointer passed to the pre-request callback +.SH SYNOPSIS +#include <curl/curl.h> + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, void *pointer); +.SH DESCRIPTION +Pass a \fIpointer\fP that will be untouched by libcurl and passed as the first +argument in the pre-request callback set with +\fICURLOPT_PREREQFUNCTION(3)\fP. +.SH DEFAULT +NULL +.SH PROTOCOLS +All +.SH EXAMPLE +.nf +static int prereq_callback(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port) +{ + printf("Connection made to %s:%s\n", conn_primary_ip, conn_primary_port); + return CURL_PREREQFUNC_OK; +} + +{ + struct data prereq_data; + curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback); + curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, &prereq_data); +} +.fi +.SH AVAILABILITY +Added in 7.80.0 +.SH RETURN VALUE +Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not. +.SH "SEE ALSO" +.BR CURLOPT_PREREQFUNCTION "(3) " diff --git a/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 new file mode 100644 index 000000000..dcc782f9d --- /dev/null +++ b/docs/libcurl/opts/CURLOPT_PREREQFUNCTION.3 @@ -0,0 +1,104 @@ +.\" ************************************************************************** +.\" * _ _ ____ _ +.\" * Project ___| | | | _ \| | +.\" * / __| | | | |_) | | +.\" * | (__| |_| | _ <| |___ +.\" * \___|\___/|_| \_\_____| +.\" * +.\" * Copyright (C) 2021, Max Dymond, <max.dymond@microsoft.com>, et al. +.\" * +.\" * This software is licensed as described in the file COPYING, which +.\" * you should have received as part of this distribution. The terms +.\" * are also available at https://curl.se/docs/copyright.html. +.\" * +.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell +.\" * copies of the Software, and permit persons to whom the Software is +.\" * furnished to do so, under the terms of the COPYING file. +.\" * +.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +.\" * KIND, either express or implied. +.\" * +.\" ************************************************************************** +.\" +.TH CURLOPT_PREREQFUNCTION 3 "2 Aug 2021" "libcurl 7.80.0" "curl_easy_setopt options" +.SH NAME +CURLOPT_PREREQFUNCTION \- user callback called when a connection has been +established, but before a request has been made. +.SH SYNOPSIS +.nf +#include <curl/curl.h> + +/* These are the return codes for the pre-request callback. */ +#define CURL_PREREQFUNC_OK 0 +#define CURL_PREREQFUNC_ABORT 1 /* fail the entire transfer */ + +int prereq_callback(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port); + +CURLcode curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback); +.SH DESCRIPTION +Pass a pointer to your callback function, which should match the prototype +shown above. + +This function gets called by libcurl after a connection has been established +or a connection has been reused (including any SSL handshaking), but before any +request is actually made on the connection. For example, for HTTP, this +callback is called once a connection has been established to the server, but +before a GET/HEAD/POST/etc request has been sent. + +This function may be called multiple times if redirections are enabled and are +being followed (see \fICURLOPT_FOLLOWLOCATION(3)\fP). + +This function is passed the following information: +.IP conn_primary_ip +A nul-terminated pointer to a C string containing the primary IP of the remote +server established with this connection. For FTP, this is the IP for the control +connection. IPv6 addresses are represented without surrounding brackets. +.IP conn_local_ip +A nul-terminated pointer to a C string containing the originating IP for this +connection. IPv6 addresses are represented without surrounding brackets. +.IP conn_primary_port +The primary port number on the remote server established with this connection. +For FTP, this is the port for the control connection. This can be a TCP or a +UDP port number dependending on the protocol. +.IP conn_local_port +The originating port number for this connection. This can be a TCP or a UDP port +number dependending on the protocol. +.RE + +\fIclientp\fP is the pointer you set with \fICURLOPT_PREREQDATA(3)\fP. + +The callback function must return \fICURL_PREREQFUNC_OK\fP on success, or +\fICURL_PREREQFUNC_ABORT\fP to cause the transfer to fail. + +.SH DEFAULT +By default, this is NULL and unused. +.SH PROTOCOLS +ALL +.SH EXAMPLE +.nf +static int prereq_callback(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port) +{ + printf("Connection made to %s:%s\n", conn_primary_ip, conn_primary_port); + return CURL_PREREQFUNC_OK; +} + +{ + struct data prereq_data; + curl_easy_setopt(CURL *handle, CURLOPT_PREREQFUNCTION, prereq_callback); + curl_easy_setopt(CURL *handle, CURLOPT_PREREQDATA, &prereq_data); +} +.fi +.SH AVAILABILITY +Added in 7.80.0 +.SH RETURN VALUE +Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not. +.SH "SEE ALSO" +.BR CURLOPT_PREREQDATA "(3) " diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc index 4ef5ddf43..7bac21024 100644 --- a/docs/libcurl/opts/Makefile.inc +++ b/docs/libcurl/opts/Makefile.inc @@ -254,6 +254,8 @@ man_MANS = \ CURLOPT_POSTQUOTE.3 \ CURLOPT_POSTREDIR.3 \ CURLOPT_PREQUOTE.3 \ + CURLOPT_PREREQDATA.3 \ + CURLOPT_PREREQFUNCTION.3 \ CURLOPT_PRE_PROXY.3 \ CURLOPT_PRIVATE.3 \ CURLOPT_PROGRESSDATA.3 \ diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions index 8be22d504..1dbcdbd3e 100644 --- a/docs/libcurl/symbols-in-versions +++ b/docs/libcurl/symbols-in-versions @@ -531,6 +531,8 @@ CURLOPT_POSTFIELDSIZE_LARGE 7.11.1 CURLOPT_POSTQUOTE 7.1 CURLOPT_POSTREDIR 7.19.1 CURLOPT_PREQUOTE 7.9.5 +CURLOPT_PREREQDATA 7.80.0 +CURLOPT_PREREQFUNCTION 7.80.0 CURLOPT_PRE_PROXY 7.52.0 CURLOPT_PRIVATE 7.10.3 CURLOPT_PROGRESSDATA 7.1 @@ -964,6 +966,8 @@ CURL_POLL_INOUT 7.14.0 CURL_POLL_NONE 7.14.0 CURL_POLL_OUT 7.14.0 CURL_POLL_REMOVE 7.14.0 +CURL_PREREQFUNC_ABORT 7.79.0 +CURL_PREREQFUNC_OK 7.79.0 CURL_PROGRESSFUNC_CONTINUE 7.68.0 CURL_PROGRESS_BAR 7.1.1 - 7.4.1 CURL_PROGRESS_STATS 7.1.1 - 7.4.1 diff --git a/include/curl/curl.h b/include/curl/curl.h index 6eb0fcb82..d0862afaf 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -470,6 +470,20 @@ typedef int (*curl_debug_callback) size_t size, /* size of the data pointed to */ void *userptr); /* whatever the user please */ +/* This is the CURLOPT_PREREQFUNCTION callback prototype. */ +typedef int (*curl_prereq_callback)(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port); + +/* Return code for when the pre-request callback has terminated without + any errors */ +#define CURL_PREREQFUNC_OK 0 +/* Return code for when the pre-request callback wants to abort the + request */ +#define CURL_PREREQFUNC_ABORT 1 + /* All possible error codes from all sorts of curl functions. Future versions may return other values, stay prepared. @@ -2105,6 +2119,13 @@ typedef enum { /* used by scp/sftp to verify the host's public key */ CURLOPT(CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, CURLOPTTYPE_STRINGPOINT, 311), + /* Function that will be called immediately before the initial request + is made on a connection (after any protocol negotiation step). */ + CURLOPT(CURLOPT_PREREQFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 312), + + /* Data passed to the CURLOPT_PREREQFUNCTION callback */ + CURLOPT(CURLOPT_PREREQDATA, CURLOPTTYPE_CBPOINT, 313), + CURLOPT_LASTENTRY /* the last unused */ } CURLoption; diff --git a/lib/easyoptions.c b/lib/easyoptions.c index b1c0704d5..717b081a3 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -356,6 +356,6 @@ struct curl_easyoption Curl_easyopts[] = { */ int Curl_easyopts_check(void) { - return ((CURLOPT_LASTENTRY%10000) != (311 + 1)); + return ((CURLOPT_LASTENTRY%10000) != (313 + 1)); } #endif diff --git a/lib/multi.c b/lib/multi.c index 68c1a64d5..f31b25262 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -2028,6 +2028,28 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; case MSTATE_DO: + if(data->set.fprereq) { + int prereq_rc; + + /* call the prerequest callback function */ + Curl_set_in_callback(data, true); + prereq_rc = data->set.fprereq(data->set.prereq_userp, + data->info.conn_primary_ip, + data->info.conn_local_ip, + data->info.conn_primary_port, + data->info.conn_local_port); + Curl_set_in_callback(data, false); + if(prereq_rc != CURL_PREREQFUNC_OK) { + failf(data, "operation aborted by pre-request callback"); + /* failure in pre-request callback - don't do any other processing */ + result = CURLE_ABORTED_BY_CALLBACK; + Curl_posttransfer(data); + multi_done(data, result, FALSE); + stream_error = TRUE; + break; + } + } + if(data->set.connect_only) { /* keep connection open for application to use the socket */ connkeep(data->conn, "CONNECT_ONLY"); diff --git a/lib/setopt.c b/lib/setopt.c index c62a62fb5..8e19389ae 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -3013,6 +3013,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) return result; break; #endif + case CURLOPT_PREREQFUNCTION: + data->set.fprereq = va_arg(param, curl_prereq_callback); + break; + case CURLOPT_PREREQDATA: + data->set.prereq_userp = va_arg(param, void *); + break; default: /* unknown tag and its companion, just ignore: */ result = CURLE_UNKNOWN_OPTION; diff --git a/lib/urldata.h b/lib/urldata.h index 2d1e873a5..47cb9e282 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1652,6 +1652,8 @@ struct UserDefined { curl_closesocket_callback fclosesocket; /* function for closing the socket */ void *closesocket_client; + curl_prereq_callback fprereq; /* pre-initial request callback */ + void *prereq_userp; /* pre-initial request user data */ void *seek_client; /* pointer to pass to the seek callback */ /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ diff --git a/tests/data/DISABLED b/tests/data/DISABLED index 6807fe23d..aa0fee396 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -29,6 +29,8 @@ # test 1801 causes problems on Mac OS X and github # https://github.com/curl/curl/issues/380 1801 +# test 2086 causes issues on Windows only +2086 # # # Tests that are disabled here for Hyper are SUPPOSED to work but diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index d906ca338..41249fdad 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -229,7 +229,7 @@ test2064 test2065 test2066 test2067 test2068 test2069 \ test2064 test2065 test2066 test2067 test2068 test2069 test2070 \ test2071 test2072 test2073 test2074 test2075 test2076 test2077 \ test2078 \ -test2080 test2081 \ +test2080 test2081 test2082 test2083 test2084 test2085 test2086 \ \ test2100 \ \ diff --git a/tests/data/test2082 b/tests/data/test2082 new file mode 100644 index 000000000..4c37772d5 --- /dev/null +++ b/tests/data/test2082 @@ -0,0 +1,51 @@ +<testcase> +<info> +<keywords> +HTTP +</keywords> +</info> + +# Server-side +<reply> +<data nocheck="yes"> +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Type: text/html +Content-Length: 0 + +</data> +</reply> + +# Client-side +<client> +<server> +http +</server> + +<name> +Pre-request callback for HTTP +</name> +<tool> +libprereq +</tool> + +<command> +%HOSTIP:%HTTPPORT/%TESTNUMBER +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<stripfile> +s/^Local port = \d+/Local port = stripped/ +</stripfile> +<stdout> +Connected to %HOSTIP +Connected from %CLIENTIP +Remote port = %HTTPPORT +Local port = stripped +Returning = 0 +</stdout> +</verify> +</testcase> diff --git a/tests/data/test2083 b/tests/data/test2083 new file mode 100644 index 000000000..9256151a8 --- /dev/null +++ b/tests/data/test2083 @@ -0,0 +1,45 @@ +<testcase> +<info> +<keywords> +FTP +</keywords> +</info> + +# Server-side +<reply> +<data> +</data> +</reply> + +# Client-side +<client> +<server> +ftp +</server> + +<name> +Pre-request callback for FTP +</name> +<tool> +libprereq +</tool> + +<command> +ftp://%HOSTIP:%FTPPORT/test-%TESTNUMBER/ +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<stripfile> +s/^Local port = \d+/Local port = stripped/ +</stripfile> +<stdout> +Connected to %HOSTIP +Connected from %CLIENTIP +Remote port = %FTPPORT +Local port = stripped +Returning = 0 +</stdout> +</verify> +</testcase> diff --git a/tests/data/test2084 b/tests/data/test2084 new file mode 100644 index 000000000..ced7086c4 --- /dev/null +++ b/tests/data/test2084 @@ -0,0 +1,54 @@ +<testcase> +<info> +<keywords> +HTTP +</keywords> +</info> + +# Server-side +<reply> +<data nocheck="yes"> +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Type: text/html +Content-Length: 0 + +</data> +</reply> + +# Client-side +<client> +<server> +http +</server> + +<name> +Pre-request callback for HTTP with callback terminating transfer +</name> +<tool> +libprereq +</tool> + +<command> +%HOSTIP:%HTTPPORT/%TESTNUMBER#err +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<errorcode> +42 +</errorcode> +<stripfile> +s/^Local port = \d+/Local port = stripped/ +</stripfile> +<stdout> +Connected to %HOSTIP +Connected from %CLIENTIP +Remote port = %HTTPPORT +Local port = stripped +Returning = 1 +</stdout> +</verify> +</testcase> diff --git a/tests/data/test2085 b/tests/data/test2085 new file mode 100644 index 000000000..665a756c0 --- /dev/null +++ b/tests/data/test2085 @@ -0,0 +1,64 @@ +<testcase> +<info> +<keywords> +HTTP +followlocation +</keywords> +</info> + +# Server-side +<reply> +<data nocheck="yes"> +HTTP/1.1 302 OK swsclose +Location: data2.html/%TESTNUMBER0002 +Date: Tue, 09 Nov 2010 14:49:00 GMT +Connection: close + +</data> +<data2 nocheck="yes"> +HTTP/1.1 200 OK swsclose +Location: this should be ignored +Date: Tue, 09 Nov 2010 14:49:00 GMT +Connection: close + +body +</data2> +</reply> + +# Client-side +<client> +<server> +http +</server> + +<name> +Pre-request callback for HTTP with location following +</name> +<tool> +libprereq +</tool> + +<command> +%HOSTIP:%HTTPPORT/%TESTNUMBER#redir +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<stripfile> +s/^Local port = \d+/Local port = stripped/ +</stripfile> +<stdout> +Connected to %HOSTIP +Connected from %CLIENTIP +Remote port = %HTTPPORT +Local port = stripped +Returning = 0 +Connected to %HOSTIP +Connected from %CLIENTIP +Remote port = %HTTPPORT +Local port = stripped +Returning = 0 +</stdout> +</verify> +</testcase> diff --git a/tests/data/test2086 b/tests/data/test2086 new file mode 100644 index 000000000..ce60aa831 --- /dev/null +++ b/tests/data/test2086 @@ -0,0 +1,52 @@ +<testcase> +<info> +<keywords> +HTTP +IPv6 +</keywords> +</info> + +# Server-side +<reply> +<data nocheck="yes"> +HTTP/1.1 200 OK +Date: Tue, 09 Nov 2010 14:49:00 GMT +Server: test-server/fake +Content-Type: text/html +Content-Length: 0 + +</data> +</reply> + +# Client-side +<client> +<server> +http-ipv6 +</server> + +<name> +Pre-request callback for HTTP IPv6 +</name> +<tool> +libprereq +</tool> + +<command> +%HOST6IP:%HTTP6PORT/%TESTNUMBER#ipv6 +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<stripfile> +s/^Local port = \d+/Local port = stripped/ +</stripfile> +<stdout> +Connected to %HOST6IP +Connected from %CLIENT6IP +Remote port = %HTTP6PORT +Local port = stripped +Returning = 0 +</stdout> +</verify> +</testcase> diff --git a/tests/libtest/.gitignore b/tests/libtest/.gitignore index 62d9176d5..f27ba8128 100644 --- a/tests/libtest/.gitignore +++ b/tests/libtest/.gitignore @@ -5,3 +5,4 @@ lib[56][0-9][0-9] lib1521.c libauthretry libntlmconnect +libprereq diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index c2d0a6e8e..0f70ceb4b 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -36,7 +36,7 @@ SUPPORTFILES = first.c test.h # These are all libcurl test programs noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ - chkdecimalpoint \ + chkdecimalpoint libprereq \ lib500 lib501 lib502 lib503 lib504 lib505 lib506 lib507 lib508 lib509 \ lib510 lib511 lib512 lib513 lib514 lib515 lib516 lib517 lib518 lib519 \ lib520 lib521 lib523 lib524 lib525 lib526 lib527 lib529 lib532 \ @@ -81,6 +81,10 @@ libntlmconnect_CPPFLAGS = $(AM_CPPFLAGS) libauthretry_SOURCES = libauthretry.c $(SUPPORTFILES) libauthretry_CPPFLAGS = $(AM_CPPFLAGS) +libprereq_SOURCES = libprereq.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) +libprereq_LDADD = $(TESTUTIL_LIBS) +libprereq_CPPFLAGS = $(AM_CPPFLAGS) + lib500_SOURCES = lib500.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) $(MULTIBYTE) lib500_LDADD = $(TESTUTIL_LIBS) lib500_CPPFLAGS = $(AM_CPPFLAGS) @@ -494,7 +498,7 @@ lib1520_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1520 nodist_lib1521_SOURCES = lib1521.c $(SUPPORTFILES) lib1521_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir) -lib1522_SOURCES = lib1522.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) +lib1522_SOURCES = lib1522.c $(SUPPORTFILES) $(TESTUTIL) $(TSTTRACE) lib1522_LDADD = $(TESTUTIL_LIBS) lib1522_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/tests/libtest/libprereq.c b/tests/libtest/libprereq.c new file mode 100644 index 000000000..11eb18c06 --- /dev/null +++ b/tests/libtest/libprereq.c @@ -0,0 +1,98 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2021, Max Dymond, <max.dymond@microsoft.com> + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "test.h" + +typedef struct prcs { + int prereq_retcode; + int ipv6; +} PRCS; + +static int prereq_callback(void *clientp, + char *conn_primary_ip, + char *conn_local_ip, + int conn_primary_port, + int conn_local_port) +{ + PRCS *prereq_cb = (PRCS *)clientp; + + if(prereq_cb->ipv6) { + printf("Connected to [%s]\n", conn_primary_ip); + printf("Connected from [%s]\n", conn_local_ip); + } + else { + printf("Connected to %s\n", conn_primary_ip); + printf("Connected from %s\n", conn_local_ip); + } + + printf("Remote port = %d\n", conn_primary_port); + printf("Local port = %d\n", conn_local_port); + printf("Returning = %d\n", prereq_cb->prereq_retcode); + return prereq_cb->prereq_retcode; +} + +int test(char *URL) +{ + PRCS prereq_cb; + CURLcode ret = CURLE_OK; + CURL *curl = NULL; + + prereq_cb.prereq_retcode = CURL_PREREQFUNC_OK; + prereq_cb.ipv6 = 0; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if(curl) { + if(strstr(URL, "#ipv6")) { + /* The IP addresses should be surrounded by brackets! */ + prereq_cb.ipv6 = 1; + } + if(strstr(URL, "#err")) { + /* Set the callback to exit with failure */ + prereq_cb.prereq_retcode = CURL_PREREQFUNC_ABORT; + } + + curl_easy_setopt(curl, CURLOPT_URL, URL); + curl_easy_setopt(curl, CURLOPT_PREREQFUNCTION, prereq_callback); + curl_easy_setopt(curl, CURLOPT_PREREQDATA, &prereq_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, stderr); + + if(strstr(URL, "#redir")) { + /* Enable follow-location */ + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + } + + ret = curl_easy_perform(curl); + if(ret) { + fprintf(stderr, "%s:%d curl_easy_perform() failed with code %d (%s)\n", + __FILE__, __LINE__, ret, curl_easy_strerror(ret)); + goto test_cleanup; + } + } + +test_cleanup: + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return ret; +} + diff --git a/tests/libtest/mk-lib1521.pl b/tests/libtest/mk-lib1521.pl index 0a4ff3dcc..48b5bbbf2 100755 --- a/tests/libtest/mk-lib1521.pl +++ b/tests/libtest/mk-lib1521.pl @@ -136,6 +136,7 @@ static curl_xferinfo_callback xferinfocb; static curl_hstsread_callback hstsreadcb; static curl_hstswrite_callback hstswritecb; static curl_resolver_start_callback resolver_start_cb; +static curl_prereq_callback prereqcb; int test(char *URL) { |