Overview
Request 312 (accepted)
update 2.4.git20121102
- Created by marguerite over 11 years ago
- In state accepted
-
Package maintainer:
detrei
Submit package home:marguerite...hes:Essentials / rtmpdump to package Essentials / rtmpdump
rtmpdump.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Thu Nov 1 16:30:15 UTC 2012 - i@margueirte.su
4
+
5
+- update to 2.4.git20121102.
6
+ * Aside from various minor bugfixes since 2.3, RTMPE type 9 handshakes
7
+ are now supported.
8
+
9
+-------------------------------------------------------------------
10
Thu Dec 15 14:15:45 UTC 2011 - ismail@namtrac.org
11
12
- Update to latest git as of 14.11.2011
13
rtmpdump.spec
Changed
10
1
2
#
3
4
Name: rtmpdump
5
-Version: 2.3.99.git20111114
6
+Version: 2.4.git20121102
7
Release: 0
8
License: GPL-2.0
9
%define soname 0
10
rtmpdump-2.3.99.git20111114.tar.bz2/Makefile -> rtmpdump-2.4.git20121102.tar.bz2/Makefile
Changed
10
1
2
#CRYPTO=POLARSSL
3
#CRYPTO=GNUTLS
4
LIBZ=-lz
5
-LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ)
6
+LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ)
7
LIB_OPENSSL=-lssl -lcrypto $(LIBZ)
8
LIB_POLARSSL=-lpolarssl $(LIBZ)
9
CRYPTO_LIB=$(LIB_$(CRYPTO))
10
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/Makefile -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/Makefile
Changed
62
1
2
LIBS_posix=
3
LIBS_darwin=
4
LIBS_mingw=-lws2_32 -lwinmm -lgdi32
5
-LIB_GNUTLS=-lgnutls -lgcrypt $(LIBZ)
6
+LIB_GNUTLS=-lgnutls -lhogweed -lnettle -lgmp $(LIBZ)
7
LIB_OPENSSL=-lssl -lcrypto $(LIBZ)
8
LIB_POLARSSL=-lpolarssl $(LIBZ)
9
PRIVATE_LIBS=$(LIBS_$(SYS))
10
11
SO_VERSION=0
12
SOX_posix=so
13
SOX_darwin=dylib
14
-SOX_mingw=so # useless
15
+SOX_mingw=dll
16
SOX=$(SOX_$(SYS))
17
-SO_posix=$(SOX).$(SO_VERSION)
18
-SO_darwin=$(SO_VERSION).$(SOX)
19
-SO_mingw=dll
20
+SO_posix=.$(SOX).$(SO_VERSION)
21
+SO_darwin=.$(SO_VERSION).$(SOX)
22
+SO_mingw=-$(SO_VERSION).$(SOX)
23
SO_EXT=$(SO_$(SYS))
24
25
SODIR_posix=$(LIBDIR)
26
27
28
SHARED=yes
29
SODEF_yes=-fPIC
30
-SOLIB_yes=librtmp.$(SO_EXT)
31
+SOLIB_yes=librtmp$(SO_EXT)
32
SOINST_yes=install_so
33
SO_DEF=$(SODEF_$(SHARED))
34
SO_LIB=$(SOLIB_$(SHARED))
35
36
all: librtmp.a $(SO_LIB)
37
38
clean:
39
- rm -f *.o *.a *.$(SOX) *.$(SO_EXT) librtmp.pc
40
+ rm -f *.o *.a *.$(SOX) *$(SO_EXT) librtmp.pc
41
42
librtmp.a: $(OBJS)
43
$(AR) rs $@ $?
44
45
-librtmp.$(SO_EXT): $(OBJS)
46
+librtmp$(SO_EXT): $(OBJS)
47
$(CC) $(SO_LDFLAGS) $(LDFLAGS) -o $@ $^ $> $(CRYPTO_LIB)
48
ln -sf $@ librtmp.$(SOX)
49
50
51
cp librtmp.pc $(LIBDIR)/pkgconfig
52
cp librtmp.3 $(MANDIR)/man3
53
54
-install_so: librtmp.$(SO_EXT)
55
- cp librtmp.$(SO_EXT) $(SODIR)
56
+install_so: librtmp$(SO_EXT)
57
+ cp librtmp$(SO_EXT) $(SODIR)
58
$(INSTALL_IMPLIB)
59
- cd $(SODIR); ln -sf librtmp.$(SO_EXT) librtmp.$(SOX)
60
+ cd $(SODIR); ln -sf librtmp$(SO_EXT) librtmp.$(SOX)
61
62
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/amf.c -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/amf.c
Changed
167
1
2
pBuffer = AMF_Encode(&prop->p_vu.p_object, pBuffer, pBufEnd);
3
break;
4
5
+ case AMF_ECMA_ARRAY:
6
+ pBuffer = AMF_EncodeEcmaArray(&prop->p_vu.p_object, pBuffer, pBufEnd);
7
+ break;
8
+
9
+ case AMF_STRICT_ARRAY:
10
+ pBuffer = AMF_EncodeArray(&prop->p_vu.p_object, pBuffer, pBufEnd);
11
+ break;
12
+
13
default:
14
RTMP_Log(RTMP_LOGERROR, "%s, invalid type. %d", __FUNCTION__, prop->p_type);
15
pBuffer = NULL;
16
17
if (nRes == -1)
18
return -1;
19
nSize -= nRes;
20
- prop->p_type = AMF_OBJECT;
21
break;
22
}
23
case AMF_OBJECT_END:
24
25
if (nRes == -1)
26
return -1;
27
nSize -= nRes;
28
- prop->p_type = AMF_OBJECT;
29
break;
30
}
31
case AMF_DATE:
32
33
break;
34
}
35
case AMF_LONG_STRING:
36
+ case AMF_XML_DOC:
37
{
38
unsigned int nStringSize = AMF_DecodeInt32(pBuffer);
39
if (nSize < (long)nStringSize + 4)
40
return -1;
41
AMF_DecodeLongString(pBuffer, &prop->p_vu.p_aval);
42
nSize -= (4 + nStringSize);
43
- prop->p_type = AMF_STRING;
44
+ if (prop->p_type == AMF_LONG_STRING)
45
+ prop->p_type = AMF_STRING;
46
break;
47
}
48
case AMF_RECORDSET:
49
50
return -1;
51
break;
52
}
53
- case AMF_XML_DOC:
54
- {
55
- RTMP_Log(RTMP_LOGERROR, "AMF_XML_DOC not supported!");
56
- return -1;
57
- break;
58
- }
59
case AMF_TYPED_OBJECT:
60
{
61
RTMP_Log(RTMP_LOGERROR, "AMF_TYPED_OBJECT not supported!");
62
63
AMF_Dump(&prop->p_vu.p_object);
64
return;
65
}
66
+ else if (prop->p_type == AMF_ECMA_ARRAY)
67
+ {
68
+ RTMP_Log(RTMP_LOGDEBUG, "Property: <%sECMA_ARRAY>", strRes);
69
+ AMF_Dump(&prop->p_vu.p_object);
70
+ return;
71
+ }
72
+ else if (prop->p_type == AMF_STRICT_ARRAY)
73
+ {
74
+ RTMP_Log(RTMP_LOGDEBUG, "Property: <%sSTRICT_ARRAY>", strRes);
75
+ AMF_Dump(&prop->p_vu.p_object);
76
+ return;
77
+ }
78
79
switch (prop->p_type)
80
{
81
82
return pBuffer;
83
}
84
85
+char *
86
+AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd)
87
+{
88
+ int i;
89
+
90
+ if (pBuffer+4 >= pBufEnd)
91
+ return NULL;
92
+
93
+ *pBuffer++ = AMF_ECMA_ARRAY;
94
+
95
+ pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num);
96
+
97
+ for (i = 0; i < obj->o_num; i++)
98
+ {
99
+ char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd);
100
+ if (res == NULL)
101
+ {
102
+ RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d",
103
+ i);
104
+ break;
105
+ }
106
+ else
107
+ {
108
+ pBuffer = res;
109
+ }
110
+ }
111
+
112
+ if (pBuffer + 3 >= pBufEnd)
113
+ return NULL; /* no room for the end marker */
114
+
115
+ pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END);
116
+
117
+ return pBuffer;
118
+}
119
+
120
+char *
121
+AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd)
122
+{
123
+ int i;
124
+
125
+ if (pBuffer+4 >= pBufEnd)
126
+ return NULL;
127
+
128
+ *pBuffer++ = AMF_STRICT_ARRAY;
129
+
130
+ pBuffer = AMF_EncodeInt32(pBuffer, pBufEnd, obj->o_num);
131
+
132
+ for (i = 0; i < obj->o_num; i++)
133
+ {
134
+ char *res = AMFProp_Encode(&obj->o_props[i], pBuffer, pBufEnd);
135
+ if (res == NULL)
136
+ {
137
+ RTMP_Log(RTMP_LOGERROR, "AMF_Encode - failed to encode property in index %d",
138
+ i);
139
+ break;
140
+ }
141
+ else
142
+ {
143
+ pBuffer = res;
144
+ }
145
+ }
146
+
147
+ //if (pBuffer + 3 >= pBufEnd)
148
+ // return NULL; /* no room for the end marker */
149
+
150
+ //pBuffer = AMF_EncodeInt24(pBuffer, pBufEnd, AMF_OBJECT_END);
151
+
152
+ return pBuffer;
153
+}
154
+
155
int
156
AMF_DecodeArray(AMFObject *obj, const char *pBuffer, int nSize,
157
int nArrayLen, int bDecodeName)
158
159
{
160
if (nIndex >= 0)
161
{
162
- if (nIndex <= obj->o_num)
163
+ if (nIndex < obj->o_num)
164
return &obj->o_props[nIndex];
165
}
166
else
167
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/amf.h -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/amf.h
Changed
11
1
2
double AMF_DecodeNumber(const char *data);
3
4
char *AMF_Encode(AMFObject * obj, char *pBuffer, char *pBufEnd);
5
+ char *AMF_EncodeEcmaArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
6
+ char *AMF_EncodeArray(AMFObject *obj, char *pBuffer, char *pBufEnd);
7
+
8
int AMF_Decode(AMFObject * obj, const char *pBuffer, int nSize,
9
int bDecodeName);
10
int AMF_DecodeArray(AMFObject * obj, const char *pBuffer, int nSize,
11
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/dh.h -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/dh.h
Changed
46
1
2
MP_set(&dh->ctx.P, dh->p);
3
MP_set(&dh->ctx.G, dh->g);
4
dh->ctx.len = 128;
5
- dhm_make_public(&dh->ctx, 1024, out, 1, havege_rand, &RTMP_TLS_ctx->hs);
6
+ dhm_make_public(&dh->ctx, 1024, out, 1, havege_random, &RTMP_TLS_ctx->hs);
7
MP_new(dh->pub_key);
8
MP_new(dh->priv_key);
9
MP_set(dh->pub_key, &dh->ctx.GX);
10
11
}
12
13
#elif defined(USE_GNUTLS)
14
-#include <gcrypt.h>
15
-typedef gcry_mpi_t MP_t;
16
-#define MP_new(m) m = gcry_mpi_new(1)
17
-#define MP_set_w(mpi, w) gcry_mpi_set_ui(mpi, w)
18
-#define MP_cmp(u, v) gcry_mpi_cmp(u, v)
19
-#define MP_set(u, v) gcry_mpi_set(u, v)
20
-#define MP_sub_w(mpi, w) gcry_mpi_sub_ui(mpi, mpi, w)
21
-#define MP_cmp_1(mpi) gcry_mpi_cmp_ui(mpi, 1)
22
-#define MP_modexp(r, y, q, p) gcry_mpi_powm(r, y, q, p)
23
-#define MP_free(mpi) gcry_mpi_release(mpi)
24
-#define MP_gethex(u, hex, res) res = (gcry_mpi_scan(&u, GCRYMPI_FMT_HEX, hex, 0, 0) == 0)
25
-#define MP_bytes(u) (gcry_mpi_get_nbits(u) + 7) / 8
26
-#define MP_setbin(u,buf,len) gcry_mpi_print(GCRYMPI_FMT_USG,buf,len,NULL,u)
27
-#define MP_getbin(u,buf,len) gcry_mpi_scan(&u,GCRYMPI_FMT_USG,buf,len,NULL)
28
+#include <gmp.h>
29
+#include <nettle/bignum.h>
30
+typedef mpz_ptr MP_t;
31
+#define MP_new(m) m = malloc(sizeof(*m)); mpz_init2(m, 1)
32
+#define MP_set_w(mpi, w) mpz_set_ui(mpi, w)
33
+#define MP_cmp(u, v) mpz_cmp(u, v)
34
+#define MP_set(u, v) mpz_set(u, v)
35
+#define MP_sub_w(mpi, w) mpz_sub_ui(mpi, mpi, w)
36
+#define MP_cmp_1(mpi) mpz_cmp_ui(mpi, 1)
37
+#define MP_modexp(r, y, q, p) mpz_powm(r, y, q, p)
38
+#define MP_free(mpi) mpz_clear(mpi); free(mpi)
39
+#define MP_gethex(u, hex, res) u = malloc(sizeof(*u)); mpz_init2(u, 1); res = (mpz_set_str(u, hex, 16) == 0)
40
+#define MP_bytes(u) (mpz_sizeinbase(u, 2) + 7) / 8
41
+#define MP_setbin(u,buf,len) nettle_mpz_get_str_256(len,buf,u)
42
+#define MP_getbin(u,buf,len) u = malloc(sizeof(*u)); mpz_init2(u, 1); nettle_mpz_set_str_256_u(u,len,buf)
43
44
typedef struct MDH {
45
MP_t p;
46
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/handshake.h -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/handshake.h
Changed
38
1
2
#define RC4_free(h) free(h)
3
4
#elif defined(USE_GNUTLS)
5
-#include <gcrypt.h>
6
+#include <nettle/hmac.h>
7
+#include <nettle/arcfour.h>
8
#ifndef SHA256_DIGEST_LENGTH
9
#define SHA256_DIGEST_LENGTH 32
10
#endif
11
-#define HMAC_CTX gcry_md_hd_t
12
-#define HMAC_setup(ctx, key, len) gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); gcry_md_setkey(ctx, key, len)
13
-#define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len)
14
-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; memcpy(dig, gcry_md_read(ctx, 0), dlen); gcry_md_close(ctx)
15
-
16
-typedef gcry_cipher_hd_t RC4_handle;
17
-#define RC4_alloc(h) gcry_cipher_open(h, GCRY_CIPHER_ARCFOUR, GCRY_CIPHER_MODE_STREAM, 0)
18
-#define RC4_setkey(h,l,k) gcry_cipher_setkey(h,k,l)
19
-#define RC4_encrypt(h,l,d) gcry_cipher_encrypt(h,(void *)d,l,NULL,0)
20
-#define RC4_encrypt2(h,l,s,d) gcry_cipher_encrypt(h,(void *)d,l,(void *)s,l)
21
-#define RC4_free(h) gcry_cipher_close(h)
22
+#undef HMAC_CTX
23
+#define HMAC_CTX struct hmac_sha256_ctx
24
+#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key)
25
+#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf)
26
+#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig)
27
+#define HMAC_close(ctx)
28
+
29
+typedef struct arcfour_ctx* RC4_handle;
30
+#define RC4_alloc(h) *h = malloc(sizeof(struct arcfour_ctx))
31
+#define RC4_setkey(h,l,k) arcfour_set_key(h, l, k)
32
+#define RC4_encrypt(h,l,d) arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)d)
33
+#define RC4_encrypt2(h,l,s,d) arcfour_crypt(h,l,(uint8_t *)d,(uint8_t *)s)
34
+#define RC4_free(h) free(h)
35
36
#else /* USE_OPENSSL */
37
#include <openssl/sha.h>
38
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/hashswf.c -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/hashswf.c
Changed
25
1
2
#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; sha2_hmac_finish(&ctx, dig)
3
#define HMAC_close(ctx)
4
#elif defined(USE_GNUTLS)
5
-#include <gnutls/gnutls.h>
6
-#include <gcrypt.h>
7
+#include <nettle/hmac.h>
8
#ifndef SHA256_DIGEST_LENGTH
9
#define SHA256_DIGEST_LENGTH 32
10
#endif
11
-#define HMAC_CTX gcry_md_hd_t
12
-#define HMAC_setup(ctx, key, len) gcry_md_open(&ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); gcry_md_setkey(ctx, key, len)
13
-#define HMAC_crunch(ctx, buf, len) gcry_md_write(ctx, buf, len)
14
-#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; memcpy(dig, gcry_md_read(ctx, 0), dlen)
15
-#define HMAC_close(ctx) gcry_md_close(ctx)
16
+#undef HMAC_CTX
17
+#define HMAC_CTX struct hmac_sha256_ctx
18
+#define HMAC_setup(ctx, key, len) hmac_sha256_set_key(&ctx, len, key)
19
+#define HMAC_crunch(ctx, buf, len) hmac_sha256_update(&ctx, len, buf)
20
+#define HMAC_finish(ctx, dig, dlen) dlen = SHA256_DIGEST_LENGTH; hmac_sha256_digest(&ctx, SHA256_DIGEST_LENGTH, dig)
21
+#define HMAC_close(ctx)
22
#else /* USE_OPENSSL */
23
#include <openssl/ssl.h>
24
#include <openssl/sha.h>
25
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/parseurl.c -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/parseurl.c
Changed
28
1
2
* application = app[/appinstance]
3
*/
4
5
- char *slash2, *slash3 = NULL;
6
+ char *slash2, *slash3 = NULL, *slash4 = NULL;
7
int applen, appnamelen;
8
9
slash2 = strchr(p, '/');
10
if(slash2)
11
slash3 = strchr(slash2+1, '/');
12
+ if(slash3)
13
+ slash4 = strchr(slash3+1, '/');
14
15
applen = end-p; /* ondemand, pass all parameters as app */
16
appnamelen = applen; /* ondemand length */
17
18
appnamelen = 8;
19
}
20
else { /* app!=ondemand, so app is app[/appinstance] */
21
- if(slash3)
22
+ if(slash4)
23
+ appnamelen = slash4-p;
24
+ else if(slash3)
25
appnamelen = slash3-p;
26
else if(slash2)
27
appnamelen = slash2-p;
28
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/rtmp.c -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/rtmp.c
Changed
1020
1
2
#include <stdlib.h>
3
#include <string.h>
4
#include <assert.h>
5
+#include <time.h>
6
7
#include "rtmp_sys.h"
8
#include "log.h"
9
10
#ifdef CRYPTO
11
#ifdef USE_POLARSSL
12
#include <polarssl/havege.h>
13
+#include <polarssl/md5.h>
14
+#include <polarssl/base64.h>
15
+#define MD5_DIGEST_LENGTH 16
16
+
17
+static const char *my_dhm_P =
18
+ "E4004C1F94182000103D883A448B3F80" \
19
+ "2CE4B44A83301270002C20D0321CFD00" \
20
+ "11CCEF784C26A400F43DFB901BCA7538" \
21
+ "F2C6B176001CF5A0FD16D2C48B1D0C1C" \
22
+ "F6AC8E1DA6BCC3B4E1F96B0564965300" \
23
+ "FFA1D0B601EB2800F489AA512C4B248C" \
24
+ "01F76949A60BB7F00A40B1EAB64BDD48" \
25
+ "E8A700D60B7F1200FA8E77B0A979DABF";
26
+
27
+static const char *my_dhm_G = "4";
28
+
29
#elif defined(USE_GNUTLS)
30
#include <gnutls/gnutls.h>
31
+#define MD5_DIGEST_LENGTH 16
32
+#include <nettle/base64.h>
33
+#include <nettle/md5.h>
34
#else /* USE_OPENSSL */
35
#include <openssl/ssl.h>
36
#include <openssl/rc4.h>
37
+#include <openssl/md5.h>
38
+#include <openssl/bio.h>
39
+#include <openssl/buffer.h>
40
#endif
41
TLS_CTX RTMP_TLS_ctx;
42
#endif
43
44
#endif
45
}
46
47
+void *
48
+RTMP_TLS_AllocServerContext(const char* cert, const char* key)
49
+{
50
+ void *ctx = NULL;
51
+#ifdef CRYPTO
52
+ if (!RTMP_TLS_ctx)
53
+ RTMP_TLS_Init();
54
+#ifdef USE_POLARSSL
55
+ tls_server_ctx *tc = ctx = calloc(1, sizeof(struct tls_server_ctx));
56
+ tc->dhm_P = my_dhm_P;
57
+ tc->dhm_G = my_dhm_G;
58
+ tc->hs = &RTMP_TLS_ctx->hs;
59
+ if (x509parse_crtfile(&tc->cert, cert)) {
60
+ free(tc);
61
+ return NULL;
62
+ }
63
+ if (x509parse_keyfile(&tc->key, key, NULL)) {
64
+ x509_free(&tc->cert);
65
+ free(tc);
66
+ return NULL;
67
+ }
68
+#elif defined(USE_GNUTLS) && !defined(NO_SSL)
69
+ gnutls_certificate_allocate_credentials((gnutls_certificate_credentials*) &ctx);
70
+ if (gnutls_certificate_set_x509_key_file(ctx, cert, key, GNUTLS_X509_FMT_PEM) != 0) {
71
+ gnutls_certificate_free_credentials(ctx);
72
+ return NULL;
73
+ }
74
+#elif !defined(NO_SSL) /* USE_OPENSSL */
75
+ ctx = SSL_CTX_new(SSLv23_server_method());
76
+ if (!SSL_CTX_use_certificate_chain_file(ctx, cert)) {
77
+ SSL_CTX_free(ctx);
78
+ return NULL;
79
+ }
80
+ if (!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
81
+ SSL_CTX_free(ctx);
82
+ return NULL;
83
+ }
84
+#endif
85
+#endif
86
+ return ctx;
87
+}
88
+
89
+void
90
+RTMP_TLS_FreeServerContext(void *ctx)
91
+{
92
+#ifdef CRYPTO
93
+#ifdef USE_POLARSSL
94
+ x509_free(&((tls_server_ctx*)ctx)->cert);
95
+ rsa_free(&((tls_server_ctx*)ctx)->key);
96
+ free(ctx);
97
+#elif defined(USE_GNUTLS) && !defined(NO_SSL)
98
+ gnutls_certificate_free_credentials(ctx);
99
+#elif !defined(NO_SSL) /* USE_OPENSSL */
100
+ SSL_CTX_free(ctx);
101
+#endif
102
+#endif
103
+}
104
+
105
RTMP *
106
RTMP_Alloc()
107
{
108
109
const AVal RTMP_DefaultFlashVer =
110
{ (char *)DEFAULT_FLASH_VER, sizeof(DEFAULT_FLASH_VER) - 1 };
111
112
+static void
113
+SocksSetup(RTMP *r, AVal *sockshost)
114
+{
115
+ if (sockshost->av_len)
116
+ {
117
+ const char *socksport = strchr(sockshost->av_val, ':');
118
+ char *hostname = strdup(sockshost->av_val);
119
+
120
+ if (socksport)
121
+ hostname[socksport - sockshost->av_val] = '\0';
122
+ r->Link.sockshost.av_val = hostname;
123
+ r->Link.sockshost.av_len = strlen(hostname);
124
+
125
+ r->Link.socksport = socksport ? atoi(socksport + 1) : 1080;
126
+ RTMP_Log(RTMP_LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", r->Link.sockshost.av_val,
127
+ r->Link.socksport);
128
+ }
129
+ else
130
+ {
131
+ r->Link.sockshost.av_val = NULL;
132
+ r->Link.sockshost.av_len = 0;
133
+ r->Link.socksport = 0;
134
+ }
135
+}
136
+
137
void
138
RTMP_SetupStream(RTMP *r,
139
int protocol,
140
141
}
142
#endif
143
144
- if (sockshost->av_len)
145
- {
146
- const char *socksport = strchr(sockshost->av_val, ':');
147
- char *hostname = strdup(sockshost->av_val);
148
-
149
- if (socksport)
150
- hostname[socksport - sockshost->av_val] = '\0';
151
- r->Link.sockshost.av_val = hostname;
152
- r->Link.sockshost.av_len = strlen(hostname);
153
-
154
- r->Link.socksport = socksport ? atoi(socksport + 1) : 1080;
155
- RTMP_Log(RTMP_LOGDEBUG, "Connecting via SOCKS proxy: %s:%d", r->Link.sockshost.av_val,
156
- r->Link.socksport);
157
- }
158
- else
159
- {
160
- r->Link.sockshost.av_val = NULL;
161
- r->Link.sockshost.av_len = 0;
162
- r->Link.socksport = 0;
163
- }
164
+ SocksSetup(r, sockshost);
165
166
if (tcUrl && tcUrl->av_len)
167
r->Link.tcUrl = *tcUrl;
168
169
"Buffer time in milliseconds" },
170
{ AVC("timeout"), OFF(Link.timeout), OPT_INT, 0,
171
"Session timeout in seconds" },
172
+ { AVC("pubUser"), OFF(Link.pubUser), OPT_STR, 0,
173
+ "Publisher username" },
174
+ { AVC("pubPasswd"), OFF(Link.pubPasswd), OPT_STR, 0,
175
+ "Publisher password" },
176
{ {NULL,0}, 0, 0}
177
};
178
179
180
(unsigned char *)r->Link.SWFHash, r->Link.swfAge);
181
#endif
182
183
+ SocksSetup(r, &r->Link.sockshost);
184
+
185
if (r->Link.port == 0)
186
{
187
if (r->Link.protocol & RTMP_FEATURE_SSL)
188
189
}
190
191
int
192
+RTMP_TLS_Accept(RTMP *r, void *ctx)
193
+{
194
+#if defined(CRYPTO) && !defined(NO_SSL)
195
+ TLS_server(ctx, r->m_sb.sb_ssl);
196
+ TLS_setfd(r->m_sb.sb_ssl, r->m_sb.sb_socket);
197
+ if (TLS_accept(r->m_sb.sb_ssl) < 0)
198
+ {
199
+ RTMP_Log(RTMP_LOGERROR, "%s, TLS_Connect failed", __FUNCTION__);
200
+ return FALSE;
201
+ }
202
+ return TRUE;
203
+#else
204
+ return FALSE;
205
+#endif
206
+}
207
+
208
+int
209
RTMP_Connect1(RTMP *r, RTMPPacket *cp)
210
{
211
if (r->Link.protocol & RTMP_FEATURE_SSL)
212
213
packet->m_nTimeStamp, packet->m_hasAbsTimestamp,
214
r->m_mediaStamp);
215
#endif
216
+ RTMPPacket_Free(packet);
217
continue;
218
}
219
r->m_pausing = 0;
220
221
if (bHasMediaPacket)
222
r->m_bPlaying = TRUE;
223
else if (r->m_sb.sb_timedout && !r->m_pausing)
224
- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel];
225
+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
226
+ r->m_channelTimestamp[r->m_mediaChannel] : 0;
227
228
return bHasMediaPacket;
229
}
230
231
int nBytes = 0, nRead;
232
if (r->Link.protocol & RTMP_FEATURE_HTTP)
233
{
234
+ int refill = 0;
235
while (!r->m_resplen)
236
{
237
- if (r->m_sb.sb_size < 144)
238
+ int ret;
239
+ if (r->m_sb.sb_size < 13 || refill)
240
{
241
if (!r->m_unackd)
242
HTTP_Post(r, RTMPT_IDLE, "", 1);
243
244
return 0;
245
}
246
}
247
- if (HTTP_read(r, 0) == -1)
248
+ if ((ret = HTTP_read(r, 0)) == -1)
249
{
250
RTMP_Log(RTMP_LOGDEBUG, "%s, No valid HTTP response found", __FUNCTION__);
251
RTMP_Close(r);
252
return 0;
253
}
254
+ else if (ret == -2)
255
+ {
256
+ refill = 1;
257
+ }
258
+ else
259
+ {
260
+ refill = 0;
261
+ }
262
}
263
if (r->m_resplen && !r->m_sb.sb_size)
264
RTMPSockBuf_Fill(&r->m_sb);
265
266
int RTMP_Pause(RTMP *r, int DoPause)
267
{
268
if (DoPause)
269
- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel];
270
+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
271
+ r->m_channelTimestamp[r->m_mediaChannel] : 0;
272
return RTMP_SendPause(r, DoPause, r->m_pauseStamp);
273
}
274
275
276
free(vals);
277
}
278
279
+
280
+#ifdef CRYPTO
281
+static int
282
+b64enc(const unsigned char *input, int length, char *output, int maxsize)
283
+{
284
+#ifdef USE_POLARSSL
285
+ size_t buf_size = maxsize;
286
+ if(base64_encode((unsigned char *) output, &buf_size, input, length) == 0)
287
+ {
288
+ output[buf_size] = '\0';
289
+ return 1;
290
+ }
291
+ else
292
+ {
293
+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
294
+ return 0;
295
+ }
296
+#elif defined(USE_GNUTLS)
297
+ if (BASE64_ENCODE_RAW_LENGTH(length) <= maxsize)
298
+ base64_encode_raw((uint8_t*) output, length, input);
299
+ else
300
+ {
301
+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
302
+ return 0;
303
+ }
304
+#else /* USE_OPENSSL */
305
+ BIO *bmem, *b64;
306
+ BUF_MEM *bptr;
307
+
308
+ b64 = BIO_new(BIO_f_base64());
309
+ bmem = BIO_new(BIO_s_mem());
310
+ b64 = BIO_push(b64, bmem);
311
+ BIO_write(b64, input, length);
312
+ if (BIO_flush(b64) == 1)
313
+ {
314
+ BIO_get_mem_ptr(b64, &bptr);
315
+ memcpy(output, bptr->data, bptr->length-1);
316
+ output[bptr->length-1] = '\0';
317
+ }
318
+ else
319
+ {
320
+ RTMP_Log(RTMP_LOGDEBUG, "%s, error", __FUNCTION__);
321
+ return 0;
322
+ }
323
+ BIO_free_all(b64);
324
+#endif
325
+ return 1;
326
+}
327
+
328
+#ifdef USE_POLARSSL
329
+#define MD5_CTX md5_context
330
+#define MD5_Init(ctx) md5_starts(ctx)
331
+#define MD5_Update(ctx,data,len) md5_update(ctx,(unsigned char *)data,len)
332
+#define MD5_Final(dig,ctx) md5_finish(ctx,dig)
333
+#elif defined(USE_GNUTLS)
334
+typedef struct md5_ctx MD5_CTX
335
+#define MD5_Init(ctx) md5_init(ctx)
336
+#define MD5_Update(ctx,data,len) md5_update(ctx,len,data)
337
+#define MD5_Final(dig,ctx) md5_digest(ctx,MD5_DIGEST_LENGTH,dig)
338
+#else
339
+#endif
340
+
341
+static const AVal av_authmod_adobe = AVC("authmod=adobe");
342
+static const AVal av_authmod_llnw = AVC("authmod=llnw");
343
+
344
+static void hexenc(unsigned char *inbuf, int len, char *dst)
345
+{
346
+ char *ptr = dst;
347
+ while(len--) {
348
+ sprintf(ptr, "%02x", *inbuf++);
349
+ ptr += 2;
350
+ }
351
+ *ptr = '\0';
352
+}
353
+
354
+static int
355
+PublisherAuth(RTMP *r, AVal *description)
356
+{
357
+ char *token_in = NULL;
358
+ char *ptr;
359
+ unsigned char md5sum_val[MD5_DIGEST_LENGTH+1];
360
+ MD5_CTX md5ctx;
361
+ int challenge2_data;
362
+#define RESPONSE_LEN 32
363
+#define CHALLENGE2_LEN 16
364
+#define SALTED2_LEN (32+8+8+8)
365
+#define B64DIGEST_LEN 22 /* 16 byte digest => 22 b64 chars */
366
+#define B64INT_LEN 6 /* 4 byte int => 6 b64 chars */
367
+#define HEXHASH_LEN (2*MD5_DIGEST_LENGTH)
368
+ char response[RESPONSE_LEN];
369
+ char challenge2[CHALLENGE2_LEN];
370
+ char salted2[SALTED2_LEN];
371
+ AVal pubToken;
372
+
373
+ if (strstr(description->av_val, av_authmod_adobe.av_val) != NULL)
374
+ {
375
+ if(strstr(description->av_val, "code=403 need auth") != NULL)
376
+ {
377
+ if (strstr(r->Link.app.av_val, av_authmod_adobe.av_val) != NULL) {
378
+ RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__);
379
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
380
+ return 0;
381
+ } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) {
382
+ pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_adobe.av_len + 8);
383
+ pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s",
384
+ av_authmod_adobe.av_val,
385
+ r->Link.pubUser.av_val);
386
+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val);
387
+ r->Link.pFlags |= RTMP_PUB_NAME;
388
+ } else {
389
+ RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__);
390
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
391
+ return 0;
392
+ }
393
+ }
394
+ else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL)
395
+ {
396
+ char *par, *val = NULL, *orig_ptr;
397
+ AVal user, salt, opaque, challenge, *aptr = NULL;
398
+ opaque.av_len = 0;
399
+ challenge.av_len = 0;
400
+
401
+ ptr = orig_ptr = strdup(token_in);
402
+ while (ptr)
403
+ {
404
+ par = ptr;
405
+ ptr = strchr(par, '&');
406
+ if(ptr)
407
+ *ptr++ = '\0';
408
+
409
+ val = strchr(par, '=');
410
+ if(val)
411
+ *val++ = '\0';
412
+
413
+ if (aptr) {
414
+ aptr->av_len = par - aptr->av_val - 1;
415
+ aptr = NULL;
416
+ }
417
+ if (strcmp(par, "user") == 0){
418
+ user.av_val = val;
419
+ aptr = &user;
420
+ } else if (strcmp(par, "salt") == 0){
421
+ salt.av_val = val;
422
+ aptr = &salt;
423
+ } else if (strcmp(par, "opaque") == 0){
424
+ opaque.av_val = val;
425
+ aptr = &opaque;
426
+ } else if (strcmp(par, "challenge") == 0){
427
+ challenge.av_val = val;
428
+ aptr = &challenge;
429
+ }
430
+
431
+ RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
432
+ }
433
+ if (aptr)
434
+ aptr->av_len = strlen(aptr->av_val);
435
+
436
+ /* hash1 = base64enc(md5(user + _aodbeAuthSalt + password)) */
437
+ MD5_Init(&md5ctx);
438
+ MD5_Update(&md5ctx, user.av_val, user.av_len);
439
+ MD5_Update(&md5ctx, salt.av_val, salt.av_len);
440
+ MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
441
+ MD5_Final(md5sum_val, &md5ctx);
442
+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
443
+ user.av_val, salt.av_val, r->Link.pubPasswd.av_val);
444
+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
445
+
446
+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, salted2, SALTED2_LEN);
447
+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_1) = %s", __FUNCTION__, salted2);
448
+
449
+ /* FIXME: what byte order does this depend on? */
450
+ challenge2_data = rand();
451
+
452
+ b64enc((unsigned char *) &challenge2_data, sizeof(int), challenge2, CHALLENGE2_LEN);
453
+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(%d) = %s", __FUNCTION__, challenge2_data, challenge2);
454
+
455
+ MD5_Init(&md5ctx);
456
+ MD5_Update(&md5ctx, salted2, B64DIGEST_LEN);
457
+ /* response = base64enc(md5(hash1 + opaque + challenge2)) */
458
+ if (opaque.av_len)
459
+ MD5_Update(&md5ctx, opaque.av_val, opaque.av_len);
460
+ if (challenge.av_len)
461
+ MD5_Update(&md5ctx, challenge.av_val, challenge.av_len);
462
+ MD5_Update(&md5ctx, challenge2, B64INT_LEN);
463
+ MD5_Final(md5sum_val, &md5ctx);
464
+
465
+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s%s%s) =>", __FUNCTION__,
466
+ salted2, opaque.av_len ? opaque.av_val : "", challenge2);
467
+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
468
+
469
+ b64enc(md5sum_val, MD5_DIGEST_LENGTH, response, RESPONSE_LEN);
470
+ RTMP_Log(RTMP_LOGDEBUG, "%s, b64(md5_2) = %s", __FUNCTION__, response);
471
+
472
+ /* have all hashes, create auth token for the end of app */
473
+ pubToken.av_val = malloc(32 + B64INT_LEN + B64DIGEST_LEN + opaque.av_len);
474
+ pubToken.av_len = sprintf(pubToken.av_val,
475
+ "&challenge=%s&response=%s&opaque=%s",
476
+ challenge2,
477
+ response,
478
+ opaque.av_len ? opaque.av_val : "");
479
+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
480
+ free(orig_ptr);
481
+ r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE;
482
+ }
483
+ else if(strstr(description->av_val, "?reason=authfailed") != NULL)
484
+ {
485
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: wrong password", __FUNCTION__);
486
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
487
+ return 0;
488
+ }
489
+ else if(strstr(description->av_val, "?reason=nosuchuser") != NULL)
490
+ {
491
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__);
492
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
493
+ return 0;
494
+ }
495
+ else
496
+ {
497
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s",
498
+ __FUNCTION__, description->av_val);
499
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
500
+ return 0;
501
+ }
502
+
503
+ ptr = malloc(r->Link.app.av_len + pubToken.av_len);
504
+ strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len);
505
+ strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len);
506
+ r->Link.app.av_len += pubToken.av_len;
507
+ if(r->Link.pFlags & RTMP_PUB_ALLOC)
508
+ free(r->Link.app.av_val);
509
+ r->Link.app.av_val = ptr;
510
+
511
+ ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len);
512
+ strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len);
513
+ strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len);
514
+ r->Link.tcUrl.av_len += pubToken.av_len;
515
+ if(r->Link.pFlags & RTMP_PUB_ALLOC)
516
+ free(r->Link.tcUrl.av_val);
517
+ r->Link.tcUrl.av_val = ptr;
518
+
519
+ free(pubToken.av_val);
520
+ r->Link.pFlags |= RTMP_PUB_ALLOC;
521
+
522
+ RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__,
523
+ r->Link.app.av_len, r->Link.app.av_val,
524
+ r->Link.tcUrl.av_len, r->Link.tcUrl.av_val,
525
+ r->Link.playpath.av_val);
526
+ }
527
+ else if (strstr(description->av_val, av_authmod_llnw.av_val) != NULL)
528
+ {
529
+ if(strstr(description->av_val, "code=403 need auth") != NULL)
530
+ {
531
+ /* This part seems to be the same for llnw and adobe */
532
+
533
+ if (strstr(r->Link.app.av_val, av_authmod_llnw.av_val) != NULL) {
534
+ RTMP_Log(RTMP_LOGERROR, "%s, wrong pubUser & pubPasswd for publisher auth", __FUNCTION__);
535
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
536
+ return 0;
537
+ } else if(r->Link.pubUser.av_len && r->Link.pubPasswd.av_len) {
538
+ pubToken.av_val = malloc(r->Link.pubUser.av_len + av_authmod_llnw.av_len + 8);
539
+ pubToken.av_len = sprintf(pubToken.av_val, "?%s&user=%s",
540
+ av_authmod_llnw.av_val,
541
+ r->Link.pubUser.av_val);
542
+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken1: %s", __FUNCTION__, pubToken.av_val);
543
+ r->Link.pFlags |= RTMP_PUB_NAME;
544
+ } else {
545
+ RTMP_Log(RTMP_LOGERROR, "%s, need to set pubUser & pubPasswd for publisher auth", __FUNCTION__);
546
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
547
+ return 0;
548
+ }
549
+ }
550
+ else if((token_in = strstr(description->av_val, "?reason=needauth")) != NULL)
551
+ {
552
+ char *orig_ptr;
553
+ char *par, *val = NULL;
554
+ char hash1[HEXHASH_LEN+1], hash2[HEXHASH_LEN+1], hash3[HEXHASH_LEN+1];
555
+ AVal user, nonce, *aptr = NULL;
556
+ AVal apptmp;
557
+
558
+ /* llnw auth method
559
+ * Seems to be closely based on HTTP Digest Auth:
560
+ * http://tools.ietf.org/html/rfc2617
561
+ * http://en.wikipedia.org/wiki/Digest_access_authentication
562
+ */
563
+
564
+ const char authmod[] = "llnw";
565
+ const char realm[] = "live";
566
+ const char method[] = "publish";
567
+ const char qop[] = "auth";
568
+ /* nc = 1..connection count (or rather, number of times cnonce has been reused) */
569
+ int nc = 1;
570
+ /* nchex = hexenc(nc) (8 hex digits according to RFC 2617) */
571
+ char nchex[9];
572
+ /* cnonce = hexenc(4 random bytes) (initialized on first connection) */
573
+ char cnonce[9];
574
+
575
+ ptr = orig_ptr = strdup(token_in);
576
+ /* Extract parameters (we need user and nonce) */
577
+ while (ptr)
578
+ {
579
+ par = ptr;
580
+ ptr = strchr(par, '&');
581
+ if(ptr)
582
+ *ptr++ = '\0';
583
+
584
+ val = strchr(par, '=');
585
+ if(val)
586
+ *val++ = '\0';
587
+
588
+ if (aptr) {
589
+ aptr->av_len = par - aptr->av_val - 1;
590
+ aptr = NULL;
591
+ }
592
+ if (strcmp(par, "user") == 0){
593
+ user.av_val = val;
594
+ aptr = &user;
595
+ } else if (strcmp(par, "nonce") == 0){
596
+ nonce.av_val = val;
597
+ aptr = &nonce;
598
+ }
599
+
600
+ RTMP_Log(RTMP_LOGDEBUG, "%s, par:\"%s\" = val:\"%s\"", __FUNCTION__, par, val);
601
+ }
602
+ if (aptr)
603
+ aptr->av_len = strlen(aptr->av_val);
604
+
605
+ /* FIXME: handle case where user==NULL or nonce==NULL */
606
+
607
+ sprintf(nchex, "%08x", nc);
608
+ sprintf(cnonce, "%08x", rand());
609
+
610
+ /* hash1 = hexenc(md5(user + ":" + realm + ":" + password)) */
611
+ MD5_Init(&md5ctx);
612
+ MD5_Update(&md5ctx, user.av_val, user.av_len);
613
+ MD5_Update(&md5ctx, ":", 1);
614
+ MD5_Update(&md5ctx, realm, sizeof(realm)-1);
615
+ MD5_Update(&md5ctx, ":", 1);
616
+ MD5_Update(&md5ctx, r->Link.pubPasswd.av_val, r->Link.pubPasswd.av_len);
617
+ MD5_Final(md5sum_val, &md5ctx);
618
+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s) =>", __FUNCTION__,
619
+ user.av_val, realm, r->Link.pubPasswd.av_val);
620
+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
621
+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash1);
622
+
623
+ /* hash2 = hexenc(md5(method + ":/" + app + "/" + appInstance)) */
624
+ /* Extract appname + appinstance without query parameters */
625
+ apptmp = r->Link.app;
626
+ ptr = strchr(apptmp.av_val, '?');
627
+ if (ptr)
628
+ apptmp.av_len = ptr - apptmp.av_val;
629
+
630
+ MD5_Init(&md5ctx);
631
+ MD5_Update(&md5ctx, method, sizeof(method)-1);
632
+ MD5_Update(&md5ctx, ":/", 2);
633
+ MD5_Update(&md5ctx, apptmp.av_val, apptmp.av_len);
634
+ MD5_Final(md5sum_val, &md5ctx);
635
+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:/%.*s) =>", __FUNCTION__,
636
+ method, apptmp.av_len, apptmp.av_val);
637
+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
638
+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash2);
639
+
640
+ /* hash3 = hexenc(md5(hash1 + ":" + nonce + ":" + nchex + ":" + cnonce + ":" + qop + ":" + hash2)) */
641
+ MD5_Init(&md5ctx);
642
+ MD5_Update(&md5ctx, hash1, HEXHASH_LEN);
643
+ MD5_Update(&md5ctx, ":", 1);
644
+ MD5_Update(&md5ctx, nonce.av_val, nonce.av_len);
645
+ MD5_Update(&md5ctx, ":", 1);
646
+ MD5_Update(&md5ctx, nchex, sizeof(nchex)-1);
647
+ MD5_Update(&md5ctx, ":", 1);
648
+ MD5_Update(&md5ctx, cnonce, sizeof(cnonce)-1);
649
+ MD5_Update(&md5ctx, ":", 1);
650
+ MD5_Update(&md5ctx, qop, sizeof(qop)-1);
651
+ MD5_Update(&md5ctx, ":", 1);
652
+ MD5_Update(&md5ctx, hash2, HEXHASH_LEN);
653
+ MD5_Final(md5sum_val, &md5ctx);
654
+ RTMP_Log(RTMP_LOGDEBUG, "%s, md5(%s:%s:%s:%s:%s:%s) =>", __FUNCTION__,
655
+ hash1, nonce.av_val, nchex, cnonce, qop, hash2);
656
+ RTMP_LogHexString(RTMP_LOGDEBUG, md5sum_val, MD5_DIGEST_LENGTH);
657
+ hexenc(md5sum_val, MD5_DIGEST_LENGTH, hash3);
658
+
659
+ /* pubToken = &authmod=<authmod>&user=<username>&nonce=<nonce>&cnonce=<cnonce>&nc=<nchex>&response=<hash3> */
660
+ /* Append nonces and response to query string which already contains
661
+ * user + authmod */
662
+ pubToken.av_val = malloc(64 + sizeof(authmod)-1 + user.av_len + nonce.av_len + sizeof(cnonce)-1 + sizeof(nchex)-1 + HEXHASH_LEN);
663
+ sprintf(pubToken.av_val,
664
+ "&nonce=%s&cnonce=%s&nc=%s&response=%s",
665
+ nonce.av_val, cnonce, nchex, hash3);
666
+ pubToken.av_len = strlen(pubToken.av_val);
667
+ RTMP_Log(RTMP_LOGDEBUG, "%s, pubToken2: %s", __FUNCTION__, pubToken.av_val);
668
+ r->Link.pFlags |= RTMP_PUB_RESP|RTMP_PUB_CLATE;
669
+
670
+ free(orig_ptr);
671
+ }
672
+ else if(strstr(description->av_val, "?reason=authfail") != NULL)
673
+ {
674
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed", __FUNCTION__);
675
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
676
+ return 0;
677
+ }
678
+ else if(strstr(description->av_val, "?reason=nosuchuser") != NULL)
679
+ {
680
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: no such user", __FUNCTION__);
681
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
682
+ return 0;
683
+ }
684
+ else
685
+ {
686
+ RTMP_Log(RTMP_LOGERROR, "%s, Authentication failed: unknown auth mode: %s",
687
+ __FUNCTION__, description->av_val);
688
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
689
+ return 0;
690
+ }
691
+
692
+ ptr = malloc(r->Link.app.av_len + pubToken.av_len);
693
+ strncpy(ptr, r->Link.app.av_val, r->Link.app.av_len);
694
+ strncpy(ptr + r->Link.app.av_len, pubToken.av_val, pubToken.av_len);
695
+ r->Link.app.av_len += pubToken.av_len;
696
+ if(r->Link.pFlags & RTMP_PUB_ALLOC)
697
+ free(r->Link.app.av_val);
698
+ r->Link.app.av_val = ptr;
699
+
700
+ ptr = malloc(r->Link.tcUrl.av_len + pubToken.av_len);
701
+ strncpy(ptr, r->Link.tcUrl.av_val, r->Link.tcUrl.av_len);
702
+ strncpy(ptr + r->Link.tcUrl.av_len, pubToken.av_val, pubToken.av_len);
703
+ r->Link.tcUrl.av_len += pubToken.av_len;
704
+ if(r->Link.pFlags & RTMP_PUB_ALLOC)
705
+ free(r->Link.tcUrl.av_val);
706
+ r->Link.tcUrl.av_val = ptr;
707
+
708
+ free(pubToken.av_val);
709
+ r->Link.pFlags |= RTMP_PUB_ALLOC;
710
+
711
+ RTMP_Log(RTMP_LOGDEBUG, "%s, new app: %.*s tcUrl: %.*s playpath: %s", __FUNCTION__,
712
+ r->Link.app.av_len, r->Link.app.av_val,
713
+ r->Link.tcUrl.av_len, r->Link.tcUrl.av_val,
714
+ r->Link.playpath.av_val);
715
+ }
716
+ else
717
+ {
718
+ return 0;
719
+ }
720
+ return 1;
721
+}
722
+#endif
723
+
724
+
725
SAVC(onBWDone);
726
SAVC(onFCSubscribe);
727
SAVC(onFCUnsubscribe);
728
729
SAVC(close);
730
SAVC(code);
731
SAVC(level);
732
+SAVC(description);
733
SAVC(onStatus);
734
SAVC(playlist_ready);
735
static const AVal av_NetStream_Failed = AVC("NetStream.Failed");
736
737
static const AVal av_NetStream_Play_UnpublishNotify =
738
AVC("NetStream.Play.UnpublishNotify");
739
static const AVal av_NetStream_Publish_Start = AVC("NetStream.Publish.Start");
740
+static const AVal av_NetConnection_Connect_Rejected =
741
+AVC("NetConnection.Connect.Rejected");
742
743
/* Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' */
744
static int
745
746
}
747
else if (AVMATCH(&method, &av__error))
748
{
749
+#ifdef CRYPTO
750
+ AVal methodInvoked = {0};
751
+ int i;
752
+
753
+ if (r->Link.protocol & RTMP_FEATURE_WRITE)
754
+ {
755
+ for (i=0; i<r->m_numCalls; i++)
756
+ {
757
+ if (r->m_methodCalls[i].num == txn)
758
+ {
759
+ methodInvoked = r->m_methodCalls[i].name;
760
+ AV_erase(r->m_methodCalls, &r->m_numCalls, i, FALSE);
761
+ break;
762
+ }
763
+ }
764
+ if (!methodInvoked.av_val)
765
+ {
766
+ RTMP_Log(RTMP_LOGDEBUG, "%s, received result id %f without matching request",
767
+ __FUNCTION__, txn);
768
+ goto leave;
769
+ }
770
+
771
+ RTMP_Log(RTMP_LOGDEBUG, "%s, received error for method call <%s>", __FUNCTION__,
772
+ methodInvoked.av_val);
773
+
774
+ if (AVMATCH(&methodInvoked, &av_connect))
775
+ {
776
+ AMFObject obj2;
777
+ AVal code, level, description;
778
+ AMFProp_GetObject(AMF_GetProp(&obj, NULL, 3), &obj2);
779
+ AMFProp_GetString(AMF_GetProp(&obj2, &av_code, -1), &code);
780
+ AMFProp_GetString(AMF_GetProp(&obj2, &av_level, -1), &level);
781
+ AMFProp_GetString(AMF_GetProp(&obj2, &av_description, -1), &description);
782
+ RTMP_Log(RTMP_LOGDEBUG, "%s, error description: %s", __FUNCTION__, description.av_val);
783
+ /* if PublisherAuth returns 1, then reconnect */
784
+ PublisherAuth(r, &description);
785
+ }
786
+ }
787
+ else
788
+ {
789
+ RTMP_Log(RTMP_LOGERROR, "rtmp server sent error");
790
+ }
791
+ free(methodInvoked.av_val);
792
+#else
793
RTMP_Log(RTMP_LOGERROR, "rtmp server sent error");
794
+#endif
795
}
796
else if (AVMATCH(&method, &av_close))
797
{
798
RTMP_Log(RTMP_LOGERROR, "rtmp server requested close");
799
RTMP_Close(r);
800
+#ifdef CRYPTO
801
+ if ((r->Link.protocol & RTMP_FEATURE_WRITE) &&
802
+ !(r->Link.pFlags & RTMP_PUB_CLEAN) &&
803
+ ( !(r->Link.pFlags & RTMP_PUB_NAME) ||
804
+ !(r->Link.pFlags & RTMP_PUB_RESP) ||
805
+ (r->Link.pFlags & RTMP_PUB_CLATE) ) )
806
+ {
807
+ /* clean later */
808
+ if(r->Link.pFlags & RTMP_PUB_CLATE)
809
+ r->Link.pFlags |= RTMP_PUB_CLEAN;
810
+ RTMP_Log(RTMP_LOGERROR, "authenticating publisher");
811
+
812
+ if (!RTMP_Connect(r, NULL) || !RTMP_ConnectStream(r, 0))
813
+ goto leave;
814
+ }
815
+#endif
816
}
817
else if (AVMATCH(&method, &av_onStatus))
818
{
819
820
break;
821
if (!r->m_pausing)
822
{
823
- r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel];
824
+ r->m_pauseStamp = r->m_mediaChannel < r->m_channelsAllocatedIn ?
825
+ r->m_channelTimestamp[r->m_mediaChannel] : 0;
826
RTMP_SendPause(r, TRUE, r->m_pauseStamp);
827
r->m_pausing = 1;
828
}
829
830
831
nSize = packetSize[packet->m_headerType];
832
833
+ if (packet->m_nChannel >= r->m_channelsAllocatedIn)
834
+ {
835
+ int n = packet->m_nChannel + 10;
836
+ int *timestamp = realloc(r->m_channelTimestamp, sizeof(int) * n);
837
+ RTMPPacket **packets = realloc(r->m_vecChannelsIn, sizeof(RTMPPacket*) * n);
838
+ if (!timestamp)
839
+ free(r->m_channelTimestamp);
840
+ if (!packets)
841
+ free(r->m_vecChannelsIn);
842
+ r->m_channelTimestamp = timestamp;
843
+ r->m_vecChannelsIn = packets;
844
+ if (!timestamp || !packets) {
845
+ r->m_channelsAllocatedIn = 0;
846
+ return FALSE;
847
+ }
848
+ memset(r->m_channelTimestamp + r->m_channelsAllocatedIn, 0, sizeof(int) * (n - r->m_channelsAllocatedIn));
849
+ memset(r->m_vecChannelsIn + r->m_channelsAllocatedIn, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedIn));
850
+ r->m_channelsAllocatedIn = n;
851
+ }
852
+
853
if (nSize == RTMP_LARGE_HEADER_SIZE) /* if we get a full header the timestamp is absolute */
854
packet->m_hasAbsTimestamp = TRUE;
855
856
857
int
858
RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue)
859
{
860
- const RTMPPacket *prevPacket = r->m_vecChannelsOut[packet->m_nChannel];
861
+ const RTMPPacket *prevPacket;
862
uint32_t last = 0;
863
int nSize;
864
int hSize, cSize;
865
866
int nChunkSize;
867
int tlen;
868
869
+ if (packet->m_nChannel >= r->m_channelsAllocatedOut)
870
+ {
871
+ int n = packet->m_nChannel + 10;
872
+ RTMPPacket **packets = realloc(r->m_vecChannelsOut, sizeof(RTMPPacket*) * n);
873
+ if (!packets) {
874
+ free(r->m_vecChannelsOut);
875
+ r->m_vecChannelsOut = NULL;
876
+ r->m_channelsAllocatedOut = 0;
877
+ return FALSE;
878
+ }
879
+ r->m_vecChannelsOut = packets;
880
+ memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut));
881
+ r->m_channelsAllocatedOut = n;
882
+ }
883
+
884
+ prevPacket = r->m_vecChannelsOut[packet->m_nChannel];
885
if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE)
886
{
887
/* compress a bit by using the prev packet's attributes */
888
889
r->m_write.m_nBytesRead = 0;
890
RTMPPacket_Free(&r->m_write);
891
892
- for (i = 0; i < RTMP_CHANNELS; i++)
893
+ for (i = 0; i < r->m_channelsAllocatedIn; i++)
894
{
895
if (r->m_vecChannelsIn[i])
896
{
897
898
free(r->m_vecChannelsIn[i]);
899
r->m_vecChannelsIn[i] = NULL;
900
}
901
+ }
902
+ free(r->m_vecChannelsIn);
903
+ r->m_vecChannelsIn = NULL;
904
+ free(r->m_channelTimestamp);
905
+ r->m_channelTimestamp = NULL;
906
+ r->m_channelsAllocatedIn = 0;
907
+ for (i = 0; i < r->m_channelsAllocatedOut; i++)
908
+ {
909
if (r->m_vecChannelsOut[i])
910
{
911
free(r->m_vecChannelsOut[i]);
912
r->m_vecChannelsOut[i] = NULL;
913
}
914
}
915
+ free(r->m_vecChannelsOut);
916
+ r->m_vecChannelsOut = NULL;
917
+ r->m_channelsAllocatedOut = 0;
918
AV_clear(r->m_methodCalls, r->m_numCalls);
919
r->m_methodCalls = NULL;
920
r->m_numCalls = 0;
921
922
r->m_resplen = 0;
923
r->m_unackd = 0;
924
925
- free(r->Link.playpath0.av_val);
926
- r->Link.playpath0.av_val = NULL;
927
-
928
if (r->Link.lFlags & RTMP_LF_FTCU)
929
{
930
free(r->Link.tcUrl.av_val);
931
932
}
933
934
#ifdef CRYPTO
935
+ if (!(r->Link.protocol & RTMP_FEATURE_WRITE) || (r->Link.pFlags & RTMP_PUB_CLEAN))
936
+ {
937
+ free(r->Link.playpath0.av_val);
938
+ r->Link.playpath0.av_val = NULL;
939
+ }
940
+ if ((r->Link.protocol & RTMP_FEATURE_WRITE) &&
941
+ (r->Link.pFlags & RTMP_PUB_CLEAN) &&
942
+ (r->Link.pFlags & RTMP_PUB_ALLOC))
943
+ {
944
+ free(r->Link.app.av_val);
945
+ r->Link.app.av_val = NULL;
946
+ free(r->Link.tcUrl.av_val);
947
+ r->Link.tcUrl.av_val = NULL;
948
+ }
949
if (r->Link.dh)
950
{
951
MDH_free(r->Link.dh);
952
953
RC4_free(r->Link.rc4keyOut);
954
r->Link.rc4keyOut = NULL;
955
}
956
+#else
957
+ free(r->Link.playpath0.av_val);
958
+ r->Link.playpath0.av_val = NULL;
959
#endif
960
}
961
962
963
964
while (1)
965
{
966
- nBytes = sizeof(sb->sb_buf) - sb->sb_size - (sb->sb_start - sb->sb_buf);
967
+ nBytes = sizeof(sb->sb_buf) - 1 - sb->sb_size - (sb->sb_start - sb->sb_buf);
968
#if defined(CRYPTO) && !defined(NO_SSL)
969
if (sb->sb_ssl)
970
{
971
972
int hlen = snprintf(hbuf, sizeof(hbuf), "POST /%s%s/%d HTTP/1.1\r\n"
973
"Host: %.*s:%d\r\n"
974
"Accept: */*\r\n"
975
- "User-Agent: Shockwave Flash\n"
976
- "Connection: Keep-Alive\n"
977
+ "User-Agent: Shockwave Flash\r\n"
978
+ "Connection: Keep-Alive\r\n"
979
"Cache-Control: no-cache\r\n"
980
"Content-type: application/x-fcs\r\n"
981
"Content-length: %d\r\n\r\n", RTMPT_cmds[cmd],
982
983
char *ptr;
984
int hlen;
985
986
+restart:
987
if (fill)
988
RTMPSockBuf_Fill(&r->m_sb);
989
- if (r->m_sb.sb_size < 144)
990
+ if (r->m_sb.sb_size < 13) {
991
+ if (fill)
992
+ goto restart;
993
return -2;
994
+ }
995
if (strncmp(r->m_sb.sb_start, "HTTP/1.1 200 ", 13))
996
return -1;
997
+ r->m_sb.sb_start[r->m_sb.sb_size] = '\0';
998
+ if (!strstr(r->m_sb.sb_start, "\r\n\r\n")) {
999
+ if (fill)
1000
+ goto restart;
1001
+ return -2;
1002
+ }
1003
+
1004
ptr = r->m_sb.sb_start + sizeof("HTTP/1.1 200");
1005
while ((ptr = strstr(ptr, "Content-"))) {
1006
if (!strncasecmp(ptr+8, "length:", 7)) break;
1007
1008
if (!ptr)
1009
return -1;
1010
ptr += 4;
1011
+ if (ptr + (r->m_clientID.av_val ? 1 : hlen) > r->m_sb.sb_start + r->m_sb.sb_size)
1012
+ {
1013
+ if (fill)
1014
+ goto restart;
1015
+ return -2;
1016
+ }
1017
r->m_sb.sb_size -= ptr - r->m_sb.sb_start;
1018
r->m_sb.sb_start = ptr;
1019
r->m_unackd--;
1020
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/rtmp.h -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/rtmp.h
Changed
57
1
2
AVal subscribepath;
3
AVal usherToken;
4
AVal token;
5
+ AVal pubUser;
6
+ AVal pubPasswd;
7
AMFObject extras;
8
int edepth;
9
10
11
int protocol;
12
int timeout; /* connection timeout in seconds */
13
14
+#define RTMP_PUB_NAME 0x0001 /* send login to server */
15
+#define RTMP_PUB_RESP 0x0002 /* send salted password hash */
16
+#define RTMP_PUB_ALLOC 0x0004 /* allocated data for new tcUrl & app */
17
+#define RTMP_PUB_CLEAN 0x0008 /* need to free allocated data for newer tcUrl & app at exit */
18
+#define RTMP_PUB_CLATE 0x0010 /* late clean tcUrl & app at exit */
19
+ int pFlags;
20
+
21
unsigned short socksport;
22
unsigned short port;
23
24
25
int m_numCalls;
26
RTMP_METHOD *m_methodCalls; /* remote method calls queue */
27
28
- RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS];
29
- RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS];
30
- int m_channelTimestamp[RTMP_CHANNELS]; /* abs timestamp of last packet */
31
+ int m_channelsAllocatedIn;
32
+ int m_channelsAllocatedOut;
33
+ RTMPPacket **m_vecChannelsIn;
34
+ RTMPPacket **m_vecChannelsOut;
35
+ int *m_channelTimestamp; /* abs timestamp of last packet */
36
37
double m_fAudioCodecs; /* audioCodecs for the connect packet */
38
double m_fVideoCodecs; /* videoCodecs for the connect packet */
39
40
int RTMP_Connect0(RTMP *r, struct sockaddr *svc);
41
int RTMP_Connect1(RTMP *r, RTMPPacket *cp);
42
int RTMP_Serve(RTMP *r);
43
+ int RTMP_TLS_Accept(RTMP *r, void *ctx);
44
45
int RTMP_ReadPacket(RTMP *r, RTMPPacket *packet);
46
int RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue);
47
48
void RTMP_Free(RTMP *r);
49
void RTMP_EnableWrite(RTMP *r);
50
51
+ void *RTMP_TLS_AllocServerContext(const char* cert, const char* key);
52
+ void RTMP_TLS_FreeServerContext(void *ctx);
53
+
54
int RTMP_LibVersion(void);
55
void RTMP_UserInterrupt(void); /* user typed Ctrl-C */
56
57
rtmpdump-2.3.99.git20111114.tar.bz2/librtmp/rtmp_sys.h -> rtmpdump-2.4.git20121102.tar.bz2/librtmp/rtmp_sys.h
Changed
66
1
2
#include "rtmp.h"
3
4
#ifdef USE_POLARSSL
5
+#include <polarssl/version.h>
6
#include <polarssl/net.h>
7
#include <polarssl/ssl.h>
8
#include <polarssl/havege.h>
9
+#if POLARSSL_VERSION_NUMBER < 0x01010000
10
+#define havege_random havege_rand
11
+#endif
12
typedef struct tls_ctx {
13
havege_state hs;
14
ssl_session ssn;
15
} tls_ctx;
16
+typedef struct tls_server_ctx {
17
+ havege_state *hs;
18
+ x509_cert cert;
19
+ rsa_context key;
20
+ ssl_session ssn;
21
+ const char *dhm_P, *dhm_G;
22
+} tls_server_ctx;
23
+
24
#define TLS_CTX tls_ctx *
25
#define TLS_client(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
26
ssl_set_endpoint(s, SSL_IS_CLIENT); ssl_set_authmode(s, SSL_VERIFY_NONE);\
27
- ssl_set_rng(s, havege_rand, &ctx->hs);\
28
+ ssl_set_rng(s, havege_random, &ctx->hs);\
29
ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
30
ssl_set_session(s, 1, 600, &ctx->ssn)
31
+#define TLS_server(ctx,s) s = malloc(sizeof(ssl_context)); ssl_init(s);\
32
+ ssl_set_endpoint(s, SSL_IS_SERVER); ssl_set_authmode(s, SSL_VERIFY_NONE);\
33
+ ssl_set_rng(s, havege_random, ((tls_server_ctx*)ctx)->hs);\
34
+ ssl_set_ciphersuites(s, ssl_default_ciphersuites);\
35
+ ssl_set_session(s, 1, 600, &((tls_server_ctx*)ctx)->ssn);\
36
+ ssl_set_own_cert(s, &((tls_server_ctx*)ctx)->cert, &((tls_server_ctx*)ctx)->key);\
37
+ ssl_set_dh_param(s, ((tls_server_ctx*)ctx)->dhm_P, ((tls_server_ctx*)ctx)->dhm_G)
38
#define TLS_setfd(s,fd) ssl_set_bio(s, net_recv, &fd, net_send, &fd)
39
#define TLS_connect(s) ssl_handshake(s)
40
+#define TLS_accept(s) ssl_handshake(s)
41
#define TLS_read(s,b,l) ssl_read(s,(unsigned char *)b,l)
42
#define TLS_write(s,b,l) ssl_write(s,(unsigned char *)b,l)
43
#define TLS_shutdown(s) ssl_close_notify(s)
44
45
} tls_ctx;
46
#define TLS_CTX tls_ctx *
47
#define TLS_client(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_CLIENT); gnutls_priority_set(s, ctx->prios); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx->cred)
48
+#define TLS_server(ctx,s) gnutls_init((gnutls_session_t *)(&s), GNUTLS_SERVER); gnutls_priority_set_direct(s, "NORMAL", NULL); gnutls_credentials_set(s, GNUTLS_CRD_CERTIFICATE, ctx)
49
#define TLS_setfd(s,fd) gnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)(long)fd)
50
#define TLS_connect(s) gnutls_handshake(s)
51
+#define TLS_accept(s) gnutls_handshake(s)
52
#define TLS_read(s,b,l) gnutls_record_recv(s,b,l)
53
#define TLS_write(s,b,l) gnutls_record_send(s,b,l)
54
#define TLS_shutdown(s) gnutls_bye(s, GNUTLS_SHUT_RDWR)
55
56
#else /* USE_OPENSSL */
57
#define TLS_CTX SSL_CTX *
58
#define TLS_client(ctx,s) s = SSL_new(ctx)
59
+#define TLS_server(ctx,s) s = SSL_new(ctx)
60
#define TLS_setfd(s,fd) SSL_set_fd(s,fd)
61
#define TLS_connect(s) SSL_connect(s)
62
+#define TLS_accept(s) SSL_accept(s)
63
#define TLS_read(s,b,l) SSL_read(s,b,l)
64
#define TLS_write(s,b,l) SSL_write(s,b,l)
65
#define TLS_shutdown(s) SSL_shutdown(s)
66
rtmpdump-2.3.99.git20111114.tar.bz2/rtmpdump.1 -> rtmpdump-2.4.git20121102.tar.bz2/rtmpdump.1
Changed
20
1
2
-.TH RTMPDUMP 1 "2011-07-20" "RTMPDump v2.4"
3
+.TH RTMPDUMP 1 "2012-07-24" "RTMPDump v2.4"
4
.\" Copyright 2011 Howard Chu.
5
.\" Copying permitted according to the GNU General Public License V2.
6
.SH NAME
7
8
Name of live stream to subscribe to. Defaults to
9
.IR playpath .
10
.TP
11
+.B \-\-realtime \-R
12
+Download approximately in realtime, without attempting to speed up via
13
+Pause/Unpause commands ("the BUFX hack").
14
+Useful for servers that jump backwards in time at the Unpause command.
15
+Resuming and seeking in realtime streams is still possible.
16
+.TP
17
.B \-\-resume \-e
18
Resume an incomplete RTMP download.
19
.TP
20
rtmpdump-2.3.99.git20111114.tar.bz2/rtmpdump.1.html -> rtmpdump-2.4.git20121102.tar.bz2/rtmpdump.1.html
Changed
34
1
2
<tr><td>RTMPDUMP(1)<td align="center"><td align="right">RTMPDUMP(1)
3
</thead>
4
<tfoot>
5
-<tr><td>RTMPDump v2.4<td align="center">2011-07-20<td align="right">RTMPDUMP(1)
6
+<tr><td>RTMPDump v2.4<td align="center">2012-07-24<td align="right">RTMPDUMP(1)
7
</tfoot>
8
<tbody><tr><td colspan="3"><br><br><ul>
9
<!-- Copyright 2011 Howard Chu.
10
11
[<b>−y</b><i> playpath</i>]
12
[<b>−Y</b>]
13
[<b>−v</b>]
14
+[<b>−R</b>]
15
[<b>−d</b><i> subscription</i>]
16
[<b>−e</b>]
17
[<b>−k</b><i> skip</i>]
18
19
</dl>
20
<p>
21
<dl compact><dt>
22
+<b>−−realtime −R</b>
23
+<dd>
24
+Download approximately in realtime, without attempting to speed up via
25
+Pause/Unpause commands ("the BUFX hack").
26
+Useful for servers that jump backwards in time at the Unpause command.
27
+Resuming and seeking in realtime streams is still possible.
28
+</dl>
29
+<p>
30
+<dl compact><dt>
31
<b>−−resume −e</b>
32
<dd>
33
Resume an incomplete RTMP download.
34
rtmpdump-2.3.99.git20111114.tar.bz2/rtmpdump.c -> rtmpdump-2.4.git20121102.tar.bz2/rtmpdump.c
Changed
192
1
2
3
int
4
Download(RTMP * rtmp, // connected RTMP object
5
- FILE * file, uint32_t dSeek, uint32_t dStopOffset, double duration, int bResume, char *metaHeader, uint32_t nMetaHeaderSize, char *initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, int bStdoutMode, int bLiveStream, int bHashes, int bOverrideBufferTime, uint32_t bufferTime, double *percent) // percentage downloaded [out]
6
+ FILE * file, uint32_t dSeek, uint32_t dStopOffset, double duration, int bResume, char *metaHeader, uint32_t nMetaHeaderSize, char *initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, int bStdoutMode, int bLiveStream, int bRealtimeStream, int bHashes, int bOverrideBufferTime, uint32_t bufferTime, double *percent) // percentage downloaded [out]
7
{
8
int32_t now, lastUpdate;
9
int bufferSize = 64 * 1024;
10
11
bResume ? "Resuming" : "Starting",
12
(double) size / 1024.0);
13
}
14
+ if (bRealtimeStream)
15
+ RTMP_LogPrintf(" in approximately realtime (disabled BUFX speedup hack)\n");
16
}
17
18
if (dStopOffset > 0)
19
20
}
21
}
22
}
23
-#ifdef _DEBUG
24
else
25
{
26
+#ifdef _DEBUG
27
RTMP_Log(RTMP_LOGDEBUG, "zero read!");
28
- }
29
#endif
30
+ if (rtmp->m_read.status == RTMP_READ_EOF)
31
+ break;
32
+ }
33
34
}
35
while (!RTMP_ctrlC && nRead > -1 && RTMP_IsConnected(rtmp) && !RTMP_IsTimedout(rtmp));
36
37
("\n%s: This program dumps the media content streamed over RTMP.\n\n", prog);
38
RTMP_LogPrintf("--help|-h Prints this help screen.\n");
39
RTMP_LogPrintf
40
+ ("--url|-i url URL with options included (e.g. rtmp://host[:port]/path swfUrl=url tcUrl=url)\n");
41
+ RTMP_LogPrintf
42
("--rtmp|-r url URL (e.g. rtmp://host[:port]/path)\n");
43
RTMP_LogPrintf
44
("--host|-n hostname Overrides the hostname in the rtmp url\n");
45
46
RTMP_LogPrintf
47
("--subscribe|-d string Stream name to subscribe to (otherwise defaults to playpath if live is specifed)\n");
48
RTMP_LogPrintf
49
+ ("--realtime|-R Don't attempt to speed up download via the Pause/Unpause BUFX hack\n");
50
+ RTMP_LogPrintf
51
("--flv|-o string FLV output file name, if the file name is - print stream to stdout\n");
52
RTMP_LogPrintf
53
("--resume|-e Resume a partial RTMP download\n");
54
55
int protocol = RTMP_PROTOCOL_UNDEFINED;
56
int retries = 0;
57
int bLiveStream = FALSE; // is it a live stream? then we can't seek/resume
58
+ int bRealtimeStream = FALSE; // If true, disable the BUFX hack (be patient)
59
int bHashes = FALSE; // display byte counters not hashes by default
60
61
long int timeout = DEF_TIMEOUT; // timeout connection after 120 seconds
62
63
uint32_t dStopOffset = 0;
64
RTMP rtmp = { 0 };
65
66
+ AVal fullUrl = { 0, 0 };
67
AVal swfUrl = { 0, 0 };
68
AVal tcUrl = { 0, 0 };
69
AVal pageUrl = { 0, 0 };
70
71
{"protocol", 1, NULL, 'l'},
72
{"playpath", 1, NULL, 'y'},
73
{"playlist", 0, NULL, 'Y'},
74
+ {"url", 1, NULL, 'i'},
75
{"rtmp", 1, NULL, 'r'},
76
{"swfUrl", 1, NULL, 's'},
77
{"tcUrl", 1, NULL, 't'},
78
79
#endif
80
{"flashVer", 1, NULL, 'f'},
81
{"live", 0, NULL, 'v'},
82
+ {"realtime", 0, NULL, 'R'},
83
{"flv", 1, NULL, 'o'},
84
{"resume", 0, NULL, 'e'},
85
{"timeout", 1, NULL, 'm'},
86
87
88
while ((opt =
89
getopt_long(argc, argv,
90
- "hVveqzr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:",
91
+ "hVveqzRr:s:t:i:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:",
92
longopts, NULL)) != -1)
93
{
94
switch (opt)
95
96
case 'v':
97
bLiveStream = TRUE; // no seeking or resuming possible!
98
break;
99
+ case 'R':
100
+ bRealtimeStream = TRUE; // seeking and resuming is still possible
101
+ break;
102
case 'd':
103
STR2AVAL(subscribepath, optarg);
104
break;
105
106
}
107
break;
108
}
109
+ case 'i':
110
+ STR2AVAL(fullUrl, optarg);
111
+ break;
112
case 's':
113
STR2AVAL(swfUrl, optarg);
114
break;
115
116
}
117
}
118
119
- if (!hostname.av_len)
120
+ if (!hostname.av_len && !fullUrl.av_len)
121
{
122
RTMP_Log(RTMP_LOGERROR,
123
"You must specify a hostname (--host) or url (-r \"rtmp://host[:port]/playpath\") containing a hostname");
124
return RD_FAILED;
125
}
126
- if (playpath.av_len == 0)
127
+ if (playpath.av_len == 0 && !fullUrl.av_len)
128
{
129
RTMP_Log(RTMP_LOGERROR,
130
"You must specify a playpath (--playpath) or url (-r \"rtmp://host[:port]/playpath\") containing a playpath");
131
return RD_FAILED;
132
}
133
134
- if (protocol == RTMP_PROTOCOL_UNDEFINED)
135
+ if (protocol == RTMP_PROTOCOL_UNDEFINED && !fullUrl.av_len)
136
{
137
RTMP_Log(RTMP_LOGWARNING,
138
"You haven't specified a protocol (--protocol) or rtmp url (-r), using default protocol RTMP");
139
protocol = RTMP_PROTOCOL_RTMP;
140
}
141
- if (port == -1)
142
+ if (port == -1 && !fullUrl.av_len)
143
{
144
RTMP_Log(RTMP_LOGWARNING,
145
"You haven't specified a port (--port) or rtmp url (-r), using default port 1935");
146
port = 0;
147
}
148
- if (port == 0)
149
+ if (port == 0 && !fullUrl.av_len)
150
{
151
if (protocol & RTMP_FEATURE_SSL)
152
port = 443;
153
154
}
155
}
156
157
- RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath,
158
- &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize,
159
- &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout);
160
+ if (!fullUrl.av_len)
161
+ {
162
+ RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath,
163
+ &tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize,
164
+ &flashVer, &subscribepath, &usherToken, dSeek, dStopOffset, bLiveStream, timeout);
165
+ }
166
+ else
167
+ {
168
+ if (RTMP_SetupURL(&rtmp, fullUrl.av_val) == FALSE)
169
+ {
170
+ RTMP_Log(RTMP_LOGERROR, "Couldn't parse URL: %s", fullUrl.av_val);
171
+ return RD_FAILED;
172
+ }
173
+ }
174
175
/* Try to keep the stream moving if it pauses on us */
176
- if (!bLiveStream && !(protocol & RTMP_FEATURE_HTTP))
177
+ if (!bLiveStream && !bRealtimeStream && !(protocol & RTMP_FEATURE_HTTP))
178
rtmp.Link.lFlags |= RTMP_LF_BUFX;
179
180
off_t size = 0;
181
182
183
nStatus = Download(&rtmp, file, dSeek, dStopOffset, duration, bResume,
184
metaHeader, nMetaHeaderSize, initialFrame,
185
- initialFrameType, nInitialFrameSize,
186
- nSkipKeyFrames, bStdoutMode, bLiveStream, bHashes,
187
+ initialFrameType, nInitialFrameSize, nSkipKeyFrames,
188
+ bStdoutMode, bLiveStream, bRealtimeStream, bHashes,
189
bOverrideBufferTime, bufferTime, &percent);
190
free(initialFrame);
191
initialFrame = NULL;
192
rtmpdump-2.3.99.git20111114.tar.bz2/rtmpgw.c -> rtmpdump-2.4.git20121102.tar.bz2/rtmpgw.c
Changed
118
1
2
uint32_t bufferTime;
3
4
char *rtmpurl;
5
+ AVal fullUrl;
6
AVal playpath;
7
AVal swfUrl;
8
AVal tcUrl;
9
10
}
11
12
// do necessary checks right here to make sure the combined request of default values and GET parameters is correct
13
- if (!req.hostname.av_len)
14
+ if (!req.hostname.av_len && !req.fullUrl.av_len)
15
{
16
RTMP_Log(RTMP_LOGERROR,
17
"You must specify a hostname (--host) or url (-r \"rtmp://host[:port]/playpath\") containing a hostname");
18
status = "400 Missing Hostname";
19
goto filenotfound;
20
}
21
- if (req.playpath.av_len == 0)
22
+ if (req.playpath.av_len == 0 && !req.fullUrl.av_len)
23
{
24
RTMP_Log(RTMP_LOGERROR,
25
"You must specify a playpath (--playpath) or url (-r \"rtmp://host[:port]/playpath\") containing a playpath");
26
27
goto filenotfound;;
28
}
29
30
- if (req.protocol == RTMP_PROTOCOL_UNDEFINED)
31
+ if (req.protocol == RTMP_PROTOCOL_UNDEFINED && !req.fullUrl.av_len)
32
{
33
RTMP_Log(RTMP_LOGWARNING,
34
"You haven't specified a protocol (--protocol) or rtmp url (-r), using default protocol RTMP");
35
req.protocol = RTMP_PROTOCOL_RTMP;
36
}
37
- if (req.rtmpport == -1)
38
+ if (req.rtmpport == -1 && !req.fullUrl.av_len)
39
{
40
RTMP_Log(RTMP_LOGWARNING,
41
"You haven't specified a port (--port) or rtmp url (-r), using default port");
42
req.rtmpport = 0;
43
}
44
- if (req.rtmpport == 0)
45
+ if (req.rtmpport == 0 && !req.fullUrl.av_len)
46
{
47
if (req.protocol & RTMP_FEATURE_SSL)
48
req.rtmpport = 443;
49
50
RTMP_Log(RTMP_LOGDEBUG, "Setting buffer time to: %dms", req.bufferTime);
51
RTMP_Init(&rtmp);
52
RTMP_SetBufferMS(&rtmp, req.bufferTime);
53
- RTMP_SetupStream(&rtmp, req.protocol, &req.hostname, req.rtmpport, &req.sockshost,
54
- &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, &req.usherToken, dSeek, req.dStopOffset,
55
- req.bLiveStream, req.timeout);
56
+ if (!req.fullUrl.av_len)
57
+ {
58
+ RTMP_SetupStream(&rtmp, req.protocol, &req.hostname, req.rtmpport, &req.sockshost,
59
+ &req.playpath, &req.tcUrl, &req.swfUrl, &req.pageUrl, &req.app, &req.auth, &req.swfHash, req.swfSize, &req.flashVer, &req.subscribepath, &req.usherToken, dSeek, req.dStopOffset,
60
+ req.bLiveStream, req.timeout);
61
+ }
62
+ else
63
+ {
64
+ if (RTMP_SetupURL(&rtmp, req.fullUrl.av_val) == FALSE)
65
+ {
66
+ RTMP_Log(RTMP_LOGERROR, "Couldn't parse URL: %s", req.fullUrl.av_val);
67
+ return;
68
+ }
69
+ }
70
/* backward compatibility, we always sent this as true before */
71
if (req.auth.av_len)
72
rtmp.Link.lFlags |= RTMP_LF_AUTH;
73
74
}
75
break;
76
}
77
+ case 'i':
78
+ STR2AVAL(req->fullUrl, arg);
79
+ break;
80
case 's':
81
STR2AVAL(req->swfUrl, arg);
82
break;
83
84
STR2AVAL(req->auth, arg);
85
break;
86
case 'C':
87
- parseAMF(&req->extras, optarg, &req->edepth);
88
+ parseAMF(&req->extras, arg, &req->edepth);
89
break;
90
case 'm':
91
req->timeout = atoi(arg);
92
93
int opt;
94
struct option longopts[] = {
95
{"help", 0, NULL, 'h'},
96
+ {"url", 1, NULL, 'i'},
97
{"host", 1, NULL, 'n'},
98
{"port", 1, NULL, 'c'},
99
{"socks", 1, NULL, 'S'},
100
101
102
while ((opt =
103
getopt_long(argc, argv,
104
- "hvqVzr:s:t:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:j:", longopts,
105
+ "hvqVzr:s:t:i:p:a:f:u:n:c:l:y:m:d:D:A:B:T:g:w:x:W:X:S:j:", longopts,
106
NULL)) != -1)
107
{
108
switch (opt)
109
110
("\nThis program serves media content streamed from RTMP onto HTTP.\n\n");
111
RTMP_LogPrintf("--help|-h Prints this help screen.\n");
112
RTMP_LogPrintf
113
+ ("--url|-i url URL with options included (e.g. rtmp://host[:port]/path swfUrl=url tcUrl=url)\n");
114
+ RTMP_LogPrintf
115
("--rtmp|-r url URL (e.g. rtmp://host[:port]/path)\n");
116
RTMP_LogPrintf
117
("--host|-n hostname Overrides the hostname in the rtmp url\n");
118
rtmpdump-2.3.99.git20111114.tar.bz2/rtmpsrv.c -> rtmpdump-2.4.git20121102.tar.bz2/rtmpsrv.c
Changed
221
1
2
} STREAMING_SERVER;
3
4
STREAMING_SERVER *rtmpServer = 0; // server structure pointer
5
+void *sslCtx = NULL;
6
7
STREAMING_SERVER *startStreaming(const char *address, int port);
8
void stopStreaming(STREAMING_SERVER * server);
9
10
*enc++ = 0;
11
*enc++ = 0;
12
*enc++ = AMF_OBJECT_END;
13
- *enc++ = 0;
14
- *enc++ = 0;
15
- *enc++ = AMF_OBJECT_END;
16
17
packet.m_nBodySize = enc - packet.m_body;
18
19
20
21
switch (packet->m_packetType)
22
{
23
- case 0x01:
24
- // chunk size
25
+ case RTMP_PACKET_TYPE_CHUNK_SIZE:
26
// HandleChangeChunkSize(r, packet);
27
break;
28
29
- case 0x03:
30
- // bytes read report
31
+ case RTMP_PACKET_TYPE_BYTES_READ_REPORT:
32
break;
33
34
- case 0x04:
35
- // ctrl
36
+ case RTMP_PACKET_TYPE_CONTROL:
37
// HandleCtrl(r, packet);
38
break;
39
40
- case 0x05:
41
- // server bw
42
+ case RTMP_PACKET_TYPE_SERVER_BW:
43
// HandleServerBW(r, packet);
44
break;
45
46
- case 0x06:
47
- // client bw
48
+ case RTMP_PACKET_TYPE_CLIENT_BW:
49
// HandleClientBW(r, packet);
50
break;
51
52
- case 0x08:
53
- // audio data
54
+ case RTMP_PACKET_TYPE_AUDIO:
55
//RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize);
56
break;
57
58
- case 0x09:
59
- // video data
60
+ case RTMP_PACKET_TYPE_VIDEO:
61
//RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize);
62
break;
63
64
- case 0x0F: // flex stream send
65
+ case RTMP_PACKET_TYPE_FLEX_STREAM_SEND:
66
break;
67
68
- case 0x10: // flex shared object
69
+ case RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT:
70
break;
71
72
- case 0x11: // flex message
73
+ case RTMP_PACKET_TYPE_FLEX_MESSAGE:
74
{
75
RTMP_Log(RTMP_LOGDEBUG, "%s, flex message, size %u bytes, not fully supported",
76
__FUNCTION__, packet->m_nBodySize);
77
78
RTMP_Close(r);
79
break;
80
}
81
- case 0x12:
82
- // metadata (notify)
83
+ case RTMP_PACKET_TYPE_INFO:
84
break;
85
86
- case 0x13:
87
- /* shared object */
88
+ case RTMP_PACKET_TYPE_SHARED_OBJECT:
89
break;
90
91
- case 0x14:
92
- // invoke
93
+ case RTMP_PACKET_TYPE_INVOKE:
94
RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %u bytes", __FUNCTION__,
95
packet->m_nBodySize);
96
//RTMP_LogHex(packet.m_body, packet.m_nBodySize);
97
98
RTMP_Close(r);
99
break;
100
101
- case 0x16:
102
- /* flv */
103
+ case RTMP_PACKET_TYPE_FLASH_VIDEO:
104
break;
105
default:
106
RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,
107
108
{
109
server->state = STREAMING_IN_PROGRESS;
110
111
- RTMP rtmp = { 0 }; /* our session with the real client */
112
+ RTMP *rtmp = RTMP_Alloc(); /* our session with the real client */
113
RTMPPacket packet = { 0 };
114
115
// timeout for http requests
116
117
}
118
else
119
{
120
- RTMP_Init(&rtmp);
121
- rtmp.m_sb.sb_socket = sockfd;
122
- if (!RTMP_Serve(&rtmp))
123
+ RTMP_Init(rtmp);
124
+ rtmp->m_sb.sb_socket = sockfd;
125
+ if (sslCtx && !RTMP_TLS_Accept(rtmp, sslCtx))
126
+ {
127
+ RTMP_Log(RTMP_LOGERROR, "TLS handshake failed");
128
+ goto cleanup;
129
+ }
130
+ if (!RTMP_Serve(rtmp))
131
{
132
RTMP_Log(RTMP_LOGERROR, "Handshake failed");
133
goto cleanup;
134
}
135
}
136
server->arglen = 0;
137
- while (RTMP_IsConnected(&rtmp) && RTMP_ReadPacket(&rtmp, &packet))
138
+ while (RTMP_IsConnected(rtmp) && RTMP_ReadPacket(rtmp, &packet))
139
{
140
if (!RTMPPacket_IsReady(&packet))
141
continue;
142
- ServePacket(server, &rtmp, &packet);
143
+ ServePacket(server, rtmp, &packet);
144
RTMPPacket_Free(&packet);
145
}
146
147
cleanup:
148
RTMP_LogPrintf("Closing connection... ");
149
- RTMP_Close(&rtmp);
150
+ RTMP_Close(rtmp);
151
/* Should probably be done by RTMP_Close() ... */
152
- rtmp.Link.playpath.av_val = NULL;
153
- rtmp.Link.tcUrl.av_val = NULL;
154
- rtmp.Link.swfUrl.av_val = NULL;
155
- rtmp.Link.pageUrl.av_val = NULL;
156
- rtmp.Link.app.av_val = NULL;
157
- rtmp.Link.flashVer.av_val = NULL;
158
- if (rtmp.Link.usherToken.av_val)
159
+ rtmp->Link.playpath.av_val = NULL;
160
+ rtmp->Link.tcUrl.av_val = NULL;
161
+ rtmp->Link.swfUrl.av_val = NULL;
162
+ rtmp->Link.pageUrl.av_val = NULL;
163
+ rtmp->Link.app.av_val = NULL;
164
+ rtmp->Link.flashVer.av_val = NULL;
165
+ if (rtmp->Link.usherToken.av_val)
166
{
167
- free(rtmp.Link.usherToken.av_val);
168
- rtmp.Link.usherToken.av_val = NULL;
169
+ free(rtmp->Link.usherToken.av_val);
170
+ rtmp->Link.usherToken.av_val = NULL;
171
}
172
+ RTMP_Free(rtmp);
173
RTMP_LogPrintf("done!\n\n");
174
175
quit:
176
177
main(int argc, char **argv)
178
{
179
int nStatus = RD_SUCCESS;
180
+ int i;
181
182
// http streaming server
183
char DEFAULT_HTTP_STREAMING_DEVICE[] = "0.0.0.0"; // 0.0.0.0 is any device
184
185
char *rtmpStreamingDevice = DEFAULT_HTTP_STREAMING_DEVICE; // streaming device, default 0.0.0.0
186
int nRtmpStreamingPort = 1935; // port
187
+ char *cert = NULL, *key = NULL;
188
189
RTMP_LogPrintf("RTMP Server %s\n", RTMPDUMP_VERSION);
190
RTMP_LogPrintf("(c) 2010 Andrej Stepanchuk, Howard Chu; license: GPL\n\n");
191
192
RTMP_debuglevel = RTMP_LOGINFO;
193
194
- if (argc > 1 && !strcmp(argv[1], "-z"))
195
- RTMP_debuglevel = RTMP_LOGALL;
196
+ for (i = 1; i < argc; i++)
197
+ {
198
+ if (!strcmp(argv[i], "-z"))
199
+ RTMP_debuglevel = RTMP_LOGALL;
200
+ else if (!strcmp(argv[i], "-c") && i + 1 < argc)
201
+ cert = argv[++i];
202
+ else if (!strcmp(argv[i], "-k") && i + 1 < argc)
203
+ key = argv[++i];
204
+ }
205
+
206
+ if (cert && key)
207
+ sslCtx = RTMP_TLS_AllocServerContext(cert, key);
208
209
// init request
210
memset(&defaultRTMPRequest, 0, sizeof(RTMP_REQUEST));
211
212
}
213
RTMP_Log(RTMP_LOGDEBUG, "Done, exiting...");
214
215
+ if (sslCtx)
216
+ RTMP_TLS_FreeServerContext(sslCtx);
217
+
218
CleanupSockets();
219
220
#ifdef _DEBUG
221
Refresh
No build results available
Refresh
No rpmlint results available
Login required, please
login
or
signup
in order to comment
Request History
marguerite created request over 11 years ago
update 2.4.git20121102
pbleser accepted request over 12 years ago
ok