Preliminary support for SSL
authorhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Tue, 9 Mar 2010 07:02:55 +0000 (07:02 +0000)
committerhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Tue, 9 Mar 2010 07:02:55 +0000 (07:02 +0000)
git-svn-id: svn://svn.mplayerhq.hu/rtmpdump/trunk@316 400ebc74-4327-4243-bc38-086b20814532

Makefile
librtmp/Makefile
librtmp/handshake.h
librtmp/hashswf.c
librtmp/rtmp.c
librtmp/rtmp.h

index d9bf1f5..dd1fc1e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ DEF=-DRTMPDUMP_VERSION=\"v2.2\"
 OPT=-O2
 CFLAGS=-Wall $(XCFLAGS) $(INC) $(DEF) $(OPT)
 LDFLAGS=-Wall $(XLDFLAGS)
-LIBS=-lcrypto -lz
+LIBS=-lssl -lcrypto -lz
 THREADLIB=-lpthread
 LIBRTMP=librtmp/librtmp.a
 SLIBS=$(THREADLIB) $(LIBS)
index a714559..234a8a9 100644 (file)
@@ -16,5 +16,5 @@ librtmp.a: rtmp.o log.o amf.o hashswf.o parseurl.o
 log.o: log.c log.h Makefile
 rtmp.o: rtmp.c rtmp.h handshake.h dh.h log.h amf.h Makefile
 amf.o: amf.c amf.h bytes.h log.h Makefile
-hashswf.o: hashswf.c http.h
+hashswf.o: hashswf.c http.h rtmp.h
 parseurl.o: parseurl.c
index 20ff82e..602c516 100644 (file)
@@ -312,8 +312,7 @@ HandShake(RTMP * r, bool FP9HandShake)
   int i;
   int dhposClient = 0;
   int digestPosClient = 0;
-  bool encrypted = r->Link.protocol == RTMP_PROTOCOL_RTMPE
-    || r->Link.protocol == RTMP_PROTOCOL_RTMPTE;
+  bool encrypted = r->Link.protocol & RTMP_FEATURE_ENC;
 
   RC4_KEY *keyIn = 0;
   RC4_KEY *keyOut = 0;
@@ -711,13 +710,12 @@ SHandShake(RTMP * r)
   if (type == 3)
     {
       encrypted = false;
-      r->Link.protocol = RTMP_PROTOCOL_RTMP;
     }
   else if (type == 6 || type == 8)
     {
       encrypted = true;
       FP9HandShake = true;
-      r->Link.protocol = RTMP_PROTOCOL_RTMPE;
+      r->Link.protocol |= RTMP_FEATURE_ENC;
     }
   else
     {
index b186fef..886a9c4 100644 (file)
 #include "log.h"
 #include "http.h"
 
+#include <openssl/ssl.h>
 #include <openssl/sha.h>
 #include <openssl/hmac.h>
 #include <zlib.h>
 
-struct info {
+struct info
+{
   HMAC_CTX *ctx;
   z_stream *zs;
   int first;
@@ -40,6 +42,9 @@ struct info {
   int size;
 };
 
+extern void RTMP_SSL_Init();
+extern SSL_CTX *RTMP_ssl_ctx;
+
 #define CHUNK  16384
 
 static size_t
@@ -54,10 +59,10 @@ swfcrunch(void *ptr, size_t size, size_t nmemb, void *stream)
       i->first = 0;
       /* compressed? */
       if (!strncmp(p, "CWS", 3))
-        {
-          *p = 'F';
-          i->zlib = 1;
-        }
+       {
+         *p = 'F';
+         i->zlib = 1;
+       }
       HMAC_Update(i->ctx, (unsigned char *)p, 8);
       p += 8;
       len -= 8;
@@ -70,14 +75,15 @@ swfcrunch(void *ptr, size_t size, size_t nmemb, void *stream)
       i->zs->next_in = (unsigned char *)p;
       i->zs->avail_in = len;
       do
-        {
-          i->zs->avail_out = CHUNK;
-          i->zs->next_out = out;
-          inflate(i->zs, Z_NO_FLUSH);
-          len = CHUNK - i->zs->avail_out;
-          i->size += len;
-          HMAC_Update(i->ctx, out, len);
-        } while (i->zs->avail_out == 0);
+       {
+         i->zs->avail_out = CHUNK;
+         i->zs->next_out = out;
+         inflate(i->zs, Z_NO_FLUSH);
+         len = CHUNK - i->zs->avail_out;
+         i->size += len;
+         HMAC_Update(i->ctx, out, len);
+       }
+      while (i->zs->avail_out == 0);
     }
   else
     {
@@ -117,13 +123,15 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb)
     {
       ssl = 1;
       port = 443;
+      if (!RTMP_ssl_ctx)
+       RTMP_SSL_Init();
     }
 
-  p1 = strchr(url+4, ':');
+  p1 = strchr(url + 4, ':');
   if (!p1 || strncmp(p1, "://", 3))
     return HTTPRES_BAD_REQUEST;
 
-  host = p1+3;
+  host = p1 + 3;
   path = strchr(host, '/');
   hlen = path - host;
   strncpy(hbuf, host, hlen);
@@ -141,34 +149,48 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb)
     {
       struct hostent *hp = gethostbyname(host);
       if (!hp || !hp->h_addr)
-        return HTTPRES_LOST_CONNECTION;
+       return HTTPRES_LOST_CONNECTION;
       sa.sin_addr = *(struct in_addr *)hp->h_addr;
     }
   sa.sin_port = htons(port);
   sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (sb.sb_socket < 0)
     return HTTPRES_LOST_CONNECTION;
-  i = sprintf(sb.sb_buf, "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferrer: %.*s\r\n",
-    path, AGENT, host, (int)(path-url+1), url);
+  i =
+    sprintf(sb.sb_buf,
+           "GET %s HTTP/1.0\r\nUser-Agent: %s\r\nHost: %s\r\nReferrer: %.*s\r\n",
+           path, AGENT, host, (int)(path - url + 1), url);
   if (http->date[0])
-    i += sprintf(sb.sb_buf+i, "If-Modified-Since: %s\r\n", http->date);
-  i += sprintf(sb.sb_buf+i, "\r\n");
+    i += sprintf(sb.sb_buf + i, "If-Modified-Since: %s\r\n", http->date);
+  i += sprintf(sb.sb_buf + i, "\r\n");
 
-  if (connect(sb.sb_socket, (struct sockaddr *)&sa, sizeof(struct sockaddr)) < 0)
+  if (connect
+      (sb.sb_socket, (struct sockaddr *)&sa, sizeof(struct sockaddr)) < 0)
     {
       ret = HTTPRES_LOST_CONNECTION;
       goto leave;
     }
-  send(sb.sb_socket, sb.sb_buf, i, 0);
+  if (ssl)
+    {
+      sb.sb_ssl = SSL_new(RTMP_ssl_ctx);
+      SSL_set_fd(sb.sb_ssl, sb.sb_socket);
+      if (SSL_connect(sb.sb_ssl) < 0)
+       {
+         Log(LOGERROR, "%s, SSL_Connect failed", __FUNCTION__);
+         ret = HTTPRES_LOST_CONNECTION;
+         goto leave;
+       }
+    }
+  RTMPSockBuf_Send(&sb, sb.sb_buf, i);
 
   // set timeout
 #define HTTP_TIMEOUT   5
   SET_RCVTIMEO(tv, HTTP_TIMEOUT);
   if (setsockopt
-    (sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv)))
+      (sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
     {
       Log(LOGERROR, "%s, Setting socket timeout to %ds failed!",
-          __FUNCTION__, HTTP_TIMEOUT);
+         __FUNCTION__, HTTP_TIMEOUT);
     }
 
   sb.sb_size = 0;
@@ -185,24 +207,25 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb)
     }
 
   p1 = strchr(sb.sb_buf, ' ');
-  rc = atoi(p1+1);
+  rc = atoi(p1 + 1);
   http->status = rc;
 
-  if (rc >= 300) {
-    if (rc == 304)
-      {
-        ret = HTTPRES_OK_NOT_MODIFIED;
-        goto leave;
-      }
-    else if (rc == 404)
-      ret = HTTPRES_NOT_FOUND;
-    else if (rc >= 500)
-      ret = HTTPRES_SERVER_ERROR;
-    else if (rc >= 400)
-      ret = HTTPRES_BAD_REQUEST;
-    else
-      ret = HTTPRES_REDIRECTED;
-  }
+  if (rc >= 300)
+    {
+      if (rc == 304)
+       {
+         ret = HTTPRES_OK_NOT_MODIFIED;
+         goto leave;
+       }
+      else if (rc == 404)
+       ret = HTTPRES_NOT_FOUND;
+      else if (rc >= 500)
+       ret = HTTPRES_SERVER_ERROR;
+      else if (rc >= 400)
+       ret = HTTPRES_BAD_REQUEST;
+      else
+       ret = HTTPRES_REDIRECTED;
+    }
 
   p1 = memchr(sb.sb_buf, '\n', sb.sb_size);
   if (!p1)
@@ -210,46 +233,50 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb)
       ret = HTTPRES_BAD_REQUEST;
       goto leave;
     }
-  sb.sb_start = p1+1;
+  sb.sb_start = p1 + 1;
   sb.sb_size -= sb.sb_start - sb.sb_buf;
 
-  while((p2=memchr(sb.sb_start, '\r', sb.sb_size)))
+  while ((p2 = memchr(sb.sb_start, '\r', sb.sb_size)))
     {
       if (*sb.sb_start == '\r')
-        {
-          sb.sb_start += 2;
-          sb.sb_size -= 2;
-          break;
-        }
-      else if (!strncasecmp(sb.sb_start, "Content-Length: ", sizeof("Content-Length: ")-1))
-        {
-          flen = atoi(sb.sb_start+sizeof("Content-Length: ")-1);
-        }
-      else if (!strncasecmp(sb.sb_start, "Last-Modified: ", sizeof("Last-Modified: ")-1))
-        {
-          *p2 = '\0';
-          strcpy(http->date, sb.sb_start+sizeof("Last-Modified: ")-1);
-        }
+       {
+         sb.sb_start += 2;
+         sb.sb_size -= 2;
+         break;
+       }
+      else
+       if (!strncasecmp
+           (sb.sb_start, "Content-Length: ", sizeof("Content-Length: ") - 1))
+       {
+         flen = atoi(sb.sb_start + sizeof("Content-Length: ") - 1);
+       }
+      else
+       if (!strncasecmp
+           (sb.sb_start, "Last-Modified: ", sizeof("Last-Modified: ") - 1))
+       {
+         *p2 = '\0';
+         strcpy(http->date, sb.sb_start + sizeof("Last-Modified: ") - 1);
+       }
       p2 += 2;
-      sb.sb_size -= p2-sb.sb_start;
+      sb.sb_size -= p2 - sb.sb_start;
       sb.sb_start = p2;
       if (sb.sb_size < 1)
-        {
-          if (RTMPSockBuf_Fill(&sb) < 1)
-            {
-              ret = HTTPRES_LOST_CONNECTION;
-              goto leave;
-            }
-        }
+       {
+         if (RTMPSockBuf_Fill(&sb) < 1)
+           {
+             ret = HTTPRES_LOST_CONNECTION;
+             goto leave;
+           }
+       }
     }
 
   len_known = flen > 0;
   while ((!len_known || flen > 0) &&
-         (sb.sb_size > 0 || RTMPSockBuf_Fill(&sb) > 0))
+        (sb.sb_size > 0 || RTMPSockBuf_Fill(&sb) > 0))
     {
       cb(sb.sb_start, 1, sb.sb_size, http->data);
       if (len_known)
-        flen -= sb.sb_size;
+       flen -= sb.sb_size;
       http->size += sb.sb_size;
       sb.sb_size = 0;
     }
@@ -258,7 +285,7 @@ HTTP_get(struct HTTP_ctx *http, const char *url, HTTP_read_callback *cb)
     ret = HTTPRES_LOST_CONNECTION;
 
 leave:
-  closesocket(sb.sb_socket);
+  RTMPSockBuf_Close(&sb);
   return ret;
 }
 
@@ -267,105 +294,111 @@ static int tzchecked;
 
 #define        JAN02_1980      318340800
 
