Skip to content

Commit

Permalink
Merge pull request abrasive#184 from alfredperlstein/master
Browse files Browse the repository at this point in the history
Fixes for ipv4 networks and building on FreeBSD

This was tested on 32bit Ubuntu 12.10.
  • Loading branch information
splbio committed Mar 13, 2013
2 parents 617cbf5 + 01405e9 commit e6eb98b
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 23 deletions.
4 changes: 4 additions & 0 deletions FreeBSD.notes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/usr/ports/security/p5-Crypt-RSA
/usr/ports/security/p5-Crypt-OpenSSL-RSA
net/p5-Net-SDP
/usr/ports/net/p5-IO-Socket-INET6
9 changes: 9 additions & 0 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ Perl modules (install from CPAN if needed e.g. `perl -MCPAN -e 'install X'`):
gmake
perl shairport.pl

## FreeBSD

pkg_add -r gmake libao avahi p5-libwww p5-Crypt-OpenSSL-RSA p5-Net-SDP p5-IO-Socket-INET6
gmake
# ipv6 does not work for me, but maybe works for you? might be due to not
# having local ipv6 working dns names?
# force ipv4 on FreeBSD with '-4' on the command line.
perl shairport.pl -4

## Mac OS X:

* install XCode
Expand Down
15 changes: 13 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
CFLAGS:=-O2 -Wall $(shell pkg-config --cflags openssl ao)
LDFLAGS:=-lm -lpthread $(shell pkg-config --libs openssl ao)

MY_CFLAGS= $(shell pkg-config --cflags ao)
MY_LDFLAGS= $(shell pkg-config --libs ao)
ifeq ($(shell uname),FreeBSD)
MY_LDFLAGS+= -lssl
else
MY_CFLAGS+= $(shell pkg-config --cflags openssl)
MY_LDFLAGS+= $(shell pkg-config --libs openssl)
endif

CFLAGS:=-O2 -Wall $(MY_CFLAGS)
LDFLAGS:=-lm -lpthread $(MY_LDFLAGS)

OBJS=socketlib.o shairport.o alac.o hairtunes.o
all: hairtunes shairport

Expand Down
83 changes: 63 additions & 20 deletions hairtunes.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,12 @@ int hairtunes_init(char *pAeskey, char *pAesiv, char *fmtpstr, int pCtrlPort, in
return EXIT_SUCCESS;
}

#ifdef AF_INET6
static int ipv4_only = 0;
#else
static int ipv4_only = 1;
#endif

