2 * Copyright (C) 2006 Benjamin Zores
3 * Network helpers for UDP connections (originally borrowed from rtp.c).
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <sys/types.h>
33 #include <netinet/in.h>
34 #include <sys/socket.h>
35 #include <arpa/inet.h>
36 #define closesocket close
46 /* Start listening on a UDP port. If multicast, join the group. */
48 udp_open_socket (URL_t
*url
)
50 int socket_server_fd
, rxsockbufsz
;
54 struct sockaddr_in server_address
;
59 mp_msg (MSGT_NETWORK
, MSGL_V
,
60 "Listening for traffic on %s:%d ...\n", url
->hostname
, url
->port
);
62 socket_server_fd
= socket (AF_INET
, SOCK_DGRAM
, 0);
63 if (socket_server_fd
== -1)
65 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to create socket\n");
69 if (isalpha (url
->hostname
[0]))
72 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
75 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
76 "Counldn't resolve name: %s\n", url
->hostname
);
77 closesocket (socket_server_fd
);
80 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
81 (void *) hp
->h_addr_list
[0], hp
->h_length
);
83 server_address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
84 #endif /* HAVE_WINSOCK2 */
90 inet_aton (url
->hostname
, &server_address
.sin_addr
);
92 inet_pton (AF_INET
, url
->hostname
, &server_address
.sin_addr
);
95 server_address
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
96 #endif /* HAVE_WINSOCK2 */
98 server_address
.sin_family
= AF_INET
;
99 server_address
.sin_port
= htons (url
->port
);
101 if (bind (socket_server_fd
, (struct sockaddr
*) &server_address
,
102 sizeof (server_address
)) == -1)
104 #ifndef HAVE_WINSOCK2
105 if (errno
!= EINPROGRESS
)
107 if (WSAGetLastError () != WSAEINPROGRESS
)
108 #endif /* HAVE_WINSOCK2 */
110 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to connect to server\n");
111 closesocket (socket_server_fd
);
117 if (isalpha (url
->hostname
[0]))
119 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
122 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
123 "Counldn't resolve name: %s\n", url
->hostname
);
124 closesocket (socket_server_fd
);
127 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
128 (void *) hp
->h_addr
, hp
->h_length
);
132 unsigned int addr
= inet_addr (url
->hostname
);
133 memcpy ((void *) &server_address
.sin_addr
, (void *) &addr
, sizeof (addr
));
135 #endif /* HAVE_WINSOCK2 */
137 /* Increase the socket rx buffer size to maximum -- this is UDP */
138 rxsockbufsz
= 240 * 1024;
139 if (setsockopt (socket_server_fd
, SOL_SOCKET
, SO_RCVBUF
,
140 &rxsockbufsz
, sizeof (rxsockbufsz
)))
142 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
143 "Couldn't set receive socket buffer size\n");
146 if ((ntohl (server_address
.sin_addr
.s_addr
) >> 28) == 0xe)
148 mcast
.imr_multiaddr
.s_addr
= server_address
.sin_addr
.s_addr
;
149 mcast
.imr_interface
.s_addr
= 0;
151 if (setsockopt (socket_server_fd
, IPPROTO_IP
,
152 IP_ADD_MEMBERSHIP
, &mcast
, sizeof (mcast
)))
154 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
155 closesocket (socket_server_fd
);
161 tv
.tv_usec
= (1 * 1000000); /* 1 second timeout */
164 FD_SET (socket_server_fd
, &set
);
166 err
= select (socket_server_fd
+ 1, &set
, NULL
, NULL
, &tv
);
169 mp_msg (MSGT_NETWORK
, MSGL_FATAL
,
170 "Select failed: %s\n", strerror (errno
));
171 closesocket (socket_server_fd
);
177 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
178 "Timeout! No data from host %s\n", url
->hostname
);
179 closesocket (socket_server_fd
);
183 err_len
= sizeof (err
);
184 getsockopt (socket_server_fd
, SOL_SOCKET
, SO_ERROR
, &err
, &err_len
);
187 mp_msg (MSGT_NETWORK
, MSGL_DBG2
, "Socket error: %d\n", err
);
188 closesocket (socket_server_fd
);
192 return socket_server_fd
;