-static const char *monthtab[12] = {"Jan", "Feb", "Mar",
-                               "Apr", "May", "Jun",
-                               "Jul", "Aug", "Sep",
-                               "Oct", "Nov", "Dec"};
-static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+static const char *monthtab[12] = { "Jan", "Feb", "Mar",
+  "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep",
+  "Oct", "Nov", "Dec"
+};
+static const char *days[] =
+  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
 
 /* Parse an HTTP datestamp into Unix time */
 static time_t
 make_unix_time(char *s)
 {
-    struct tm       time;
-    int             i, ysub = 1900, fmt = 0;
-    char           *month;
-    char           *n;
-    time_t res;
+  struct tm time;
+  int i, ysub = 1900, fmt = 0;
+  char *month;
+  char *n;
+  time_t res;
 
-    if (s[3] != ' ')
+  if (s[3] != ' ')
     {
-       fmt = 1;
-       if (s[3] != ',')
-           ysub = 0;
+      fmt = 1;
+      if (s[3] != ',')
+       ysub = 0;
     }
-    for (n = s; *n; ++n)
-       if (*n == '-' || *n == ':')
-           *n = ' ';
+  for (n = s; *n; ++n)
+    if (*n == '-' || *n == ':')
+      *n = ' ';
 
-    time.tm_mon = 0;
-    n = strchr(s, ' ');
-    if (fmt)
+  time.tm_mon = 0;
+  n = strchr(s, ' ');
+  if (fmt)
     {
-       /* Day, DD-MMM-YYYY HH:MM:SS GMT */
-       time.tm_mday = strtol(n+1, &n, 0);
-       month = n+1;
-       n = strchr(month, ' ');
-       time.tm_year = strtol(n+1, &n, 0);
-       time.tm_hour = strtol(n+1, &n, 0);
-       time.tm_min = strtol(n+1, &n, 0);
-       time.tm_sec = strtol(n+1, NULL, 0);
-    } else
+      /* Day, DD-MMM-YYYY HH:MM:SS GMT */
+      time.tm_mday = strtol(n + 1, &n, 0);
+      month = n + 1;
+      n = strchr(month, ' ');
+      time.tm_year = strtol(n + 1, &n, 0);
+      time.tm_hour = strtol(n + 1, &n, 0);
+      time.tm_min = strtol(n + 1, &n, 0);
+      time.tm_sec = strtol(n + 1, NULL, 0);
+    }
+  else
     {
-       /* Unix ctime() format. Does not conform to HTTP spec. */
-       /* Day MMM DD HH:MM:SS YYYY */
-       month = n+1;
-       n = strchr(month, ' ');
-       while (isspace(*n)) n++;
-       time.tm_mday = strtol(n, &n, 0);
-       time.tm_hour = strtol(n+1, &n, 0);
-       time.tm_min = strtol(n+1, &n, 0);
-       time.tm_sec = strtol(n+1, &n, 0);
-       time.tm_year = strtol(n+1, NULL, 0);
+      /* Unix ctime() format. Does not conform to HTTP spec. */
+      /* Day MMM DD HH:MM:SS YYYY */
+      month = n + 1;
+      n = strchr(month, ' ');
+      while (isspace(*n))
+       n++;
+      time.tm_mday = strtol(n, &n, 0);
+      time.tm_hour = strtol(n + 1, &n, 0);
+      time.tm_min = strtol(n + 1, &n, 0);
+      time.tm_sec = strtol(n + 1, &n, 0);
+      time.tm_year = strtol(n + 1, NULL, 0);
     }
-    if (time.tm_year > 100)
-       time.tm_year -= ysub;
+  if (time.tm_year > 100)
+    time.tm_year -= ysub;
 
-    for (i = 0; i < 12; i++)
-       if (!strncasecmp(month, monthtab[i], 3))
-       {
-           time.tm_mon = i;
-           break;
-       }
-    time.tm_isdst = 0;         /* daylight saving is never in effect in GMT */
+  for (i = 0; i < 12; i++)
+    if (!strncasecmp(month, monthtab[i], 3))
+      {
+       time.tm_mon = i;
+       break;
+      }
+  time.tm_isdst = 0;           /* daylight saving is never in effect in GMT */
 
-    /* this is normally the value of extern int timezone, but some
-     * braindead C libraries don't provide it.
-     */
-    if (!tzchecked)
+  /* this is normally the value of extern int timezone, but some
+   * braindead C libraries don't provide it.
+   */
+  if (!tzchecked)
     {
-       struct tm *tc;
-       time_t then = JAN02_1980;
-       tc = localtime(&then);
-       tzoff = (12 - tc->tm_hour) * 3600 + tc->tm_min * 60 + tc->tm_sec;
-       tzchecked = 1;
+      struct tm *tc;
+      time_t then = JAN02_1980;
+      tc = localtime(&then);
+      tzoff = (12 - tc->tm_hour) * 3600 + tc->tm_min * 60 + tc->tm_sec;
+      tzchecked = 1;
     }
-    res = mktime(&time);
-    /* Unfortunately, mktime() assumes the input is in local time,
-     * not GMT, so we have to correct it here.
-     */
-    if (res != -1)
-       res += tzoff;
-    return res;
+  res = mktime(&time);
+  /* Unfortunately, mktime() assumes the input is in local time,
+   * not GMT, so we have to correct it here.
+   */
+  if (res != -1)
+    res += tzoff;
+  return res;
 }
 
 /* Convert a Unix time to a network time string
  * Weekday, DD-MMM-YYYY HH:MM:SS GMT
  */
-void strtime(time_t *t, char *s)
+void
+strtime(time_t * t, char *s)
 {
-    struct tm *tm;
+  struct tm *tm;
 
-    tm = gmtime((time_t *)t);
-    sprintf(s, "%s, %02d %s %d %02d:%02d:%02d GMT",
-       days[tm->tm_wday], tm->tm_mday, monthtab[tm->tm_mon],
-       tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec);
+  tm = gmtime((time_t *) t);
+  sprintf(s, "%s, %02d %s %d %02d:%02d:%02d GMT",
+         days[tm->tm_wday], tm->tm_mday, monthtab[tm->tm_mon],
+         tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec);
 }
 
 #define HEX2BIN(a)      (((a)&0x40)?((a)&0xf)+9:((a)&0xf))
 
 int
-RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
+RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash,
+            int age)
 {
   FILE *f = NULL;
   char *path, *home, date[64], cctim[64];
@@ -373,10 +406,10 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
   time_t ctim = -1, cnow;
   int i, got = 0, ret = 0;
   unsigned int hlen;
-  struct info in = {0};
-  struct HTTP_ctx http = {0};
+  struct info in = { 0 };
+  struct HTTP_ctx http = { 0 };
   HTTPResult httpres;
-  z_stream zs = {0};
+  z_stream zs = { 0 };
   HMAC_CTX ctx;
 
   date[0] = '\0';
@@ -394,7 +427,7 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
    * These fields must be present in this order. All fields
    * besides URL are fixed size.
    */
-  path=malloc(strlen(home)+sizeof("/.swfinfo"));
+  path = malloc(strlen(home) + sizeof("/.swfinfo"));
   strcpy(path, home);
   strcat(path, "/.swfinfo");
 
@@ -405,67 +438,67 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
 
       file = strchr(url, '/');
       if (!file)
-        break;
+       break;
       file += 2;
       file = strchr(file, '/');
       if (!file)
-        break;
+       break;
       file++;
       hlen = file - url;
       p = strrchr(file, '/');
       if (p)
-        file = p;
+       file = p;
       else
-        file--;
+       file--;
 
       while (fgets(buf, sizeof(buf), f))
-        {
-          char *r1;
-
-          got = 0;
-
-          if (strncmp(buf, "url: ", 5))
-            continue;
-          if (strncmp(buf+5, url, hlen))
-            continue;
-          r1 = strrchr(buf, '/');
-          i = strlen(r1);
-          r1[--i] = '\0';
-          if (strncmp(r1, file, i))
-            continue;
-          pos = ftell(f);
-          while (got < 4 && fgets(buf, sizeof(buf), f))
-            {
-              if (!strncmp(buf, "size: ", 6))
-                {
-                  *size = strtol(buf+6, NULL, 16);
-                  got++;
-                }
-              else if (!strncmp(buf, "hash: ", 6))
-                {
-                  unsigned char *ptr = hash, *in = (unsigned char *)buf+6;
-                  int l = strlen((char *)in)-1;
-                  for (i=0; i<l; i+=2)
-                    *ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i+1]);
-                  got++;
-                }
-              else if (!strncmp(buf, "date: ", 6))
-                {
-                  buf[strlen(buf)-1] = '\0';
-                  strncpy(date, buf+6, sizeof(date));
-                  got++;
-                }
-              else if (!strncmp(buf, "ctim: ", 6))
-                {
-                  buf[strlen(buf)-1] = '\0';
-                 ctim = make_unix_time(buf+6);
-                  got++;
-                }
-              else if (!strncmp(buf, "url: ", 5))
-                break;
-            }
-          break;
-        }
+       {
+         char *r1;
+
+         got = 0;
+
+         if (strncmp(buf, "url: ", 5))
+           continue;
+         if (strncmp(buf + 5, url, hlen))
+           continue;
+         r1 = strrchr(buf, '/');
+         i = strlen(r1);
+         r1[--i] = '\0';
+         if (strncmp(r1, file, i))
+           continue;
+         pos = ftell(f);
+         while (got < 4 && fgets(buf, sizeof(buf), f))
+           {
+             if (!strncmp(buf, "size: ", 6))
+               {
+                 *size = strtol(buf + 6, NULL, 16);
+                 got++;
+               }
+             else if (!strncmp(buf, "hash: ", 6))
+               {
+                 unsigned char *ptr = hash, *in = (unsigned char *)buf + 6;
+                 int l = strlen((char *)in) - 1;
+                 for (i = 0; i < l; i += 2)
+                   *ptr++ = (HEX2BIN(in[i]) << 4) | HEX2BIN(in[i + 1]);
+                 got++;
+               }
+             else if (!strncmp(buf, "date: ", 6))
+               {
+                 buf[strlen(buf) - 1] = '\0';
+                 strncpy(date, buf + 6, sizeof(date));
+                 got++;
+               }
+             else if (!strncmp(buf, "ctim: ", 6))
+               {
+                 buf[strlen(buf) - 1] = '\0';
+                 ctim = make_unix_time(buf + 6);
+                 got++;
+               }
+             else if (!strncmp(buf, "url: ", 5))
+               break;
+           }
+         break;
+       }
       break;
     }
 
@@ -474,14 +507,15 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
   if (age && ctim > 0)
     {
       ctim = cnow - ctim;
-      ctim /= 3600 * 24; /* seconds to days */
-      if (ctim < age)  /* ok, it's new enough */
-        goto out;
+      ctim /= 3600 * 24;       /* seconds to days */
+      if (ctim < age)          /* ok, it's new enough */
+       goto out;
     }
 
   in.first = 1;
   HMAC_CTX_init(&ctx);
-  HMAC_Init_ex(&ctx, "Genuine Adobe Flash Player 001", 30, EVP_sha256(), NULL);
+  HMAC_Init_ex(&ctx, "Genuine Adobe Flash Player 001", 30, EVP_sha256(),
+              NULL);
   inflateInit(&zs);
   in.ctx = &ctx;
   in.zs = &zs;