#ifdef HAIRTUNES_STANDALONE
int main(int argc, char **argv) {
char *hexaeskey = 0, *hexaesiv = 0;
Expand All @@ -257,6 +263,9 @@ int main(int argc, char **argv) {
hexaesiv = *++argv;
argc--;
} else
if (!strcasecmp(arg, "ipv4_only")) {
ipv4_only = 1;
} else
if (!strcasecmp(arg, "key")) {
hexaeskey = *++argv;
argc--;
Expand Down Expand Up @@ -403,20 +412,44 @@ static void buffer_put_packet(seq_t seqno, char *data, int len) {

static int rtp_sockets[2]; // data, control
#ifdef AF_INET6
static struct sockaddr_in6 rtp_client;
#else
static struct sockaddr_in rtp_client;
static struct sockaddr_in6 rtp_client6;
#endif
static struct sockaddr_in rtp_client4;

struct sockaddr * get_rtp_client_sockaddr(void) {

#ifdef AF_INET6
if (!ipv4_only) {
return ((struct sockaddr*)&rtp_client6);
}
#endif
return ((struct sockaddr*)&rtp_client4);
}

socklen_t get_rtp_sockaddr_len(void) {
#ifdef AF_INET6
if (!ipv4_only) {
return (sizeof(&rtp_client6));
}
#endif
return (sizeof(rtp_client4));
}



static void *rtp_thread_func(void *arg) {
socklen_t si_len = sizeof(rtp_client);
socklen_t si_len;
char packet[MAX_PACKET];
char *pktp;
seq_t seqno;
ssize_t plen;
int sock = rtp_sockets[0], csock = rtp_sockets[1];
int readsock;
char type;
struct sockaddr *rtp_client;

rtp_client = get_rtp_client_sockaddr();
si_len = get_rtp_sockaddr_len();

fd_set fds;
FD_ZERO(&fds);
Expand All @@ -432,7 +465,7 @@ static void *rtp_thread_func(void *arg) {
FD_SET(sock, &fds);
FD_SET(csock, &fds);

plen = recvfrom(readsock, packet, sizeof(packet), 0, (struct sockaddr*)&rtp_client, &si_len);
plen = recvfrom(readsock, packet, sizeof(packet), 0, rtp_client, &si_len);
if (plen < 0)
continue;
assert(plen<=MAX_PACKET);
Expand Down Expand Up @@ -481,12 +514,17 @@ static void rtp_request_resend(seq_t first, seq_t last) {
*(unsigned short *)(req+4) = htons(first); // missed seqnum
*(unsigned short *)(req+6) = htons(last-first+1); // count

struct sockaddr *rtp_client = get_rtp_client_sockaddr();

if (ipv4_only) {
((struct sockaddr_in *)rtp_client)->sin_port = htons(controlport);
}
#ifdef AF_INET6
rtp_client.sin6_port = htons(controlport);
#else
rtp_client.sin_port = htons(controlport);
else {
((struct sockaddr_in6 *)rtp_client)->sin6_port = htons(controlport);
}
#endif
sendto(rtp_sockets[1], req, sizeof(req), 0, (struct sockaddr *)&rtp_client, sizeof(rtp_client));
sendto(rtp_sockets[1], req, sizeof(req), 0, rtp_client, get_rtp_sockaddr_len());
}


Expand All @@ -499,11 +537,14 @@ static int init_rtp(void) {
memset(&si, 0, sizeof(si));
#ifdef AF_INET6
struct sockaddr_in6 si6;
type = AF_INET6;
si_p = (struct sockaddr*)&si6;
si_len = sizeof(si6);
sin_port = &si6.sin6_port;
memset(&si6, 0, sizeof(si6));

if (!ipv4_only) {
type = AF_INET6;
si_p = (struct sockaddr*)&si6;
si_len = sizeof(si6);
sin_port = &si6.sin6_port;
memset(&si6, 0, sizeof(si6));
}
#endif

si.sin_family = AF_INET;
Expand All @@ -512,12 +553,14 @@ static int init_rtp(void) {
#endif
si.sin_addr.s_addr = htonl(INADDR_ANY);
#ifdef AF_INET6
si6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
si6.sin6_len = sizeof(si);
#endif
si6.sin6_addr = in6addr_any;
si6.sin6_flowinfo = 0;
if (!ipv4_only) {
si6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
si6.sin6_len = sizeof(si);
#endif
si6.sin6_addr = in6addr_any;
si6.sin6_flowinfo = 0;
}
#endif

int sock = -1, csock = -1; // data and control (we treat the streams the same here)
Expand Down
22 changes: 21 additions & 1 deletion shairport.pl
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@
# show help
my $help;


my $ipv4_only;

unless (-x $hairtunes_cli) {
say "Can't find the 'hairtunes' decoder binary, you need to build this before using ShairPort.";
say "Read the INSTALL instructions!";
Expand All @@ -97,6 +100,7 @@
"ao_devicename=s" => \$libao_devicename,
"ao_deviceid=s" => \$libao_deviceid,
"v|verbose" => \$verbose,
"4" => \$ipv4_only,
"w|writepid=s" => \$writepid,
"s|squeezebox" => \$squeeze,
"c|cliport=s" => \$cliport,
Expand Down Expand Up @@ -295,6 +299,7 @@ sub REAP {

my $listen;
{
if (!defined($ipv4_only)) {
eval {
local $SIG{__DIE__};
$listen = new IO::Socket::INET6(Listen => 1,
Expand All @@ -309,6 +314,7 @@ sub REAP {
"* Install this if iTunes won't play. *\n",
"**************************************\n\n";
}
}

$listen ||= new IO::Socket::INET(Listen => 1,
LocalPort => $port,
Expand Down Expand Up @@ -491,6 +497,7 @@ sub performSqueezeboxSetup {
};

while (1) {
printf "about to select\n" if $verbose;
my @waiting = $sel->can_read;
foreach my $fh (@waiting) {
if ($fh==$listen) {
Expand All @@ -507,6 +514,7 @@ sub performSqueezeboxSetup {

# the 2nd connection is a player connection
if (defined($play_prog) && $sel->count() == 2) {
printf "play prog: $play_prog\n" if ($verbose);
system($play_prog);
}
} else {
Expand Down Expand Up @@ -541,6 +549,8 @@ sub conn_handle_data {
my $fh = shift;
my $conn = $conns{$fh};

printf "handle data 1\n" if ($verbose);

if ($conn->{req_need}) {
if (length($conn->{data}) >= $conn->{req_need}) {
$conn->{req}->content(substr($conn->{data}, 0, $conn->{req_need}, ''));
Expand Down Expand Up @@ -675,7 +685,11 @@ sub conn_handle_request {

my $dec = '"' . $hairtunes_cli . '"' . join(' ', '', map { sprintf "%s '%s'", $_, $dec_args{$_} } keys(%dec_args));

# print "decode command: $dec\n";
if ($ipv4_only) {
$dec .= " ipv4_only";
}

print "decode command: $dec\n" if ($verbose);
my $decoder = open2(my $dec_out, my $dec_in, $dec);

$conn->{decoder_pid} = $decoder;
Expand All @@ -701,10 +715,15 @@ sub conn_handle_request {
};
/^SET_PARAMETER$/ && do {
my @lines = split /[\r\n]+/, $req->content;
printf("SET_PARAMETER req: " . $req->content . "\n") if ($verbose);
my %content = map { /^(\S+): (.+)/; (lc $1, $2) } @lines;
my $cfh = $conn->{decoder_fh};
if (exists $content{volume}) {
printf("sending-> vol: %f\n", $content{volume}) if ($verbose);
printf $cfh "vol: %f\n", $content{volume};
} else {
printf("unable to perform content for req: " . $req->content . "\n") if ($verbose);

}
last;
};
Expand All @@ -713,6 +732,7 @@ sub conn_handle_request {
die("Unknown method: $_");
}

printf("%s", $resp->as_string("\r\n")) if ($verbose);
print $fh $resp->as_string("\r\n");
$fh->flush;
}
Expand Down

0 comments on commit e6eb98b

Please sign in to comment.