squeezelite: update to 1.9.9-1432
[feed/packages.git] / sound / squeezelite / patches / 010-select_broadcast_interface.patch
1 --- a/main.c
2 +++ b/main.c
3 @@ -99,6 +99,7 @@ static void usage(const char *argv0) {
4 #if IR
5 " -i [<filename>]\tEnable lirc remote control support (lirc config file ~/.lircrc used if filename not specified)\n"
6 #endif
7 + " -I <interface>\tNetwork interface used to send discovery\n"
8 " -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
9 " -M <modelname>\tSet the squeezelite player model name sent to the server (default: " MODEL_NAME_STRING ")\n"
10 " -n <name>\t\tSet the player name\n"
11 @@ -304,6 +305,8 @@ int main(int argc, char **argv) {
12 extern bool user_rates;
13 char *logfile = NULL;
14 u8_t mac[6];
15 + char *iface = NULL;
16 + in_addr_t bcast_addr = 0;
17 unsigned stream_buf_size = STREAMBUF_SIZE;
18 unsigned output_buf_size = 0; // set later
19 unsigned rates[MAX_SUPPORTED_SAMPLERATES] = { 0 };
20 @@ -344,6 +347,7 @@ int main(int argc, char **argv) {
21
22 int maxSampleRate = 0;
23
24 + memset(mac, 0, sizeof(mac));
25 char *optarg = NULL;
26 int optind = 1;
27 int i;
28 @@ -351,8 +355,6 @@ int main(int argc, char **argv) {
29 #define MAXCMDLINE 512
30 char cmdline[MAXCMDLINE] = "";
31
32 - get_mac(mac);
33 -
34 for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
35 strcat(cmdline, argv[i]);
36 strcat(cmdline, " ");
37 @@ -360,7 +362,7 @@ int main(int argc, char **argv) {
38
39 while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') {
40 char *opt = argv[optind] + 1;
41 - if (strstr("oabcCdefmMnNpPrsZ"
42 + if (strstr("oabcCdefImMnNpPrsZ"
43 #if ALSA
44 "UVO"
45 #endif
46 @@ -454,6 +456,9 @@ int main(int argc, char **argv) {
47 case 'f':
48 logfile = optarg;
49 break;
50 + case 'I':
51 + iface = optarg;
52 + break;
53 case 'm':
54 {
55 int byte = 0;
56 @@ -767,6 +772,11 @@ int main(int argc, char **argv) {
57 winsock_init();
58 #endif
59
60 + if (!(bcast_addr = get_iface_info(log_slimproto, iface, mac))) {
61 + fprintf(stderr, "Error binding to network or none given\n");
62 + exit(1);
63 + }
64 +
65 stream_init(log_stream, stream_buf_size);
66
67 if (!strcmp(output_device, "-")) {
68 @@ -813,7 +823,7 @@ int main(int argc, char **argv) {
69 exit(1);
70 }
71
72 - slimproto(log_slimproto, server, mac, name, namefile, modelname, maxSampleRate);
73 + slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname, maxSampleRate);
74
75 decode_close();
76 stream_close();
77 --- a/slimproto.c
78 +++ b/slimproto.c
79 @@ -119,7 +119,7 @@ void send_packet(u8_t *packet, size_t le
80 }
81 }
82
83 -static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) {
84 +static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t *mac) {
85 #define BASE_CAP "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Balance=1,Firmware=" VERSION
86 #define SSL_CAP "CanHTTPS=1"
87 const char *base_cap;
88 @@ -768,7 +768,7 @@ void wake_controller(void) {
89 wake_signal(wake_e);
90 }
91
92 -in_addr_t discover_server(char *default_server) {
93 +in_addr_t discover_server(char *default_server, in_addr_t bcast_addr) {
94 struct sockaddr_in d;
95 struct sockaddr_in s;
96 char *buf;
97 @@ -785,7 +785,7 @@ in_addr_t discover_server(char *default_
98 memset(&d, 0, sizeof(d));
99 d.sin_family = AF_INET;
100 d.sin_port = htons(PORT);
101 - d.sin_addr.s_addr = htonl(INADDR_BROADCAST);
102 + d.sin_addr.s_addr = bcast_addr;
103
104 pollinfo.fd = disc_sock;
105 pollinfo.events = POLLIN;
106 @@ -820,7 +820,7 @@ in_addr_t discover_server(char *default_
107 #define FIXED_CAP_LEN 256
108 #define VAR_CAP_LEN 128
109
110 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate) {
111 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate) {
112 struct sockaddr_in serv_addr;
113 static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
114 bool reconnect = false;
115 @@ -841,7 +841,7 @@ void slimproto(log_level level, char *se
116 }
117
118 if (!slimproto_ip) {
119 - slimproto_ip = discover_server(server);
120 + slimproto_ip = discover_server(server, bcast_addr);
121 }
122
123 if (!slimproto_port) {
124 @@ -926,7 +926,7 @@ void slimproto(log_level level, char *se
125
126 // rediscover server if it was not set at startup
127 if (!server && ++failed_connect > 5) {
128 - slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL);
129 + slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(NULL, bcast_addr);
130 }
131
132 } else {
133 --- a/squeezelite.h
134 +++ b/squeezelite.h
135 @@ -463,7 +463,7 @@ char* strcasestr(const char *haystack, c
136
137 char *next_param(char *src, char c);
138 u32_t gettime_ms(void);
139 -void get_mac(u8_t *mac);
140 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac);
141 void set_nonblock(sockfd s);
142 void set_recvbufsize(sockfd s);
143 int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout);
144 @@ -521,7 +521,7 @@ void buf_init(struct buffer *buf, size_t
145 void buf_destroy(struct buffer *buf);
146
147 // slimproto.c
148 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate);
149 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t mac[6], const char *name, const char *namefile, const char *modelname, int maxSampleRate);
150 void slimproto_stop(void);
151 void wake_controller(void);
152
153 --- a/utils.c
154 +++ b/utils.c
155 @@ -22,11 +22,11 @@
156 #include "squeezelite.h"
157
158 #if LINUX || OSX || FREEBSD
159 -#include <sys/ioctl.h>
160 +#include <sys/types.h>
161 #include <net/if.h>
162 -#include <netdb.h>
163 -#if FREEBSD
164 #include <ifaddrs.h>
165 +#include <netdb.h>
166 +#if FREEBSD || OSX
167 #include <net/if_dl.h>
168 #include <net/if_types.h>
169 #endif
170 @@ -49,15 +49,11 @@
171 #include <ctype.h>
172 #endif
173 #endif
174 -#if OSX
175 -#include <net/if_dl.h>
176 -#include <net/if_types.h>
177 -#include <ifaddrs.h>
178 -#include <netdb.h>
179 -#endif
180
181 #include <fcntl.h>
182
183 +static log_level loglevel;
184 +
185 // logging functions
186 const char *logtime(void) {
187 static char buf[100];
188 @@ -120,58 +116,94 @@ u32_t gettime_ms(void) {
189 #endif
190 }
191
192 -// mac address
193 -#if LINUX && !defined(SUN)
194 -// search first 4 interfaces returned by IFCONF
195 -void get_mac(u8_t mac[]) {
196 - char *utmac;
197 - struct ifconf ifc;
198 - struct ifreq *ifr, *ifend;
199 - struct ifreq ifreq;
200 - struct ifreq ifs[4];
201 +// Get broadcast address for interface (given or first available)
202 +// Return MAC address if none given
203 +#if LINUX || OSX || FREEBSD
204
205 - utmac = getenv("UTMAC");
206 - if (utmac)
207 - {
208 - if ( strlen(utmac) == 17 )
209 - {
210 - if (sscanf(utmac,"%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
211 - &mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]) == 6)
212 - {
213 - return;
214 - }
215 - }
216 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) {
217 + struct ifaddrs *addrs, *ifa;
218 + struct sockaddr *sdl;
219 + char ifname[16];
220 + unsigned char *ptr;
221 + in_addr_t bcast_addr = 0;
222 + int have_mac = 0, have_ifname = 0;
223 +
224 + loglevel = level;
225 +
226 + // Check for non-zero MAC
227 + if (mac[0] | mac[1] | mac[2] != 0)
228 + have_mac = 1;
229 +
230 + // Copy interface name, if it was provided.
231 + if (iface != NULL) {
232 + if (strlen(iface) > sizeof(ifname))
233 + return -1;
234
235 + strncpy(ifname, iface, sizeof(ifname) - 1);
236 + have_ifname = 1;
237 }
238
239 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
240 + if (getifaddrs(&addrs) == 0) {
241 + //iterate to find corresponding ethernet address
242 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
243 + // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
244 + // don't support BROADCAST.
245 + if (ifa->ifa_flags & IFF_LOOPBACK
246 + || !ifa->ifa_flags & IFF_UP
247 + || !ifa->ifa_flags & IFF_BROADCAST) {
248 + continue;
249 + }
250
251 - int s = socket(AF_INET, SOCK_DGRAM, 0);
252 + if (!have_ifname) {
253 + // We have found a valid interface name. Keep it.
254 + strncpy(ifname, ifa->ifa_name, sizeof(ifname) - 1);
255 + have_ifname = 1;
256 + } else {
257 + if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0) {
258 + // This is not the interface we're looking for.
259 + continue;
260 + }
261 + }
262
263 - ifc.ifc_len = sizeof(ifs);
264 - ifc.ifc_req = ifs;
265
266 - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
267 - ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
268 + // Check address family.
269 + if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET &&
270 + ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0) {
271 + // Get broadcast address and MAC address
272 + bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr;
273 + break;
274 + }
275 + else {
276 + // Address is not IPv4
277 + if (iface == NULL)
278 + have_ifname = 0;
279 + }
280 + }
281
282 - for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
283 - if (ifr->ifr_addr.sa_family == AF_INET) {
284 -
285 - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name) - 1);
286 - if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
287 - memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
288 - if (mac[0]+mac[1]+mac[2] != 0) {
289 - break;
290 - }
291 + // Find MAC address matching interface
292 + if (!have_mac && bcast_addr != 0) {
293 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
294 + if (ifa->ifa_addr && ifa->ifa_addr->sa_family == PF_PACKET &&
295 + strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0) {
296 + sdl = (struct sockaddr *)(ifa->ifa_addr);
297 + ptr = (unsigned char *)sdl->sa_data;
298 + memcpy(mac, ptr + 10, 6);
299 + have_mac = 1;
300 }
301 }
302 }
303 +
304 + freeifaddrs(addrs);
305 }
306
307 - close(s);
308 + LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x",
309 + ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
310 +
311 + return bcast_addr;
312 }
313 #endif
314
315 +
316 #if SUN
317 void get_mac(u8_t mac[]) {
318 struct arpreq parpreq;
319 @@ -238,30 +270,6 @@ void get_mac(u8_t mac[]) {
320 }
321 #endif
322
323 -#if OSX || FREEBSD
324 -void get_mac(u8_t mac[]) {
325 - struct ifaddrs *addrs, *ptr;
326 - const struct sockaddr_dl *dlAddr;
327 - const unsigned char *base;
328 -
329 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
330 -
331 - if (getifaddrs(&addrs) == 0) {
332 - ptr = addrs;
333 - while (ptr) {
334 - if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
335 - dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
336 - base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
337 - memcpy(mac, base, min(dlAddr->sdl_alen, 6));
338 - break;
339 - }
340 - ptr = ptr->ifa_next;
341 - }
342 - freeifaddrs(addrs);
343 - }
344 -}
345 -#endif
346 -
347 #if WIN
348 #pragma comment(lib, "IPHLPAPI.lib")
349 void get_mac(u8_t mac[]) {