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
48 /* Start listening on a UDP port. If multicast, join the group. */
50 udp_open_socket (URL_t
*url
)
52 int socket_server_fd
, rxsockbufsz
;
56 struct sockaddr_in server_address
;
60 int reuse
=reuse_socket
;
62 mp_msg (MSGT_NETWORK
, MSGL_V
,
63 "Listening for traffic on %s:%d ...\n", url
->hostname
, url
->port
);
65 socket_server_fd
= socket (AF_INET
, SOCK_DGRAM
, 0);
66 if (socket_server_fd
== -1)
68 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to create socket\n");
72 if (isalpha (url
->hostname
[0]))
75 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
78 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
79 "Counldn't resolve name: %s\n", url
->hostname
);
80 closesocket (socket_server_fd
);
83 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
84 (void *) hp
->h_addr_list
[0], hp
->h_length
);
86 server_address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
87 #endif /* HAVE_WINSOCK2 */
93 inet_aton (url
->hostname
, &server_address
.sin_addr
);
95 inet_pton (AF_INET
, url
->hostname
, &server_address
.sin_addr
);
98 server_address
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
99 #endif /* HAVE_WINSOCK2 */
101 server_address
.sin_family
= AF_INET
;
102 server_address
.sin_port
= htons (url
->port
);
104 if(reuse_socket
&& setsockopt(socket_server_fd
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(reuse
)))
105 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "SO_REUSEADDR failed! ignore.\n");
107 if (bind (socket_server_fd
, (struct sockaddr
*) &server_address
,
108 sizeof (server_address
)) == -1)
110 #ifndef HAVE_WINSOCK2
111 if (errno
!= EINPROGRESS
)
113 if (WSAGetLastError () != WSAEINPROGRESS
)
114 #endif /* HAVE_WINSOCK2 */
116 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to connect to server\n");
117 closesocket (socket_server_fd
);
123 if (isalpha (url
->hostname
[0]))
125 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
128 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
129 "Could not resolve name: %s\n", url
->hostname
);
130 closesocket (socket_server_fd
);
133 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
134 (void *) hp
->h_addr
, hp
->h_length
);
138 unsigned int addr
= inet_addr (url
->hostname
);
139 memcpy ((void *) &server_address
.sin_addr
, (void *) &addr
, sizeof (addr
));
141 #endif /* HAVE_WINSOCK2 */
143 /* Increase the socket rx buffer size to maximum -- this is UDP */
144 rxsockbufsz
= 240 * 1024;
145 if (setsockopt (socket_server_fd
, SOL_SOCKET
, SO_RCVBUF
,
146 &rxsockbufsz
, sizeof (rxsockbufsz
)))
148 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
149 "Couldn't set receive socket buffer size\n");
152 if ((ntohl (server_address
.sin_addr
.s_addr
) >> 28) == 0xe)
154 mcast
.imr_multiaddr
.s_addr
= server_address
.sin_addr
.s_addr
;
155 mcast
.imr_interface
.s_addr
= 0;
157 if (setsockopt (socket_server_fd
, IPPROTO_IP
,
158 IP_ADD_MEMBERSHIP
, &mcast
, sizeof (mcast
)))
160 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
161 closesocket (socket_server_fd
);
166 tv
.tv_sec
= 1; /* 1 second timeout */
170 FD_SET (socket_server_fd
, &set
);
172 err
= select (socket_server_fd
+ 1, &set
, NULL
, NULL
, &tv
);
175 mp_msg (MSGT_NETWORK
, MSGL_FATAL
,
176 "Select failed: %s\n", strerror (errno
));
177 closesocket (socket_server_fd
);
183 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
184 "Timeout! No data from host %s\n", url
->hostname
);
185 closesocket (socket_server_fd
);
189 err_len
= sizeof (err
);
190 getsockopt (socket_server_fd
, SOL_SOCKET
, SO_ERROR
, &err
, &err_len
);
193 mp_msg (MSGT_NETWORK
, MSGL_DBG2
, "Socket error: %d\n", err
);
194 closesocket (socket_server_fd
);
198 return socket_server_fd
;