Merge pull request #2126 from lynxis/libmicrohttpd
[feed/packages.git] / sound / squeezelite / patches / 010-select_broadcast_interface.patch
1 --- a/main.c
2 +++ b/main.c
3 @@ -69,6 +69,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>\t\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 @@ -197,6 +198,8 @@ int main(int argc, char **argv) {
12 char *modelname = NULL;
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 @@ -233,6 +236,7 @@ int main(int argc, char **argv) {
21 log_level log_ir = lWARN;
22 #endif
23
24 + memset(mac, 0, sizeof(mac));
25 char *optarg = NULL;
26 int optind = 1;
27 int i;
28 @@ -240,8 +244,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 @@ -249,7 +251,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("oabcCdefmMnNpPrs"
42 + if (strstr("oabcCdefImMnNpPrs"
43 #if ALSA
44 "UV"
45 #endif
46 @@ -334,6 +336,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 @@ -556,6 +561,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 @@ -599,7 +609,7 @@ int main(int argc, char **argv) {
69 exit(1);
70 }
71
72 - slimproto(log_slimproto, server, mac, name, namefile, modelname);
73 + slimproto(log_slimproto, server, bcast_addr, mac, name, namefile, modelname);
74
75 decode_close();
76 stream_close();
77 --- a/squeezelite.h
78 +++ b/squeezelite.h
79 @@ -374,7 +374,7 @@ typedef enum { EVENT_TIMEOUT = 0, EVENT_
80
81 char *next_param(char *src, char c);
82 u32_t gettime_ms(void);
83 -void get_mac(u8_t *mac);
84 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac);
85 void set_nonblock(sockfd s);
86 int connect_timeout(sockfd sock, const struct sockaddr *addr, socklen_t addrlen, int timeout);
87 void server_addr(char *server, in_addr_t *ip_ptr, unsigned *port_ptr);
88 @@ -426,7 +426,7 @@ void buf_init(struct buffer *buf, size_t
89 void buf_destroy(struct buffer *buf);
90
91 // slimproto.c
92 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname);
93 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname);
94 void slimproto_stop(void);
95 void wake_controller(void);
96
97 --- a/slimproto.c
98 +++ b/slimproto.c
99 @@ -107,7 +107,7 @@ void send_packet(u8_t *packet, size_t le
100 }
101 }
102
103 -static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t mac[6]) {
104 +static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap, u8_t *mac) {
105 const char *base_cap = "Model=squeezelite,AccuratePlayPoints=1,HasDigitalOut=1,HasPolarityInversion=1,Firmware=" VERSION;
106 struct HELO_packet pkt;
107
108 @@ -730,7 +730,7 @@ void wake_controller(void) {
109 wake_signal(wake_e);
110 }
111
112 -in_addr_t discover_server(void) {
113 +in_addr_t discover_server(in_addr_t bcast_addr) {
114 struct sockaddr_in d;
115 struct sockaddr_in s;
116 char *buf;
117 @@ -746,7 +746,7 @@ in_addr_t discover_server(void) {
118 memset(&d, 0, sizeof(d));
119 d.sin_family = AF_INET;
120 d.sin_port = htons(PORT);
121 - d.sin_addr.s_addr = htonl(INADDR_BROADCAST);
122 + d.sin_addr.s_addr = bcast_addr;
123
124 pollinfo.fd = disc_sock;
125 pollinfo.events = POLLIN;
126 @@ -777,7 +777,7 @@ in_addr_t discover_server(void) {
127 #define FIXED_CAP_LEN 256
128 #define VAR_CAP_LEN 128
129
130 -void slimproto(log_level level, char *server, u8_t mac[6], const char *name, const char *namefile, const char *modelname) {
131 +void slimproto(log_level level, char *server, in_addr_t bcast_addr, u8_t *mac, const char *name, const char *namefile, const char *modelname) {
132 struct sockaddr_in serv_addr;
133 static char fixed_cap[FIXED_CAP_LEN], var_cap[VAR_CAP_LEN] = "";
134 bool reconnect = false;
135 @@ -795,7 +795,7 @@ void slimproto(log_level level, char *se
136 }
137
138 if (!slimproto_ip) {
139 - slimproto_ip = discover_server();
140 + slimproto_ip = discover_server(bcast_addr);
141 }
142
143 if (!slimproto_port) {
144 @@ -870,7 +870,7 @@ void slimproto(log_level level, char *se
145
146 // rediscover server if it was not set at startup
147 if (!server && ++failed_connect > 5) {
148 - slimproto_ip = serv_addr.sin_addr.s_addr = discover_server();
149 + slimproto_ip = serv_addr.sin_addr.s_addr = discover_server(bcast_addr);
150 }
151
152 } else {
153 --- a/utils.c
154 +++ b/utils.c
155 @@ -21,11 +21,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 @@ -33,15 +33,11 @@
171 #if WIN
172 #include <iphlpapi.h>
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 @@ -99,67 +95,101 @@ u32_t gettime_ms(void) {
189 #endif
190 }
191
192 -// mac address
193 -#if LINUX
194 -// search first 4 interfaces returned by IFCONF
195 -void get_mac(u8_t mac[]) {
196 - struct ifconf ifc;
197 - struct ifreq *ifr, *ifend;
198 - struct ifreq ifreq;
199 - struct ifreq ifs[4];
200 -
201 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
202 -
203 - int s = socket(AF_INET, SOCK_DGRAM, 0);
204 -
205 - ifc.ifc_len = sizeof(ifs);
206 - ifc.ifc_req = ifs;
207 -
208 - if (ioctl(s, SIOCGIFCONF, &ifc) == 0) {
209 - ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
210 -
211 - for (ifr = ifc.ifc_req; ifr < ifend; ifr++) {
212 - if (ifr->ifr_addr.sa_family == AF_INET) {
213 -
214 - strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
215 - if (ioctl (s, SIOCGIFHWADDR, &ifreq) == 0) {
216 - memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
217 - if (mac[0]+mac[1]+mac[2] != 0) {
218 - break;
219 - }
220 +// Get broadcast address for interface (given or first available)
221 +// Return MAC address if none given
222 +#if LINUX || OSX || FREEBSD
223 +
224 +in_addr_t get_iface_info(log_level level, char *iface, u8_t *mac) {
225 + struct ifaddrs *addrs, *ifa;
226 + struct sockaddr *sdl;
227 + char ifname[16];
228 + unsigned char *ptr;
229 + in_addr_t bcast_addr = 0;
230 + int have_mac = 0, have_ifname = 0;
231 +
232 + loglevel = level;
233 +
234 + // Check for non-zero MAC
235 + if ((mac[0] | mac[1] | mac[2]) != 0)
236 + have_mac = 1;
237 +
238 + // Copy interface name, if it was provided.
239 + if (iface != NULL)
240 + {
241 + if( strlen(iface) > sizeof(ifname) )
242 + return -1;
243 +
244 + strncpy(ifname, iface, sizeof(ifname));
245 + have_ifname = 1;
246 + }
247 +
248 + if (getifaddrs(&addrs) == 0) {
249 + //iterate to find corresponding ethernet address
250 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
251 + // Skip LOOPBACK interfaces, DOWN interfaces and interfaces that
252 + // don't support BROADCAST.
253 + if ((ifa->ifa_flags & IFF_LOOPBACK)
254 + || !(ifa->ifa_flags & IFF_UP)
255 + || !(ifa->ifa_flags & IFF_BROADCAST))
256 + {
257 + continue;
258 + }
259 +
260 + if (!have_ifname)
261 + {
262 + // We have found a valid interface name. Keep it.
263 + strncpy(ifname, ifa->ifa_name, sizeof(ifname));
264 + have_ifname = 1;
265 + } else {
266 + if (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) != 0)
267 + {
268 + // This is not the interface we're looking for.
269 + continue;
270 }
271 }
272 - }
273 - }
274
275 - close(s);
276 -}
277 -#endif
278
279 -#if OSX || FREEBSD
280 -void get_mac(u8_t mac[]) {
281 - struct ifaddrs *addrs, *ptr;
282 - const struct sockaddr_dl *dlAddr;
283 - const unsigned char *base;
284 -
285 - mac[0] = mac[1] = mac[2] = mac[3] = mac[4] = mac[5] = 0;
286 -
287 - if (getifaddrs(&addrs) == 0) {
288 - ptr = addrs;
289 - while (ptr) {
290 - if (ptr->ifa_addr->sa_family == AF_LINK && ((const struct sockaddr_dl *) ptr->ifa_addr)->sdl_type == IFT_ETHER) {
291 - dlAddr = (const struct sockaddr_dl *)ptr->ifa_addr;
292 - base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
293 - memcpy(mac, base, min(dlAddr->sdl_alen, 6));
294 + // Check address family.
295 + if ((ifa->ifa_addr->sa_family == AF_INET) &&
296 + (((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr != 0))
297 + {
298 + // Get broadcast address and MAC address
299 + bcast_addr = ((struct sockaddr_in *)ifa->ifa_broadaddr)->sin_addr.s_addr;
300 break;
301 }
302 - ptr = ptr->ifa_next;
303 + else
304 + {
305 + // Address is not IPv4
306 + if (iface == NULL)
307 + have_ifname = 0;
308 + }
309 +
310 }
311 +
312 + // Find MAC address matching interface
313 + if (!have_mac && (bcast_addr != 0)) {
314 + for (ifa = addrs; ifa; ifa = ifa->ifa_next) {
315 + if ((ifa->ifa_addr->sa_family == PF_PACKET) &&
316 + (strncmp(ifname, ifa->ifa_name, sizeof(ifname)) == 0)) {
317 + sdl = (struct sockaddr *)(ifa->ifa_addr);
318 + ptr = (unsigned char *)sdl->sa_data;
319 + memcpy(mac, ptr + 10, 6);
320 + have_mac = 1;
321 + }
322 + }
323 + }
324 +
325 freeifaddrs(addrs);
326 }
327 +
328 + LOG_INFO("Interface: %s, broadcast: %08X, macaddr = %02x:%02x:%02x:%02x:%02x:%02x",
329 + ifname, bcast_addr, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
330 +
331 + return bcast_addr;
332 }
333 #endif
334
335 +
336 #if WIN
337 #pragma comment(lib, "IPHLPAPI.lib")
338 void get_mac(u8_t mac[]) {