diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 81218db1..7a97c136 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -9,7 +9,8 @@ EXTRA_DIST = \ rail.h \ sound.h \ xcommon.h \ - mlog.h + mlog.h \ + chansrv_common.h EXTRA_DEFINES = EXTRA_INCLUDES = @@ -48,7 +49,8 @@ xrdp_chansrv_SOURCES = \ drdynvc.c \ chansrv_fuse.c \ irp.c \ - fifo.c + fifo.c \ + chansrv_common.c xrdp_chansrv_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/sesman/chansrv/chansrv_common.c b/sesman/chansrv/chansrv_common.c new file mode 100644 index 00000000..fd26da7c --- /dev/null +++ b/sesman/chansrv/chansrv_common.c @@ -0,0 +1,73 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2009-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "chansrv_common.h" + +/** + * Assemble fragmented incoming packets into one stream + * + * @param src stream that contains partial data + * @param dest stream that contains entire data + * @param chan_flags fragmentation flags + * @param length bytes in this packet + * @param total_length total length of assembled packet + * + * @return 1 when all data has been assembled, 0 otherwise + * + * NOTE: it is the responsibility of the caller to free dest stream + ****************************************************************************/ +int +read_entire_packet(struct stream *src, struct stream **dest, int chan_flags, + int length, int total_length) +{ + struct stream *ls; + + if ((chan_flags & 3) == 3) + { + /* packet not fragmented */ + xstream_new(ls, total_length); + xstream_copyin(ls, src->p, length); + ls->p = ls->data; + *dest = ls; + return 1; + } + + /* is this the first fragmented packet? */ + if (chan_flags & 1) + { + xstream_new(ls, total_length); + *dest = ls; + } + else + { + ls = *dest; + } + + xstream_copyin(ls, src->p, length); + + /* in last packet, chan_flags & 0x02 will be true */ + if (chan_flags & 0x02) + { + /* rewind stream */ + ls->p = ls->data; + return 1; + } + + return 0; +} + diff --git a/sesman/chansrv/chansrv_common.h b/sesman/chansrv/chansrv_common.h new file mode 100644 index 00000000..833e3359 --- /dev/null +++ b/sesman/chansrv/chansrv_common.h @@ -0,0 +1,27 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Laxmikant Rashinkar 2009-2014 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CHANSRV_COMMON_H +#define _CHANSRV_COMMON_H + +#include "parse.h" + +int read_entire_packet(struct stream *src, struct stream **dest, int chan_flags, int length, int total_length); + +#endif + diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index f5e17fef..b4e0a384 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -46,6 +46,7 @@ static int g_bytes_in_stream = 0; static FIFO in_fifo; static struct stream *g_stream_inp = NULL; +static struct stream *g_stream_incoming_packet = NULL; #define BBUF_SIZE (1024 * 8) char g_buffer[BBUF_SIZE]; @@ -686,6 +687,7 @@ sound_init(void) LOG(0, ("sound_init:")); g_memset(g_sent_flag, 0, sizeof(g_sent_flag)); + g_stream_incoming_packet = NULL; /* init sound output */ sound_send_server_output_formats(); @@ -759,31 +761,39 @@ sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, { int code; int size; + int ok_to_free = 1; - in_uint8(s, code); - in_uint8s(s, 1); - in_uint16_le(s, size); + if (!read_entire_packet(s, &g_stream_incoming_packet, chan_flags, + length, total_length)) + { + return 0; + } + + in_uint8(g_stream_incoming_packet, code); + in_uint8s(g_stream_incoming_packet, 1); + in_uint16_le(g_stream_incoming_packet, size); switch (code) { case SNDC_WAVECONFIRM: - sound_process_wave_confirm(s, size); + sound_process_wave_confirm(g_stream_incoming_packet, size); break; case SNDC_TRAINING: - sound_process_training(s, size); + sound_process_training(g_stream_incoming_packet, size); break; case SNDC_FORMATS: - sound_process_output_formats(s, size); + sound_process_output_formats(g_stream_incoming_packet, size); break; case SNDC_REC_NEGOTIATE: - sound_process_input_formats(s, size); + sound_process_input_formats(g_stream_incoming_packet, size); break; case SNDC_REC_DATA: - sound_process_input_data(s, size); + sound_process_input_data(g_stream_incoming_packet, size); + ok_to_free = 0; break; default: @@ -791,6 +801,12 @@ sound_data_in(struct stream *s, int chan_id, int chan_flags, int length, break; } + if (ok_to_free && g_stream_incoming_packet) + { + xstream_free(g_stream_incoming_packet); + g_stream_incoming_packet = NULL; + } + return 0; }