1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*
* xine_frontend_vdrdiscovery.c
*
* Try to found VDR with xineliboutput server from (local) network.
*
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
* $Id: xine_frontend_vdrdiscovery.c,v 1.2 2006-07-02 16:43:30 phintuka Exp $
*
*/
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "xine_input_vdr_net.h" /* default ports */
static int search_vdr_server(int *port, char *address)
{
struct sockaddr_in sin;
int fd_broadcast = -1;
int dummy = 1, trycount = 0;
struct pollfd pfd;
char pktbuf[1024];
*port = DEFAULT_VDR_PORT;
strcpy(address, "vdr");
if ((fd_broadcast = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_TCP*/)) < 0) {
LOGERR("fd_broadcast = socket() failed");
} else {
if(setsockopt(fd_broadcast, SOL_SOCKET, SO_BROADCAST,
&dummy, sizeof(int)) < 0)
LOGERR("setsockopt(SO_BROADCAST) failed");
if(setsockopt(fd_broadcast, SOL_SOCKET, SO_REUSEADDR,
&dummy, sizeof(int)) < 0)
LOGERR("setsockopt(SO_REUSEADDR) failed");
sin.sin_family = AF_INET;
sin.sin_port = htons(DISCOVERY_PORT);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(fd_broadcast, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
LOGERR("Can't bind fd_broadcast to %d", DISCOVERY_PORT);
} else {
char *test = "VDR xineliboutput DISCOVERY 1.0\r\n"
"Client: 192.168.1.21:37890\r\n"
"\r\n";
int testlen = strlen(test);
retry:
sin.sin_addr.s_addr = INADDR_BROADCAST;
if(testlen != sendto(fd_broadcast, test, testlen, 0,
(struct sockaddr *)&sin, sizeof(sin))) {
LOGERR("UDP broadcast send failed (discovery)");
} else {
while(1) {
int err;
pfd.fd = fd_broadcast;
pfd.events = POLLIN;
errno=0;
while(1==(err=poll(&pfd, 1, 500))) {
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
memset(pktbuf, 0, sizeof(pktbuf));
errno=0;
if((err=recvfrom(fd_broadcast, pktbuf, 1023, 0,
(struct sockaddr *)&from, &fromlen)) > 0) {
char *mystring = "VDR xineliboutput DISCOVERY 1.0\r\n"
"Server port: ";
uint32_t tmp = ntohl(from.sin_addr.s_addr);
pktbuf[err] = 0;
LOGDBG("Reveived broadcast: %d bytes from %d.%d.%d.%d\n %s",
err,
((tmp>>24)&0xff), ((tmp>>16)&0xff),
((tmp>>8)&0xff), ((tmp)&0xff),
pktbuf);
if(!strncmp(mystring, pktbuf, strlen(mystring))) {
LOGDBG("Valid discovery message");
close(fd_broadcast);
sprintf(address, "%d.%d.%d.%d",
((tmp>>24)&0xff), ((tmp>>16)&0xff),
((tmp>>8)&0xff), ((tmp)&0xff));
if(1==sscanf(pktbuf+strlen(mystring), "%d", port))
return 1;
} else {
LOGDBG("NOT valid discovery message");
}
} else {
LOGERR("broadcast recvfrom failed");
break;
}
}
if(!err) {
/* timeout */
trycount++;
if(trycount < 3)
goto retry;
break;
}
LOGERR("broadcast poll error");
break;
}
}
}
}
/* failed */
close(fd_broadcast);
return 0;
}
|