rdpsnd.c (3629B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "channels/common-svc.h" 21#include "channels/rdpsnd/rdpsnd.h" 22#include "channels/rdpsnd/rdpsnd-messages.h" 23#include "rdp.h" 24 25#include <freerdp/codec/audio.h> 26#include <freerdp/freerdp.h> 27#include <guacamole/client.h> 28#include <guacamole/mem.h> 29#include <winpr/stream.h> 30 31#include <stdlib.h> 32 33void guac_rdpsnd_process_receive(guac_rdp_common_svc* svc, 34 wStream* input_stream) { 35 36 guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; 37 guac_rdpsnd_pdu_header header; 38 39 /* Check that we have at least the 4 byte header (UINT8 + UINT8 + UINT16) */ 40 if (Stream_GetRemainingLength(input_stream) < 4) { 41 guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Stream does not " 42 "contain the expected number of bytes. Audio redirection may " 43 "not work as expected."); 44 return; 45 } 46 47 /* Read RDPSND PDU header */ 48 Stream_Read_UINT8(input_stream, header.message_type); 49 Stream_Seek_UINT8(input_stream); 50 Stream_Read_UINT16(input_stream, header.body_size); 51 52 /* 53 * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously), 54 * ignore the header and parse as a Wave PDU. 55 */ 56 if (rdpsnd->next_pdu_is_wave) { 57 guac_rdpsnd_wave_handler(svc, input_stream, &header); 58 return; 59 } 60 61 /* Dispatch message to standard handlers */ 62 switch (header.message_type) { 63 64 /* Server Audio Formats and Version PDU */ 65 case SNDC_FORMATS: 66 guac_rdpsnd_formats_handler(svc, input_stream, &header); 67 break; 68 69 /* Training PDU */ 70 case SNDC_TRAINING: 71 guac_rdpsnd_training_handler(svc, input_stream, &header); 72 break; 73 74 /* WaveInfo PDU */ 75 case SNDC_WAVE: 76 guac_rdpsnd_wave_info_handler(svc, input_stream, &header); 77 break; 78 79 /* Close PDU */ 80 case SNDC_CLOSE: 81 guac_rdpsnd_close_handler(svc, input_stream, &header); 82 break; 83 84 } 85 86} 87 88void guac_rdpsnd_process_connect(guac_rdp_common_svc* svc) { 89 90 guac_rdpsnd* rdpsnd = (guac_rdpsnd*) guac_mem_zalloc(sizeof(guac_rdpsnd)); 91 svc->data = rdpsnd; 92 93} 94 95void guac_rdpsnd_process_terminate(guac_rdp_common_svc* svc) { 96 guac_mem_free(svc->data); 97} 98 99void guac_rdpsnd_load_plugin(rdpContext* context) { 100 101 guac_client* client = ((rdp_freerdp_context*) context)->client; 102 103 /* Load support for RDPSND */ 104 if (guac_rdp_common_svc_load_plugin(context, "rdpsnd", 0, 105 guac_rdpsnd_process_connect, guac_rdpsnd_process_receive, 106 guac_rdpsnd_process_terminate)) { 107 guac_client_log(client, GUAC_LOG_WARNING, "Support for the RDPSND " 108 "channel (audio output) could not be loaded. Sound will not " 109 "work. Drive redirection and printing MAY not work."); 110 } 111 112} 113