/*
* [MS-RDPBCGR] 3.1.5.2 Static Virtual Channels
* http://msdn.microsoft.com/en-us/library/cc240926.aspx
*/
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
enum
{
/* 2.2.1.3.4.1 Channel Definition Structure */
Inited= 1<<31,
/* 2.2.6.1 Virtual Channel PDU */
MTU= 1600,
/* 2.2.6.1.1 Channel PDU Header */
First= 1<<0,
Last= 1<<1,
Vis= 1<<4,
};
static Vchan vctab[] =
{
{
.mcsid = GLOBALCHAN+1, /* iota */
.name = "CLIPRDR",
.fn = clipvcfn,
.flags = Inited,
},
{
.mcsid = GLOBALCHAN+2,
.name = "RDPDR",
.fn = efsvcfn,
.flags = Inited,
},
{
.mcsid = GLOBALCHAN+3,
.name = "RDPSND",
.fn = audiovcfn,
.flags = Inited,
},
};
static uint nvc = nelem(vctab);
void
initvc(Rdp* c)
{
c->vc = vctab;
c->nvc = nvc;
}
static Vchan*
lookupvc(int mcsid)
{
int i;
for(i=0; i<nvc; i++)
if(vctab[i].mcsid == mcsid)
return &vctab[i];
return nil;
}
static Vchan*
namevc(char* name)
{
int i;
for(i=0; i<nvc; i++)
if(strcmp(vctab[i].name, name) == 0)
return &vctab[i];
return nil;
}
int
defragvc(Rdp* c, Msg* m)
{
Vchan* vc;
int n;
USED(c);
vc = lookupvc(m->chanid);
if(vc == nil){
fprint(2, "defragvc: bad chanid\n");
return -1;
}
if(m->flags&First)
vc->pos = 0;
if(m->len > vc->nb){
vc->buf = erealloc(vc->buf, m->len);
vc->nb = m->len;
}
n = m->len - vc->pos;
if(n > m->ndata)
n = m->ndata;
memcpy(vc->buf+vc->pos, m->data, n);
vc->pos += n;
if(m->flags&Last){
m->data = vc->buf;
m->ndata = m->len;
return m->len;
}
return 0;
}
void
callvcfunc(Rdp *c, Msg* m)
{
Vchan* vc;
vc = lookupvc(m->chanid);
if(vc == nil || vc->fn==nil){
fprint(2, "unhandled virtual channel[%d] msg\n", m->chanid);
return;
}
vc->fn(c, m->data, m->ndata);
}
int
sendvc(Rdp* c, char* cname, uchar* a, int n)
{
int sofar, chunk;
Vchan* vc;
Msg t;
if(n < 0)
return -1;
vc = namevc(cname);
if(vc == nil){
werrstr("%s: no such vchannel", cname);
return -1;
}
if(vc->mcsid < 0)
return -1;
t.type = Mvchan;
t.originid = c->userchan;
t.chanid = vc->mcsid;
t.flags = First | Vis;
t.len = n;
t.data = a;
for(sofar=0; sofar<n; sofar += chunk){
chunk = n-sofar;
if(chunk > MTU)
chunk = MTU;
else
t.flags |= Last;
t.data = a+sofar;
t.ndata = chunk;
writemsg(c, &t);
t.flags &= ~First;
}
return n;
}
|