Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/lib/curl_rtmp.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) 2012 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. | |
| 9 * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com> | |
| 10 * | |
| 11 * This software is licensed as described in the file COPYING, which | |
| 12 * you should have received as part of this distribution. The terms | |
| 13 * are also available at https://curl.haxx.se/docs/copyright.html. | |
| 14 * | |
| 15 * You may opt to use, copy, modify, merge, publish, distribute and/or sell | |
| 16 * copies of the Software, and permit persons to whom the Software is | |
| 17 * furnished to do so, under the terms of the COPYING file. | |
| 18 * | |
| 19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | |
| 20 * KIND, either express or implied. | |
| 21 * | |
| 22 ***************************************************************************/ | |
| 23 | |
| 24 #include "curl_setup.h" | |
| 25 | |
| 26 #ifdef USE_LIBRTMP | |
| 27 | |
| 28 #include "curl_rtmp.h" | |
| 29 #include "urldata.h" | |
| 30 #include "nonblock.h" /* for curlx_nonblock */ | |
| 31 #include "progress.h" /* for Curl_pgrsSetUploadSize */ | |
| 32 #include "transfer.h" | |
| 33 #include "warnless.h" | |
| 34 #include <curl/curl.h> | |
| 35 #include <librtmp/rtmp.h> | |
| 36 #include "curl_memory.h" | |
| 37 /* The last #include file should be: */ | |
| 38 #include "memdebug.h" | |
| 39 | |
| 40 #if defined(WIN32) && !defined(USE_LWIPSOCK) | |
| 41 #define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e) | |
| 42 #define SET_RCVTIMEO(tv,s) int tv = s*1000 | |
| 43 #elif defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) | |
| 44 #define SET_RCVTIMEO(tv,s) int tv = s*1000 | |
| 45 #else | |
| 46 #define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} | |
| 47 #endif | |
| 48 | |
| 49 #define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ | |
| 50 | |
| 51 static CURLcode rtmp_setup_connection(struct connectdata *conn); | |
| 52 static CURLcode rtmp_do(struct connectdata *conn, bool *done); | |
| 53 static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature); | |
| 54 static CURLcode rtmp_connect(struct connectdata *conn, bool *done); | |
| 55 static CURLcode rtmp_disconnect(struct connectdata *conn, bool dead); | |
| 56 | |
| 57 static Curl_recv rtmp_recv; | |
| 58 static Curl_send rtmp_send; | |
| 59 | |
| 60 /* | |
| 61 * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu | |
| 62 */ | |
| 63 | |
| 64 const struct Curl_handler Curl_handler_rtmp = { | |
| 65 "RTMP", /* scheme */ | |
| 66 rtmp_setup_connection, /* setup_connection */ | |
| 67 rtmp_do, /* do_it */ | |
| 68 rtmp_done, /* done */ | |
| 69 ZERO_NULL, /* do_more */ | |
| 70 rtmp_connect, /* connect_it */ | |
| 71 ZERO_NULL, /* connecting */ | |
| 72 ZERO_NULL, /* doing */ | |
| 73 ZERO_NULL, /* proto_getsock */ | |
| 74 ZERO_NULL, /* doing_getsock */ | |
| 75 ZERO_NULL, /* domore_getsock */ | |
| 76 ZERO_NULL, /* perform_getsock */ | |
| 77 rtmp_disconnect, /* disconnect */ | |
| 78 ZERO_NULL, /* readwrite */ | |
| 79 ZERO_NULL, /* connection_check */ | |
| 80 PORT_RTMP, /* defport */ | |
| 81 CURLPROTO_RTMP, /* protocol */ | |
| 82 PROTOPT_NONE /* flags*/ | |
| 83 }; | |
| 84 | |
| 85 const struct Curl_handler Curl_handler_rtmpt = { | |
| 86 "RTMPT", /* scheme */ | |
| 87 rtmp_setup_connection, /* setup_connection */ | |
| 88 rtmp_do, /* do_it */ | |
| 89 rtmp_done, /* done */ | |
| 90 ZERO_NULL, /* do_more */ | |
| 91 rtmp_connect, /* connect_it */ | |
| 92 ZERO_NULL, /* connecting */ | |
| 93 ZERO_NULL, /* doing */ | |
| 94 ZERO_NULL, /* proto_getsock */ | |
| 95 ZERO_NULL, /* doing_getsock */ | |
| 96 ZERO_NULL, /* domore_getsock */ | |
| 97 ZERO_NULL, /* perform_getsock */ | |
| 98 rtmp_disconnect, /* disconnect */ | |
| 99 ZERO_NULL, /* readwrite */ | |
| 100 ZERO_NULL, /* connection_check */ | |
| 101 PORT_RTMPT, /* defport */ | |
| 102 CURLPROTO_RTMPT, /* protocol */ | |
| 103 PROTOPT_NONE /* flags*/ | |
| 104 }; | |
| 105 | |
| 106 const struct Curl_handler Curl_handler_rtmpe = { | |
| 107 "RTMPE", /* scheme */ | |
| 108 rtmp_setup_connection, /* setup_connection */ | |
| 109 rtmp_do, /* do_it */ | |
| 110 rtmp_done, /* done */ | |
| 111 ZERO_NULL, /* do_more */ | |
| 112 rtmp_connect, /* connect_it */ | |
| 113 ZERO_NULL, /* connecting */ | |
| 114 ZERO_NULL, /* doing */ | |
| 115 ZERO_NULL, /* proto_getsock */ | |
| 116 ZERO_NULL, /* doing_getsock */ | |
| 117 ZERO_NULL, /* domore_getsock */ | |
| 118 ZERO_NULL, /* perform_getsock */ | |
| 119 rtmp_disconnect, /* disconnect */ | |
| 120 ZERO_NULL, /* readwrite */ | |
| 121 ZERO_NULL, /* connection_check */ | |
| 122 PORT_RTMP, /* defport */ | |
| 123 CURLPROTO_RTMPE, /* protocol */ | |
| 124 PROTOPT_NONE /* flags*/ | |
| 125 }; | |
| 126 | |
| 127 const struct Curl_handler Curl_handler_rtmpte = { | |
| 128 "RTMPTE", /* scheme */ | |
| 129 rtmp_setup_connection, /* setup_connection */ | |
| 130 rtmp_do, /* do_it */ | |
| 131 rtmp_done, /* done */ | |
| 132 ZERO_NULL, /* do_more */ | |
| 133 rtmp_connect, /* connect_it */ | |
| 134 ZERO_NULL, /* connecting */ | |
| 135 ZERO_NULL, /* doing */ | |
| 136 ZERO_NULL, /* proto_getsock */ | |
| 137 ZERO_NULL, /* doing_getsock */ | |
| 138 ZERO_NULL, /* domore_getsock */ | |
| 139 ZERO_NULL, /* perform_getsock */ | |
| 140 rtmp_disconnect, /* disconnect */ | |
| 141 ZERO_NULL, /* readwrite */ | |
| 142 ZERO_NULL, /* connection_check */ | |
| 143 PORT_RTMPT, /* defport */ | |
| 144 CURLPROTO_RTMPTE, /* protocol */ | |
| 145 PROTOPT_NONE /* flags*/ | |
| 146 }; | |
| 147 | |
| 148 const struct Curl_handler Curl_handler_rtmps = { | |
| 149 "RTMPS", /* scheme */ | |
| 150 rtmp_setup_connection, /* setup_connection */ | |
| 151 rtmp_do, /* do_it */ | |
| 152 rtmp_done, /* done */ | |
| 153 ZERO_NULL, /* do_more */ | |
| 154 rtmp_connect, /* connect_it */ | |
| 155 ZERO_NULL, /* connecting */ | |
| 156 ZERO_NULL, /* doing */ | |
| 157 ZERO_NULL, /* proto_getsock */ | |
| 158 ZERO_NULL, /* doing_getsock */ | |
| 159 ZERO_NULL, /* domore_getsock */ | |
| 160 ZERO_NULL, /* perform_getsock */ | |
| 161 rtmp_disconnect, /* disconnect */ | |
| 162 ZERO_NULL, /* readwrite */ | |
| 163 ZERO_NULL, /* connection_check */ | |
| 164 PORT_RTMPS, /* defport */ | |
| 165 CURLPROTO_RTMPS, /* protocol */ | |
| 166 PROTOPT_NONE /* flags*/ | |
| 167 }; | |
| 168 | |
| 169 const struct Curl_handler Curl_handler_rtmpts = { | |
| 170 "RTMPTS", /* scheme */ | |
| 171 rtmp_setup_connection, /* setup_connection */ | |
| 172 rtmp_do, /* do_it */ | |
| 173 rtmp_done, /* done */ | |
| 174 ZERO_NULL, /* do_more */ | |
| 175 rtmp_connect, /* connect_it */ | |
| 176 ZERO_NULL, /* connecting */ | |
| 177 ZERO_NULL, /* doing */ | |
| 178 ZERO_NULL, /* proto_getsock */ | |
| 179 ZERO_NULL, /* doing_getsock */ | |
| 180 ZERO_NULL, /* domore_getsock */ | |
| 181 ZERO_NULL, /* perform_getsock */ | |
| 182 rtmp_disconnect, /* disconnect */ | |
| 183 ZERO_NULL, /* readwrite */ | |
| 184 ZERO_NULL, /* connection_check */ | |
| 185 PORT_RTMPS, /* defport */ | |
| 186 CURLPROTO_RTMPTS, /* protocol */ | |
| 187 PROTOPT_NONE /* flags*/ | |
| 188 }; | |
| 189 | |
| 190 static CURLcode rtmp_setup_connection(struct connectdata *conn) | |
| 191 { | |
| 192 RTMP *r = RTMP_Alloc(); | |
| 193 if(!r) | |
| 194 return CURLE_OUT_OF_MEMORY; | |
| 195 | |
| 196 RTMP_Init(r); | |
| 197 RTMP_SetBufferMS(r, DEF_BUFTIME); | |
| 198 if(!RTMP_SetupURL(r, conn->data->change.url)) { | |
| 199 RTMP_Free(r); | |
| 200 return CURLE_URL_MALFORMAT; | |
| 201 } | |
| 202 conn->proto.rtmp = r; | |
| 203 return CURLE_OK; | |
| 204 } | |
| 205 | |
| 206 static CURLcode rtmp_connect(struct connectdata *conn, bool *done) | |
| 207 { | |
| 208 RTMP *r = conn->proto.rtmp; | |
| 209 SET_RCVTIMEO(tv, 10); | |
| 210 | |
| 211 r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET]; | |
| 212 | |
| 213 /* We have to know if it's a write before we send the | |
| 214 * connect request packet | |
| 215 */ | |
| 216 if(conn->data->set.upload) | |
| 217 r->Link.protocol |= RTMP_FEATURE_WRITE; | |
| 218 | |
| 219 /* For plain streams, use the buffer toggle trick to keep data flowing */ | |
| 220 if(!(r->Link.lFlags & RTMP_LF_LIVE) && | |
| 221 !(r->Link.protocol & RTMP_FEATURE_HTTP)) | |
| 222 r->Link.lFlags |= RTMP_LF_BUFX; | |
| 223 | |
| 224 (void)curlx_nonblock(r->m_sb.sb_socket, FALSE); | |
| 225 setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, | |
| 226 (char *)&tv, sizeof(tv)); | |
| 227 | |
| 228 if(!RTMP_Connect1(r, NULL)) | |
| 229 return CURLE_FAILED_INIT; | |
| 230 | |
| 231 /* Clients must send a periodic BytesReceived report to the server */ | |
| 232 r->m_bSendCounter = true; | |
| 233 | |
| 234 *done = TRUE; | |
| 235 conn->recv[FIRSTSOCKET] = rtmp_recv; | |
| 236 conn->send[FIRSTSOCKET] = rtmp_send; | |
| 237 return CURLE_OK; | |
| 238 } | |
| 239 | |
| 240 static CURLcode rtmp_do(struct connectdata *conn, bool *done) | |
| 241 { | |
| 242 struct Curl_easy *data = conn->data; | |
| 243 RTMP *r = conn->proto.rtmp; | |
| 244 | |
| 245 if(!RTMP_ConnectStream(r, 0)) | |
| 246 return CURLE_FAILED_INIT; | |
| 247 | |
| 248 if(conn->data->set.upload) { | |
| 249 Curl_pgrsSetUploadSize(data, data->state.infilesize); | |
| 250 Curl_setup_transfer(data, -1, -1, FALSE, FIRSTSOCKET); | |
| 251 } | |
| 252 else | |
| 253 Curl_setup_transfer(data, FIRSTSOCKET, -1, FALSE, -1); | |
| 254 *done = TRUE; | |
| 255 return CURLE_OK; | |
| 256 } | |
| 257 | |
| 258 static CURLcode rtmp_done(struct connectdata *conn, CURLcode status, | |
| 259 bool premature) | |
| 260 { | |
| 261 (void)conn; /* unused */ | |
| 262 (void)status; /* unused */ | |
| 263 (void)premature; /* unused */ | |
| 264 | |
| 265 return CURLE_OK; | |
| 266 } | |
| 267 | |
| 268 static CURLcode rtmp_disconnect(struct connectdata *conn, | |
| 269 bool dead_connection) | |
| 270 { | |
| 271 RTMP *r = conn->proto.rtmp; | |
| 272 (void)dead_connection; | |
| 273 if(r) { | |
| 274 conn->proto.rtmp = NULL; | |
| 275 RTMP_Close(r); | |
| 276 RTMP_Free(r); | |
| 277 } | |
| 278 return CURLE_OK; | |
| 279 } | |
| 280 | |
| 281 static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf, | |
| 282 size_t len, CURLcode *err) | |
| 283 { | |
| 284 RTMP *r = conn->proto.rtmp; | |
| 285 ssize_t nread; | |
| 286 | |
| 287 (void)sockindex; /* unused */ | |
| 288 | |
| 289 nread = RTMP_Read(r, buf, curlx_uztosi(len)); | |
| 290 if(nread < 0) { | |
| 291 if(r->m_read.status == RTMP_READ_COMPLETE || | |
| 292 r->m_read.status == RTMP_READ_EOF) { | |
| 293 conn->data->req.size = conn->data->req.bytecount; | |
| 294 nread = 0; | |
| 295 } | |
| 296 else | |
| 297 *err = CURLE_RECV_ERROR; | |
| 298 } | |
| 299 return nread; | |
| 300 } | |
| 301 | |
| 302 static ssize_t rtmp_send(struct connectdata *conn, int sockindex, | |
| 303 const void *buf, size_t len, CURLcode *err) | |
| 304 { | |
| 305 RTMP *r = conn->proto.rtmp; | |
| 306 ssize_t num; | |
| 307 | |
| 308 (void)sockindex; /* unused */ | |
| 309 | |
| 310 num = RTMP_Write(r, (char *)buf, curlx_uztosi(len)); | |
| 311 if(num < 0) | |
| 312 *err = CURLE_SEND_ERROR; | |
| 313 | |
| 314 return num; | |
| 315 } | |
| 316 #endif /* USE_LIBRTMP */ |