@@ -497,56 +531,56 @@ RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age)
     {
       ret = -1;
       if (httpres == HTTPRES_LOST_CONNECTION)
-        Log(LOGERROR, "%s: connection lost while downloading swfurl %s",
-            __FUNCTION__, url);
+       Log(LOGERROR, "%s: connection lost while downloading swfurl %s",
+           __FUNCTION__, url);
       else if (httpres == HTTPRES_NOT_FOUND)
-        Log(LOGERROR, "%s: swfurl %s not found",
-            __FUNCTION__, url);
+       Log(LOGERROR, "%s: swfurl %s not found", __FUNCTION__, url);
       else
-        Log(LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)",
-            __FUNCTION__, url, http.status);
+       Log(LOGERROR, "%s: couldn't contact swfurl %s (HTTP error %d)",
+           __FUNCTION__, url, http.status);
     }
   else
     {
       if (got && pos)
-        fseek(f, pos, SEEK_SET);
+       fseek(f, pos, SEEK_SET);
       else
-        {
-          char *q;
-          if (!f)
-            f = fopen(path, "w");
-          if (!f)
-            {
-              int err = errno;
-              Log(LOGERROR, "%s: couldn't open %s for writing, errno %d (%s)",
-                __FUNCTION__, path, err, strerror(err));
-              ret = -1;
-              goto out;
-            }
-          fseek(f, 0, SEEK_END);
-          q = strchr(url, '?');
-          if (q)
-            i = q - url;
-          else
-            i = strlen(url);
-
-          fprintf(f, "url: %.*s\n", i, url);
-        }
+       {
+         char *q;
+         if (!f)
+           f = fopen(path, "w");
+         if (!f)
+           {
+             int err = errno;
+             Log(LOGERROR,
+                 "%s: couldn't open %s for writing, errno %d (%s)",
+                 __FUNCTION__, path, err, strerror(err));
+             ret = -1;
+             goto out;
+           }
+         fseek(f, 0, SEEK_END);
+         q = strchr(url, '?');
+         if (q)
+           i = q - url;
+         else
+           i = strlen(url);
+
+         fprintf(f, "url: %.*s\n", i, url);
+       }
       strtime(&cnow, cctim);
       fprintf(f, "ctim: %s\n", cctim);
 
       if (!in.first)
-        {
-          HMAC_Final(&ctx, (unsigned char *)hash, &hlen);
-          *size = in.size;
-
-          fprintf(f, "date: %s\n", date);
-          fprintf(f, "size: %08x\n", in.size);
-          fprintf(f, "hash: ");
-          for (i=0; i<SHA256_DIGEST_LENGTH; i++)
-            fprintf(f, "%02x", hash[i]);
-          fprintf(f, "\n");
-        }
+       {
+         HMAC_Final(&ctx, (unsigned char *)hash, &hlen);
+         *size = in.size;
+
+         fprintf(f, "date: %s\n", date);
+         fprintf(f, "size: %08x\n", in.size);
+         fprintf(f, "hash: ");
+         for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+           fprintf(f, "%02x", hash[i]);
+         fprintf(f, "\n");
+       }
     }
   HMAC_CTX_cleanup(&ctx);
 out:
index 197feed..12c426b 100644 (file)
@@ -30,6 +30,8 @@
 #include "rtmp.h"
 #include "log.h"
 
+#include <openssl/ssl.h>
+
 #ifdef CRYPTO
 #include <openssl/rc4.h>
 #endif
@@ -37,6 +39,7 @@
 #define RTMP_SIG_SIZE 1536
 #define RTMP_LARGE_HEADER_SIZE 12
 
+SSL_CTX *RTMP_ssl_ctx;
 static const int packetSize[] = { 12, 8, 4, 1 };
 
 bool RTMP_ctrlC;
@@ -44,49 +47,54 @@ bool RTMP_ctrlC;
 const char RTMPProtocolStrings[][7] = {
   "RTMP",
   "RTMPT",
-  "RTMPS",
   "RTMPE",
   "RTMPTE",
+  "",
+  "RTMPS",
+  "",
+  "",
   "RTMFP"
 };
 
 const char RTMPProtocolStringsLower[][7] = {
   "rtmp",
   "rtmpt",
-  "rtmps",
   "rtmpe",
   "rtmpte",
-  "rtmpfp"
+  "",
+  "rtmps",
+  "",
+  "",
+  "rtmfp"
 };
 
-static bool DumpMetaData(AMFObject * obj);
-static bool HandShake(RTMP * r, bool FP9HandShake);
-static bool SocksNegotiate(RTMP * r);
-
-static bool SendConnectPacket(RTMP * r, RTMPPacket *cp);
-static bool SendCheckBW(RTMP * r);
-static bool SendCheckBWResult(RTMP * r, double txn);
-static bool SendDeleteStream(RTMP * r, double dStreamId);
-static bool SendFCSubscribe(RTMP * r, AVal * subscribepath);
-static bool SendPlay(RTMP * r);
-static bool SendBytesReceived(RTMP * r);
-
-#if 0 /* unused */
-static bool SendBGHasStream(RTMP * r, double dId, AVal * playpath);
-static bool SendSeek(RTMP * r, double dTime);
+static bool DumpMetaData(AMFObject *obj);
+static bool HandShake(RTMP *r, bool FP9HandShake);
+static bool SocksNegotiate(RTMP *r);
+
+static bool SendConnectPacket(RTMP *r, RTMPPacket *cp);
+static bool SendCheckBW(RTMP *r);
+static bool SendCheckBWResult(RTMP *r, double txn);
+static bool SendDeleteStream(RTMP *r, double dStreamId);
+static bool SendFCSubscribe(RTMP *r, AVal *subscribepath);
+static bool SendPlay(RTMP *r);
+static bool SendBytesReceived(RTMP *r);
+
+#if 0                          /* unused */
+static bool SendBGHasStream(RTMP *r, double dId, AVal *playpath);
 #endif
 
-static int HandleInvoke(RTMP * r, const char *body, unsigned int nBodySize);
-static bool HandleMetadata(RTMP * r, char *body, unsigned int len);
-static void HandleChangeChunkSize(RTMP * r, const RTMPPacket * packet);
-static void HandleAudio(RTMP * r, const RTMPPacket * packet);
-static void HandleVideo(RTMP * r, const RTMPPacket * packet);
-static void HandleCtrl(RTMP * r, const RTMPPacket * packet);
-static void HandleServerBW(RTMP * r, const RTMPPacket * packet);
-static void HandleClientBW(RTMP * r, const RTMPPacket * packet);
+static int HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize);
+static bool HandleMetadata(RTMP *r, char *body, unsigned int len);
+static void HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet);
+static void HandleAudio(RTMP *r, const RTMPPacket *packet);
+static void HandleVideo(RTMP *r, const RTMPPacket *packet);
+static void HandleCtrl(RTMP *r, const RTMPPacket *packet);
+static void HandleServerBW(RTMP *r, const RTMPPacket *packet);
+static void HandleClientBW(RTMP *r, const RTMPPacket *packet);
 
-static int ReadN(RTMP * r, char *buffer, int n);
-static bool WriteN(RTMP * r, const char *buffer, int n);
+static int ReadN(RTMP *r, char *buffer, int n);
+static bool WriteN(RTMP *r, const char *buffer, int n);
 
 static void DecodeTEA(AVal *key, AVal *text);
 
@@ -104,7 +112,7 @@ RTMP_GetTime()
 }
 
 void
-RTMPPacket_Reset(RTMPPacket * p)
+RTMPPacket_Reset(RTMPPacket *p)
 {
   p->m_headerType = 0;
   p->m_packetType = 0;
@@ -117,9 +125,9 @@ RTMPPacket_Reset(RTMPPacket * p)
 }
 
 bool
-RTMPPacket_Alloc(RTMPPacket * p, int nSize)
+RTMPPacket_Alloc(RTMPPacket *p, int nSize)
 {
-  char *ptr = calloc(1, nSize+RTMP_MAX_HEADER_SIZE);
+  char *ptr = calloc(1, nSize + RTMP_MAX_HEADER_SIZE);
   if (!ptr)
     return false;
   p->m_body = ptr + RTMP_MAX_HEADER_SIZE;
@@ -128,28 +136,43 @@ RTMPPacket_Alloc(RTMPPacket * p, int nSize)
 }
 
 void
-RTMPPacket_Free(RTMPPacket * p)
+RTMPPacket_Free(RTMPPacket *p)
 {
   if (p->m_body)
     {
-      free(p->m_body-RTMP_MAX_HEADER_SIZE);
+      free(p->m_body - RTMP_MAX_HEADER_SIZE);
       p->m_body = NULL;
     }
 }
 
 void
-RTMPPacket_Dump(RTMPPacket * p)
+RTMPPacket_Dump(RTMPPacket *p)
 {
   Log(LOGDEBUG,
       "RTMP PACKET: packet type: 0x%02x. channel: 0x%02x. info 1: %d info 2: %d. Body size: %lu. body: 0x%02x",
       p->m_packetType, p->m_nChannel, p->m_nInfoField1, p->m_nInfoField2,
-      p->m_nBodySize, p->m_body ? (unsigned char) p->m_body[0] : 0);
+      p->m_nBodySize, p->m_body ? (unsigned char)p->m_body[0] : 0);
+}
+
+void
+RTMP_SSL_Init()
+{
+  SSL_load_error_strings();
+  SSL_library_init();
+  OpenSSL_add_all_digests();
+  RTMP_ssl_ctx = SSL_CTX_new(SSLv23_method());
+  SSL_CTX_set_options(RTMP_ssl_ctx, SSL_OP_ALL);
+  SSL_CTX_set_default_verify_paths(RTMP_ssl_ctx);
 }
 
 void
