New packet based parser for the rdpsnd protocol.

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1341 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Pierre Ossman 2006-12-06 13:29:42 +00:00
parent 1f47dce7ed
commit 10bad3c82d
3 changed files with 103 additions and 58 deletions

143
rdpsnd.c
View File

@ -50,6 +50,9 @@ static unsigned int current_format;
unsigned int queue_hi, queue_lo, queue_pending;
struct audio_packet packet_queue[MAX_QUEUE];
static uint8 packet_opcode;
static struct stream packet;
void (*wave_out_play) (void);
static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
@ -195,70 +198,53 @@ rdpsnd_process_ping(STREAM in)
}
static void
rdpsnd_process(STREAM s)
rdpsnd_process_packet(uint8 opcode, STREAM s)
{
uint8 type;
uint16 datalen;
uint16 vol_left, vol_right;
static uint16 tick, format;
static uint8 packet_index;
static BOOL awaiting_data_packet;
static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
#ifdef RDPSND_DEBUG
printf("RDPSND recv:\n");
hexdump(s->p, s->end - s->p);
#endif
if (awaiting_data_packet)
{
if (format >= MAX_FORMATS)
{
error("RDPSND: Invalid format index\n");
return;
}
if (!device_open || (format != current_format))
{
if (!device_open && !current_driver->wave_out_open())
{
rdpsnd_send_completion(tick, packet_index);
return;
}
if (!current_driver->wave_out_set_format(&formats[format]))
{
rdpsnd_send_completion(tick, packet_index);
current_driver->wave_out_close();
device_open = False;
return;
}
device_open = True;
current_format = format;
}
/* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
memcpy(s->data, missing_bytes, 4);
rdpsnd_queue_write(rdpsnd_dsp_process
(s, current_driver, &formats[current_format]), tick,
packet_index);
awaiting_data_packet = False;
return;
}
in_uint8(s, type);
in_uint8s(s, 1); /* unknown? */
in_uint16_le(s, datalen);
switch (type)
switch (opcode)
{
case RDPSND_WRITE:
in_uint16_le(s, tick);
in_uint16_le(s, format);
in_uint8(s, packet_index);
/* Here are our lost bytes, but why? */
memcpy(missing_bytes, s->end - 4, 4);
awaiting_data_packet = True;
in_uint8s(s, 3);
if (format >= MAX_FORMATS)
{
error("RDPSND: Invalid format index\n");
break;
}
if (!device_open || (format != current_format))
{
if (!device_open && !current_driver->wave_out_open())
{
rdpsnd_send_completion(tick, packet_index);
break;
}
if (!current_driver->wave_out_set_format(&formats[format]))
{
rdpsnd_send_completion(tick, packet_index);
current_driver->wave_out_close();
device_open = False;
break;
}
device_open = True;
current_format = format;
}
rdpsnd_queue_write(rdpsnd_dsp_process
(s->p, s->end - s->p, current_driver,
&formats[current_format]), tick, packet_index);
return;
break;
case RDPSND_CLOSE:
current_driver->wave_out_close();
@ -277,11 +263,64 @@ rdpsnd_process(STREAM s)
current_driver->wave_out_volume(vol_left, vol_right);
break;
default:
unimpl("RDPSND packet type %d\n", type);
unimpl("RDPSND packet type %x\n", opcode);
break;
}
}
static void
rdpsnd_process(STREAM s)
{
uint16 len;
while (!s_check_end(s))
{
/* New packet */
if (packet.size == 0)
{
if ((s->end - s->p) < 4)
{
error("RDPSND: Split at packet header. Things will go south from here...\n");
return;
}
in_uint8(s, packet_opcode);
in_uint8s(s, 1); /* Padding */
in_uint16_le(s, len);
packet.p = packet.data;
packet.end = packet.data + len;
packet.size = len;
}
else
{
len = MIN(s->end - s->p, packet.end - packet.p);
/* Microsoft's server is so broken it's not even funny... */
if (packet_opcode == RDPSND_WRITE)
{
if ((packet.p - packet.data) < 12)
len = MIN(len, 12 - (packet.p - packet.data));
else if ((packet.p - packet.data) == 12)
{
in_uint8s(s, 4);
len -= 4;
}
}
in_uint8a(s, packet.p, len);
packet.p += len;
}
/* Packet fully assembled */
if (packet.p == packet.end)
{
packet.p = packet.data;
rdpsnd_process_packet(packet_opcode, &packet);
packet.size = 0;
}
}
}
static BOOL
rdpsnd_auto_open(void)
{
@ -357,6 +396,10 @@ rdpsnd_init(char *optarg)
drivers = NULL;
packet.data = xmalloc(65536);
packet.p = packet.end = packet.data;
packet.size = 0;
rdpsnd_channel =
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
rdpsnd_process);

View File

@ -384,7 +384,8 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
}
STREAM
rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX * format)
rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
WAVEFORMATEX * format)
{
static struct stream out;
BOOL stream_be = False;
@ -392,12 +393,12 @@ rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX
/* softvol and byteswap do not change the amount of data they
return, so they can operate on the input-stream */
if (current_driver->wave_out_volume == rdpsnd_dsp_softvol_set)
rdpsnd_dsp_softvol(s->data, s->size, format);
rdpsnd_dsp_softvol(data, size, format);
#ifdef B_ENDIAN
if (current_driver->need_byteswap_on_be)
{
rdpsnd_dsp_swapbytes(s->data, s->size, format);
rdpsnd_dsp_swapbytes(data, size, format);
stream_be = True;
}
#endif
@ -405,13 +406,13 @@ rdpsnd_dsp_process(STREAM s, struct audio_driver * current_driver, WAVEFORMATEX
out.data = NULL;
if (current_driver->need_resampling)
out.size = rdpsnd_dsp_resample(&out.data, s->data, s->size, format, stream_be);
out.size = rdpsnd_dsp_resample(&out.data, data, size, format, stream_be);
if (out.data == NULL)
{
out.data = xmalloc(s->size);
memcpy(out.data, s->data, s->size);
out.size = s->size;
out.data = xmalloc(size);
memcpy(out.data, data, size);
out.size = size;
}
out.p = out.data;

View File

@ -26,4 +26,5 @@ BOOL rdpsnd_dsp_resample_set(uint32 device_srate, uint16 device_bitspersample,
uint16 device_channels);
BOOL rdpsnd_dsp_resample_supported(WAVEFORMATEX * pwfx);
STREAM rdpsnd_dsp_process(STREAM s, struct audio_driver *current_driver, WAVEFORMATEX * format);
STREAM rdpsnd_dsp_process(unsigned char *data, unsigned int size,
struct audio_driver *current_driver, WAVEFORMATEX * format);