ref: 0ec0e4fde657c442431548180c91018078c2bf3c
dir: /rtmp.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>
#include <libsec.h>
#include "amf.h"
#include "ivf.h"
#include "rtmp.h"
enum {
Port = 1935,
Sigsz = 1536,
ChanCtl = 3,
SzLarge,
SzMedium,
SzSmall,
SzTiny,
PktInvoke = 20,
};
typedef struct RTMPacket RTMPacket;
struct RTMP {
int f;
int invokes;
};
struct RTMPacket {
int chan;
int sztype;
int pktype;
u32int ts;
u8int *data;
int sz;
};
static int
handshake(int f)
{
u8int cl[1+Sigsz], sv[1+Sigsz];
cl[0] = 3; /* no encryption */
memset(cl+1, 0, 8);
prng(cl+1+8, Sigsz-8);
if(write(f, cl, sizeof(cl)) != sizeof(cl))
goto err;
if(readn(f, sv, sizeof(sv)) != sizeof(sv))
goto err;
if(cl[0] != sv[0]){
werrstr("expected %d (no encryption), got %d", cl[0], sv[0]);
goto err;
}
if(write(f, sv+1, Sigsz) != Sigsz)
goto err;
if(readn(f, sv+1, Sigsz) != Sigsz)
goto err;
if(memcmp(cl, sv, sizeof(cl)) != 0){
werrstr("signature mismatch");
goto err;
}
return 0;
err:
werrstr("handshake: %r");
return -1;
}
static int
connect(int f, char *path)
{
RTMPacket p;
memset(&p, 0, sizeof(p));
p.chan = ChanCtl;
p.sztype = SzLarge;
p.pktype = PktInvoke;
return -1;
}
static int
rtmpsend(RTMP *r, RTMPacket *p)
{
return -1;
}
RTMP *
rtmpdial(char *url)
{
char *s, *e, *path;
int f, port, ctl;
RTMP *r;
f = -1;
if(memcmp(url, "rtmp://", 7) != 0){
werrstr("invalid url");
goto err;
}
s = url + 7;
if((e = strpbrk(s, ":/")) == nil){
werrstr("no path");
goto err;
}
port = 1935;
if(*e == ':'){
if((port = strtol(e+1, &path, 10)) < 1 || path == e+1 || *path != '/'){
werrstr("invalid port");
goto err;
}
}else{
path = e;
}
s = smprint("tcp!%.*s!%d", (int)(e-s), s, port);
f = dial(s, nil, nil, &ctl);
free(s);
if(f < 0)
goto err;
if(handshake(f) != 0 || connect(f, path) == 0)
goto err;
if((r = calloc(1, sizeof(*r))) == nil)
sysfatal("memory");
r->f = f;
return r;
err:
werrstr("rtmpdial: %r");
if(f >= 0)
close(f);
return nil;
}