-RTMP_Init(RTMP * r)
+RTMP_Init(RTMP *r)
 {
   int i;
+
+  if (!RTMP_ssl_ctx)
+    RTMP_SSL_Init();
+
   for (i = 0; i < RTMP_CHANNELS; i++)
     {
       r->m_vecChannelsIn[i] = NULL;
@@ -169,31 +192,31 @@ RTMP_Init(RTMP * r)
 }
 
 double
-RTMP_GetDuration(RTMP * r)
+RTMP_GetDuration(RTMP *r)
 {
   return r->m_fDuration;
 }
 
 bool
-RTMP_IsConnected(RTMP * r)
+RTMP_IsConnected(RTMP *r)
 {
   return r->m_sb.sb_socket != -1;
 }
 
 bool
-RTMP_IsTimedout(RTMP * r)
+RTMP_IsTimedout(RTMP *r)
 {
   return r->m_sb.sb_timedout;
 }
 
 void
-RTMP_SetBufferMS(RTMP * r, int size)
+RTMP_SetBufferMS(RTMP *r, int size)
 {
   r->m_nBufferMS = size;
 }
 
 void
-RTMP_UpdateBufferMS(RTMP * r)
+RTMP_UpdateBufferMS(RTMP *r)
 {
   RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
 }
@@ -211,28 +234,29 @@ RTMP_UpdateBufferMS(RTMP * r)
 #define OSS    "GNU"
 #endif
 static const char DEFAULT_FLASH_VER[] = OSS " 10,0,32,18";
-const AVal RTMP_DefaultFlashVer = {(char *)DEFAULT_FLASH_VER, sizeof(DEFAULT_FLASH_VER)-1};
+const AVal RTMP_DefaultFlashVer =
+  { (char *)DEFAULT_FLASH_VER, sizeof(DEFAULT_FLASH_VER) - 1 };
 
 void
-RTMP_SetupStream(RTMP * r,
+RTMP_SetupStream(RTMP *r,
                 int protocol,
                 const char *hostname,
                 unsigned int port,
                 const char *sockshost,
-                AVal * playpath,
-                AVal * tcUrl,
-                AVal * swfUrl,
-                AVal * pageUrl,
-                AVal * app,
-                AVal * auth,
-                AVal * swfSHA256Hash,
+                AVal *playpath,
+                AVal *tcUrl,
+                AVal *swfUrl,
+                AVal *pageUrl,
+                AVal *app,
+                AVal *auth,
+                AVal *swfSHA256Hash,
                 uint32_t swfSize,
-                AVal * flashVer,
-                AVal * subscribepath,
+                AVal *flashVer,
+                AVal *subscribepath,
                 double dTime,
                 uint32_t dLength, bool bLiveStream, long int timeout)
 {
-  assert(protocol < 6);
+  assert(protocol < 9);
 
   Log(LOGDEBUG, "Protocol : %s", RTMPProtocolStrings[protocol]);
   Log(LOGDEBUG, "Hostname : %s", hostname);
@@ -254,9 +278,9 @@ RTMP_SetupStream(RTMP * r,
   if (flashVer && flashVer->av_val)
     Log(LOGDEBUG, "flashVer : %s", flashVer->av_val);
   if (dTime > 0)
-    Log(LOGDEBUG, "SeekTime      : %.3f sec", (double) dTime / 1000.0);
+    Log(LOGDEBUG, "SeekTime      : %.3f sec", (double)dTime / 1000.0);
   if (dLength > 0)
-    Log(LOGDEBUG, "playLength    : %.3f sec", (double) dLength / 1000.0);
+    Log(LOGDEBUG, "playLength    : %.3f sec", (double)dLength / 1000.0);
 
   Log(LOGDEBUG, "live     : %s", bLiveStream ? "yes" : "no");
   Log(LOGDEBUG, "timeout  : %d sec", timeout);
@@ -339,7 +363,7 @@ add_addr_info(struct sockaddr_in *service, const char *hostname, int port)
          Log(LOGERROR, "Problem accessing the DNS. (addr: %s)", hostname);
          return false;
        }
-      service->sin_addr = *(struct in_addr *) host->h_addr;
+      service->sin_addr = *(struct in_addr *)host->h_addr;
     }
 
   service->sin_port = htons(port);
@@ -347,7 +371,7 @@ add_addr_info(struct sockaddr_in *service, const char *hostname, int port)
 }
 
 bool
-RTMP_Connect0(RTMP *r, struct sockaddr *service)
+RTMP_Connect0(RTMP *r, struct sockaddr * service)
 {
   // close any previous connection
   RTMP_Close(r);
@@ -359,12 +383,11 @@ RTMP_Connect0(RTMP *r, struct sockaddr *service)
   r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (r->m_sb.sb_socket != -1)
     {
-      if (connect
-         (r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0)
+      if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0)
        {
          int err = GetSockError();
-         Log(LOGERROR, "%s, failed to connect socket. %d (%s)", __FUNCTION__,
-             err, strerror(err));
+         Log(LOGERROR, "%s, failed to connect socket. %d (%s)",
+             __FUNCTION__, err, strerror(err));
          RTMP_Close(r);
          return false;
        }
@@ -390,10 +413,10 @@ RTMP_Connect0(RTMP *r, struct sockaddr *service)
   // set timeout
   SET_RCVTIMEO(tv, r->Link.timeout);
   if (setsockopt
-      (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv)))
+      (r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
     {
       Log(LOGERROR, "%s, Setting socket timeout to %ds failed!",
-          __FUNCTION__, r->Link.timeout);
+         __FUNCTION__, r->Link.timeout);
     }
 
   int on = 1;
@@ -405,6 +428,17 @@ RTMP_Connect0(RTMP *r, struct sockaddr *service)
 bool
 RTMP_Connect1(RTMP *r, RTMPPacket *cp)
 {
+  if (r->Link.protocol & RTMP_FEATURE_SSL)
+    {
+      r->m_sb.sb_ssl = SSL_new(RTMP_ssl_ctx);
+      SSL_set_fd(r->m_sb.sb_ssl, r->m_sb.sb_socket);
+      if (SSL_connect(r->m_sb.sb_ssl) < 0)
+       {
+         Log(LOGERROR, "%s, SSL_Connect failed", __FUNCTION__);
+         RTMP_Close(r);
+         return false;
+       }
+    }
   Log(LOGDEBUG, "%s, ... connected, handshaking", __FUNCTION__);
   if (!HandShake(r, true))
     {
@@ -455,7 +489,7 @@ RTMP_Connect(RTMP *r, RTMPPacket *cp)
 }
 
 static bool
-SocksNegotiate(RTMP * r)
+SocksNegotiate(RTMP *r)
 {
   struct sockaddr_in service;
   memset(&service, 0, sizeof(struct sockaddr_in));
@@ -467,8 +501,8 @@ SocksNegotiate(RTMP * r)
     4, 1,                      // SOCKS 4, connect
     (r->Link.port >> 8) & 0xFF,
     (r->Link.port) & 0xFF,
-    (char) (addr >> 24) & 0xFF, (char) (addr >> 16) & 0xFF,
-    (char) (addr >> 8) & 0xFF, (char) addr & 0xFF,
+    (char)(addr >> 24) & 0xFF, (char)(addr >> 16) & 0xFF,
+    (char)(addr >> 8) & 0xFF, (char)addr & 0xFF,
     0
   };                           // NULL terminate
 
@@ -489,7 +523,7 @@ SocksNegotiate(RTMP * r)
 }
 
 bool
-RTMP_ConnectStream(RTMP * r, double seekTime, uint32_t dLength)
+RTMP_ConnectStream(RTMP *r, double seekTime, uint32_t dLength)
 {
   RTMPPacket packet = { 0 };
   if (seekTime >= -2.0)
@@ -524,7 +558,7 @@ RTMP_ConnectStream(RTMP * r, double seekTime, uint32_t dLength)
 }
 
 bool
-RTMP_ReconnectStream(RTMP * r, int bufferTime, double seekTime,
+RTMP_ReconnectStream(RTMP *r, int bufferTime, double seekTime,
                     uint32_t dLength)
 {
   RTMP_DeleteStream(r);
@@ -537,25 +571,26 @@ RTMP_ReconnectStream(RTMP * r, int bufferTime, double seekTime,
 }
 
 bool
-RTMP_ToggleStream(RTMP * r)
+RTMP_ToggleStream(RTMP *r)
 {
   bool res;
 
-  if (!r->m_pausing) {
-    res = RTMP_SendPause(r, true, r->m_pauseStamp);
-    if (!res)
-      return res;
+  if (!r->m_pausing)
+    {
+      res = RTMP_SendPause(r, true, r->m_pauseStamp);
+      if (!res)
+       return res;
 
-    r->m_pausing = 1;
-    sleep(1);
-  }
+      r->m_pausing = 1;
+      sleep(1);
+    }
   res = RTMP_SendPause(r, false, r->m_pauseStamp);
   r->m_pausing = 3;
   return res;
 }
 
 void
-RTMP_DeleteStream(RTMP * r)
+RTMP_DeleteStream(RTMP *r)
 {
   if (r->m_stream_id < 0)
     return;
@@ -566,11 +601,12 @@ RTMP_DeleteStream(RTMP * r)
 }
 
 int
-RTMP_GetNextMediaPacket(RTMP * r, RTMPPacket * packet)
+RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet)
 {
   int bHasMediaPacket = 0;
 
-  while (!bHasMediaPacket && RTMP_IsConnected(r) && RTMP_ReadPacket(r, packet))
+  while (!bHasMediaPacket && RTMP_IsConnected(r)
+        && RTMP_ReadPacket(r, packet))
     {
       if (!RTMPPacket_IsReady(packet))
        {
@@ -610,7 +646,7 @@ RTMP_GetNextMediaPacket(RTMP * r, RTMPPacket * packet)
 }
 
 int
-RTMP_ClientPacket(RTMP * r, RTMPPacket * packet)
+RTMP_ClientPacket(RTMP *r, RTMPPacket *packet)
 {
   int bHasMediaPacket = 0;
   switch (packet->m_packetType)
@@ -676,7 +712,8 @@ RTMP_ClientPacket(RTMP * r, RTMPPacket * packet)
 
     case 0x11:                 // flex message
       {
-       Log(LOGDEBUG, "%s, flex message, size %lu bytes, not fully supported",
+       Log(LOGDEBUG,
+           "%s, flex message, size %lu bytes, not fully supported",
            __FUNCTION__, packet->m_nBodySize);
        //LogHex(packet.m_body, packet.m_nBodySize);
 
@@ -768,7 +805,7 @@ extern FILE *netstackdump_read;
 #endif
 
 static int
-ReadN(RTMP * r, char *buffer, int n)
+ReadN(RTMP *r, char *buffer, int n)
 {
   int nOriginalSize = n;
   char *ptr;
@@ -784,7 +821,7 @@ ReadN(RTMP * r, char *buffer, int n)
     {
       int nBytes = 0, nRead;
       if (r->m_sb.sb_size == 0)
-       if (RTMPSockBuf_Fill(&r->m_sb)<1)
+       if (RTMPSockBuf_Fill(&r->m_sb) < 1)
          {
            if (!r->m_sb.sb_timedout)
              RTMP_Close(r);
@@ -798,7 +835,8 @@ ReadN(RTMP * r, char *buffer, int n)
          r->m_sb.sb_size -= nRead;
          nBytes = nRead;
          r->m_nBytesIn += nRead;
-         if (r->m_bSendCounter && r->m_nBytesIn > r->m_nBytesInSent + r->m_nClientBW / 2)
+         if (r->m_bSendCounter
+             && r->m_nBytesIn > r->m_nBytesInSent + r->m_nClientBW / 2)
            SendBytesReceived(r);
        }
 
@@ -830,7 +868,7 @@ ReadN(RTMP * r, char *buffer, int n)
 }
 
 static bool
-WriteN(RTMP * r, const char *buffer, int n)
+WriteN(RTMP *r, const char *buffer, int n)
 {
   const char *ptr = buffer;
 #ifdef CRYPTO
@@ -840,9 +878,9 @@ WriteN(RTMP * r, const char *buffer, int n)
   if (r->Link.rc4keyOut)
     {
       if (n > sizeof(buf))
-       encrypted = (char *) malloc(n);
+       encrypted = (char *)malloc(n);
       else
-       encrypted = (char *) buf;
+       encrypted = (char *)buf;
       ptr = encrypted;
       RC4(r->Link.rc4keyOut, n, (uint8_t *) buffer, (uint8_t *) ptr);
     }
@@ -850,11 +888,7 @@ WriteN(RTMP * r, const char *buffer, int n)
 
   while (n > 0)
     {
-#ifdef _DEBUG
-      fwrite(ptr, 1, n, netstackdump);
-#endif
-
-      int nBytes = send(r->m_sb.sb_socket, ptr, n, 0);
+      int nBytes = RTMPSockBuf_Send(&r->m_sb, ptr, n);
       //Log(LOGDEBUG, "%s: %d\n", __FUNCTION__, nBytes);
 
       if (nBytes < 0)
@@ -907,7 +941,7 @@ static bool
 SendConnectPacket(RTMP *r, RTMPPacket *cp)
 {
   RTMPPacket packet;
-  char pbuf[4096], *pend = pbuf+sizeof(pbuf);
+  char pbuf[4096], *pend = pbuf + sizeof(pbuf);
 
   if (cp)
     return RTMP_SendPacket(r, cp, true);
@@ -929,25 +963,25 @@ SendConnectPacket(RTMP *r, RTMPPacket *cp)
     {
       enc = AMF_EncodeNamedString(enc, pend, &av_app, &r->Link.app);
       if (!enc)
-        return false;
+       return false;
     }
   if (r->Link.flashVer.av_len)
     {
       enc = AMF_EncodeNamedString(enc, pend, &av_flashVer, &r->Link.flashVer);
       if (!enc)
-        return false;
+       return false;
     }
   if (r->Link.swfUrl.av_len)
     {
       enc = AMF_EncodeNamedString(enc, pend, &av_swfUrl, &r->Link.swfUrl);
       if (!enc)
-        return false;
+       return false;
     }
   if (r->Link.tcUrl.av_len)
     {
       enc = AMF_EncodeNamedString(enc, pend, &av_tcUrl, &r->Link.tcUrl);
       if (!enc)
-        return false;
+       return false;
     }
   enc = AMF_EncodeNamedBoolean(enc, pend, &av_fpad, false);
   if (!enc)
@@ -968,15 +1002,15 @@ SendConnectPacket(RTMP *r, RTMPPacket *cp)
     {
       enc = AMF_EncodeNamedString(enc, pend, &av_pageUrl, &r->Link.pageUrl);
       if (!enc)
-        return false;
+       return false;
     }
   if (r->m_fEncoding != 0.0 || r->m_bSendEncoding)
     {
       enc = AMF_EncodeNamedNumber(enc, pend, &av_objectEncoding, r->m_fEncoding);      // AMF0, AMF3 not supported yet
       if (!enc)
-        return false;
+       return false;
     }
-  if (enc+3 >= pend)
+  if (enc + 3 >= pend)
     return false;
   *enc++ = 0;
   *enc++ = 0;                  // end of object - 0x00 0x00 0x09
@@ -987,34 +1021,34 @@ SendConnectPacket(RTMP *r, RTMPPacket *cp)
     {
       enc = AMF_EncodeBoolean(enc, pend, r->Link.authflag);
       if (!enc)
-        return false;
+       return false;
       enc = AMF_EncodeString(enc, pend, &r->Link.auth);
       if (!enc)
-        return false;
+       return false;
     }
   if (r->Link.extras.o_num)
     {
       int i;
-      for (i=0; i < r->Link.extras.o_num; i++)
-        {
-          enc = AMFProp_Encode(&r->Link.extras.o_props[i], enc, pend);
-          if (!enc)
-            return false;
-        }
+      for (i = 0; i < r->Link.extras.o_num; i++)
+       {
+         enc = AMFProp_Encode(&r->Link.extras.o_props[i], enc, pend);
+         if (!enc)
+           return false;
+       }
     }
   packet.m_nBodySize = enc - packet.m_body;
 
   return RTMP_SendPacket(r, &packet, true);
 }
 
-#if 0 /* unused */
+#if 0                          /* unused */
 SAVC(bgHasStream);
 
 static bool
-SendBGHasStream(RTMP * r, double dId, AVal * playpath)
+SendBGHasStream(RTMP *r, double dId, AVal *playpath)
 {
   RTMPPacket packet;
-  char pbuf[1024], *pend = pbuf+sizeof(pbuf);
+  char pbuf[1024], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1042,10 +1076,10 @@ SendBGHasStream(RTMP * r, double dId, AVal * playpath)
 SAVC(createStream);
 
 bool
-RTMP_SendCreateStream(RTMP * r, double dCmdID)
+RTMP_SendCreateStream(RTMP *r, double dCmdID)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1068,10 +1102,10 @@ RTMP_SendCreateStream(RTMP * r, double dCmdID)
 SAVC(FCSubscribe);
 
 static bool
-SendFCSubscribe(RTMP * r, AVal * subscribepath)
+SendFCSubscribe(RTMP *r, AVal *subscribepath)
 {
   RTMPPacket packet;
-  char pbuf[512], *pend = pbuf+sizeof(pbuf);
+  char pbuf[512], *pend = pbuf + sizeof(pbuf);
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
   packet.m_packetType = 0x14;  // INVOKE
@@ -1098,10 +1132,10 @@ SendFCSubscribe(RTMP * r, AVal * subscribepath)
 SAVC(deleteStream);
 
 static bool
-SendDeleteStream(RTMP * r, double dStreamId)
+SendDeleteStream(RTMP *r, double dStreamId)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1126,10 +1160,10 @@ SendDeleteStream(RTMP * r, double dStreamId)
 SAVC(pause);
 
 bool
-RTMP_SendPause(RTMP * r, bool DoPause, double dTime)
+RTMP_SendPause(RTMP *r, bool DoPause, double dTime)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x08;    // video channel
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1144,21 +1178,21 @@ RTMP_SendPause(RTMP * r, bool DoPause, double dTime)
   enc = AMF_EncodeNumber(enc, pend, 0);
   *enc++ = AMF_NULL;
   enc = AMF_EncodeBoolean(enc, pend, DoPause);
-  enc = AMF_EncodeNumber(enc, pend, (double) dTime);
+  enc = AMF_EncodeNumber(enc, pend, (double)dTime);
 
   packet.m_nBodySize = enc - packet.m_body;
 
-  Log(LOGDEBUG, "%s, %d, pauseTime=%.2f",
-      __FUNCTION__, DoPause, dTime);
+  Log(LOGDEBUG, "%s, %d, pauseTime=%.2f", __FUNCTION__, DoPause, dTime);
   return RTMP_SendPacket(r, &packet, true);
 }
 
 SAVC(seek);
 
-bool RTMP_SendSeek(RTMP * r, double dTime)
+bool
+RTMP_SendSeek(RTMP *r, double dTime)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x08;    // video channel
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1180,10 +1214,10 @@ bool RTMP_SendSeek(RTMP * r, double dTime)
 }
 
 bool
-RTMP_SendServerBW(RTMP * r)
+RTMP_SendServerBW(RTMP *r)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x02;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
@@ -1200,10 +1234,10 @@ RTMP_SendServerBW(RTMP * r)
 }
 
 static bool
-SendBytesReceived(RTMP * r)
+SendBytesReceived(RTMP *r)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x02;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1225,15 +1259,15 @@ SendBytesReceived(RTMP * r)
 SAVC(_checkbw);
 
 static bool
-SendCheckBW(RTMP * r)
+SendCheckBW(RTMP *r)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
   packet.m_packetType = 0x14;  // INVOKE
-  packet.m_nInfoField1 = 0; /* RTMP_GetTime(); */
+  packet.m_nInfoField1 = 0;    /* RTMP_GetTime(); */
   packet.m_nInfoField2 = 0;
   packet.m_hasAbsTimestamp = 0;
   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
@@ -1252,10 +1286,10 @@ SendCheckBW(RTMP * r)
 SAVC(_result);
 
 static bool
-SendCheckBWResult(RTMP * r, double txn)
+SendCheckBWResult(RTMP *r, double txn)
 {
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    // control channel (invoke)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1269,7 +1303,7 @@ SendCheckBWResult(RTMP * r, double txn)
   enc = AMF_EncodeString(enc, pend, &av__result);
   enc = AMF_EncodeNumber(enc, pend, txn);
   *enc++ = AMF_NULL;
-  enc = AMF_EncodeNumber(enc, pend, (double) r->m_nBWCheckCounter++);
+  enc = AMF_EncodeNumber(enc, pend, (double)r->m_nBWCheckCounter++);
 
   packet.m_nBodySize = enc - packet.m_body;
 
@@ -1279,10 +1313,10 @@ SendCheckBWResult(RTMP * r, double txn)
 SAVC(play);
 
 static bool
-SendPlay(RTMP * r)
+SendPlay(RTMP *r)
 {
   RTMPPacket packet;
-  char pbuf[1024], *pend = pbuf+sizeof(pbuf);
+  char pbuf[1024], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x08;    // we make 8 our stream channel
   packet.m_headerType = RTMP_PACKET_SIZE_LARGE;
@@ -1331,7 +1365,7 @@ SendPlay(RTMP * r)
     {
       enc = AMF_EncodeNumber(enc, pend, r->Link.length);       // len
       if (!enc)
-        return false;
+       return false;
     }
 
   packet.m_nBodySize = enc - packet.m_body;
@@ -1343,7 +1377,7 @@ static bool
 SendSecureTokenResponse(RTMP *r, AVal *resp)
 {
   RTMPPacket packet;
-  char pbuf[1024], *pend = pbuf+sizeof(pbuf);
+  char pbuf[1024], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x03;    /* control channel (invoke) */
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
@@ -1383,17 +1417,17 @@ The type of Ping packet is 0x4 and contains two mandatory parameters and two opt
     * type 27: SWFVerification response
 */
 bool
-RTMP_SendCtrl(RTMP * r, short nType, unsigned int nObject, unsigned int nTime)
+RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject, unsigned int nTime)
 {
-  Log(LOGDEBUG, "sending ctrl. type: 0x%04x", (unsigned short) nType);
+  Log(LOGDEBUG, "sending ctrl. type: 0x%04x", (unsigned short)nType);
 
   RTMPPacket packet;
-  char pbuf[256], *pend = pbuf+sizeof(pbuf);
+  char pbuf[256], *pend = pbuf + sizeof(pbuf);
 
   packet.m_nChannel = 0x02;    // control channel (ping)
   packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;
   packet.m_packetType = 0x04;  // ctrl
-  packet.m_nInfoField1 = 0; /* RTMP_GetTime(); */
+  packet.m_nInfoField1 = 0;    /* RTMP_GetTime(); */
   packet.m_nInfoField2 = 0;
   packet.m_hasAbsTimestamp = 0;
   packet.m_body = pbuf + RTMP_MAX_HEADER_SIZE;
@@ -1428,7 +1462,7 @@ RTMP_SendCtrl(RTMP * r, short nType, unsigned int nObject, unsigned int nTime)
 }
 
 static void
-AV_erase(AVal * vals, int *num, int i, bool freeit)
+AV_erase(AVal *vals, int *num, int i, bool freeit)
 {
   if (freeit)
     free(vals[i].av_val);
@@ -1448,7 +1482,7 @@ RTMP_DropRequest(RTMP *r, int i, bool freeit)
 }
 
 static void
-AV_queue(AVal ** vals, int *num, AVal * av)
+AV_queue(AVal **vals, int *num, AVal *av)
 {
   char *tmp;
   if (!(*num & 0x0f))
@@ -1461,7 +1495,7 @@ AV_queue(AVal ** vals, int *num, AVal * av)
 }
 
 static void
-AV_clear(AVal * vals, int num)
+AV_clear(AVal *vals, int num)
 {
   int i;
   for (i = 0; i < num; i++)
@@ -1491,7 +1525,7 @@ static const AVal av_NetStream_Play_Stop = AVC("NetStream.Play.Stop");
 
 // Returns 0 for OK/Failed/error, 1 for 'Stop or Complete'
 static int
-HandleInvoke(RTMP * r, const char *body, unsigned int nBodySize)
+HandleInvoke(RTMP *r, const char *body, unsigned int nBodySize)
 {
   int ret = 0, nRes;
   if (body[0] != 0x02)         // make sure it is a string method name we start with
@@ -1525,15 +1559,15 @@ HandleInvoke(RTMP * r, const char *body, unsigned int nBodySize)
 
       if (AVMATCH(&methodInvoked, &av_connect))
        {
-          if (r->Link.token.av_len)
-            {
-              AMFObjectProperty p;
-              if (RTMP_FindFirstMatchingProperty(&obj, &av_secureToken, &p))
-                {
-                  DecodeTEA(&r->Link.token, &p.p_vu.p_aval);
-                  SendSecureTokenResponse(r, &p.p_vu.p_aval);
-                }
-            }
+         if (r->Link.token.av_len)
+           {
+             AMFObjectProperty p;
+             if (RTMP_FindFirstMatchingProperty(&obj, &av_secureToken, &p))
+               {
+                 DecodeTEA(&r->Link.token, &p.p_vu.p_aval);
+                 SendSecureTokenResponse(r, &p.p_vu.p_aval);
+               }
+           }
          RTMP_SendServerBW(r);
          RTMP_SendCtrl(r, 3, 0, 300);
 
@@ -1547,8 +1581,7 @@ HandleInvoke(RTMP * r, const char *body, unsigned int nBodySize)
        }
       else if (AVMATCH(&methodInvoked, &av_createStream))
        {
-         r->m_stream_id =
-           (int) AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3));
+         r->m_stream_id = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3));
 
          SendPlay(r);
          RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);
@@ -1645,7 +1678,7 @@ HandleInvoke(RTMP * r, const char *body, unsigned int nBodySize)
 }
 
 bool
-RTMP_FindFirstMatchingProperty(AMFObject * obj, const AVal * name,
+RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name,
                               AMFObjectProperty * p)
 {
   int n;
@@ -1663,14 +1696,14 @@ RTMP_FindFirstMatchingProperty(AMFObject * obj, const AVal * name,
       if (prop->p_type == AMF_OBJECT)
        {
          if (RTMP_FindFirstMatchingProperty(&prop->p_vu.p_object, name, p))
-            return true;
+           return true;
        }
     }
   return false;
 }
 
 static bool
-DumpMetaData(AMFObject * obj)
+DumpMetaData(AMFObject *obj)
 {
   AMFObjectProperty *prop;
   int n;
@@ -1698,7 +1731,7 @@ DumpMetaData(AMFObject * obj)
              break;
            default:
              snprintf(str, 255, "INVALID TYPE 0x%02x",
-                      (unsigned char) prop->p_type);
+                      (unsigned char)prop->p_type);
            }
          if (prop->p_name.av_len)
            {
@@ -1723,7 +1756,7 @@ SAVC(onMetaData);
 SAVC(duration);
 
 static bool
-HandleMetadata(RTMP * r, char *body, unsigned int len)
+HandleMetadata(RTMP *r, char *body, unsigned int len)
 {
   // allright we get some info here, so parse it and print it
   // also keep duration or filesize to make a nice progress bar
@@ -1760,7 +1793,7 @@ HandleMetadata(RTMP * r, char *body, unsigned int len)
 }
 
 static void
-HandleChangeChunkSize(RTMP * r, const RTMPPacket * packet)
+HandleChangeChunkSize(RTMP *r, const RTMPPacket *packet)
 {
   if (packet->m_nBodySize >= 4)
     {
@@ -1771,17 +1804,17 @@ HandleChangeChunkSize(RTMP * r, const RTMPPacket * packet)
 }
 
 static void
-HandleAudio(RTMP * r, const RTMPPacket * packet)
+HandleAudio(RTMP *r, const RTMPPacket *packet)
 {
 }
 
 static void
-HandleVideo(RTMP * r, const RTMPPacket * packet)
+HandleVideo(RTMP *r, const RTMPPacket *packet)
 {
 }
 
 static void
-HandleCtrl(RTMP * r, const RTMPPacket * packet)
+HandleCtrl(RTMP *r, const RTMPPacket *packet)
 {
   short nType = -1;
   unsigned int tmp;
@@ -1826,7 +1859,8 @@ HandleCtrl(RTMP * r, const RTMPPacket * packet)
        case 31:
          tmp = AMF_DecodeInt32(packet->m_body + 2);
          Log(LOGDEBUG, "%s, Stream BufferEmpty %d", __FUNCTION__, tmp);
-         if (r->Link.bLiveStream) break;
+         if (r->Link.bLiveStream)
+           break;
          if (!r->m_pausing)
            {
              r->m_pauseStamp = r->m_channelTimestamp[r->m_mediaChannel];
@@ -1872,21 +1906,21 @@ HandleCtrl(RTMP * r, const RTMPPacket * packet)
        }
 #else
       Log(LOGERROR,
-       "%s: Ignoring SWFVerification request, no CRYPTO support!",
-             __FUNCTION__);
+         "%s: Ignoring SWFVerification request, no CRYPTO support!",
+         __FUNCTION__);
 #endif
     }
 }
 
 static void
-HandleServerBW(RTMP * r, const RTMPPacket * packet)
+HandleServerBW(RTMP *r, const RTMPPacket *packet)
 {
   r->m_nServerBW = AMF_DecodeInt32(packet->m_body);
   Log(LOGDEBUG, "%s: server BW = %d", __FUNCTION__, r->m_nServerBW);
 }
 
 static void
-HandleClientBW(RTMP * r, const RTMPPacket * packet)
+HandleClientBW(RTMP *r, const RTMPPacket *packet)
 {
   r->m_nClientBW = AMF_DecodeInt32(packet->m_body);
   if (packet->m_nBodySize > 4)
@@ -1921,7 +1955,7 @@ EncodeInt32LE(char *output, int nVal)
 }
 
 bool
-RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
+RTMP_ReadPacket(RTMP *r, RTMPPacket *packet)
 {
   char hbuf[RTMP_MAX_HEADER_SIZE] = { 0 }, *header = hbuf;
 
@@ -1944,7 +1978,7 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
              __FUNCTION__);
          return false;
        }
-      packet->m_nChannel = (unsigned) hbuf[1];
+      packet->m_nChannel = (unsigned)hbuf[1];
       packet->m_nChannel += 64;
       header++;
     }
@@ -1957,7 +1991,7 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
              __FUNCTION__);
          return false;
        }
-      tmp = (((unsigned) hbuf[2]) << 8) + (unsigned) hbuf[1];
+      tmp = (((unsigned)hbuf[2]) << 8) + (unsigned)hbuf[1];
       packet->m_nChannel = tmp + 64;
       Log(LOGDEBUG, "%s, m_nChannel: %0x", __FUNCTION__, packet->m_nChannel);
       header += 2;
@@ -1980,11 +2014,11 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
   if (nSize > 0 && ReadN(r, header, nSize) != nSize)
     {
       Log(LOGERROR, "%s, failed to read RTMP packet header. type: %x",
-         __FUNCTION__, (unsigned int) hbuf[0]);
+         __FUNCTION__, (unsigned int)hbuf[0]);
       return false;
     }
 
-  hSize = nSize+(header-hbuf);
+  hSize = nSize + (header - hbuf);
 
   if (nSize >= 3)
     {
@@ -2007,16 +2041,16 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
            }
        }
       if (packet->m_nInfoField1 == 0xffffff)
-        {
-          if (ReadN(r, header+nSize, 4) != 4)
-            {
-              Log(LOGERROR, "%s, failed to read extended timestamp",
-                 __FUNCTION__);
-              return false;
-            }
-          packet->m_nInfoField1 = AMF_DecodeInt32(header+nSize);
-          hSize += 4;
-        }
+       {
+         if (ReadN(r, header + nSize, 4) != 4)
+           {
+             Log(LOGERROR, "%s, failed to read extended timestamp",
+                 __FUNCTION__);
+             return false;
+           }
+         packet->m_nInfoField1 = AMF_DecodeInt32(header + nSize);
+         hSize += 4;
+       }
     }
 
   LogHexString(LOGDEBUG2, hbuf, hSize);
@@ -2043,7 +2077,7 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
     {
       packet->m_chunk->c_headerSize = hSize;
       memcpy(packet->m_chunk->c_header, hbuf, hSize);
-      packet->m_chunk->c_chunk = packet->m_body+packet->m_nBytesRead;
+      packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead;
       packet->m_chunk->c_chunkSize = nChunk;
     }
 
@@ -2054,7 +2088,7 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
       return false;
     }
 
