shithub: rtmp

Download patch

ref: f6d84677e9cd1cd4725391a577295ff561e09443
parent: c4f625f3c3c5cacce9c401254430cf74f6a68847
author: Sigrid Solveig Haflínudóttir <[email protected]>
date: Mon Jul 26 11:17:52 EDT 2021

more wip logic

--- a/amf.c
+++ b/amf.c
@@ -158,3 +158,35 @@
 {
 	return amfstr(amfkv(p, e, name), e, v);
 }
+
+u8int *
+amfbyteget(u8int *p, u8int *e, u8int *byte)
+{
+	atleast(1);
+	*byte = *p;
+	return p+1;
+}
+
+u8int *
+amfi16get(u8int *p, u8int *e, s16int *i)
+{
+	atleast(2);
+	*i = p[0]<<8 | p[1];
+	return p+2;
+}
+
+u8int *
+amfi24get(u8int *p, u8int *e, s32int *i)
+{
+	atleast(3);
+	*i = p[0]<<16 | p[1]<<8 | p[2];
+	return p+3;
+}
+
+u8int *
+amfi32get(u8int *p, u8int *e, s32int *i)
+{
+	atleast(4);
+	*i = p[0]<<16 | p[1]<<16 | p[2]<<8 | p[3];
+	return p+4;
+}
--- a/amf.h
+++ b/amf.h
@@ -11,3 +11,8 @@
 u8int *amfkvnum(u8int *p, u8int *e, char *name, double v);
 u8int *amfkvstr(u8int *p, u8int *e, char *name, char *v);
 u8int *amfkvbool(u8int *p, u8int *e, char *name, int v);
+
+u8int *amfbyteget(u8int *p, u8int *e, u8int *byte);
+u8int *amfi16get(u8int *p, u8int *e, s16int *i);
+u8int *amfi24get(u8int *p, u8int *e, s32int *i);
+u8int *amfi32get(u8int *p, u8int *e, s32int *i);
--- a/main.c
+++ b/main.c
@@ -7,6 +7,7 @@
 #include "rtmp.h"
 
 int mainstacksize = 65536;
+int debug = 0;
 
 static void
 usage(void)
@@ -29,6 +30,9 @@
 	a = nil;
 	v = nil;
 	ARGBEGIN{
+	case 'd':
+		debug++;
+		break;
 	case 'D':
 		rtmpdump++;
 		break;
--- a/rtmp.c
+++ b/rtmp.c
@@ -37,6 +37,9 @@
 	u32int ts;
 	u8int *data;
 	int sz;
+	int left;
+	Packet *prev;
+	Packet *next;
 };
 
 struct RTMP {
@@ -45,6 +48,7 @@
 	char *path;
 	char *tcurl;
 	Packet pk;
+	Packet *ch;
 	u8int *b, *p, *e;
 	int mode;
 	int bsz;
@@ -66,8 +70,41 @@
 #define putkvbool(name, s) do{ r->p = amfkvbool(r->p, r->e, name, s); }while(0)
 
 int rtmpdump = 0;
+extern int debug;
 
+static Packet *
+pk4chan(RTMP *r, int chan)
+{
+	Packet *p;
+
+	for(p = r->ch; p != nil && p->chan != chan; p = p->next);
+
+	if(p == nil){
+		if((p = calloc(1, sizeof(*p))) == nil)
+			sysfatal("memory");
+		p->type = -1;
+		p->chan = chan;
+		if((p->next = r->ch) != nil)
+			r->ch->prev = p;
+	}
+
+	return p;
+}
+
 static void
+pkfree(RTMP *r, Packet *p)
+{
+	if(p->prev != nil)
+		p->prev->next = p->next;
+	if(p->next != nil)
+		p->next->prev = p->prev;
+	if(r->ch == p)
+		r->ch = p->next;
+
+	free(p->data);
+}
+
+static void
 newpacket(RTMP *r, int type, int hsz, int chan)
 {
 	memset(&r->pk, 0, sizeof(r->pk));
@@ -85,6 +122,22 @@
 	}
 }
 
