$ git clone http://tcclient.ion.nu/tc_client.git
commit eec5f91f13e24300ce9202b0e7d7cbed378febc0
Author: Alicia <...>
Date:   Thu Dec 29 01:44:54 2016 +0100

    Improved RTMP compatibility by responding to RTMP ping requests and always starting new chunk streams with a format 0 packet.

diff --git a/ChangeLog b/ChangeLog
index dfdb76e..4a4583d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+0.42:
+Improved RTMP compatibility by responding to RTMP ping requests and always starting new chunk streams with a format 0 packet.
 0.41.1:
 Use tinychat.com instead of apl.tinychat.com (works around SSL/TLS issues on windows)
 0.41:
diff --git a/rtmp.c b/rtmp.c
index f86e12c..e237cce 100644
--- a/rtmp.c
+++ b/rtmp.c
@@ -150,6 +150,20 @@ char rtmp_get(int sock, struct rtmp* rtmp)
     {
       uint32_t bytes=*(unsigned int*)chunk->buf;
       rtmpack=be32(bytes)+ackwindow;
+      free(chunk->buf);
+      chunk->buf=0;
+      return 2;
+    }
+    else if(chunk->type==RTMP_PING)
+    {
+      if(!memcmp(chunk->buf, "\x00\x06", 2)) // Ping request
+      {
+        ((unsigned char*)chunk->buf)[1]=7;
+        struct rtmp pong={.type=RTMP_PING, .chunkid=2, .length=chunk->length, .msgid=0, .buf=chunk->buf};
+        rtmp_send(sock, &pong);
+      }
+      free(chunk->buf);
+      chunk->buf=0;
       return 2;
     }
 // printf("Got chunk: chunkid=%u, type=%u, length=%u, streamid=%u\n", chunk->id, chunk->type, chunk->length, chunk->streamid);
@@ -166,14 +180,43 @@ char rtmp_get(int sock, struct rtmp* rtmp)
   return 2;
 }
 
-char firstpacket=1;
+static char firstpacket(unsigned int chunkid)
+{
+/* Possibly over-optimized, not sure if it's even any faster
+  static char* ids=0;
+  static unsigned int size;
+  if(chunkid<size)
+  {
+    char ret=ids[chunkid];
+    ids[chunkid]=0;
+    return ret;
+  }else{
+    ids=realloc(ids, chunkid+1);
+    memset(&ids[size], 1, chunkid-size);
+    size=chunkid+1;
+    return (ids[chunkid]=0);
+  }
+*/
+  static unsigned int* notfirst=0;
+  static unsigned int count=0;
+  unsigned int i;
+  for(i=0; i<count; ++i)
+  {
+    if(notfirst[i]==chunkid){return 0;}
+  }
+  ++count;
+  notfirst=realloc(notfirst, sizeof(unsigned int)*count);
+  notfirst[count-1]=chunkid;
+  return 1;
+}
+
 void rtmp_send(int sock, struct rtmp* rtmp)
 {
   #define rwrite(x,y,z) write(x,y,z); rtmpsent+=z // Add to the data sent counter
   if(rtmpsent>rtmpack && rtmp->type==RTMP_VIDEO){return;}
   // Header format and stream ID
   unsigned int fmt=(rtmp->msgid?0:1);
-  if(firstpacket){firstpacket=fmt=0;}
+  if(firstpacket(rtmp->chunkid)){fmt=0;}
   unsigned char basicheader=(rtmp->chunkid<64?rtmp->chunkid:(rtmp->chunkid<256?0:1)) | (fmt<<6);
   rwrite(sock, &basicheader, sizeof(basicheader));
   if(rtmp->chunkid>=64) // Handle large stream IDs
@@ -220,3 +263,17 @@ void rtmp_send(int sock, struct rtmp* rtmp)
   }
   rtmpsent+=rtmp->length;
 }
+
+void rtmp_handshake(int sock)
+{
+  int random=open("/dev/urandom", O_RDONLY);
+  unsigned char handshake[1536];
+  read(random, handshake, 1536);
+  close(random);
+  write(sock, "\x03", 1); // Send 0x03 and 1536 bytes of random junk
+  write(sock, handshake, 1536);
+  fullread(sock, handshake, 1); // Receive server's 0x03+junk
+  fullread(sock, handshake, 1536);
+  write(sock, handshake, 1536); // Send server's junk back
+  fullread(sock, handshake, 1536); // Read our junk back, we don't bother checking that it's the same
+}
diff --git a/rtmp.h b/rtmp.h
index e21726a..c5d1b50 100644
--- a/rtmp.h
+++ b/rtmp.h
@@ -14,6 +14,8 @@
     You should have received a copy of the GNU Affero General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
+#ifndef RTMP_H
+#define RTMP_H
 #define RTMP_SET_PACKET_SIZE 0x01
 #define RTMP_ACKNOWLEDGEMENT 0x03
 #define RTMP_PING            0x04
@@ -37,3 +39,5 @@ struct rtmp
 extern size_t fullread(int fd, void* buf, size_t len);
 extern char rtmp_get(int sock, struct rtmp* rtmp);
 extern void rtmp_send(int sock, struct rtmp* rtmp);
+extern void rtmp_handshake(int sock);
+#endif