You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ic...@apache.org on 2019/10/25 13:27:13 UTC
svn commit: r1868930 [2/5] - in /httpd/httpd/branches/2.4.x: ./ build/
docs/manual/mod/ modules/md/
Modified: httpd/httpd/branches/2.4.x/modules/md/md_crypt.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_crypt.c?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_crypt.c (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_crypt.c Fri Oct 25 13:27:12 2019
@@ -155,7 +155,7 @@ apr_status_t md_crypt_init(apr_pool_t *p
static apr_status_t fwrite_buffer(void *baton, apr_file_t *f, apr_pool_t *p)
{
- md_data *buf = baton;
+ md_data_t *buf = baton;
apr_size_t wlen;
(void)p;
@@ -253,6 +253,11 @@ static apr_time_t md_asn1_time_get(const
#endif
}
+apr_time_t md_asn1_generalized_time_get(void *ASN1_GENERALIZEDTIME)
+{
+ return md_asn1_time_get(ASN1_GENERALIZEDTIME);
+}
+
/**************************************************************************************************/
/* private keys */
@@ -384,7 +389,7 @@ apr_status_t md_pkey_fload(md_pkey_t **p
return rv;
}
-static apr_status_t pkey_to_buffer(md_data *buf, md_pkey_t *pkey, apr_pool_t *p,
+static apr_status_t pkey_to_buffer(md_data_t *buf, md_pkey_t *pkey, apr_pool_t *p,
const char *pass, apr_size_t pass_len)
{
BIO *bio = BIO_new(BIO_s_mem());
@@ -435,7 +440,7 @@ apr_status_t md_pkey_fsave(md_pkey_t *pk
const char *pass_phrase, apr_size_t pass_len,
const char *fname, apr_fileperms_t perms)
{
- md_data buffer;
+ md_data_t buffer;
apr_status_t rv;
if (APR_SUCCESS == (rv = pkey_to_buffer(&buffer, pkey, p, pass_phrase, pass_len))) {
@@ -507,12 +512,14 @@ static void RSA_get0_key(const RSA *r,
static const char *bn64(const BIGNUM *b, apr_pool_t *p)
{
if (b) {
- apr_size_t len = (apr_size_t)BN_num_bytes(b);
- char *buffer = apr_pcalloc(p, len);
- if (buffer) {
- BN_bn2bin(b, (unsigned char *)buffer);
- return md_util_base64url_encode(buffer, len, p);
- }
+ md_data_t buffer;
+
+ buffer.len = (apr_size_t)BN_num_bytes(b);
+ buffer.data = apr_pcalloc(p, buffer.len);
+ if (buffer.data) {
+ BN_bn2bin(b, (unsigned char *)buffer.data);
+ return md_util_base64url_encode(&buffer, p);
+ }
}
return NULL;
}
@@ -545,21 +552,23 @@ apr_status_t md_crypt_sign64(const char
const char *d, size_t dlen)
{
EVP_MD_CTX *ctx = NULL;
- char *buffer;
+ md_data_t buffer;
unsigned int blen;
const char *sign64 = NULL;
apr_status_t rv = APR_ENOMEM;
- buffer = apr_pcalloc(p, (apr_size_t)EVP_PKEY_size(pkey->pkey));
- if (buffer) {
+ buffer.len = (apr_size_t)EVP_PKEY_size(pkey->pkey);
+ buffer.data = apr_pcalloc(p, buffer.len);
+ if (buffer.data) {
ctx = EVP_MD_CTX_create();
if (ctx) {
rv = APR_ENOTIMPL;
if (EVP_SignInit_ex(ctx, EVP_sha256(), NULL)) {
rv = APR_EGENERAL;
if (EVP_SignUpdate(ctx, d, dlen)) {
- if (EVP_SignFinal(ctx, (unsigned char*)buffer, &blen, pkey->pkey)) {
- sign64 = md_util_base64url_encode(buffer, blen, p);
+ if (EVP_SignFinal(ctx, (unsigned char*)buffer.data, &blen, pkey->pkey)) {
+ buffer.len = blen;
+ sign64 = md_util_base64url_encode(&buffer, p);
if (sign64) {
rv = APR_SUCCESS;
}
@@ -581,10 +590,10 @@ apr_status_t md_crypt_sign64(const char
return rv;
}
-static apr_status_t sha256_digest(md_data **pdigest, apr_pool_t *p, const md_data *buf)
+static apr_status_t sha256_digest(md_data_t **pdigest, apr_pool_t *p, const md_data_t *buf)
{
EVP_MD_CTX *ctx = NULL;
- md_data *digest;
+ md_data_t *digest;
apr_status_t rv = APR_ENOMEM;
unsigned int dlen;
@@ -614,14 +623,14 @@ leave:
return rv;
}
-apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, const md_data *d)
+apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p, const md_data_t *d)
{
const char *digest64 = NULL;
- md_data *digest;
+ md_data_t *digest;
apr_status_t rv;
if (APR_SUCCESS == (rv = sha256_digest(&digest, p, d))) {
- if (NULL == (digest64 = md_util_base64url_encode(digest->data, digest->len, p))) {
+ if (NULL == (digest64 = md_util_base64url_encode(digest, p))) {
rv = APR_EGENERAL;
}
}
@@ -630,9 +639,9 @@ apr_status_t md_crypt_sha256_digest64(co
}
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p,
- const md_data *data)
+ const md_data_t *data)
{
- md_data *digest;
+ md_data_t *digest;
apr_status_t rv;
if (APR_SUCCESS == (rv = sha256_digest(&digest, p, data))) {
@@ -661,19 +670,19 @@ static apr_status_t cert_cleanup(void *d
return APR_SUCCESS;
}
-static md_cert_t *make_cert(apr_pool_t *p, X509 *x509)
+md_cert_t *md_cert_wrap(apr_pool_t *p, void *x509)
{
md_cert_t *cert = apr_pcalloc(p, sizeof(*cert));
cert->pool = p;
cert->x509 = x509;
- apr_pool_cleanup_register(p, cert, cert_cleanup, apr_pool_cleanup_null);
-
return cert;
}
-void md_cert_free(md_cert_t *cert)
+md_cert_t *md_cert_make(apr_pool_t *p, void *x509)
{
- cert_cleanup(cert);
+ md_cert_t *cert = md_cert_wrap(p, x509);
+ apr_pool_cleanup_register(p, cert, cert_cleanup, apr_pool_cleanup_null);
+ return cert;
}
void *md_cert_get_X509(const md_cert_t *cert)
@@ -684,16 +693,15 @@ void *md_cert_get_X509(const md_cert_t *
const char *md_cert_get_serial_number(const md_cert_t *cert, apr_pool_t *p)
{
const char *s = "";
+ BIGNUM *bn;
+ const char *serial;
const ASN1_INTEGER *ai = X509_get_serialNumber(cert->x509);
if (ai) {
- BIGNUM *bn;
- const char *hex;
-
bn = ASN1_INTEGER_to_BN(ai, NULL);
- hex = BN_bn2hex(bn);
- s = apr_pstrdup(p, hex);
+ serial = BN_bn2hex(bn);
+ s = apr_pstrdup(p, serial);
+ OPENSSL_free((void*)serial);
OPENSSL_free((void*)bn);
- OPENSSL_free((void*)hex);
}
return s;
}
@@ -831,7 +839,7 @@ apr_status_t md_cert_fload(md_cert_t **p
x509 = PEM_read_X509(f, NULL, NULL, NULL);
rv = fclose(f);
if (x509 != NULL) {
- cert = make_cert(p, x509);
+ cert = md_cert_make(p, x509);
}
else {
rv = APR_EINVAL;
@@ -842,7 +850,7 @@ apr_status_t md_cert_fload(md_cert_t **p
return rv;
}
-static apr_status_t cert_to_buffer(md_data *buffer, const md_cert_t *cert, apr_pool_t *p)
+static apr_status_t cert_to_buffer(md_data_t *buffer, const md_cert_t *cert, apr_pool_t *p)
{
BIO *bio = BIO_new(BIO_s_mem());
int i;
@@ -871,7 +879,7 @@ static apr_status_t cert_to_buffer(md_da
apr_status_t md_cert_fsave(md_cert_t *cert, apr_pool_t *p,
const char *fname, apr_fileperms_t perms)
{
- md_data buffer;
+ md_data_t buffer;
apr_status_t rv;
if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
@@ -882,20 +890,20 @@ apr_status_t md_cert_fsave(md_cert_t *ce
apr_status_t md_cert_to_base64url(const char **ps64, const md_cert_t *cert, apr_pool_t *p)
{
- md_data buffer;
+ md_data_t buffer;
apr_status_t rv;
if (APR_SUCCESS == (rv = cert_to_buffer(&buffer, cert, p))) {
- *ps64 = md_util_base64url_encode(buffer.data, buffer.len, p);
+ *ps64 = md_util_base64url_encode(&buffer, p);
return APR_SUCCESS;
}
*ps64 = NULL;
return rv;
}
-apr_status_t md_cert_to_sha256_digest(md_data **pdigest, const md_cert_t *cert, apr_pool_t *p)
+apr_status_t md_cert_to_sha256_digest(md_data_t **pdigest, const md_cert_t *cert, apr_pool_t *p)
{
- md_data *digest;
+ md_data_t *digest;
unsigned int dlen;
apr_status_t rv = APR_ENOMEM;
@@ -914,7 +922,7 @@ leave:
apr_status_t md_cert_to_sha256_fingerprint(const char **pfinger, const md_cert_t *cert, apr_pool_t *p)
{
- md_data *digest;
+ md_data_t *digest;
apr_status_t rv;
rv = md_cert_to_sha256_digest(&digest, cert, p);
@@ -937,7 +945,7 @@ static int md_cert_read_pem(BIO *bf, apr
rv = APR_ENOENT;
goto out;
}
- cert = make_cert(p, x509);
+ cert = md_cert_make(p, x509);
rv = APR_SUCCESS;
out:
@@ -974,7 +982,7 @@ apr_status_t md_cert_read_http(md_cert_t
goto out;
}
else {
- cert = make_cert(p, x509);
+ cert = md_cert_make(p, x509);
rv = APR_SUCCESS;
md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p, "cert parsed");
}
@@ -1065,7 +1073,7 @@ apr_status_t md_chain_fappend(struct apr
if (rv == APR_SUCCESS) {
ERR_clear_error();
while (NULL != (x509 = PEM_read_X509(f, NULL, NULL, NULL))) {
- cert = make_cert(p, x509);
+ cert = md_cert_make(p, x509);
APR_ARRAY_PUSH(certs, md_cert_t *) = cert;
}
fclose(f);
@@ -1248,12 +1256,13 @@ apr_status_t md_cert_req_create(const ch
apr_array_header_t *domains, int must_staple,
md_pkey_t *pkey, apr_pool_t *p)
{
- const char *s, *csr_der, *csr_der_64 = NULL;
+ const char *s, *csr_der_64 = NULL;
const unsigned char *domain;
X509_REQ *csr;
X509_NAME *n = NULL;
STACK_OF(X509_EXTENSION) *exts = NULL;
apr_status_t rv;
+ md_data_t csr_der;
int csr_der_len;
assert(domains->nelts > 0);
@@ -1305,12 +1314,13 @@ apr_status_t md_cert_req_create(const ch
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: der length", name);
rv = APR_EGENERAL; goto out;
}
- s = csr_der = apr_pcalloc(p, (apr_size_t)csr_der_len + 1);
+ csr_der.len = (apr_size_t)csr_der_len;
+ s = csr_der.data = apr_pcalloc(p, csr_der.len + 1);
if (i2d_X509_REQ(csr, (unsigned char**)&s) != csr_der_len) {
md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, p, "%s: csr der enc", name);
rv = APR_EGENERAL; goto out;
}
- csr_der_64 = md_util_base64url_encode(csr_der, (apr_size_t)csr_der_len, p);
+ csr_der_64 = md_util_base64url_encode(&csr_der, p);
rv = APR_SUCCESS;
out:
@@ -1418,7 +1428,7 @@ apr_status_t md_cert_self_sign(md_cert_t
rv = APR_EGENERAL; goto out;
}
- cert = make_cert(p, x);
+ cert = md_cert_make(p, x);
rv = APR_SUCCESS;
out:
@@ -1470,7 +1480,7 @@ apr_status_t md_cert_make_tls_alpn_01(md
rv = APR_EGENERAL; goto out;
}
- cert = make_cert(p, x);
+ cert = md_cert_make(p, x);
rv = APR_SUCCESS;
out:
Modified: httpd/httpd/branches/2.4.x/modules/md/md_crypt.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_crypt.h?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_crypt.h (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_crypt.h Fri Oct 25 13:27:12 2019
@@ -24,7 +24,7 @@ struct md_t;
struct md_http_response_t;
struct md_cert_t;
struct md_pkey_t;
-struct md_data;
+struct md_data_t;
/**************************************************************************************************/
@@ -32,12 +32,14 @@ struct md_data;
apr_status_t md_rand_bytes(unsigned char *buf, apr_size_t len, apr_pool_t *p);
+apr_time_t md_asn1_generalized_time_get(void *ASN1_GENERALIZEDTIME);
+
/**************************************************************************************************/
/* digests */
apr_status_t md_crypt_sha256_digest64(const char **pdigest64, apr_pool_t *p,
- const struct md_data *data);
+ const struct md_data_t *data);
apr_status_t md_crypt_sha256_digest_hex(const char **pdigesthex, apr_pool_t *p,
- const struct md_data *data);
+ const struct md_data_t *data);
#define MD_DATA_SET_STR(d, s) do { (d)->data = (s); (d)->len = strlen(s); } while(0)
@@ -97,7 +99,18 @@ typedef enum {
MD_CERT_EXPIRED
} md_cert_state_t;
-void md_cert_free(md_cert_t *cert);
+/**
+ * Create a holder of the certificate that will free its memmory when the
+ * pool is destroyed.
+ */
+md_cert_t *md_cert_make(apr_pool_t *p, void *x509);
+
+/**
+ * Wrap a x509 certificate into our own structure, without taking ownership
+ * of its memory. The caller remains responsible.
+ */
+md_cert_t *md_cert_wrap(apr_pool_t *p, void *x509);
+
void *md_cert_get_X509(const md_cert_t *cert);
apr_status_t md_cert_fload(md_cert_t **pcert, apr_pool_t *p, const char *fname);
@@ -136,7 +149,7 @@ apr_status_t md_cert_get_alt_names(apr_a
apr_status_t md_cert_to_base64url(const char **ps64, const md_cert_t *cert, apr_pool_t *p);
apr_status_t md_cert_from_base64url(md_cert_t **pcert, const char *s64, apr_pool_t *p);
-apr_status_t md_cert_to_sha256_digest(struct md_data **pdigest, const md_cert_t *cert, apr_pool_t *p);
+apr_status_t md_cert_to_sha256_digest(struct md_data_t **pdigest, const md_cert_t *cert, apr_pool_t *p);
apr_status_t md_cert_to_sha256_fingerprint(const char **pfinger, const md_cert_t *cert, apr_pool_t *p);
const char *md_cert_get_serial_number(const md_cert_t *cert, apr_pool_t *p);
@@ -181,9 +194,9 @@ typedef struct md_sct md_sct;
struct md_sct {
int version;
apr_time_t timestamp;
- struct md_data *logid;
+ struct md_data_t *logid;
int signature_type_nid;
- struct md_data *signature;
+ struct md_data_t *signature;
};
#endif /* md_crypt_h */
Modified: httpd/httpd/branches/2.4.x/modules/md/md_curl.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_curl.c?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_curl.c (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_curl.c Fri Oct 25 13:27:12 2019
@@ -24,13 +24,14 @@
#include "md_http.h"
#include "md_log.h"
+#include "md_util.h"
#include "md_curl.h"
/**************************************************************************************************/
/* md_http curl implementation */
-static apr_status_t curl_status(int curl_code)
+static apr_status_t curl_status(unsigned int curl_code)
{
switch (curl_code) {
case CURLE_OK: return APR_SUCCESS;
@@ -49,6 +50,15 @@ static apr_status_t curl_status(int curl
}
}
+typedef struct {
+ CURL *curl;
+ CURLM *curlm;
+ struct curl_slist *req_hdrs;
+ md_http_response_t *response;
+ apr_status_t rv;
+ int status_fired;
+} md_curl_internals_t;
+
static size_t req_data_cb(void *data, size_t len, size_t nmemb, void *baton)
{
apr_bucket_brigade *body = baton;
@@ -92,7 +102,8 @@ static size_t req_data_cb(void *data, si
static size_t resp_data_cb(void *data, size_t len, size_t nmemb, void *baton)
{
- md_http_response_t *res = baton;
+ md_curl_internals_t *internals = baton;
+ md_http_response_t *res = internals->response;
size_t blen = len * nmemb;
apr_status_t rv;
@@ -100,7 +111,7 @@ static size_t resp_data_cb(void *data, s
if (res->req->resp_limit) {
apr_off_t body_len = 0;
apr_brigade_length(res->body, 0, &body_len);
- if (body_len + (apr_off_t)len > res->req->resp_limit) {
+ if (body_len + (apr_off_t)blen > res->req->resp_limit) {
return 0; /* signal curl failure */
}
}
@@ -115,7 +126,8 @@ static size_t resp_data_cb(void *data, s
static size_t header_cb(void *buffer, size_t elen, size_t nmemb, void *baton)
{
- md_http_response_t *res = baton;
+ md_curl_internals_t *internals = baton;
+ md_http_response_t *res = internals->response;
size_t len, clen = elen * nmemb;
const char *name = NULL, *value = "", *b = buffer;
apr_size_t i;
@@ -142,24 +154,6 @@ static size_t header_cb(void *buffer, si
return clen;
}
-static apr_status_t curl_init(md_http_request_t *req)
-{
- CURL *curl = curl_easy_init();
- if (!curl) {
- return APR_EGENERAL;
- }
-
- curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
- curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
-
- req->internals = curl;
- return APR_SUCCESS;
-}
-
typedef struct {
md_http_request_t *req;
struct curl_slist *hdrs;
@@ -181,24 +175,96 @@ static int curlify_headers(void *baton,
return 1;
}
-static apr_status_t curl_perform(md_http_request_t *req)
+/* Convert timeout values for curl. Since curl uses 0 to disable
+ * timeout, return at least 1 if the apr_time_t value is non-zero. */
+static long timeout_msec(apr_time_t timeout)
{
- apr_status_t rv = APR_SUCCESS;
- CURLcode curle;
- md_http_response_t *res;
- CURL *curl;
- struct curl_slist *req_hdrs = NULL;
+ long ms = (long)apr_time_as_msec(timeout);
+ return ms? ms : (timeout? 1 : 0);
+}
- rv = curl_init(req);
- curl = req->internals;
+static long timeout_sec(apr_time_t timeout)
+{
+ long s = (long)apr_time_sec(timeout);
+ return s? s : (timeout? 1 : 0);
+}
+
+static int curl_debug_log(CURL *curl, curl_infotype type, char *data, size_t size, void *baton)
+{
+ md_http_request_t *req = baton;
- res = apr_pcalloc(req->pool, sizeof(*res));
+ (void)curl;
+ switch (type) {
+ case CURLINFO_TEXT:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, req->pool,
+ "req[%d]: info %s", req->id, apr_pstrndup(req->pool, data, size));
+ break;
+ case CURLINFO_HEADER_OUT:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, req->pool,
+ "req[%d]: header --> %s", req->id, apr_pstrndup(req->pool, data, size));
+ break;
+ case CURLINFO_HEADER_IN:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, req->pool,
+ "req[%d]: header <-- %s", req->id, apr_pstrndup(req->pool, data, size));
+ break;
+ case CURLINFO_DATA_OUT:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, req->pool,
+ "req[%d]: data --> %ld bytes", req->id, (long)size);
+ if (md_log_is_level(req->pool, MD_LOG_TRACE5)) {
+ md_data_t d;
+ const char *s;
+ d.data = data;
+ d.len = size;
+ md_data_to_hex(&s, 0, req->pool, &d);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE5, 0, req->pool,
+ "req[%d]: data(hex) --> %s", req->id, s);
+ }
+ break;
+ case CURLINFO_DATA_IN:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE4, 0, req->pool,
+ "req[%d]: data <-- %ld bytes", req->id, (long)size);
+ if (md_log_is_level(req->pool, MD_LOG_TRACE5)) {
+ md_data_t d;
+ const char *s;
+ d.data = data;
+ d.len = size;
+ md_data_to_hex(&s, 0, req->pool, &d);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE5, 0, req->pool,
+ "req[%d]: data(hex) <-- %s", req->id, s);
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static apr_status_t internals_setup(md_http_request_t *req)
+{
+ md_curl_internals_t *internals;
+ CURL *curl;
+ apr_status_t rv = APR_SUCCESS;
- res->req = req;
- res->rv = APR_SUCCESS;
- res->status = 400;
- res->headers = apr_table_make(req->pool, 5);
- res->body = apr_brigade_create(req->pool, req->bucket_alloc);
+ curl = curl_easy_init();
+ if (!curl) {
+ rv = APR_EGENERAL;
+ goto leave;
+ }
+ internals = apr_pcalloc(req->pool, sizeof(*internals));
+ internals->curl = curl;
+
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_cb);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_READFUNCTION, req_data_cb);
+ curl_easy_setopt(curl, CURLOPT_READDATA, NULL);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, resp_data_cb);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, NULL);
+
+ internals->response = apr_pcalloc(req->pool, sizeof(md_http_response_t));
+ internals->response->req = req;
+ internals->response->status = 400;
+ internals->response->headers = apr_table_make(req->pool, 5);
+ internals->response->body = apr_brigade_create(req->pool, req->bucket_alloc);
curl_easy_setopt(curl, CURLOPT_URL, req->url);
if (!apr_strnatcasecmp("GET", req->method)) {
@@ -213,9 +279,20 @@ static apr_status_t curl_perform(md_http
else {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, req->method);
}
- curl_easy_setopt(curl, CURLOPT_HEADERDATA, res);
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, internals);
curl_easy_setopt(curl, CURLOPT_READDATA, req->body);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, res);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, internals);
+
+ if (req->timeout.overall > 0) {
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, timeout_msec(req->timeout.overall));
+ }
+ if (req->timeout.connect > 0) {
+ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, timeout_msec(req->timeout.connect));
+ }
+ if (req->timeout.stalled > 0) {
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, req->timeout.stall_bytes_per_sec);
+ curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, timeout_sec(req->timeout.stalled));
+ }
if (req->user_agent) {
curl_easy_setopt(curl, CURLOPT_USERAGENT, req->user_agent);
@@ -230,47 +307,244 @@ static apr_status_t curl_perform(md_http
ctx.hdrs = NULL;
ctx.rv = APR_SUCCESS;
apr_table_do(curlify_headers, &ctx, req->headers, NULL);
- req_hdrs = ctx.hdrs;
+ internals->req_hdrs = ctx.hdrs;
if (ctx.rv == APR_SUCCESS) {
- curl_easy_setopt(curl, CURLOPT_HTTPHEADER, req_hdrs);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, internals->req_hdrs);
}
}
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, 0, req->pool,
- "request --> %s %s", req->method, req->url);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, req->pool,
+ "req[%d]: %s %s", req->id, req->method, req->url);
- if (md_log_is_level(req->pool, MD_LOG_TRACE3)) {
+ if (md_log_is_level(req->pool, MD_LOG_TRACE4)) {
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curl_debug_log);
+ curl_easy_setopt(curl, CURLOPT_DEBUGDATA, req);
}
- curle = curl_easy_perform(curl);
- res->rv = curl_status(curle);
+leave:
+ req->internals = (APR_SUCCESS == rv)? internals : NULL;
+ return rv;
+}
+
+static apr_status_t update_status(md_http_request_t *req)
+{
+ md_curl_internals_t *internals = req->internals;
+ long l;
+ apr_status_t rv = APR_SUCCESS;
+
+ if (internals) {
+ rv = curl_status(curl_easy_getinfo(internals->curl, CURLINFO_RESPONSE_CODE, &l));
+ if (APR_SUCCESS == rv) {
+ internals->response->status = (int)l;
+ }
+ }
+ return rv;
+}
+
+static void fire_status(md_http_request_t *req, apr_status_t rv)
+{
+ md_curl_internals_t *internals = req->internals;
+
+ if (internals && !internals->status_fired) {
+ internals->status_fired = 1;
+
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, req->pool,
+ "req[%d] fire callbacks", req->id);
+ if ((APR_SUCCESS == rv) && req->cb.on_response) {
+ rv = req->cb.on_response(internals->response, req->cb.on_response_data);
+ }
- if (APR_SUCCESS == res->rv) {
- long l;
- res->rv = curl_status(curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &l));
- if (APR_SUCCESS == res->rv) {
- res->status = (int)l;
+ internals->rv = rv;
+ if (req->cb.on_status) {
+ req->cb.on_status(req, rv, req->cb.on_status_data);
}
- md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, res->rv, req->pool,
- "request <-- %d", res->status);
}
- else {
- md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, res->rv, req->pool,
- "request failed(%d): %s", curle,
- curl_easy_strerror(curle));
+}
+
+static apr_status_t md_curl_perform(md_http_request_t *req)
+{
+ apr_status_t rv = APR_SUCCESS;
+ CURLcode curle;
+ md_curl_internals_t *internals;
+ long l;
+
+ if (APR_SUCCESS != (rv = internals_setup(req))) goto leave;
+ internals = req->internals;
+
+ curle = curl_easy_perform(internals->curl);
+
+ rv = curl_status(curle);
+ if (APR_SUCCESS != rv) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, req->pool,
+ "request failed(%d): %s", curle, curl_easy_strerror(curle));
+ goto leave;
}
- if (req->cb) {
- res->rv = req->cb(res);
+ rv = curl_status(curl_easy_getinfo(internals->curl, CURLINFO_RESPONSE_CODE, &l));
+ if (APR_SUCCESS == rv) {
+ internals->response->status = (int)l;
}
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE1, rv, req->pool, "request <-- %d",
+ internals->response->status);
- rv = res->rv;
+ if (req->cb.on_response) {
+ rv = req->cb.on_response(internals->response, req->cb.on_response_data);
+ req->cb.on_response = NULL;
+ }
+
+leave:
+ fire_status(req, rv);
md_http_req_destroy(req);
- if (req_hdrs) {
- curl_slist_free_all(req_hdrs);
+ return rv;
+}
+
+static md_http_request_t *find_curl_request(apr_array_header_t *requests, CURL *curl)
+{
+ md_http_request_t *req;
+ md_curl_internals_t *internals;
+ int i;
+
+ for (i = 0; i < requests->nelts; ++i) {
+ req = APR_ARRAY_IDX(requests, i, md_http_request_t*);
+ internals = req->internals;
+ if (internals && internals->curl == curl) {
+ return req;
+ }
+ }
+ return NULL;
+}
+
+static void add_to_curlm(md_http_request_t *req, CURLM *curlm)
+{
+ md_curl_internals_t *internals = req->internals;
+
+ if (curlm && internals && internals->curlm == NULL) {
+ curl_multi_add_handle(curlm, internals->curl);
+ internals->curlm = curlm;
+ }
+}
+
+static void remove_from_curlm(md_http_request_t *req, CURLM *curlm)
+{
+ md_curl_internals_t *internals = req->internals;
+
+ if (curlm && internals && internals->curlm == curlm) {
+ curl_multi_remove_handle(curlm, internals->curl);
+ internals->curlm = NULL;
+ }
+}
+
+static apr_status_t md_curl_multi_perform(md_http_t *http, apr_pool_t *p,
+ md_http_next_req *nextreq, void *baton)
+{
+ md_http_request_t *req;
+ CURLM *curlm = NULL;
+ CURLMcode mc;
+ struct CURLMsg *curlmsg;
+ apr_array_header_t *requests;
+ int i, running, numfds, slowdown, msgcount;
+ apr_status_t rv;
+
+ requests = apr_array_make(p, 10, sizeof(md_http_request_t*));
+ curlm = curl_multi_init();
+ if (!curlm) {
+ rv = APR_ENOMEM;
+ goto leave;
}
+ running = 1;
+ slowdown = 0;
+ while(1) {
+ while (1) {
+ /* fetch as many requests as nextreq gives us */
+ rv = nextreq(&req, baton, http, requests->nelts);
+
+ if (APR_SUCCESS == rv) {
+ if (APR_SUCCESS != (rv = internals_setup(req))) {
+ if (req->cb.on_status) req->cb.on_status(req, rv, req->cb.on_status_data);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: setup failed", requests->nelts);
+ }
+ else {
+ APR_ARRAY_PUSH(requests, md_http_request_t*) = req;
+ add_to_curlm(req, curlm);
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: added request", requests->nelts);
+ }
+ continue;
+ }
+ else if (APR_STATUS_IS_ENOENT(rv)) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p,
+ "multi_perform[%d reqs]: no more requests", requests->nelts);
+ if (!running) {
+ goto leave;
+ }
+ break;
+ }
+ else {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: nextreq() failed", requests->nelts);
+ goto leave;
+ }
+ }
+
+ mc = curl_multi_perform(curlm, &running);
+ if (CURLM_OK == mc) {
+ mc = curl_multi_wait(curlm, NULL, 0, 1000, &numfds);
+ if (numfds) slowdown = 0;
+ }
+ if (CURLM_OK != mc) {
+ rv = APR_ECONNABORTED;
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, rv, p,
+ "multi_perform[%d reqs] failed(%d): %s",
+ requests->nelts, mc, curl_multi_strerror(mc));
+ goto leave;
+ }
+ if (!numfds) {
+ /* no activity on any connection, timeout */
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p,
+ "multi_perform[%d reqs]: slowdown %d", requests->nelts, slowdown);
+ if (slowdown) apr_sleep(apr_time_from_msec(100));
+ ++slowdown;
+ }
+
+ /* process status messages, e.g. that a request is done */
+ while (1) {
+ curlmsg = curl_multi_info_read(curlm, &msgcount);
+ if (!curlmsg) break;
+ if (curlmsg->msg == CURLMSG_DONE) {
+ req = find_curl_request(requests, curlmsg->easy_handle);
+ if (req) {
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, 0, p,
+ "multi_perform[%d reqs]: req[%d] done",
+ requests->nelts, req->id);
+ update_status(req);
+ fire_status(req, curl_status(curlmsg->data.result));
+ remove_from_curlm(req, curlm);
+ md_array_remove(requests, req);
+ md_http_req_destroy(req);
+ }
+ else {
+ md_log_perror(MD_LOG_MARK, MD_LOG_DEBUG, 0, p,
+ "multi_perform[%d reqs]: req done, but not found by handle",
+ requests->nelts);
+ }
+ }
+ }
+ assert(running == requests->nelts);
+ };
+
+leave:
+ md_log_perror(MD_LOG_MARK, MD_LOG_TRACE3, rv, p,
+ "multi_perform[%d reqs]: leaving", requests->nelts);
+ for (i = 0; i < requests->nelts; ++i) {
+ req = APR_ARRAY_IDX(requests, i, md_http_request_t*);
+ fire_status(req, APR_SUCCESS);
+ remove_from_curlm(req, curlm);
+ md_http_req_destroy(req);
+ }
+ if (curlm) curl_multi_cleanup(curlm);
return rv;
}
@@ -284,18 +558,21 @@ static apr_status_t md_curl_init(void) {
return APR_SUCCESS;
}
-static void curl_req_cleanup(md_http_request_t *req)
+static void md_curl_req_cleanup(md_http_request_t *req)
{
- if (req->internals) {
- curl_easy_cleanup(req->internals);
+ md_curl_internals_t *internals = req->internals;
+ if (internals) {
+ if (internals->curl) curl_easy_cleanup(internals->curl);
+ if (internals->req_hdrs) curl_slist_free_all(internals->req_hdrs);
req->internals = NULL;
}
}
static md_http_impl_t impl = {
md_curl_init,
- curl_req_cleanup,
- curl_perform
+ md_curl_req_cleanup,
+ md_curl_perform,
+ md_curl_multi_perform,
};
md_http_impl_t * md_curl_get_impl(apr_pool_t *p)
Modified: httpd/httpd/branches/2.4.x/modules/md/md_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_http.c?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_http.c (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_http.c Fri Oct 25 13:27:12 2019
@@ -22,14 +22,17 @@
#include "md_http.h"
#include "md_log.h"
+#include "md_util.h"
struct md_http_t {
apr_pool_t *pool;
apr_bucket_alloc_t *bucket_alloc;
+ int next_id;
apr_off_t resp_limit;
md_http_impl_t *impl;
const char *user_agent;
const char *proxy_url;
+ md_http_timeouts_t timeout;
};
static md_http_impl_t *cur_impl;
@@ -81,9 +84,82 @@ void md_http_set_response_limit(md_http_
http->resp_limit = resp_limit;
}
+void md_http_set_timeout_default(md_http_t *http, apr_time_t timeout)
+{
+ http->timeout.overall = timeout;
+}
+
+void md_http_set_timeout(md_http_request_t *req, apr_time_t timeout)
+{
+ req->timeout.overall = timeout;
+}
+
+void md_http_set_connect_timeout_default(md_http_t *http, apr_time_t timeout)
+{
+ http->timeout.connect = timeout;
+}
+
+void md_http_set_connect_timeout(md_http_request_t *req, apr_time_t timeout)
+{
+ req->timeout.connect = timeout;
+}
+
+void md_http_set_stalling_default(md_http_t *http, long bytes_per_sec, apr_time_t timeout)
+{
+ http->timeout.stall_bytes_per_sec = bytes_per_sec;
+ http->timeout.stalled = timeout;
+}
+
+void md_http_set_stalling(md_http_request_t *req, long bytes_per_sec, apr_time_t timeout)
+{
+ req->timeout.stall_bytes_per_sec = bytes_per_sec;
+ req->timeout.stalled = timeout;
+}
+
+static apr_status_t req_set_body(md_http_request_t *req, const char *content_type,
+ apr_bucket_brigade *body, apr_off_t body_len,
+ int detect_len)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ if (body && detect_len) {
+ rv = apr_brigade_length(body, 1, &body_len);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ req->body = body;
+ req->body_len = body? body_len : 0;
+ if (content_type) {
+ apr_table_set(req->headers, "Content-Type", content_type);
+ }
+ else {
+ apr_table_unset(req->headers, "Content-Type");
+ }
+ return rv;
+}
+
+static apr_status_t req_set_body_data(md_http_request_t *req, const char *content_type,
+ const md_data_t *body)
+{
+ apr_bucket_brigade *bbody = NULL;
+ apr_status_t rv;
+
+ if (body && body->len > 0) {
+ bbody = apr_brigade_create(req->pool, req->http->bucket_alloc);
+ rv = apr_brigade_write(bbody, NULL, NULL, body->data, body->len);
+ if (rv != APR_SUCCESS) {
+ md_http_req_destroy(req);
+ return rv;
+ }
+ }
+ return req_set_body(req, content_type, bbody, body? (apr_off_t)body->len : 0, 0);
+}
+
static apr_status_t req_create(md_http_request_t **preq, md_http_t *http,
- const char *method, const char *url, struct apr_table_t *headers,
- md_http_cb *cb, void *baton)
+ const char *method, const char *url,
+ struct apr_table_t *headers)
{
md_http_request_t *req;
apr_pool_t *pool;
@@ -96,17 +172,16 @@ static apr_status_t req_create(md_http_r
req = apr_pcalloc(pool, sizeof(*req));
req->pool = pool;
+ req->id = http->next_id++;
req->bucket_alloc = http->bucket_alloc;
req->http = http;
req->method = method;
req->url = url;
req->headers = headers? apr_table_copy(req->pool, headers) : apr_table_make(req->pool, 5);
req->resp_limit = http->resp_limit;
- req->cb = cb;
- req->baton = baton;
req->user_agent = http->user_agent;
req->proxy_url = http->proxy_url;
-
+ req->timeout = http->timeout;
*preq = req;
return rv;
}
@@ -120,107 +195,157 @@ void md_http_req_destroy(md_http_request
apr_pool_destroy(req->pool);
}
-static apr_status_t schedule(md_http_request_t *req,
- apr_bucket_brigade *body, int detect_clen)
+void md_http_set_on_status_cb(md_http_request_t *req, md_http_status_cb *cb, void *baton)
{
- apr_status_t rv;
-
- req->body = body;
- req->body_len = body? -1 : 0;
+ req->cb.on_status = cb;
+ req->cb.on_status_data = baton;
+}
- if (req->body && detect_clen) {
- rv = apr_brigade_length(req->body, 1, &req->body_len);
- if (rv != APR_SUCCESS) {
- md_http_req_destroy(req);
- return rv;
- }
- }
-
+void md_http_set_on_response_cb(md_http_request_t *req, md_http_response_cb *cb, void *baton)
+{
+ req->cb.on_response = cb;
+ req->cb.on_response_data = baton;
+}
+
+static void req_init_cl(md_http_request_t *req)
+{
if (req->body_len == 0 && apr_strnatcasecmp("GET", req->method)) {
apr_table_setn(req->headers, "Content-Length", "0");
}
else if (req->body_len > 0) {
apr_table_setn(req->headers, "Content-Length", apr_off_t_toa(req->pool, req->body_len));
}
-
+}
+
+apr_status_t md_http_perform(md_http_request_t *req)
+{
+ req_init_cl(req);
return req->http->impl->perform(req);
}
-apr_status_t md_http_GET(struct md_http_t *http,
- const char *url, struct apr_table_t *headers,
- md_http_cb *cb, void *baton)
+typedef struct {
+ md_http_next_req *nextreq;
+ void *baton;
+} nextreq_proxy_t;
+
+static apr_status_t proxy_nextreq(md_http_request_t **preq, void *baton,
+ md_http_t *http, int in_flight)
{
- md_http_request_t *req;
+ nextreq_proxy_t *proxy = baton;
apr_status_t rv;
- rv = req_create(&req, http, "GET", url, headers, cb, baton);
- if (rv != APR_SUCCESS) {
- return rv;
- }
+ rv = proxy->nextreq(preq, proxy->baton, http, in_flight);
+ if (APR_SUCCESS == rv) req_init_cl(*preq);
+ return rv;
+}
+
+apr_status_t md_http_multi_perform(md_http_t *http, md_http_next_req *nextreq, void *baton)
+{
+ nextreq_proxy_t proxy;
- return schedule(req, NULL, 0);
+ proxy.nextreq = nextreq;
+ proxy.baton = baton;
+ return http->impl->multi_perform(http, http->pool, proxy_nextreq, &proxy);
}
-apr_status_t md_http_HEAD(struct md_http_t *http,
- const char *url, struct apr_table_t *headers,
- md_http_cb *cb, void *baton)
+apr_status_t md_http_GET_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers)
{
md_http_request_t *req;
apr_status_t rv;
- rv = req_create(&req, http, "HEAD", url, headers, cb, baton);
- if (rv != APR_SUCCESS) {
- return rv;
- }
-
- return schedule(req, NULL, 0);
+ rv = req_create(&req, http, "GET", url, headers);
+ *preq = (APR_SUCCESS == rv)? req : NULL;
+ return rv;
}
-apr_status_t md_http_POST(struct md_http_t *http, const char *url,
- struct apr_table_t *headers, const char *content_type,
- apr_bucket_brigade *body,
- md_http_cb *cb, void *baton)
+apr_status_t md_http_HEAD_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers)
{
md_http_request_t *req;
apr_status_t rv;
- rv = req_create(&req, http, "POST", url, headers, cb, baton);
- if (rv != APR_SUCCESS) {
- return rv;
- }
-
- if (content_type) {
- apr_table_set(req->headers, "Content-Type", content_type);
- }
- return schedule(req, body, 1);
+ rv = req_create(&req, http, "HEAD", url, headers);
+ *preq = (APR_SUCCESS == rv)? req : NULL;
+ return rv;
}
-apr_status_t md_http_POSTd(md_http_t *http, const char *url,
- struct apr_table_t *headers, const char *content_type,
- const char *data, size_t data_len,
- md_http_cb *cb, void *baton)
+apr_status_t md_http_POST_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ struct apr_bucket_brigade *body, int detect_len)
{
md_http_request_t *req;
apr_status_t rv;
- apr_bucket_brigade *body = NULL;
- rv = req_create(&req, http, "POST", url, headers, cb, baton);
- if (rv != APR_SUCCESS) {
- return rv;
+ rv = req_create(&req, http, "POST", url, headers);
+ if (APR_SUCCESS == rv) {
+ rv = req_set_body(req, content_type, body, -1, detect_len);
}
+ *preq = (APR_SUCCESS == rv)? req : NULL;
+ return rv;
+}
- if (data && data_len > 0) {
- body = apr_brigade_create(req->pool, req->http->bucket_alloc);
- rv = apr_brigade_write(body, NULL, NULL, data, data_len);
- if (rv != APR_SUCCESS) {
- md_http_req_destroy(req);
- return rv;
- }
- }
+apr_status_t md_http_POSTd_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ const struct md_data_t *body)
+{
+ md_http_request_t *req;
+ apr_status_t rv;
- if (content_type) {
- apr_table_set(req->headers, "Content-Type", content_type);
+ rv = req_create(&req, http, "POST", url, headers);
+ if (APR_SUCCESS == rv) {
+ rv = req_set_body_data(req, content_type, body);
}
-
- return schedule(req, body, 1);
+ *preq = (APR_SUCCESS == rv)? req : NULL;
+ return rv;
+}
+
+apr_status_t md_http_GET_perform(struct md_http_t *http,
+ const char *url, struct apr_table_t *headers,
+ md_http_response_cb *cb, void *baton)
+{
+ md_http_request_t *req;
+ apr_status_t rv;
+
+ rv = md_http_GET_create(&req, http, url, headers);
+ if (APR_SUCCESS == rv) md_http_set_on_response_cb(req, cb, baton);
+ return (APR_SUCCESS == rv)? md_http_perform(req) : rv;
+}
+
+apr_status_t md_http_HEAD_perform(struct md_http_t *http,
+ const char *url, struct apr_table_t *headers,
+ md_http_response_cb *cb, void *baton)
+{
+ md_http_request_t *req;
+ apr_status_t rv;
+
+ rv = md_http_HEAD_create(&req, http, url, headers);
+ if (APR_SUCCESS == rv) md_http_set_on_response_cb(req, cb, baton);
+ return (APR_SUCCESS == rv)? md_http_perform(req) : rv;
+}
+
+apr_status_t md_http_POST_perform(struct md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ apr_bucket_brigade *body, int detect_len,
+ md_http_response_cb *cb, void *baton)
+{
+ md_http_request_t *req;
+ apr_status_t rv;
+
+ rv = md_http_POST_create(&req, http, url, headers, content_type, body, detect_len);
+ if (APR_SUCCESS == rv) md_http_set_on_response_cb(req, cb, baton);
+ return (APR_SUCCESS == rv)? md_http_perform(req) : rv;
+}
+
+apr_status_t md_http_POSTd_perform(md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ const md_data_t *body,
+ md_http_response_cb *cb, void *baton)
+{
+ md_http_request_t *req;
+ apr_status_t rv;
+
+ rv = md_http_POSTd_create(&req, http, url, headers, content_type, body);
+ if (APR_SUCCESS == rv) md_http_set_on_response_cb(req, cb, baton);
+ return (APR_SUCCESS == rv)? md_http_perform(req) : rv;
}
Modified: httpd/httpd/branches/2.4.x/modules/md/md_http.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_http.h?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_http.h (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_http.h Fri Oct 25 13:27:12 2019
@@ -20,17 +20,45 @@
struct apr_table_t;
struct apr_bucket_brigade;
struct apr_bucket_alloc_t;
+struct md_data_t;
typedef struct md_http_t md_http_t;
typedef struct md_http_request_t md_http_request_t;
typedef struct md_http_response_t md_http_response_t;
-typedef apr_status_t md_http_cb(const md_http_response_t *res);
+/**
+ * Callback invoked once per request, either when an error was encountered
+ * or when everything succeeded and the request is about to be released. Only
+ * in the last case will the status be APR_SUCCESS.
+ */
+typedef apr_status_t md_http_status_cb(const md_http_request_t *req, apr_status_t status, void *data);
+
+/**
+ * Callback invoked when the complete response has been received.
+ */
+typedef apr_status_t md_http_response_cb(const md_http_response_t *res, void *data);
+
+typedef struct md_http_callbacks_t md_http_callbacks_t;
+struct md_http_callbacks_t {
+ md_http_status_cb *on_status;
+ void *on_status_data;
+ md_http_response_cb *on_response;
+ void *on_response_data;
+};
+
+typedef struct md_http_timeouts_t md_http_timeouts_t;
+struct md_http_timeouts_t {
+ apr_time_t overall;
+ apr_time_t connect;
+ long stall_bytes_per_sec;
+ apr_time_t stalled;
+};
struct md_http_request_t {
md_http_t *http;
apr_pool_t *pool;
+ int id;
struct apr_bucket_alloc_t *bucket_alloc;
const char *method;
const char *url;
@@ -40,14 +68,13 @@ struct md_http_request_t {
struct apr_bucket_brigade *body;
apr_off_t body_len;
apr_off_t resp_limit;
- md_http_cb *cb;
- void *baton;
+ md_http_timeouts_t timeout;
+ md_http_callbacks_t cb;
void *internals;
};
struct md_http_response_t {
md_http_request_t *req;
- apr_status_t rv;
int status;
apr_table_t *headers;
struct apr_bucket_brigade *body;
@@ -58,38 +85,154 @@ apr_status_t md_http_create(md_http_t **
void md_http_set_response_limit(md_http_t *http, apr_off_t resp_limit);
-apr_status_t md_http_GET(md_http_t *http,
- const char *url, struct apr_table_t *headers,
- md_http_cb *cb, void *baton);
-
-apr_status_t md_http_HEAD(md_http_t *http,
- const char *url, struct apr_table_t *headers,
- md_http_cb *cb, void *baton);
-
-apr_status_t md_http_POST(md_http_t *http, const char *url,
- struct apr_table_t *headers, const char *content_type,
- struct apr_bucket_brigade *body,
- md_http_cb *cb, void *baton);
-
-apr_status_t md_http_POSTd(md_http_t *http, const char *url,
- struct apr_table_t *headers, const char *content_type,
- const char *data, size_t data_len,
- md_http_cb *cb, void *baton);
+/**
+ * Set the timeout for the complete reqest. This needs to take everything from
+ * DNS looksups, to conntects, to transfer of all data into account and should
+ * be sufficiently large.
+ * Set to 0 the have no timeout for this.
+ */
+void md_http_set_timeout_default(md_http_t *http, apr_time_t timeout);
+void md_http_set_timeout(md_http_request_t *req, apr_time_t timeout);
+
+/**
+ * Set the timeout for establishing a connection.
+ * Set to 0 the have no special timeout for this.
+ */
+void md_http_set_connect_timeout_default(md_http_t *http, apr_time_t timeout);
+void md_http_set_connect_timeout(md_http_request_t *req, apr_time_t timeout);
+
+/**
+ * Set the condition for when a transfer is considered "stalled", e.g. does not
+ * progress at a sufficient rate and will be aborted.
+ * Set to 0 the have no stall detection in place.
+ */
+void md_http_set_stalling_default(md_http_t *http, long bytes_per_sec, apr_time_t timeout);
+void md_http_set_stalling(md_http_request_t *req, long bytes_per_sec, apr_time_t timeout);
+
+/**
+ * Perform the request. Then this function returns, the request and
+ * all its memory has been freed and must no longer be used.
+ */
+apr_status_t md_http_perform(md_http_request_t *request);
+
+/**
+ * Set the callback to be invoked once the status of a request is known.
+ * @param req the request
+ * @param cb the callback to invoke on the response
+ * @param baton data passed to the callback
+ */
+void md_http_set_on_status_cb(md_http_request_t *req, md_http_status_cb *cb, void *baton);
+
+/**
+ * Set the callback to be invoked when the complete
+ * response has been successfully received. The HTTP status may
+ * be 500, however.
+ * @param req the request
+ * @param cb the callback to invoke on the response
+ * @param baton data passed to the callback
+ */
+void md_http_set_on_response_cb(md_http_request_t *req, md_http_response_cb *cb, void *baton);
+
+/**
+ * Create a GET reqest.
+ * @param preq the created request after success
+ * @param http the md_http instance
+ * @param url the url to GET
+ * @param headers request headers
+ */
+apr_status_t md_http_GET_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers);
+
+/**
+ * Create a HEAD reqest.
+ * @param preq the created request after success
+ * @param http the md_http instance
+ * @param url the url to GET
+ * @param headers request headers
+ */
+apr_status_t md_http_HEAD_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers);
+
+/**
+ * Create a POST reqest with a bucket brigade as request body.
+ * @param preq the created request after success
+ * @param http the md_http instance
+ * @param url the url to GET
+ * @param headers request headers
+ * @param content_type the content_type of the body or NULL
+ * @param body the body of the request or NULL
+ * @param detect_len scan the body to detect its length
+ */
+apr_status_t md_http_POST_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ struct apr_bucket_brigade *body, int detect_len);
+
+/**
+ * Create a POST reqest with known request body data.
+ * @param preq the created request after success
+ * @param http the md_http instance
+ * @param url the url to GET
+ * @param headers request headers
+ * @param content_type the content_type of the body or NULL
+ * @param body the body of the request or NULL
+ */
+apr_status_t md_http_POSTd_create(md_http_request_t **preq, md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ const struct md_data_t *body);
+
+/*
+ * Convenience functions for create+perform.
+ */
+apr_status_t md_http_GET_perform(md_http_t *http, const char *url,
+ struct apr_table_t *headers,
+ md_http_response_cb *cb, void *baton);
+apr_status_t md_http_HEAD_perform(md_http_t *http, const char *url,
+ struct apr_table_t *headers,
+ md_http_response_cb *cb, void *baton);
+apr_status_t md_http_POST_perform(md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ struct apr_bucket_brigade *body, int detect_len,
+ md_http_response_cb *cb, void *baton);
+apr_status_t md_http_POSTd_perform(md_http_t *http, const char *url,
+ struct apr_table_t *headers, const char *content_type,
+ const struct md_data_t *body,
+ md_http_response_cb *cb, void *baton);
void md_http_req_destroy(md_http_request_t *req);
+/** Return the next request for processing on APR_SUCCESS. Return ARP_ENOENT
+ * when no request is available. Anything else is an error.
+ */
+typedef apr_status_t md_http_next_req(md_http_request_t **preq, void *baton,
+ md_http_t *http, int in_flight);
+
+/**
+ * Perform requests in parallel as retrieved from the nextreq function.
+ * There are as many requests in flight as the nextreq functions provides.
+ *
+ * To limit the number of parallel requests, nextreq should return APR_ENOENT when the limit
+ * is reached. It will be called again when the number of in_flight requests changes.
+ *
+ * When all reqests are done, nextreq will be called one more time. Should it not
+ * return anything, this function returns.
+ */
+apr_status_t md_http_multi_perform(md_http_t *http, md_http_next_req *nextreq, void *baton);
+
/**************************************************************************************************/
/* interface to implementation */
typedef apr_status_t md_http_init_cb(void);
typedef void md_http_req_cleanup_cb(md_http_request_t *req);
typedef apr_status_t md_http_perform_cb(md_http_request_t *req);
+typedef apr_status_t md_http_multi_perform_cb(md_http_t *http, apr_pool_t *p,
+ md_http_next_req *nextreq, void *baton);
typedef struct md_http_impl_t md_http_impl_t;
struct md_http_impl_t {
md_http_init_cb *init;
md_http_req_cleanup_cb *req_cleanup;
md_http_perform_cb *perform;
+ md_http_multi_perform_cb *multi_perform;
};
void md_http_use_implementation(md_http_impl_t *impl);
Modified: httpd/httpd/branches/2.4.x/modules/md/md_json.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_json.c?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_json.c (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_json.c Fri Oct 25 13:27:12 2019
@@ -18,10 +18,12 @@
#include <apr_lib.h>
#include <apr_strings.h>
#include <apr_buckets.h>
+#include <apr_date.h>
#include "md_json.h"
#include "md_log.h"
#include "md_http.h"
+#include "md_time.h"
#include "md_util.h"
/* jansson thinks everyone compiles with the platform's cc in its fullest capabilities
@@ -106,12 +108,12 @@ void md_json_destroy(md_json_t *json)
}
}
-md_json_t *md_json_copy(apr_pool_t *pool, md_json_t *json)
+md_json_t *md_json_copy(apr_pool_t *pool, const md_json_t *json)
{
return json_create(pool, json_copy(json->j));
}
-md_json_t *md_json_clone(apr_pool_t *pool, md_json_t *json)
+md_json_t *md_json_clone(apr_pool_t *pool, const md_json_t *json)
{
return json_create(pool, json_deep_copy(json->j));
}
@@ -168,18 +170,16 @@ static apr_status_t jselect_add(json_t *
j = jselect_parent(&key, 1, json, ap);
if (!j || !json_is_object(j)) {
- json_decref(val);
return APR_EINVAL;
}
aj = json_object_get(j, key);
if (!aj) {
aj = json_array();
- json_object_set_new(j, key, aj);
+ json_object_set(j, key, aj);
}
if (!json_is_array(aj)) {
- json_decref(val);
return APR_EINVAL;
}
@@ -202,7 +202,7 @@ static apr_status_t jselect_insert(json_
aj = json_object_get(j, key);
if (!aj) {
aj = json_array();
- json_object_set_new(j, key, aj);
+ json_object_set(j, key, aj);
}
if (!json_is_array(aj)) {
@@ -227,13 +227,11 @@ static apr_status_t jselect_set(json_t *
j = jselect_parent(&key, 1, json, ap);
if (!j) {
- json_decref(val);
return APR_EINVAL;
}
if (key) {
if (!json_is_object(j)) {
- json_decref(val);
return APR_EINVAL;
}
json_object_set(j, key, val);
@@ -313,6 +311,19 @@ int md_json_is(const md_json_type_t jtyp
return 0;
}
+static const char *md_json_type_name(const md_json_t *json)
+{
+ json_t *j = json->j;
+ if (json_is_object(j)) return "object";
+ if (json_is_array(j)) return "array";
+ if (json_is_string(j)) return "string";
+ if (json_is_real(j)) return "real";
+ if (json_is_integer(j)) return "integer";
+ if (json_is_true(j)) return "true";
+ if (json_is_false(j)) return "false";
+ return "unknown";
+}
+
/**************************************************************************************************/
/* booleans */
@@ -428,6 +439,35 @@ apr_status_t md_json_sets(const char *va
}
/**************************************************************************************************/
+/* time */
+
+apr_time_t md_json_get_time(const md_json_t *json, ...)
+{
+ json_t *j;
+ va_list ap;
+
+ va_start(ap, json);
+ j = jselect(json, ap);
+ va_end(ap);
+
+ if (!j || !json_is_string(j)) return 0;
+ return apr_date_parse_rfc(json_string_value(j));
+}
+
+apr_status_t md_json_set_time(apr_time_t value, md_json_t *json, ...)
+{
+ char ts[APR_RFC822_DATE_LEN];
+ va_list ap;
+ apr_status_t rv;
+
+ apr_rfc822_date(ts, value);
+ va_start(ap, json);
+ rv = jselect_set_new(json_string(ts), json, ap);
+ va_end(ap);
+ return rv;
+}
+
+/**************************************************************************************************/
/* json itself */
md_json_t *md_json_getj(md_json_t *json, ...)
@@ -449,6 +489,22 @@ md_json_t *md_json_getj(md_json_t *json,
return NULL;
}
+md_json_t *md_json_dupj(apr_pool_t *p, const md_json_t *json, ...)
+{
+ json_t *j;
+ va_list ap;
+
+ va_start(ap, json);
+ j = jselect(json, ap);
+ va_end(ap);
+
+ if (j) {
+ json_incref(j);
+ return json_create(p, j);
+ }
+ return NULL;
+}
+
const md_json_t *md_json_getcj(const md_json_t *json, ...)
{
json_t *j;
@@ -468,7 +524,7 @@ const md_json_t *md_json_getcj(const md_
return NULL;
}
-apr_status_t md_json_setj(md_json_t *value, md_json_t *json, ...)
+apr_status_t md_json_setj(const md_json_t *value, md_json_t *json, ...)
{
va_list ap;
apr_status_t rv;
@@ -496,7 +552,7 @@ apr_status_t md_json_setj(md_json_t *val
return rv;
}
-apr_status_t md_json_addj(md_json_t *value, md_json_t *json, ...)
+apr_status_t md_json_addj(const md_json_t *value, md_json_t *json, ...)
{
va_list ap;
apr_status_t rv;
@@ -518,6 +574,25 @@ apr_status_t md_json_insertj(md_json_t *
return rv;
}
+apr_size_t md_json_limita(size_t max_elements, md_json_t *json, ...)
+{
+ json_t *j;
+ va_list ap;
+ apr_size_t n = 0;
+
+ va_start(ap, json);
+ j = jselect(json, ap);
+ va_end(ap);
+
+ if (j && json_is_array(j)) {
+ n = json_array_size(j);
+ while (n > max_elements) {
+ json_array_remove(j, n-1);
+ n = json_array_size(j);
+ }
+ }
+ return n;
+}
/**************************************************************************************************/
/* arrays / objects */
@@ -642,7 +717,7 @@ apr_status_t md_json_clone_to(void *valu
return md_json_setj(md_json_clone(p, value), json, NULL);
}
-apr_status_t md_json_clone_from(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton)
+apr_status_t md_json_clone_from(void **pvalue, const md_json_t *json, apr_pool_t *p, void *baton)
{
(void)baton;
*pvalue = md_json_clone(p, json);
@@ -843,7 +918,7 @@ apr_status_t md_json_setsa(apr_array_hea
/* formatting, parsing */
typedef struct {
- md_json_t *json;
+ const md_json_t *json;
md_json_fmt_t fmt;
const char *fname;
apr_file_t *f;
@@ -868,7 +943,7 @@ static int dump_cb(const char *buffer, s
return (rv == APR_SUCCESS)? 0 : -1;
}
-apr_status_t md_json_writeb(md_json_t *json, md_json_fmt_t fmt, apr_bucket_brigade *bb)
+apr_status_t md_json_writeb(const md_json_t *json, md_json_fmt_t fmt, apr_bucket_brigade *bb)
{
int rv = json_dump_callback(json->j, dump_cb, bb, fmt_to_flags(fmt));
return rv? APR_EGENERAL : APR_SUCCESS;
@@ -877,14 +952,18 @@ apr_status_t md_json_writeb(md_json_t *j
static int chunk_cb(const char *buffer, size_t len, void *baton)
{
apr_array_header_t *chunks = baton;
- char *chunk = apr_pcalloc(chunks->pool, len+1);
+ char *chunk;
- memcpy(chunk, buffer, len);
- APR_ARRAY_PUSH(chunks, const char *) = chunk;
+ if (len > 0) {
+ chunk = apr_palloc(chunks->pool, len+1);
+ memcpy(chunk, buffer, len);
+ chunk[len] = '\0';
+ APR_ARRAY_PUSH(chunks, const char*) = chunk;
+ }
return 0;
}
-const char *md_json_writep(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt)
+const char *md_json_writep(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt)
{
apr_array_header_t *chunks;
int rv;
@@ -901,13 +980,13 @@ const char *md_json_writep(md_json_t *js
case 0:
return "";
case 1:
- return APR_ARRAY_IDX(chunks, 0, const char *);
+ return APR_ARRAY_IDX(chunks, 0, const char*);
default:
return apr_array_pstrcat(p, chunks, 0);
}
}
-apr_status_t md_json_writef(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt, apr_file_t *f)
+apr_status_t md_json_writef(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt, apr_file_t *f)
{
apr_status_t rv;
const char *s;
@@ -920,12 +999,13 @@ apr_status_t md_json_writef(md_json_t *j
}
else {
rv = APR_EINVAL;
- md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, json->p, "md_json_writef: error dumping json");
+ md_log_perror(MD_LOG_MARK, MD_LOG_ERR, rv, json->p,
+ "md_json_writef: error dumping json (%s)", md_json_dump_state(json, p));
}
return rv;
}
-apr_status_t md_json_fcreatex(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
+apr_status_t md_json_fcreatex(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
const char *fpath, apr_fileperms_t perms)
{
apr_status_t rv;
@@ -949,7 +1029,7 @@ static apr_status_t write_json(void *bat
return rv;
}
-apr_status_t md_json_freplace(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
+apr_status_t md_json_freplace(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
const char *fpath, apr_fileperms_t perms)
{
j_write_ctx ctx;
@@ -1076,11 +1156,9 @@ apr_status_t md_json_readf(md_json_t **p
apr_status_t md_json_read_http(md_json_t **pjson, apr_pool_t *pool, const md_http_response_t *res)
{
apr_status_t rv = APR_ENOENT;
- if (res->rv == APR_SUCCESS) {
- const char *ctype = apr_table_get(res->headers, "content-type");
- if (ctype && res->body && (strstr(ctype, "/json") || strstr(ctype, "+json"))) {
- rv = md_json_readb(pjson, pool, res->body);
- }
+ const char *ctype = apr_table_get(res->headers, "content-type");
+ if (ctype && res->body && (strstr(ctype, "/json") || strstr(ctype, "+json"))) {
+ rv = md_json_readb(pjson, pool, res->body);
}
return rv;
}
@@ -1091,9 +1169,9 @@ typedef struct {
md_json_t *json;
} resp_data;
-static apr_status_t json_resp_cb(const md_http_response_t *res)
+static apr_status_t json_resp_cb(const md_http_response_t *res, void *data)
{
- resp_data *resp = res->req->baton;
+ resp_data *resp = data;
return md_json_read_http(&resp->json, resp->pool, res);
}
@@ -1106,7 +1184,7 @@ apr_status_t md_json_http_get(md_json_t
memset(&resp, 0, sizeof(resp));
resp.pool = pool;
- rv = md_http_GET(http, url, NULL, json_resp_cb, &resp);
+ rv = md_http_GET_perform(http, url, NULL, json_resp_cb, &resp);
if (rv == APR_SUCCESS) {
*pjson = resp.json;
@@ -1134,3 +1212,63 @@ apr_status_t md_json_copy_to(md_json_t *
}
return rv;
}
+
+const char *md_json_dump_state(const md_json_t *json, apr_pool_t *p)
+{
+ if (!json) return "NULL";
+ return apr_psprintf(p, "%s, refc=%ld", md_json_type_name(json), (long)json->j->refcount);
+}
+
+apr_status_t md_json_set_timeperiod(const md_timeperiod_t *tp, md_json_t *json, ...)
+{
+ char ts[APR_RFC822_DATE_LEN];
+ json_t *jn, *j;
+ va_list ap;
+ const char *key;
+ apr_status_t rv;
+
+ if (!tp || tp->start || tp->end) {
+ jn = json_object();
+ apr_rfc822_date(ts, tp->start);
+ json_object_set_new(jn, "from", json_string(ts));
+ apr_rfc822_date(ts, tp->end);
+ json_object_set_new(jn, "until", json_string(ts));
+
+ va_start(ap, json);
+ rv = jselect_set_new(jn, json, ap);
+ va_end(ap);
+ return rv;
+ }
+ else {
+ va_start(ap, json);
+ j = jselect_parent(&key, 0, json, ap);
+ va_end(ap);
+
+ if (key && j && json_is_object(j)) {
+ json_object_del(j, key);
+ }
+ return APR_SUCCESS;
+ }
+}
+
+apr_status_t md_json_get_timeperiod(md_timeperiod_t *tp, md_json_t *json, ...)
+{
+ json_t *j, *jts;
+ va_list ap;
+
+ va_start(ap, json);
+ j = jselect(json, ap);
+ va_end(ap);
+
+ memset(tp, 0, sizeof(*tp));
+ if (!j) goto not_found;
+ jts = json_object_get(j, "from");
+ if (!jts || !json_is_string(jts)) goto not_found;
+ tp->start = apr_date_parse_rfc(json_string_value(jts));
+ jts = json_object_get(j, "until");
+ if (!jts || !json_is_string(jts)) goto not_found;
+ tp->end = apr_date_parse_rfc(json_string_value(jts));
+ return APR_SUCCESS;
+not_found:
+ return APR_ENOENT;
+}
Modified: httpd/httpd/branches/2.4.x/modules/md/md_json.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_json.h?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_json.h (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_json.h Fri Oct 25 13:27:12 2019
@@ -24,7 +24,7 @@ struct apr_file_t;
struct md_http_t;
struct md_http_response_t;
-
+struct md_timeperiod_t;
typedef struct md_json_t md_json_t;
@@ -47,8 +47,8 @@ typedef enum {
md_json_t *md_json_create(apr_pool_t *pool);
void md_json_destroy(md_json_t *json);
-md_json_t *md_json_copy(apr_pool_t *pool, md_json_t *json);
-md_json_t *md_json_clone(apr_pool_t *pool, md_json_t *json);
+md_json_t *md_json_copy(apr_pool_t *pool, const md_json_t *json);
+md_json_t *md_json_clone(apr_pool_t *pool, const md_json_t *json);
int md_json_has_key(const md_json_t *json, ...);
@@ -72,17 +72,25 @@ const char *md_json_gets(const md_json_t
const char *md_json_dups(apr_pool_t *p, const md_json_t *json, ...);
apr_status_t md_json_sets(const char *s, md_json_t *json, ...);
+/* timestamp manipulation */
+apr_time_t md_json_get_time(const md_json_t *json, ...);
+apr_status_t md_json_set_time(apr_time_t value, md_json_t *json, ...);
+
/* json manipulation */
md_json_t *md_json_getj(md_json_t *json, ...);
+md_json_t *md_json_dupj(apr_pool_t *p, const md_json_t *json, ...);
const md_json_t *md_json_getcj(const md_json_t *json, ...);
-apr_status_t md_json_setj(md_json_t *value, md_json_t *json, ...);
-apr_status_t md_json_addj(md_json_t *value, md_json_t *json, ...);
+apr_status_t md_json_setj(const md_json_t *value, md_json_t *json, ...);
+apr_status_t md_json_addj(const md_json_t *value, md_json_t *json, ...);
apr_status_t md_json_insertj(md_json_t *value, size_t index, md_json_t *json, ...);
/* Array/Object manipulation */
apr_status_t md_json_clr(md_json_t *json, ...);
apr_status_t md_json_del(md_json_t *json, ...);
+/* Remove all array elements beyond max_elements */
+apr_size_t md_json_limita(size_t max_elements, md_json_t *json, ...);
+
/* conversion function from and to json */
typedef apr_status_t md_json_to_cb(void *value, md_json_t *json, apr_pool_t *p, void *baton);
typedef apr_status_t md_json_from_cb(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton);
@@ -93,7 +101,7 @@ apr_status_t md_json_pass_from(void **pv
/* conversions from json to json in specified pool */
apr_status_t md_json_clone_to(void *value, md_json_t *json, apr_pool_t *p, void *baton);
-apr_status_t md_json_clone_from(void **pvalue, md_json_t *json, apr_pool_t *p, void *baton);
+apr_status_t md_json_clone_from(void **pvalue, const md_json_t *json, apr_pool_t *p, void *baton);
/* Manipulating/Iteration on generic Arrays */
apr_status_t md_json_geta(apr_array_header_t *a, md_json_from_cb *cb,
@@ -115,13 +123,13 @@ apr_status_t md_json_dupsa(apr_array_hea
apr_status_t md_json_setsa(apr_array_header_t *a, md_json_t *json, ...);
/* serialization & parsing */
-apr_status_t md_json_writeb(md_json_t *json, md_json_fmt_t fmt, struct apr_bucket_brigade *bb);
-const char *md_json_writep(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt);
-apr_status_t md_json_writef(md_json_t *json, apr_pool_t *p,
+apr_status_t md_json_writeb(const md_json_t *json, md_json_fmt_t fmt, struct apr_bucket_brigade *bb);
+const char *md_json_writep(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt);
+apr_status_t md_json_writef(const md_json_t *json, apr_pool_t *p,
md_json_fmt_t fmt, struct apr_file_t *f);
-apr_status_t md_json_fcreatex(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
+apr_status_t md_json_fcreatex(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
const char *fpath, apr_fileperms_t perms);
-apr_status_t md_json_freplace(md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
+apr_status_t md_json_freplace(const md_json_t *json, apr_pool_t *p, md_json_fmt_t fmt,
const char *fpath, apr_fileperms_t perms);
apr_status_t md_json_readb(md_json_t **pjson, apr_pool_t *pool, struct apr_bucket_brigade *bb);
@@ -137,4 +145,9 @@ apr_status_t md_json_read_http(md_json_t
apr_status_t md_json_copy_to(md_json_t *dest, const md_json_t *src, ...);
+const char *md_json_dump_state(const md_json_t *json, apr_pool_t *p);
+
+apr_status_t md_json_set_timeperiod(const struct md_timeperiod_t *tp, md_json_t *json, ...);
+apr_status_t md_json_get_timeperiod(struct md_timeperiod_t *tp, md_json_t *json, ...);
+
#endif /* md_json_h */
Modified: httpd/httpd/branches/2.4.x/modules/md/md_jws.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_jws.c?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_jws.c (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_jws.c Fri Oct 25 13:27:12 2019
@@ -32,13 +32,13 @@ static int header_set(void *data, const
}
apr_status_t md_jws_sign(md_json_t **pmsg, apr_pool_t *p,
- const char *payload, size_t len,
- struct apr_table_t *protected,
+ md_data_t *payload, struct apr_table_t *protected,
struct md_pkey_t *pkey, const char *key_id)
{
md_json_t *msg, *jprotected;
const char *prot64, *pay64, *sign64, *sign, *prot;
apr_status_t rv = APR_SUCCESS;
+ md_data_t data;
*pmsg = NULL;
@@ -64,9 +64,11 @@ apr_status_t md_jws_sign(md_json_t **pms
}
if (rv == APR_SUCCESS) {
- prot64 = md_util_base64url_encode(prot, strlen(prot), p);
+ data.data = prot;
+ data.len = strlen(prot);
+ prot64 = md_util_base64url_encode(&data, p);
md_json_sets(prot64, msg, "protected", NULL);
- pay64 = md_util_base64url_encode(payload, len, p);
+ pay64 = md_util_base64url_encode(payload, p);
md_json_sets(pay64, msg, "payload", NULL);
sign = apr_psprintf(p, "%s.%s", prot64, pay64);
@@ -91,7 +93,7 @@ apr_status_t md_jws_sign(md_json_t **pms
apr_status_t md_jws_pkey_thumb(const char **pthumb, apr_pool_t *p, struct md_pkey_t *pkey)
{
const char *e64, *n64, *s;
- md_data data;
+ md_data_t data;
apr_status_t rv;
e64 = md_pkey_get_rsa_e64(pkey, p);
Modified: httpd/httpd/branches/2.4.x/modules/md/md_jws.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/md/md_jws.h?rev=1868930&r1=1868929&r2=1868930&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/md/md_jws.h (original)
+++ httpd/httpd/branches/2.4.x/modules/md/md_jws.h Fri Oct 25 13:27:12 2019
@@ -20,9 +20,10 @@
struct apr_table_t;
struct md_json_t;
struct md_pkey_t;
+struct md_data_t;
apr_status_t md_jws_sign(md_json_t **pmsg, apr_pool_t *p,
- const char *payload, size_t len, struct apr_table_t *protected,
+ struct md_data_t *payload, struct apr_table_t *protected,
struct md_pkey_t *pkey, const char *key_id);
apr_status_t md_jws_pkey_thumb(const char **pthumb, apr_pool_t *p, struct md_pkey_t *pkey);