+static void
+bextend(RTMP *r, int bsz)
+{
+	u8int *ob;
+
+	if(r->bsz >= bsz)
+		return;
+	ob = r->b;
+	if((r->b = realloc(r->b, bsz*2)) == nil)
+		sysfatal("memory");
+	if(ob != nil)
+		r->p = r->b + (intptr)(ob - r->p);
+	r->bsz *= 2;
+	r->e = r->b + r->bsz;
+}
+
 static int
 handshake(int f)
 {
@@ -118,6 +171,60 @@
 }
 
 static int
+rtmprecv(RTMP *r)
+{
+	u8int *h, *e, type;
+	int hsz, chan, bodysz, dummy;
+	u32int ts;
+
+	r->p = r->b;
+	if(readn(r->i, r->p, 1) != 1)
+		goto err;
+	hsz = (r->p[0] & 0xc0)>>6;
+	chan = r->p[0] & 0x3f;
+	if(debug)
+		fprint(2, "hsz=%d chan=%d\n", hsz, chan);
+	if(readn(r->i, r->p+1, hsz-1) != hsz-1)
+		goto err;
+
+	memset(&r->pk, 0, sizeof(r->pk));
+	r->pk.hsz = hsz;
+	r->pk.chan = chan;
+
+	h = r->p + 1;
+	e = r->p + hsz;
+	r->pk.type = -1;
+	bodysz = 0;
+	if(hsz >= SzSmall){
+		h = amfi24get(h, e, (s32int*)&ts); /* FIXME proper timestamps? */
+		if(hsz >= SzMedium){
+			h = amfi24get(h, e, &bodysz);
+			h = amfbyteget(h, e, &type);
+			r->pk.type = type;
+			if(hsz >= SzLarge)
+				h = amfi32get(h, e, &dummy); /* FIXME seems to be always 0? */
+		}
+	}
+
+	if(ts == 0xffffff){ /* exntended timestamp */
+		if(readn(r->i, h, 4) != 4)
+			goto err;
+		h = amfi32get(h, h+4, (s32int*)&ts);
+	}
+
+	bextend(r, bodysz);
+	if(readn(r->i, h, bodysz) != bodysz)
+		goto err;
+	h += bodysz;
+
+	return 0;
+
+err:
+	werrstr("rtmprecv: %r");
+	return -1;
+}
+
+static int
 rtmpsend(RTMP *r)
 {
 	int bodysz, n, hsz;
@@ -147,7 +254,6 @@
 	hsz = e - r->b;
 	for(; hsz+bodysz > 0;){
 		n = min(bodysz, Chunk);
-		fprint(2, "header is %d bytes, writing %d+%d=%d\n", hsz, hsz, n, hsz+n);
 		if(Bwrite(r, p, hsz+n) < 0)
 			goto err;
 		if(rtmpdump)
@@ -162,6 +268,7 @@
 	}
 
 	r->p = nil;
+	Bflush(r);
 
 	return 0;
 err:
@@ -247,16 +354,15 @@
 
 	if(handshake(f) != 0)
 		goto err;
-	if((r = calloc(1, sizeof(*r))) == nil || (r->b = malloc(Bufsz)) == nil)
+	if((r = calloc(1, sizeof(*r))) == nil)
 		sysfatal("memory");
 	if((r->app = strdup(app)) == nil || (path != nil && (r->path = strdup(path)) == nil))
 		sysfatal("memory");
+	bextend(r, Bufsz);
 	r->tcurl = url;
-	r->bsz = Bufsz;
-	r->e = r->b + r->bsz;
 	Binits(r, f, OWRITE, r->biobuf, sizeof(r->biobuf));
 	r->i = f;
-	if(connect(r) != 0)
+	if(connect(r) != 0 || rtmprecv(r) != 0)
 		goto err;
 
 	return r;