$ 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