ref: 25e9575509db6d607c5ca215b28393e64407d74c
dir: /vchan.c/
/*
* [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 <draw.h>
#include "dat.h"
#include "fns.h"
enum
{
ChanInited= 0x80000000, /* 2.2.1.3.4.1 Channel Definition Structure */
ChanShowproto= 0x00200000,
ChanChunkLen= 1600, /* 2.2.6.1 Virtual Channel PDU */
CFfirst= 0x01, /* 2.2.6.1.1 Channel PDU Header */
CFlast= 0x02,
CFshowproto= 0x10,
};
static
Vchan vctab[] =
{
{
.mcsid = GLOBALCHAN + 1, /* iota */
.name = "CLIPRDR",
.fn = clipvcfn,
.flags = ChanInited | ChanShowproto,
},
};
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;
}
void
scanvcdata(Rdp* c, Msg* m)
{
Vchan* vc;
int n;
vc = lookupvc(m->chanid);
if(vc == nil)
return;
if(m->flags&CFfirst)
vc->pos = 0;
vc->buf = erealloc(vc->buf, m->len);
vc->nb = m->len;
n = vc->nb - vc->pos;
if(n > m->ndata)
n = m->ndata;
memcpy(vc->buf+vc->pos, m->data, n);
vc->pos += n;
if(m->flags&CFlast){
vc->fn(c, vc->buf, vc->nb);
free(vc->buf);
vc->buf = nil;
vc->nb = 0;
}
}
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 = Mvcdata;
t.originid = c->userchan;
t.chanid = vc->mcsid;
t.flags = CFfirst | CFshowproto;
t.len = n;
t.data = a;
for(sofar=0; sofar<n; sofar += chunk){
chunk = n-sofar;
if(chunk > ChanChunkLen)
chunk = ChanChunkLen;
else
t.flags |= CFlast;
t.data = a+sofar;
t.ndata = chunk;
writemsg(c, &t);
t.flags &= ~CFfirst;
}
return n;
}