shithub: rd

Download patch

ref: 142b452d762c751ee0c01c559f2bbfb938934e75
parent: dd10b5ab57391a959da5b8dd586bc372e916b43f
author: Yaroslav Kolomiiets <yarikos@gmail.com>
date: Wed Aug 10 09:12:00 EDT 2016

basic primitives for RPDSND support

--- /dev/null
+++ b/audio.c
@@ -1,0 +1,91 @@
+/* [MS-RDPEA]: Remote Desktop Protocol: Audio Output Virtual Channel Extension */
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+static char	rdpsnd[]				= "RDPSND";
+
+enum	/* Audiomsg.type */
+{
+	Awav=	2,	/* WaveInfo PDU */
+	Awavack=	5,	/* Wave Confirm PDU */
+	Aprobe=	6,	/* Training PDU or Training Confirm PDU */
+	Afmt=	7,	/* Client/Server Audio Formats and Version PDU */
+		/* 2.2.1 RDPSND PDU Header (SNDPROLOG) */
+};
+typedef	struct	Audiomsg Audiomsg;
+struct Audiomsg
+{
+	uint	type;
+	uint	nfmt;	/* Afmt */
+	uint	ack;	/* Afmt */
+	uint	ver;	/* Afmt */
+	uchar	*data;	/* Afmt */
+	uint	ndata;	/* Afmt */
+};
+static	int	getaudiomsg(Audiomsg*,uchar*,int);
+static	int	putaudiomsg(uchar*,int, Audiomsg*);
+
+enum
+{
+	FmtPCM=	0x01,	/* WAVE_FORMAT_PCM */
+	FmtMP3=	0x55,	/* WAVE_FORMAT_MPEGLAYER3 */
+		/* RFC2361 Appendix A */
+};
+
+
+void
+audiovcfn(Rdp*, uchar* a, uint nb)
+{
+	Audiomsg r;
+
+fprint(2, " A ");
+	if(getaudiomsg(&r, a, nb) < 0){
+		fprint(2, "audio: %r\n");
+		return;
+	}
+fprint(2, " a%ud ", r.type);
+}
+
+
+/*
+ * 2.2.1 RDPSND PDU Header (SNDPROLOG)
+ *	msgtype[1] pad[1] bodysize[2]
+ *
+ * 2.2.2.1 Server Audio Formats and Version PDU
+ *	hdr[4] flags[4] vol[4] pitch[4] dgport[2] nfmt[2] ack[1] ver[2] pad[1] nfmt*(afmt[*])
+ *
+ * 2.2.2.1.1 Audio Format (AUDIO_FORMAT)
+ *	ftag[2] nchan[2] samphz[4] avgbytehz[4] blocksz[2] sampbitsz[2] ndata[2] data[ndata]
+ */
+
+static int
+getaudiomsg(Audiomsg* m, uchar* a, int nb)
+{
+	ulong len;
+
+	if(nb < 4){
+		werrstr(Eshort);
+		return -1;
+	}
+	
+	m->type = *a;
+	len = GSHORT(a+2);
+	switch(m->type){
+	case Afmt:
+		if(len < 20 || nb < len+4){
+			werrstr(Eshort);
+			return -1;
+		}
+		m->nfmt = GSHORT(a+18);
+		m->ack = a[20];
+		m->ver = GSHORT(a+21);
+		m->data = a+24;
+		m->ndata = len-20;
+		return len+4;
+	}
+	werrstr("unrecognized audio msg type");
+	return -1;
+}
+
--- a/dat.h
+++ b/dat.h
@@ -63,6 +63,7 @@
 void	readnet(Rdp*);
 void	clipannounce(Rdp*);
 void	clipvcfn(Rdp*, uchar*,uint);
+void	audiovcfn(Rdp*, uchar*,uint);
 void	pollsnarf(Rdp*);
 
 void	initscreen(Rdp*);
--- a/mkfile
+++ b/mkfile
@@ -7,6 +7,7 @@
 HFILES=fns.h dat.h
 OFILES=\
 	alloc.$O\
+	audio.$O\
 	cap.$O\
 	draw.$O\
 	eclip.$O\
@@ -30,6 +31,7 @@
 
 THREADOFILES=\
 	alloc.$O\
+	audio.$O\
 	cap.$O\
 	draw.$O\
 	eclip.$O\
--- a/rpc.c
+++ b/rpc.c
@@ -111,7 +111,7 @@
 joinchannel(Rdp* c, int mcsuid, int chanid)
 {
 	Msg t, r;
-	
+
 	t.type = Mjoin;
 	t.mcsuid = mcsuid;
 	t.chanid = chanid;
--- a/vchan.c
+++ b/vchan.c
@@ -29,6 +29,12 @@
 		.fn = clipvcfn,
 		.flags = Inited,
 	},
+	{
+		.mcsid = GLOBALCHAN+2,
+		.name = "RDPSND",
+		.fn = audiovcfn,
+		.flags = Inited,
+	},
 };
 static uint nvc = nelem(vctab);
 
@@ -68,8 +74,10 @@
 	int n;
 	
 	vc = lookupvc(m->chanid);
-	if(vc == nil)
+	if(vc == nil){
+		fprint(2, "defragvc: bad chanid\n");
 		return -1;
+	}
 
 	if(m->flags&First)
 		vc->pos = 0;
@@ -97,8 +105,10 @@
 {
 	Vchan* vc;
 	vc = lookupvc(m->chanid);
-	if(vc == nil)
+	if(vc == nil || vc->fn==nil){
+		fprint(2, "unhandled virtual channel[%d] msg\n", m->chanid);
 		return;
+	}
 	vc->fn(c, m->data, m->ndata);
 }