Overview

Request 312 (accepted)

update 2.4.git20121102

Submit package home:marguerite...hes:Essentials / rtmpdump to package Essentials / rtmpdump

rtmpdump.changes Changed
x
 
1
@@ -1,4 +1,11 @@
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
@@ -4,7 +4,7 @@
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
@@ -12,7 +12,7 @@
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
@@ -28,7 +28,7 @@
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
@@ -39,11 +39,11 @@
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
@@ -64,7 +64,7 @@
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
@@ -81,12 +81,12 @@
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
@@ -111,8 +111,8 @@
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
@@ -396,6 +396,14 @@
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
@@ -700,7 +708,6 @@
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
@@ -718,7 +725,6 @@
25
    if (nRes == -1)
26
      return -1;
27
    nSize -= nRes;
28
-   prop->p_type = AMF_OBJECT;
29
    break;
30
       }
31
     case AMF_DATE:
32
@@ -735,13 +741,15 @@
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
@@ -750,12 +758,6 @@
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
@@ -819,6 +821,18 @@
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
@@ -892,6 +906,76 @@
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
@@ -1125,7 +1209,7 @@
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
@@ -104,6 +104,9 @@
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
@@ -61,7 +61,7 @@
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
@@ -77,20 +77,21 @@
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
@@ -43,21 +43,24 @@
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
@@ -42,16 +42,16 @@
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
@@ -137,12 +137,14 @@
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
@@ -156,7 +158,9 @@
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
@@ -27,6 +27,7 @@
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
@@ -34,11 +35,33 @@
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
@@ -227,6 +250,64 @@
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
@@ -320,6 +401,31 @@
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
@@ -384,26 +490,7 @@
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
@@ -499,6 +586,10 @@
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
@@ -756,6 +847,8 @@
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
@@ -859,6 +952,23 @@
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
@@ -1091,6 +1201,7 @@
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
@@ -1100,7 +1211,8 @@
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
@@ -1288,9 +1400,11 @@
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
@@ -1301,12 +1415,20 @@
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
@@ -1872,7 +1994,8 @@
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
@@ -2305,6 +2428,452 @@
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
@@ -2314,6 +2883,7 @@
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
@@ -2332,6 +2902,8 @@
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
@@ -2473,12 +3045,73 @@
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
@@ -2827,7 +3460,8 @@
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
@@ -2972,6 +3606,26 @@
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
@@ -3247,7 +3901,7 @@
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
@@ -3257,6 +3911,22 @@
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
@@ -3493,7 +4163,7 @@
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
@@ -3501,12 +4171,23 @@
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
@@ -3519,9 +4200,6 @@
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
@@ -3530,6 +4208,20 @@
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
@@ -3545,6 +4237,9 @@
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
@@ -3558,7 +4253,7 @@
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
@@ -3710,8 +4405,8 @@
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
@@ -3731,12 +4426,23 @@
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
@@ -3749,6 +4455,12 @@
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
@@ -157,6 +157,8 @@
2
     AVal subscribepath;
3
     AVal usherToken;
4
     AVal token;
5
+    AVal pubUser;
6
+    AVal pubPasswd;
7
     AMFObject extras;
8
     int edepth;
9
 
10
@@ -176,6 +178,13 @@
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
@@ -253,9 +262,11 @@
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
@@ -307,6 +318,7 @@
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
@@ -329,6 +341,9 @@
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
@@ -61,21 +61,41 @@
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
@@ -89,8 +109,10 @@
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
@@ -99,8 +121,10 @@
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
@@ -1,4 +1,4 @@
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
@@ -177,6 +177,12 @@
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
@@ -6,7 +6,7 @@
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
@@ -34,6 +34,7 @@
11
 [<b>&minus;y</b><i>&nbsp;playpath</i>]
12
 [<b>&minus;Y</b>]
13
 [<b>&minus;v</b>]
14
+[<b>&minus;R</b>]
15
 [<b>&minus;d</b><i>&nbsp;subscription</i>]
16
 [<b>&minus;e</b>]
17
 [<b>&minus;k</b><i>&nbsp;skip</i>]
18
@@ -218,6 +219,15 @@
19
 </dl>
20
 <p>
21
 <dl compact><dt>
22
+<b>&minus;&minus;realtime &minus;R</b>
23
+<dd>
24
+Download approximately in realtime, without attempting to speed up via
25
+Pause/Unpause commands (&quot;the BUFX hack&quot;).
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>&minus;&minus;resume &minus;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
@@ -441,7 +441,7 @@
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
@@ -492,6 +492,8 @@
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
@@ -578,12 +580,14 @@
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
@@ -638,6 +642,8 @@
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
@@ -682,6 +688,8 @@
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
@@ -748,6 +756,7 @@
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
@@ -755,6 +764,7 @@
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
@@ -817,6 +827,7 @@
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
@@ -832,6 +843,7 @@
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
@@ -851,7 +863,7 @@
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
@@ -936,6 +948,9 @@
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
@@ -991,6 +1006,9 @@
106
          }
107
        break;
108
      }
109
+   case 'i':
110
+     STR2AVAL(fullUrl, optarg);
111
+          break;
112
    case 's':
113
      STR2AVAL(swfUrl, optarg);
114
      break;
115
@@ -1069,32 +1087,32 @@
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
@@ -1176,12 +1194,23 @@
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
@@ -1348,8 +1377,8 @@
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
@@ -85,6 +85,7 @@
2
   uint32_t bufferTime;
3
 
4
   char *rtmpurl;
5
+  AVal fullUrl;
6
   AVal playpath;
7
   AVal swfUrl;
8
   AVal tcUrl;
9
@@ -469,14 +470,14 @@
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
@@ -484,19 +485,19 @@
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
@@ -552,9 +553,20 @@
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
@@ -908,6 +920,9 @@
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
@@ -927,7 +942,7 @@
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
@@ -993,6 +1008,7 @@
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
@@ -1040,7 +1056,7 @@
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
@@ -1050,6 +1066,8 @@
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
@@ -92,6 +92,7 @@
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
@@ -223,9 +224,6 @@
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
@@ -770,47 +768,40 @@
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
@@ -830,16 +821,13 @@
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
@@ -848,8 +836,7 @@
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
@@ -889,7 +876,7 @@
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
@@ -909,38 +896,44 @@
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
@@ -1074,20 +1067,32 @@
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
@@ -1131,6 +1136,9 @@
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

Request History
Marguerite Su's avatar

marguerite created request over 11 years ago

update 2.4.git20121102


pbleser's avatar

pbleser accepted request over 12 years ago

ok