-  LogHexString(LOGDEBUG2, packet->m_body+packet->m_nBytesRead, nChunk);
+  LogHexString(LOGDEBUG2, packet->m_body + packet->m_nBytesRead, nChunk);
 
   packet->m_nBytesRead += nChunk;
 
@@ -2091,10 +2125,10 @@ RTMP_ReadPacket(RTMP * r, RTMPPacket * packet)
 #include "handshake.h"
 #else
 static bool
-HandShake(RTMP * r, bool FP9HandShake)
+HandShake(RTMP *r, bool FP9HandShake)
 {
   int i;
-  char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf+1;
+  char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf + 1;
   char serversig[RTMP_SIG_SIZE];
 
   clientbuf[0] = 0x03;         // not encrypted
@@ -2109,7 +2143,7 @@ HandShake(RTMP * r, bool FP9HandShake)
     clientsig[i] = 0xff;
 #else
   for (i = 8; i < RTMP_SIG_SIZE; i++)
-    clientsig[i] = (char) (rand() % 256);
+    clientsig[i] = (char)(rand() % 256);
 #endif
 
   if (!WriteN(r, clientbuf, RTMP_SIG_SIZE + 1))
@@ -2135,8 +2169,8 @@ HandShake(RTMP * r, bool FP9HandShake)
   suptime = ntohl(suptime);
 
   Log(LOGDEBUG, "%s: Server Uptime : %d", __FUNCTION__, suptime);
-  Log(LOGDEBUG, "%s: FMS Version   : %d.%d.%d.%d", __FUNCTION__, serversig[4],
-      serversig[5], serversig[6], serversig[7]);
+  Log(LOGDEBUG, "%s: FMS Version   : %d.%d.%d.%d", __FUNCTION__,
+      serversig[4], serversig[5], serversig[6], serversig[7]);
 
   // 2nd part of handshake
   if (!WriteN(r, serversig, RTMP_SIG_SIZE))
@@ -2154,10 +2188,10 @@ HandShake(RTMP * r, bool FP9HandShake)
 }
 
 static bool
