/[rdesktop]/sourceforge.net/rdesktop/trunk/rdpsnd.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1342 - (show annotations)
Wed Dec 6 13:29:42 2006 UTC (17 years, 5 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 13357 byte(s)
New packet based parser for the rdpsnd protocol.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <assert.h>
23
24 #include "rdesktop.h"
25 #include "rdpsnd.h"
26 #include "rdpsnd_dsp.h"
27
28 #define RDPSND_CLOSE 1
29 #define RDPSND_WRITE 2
30 #define RDPSND_SET_VOLUME 3
31 #define RDPSND_UNKNOWN4 4
32 #define RDPSND_COMPLETION 5
33 #define RDPSND_PING 6
34 #define RDPSND_NEGOTIATE 7
35
36 #define MAX_FORMATS 10
37 #define MAX_QUEUE 10
38
39 BOOL g_dsp_busy = False;
40 int g_dsp_fd;
41
42 static VCHANNEL *rdpsnd_channel;
43 static struct audio_driver *drivers = NULL;
44 struct audio_driver *current_driver = NULL;
45
46 static BOOL device_open;
47 static WAVEFORMATEX formats[MAX_FORMATS];
48 static unsigned int format_count;
49 static unsigned int current_format;
50 unsigned int queue_hi, queue_lo, queue_pending;
51 struct audio_packet packet_queue[MAX_QUEUE];
52
53 static uint8 packet_opcode;
54 static struct stream packet;
55
56 void (*wave_out_play) (void);
57
58 static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
59 static void rdpsnd_queue_init(void);
60 static void rdpsnd_queue_complete_pending(void);
61 static long rdpsnd_queue_next_completion(void);
62
63 static STREAM
64 rdpsnd_init_packet(uint16 type, uint16 size)
65 {
66 STREAM s;
67
68 s = channel_init(rdpsnd_channel, size + 4);
69 out_uint16_le(s, type);
70 out_uint16_le(s, size);
71 return s;
72 }
73
74 static void
75 rdpsnd_send(STREAM s)
76 {
77 #ifdef RDPSND_DEBUG
78 printf("RDPSND send:\n");
79 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
80 #endif
81
82 channel_send(s, rdpsnd_channel);
83 }
84
85 static void
86 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
87 {
88 STREAM s;
89
90 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
91 out_uint16_le(s, tick);
92 out_uint8(s, packet_index);
93 out_uint8(s, 0);
94 s_mark_end(s);
95 rdpsnd_send(s);
96 }
97
98 static void
99 rdpsnd_process_negotiate(STREAM in)
100 {
101 uint16 in_format_count, i;
102 uint8 pad;
103 uint16 version;
104 WAVEFORMATEX *format;
105 STREAM out;
106 BOOL device_available = False;
107 int readcnt;
108 int discardcnt;
109
110 in_uint8s(in, 14); /* initial bytes not valid from server */
111 in_uint16_le(in, in_format_count);
112 in_uint8(in, pad);
113 in_uint16_le(in, version);
114 in_uint8s(in, 1); /* padding */
115
116 if (current_driver->wave_out_open())
117 {
118 current_driver->wave_out_close();
119 device_available = True;
120 }
121
122 format_count = 0;
123 if (s_check_rem(in, 18 * in_format_count))
124 {
125 for (i = 0; i < in_format_count; i++)
126 {
127 format = &formats[format_count];
128 in_uint16_le(in, format->wFormatTag);
129 in_uint16_le(in, format->nChannels);
130 in_uint32_le(in, format->nSamplesPerSec);
131 in_uint32_le(in, format->nAvgBytesPerSec);
132 in_uint16_le(in, format->nBlockAlign);
133 in_uint16_le(in, format->wBitsPerSample);
134 in_uint16_le(in, format->cbSize);
135
136 /* read in the buffer of unknown use */
137 readcnt = format->cbSize;
138 discardcnt = 0;
139 if (format->cbSize > MAX_CBSIZE)
140 {
141 fprintf(stderr, "cbSize too large for buffer: %d\n",
142 format->cbSize);
143 readcnt = MAX_CBSIZE;
144 discardcnt = format->cbSize - MAX_CBSIZE;
145 }
146 in_uint8a(in, format->cb, readcnt);
147 in_uint8s(in, discardcnt);
148
149 if (device_available && current_driver->wave_out_format_supported(format))
150 {
151 format_count++;
152 if (format_count == MAX_FORMATS)
153 break;
154 }
155 }
156 }
157
158 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
159 out_uint32_le(out, 3); /* flags */
160 out_uint32(out, 0xffffffff); /* volume */
161 out_uint32(out, 0); /* pitch */
162 out_uint16(out, 0); /* UDP port */
163
164 out_uint16_le(out, format_count);
165 out_uint8(out, 0); /* padding */
166 out_uint16_le(out, 2); /* version */
167 out_uint8(out, 0); /* padding */
168
169 for (i = 0; i < format_count; i++)
170 {
171 format = &formats[i];
172 out_uint16_le(out, format->wFormatTag);
173 out_uint16_le(out, format->nChannels);
174 out_uint32_le(out, format->nSamplesPerSec);
175 out_uint32_le(out, format->nAvgBytesPerSec);
176 out_uint16_le(out, format->nBlockAlign);
177 out_uint16_le(out, format->wBitsPerSample);
178 out_uint16(out, 0); /* cbSize */
179 }
180
181 s_mark_end(out);
182 rdpsnd_send(out);
183 }
184
185 static void
186 rdpsnd_process_ping(STREAM in)
187 {
188 uint16 tick;
189 STREAM out;
190
191 in_uint16_le(in, tick);
192
193 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
194 out_uint16_le(out, tick);
195 out_uint16_le(out, 0);
196 s_mark_end(out);
197 rdpsnd_send(out);
198 }
199
200 static void
201 rdpsnd_process_packet(uint8 opcode, STREAM s)
202 {
203 uint16 vol_left, vol_right;
204 static uint16 tick, format;
205 static uint8 packet_index;
206
207 #ifdef RDPSND_DEBUG
208 printf("RDPSND recv:\n");
209 hexdump(s->p, s->end - s->p);
210 #endif
211
212 switch (opcode)
213 {
214 case RDPSND_WRITE:
215 in_uint16_le(s, tick);
216 in_uint16_le(s, format);
217 in_uint8(s, packet_index);
218 in_uint8s(s, 3);
219
220 if (format >= MAX_FORMATS)
221 {
222 error("RDPSND: Invalid format index\n");
223 break;
224 }
225
226 if (!device_open || (format != current_format))
227 {
228 if (!device_open && !current_driver->wave_out_open())
229 {
230 rdpsnd_send_completion(tick, packet_index);
231 break;
232 }
233 if (!current_driver->wave_out_set_format(&formats[format]))
234 {
235 rdpsnd_send_completion(tick, packet_index);
236 current_driver->wave_out_close();
237 device_open = False;
238 break;
239 }
240 device_open = True;
241 current_format = format;
242 }
243
244 rdpsnd_queue_write(rdpsnd_dsp_process
245 (s->p, s->end - s->p, current_driver,
246 &formats[current_format]), tick, packet_index);
247 return;
248 break;
249 case RDPSND_CLOSE:
250 current_driver->wave_out_close();
251 device_open = False;
252 break;
253 case RDPSND_NEGOTIATE:
254 rdpsnd_process_negotiate(s);
255 break;
256 case RDPSND_PING:
257 rdpsnd_process_ping(s);
258 break;
259 case RDPSND_SET_VOLUME:
260 in_uint16_le(s, vol_left);
261 in_uint16_le(s, vol_right);
262 if (device_open)
263 current_driver->wave_out_volume(vol_left, vol_right);
264 break;
265 default:
266 unimpl("RDPSND packet type %x\n", opcode);
267 break;
268 }
269 }
270
271 static void
272 rdpsnd_process(STREAM s)
273 {
274 uint16 len;
275
276 while (!s_check_end(s))
277 {
278 /* New packet */
279 if (packet.size == 0)
280 {
281 if ((s->end - s->p) < 4)
282 {
283 error("RDPSND: Split at packet header. Things will go south from here...\n");
284 return;
285 }
286 in_uint8(s, packet_opcode);
287 in_uint8s(s, 1); /* Padding */
288 in_uint16_le(s, len);
289
290 packet.p = packet.data;
291 packet.end = packet.data + len;
292 packet.size = len;
293 }
294 else
295 {
296 len = MIN(s->end - s->p, packet.end - packet.p);
297
298 /* Microsoft's server is so broken it's not even funny... */
299 if (packet_opcode == RDPSND_WRITE)
300 {
301 if ((packet.p - packet.data) < 12)
302 len = MIN(len, 12 - (packet.p - packet.data));
303 else if ((packet.p - packet.data) == 12)
304 {
305 in_uint8s(s, 4);
306 len -= 4;
307 }
308 }
309
310 in_uint8a(s, packet.p, len);
311 packet.p += len;
312 }
313
314 /* Packet fully assembled */
315 if (packet.p == packet.end)
316 {
317 packet.p = packet.data;
318 rdpsnd_process_packet(packet_opcode, &packet);
319 packet.size = 0;
320 }
321 }
322 }
323
324 static BOOL
325 rdpsnd_auto_open(void)
326 {
327 static BOOL failed = False;
328
329 if (!failed)
330 {
331 struct audio_driver *auto_driver = current_driver;
332
333 current_driver = drivers;
334 while (current_driver != NULL)
335 {
336 DEBUG(("trying %s...\n", current_driver->name));
337 if (current_driver->wave_out_open())
338 {
339 DEBUG(("selected %s\n", current_driver->name));
340 return True;
341 }
342 g_dsp_fd = 0;
343 current_driver = current_driver->next;
344 }
345
346 warning("no working audio-driver found\n");
347 failed = True;
348 current_driver = auto_driver;
349 }
350
351 return False;
352 }
353
354 static void
355 rdpsnd_register_drivers(char *options)
356 {
357 struct audio_driver **reg;
358
359 /* The order of registrations define the probe-order
360 when opening the device for the first time */
361 reg = &drivers;
362 #if defined(RDPSND_ALSA)
363 *reg = alsa_register(options);
364 assert(*reg);
365 reg = &((*reg)->next);
366 #endif
367 #if defined(RDPSND_SUN)
368 *reg = sun_register(options);
369 assert(*reg);
370 reg = &((*reg)->next);
371 #endif
372 #if defined(RDPSND_OSS)
373 *reg = oss_register(options);
374 assert(*reg);
375 reg = &((*reg)->next);
376 #endif
377 #if defined(RDPSND_SGI)
378 *reg = sgi_register(options);
379 assert(*reg);
380 reg = &((*reg)->next);
381 #endif
382 #if defined(RDPSND_LIBAO)
383 *reg = libao_register(options);
384 assert(*reg);
385 reg = &((*reg)->next);
386 #endif
387 *reg = NULL;
388 }
389
390 BOOL
391 rdpsnd_init(char *optarg)
392 {
393 static struct audio_driver auto_driver;
394 struct audio_driver *pos;
395 char *driver = NULL, *options = NULL;
396
397 drivers = NULL;
398
399 packet.data = xmalloc(65536);
400 packet.p = packet.end = packet.data;
401 packet.size = 0;
402
403 rdpsnd_channel =
404 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
405 rdpsnd_process);
406
407 if (rdpsnd_channel == NULL)
408 {
409 error("channel_register\n");
410 return False;
411 }
412
413 rdpsnd_queue_init();
414
415 if (optarg != NULL && strlen(optarg) > 0)
416 {
417 driver = options = optarg;
418
419 while (*options != '\0' && *options != ':')
420 options++;
421
422 if (*options == ':')
423 {
424 *options = '\0';
425 options++;
426 }
427
428 if (*options == '\0')
429 options = NULL;
430 }
431
432 rdpsnd_register_drivers(options);
433
434 if (!driver)
435 {
436 auto_driver.wave_out_open = &rdpsnd_auto_open;
437 current_driver = &auto_driver;
438 return True;
439 }
440
441 pos = drivers;
442 while (pos != NULL)
443 {
444 if (!strcmp(pos->name, driver))
445 {
446 DEBUG(("selected %s\n", pos->name));
447 current_driver = pos;
448 return True;
449 }
450 pos = pos->next;
451 }
452 return False;
453 }
454
455 void
456 rdpsnd_show_help(void)
457 {
458 struct audio_driver *pos;
459
460 rdpsnd_register_drivers(NULL);
461
462 pos = drivers;
463 while (pos != NULL)
464 {
465 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
466 pos = pos->next;
467 }
468 }
469
470 void
471 rdpsnd_play(void)
472 {
473 current_driver->wave_out_play();
474 }
475
476 void
477 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
478 {
479 long next_pending;
480
481 if (g_dsp_busy)
482 {
483 FD_SET(g_dsp_fd, wfds);
484 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
485 }
486
487 next_pending = rdpsnd_queue_next_completion();
488 if (next_pending >= 0)
489 {
490 long cur_timeout;
491
492 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
493 if (cur_timeout > next_pending)
494 {
495 tv->tv_sec = next_pending / 1000000;
496 tv->tv_usec = next_pending % 1000000;
497 }
498 }
499 }
500
501 void
502 rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
503 {
504 rdpsnd_queue_complete_pending();
505
506 if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
507 rdpsnd_play();
508 }
509
510 static void
511 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
512 {
513 struct audio_packet *packet = &packet_queue[queue_hi];
514 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
515
516 if (next_hi == queue_pending)
517 {
518 error("No space to queue audio packet\n");
519 return;
520 }
521
522 queue_hi = next_hi;
523
524 packet->s = *s;
525 packet->tick = tick;
526 packet->index = index;
527
528 gettimeofday(&packet->arrive_tv, NULL);
529
530 if (!g_dsp_busy)
531 current_driver->wave_out_play();
532 }
533
534 struct audio_packet *
535 rdpsnd_queue_current_packet(void)
536 {
537 return &packet_queue[queue_lo];
538 }
539
540 BOOL
541 rdpsnd_queue_empty(void)
542 {
543 return (queue_lo == queue_hi);
544 }
545
546 static void
547 rdpsnd_queue_init(void)
548 {
549 queue_pending = queue_lo = queue_hi = 0;
550 }
551
552 void
553 rdpsnd_queue_next(unsigned long completed_in_us)
554 {
555 struct audio_packet *packet;
556
557 assert(!rdpsnd_queue_empty());
558
559 packet = &packet_queue[queue_lo];
560
561 gettimeofday(&packet->completion_tv, NULL);
562
563 packet->completion_tv.tv_usec += completed_in_us;
564 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
565 packet->completion_tv.tv_usec %= 1000000;
566
567 queue_lo = (queue_lo + 1) % MAX_QUEUE;
568
569 rdpsnd_queue_complete_pending();
570 }
571
572 int
573 rdpsnd_queue_next_tick(void)
574 {
575 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
576 {
577 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
578 }
579 else
580 {
581 return (packet_queue[queue_lo].tick + 65535) % 65536;
582 }
583 }
584
585 static void
586 rdpsnd_queue_complete_pending(void)
587 {
588 struct timeval now;
589 long elapsed;
590 struct audio_packet *packet;
591
592 gettimeofday(&now, NULL);
593
594 while (queue_pending != queue_lo)
595 {
596 packet = &packet_queue[queue_pending];
597
598 if (now.tv_sec < packet->completion_tv.tv_sec)
599 break;
600
601 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
602 (now.tv_usec < packet->completion_tv.tv_usec))
603 break;
604
605 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
606 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
607 elapsed /= 1000;
608
609 xfree(packet->s.data);
610 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
611 queue_pending = (queue_pending + 1) % MAX_QUEUE;
612 }
613 }
614
615 static long
616 rdpsnd_queue_next_completion(void)
617 {
618 struct audio_packet *packet;
619 long remaining;
620 struct timeval now;
621
622 if (queue_pending == queue_lo)
623 return -1;
624
625 gettimeofday(&now, NULL);
626
627 packet = &packet_queue[queue_pending];
628
629 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
630 (packet->completion_tv.tv_usec - now.tv_usec);
631
632 if (remaining < 0)
633 return 0;
634
635 return remaining;
636 }

  ViewVC Help
Powered by ViewVC 1.1.26