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; }