ref: f6d84677e9cd1cd4725391a577295ff561e09443
parent: c4f625f3c3c5cacce9c401254430cf74f6a68847
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
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;