19bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/***************************************************************************
29bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                      _   _ ____  _
39bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *  Project         ___| | | |  _ \| |
49bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                 / __| | | | |_) | |
59bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                | (__| |_| |  _ <| |___
69bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *                 \___|\___/|_| \_\_____|
79bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 2012 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
99bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is licensed as described in the file COPYING, which
129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * you should have received as part of this distribution. The terms
138f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html.
149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * You may opt to use, copy, modify, merge, publish, distribute and/or sell
169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * copies of the Software, and permit persons to whom the Software is
179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * furnished to do so, under the terms of the COPYING file.
189bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
199bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels * KIND, either express or implied.
219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels *
229bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels ***************************************************************************/
239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h"
259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef USE_LIBRTMP
279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2882be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes#include "curl_rtmp.h"
299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "urldata.h"
309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "nonblock.h" /* for curlx_nonblock */
319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "progress.h" /* for Curl_pgrsSetUploadSize */
329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "transfer.h"
33e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "warnless.h"
349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <curl/curl.h>
359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include <librtmp/rtmp.h>
369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "curl_memory.h"
379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/* The last #include file should be: */
389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#include "memdebug.h"
399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#ifdef _WIN32
419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
429bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define SET_RCVTIMEO(tv,s)   int tv = s*1000
439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#else
449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define SET_RCVTIMEO(tv,s)   struct timeval tv = {s,0}
459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif
469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#define DEF_BUFTIME    (2*60*60*1000)    /* 2 hours */
489bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
49e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic CURLcode rtmp_setup_connection(struct connectdata *conn);
509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_do(struct connectdata *conn, bool *done);
519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_connect(struct connectdata *conn, bool *done);
53e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic CURLcode rtmp_disconnect(struct connectdata *conn, bool dead);
549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic Curl_recv rtmp_recv;
569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic Curl_send rtmp_send;
579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels/*
598f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu
609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels */
619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmp = {
639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMP",                               /* scheme */
64e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
669bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
699bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
73e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
76e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
7782be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMP,                            /* defport */
79e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMP,                       /* protocol */
80e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmpt = {
849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMPT",                              /* scheme */
85e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
889bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
94e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
97e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
9882be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMPT,                           /* defport */
100e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMPT,                      /* protocol */
101e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
1029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
1039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmpe = {
1059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMPE",                              /* scheme */
106e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
1079bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
1089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
1099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
1109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
1119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
1129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
1139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
1149bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
115e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
1169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
1179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
118e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
11982be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
1209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMP,                            /* defport */
121e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMPE,                      /* protocol */
122e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
1239bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
1249bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmpte = {
1269bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMPTE",                             /* scheme */
127e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
1289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
1299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
1309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
1329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
1339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
1349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
1359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
136e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
1379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
1389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
139e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
14082be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
1419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMPT,                           /* defport */
142e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMPTE,                     /* protocol */
143e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
1449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
1459bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1469bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmps = {
1479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMPS",                              /* scheme */
148e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
1499bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
1509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
1519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
1529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
1549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
1559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
1569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
157e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
1589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
1599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
160e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
16182be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
1629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMPS,                           /* defport */
163e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMPS,                      /* protocol */
164e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
1659bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
166e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
1679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsconst struct Curl_handler Curl_handler_rtmpts = {
1689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  "RTMPTS",                             /* scheme */
169e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  rtmp_setup_connection,                /* setup_connection */
1709bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_do,                              /* do_it */
1719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_done,                            /* done */
1729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* do_more */
1739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_connect,                         /* connect_it */
1749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* connecting */
1759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing */
1769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* proto_getsock */
1779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* doing_getsock */
178e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* domore_getsock */
1799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ZERO_NULL,                            /* perform_getsock */
1809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  rtmp_disconnect,                      /* disconnect */
181e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  ZERO_NULL,                            /* readwrite */
18282be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  ZERO_NULL,                            /* connection_check */
1839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  PORT_RTMPS,                           /* defport */
184e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  CURLPROTO_RTMPTS,                     /* protocol */
185e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  PROTOPT_NONE                          /* flags*/
1869bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels};
1879bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
188e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic CURLcode rtmp_setup_connection(struct connectdata *conn)
1899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
1909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = RTMP_Alloc();
191e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!r)
1929bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return CURLE_OUT_OF_MEMORY;
1939bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
1949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP_Init(r);
1959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP_SetBufferMS(r, DEF_BUFTIME);
196e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!RTMP_SetupURL(r, conn->data->change.url)) {
1979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    RTMP_Free(r);
1989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return CURLE_URL_MALFORMAT;
1999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->proto.generic = r;
2019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return CURLE_OK;
2029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_connect(struct connectdata *conn, bool *done)
2059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = conn->proto.generic;
207e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  SET_RCVTIMEO(tv, 10);
2089bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
20982be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes  r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET];
2109bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* We have to know if it's a write before we send the
2129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels   * connect request packet
2139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels   */
214e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(conn->data->set.upload)
2159bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    r->Link.protocol |= RTMP_FEATURE_WRITE;
2169bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2179bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* For plain streams, use the buffer toggle trick to keep data flowing */
218e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!(r->Link.lFlags & RTMP_LF_LIVE) &&
219e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET     !(r->Link.protocol & RTMP_FEATURE_HTTP))
2209bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    r->Link.lFlags |= RTMP_LF_BUFX;
2219bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
222e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  (void)curlx_nonblock(r->m_sb.sb_socket, FALSE);
223e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO,
224e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET             (char *)&tv, sizeof(tv));
2259bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
226e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!RTMP_Connect1(r, NULL))
2279bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return CURLE_FAILED_INIT;
2289bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2299bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  /* Clients must send a periodic BytesReceived report to the server */
2309bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  r->m_bSendCounter = true;
2319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2329bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *done = TRUE;
2339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->recv[FIRSTSOCKET] = rtmp_recv;
2349bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  conn->send[FIRSTSOCKET] = rtmp_send;
2359bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return CURLE_OK;
2369bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2379bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2389bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_do(struct connectdata *conn, bool *done)
2399bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2409bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = conn->proto.generic;
2419bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
242e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(!RTMP_ConnectStream(r, 0))
2439bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    return CURLE_FAILED_INIT;
2449bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
245e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(conn->data->set.upload) {
246e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    Curl_pgrsSetUploadSize(conn->data, conn->data->state.infilesize);
2479bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
248e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  }
249e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  else
2509bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
2519bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  *done = TRUE;
2529bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return CURLE_OK;
2539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2549bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
2569bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                          bool premature)
2579bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2589bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)conn; /* unused */
2599bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)status; /* unused */
2609bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)premature; /* unused */
2619bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2629bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return CURLE_OK;
2639bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2649bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
265e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNETstatic CURLcode rtmp_disconnect(struct connectdata *conn,
266e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET                                bool dead_connection)
2679bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2689bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = conn->proto.generic;
269e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  (void)dead_connection;
270e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(r) {
2719bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    conn->proto.generic = NULL;
2729bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    RTMP_Close(r);
2739bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    RTMP_Free(r);
2749bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2759bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return CURLE_OK;
2769bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2779bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2789bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
2799bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                         size_t len, CURLcode *err)
2809bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
2819bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = conn->proto.generic;
2829bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ssize_t nread;
2839bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2849bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)sockindex; /* unused */
2859bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
286e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  nread = RTMP_Read(r, buf, curlx_uztosi(len));
287e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(nread < 0) {
288e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    if(r->m_read.status == RTMP_READ_COMPLETE ||
2899bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels        r->m_read.status == RTMP_READ_EOF) {
2909bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      conn->data->req.size = conn->data->req.bytecount;
2919bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      nread = 0;
292e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    }
293e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET    else
2949bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      *err = CURLE_RECV_ERROR;
2959bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  }
2969bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return nread;
2979bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
2989bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
2999bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckelsstatic ssize_t rtmp_send(struct connectdata *conn, int sockindex,
3009bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels                         const void *buf, size_t len, CURLcode *err)
3019bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels{
3029bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  RTMP *r = conn->proto.generic;
3039bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  ssize_t num;
3049bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
3059bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  (void)sockindex; /* unused */
3069bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels
307e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  num = RTMP_Write(r, (char *)buf, curlx_uztosi(len));
308e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  if(num < 0)
3099bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels    *err = CURLE_SEND_ERROR;
310e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
3119bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels  return num;
3129bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels}
3139bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels#endif  /* USE_LIBRTMP */
314