-SHandShake(RTMP * r)
+SHandShake(RTMP *r)
 {
   int i;
-  char serverbuf[RTMP_SIG_SIZE + 1], *serversig = serverbuf+1;
+  char serverbuf[RTMP_SIG_SIZE + 1], *serversig = serverbuf + 1;
   char clientsig[RTMP_SIG_SIZE];
   uint32_t uptime;
 
@@ -2182,7 +2216,7 @@ SHandShake(RTMP * r)
     serversig[i] = 0xff;
 #else
   for (i = 8; i < RTMP_SIG_SIZE; i++)
-    serversig[i] = (char) (rand() % 256);
+    serversig[i] = (char)(rand() % 256);
 #endif
 
   if (!WriteN(r, serverbuf, RTMP_SIG_SIZE + 1))
@@ -2197,8 +2231,8 @@ SHandShake(RTMP * r)
   uptime = ntohl(uptime);
 
   Log(LOGDEBUG, "%s: Client Uptime : %d", __FUNCTION__, uptime);
-  Log(LOGDEBUG, "%s: Player Version: %d.%d.%d.%d", __FUNCTION__, clientsig[4],
-      clientsig[5], clientsig[6], clientsig[7]);
+  Log(LOGDEBUG, "%s: Player Version: %d.%d.%d.%d", __FUNCTION__,
+      clientsig[4], clientsig[5], clientsig[6], clientsig[7]);
 
   // 2nd part of handshake
   if (!WriteN(r, clientsig, RTMP_SIG_SIZE))
@@ -2222,7 +2256,8 @@ RTMP_SendChunk(RTMP *r, RTMPChunk *chunk)
   bool wrote;
   char hbuf[RTMP_MAX_HEADER_SIZE];
 
-  Log(LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket, chunk->c_chunkSize);
+  Log(LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket,
+      chunk->c_chunkSize);
   LogHexString(LOGDEBUG2, chunk->c_header, chunk->c_headerSize);
   if (chunk->c_chunkSize)
     {
@@ -2240,7 +2275,7 @@ RTMP_SendChunk(RTMP *r, RTMPChunk *chunk)
 }
 
 bool
-RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
+RTMP_SendPacket(RTMP *r, RTMPPacket *packet, bool queue)
 {
   const RTMPPacket *prevPacket = r->m_vecChannelsOut[packet->m_nChannel];
   if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE)
@@ -2259,7 +2294,7 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
   if (packet->m_headerType > 3)        // sanity
     {
       Log(LOGERROR, "sanity failed!! trying to send header of type: 0x%02x.",
-         (unsigned char) packet->m_headerType);
+         (unsigned char)packet->m_headerType);
       return false;
     }
 
@@ -2274,8 +2309,8 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
     }
   else
     {
-      header = hbuf+6;
-      hend = hbuf+sizeof(hbuf);
+      header = hbuf + 6;
+      hend = hbuf + sizeof(hbuf);
     }
 
   if (packet->m_nChannel > 319)
@@ -2296,7 +2331,7 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
 
   hptr = header;
   c = packet->m_headerType << 6;
-  switch(cSize)
+  switch (cSize)
     {
     case 0:
       c |= packet->m_nChannel;
@@ -2313,14 +2348,14 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
       int tmp = packet->m_nChannel - 64;
       *hptr++ = tmp & 0xff;
       if (cSize == 2)
-        *hptr++ = tmp >> 8;
+       *hptr++ = tmp >> 8;
     }
 
   if (nSize > 1)
     {
       uint32_t t = packet->m_nInfoField1;
       if (t > 0xffffff)
-        t = 0xffffff;
+       t = 0xffffff;
       hptr = AMF_EncodeInt24(hptr, hend, t);
     }
 
@@ -2340,8 +2375,9 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
   char *buffer = packet->m_body;
   int nChunkSize = r->m_outChunkSize;
 
-  Log(LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket, nSize);
-  while (nSize+hSize)
+  Log(LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket,
+      nSize);
+  while (nSize + hSize)
     {
       int wrote;
 
@@ -2350,15 +2386,15 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
 
       if (header)
        {
-          LogHexString(LOGDEBUG2, header, hSize);
-          LogHexString(LOGDEBUG2, buffer, nChunkSize);
+         LogHexString(LOGDEBUG2, header, hSize);
+         LogHexString(LOGDEBUG2, buffer, nChunkSize);
          wrote = WriteN(r, header, nChunkSize + hSize);
          header = NULL;
-          hSize = 0;
+         hSize = 0;
        }
       else
        {
-          LogHexString(LOGDEBUG2, buffer, nChunkSize);
+         LogHexString(LOGDEBUG2, buffer, nChunkSize);
          wrote = WriteN(r, buffer, nChunkSize);
        }
       if (!wrote)
@@ -2371,19 +2407,19 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
        {
          header = buffer - 1;
          hSize = 1;
-          if (cSize)
-            {
-              header -= cSize;
-              hSize += cSize;
-            }
+         if (cSize)
+           {
+             header -= cSize;
+             hSize += cSize;
+           }
          *header = (0xc0 | c);
-          if (cSize)
-            {
-              int tmp = packet->m_nChannel - 64;
-              header[1] = tmp & 0xff;
-              if (cSize == 2)
-                header[2] = tmp >> 8;
-            }
+         if (cSize)
+           {
+             int tmp = packet->m_nChannel - 64;
+             header[1] = tmp & 0xff;
+             if (cSize == 2)
+               header[2] = tmp >> 8;
+           }
        }
     }
 
