/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1342 - (hide 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 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 474 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 ossman_ 1298 #include <assert.h>
23    
24 matthewc 432 #include "rdesktop.h"
25 stargo 1254 #include "rdpsnd.h"
26 stargo 1258 #include "rdpsnd_dsp.h"
27 matthewc 432
28 matthewc 474 #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 ossman_ 1339 #define RDPSND_PING 6
34 matthewc 474 #define RDPSND_NEGOTIATE 7
35    
36     #define MAX_FORMATS 10
37 stargo 1254 #define MAX_QUEUE 10
38 matthewc 474
39 stargo 1254 BOOL g_dsp_busy = False;
40     int g_dsp_fd;
41    
42 matthewc 432 static VCHANNEL *rdpsnd_channel;
43 stargo 1255 static struct audio_driver *drivers = NULL;
44 stargo 1256 struct audio_driver *current_driver = NULL;
45 matthewc 432
46 matthewc 474 static BOOL device_open;
47     static WAVEFORMATEX formats[MAX_FORMATS];
48     static unsigned int format_count;
49     static unsigned int current_format;
50 ossman_ 1302 unsigned int queue_hi, queue_lo, queue_pending;
51 stargo 1256 struct audio_packet packet_queue[MAX_QUEUE];
52 matthewc 474
53 ossman_ 1342 static uint8 packet_opcode;
54     static struct stream packet;
55    
56 stargo 1255 void (*wave_out_play) (void);
57    
58 ossman_ 1302 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 astrand 665 static STREAM
64 matthewc 474 rdpsnd_init_packet(uint16 type, uint16 size)
65     {
66     STREAM s;
67    
68 astrand 499 s = channel_init(rdpsnd_channel, size + 4);
69 matthewc 474 out_uint16_le(s, type);
70     out_uint16_le(s, size);
71     return s;
72     }
73    
74 astrand 665 static void
75 matthewc 474 rdpsnd_send(STREAM s)
76     {
77     #ifdef RDPSND_DEBUG
78     printf("RDPSND send:\n");
79 astrand 499 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
80 matthewc 474 #endif
81    
82     channel_send(s, rdpsnd_channel);
83     }
84    
85 ossman_ 1302 static void
86 astrand 499 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
87 matthewc 474 {
88     STREAM s;
89    
90     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
91 stargo 1254 out_uint16_le(s, tick);
92 matthewc 474 out_uint8(s, packet_index);
93     out_uint8(s, 0);
94     s_mark_end(s);
95     rdpsnd_send(s);
96     }
97    
98 astrand 665 static void
99 matthewc 474 rdpsnd_process_negotiate(STREAM in)
100     {
101 ossman_ 1340 uint16 in_format_count, i;
102     uint8 pad;
103     uint16 version;
104 matthewc 474 WAVEFORMATEX *format;
105     STREAM out;
106 stargo 491 BOOL device_available = False;
107 stargo 493 int readcnt;
108     int discardcnt;
109 matthewc 474
110 ossman_ 1340 in_uint8s(in, 14); /* initial bytes not valid from server */
111 matthewc 474 in_uint16_le(in, in_format_count);
112 ossman_ 1340 in_uint8(in, pad);
113     in_uint16_le(in, version);
114     in_uint8s(in, 1); /* padding */
115 matthewc 474
116 stargo 1255 if (current_driver->wave_out_open())
117 stargo 491 {
118 stargo 1255 current_driver->wave_out_close();
119 stargo 491 device_available = True;
120     }
121    
122 matthewc 474 format_count = 0;
123 astrand 499 if (s_check_rem(in, 18 * in_format_count))
124 matthewc 474 {
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 stargo 492 /* read in the buffer of unknown use */
137 stargo 493 readcnt = format->cbSize;
138     discardcnt = 0;
139 stargo 492 if (format->cbSize > MAX_CBSIZE)
140     {
141 astrand 499 fprintf(stderr, "cbSize too large for buffer: %d\n",
142     format->cbSize);
143 stargo 492 readcnt = MAX_CBSIZE;
144     discardcnt = format->cbSize - MAX_CBSIZE;
145     }
146     in_uint8a(in, format->cb, readcnt);
147     in_uint8s(in, discardcnt);
148    
149 stargo 1255 if (device_available && current_driver->wave_out_format_supported(format))
150 matthewc 474 {
151     format_count++;
152     if (format_count == MAX_FORMATS)
153     break;
154     }
155     }
156     }
157    
158 astrand 499 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
159     out_uint32_le(out, 3); /* flags */
160 matthewc 474 out_uint32(out, 0xffffffff); /* volume */
161 astrand 499 out_uint32(out, 0); /* pitch */
162     out_uint16(out, 0); /* UDP port */
163 matthewc 474
164     out_uint16_le(out, format_count);
165 ossman_ 1340 out_uint8(out, 0); /* padding */
166     out_uint16_le(out, 2); /* version */
167     out_uint8(out, 0); /* padding */
168 matthewc 474
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 astrand 499 out_uint16(out, 0); /* cbSize */
179 matthewc 474 }
180    
181     s_mark_end(out);
182     rdpsnd_send(out);
183     }
184    
185 astrand 665 static void
186 ossman_ 1339 rdpsnd_process_ping(STREAM in)
187 matthewc 474 {
188 ossman_ 1339 uint16 tick;
189 matthewc 474 STREAM out;
190    
191 ossman_ 1339 in_uint16_le(in, tick);
192 matthewc 474
193 ossman_ 1339 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
194     out_uint16_le(out, tick);
195     out_uint16_le(out, 0);
196 matthewc 474 s_mark_end(out);
197     rdpsnd_send(out);
198     }
199    
200 astrand 665 static void
201 ossman_ 1342 rdpsnd_process_packet(uint8 opcode, STREAM s)
202 matthewc 432 {
203 ossman_ 1341 uint16 vol_left, vol_right;
204 matthewc 474 static uint16 tick, format;
205     static uint8 packet_index;
206    
207     #ifdef RDPSND_DEBUG
208     printf("RDPSND recv:\n");
209 astrand 499 hexdump(s->p, s->end - s->p);
210 matthewc 474 #endif
211    
212 ossman_ 1342 switch (opcode)
213 matthewc 474 {
214 ossman_ 1342 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 matthewc 474
220 ossman_ 1342 if (format >= MAX_FORMATS)
221 matthewc 474 {
222 ossman_ 1342 error("RDPSND: Invalid format index\n");
223     break;
224 matthewc 474 }
225 ossman_ 1342
226     if (!device_open || (format != current_format))
227 matthewc 474 {
228 ossman_ 1342 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 matthewc 474 }
243    
244 ossman_ 1342 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 astrand 499 break;
249     case RDPSND_CLOSE:
250 stargo 1255 current_driver->wave_out_close();
251 astrand 499 device_open = False;
252     break;
253     case RDPSND_NEGOTIATE:
254     rdpsnd_process_negotiate(s);
255     break;
256 ossman_ 1339 case RDPSND_PING:
257     rdpsnd_process_ping(s);
258 astrand 499 break;
259     case RDPSND_SET_VOLUME:
260 ossman_ 1341 in_uint16_le(s, vol_left);
261     in_uint16_le(s, vol_right);
262 astrand 499 if (device_open)
263 ossman_ 1341 current_driver->wave_out_volume(vol_left, vol_right);
264 astrand 499 break;
265     default:
266 ossman_ 1342 unimpl("RDPSND packet type %x\n", opcode);
267 astrand 499 break;
268 matthewc 474 }
269 matthewc 432 }
270    
271 ossman_ 1342 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 stargo 1274 static BOOL
325 stargo 1255 rdpsnd_auto_open(void)
326     {
327 stargo 1271 static BOOL failed = False;
328    
329     if (!failed)
330 stargo 1255 {
331 stargo 1271 struct audio_driver *auto_driver = current_driver;
332    
333     current_driver = drivers;
334     while (current_driver != NULL)
335 stargo 1255 {
336 stargo 1271 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 stargo 1255 }
345 stargo 1271
346     warning("no working audio-driver found\n");
347     failed = True;
348     current_driver = auto_driver;
349 stargo 1255 }
350    
351     return False;
352     }
353    
354 stargo 1274 static void
355 stargo 1255 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 ossman_ 1298 assert(*reg);
365 stargo 1255 reg = &((*reg)->next);
366     #endif
367 stargo 1264 #if defined(RDPSND_SUN)
368     *reg = sun_register(options);
369 ossman_ 1298 assert(*reg);
370 stargo 1264 reg = &((*reg)->next);
371     #endif
372 stargo 1255 #if defined(RDPSND_OSS)
373     *reg = oss_register(options);
374 ossman_ 1298 assert(*reg);
375 stargo 1255 reg = &((*reg)->next);
376     #endif
377     #if defined(RDPSND_SGI)
378     *reg = sgi_register(options);
379 ossman_ 1298 assert(*reg);
380 stargo 1255 reg = &((*reg)->next);
381     #endif
382     #if defined(RDPSND_LIBAO)
383     *reg = libao_register(options);
384 ossman_ 1302 assert(*reg);
385 stargo 1255 reg = &((*reg)->next);
386     #endif
387 stargo 1332 *reg = NULL;
388 stargo 1255 }
389    
390     BOOL
391 stargo 1272 rdpsnd_init(char *optarg)
392 stargo 1255 {
393     static struct audio_driver auto_driver;
394     struct audio_driver *pos;
395 stargo 1272 char *driver = NULL, *options = NULL;
396 stargo 1255
397     drivers = NULL;
398 stargo 1272
399 ossman_ 1342 packet.data = xmalloc(65536);
400     packet.p = packet.end = packet.data;
401     packet.size = 0;
402    
403 stargo 1272 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 ossman_ 1302 rdpsnd_queue_init();
414    
415 stargo 1272 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 stargo 1255 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 stargo 1273 void
471 stargo 1255 rdpsnd_play(void)
472     {
473     current_driver->wave_out_play();
474     }
475    
476 ossman_ 1299 void
477 ossman_ 1302 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 stargo 1254 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 ossman_ 1302 if (next_hi == queue_pending)
517 stargo 1254 {
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 ossman_ 1302 gettimeofday(&packet->arrive_tv, NULL);
529    
530 stargo 1254 if (!g_dsp_busy)
531 stargo 1255 current_driver->wave_out_play();
532 stargo 1254 }
533    
534 ossman_ 1299 struct audio_packet *
535 stargo 1254 rdpsnd_queue_current_packet(void)
536     {
537     return &packet_queue[queue_lo];
538     }
539    
540 ossman_ 1299 BOOL
541 stargo 1254 rdpsnd_queue_empty(void)
542     {
543     return (queue_lo == queue_hi);
544     }
545    
546 ossman_ 1302 static void
547 stargo 1254 rdpsnd_queue_init(void)
548     {
549 ossman_ 1302 queue_pending = queue_lo = queue_hi = 0;
550 stargo 1254 }
551    
552 ossman_ 1299 void
553 ossman_ 1302 rdpsnd_queue_next(unsigned long completed_in_us)
554 stargo 1254 {
555 ossman_ 1302 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 stargo 1254 queue_lo = (queue_lo + 1) % MAX_QUEUE;
568 ossman_ 1302
569     rdpsnd_queue_complete_pending();
570 stargo 1254 }
571    
572 ossman_ 1299 int
573 stargo 1254 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 ossman_ 1302
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 ossman_ 1337 elapsed /= 1000;
608 ossman_ 1302
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