Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/docs/examples/http2-pushinmemory.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*************************************************************************** | |
| 2 * _ _ ____ _ | |
| 3 * Project ___| | | | _ \| | | |
| 4 * / __| | | | |_) | | | |
| 5 * | (__| |_| | _ <| |___ | |
| 6 * \___|\___/|_| \_\_____| | |
| 7 * | |
| 8 * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@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 * HTTP/2 server push. Receive all data in memory. | |
| 24 * </DESC> | |
| 25 */ | |
| 26 #include <stdio.h> | |
| 27 #include <stdlib.h> | |
| 28 #include <string.h> | |
| 29 | |
| 30 /* somewhat unix-specific */ | |
| 31 #include <sys/time.h> | |
| 32 #include <unistd.h> | |
| 33 | |
| 34 /* curl stuff */ | |
| 35 #include <curl/curl.h> | |
| 36 | |
| 37 struct Memory { | |
| 38 char *memory; | |
| 39 size_t size; | |
| 40 }; | |
| 41 | |
| 42 static size_t | |
| 43 write_cb(void *contents, size_t size, size_t nmemb, void *userp) | |
| 44 { | |
| 45 size_t realsize = size * nmemb; | |
| 46 struct Memory *mem = (struct Memory *)userp; | |
| 47 char *ptr = realloc(mem->memory, mem->size + realsize + 1); | |
| 48 if(!ptr) { | |
| 49 /* out of memory! */ | |
| 50 printf("not enough memory (realloc returned NULL)\n"); | |
| 51 return 0; | |
| 52 } | |
| 53 | |
| 54 mem->memory = ptr; | |
| 55 memcpy(&(mem->memory[mem->size]), contents, realsize); | |
| 56 mem->size += realsize; | |
| 57 mem->memory[mem->size] = 0; | |
| 58 | |
| 59 return realsize; | |
| 60 } | |
| 61 | |
| 62 #define MAX_FILES 10 | |
| 63 static struct Memory files[MAX_FILES]; | |
| 64 static int pushindex = 1; | |
| 65 | |
| 66 static void init_memory(struct Memory *chunk) | |
| 67 { | |
| 68 chunk->memory = malloc(1); /* grown as needed with realloc */ | |
| 69 chunk->size = 0; /* no data at this point */ | |
| 70 } | |
| 71 | |
| 72 static void setup(CURL *hnd) | |
| 73 { | |
| 74 /* set the same URL */ | |
| 75 curl_easy_setopt(hnd, CURLOPT_URL, "https://localhost:8443/index.html"); | |
| 76 | |
| 77 /* HTTP/2 please */ | |
| 78 curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); | |
| 79 | |
| 80 /* we use a self-signed test server, skip verification during debugging */ | |
| 81 curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); | |
| 82 curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L); | |
| 83 | |
| 84 /* write data to a struct */ | |
| 85 curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, write_cb); | |
| 86 init_memory(&files[0]); | |
| 87 curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &files[0]); | |
| 88 | |
| 89 /* wait for pipe connection to confirm */ | |
| 90 curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); | |
| 91 } | |
| 92 | |
| 93 /* called when there's an incoming push */ | |
| 94 static int server_push_callback(CURL *parent, | |
| 95 CURL *easy, | |
| 96 size_t num_headers, | |
| 97 struct curl_pushheaders *headers, | |
| 98 void *userp) | |
| 99 { | |
| 100 char *headp; | |
| 101 int *transfers = (int *)userp; | |
| 102 (void)parent; /* we have no use for this */ | |
| 103 (void)num_headers; /* unused */ | |
| 104 | |
| 105 if(pushindex == MAX_FILES) | |
| 106 /* can't fit anymore */ | |
| 107 return CURL_PUSH_DENY; | |
| 108 | |
| 109 /* write to this buffer */ | |
| 110 init_memory(&files[pushindex]); | |
| 111 curl_easy_setopt(easy, CURLOPT_WRITEDATA, &files[pushindex]); | |
| 112 pushindex++; | |
| 113 | |
| 114 headp = curl_pushheader_byname(headers, ":path"); | |
| 115 if(headp) | |
| 116 fprintf(stderr, "* Pushed :path '%s'\n", headp /* skip :path + colon */); | |
| 117 | |
| 118 (*transfers)++; /* one more */ | |
| 119 return CURL_PUSH_OK; | |
| 120 } | |
| 121 | |
| 122 | |
| 123 /* | |
| 124 * Download a file over HTTP/2, take care of server push. | |
| 125 */ | |
| 126 int main(void) | |
| 127 { | |
| 128 CURL *easy; | |
| 129 CURLM *multi; | |
| 130 int still_running; /* keep number of running handles */ | |
| 131 int transfers = 1; /* we start with one */ | |
| 132 int i; | |
| 133 struct CURLMsg *m; | |
| 134 | |
| 135 /* init a multi stack */ | |
| 136 multi = curl_multi_init(); | |
| 137 | |
| 138 easy = curl_easy_init(); | |
| 139 | |
| 140 /* set options */ | |
| 141 setup(easy); | |
| 142 | |
| 143 /* add the easy transfer */ | |
| 144 curl_multi_add_handle(multi, easy); | |
| 145 | |
| 146 curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); | |
| 147 curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, server_push_callback); | |
| 148 curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &transfers); | |
| 149 | |
| 150 while(transfers) { | |
| 151 int rc; | |
| 152 CURLMcode mcode = curl_multi_perform(multi, &still_running); | |
| 153 if(mcode) | |
| 154 break; | |
| 155 | |
| 156 mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc); | |
| 157 if(mcode) | |
| 158 break; | |
| 159 | |
| 160 | |
| 161 /* | |
| 162 * When doing server push, libcurl itself created and added one or more | |
| 163 * easy handles but *we* need to clean them up when they are done. | |
| 164 */ | |
| 165 do { | |
| 166 int msgq = 0;; | |
| 167 m = curl_multi_info_read(multi, &msgq); | |
| 168 if(m && (m->msg == CURLMSG_DONE)) { | |
| 169 CURL *e = m->easy_handle; | |
| 170 transfers--; | |
| 171 curl_multi_remove_handle(multi, e); | |
| 172 curl_easy_cleanup(e); | |
| 173 } | |
| 174 } while(m); | |
| 175 | |
| 176 } | |
| 177 | |
| 178 | |
| 179 curl_multi_cleanup(multi); | |
| 180 | |
| 181 /* 'pushindex' is now the number of received transfers */ | |
| 182 for(i = 0; i < pushindex; i++) { | |
| 183 /* do something fun with the data, and then free it when done */ | |
| 184 free(files[i].memory); | |
| 185 } | |
| 186 | |
| 187 return 0; | |
| 188 } |