@@ -2395,7 +2431,7 @@ RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue)
       Log(LOGDEBUG, "Invoking %s", method.av_val);
       /* keep it in call queue till result arrives */
       if (queue)
-        AV_queue(&r->m_methodCalls, &r->m_numCalls, &method);
+       AV_queue(&r->m_methodCalls, &r->m_numCalls, &method);
     }
 
   if (!r->m_vecChannelsOut[packet->m_nChannel])
@@ -2411,12 +2447,12 @@ RTMP_Serve(RTMP *r)
 }
 
 void
-RTMP_Close(RTMP * r)
+RTMP_Close(RTMP *r)
 {
   int i;
 
   if (RTMP_IsConnected(r))
-    closesocket(r->m_sb.sb_socket);
+    RTMPSockBuf_Close(&r->m_sb);
 
   r->m_stream_id = -1;
   r->m_sb.sb_socket = -1;
@@ -2451,17 +2487,17 @@ RTMP_Close(RTMP * r)
   r->m_sb.sb_size = 0;
 
 #ifdef CRYPTO
-  if(r->Link.dh)
+  if (r->Link.dh)
     {
       DH_free(r->Link.dh);
       r->Link.dh = NULL;
     }
-  if(r->Link.rc4keyIn)
+  if (r->Link.rc4keyIn)
     {
       free(r->Link.rc4keyIn);
       r->Link.rc4keyIn = NULL;
     }
-  if(r->Link.rc4keyOut)
+  if (r->Link.rc4keyOut)
     {
       free(r->Link.rc4keyOut);
       r->Link.rc4keyOut = NULL;
@@ -2480,71 +2516,118 @@ RTMPSockBuf_Fill(RTMPSockBuf *sb)
   while (1)
     {
       nBytes = sizeof(sb->sb_buf) - sb->sb_size - (sb->sb_start - sb->sb_buf);
-      nBytes = recv(sb->sb_socket, sb->sb_start+sb->sb_size, nBytes, 0);
+      if (sb->sb_ssl)
+       {
+         nBytes = SSL_read(sb->sb_ssl, sb->sb_start + sb->sb_size, nBytes);
+       }
+      else
+       {
+         nBytes = recv(sb->sb_socket, sb->sb_start + sb->sb_size, nBytes, 0);
+       }
       if (nBytes != -1)
-        {
-          sb->sb_size += nBytes;
-        }
+       {
+         sb->sb_size += nBytes;
+       }
       else
-        {
-          int sockerr = GetSockError();
-          Log(LOGDEBUG, "%s, recv returned %d. GetSockError(): %d (%s)",
+       {
+         int sockerr = GetSockError();
+         Log(LOGDEBUG, "%s, recv returned %d. GetSockError(): %d (%s)",
              __FUNCTION__, nBytes, sockerr, strerror(sockerr));
-          if (sockerr == EINTR && !RTMP_ctrlC)
+         if (sockerr == EINTR && !RTMP_ctrlC)
            continue;
 
-          if (sockerr == EWOULDBLOCK || sockerr == EAGAIN)
-            {
+         if (sockerr == EWOULDBLOCK || sockerr == EAGAIN)
+           {
              sb->sb_timedout = true;
-              nBytes = 0;
-            }
-        }
+             nBytes = 0;
+           }
+       }
       break;
     }
 
   return nBytes;
 }
 
+int
+RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int len)
+{
+  int rc;
+
+#ifdef _DEBUG
+  fwrite(buf, 1, len, netstackdump);
+#endif
+
+  if (sb->sb_ssl)
+    {
+      rc = SSL_write(sb->sb_ssl, buf, len);
+    }
+  else
+    {
+      rc = send(sb->sb_socket, buf, len, 0);
+    }
+  return rc;
+}
+
+int
+RTMPSockBuf_Close(RTMPSockBuf *sb)
+{
+  int rc;
+
+  if (sb->sb_ssl)
+    {
+      SSL_shutdown(sb->sb_ssl);
+      SSL_free(sb->sb_ssl);
+      sb->sb_ssl = NULL;
+      rc = 0;
+    }
+  else
+    {
+      rc = closesocket(sb->sb_socket);
+    }
+  return rc;
+}
+
 #define HEX2BIN(a)     (((a)&0x40)?((a)&0xf)+9:((a)&0xf))
 
 static void
 DecodeTEA(AVal *key, AVal *text)
 {
-  uint32_t *v, k[4] = {0}, u;
-  uint32_t z, y, sum=0, e, DELTA=0x9e3779b9;
+  uint32_t *v, k[4] = { 0 }, u;
+  uint32_t z, y, sum = 0, e, DELTA = 0x9e3779b9;
   int32_t p, q;
   int i, n;
   unsigned char *ptr, *out;
 
   /* prep key: pack 1st 16 chars into 4 LittleEndian ints */
   ptr = (unsigned char *)key->av_val;
-  u = 0; n = 0;
+  u = 0;
+  n = 0;
   v = k;
-  p = key->av_len > 16 ? 16:key->av_len;
-  for (i=0; i<p; i++)
-    {
-      u |= ptr[i] << (n*8);
-      if (n==3)
-        {
-          *v++ = u;
-          u = 0;
-          n = 0;
-        }
+  p = key->av_len > 16 ? 16 : key->av_len;
+  for (i = 0; i < p; i++)
+    {
+      u |= ptr[i] << (n * 8);
+      if (n == 3)
+       {
+         *v++ = u;
+         u = 0;
+         n = 0;
+       }
       else
-        {
-          n++;
-        }
+       {
+         n++;
+       }
     }
   /* any trailing chars */
   if (u)
     *v = u;
 
   /* prep text: hex2bin, multiples of 4 */
-  n = (text->av_len+7)/8;
-  out = malloc(n*8);
+  n = (text->av_len + 7) / 8;
+  out = malloc(n * 8);
   ptr = (unsigned char *)text->av_val;
-  v = (uint32_t *)out;
-  for (i=0; i<n; i++)
+  v = (uint32_t *) out;
+  for (i = 0; i < n; i++)
     {
       u = (HEX2BIN(ptr[0]) << 4) + HEX2BIN(ptr[1]);
       u |= ((HEX2BIN(ptr[2]) << 4) + HEX2BIN(ptr[3])) << 8;
@@ -2553,19 +2636,20 @@ DecodeTEA(AVal *key, AVal *text)
       *v++ = u;
       ptr += 8;
     }
-  v = (uint32_t *)out;
+  v = (uint32_t *) out;
 
   /* http://www.movable-type.co.uk/scripts/tea-block.html */
 #define MX (((z>>5)^(y<<2)) + ((y>>3)^(z<<4))) ^ ((sum^y) + (k[(p&3)^e]^z));
-  z=v[n-1];
-  y=v[0];
-  q = 6+52/n ;
-  sum = q*DELTA ;
+  z = v[n - 1];
+  y = v[0];
+  q = 6 + 52 / n;
+  sum = q * DELTA;
   while (sum != 0)
     {
-      e = sum>>2 & 3;
-      for (p=n-1; p>0; p--) z = v[p-1], y = v[p] -= MX;
-      z = v[n-1];
+      e = sum >> 2 & 3;
+      for (p = n - 1; p > 0; p--)
+       z = v[p - 1], y = v[p] -= MX;
+      z = v[n - 1];
       y = v[0] -= MX;
       sum -= DELTA;
     }
index 78ec049..8ef747f 100644 (file)
 #include "amf.h"
 
 #ifdef __cplusplus
-extern "C" {
+extern "C"
+{
 #endif
 
+#define RTMP_FEATURE_HTTP      0x01    // not yet supported
+#define RTMP_FEATURE_ENC       0x02
+#define RTMP_FEATURE_SSL       0x04
+#define RTMP_FEATURE_MFP       0x08    // not yet supported
+
 #define RTMP_PROTOCOL_UNDEFINED        -1
 #define RTMP_PROTOCOL_RTMP      0
-#define RTMP_PROTOCOL_RTMPT     1      // not yet supported
-#define RTMP_PROTOCOL_RTMPS     2      // not yet supported
-#define RTMP_PROTOCOL_RTMPE     3
-#define RTMP_PROTOCOL_RTMPTE    4      // not yet supported
-#define RTMP_PROTOCOL_RTMFP     5      // not yet supported
+#define RTMP_PROTOCOL_RTMPE     RTMP_FEATURE_ENC
+#define RTMP_PROTOCOL_RTMPT     RTMP_FEATURE_HTTP
+#define RTMP_PROTOCOL_RTMPS     (RTMP_FEATURE_HTTP|RTMP_FEATURE_SSL)
+#define RTMP_PROTOCOL_RTMPTE    (RTMP_FEATURE_HTTP|RTMP_FEATURE_ENC)
+#define RTMP_PROTOCOL_RTMFP     RTMP_FEATURE_MFP
 
 #define RTMP_DEFAULT_CHUNKSIZE 128
 
-#define RTMP_BUFFER_CACHE_SIZE (16*1024) // needs to fit largest number of bytes recv() may return
+#define RTMP_BUFFER_CACHE_SIZE (16*1024)       // needs to fit largest number of bytes recv() may return
 
 #define        RTMP_CHANNELS   65600
 
-extern const char RTMPProtocolStringsLower[][7];
-extern const AVal RTMP_DefaultFlashVer;
-extern bool RTMP_ctrlC;
+  extern const char RTMPProtocolStringsLower[][7];
+  extern const AVal RTMP_DefaultFlashVer;
+  extern bool RTMP_ctrlC;
 
-uint32_t RTMP_GetTime();
+  uint32_t RTMP_GetTime();
 
 #define RTMP_PACKET_TYPE_AUDIO 0x08
 #define RTMP_PACKET_TYPE_VIDEO 0x09
@@ -90,185 +96,191 @@ uint32_t RTMP_GetTime();
 #define RTMP_PACKET_SIZE_SMALL    2
 #define RTMP_PACKET_SIZE_MINIMUM  3
 
-typedef unsigned char BYTE;
-
-typedef struct RTMPChunk
-{
-  int c_headerSize;
-  int c_chunkSize;
-  char *c_chunk;
-  char c_header[RTMP_MAX_HEADER_SIZE];
-} RTMPChunk;
-
-typedef struct RTMPPacket
-{
-  BYTE m_headerType;
-  BYTE m_packetType;
-  BYTE m_hasAbsTimestamp;      // timestamp absolute or relative?
-  int m_nChannel;
-  uint32_t m_nInfoField1;      // 3 first bytes
-  int32_t m_nInfoField2;       // last 4 bytes in a long header, absolute timestamp for long headers, relative timestamp for short headers
-  uint32_t m_nTimeStamp;       // absolute timestamp
-  uint32_t m_nBodySize;
-  uint32_t m_nBytesRead;
-  RTMPChunk *m_chunk;
-  char *m_body;
-} RTMPPacket;
-
-typedef struct RTMPSockBuf
-{
-  int sb_socket;
-  int sb_size;                         /* number of unprocessed bytes in buffer */
-  char *sb_start;                      /* pointer into sb_pBuffer of next byte to process */
-  char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */
-  bool sb_timedout;
-} RTMPSockBuf;
-
-void RTMPPacket_Reset(RTMPPacket *p);
-void RTMPPacket_Dump(RTMPPacket *p);
-bool RTMPPacket_Alloc(RTMPPacket *p, int nSize);
-void RTMPPacket_Free(RTMPPacket *p);
+  typedef unsigned char BYTE;
+
+  typedef struct RTMPChunk
+  {
+    int c_headerSize;
+    int c_chunkSize;
+    char *c_chunk;
+    char c_header[RTMP_MAX_HEADER_SIZE];
+  } RTMPChunk;
+
+  typedef struct RTMPPacket
+  {
+    BYTE m_headerType;
+    BYTE m_packetType;
+    BYTE m_hasAbsTimestamp;    // timestamp absolute or relative?
+    int m_nChannel;
+    uint32_t m_nInfoField1;    // 3 first bytes
+    int32_t m_nInfoField2;     // last 4 bytes in a long header, absolute timestamp for long headers, relative timestamp for short headers
+    uint32_t m_nTimeStamp;     // absolute timestamp
+    uint32_t m_nBodySize;
+    uint32_t m_nBytesRead;
+    RTMPChunk *m_chunk;
+    char *m_body;
+  } RTMPPacket;
+
+  typedef struct RTMPSockBuf
+  {
+    int sb_socket;
+    int sb_size;               /* number of unprocessed bytes in buffer */
+    char *sb_start;            /* pointer into sb_pBuffer of next byte to process */
+    char sb_buf[RTMP_BUFFER_CACHE_SIZE];       /* data read from socket */
+    bool sb_timedout;
+    void *sb_ssl;
+  } RTMPSockBuf;
+
+  void RTMPPacket_Reset(RTMPPacket *p);
+  void RTMPPacket_Dump(RTMPPacket *p);
+  bool RTMPPacket_Alloc(RTMPPacket *p, int nSize);
+  void RTMPPacket_Free(RTMPPacket *p);
 
 #define RTMPPacket_IsReady(a)  ((a)->m_nBytesRead == (a)->m_nBodySize)
 
-typedef struct RTMP_LNK
-{
-  const char *hostname;
-  unsigned int port;
-  int protocol;
-
-  AVal playpath;
-  AVal tcUrl;
-  AVal swfUrl;
-  AVal pageUrl;
-  AVal app;
-  AVal auth;
-  AVal flashVer;
-  AVal subscribepath;
-  AVal token;
-  AVal playpath0;
-  AMFObject extras;
-
-  double seekTime;
-  uint32_t length;
-  bool authflag;
-  bool bLiveStream;
-
-  int timeout;         // number of seconds before connection times out
-
-  const char *sockshost;
-  unsigned short socksport;
+  typedef struct RTMP_LNK
+  {
+    const char *hostname;
+    unsigned int port;
+    int protocol;
+
+    AVal playpath;
+    AVal tcUrl;
+    AVal swfUrl;
+    AVal pageUrl;
+    AVal app;
+    AVal auth;
+    AVal flashVer;
+    AVal subscribepath;
+    AVal token;
+    AVal playpath0;
+    AMFObject extras;
+
+    double seekTime;
+    uint32_t length;
+    bool authflag;
+    bool bLiveStream;
+
+    int timeout;               // number of seconds before connection times out
+
+    const char *sockshost;
+    unsigned short socksport;
 
 #ifdef CRYPTO
-  void *dh;                    // for encryption
-  void *rc4keyIn;
-  void *rc4keyOut;
+    void *dh;                  // for encryption
+    void *rc4keyIn;
+    void *rc4keyOut;
 
-  AVal SWFHash;
-  uint32_t SWFSize;
-  char SWFVerificationResponse[42];
+    AVal SWFHash;
+    uint32_t SWFSize;
+    char SWFVerificationResponse[42];
 #endif
-} RTMP_LNK;
-
-typedef struct RTMP
-{
-  int m_inChunkSize;
-  int m_outChunkSize;
-  int m_nBWCheckCounter;
-  int m_nBytesIn;
-  int m_nBytesInSent;
-  int m_nBufferMS;
-  int m_stream_id;             // returned in _result from invoking createStream
-  int m_mediaChannel;
-  uint32_t m_mediaStamp;
-  uint32_t m_pauseStamp;
-  int m_pausing;
-  int m_nServerBW;
-  int m_nClientBW;
-  uint8_t m_nClientBW2;
-  bool m_bPlaying;
-  bool m_bSendEncoding;
-  bool m_bSendCounter;
-
-  AVal *m_methodCalls;         /* remote method calls queue */
-  int m_numCalls;
-
-  RTMP_LNK Link;
-  RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS];
-  RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS];
-  int m_channelTimestamp[RTMP_CHANNELS];       // abs timestamp of last packet
-
-  double m_fAudioCodecs;       // audioCodecs for the connect packet
-  double m_fVideoCodecs;       // videoCodecs for the connect packet
-  double m_fEncoding;          /* AMF0 or AMF3 */
-
-  double m_fDuration;          // duration of stream in seconds
-
-  RTMPSockBuf m_sb;
-} RTMP;
-
-bool RTMP_ParseURL(const char *url, int *protocol, char **host,
-       unsigned int *port, AVal *playpath, AVal *app);
-void RTMP_ParsePlaypath(AVal *in, AVal *out);
-void RTMP_SetBufferMS(RTMP *r, int size);
-void RTMP_UpdateBufferMS(RTMP *r);
-
-void RTMP_SetupStream(RTMP *r, int protocol,
-                     const char *hostname,
-                     unsigned int port,
-                     const char *sockshost,
-                     AVal *playpath,
-                     AVal *tcUrl,
-                     AVal *swfUrl,
-                     AVal *pageUrl,
-                     AVal *app,
-                     AVal *auth,
-                     AVal *swfSHA256Hash,
-                     uint32_t swfSize,
-                     AVal *flashVer,
-                     AVal *subscribepath,
-                     double dTime,
-                     uint32_t dLength, bool bLiveStream, long int timeout);
-
-bool RTMP_Connect(RTMP *r, RTMPPacket *cp);
-bool RTMP_Connect0(RTMP *r, struct sockaddr *svc);
-bool RTMP_Connect1(RTMP *r, RTMPPacket *cp);
-bool RTMP_Serve(RTMP *r);
-
-bool RTMP_ReadPacket(RTMP * r, RTMPPacket * packet);
-bool RTMP_SendPacket(RTMP * r, RTMPPacket * packet, bool queue);
-bool RTMP_SendChunk(RTMP * r, RTMPChunk *chunk);
-bool RTMP_IsConnected(RTMP *r);
-bool RTMP_IsTimedout(RTMP *r);
-double RTMP_GetDuration(RTMP *r);
-bool RTMP_ToggleStream(RTMP *r);
-
-bool RTMP_ConnectStream(RTMP *r, double seekTime, uint32_t dLength);
-bool RTMP_ReconnectStream(RTMP *r, int bufferTime, double seekTime, uint32_t dLength);
-void RTMP_DeleteStream(RTMP *r);
-int RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet);
-int RTMP_ClientPacket(RTMP *r, RTMPPacket *packet);
-
-void RTMP_Init(RTMP *r);
-void RTMP_Close(RTMP *r);
-
-bool RTMP_SendCtrl(RTMP * r, short nType, unsigned int nObject, unsigned int nTime);
-bool RTMP_SendPause(RTMP *r, bool DoPause, double dTime);
-bool RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name,
-                                     AMFObjectProperty *p);
-
-bool RTMPSockBuf_Fill(RTMPSockBuf *sb);
-
-bool RTMP_SendCreateStream(RTMP * r, double dCmdID);
-bool RTMP_SendSeek(RTMP * r, double dTime);
-bool RTMP_SendServerBW(RTMP * r);
-void RTMP_DropRequest(RTMP *r, int i, bool freeit);
+  } RTMP_LNK;
+
+  typedef struct RTMP
+  {
+    int m_inChunkSize;
+    int m_outChunkSize;
+    int m_nBWCheckCounter;
+    int m_nBytesIn;
+    int m_nBytesInSent;
+    int m_nBufferMS;
+    int m_stream_id;           // returned in _result from invoking createStream
+    int m_mediaChannel;
+    uint32_t m_mediaStamp;
+    uint32_t m_pauseStamp;
+    int m_pausing;
+    int m_nServerBW;
+    int m_nClientBW;
+    uint8_t m_nClientBW2;
+    bool m_bPlaying;
+    bool m_bSendEncoding;
+    bool m_bSendCounter;
+
+    AVal *m_methodCalls;       /* remote method calls queue */
+    int m_numCalls;
+
+    RTMP_LNK Link;
+    RTMPPacket *m_vecChannelsIn[RTMP_CHANNELS];
+    RTMPPacket *m_vecChannelsOut[RTMP_CHANNELS];
+    int m_channelTimestamp[RTMP_CHANNELS];     // abs timestamp of last packet
+
+    double m_fAudioCodecs;     // audioCodecs for the connect packet
+    double m_fVideoCodecs;     // videoCodecs for the connect packet
+    double m_fEncoding;                /* AMF0 or AMF3 */
+
+    double m_fDuration;                // duration of stream in seconds
+
+    RTMPSockBuf m_sb;
+  } RTMP;
+
+  bool RTMP_ParseURL(const char *url, int *protocol, char **host,
+                    unsigned int *port, AVal *playpath, AVal *app);
+  void RTMP_ParsePlaypath(AVal *in, AVal *out);
+  void RTMP_SetBufferMS(RTMP *r, int size);
+  void RTMP_UpdateBufferMS(RTMP *r);
+
+  void RTMP_SetupStream(RTMP *r, int protocol,
+                       const char *hostname,
+                       unsigned int port,
+                       const char *sockshost,
+                       AVal *playpath,
+                       AVal *tcUrl,
+                       AVal *swfUrl,
+                       AVal *pageUrl,
+                       AVal *app,
+                       AVal *auth,
+                       AVal *swfSHA256Hash,
+                       uint32_t swfSize,
+                       AVal *flashVer,
+                       AVal *subscribepath,
+                       double dTime,
+                       uint32_t dLength, bool bLiveStream, long int timeout);
+
+  bool RTMP_Connect(RTMP *r, RTMPPacket *cp);
+  bool RTMP_Connect0(RTMP *r, struct sockaddr *svc);
+  bool RTMP_Connect1(RTMP *r, RTMPPacket *cp);
+  bool RTMP_Serve(RTMP *r);
+
+  bool RTMP_ReadPacket(RTMP *r, RTMPPacket *packet);
+  bool RTMP_SendPacket(RTMP *r, RTMPPacket *packet, bool queue);
+  bool RTMP_SendChunk(RTMP *r, RTMPChunk *chunk);
+  bool RTMP_IsConnected(RTMP *r);
+  bool RTMP_IsTimedout(RTMP *r);
+  double RTMP_GetDuration(RTMP *r);
+  bool RTMP_ToggleStream(RTMP *r);
+
+  bool RTMP_ConnectStream(RTMP *r, double seekTime, uint32_t dLength);
+  bool RTMP_ReconnectStream(RTMP *r, int bufferTime, double seekTime,
+                           uint32_t dLength);
+  void RTMP_DeleteStream(RTMP *r);
+  int RTMP_GetNextMediaPacket(RTMP *r, RTMPPacket *packet);
+  int RTMP_ClientPacket(RTMP *r, RTMPPacket *packet);
+
+  void RTMP_Init(RTMP *r);
+  void RTMP_Close(RTMP *r);
+
+  bool RTMP_SendCtrl(RTMP *r, short nType, unsigned int nObject,
+                    unsigned int nTime);
+  bool RTMP_SendPause(RTMP *r, bool DoPause, double dTime);
+  bool RTMP_FindFirstMatchingProperty(AMFObject *obj, const AVal *name,
+                                     AMFObjectProperty * p);
+
+  bool RTMPSockBuf_Fill(RTMPSockBuf *sb);
+  int RTMPSockBuf_Send(RTMPSockBuf *sb, const char *buf, int len);
+  int RTMPSockBuf_Close(RTMPSockBuf *sb);
+
+  bool RTMP_SendCreateStream(RTMP *r, double dCmdID);
+  bool RTMP_SendSeek(RTMP *r, double dTime);
+  bool RTMP_SendServerBW(RTMP *r);
+  void RTMP_DropRequest(RTMP *r, int i, bool freeit);
 
 #ifdef CRYPTO
 /* hashswf.c */
 #define HASHLEN        32
 
-int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash, int age);
+  int RTMP_HashSWF(const char *url, unsigned int *size, unsigned char *hash,
+                  int age);
 #endif
 
 #ifdef __cplusplus