1
/* $Id: sap.c 1272 2006-08-18 21:38:40Z lennart $ */
4
This file is part of PulseAudio.
6
PulseAudio is free software; you can redistribute it and/or modify
7
it under the terms of the GNU Lesser General Public License as published
8
by the Free Software Foundation; either version 2 of the License,
9
or (at your option) any later version.
11
PulseAudio is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU Lesser General Public License
17
along with PulseAudio; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29
#include <sys/types.h>
30
#include <sys/socket.h>
31
#include <netinet/in.h>
32
#include <arpa/inet.h>
36
#include <sys/ioctl.h>
38
#ifdef HAVE_SYS_FILIO_H
39
#include <sys/filio.h>
42
#include <pulse/xmalloc.h>
44
#include <pulsecore/core-error.h>
45
#include <pulsecore/core-util.h>
46
#include <pulsecore/log.h>
51
#define MIME_TYPE "application/sdp"
53
pa_sap_context* pa_sap_context_init_send(pa_sap_context *c, int fd, char *sdp_data) {
59
c->sdp_data = sdp_data;
60
c->msg_id_hash = (uint16_t) (rand()*rand());
65
void pa_sap_context_destroy(pa_sap_context *c) {
69
pa_xfree(c->sdp_data);
72
int pa_sap_send(pa_sap_context *c, int goodbye) {
74
struct sockaddr_storage sa_buf;
75
struct sockaddr *sa = (struct sockaddr*) &sa_buf;
76
socklen_t salen = sizeof(sa_buf);
81
if (getsockname(c->fd, sa, &salen) < 0) {
82
pa_log("getsockname() failed: %s\n", pa_cstrerror(errno));
86
assert(sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
88
header = htonl(((uint32_t) 1 << 29) |
89
(sa->sa_family == AF_INET6 ? (uint32_t) 1 << 28 : 0) |
90
(goodbye ? (uint32_t) 1 << 26 : 0) |
93
iov[0].iov_base = &header;
94
iov[0].iov_len = sizeof(header);
96
iov[1].iov_base = sa->sa_family == AF_INET ? (void*) &((struct sockaddr_in*) sa)->sin_addr : (void*) &((struct sockaddr_in6*) sa)->sin6_addr;
97
iov[1].iov_len = sa->sa_family == AF_INET ? 4 : 16;
99
iov[2].iov_base = (char*) MIME_TYPE;
100
iov[2].iov_len = sizeof(MIME_TYPE);
102
iov[3].iov_base = c->sdp_data;
103
iov[3].iov_len = strlen(c->sdp_data);
109
m.msg_control = NULL;
110
m.msg_controllen = 0;
113
if ((k = sendmsg(c->fd, &m, MSG_DONTWAIT)) < 0)
114
pa_log("sendmsg() failed: %s\n", pa_cstrerror(errno));
119
pa_sap_context* pa_sap_context_init_recv(pa_sap_context *c, int fd) {
128
int pa_sap_recv(pa_sap_context *c, int *goodbye) {
132
char *buf = NULL, *e;
140
if (ioctl(c->fd, FIONREAD, &size) < 0) {
141
pa_log("FIONREAD failed: %s", pa_cstrerror(errno));
148
buf = pa_xnew(char, size+1);
158
m.msg_control = NULL;
159
m.msg_controllen = 0;
162
if ((r = recvmsg(c->fd, &m, 0)) != size) {
163
pa_log("recvmsg() failed: %s", r < 0 ? pa_cstrerror(errno) : "size mismatch");
168
pa_log("SAP packet too short.");
172
memcpy(&header, buf, sizeof(uint32_t));
173
header = ntohl(header);
175
if (header >> 29 != 1) {
176
pa_log("Unsupported SAP version.");
180
if ((header >> 25) & 1) {
181
pa_log("Encrypted SAP not supported.");
185
if ((header >> 24) & 1) {
186
pa_log("Compressed SAP not supported.");
190
six = (header >> 28) & 1;
191
ac = (header >> 16) & 0xFF;
193
k = 4 + (six ? 16 : 4) + ac*4;
195
pa_log("SAP packet too short (AD).");
202
if ((unsigned) size >= sizeof(MIME_TYPE) && !strcmp(e, MIME_TYPE)) {
203
e += sizeof(MIME_TYPE);
204
size -= sizeof(MIME_TYPE);
205
} else if ((unsigned) size < sizeof(PA_SDP_HEADER)-1 || strncmp(e, PA_SDP_HEADER, sizeof(PA_SDP_HEADER)-1)) {
206
pa_log("Invalid SDP header.");
211
pa_xfree(c->sdp_data);
213
c->sdp_data = pa_xstrndup(e, size);
216
*goodbye = !!((header >> 26) & 1);