2 * network helpers for UDP connections (originally borrowed from rtp.c)
4 * Copyright (C) 2006 Benjamin Zores
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <sys/types.h>
34 #ifndef HAVE_WINSOCK2_H
36 #include <netinet/in.h>
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
51 /* Start listening on a UDP port. If multicast, join the group. */
53 udp_open_socket (URL_t
*url
)
55 int socket_server_fd
, rxsockbufsz
;
59 struct sockaddr_in server_address
;
63 int reuse
=reuse_socket
;
65 mp_msg (MSGT_NETWORK
, MSGL_V
,
66 "Listening for traffic on %s:%d ...\n", url
->hostname
, url
->port
);
68 socket_server_fd
= socket (AF_INET
, SOCK_DGRAM
, 0);
69 if (socket_server_fd
== -1)
71 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to create socket\n");
75 if (isalpha (url
->hostname
[0]))
77 #ifndef HAVE_WINSOCK2_H
78 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
81 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
82 "Counldn't resolve name: %s\n", url
->hostname
);
83 closesocket (socket_server_fd
);
86 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
87 (void *) hp
->h_addr_list
[0], hp
->h_length
);
89 server_address
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
90 #endif /* HAVE_WINSOCK2_H */
94 #ifndef HAVE_WINSOCK2_H
96 inet_aton (url
->hostname
, &server_address
.sin_addr
);
98 inet_pton (AF_INET
, url
->hostname
, &server_address
.sin_addr
);
99 #endif /* HAVE_INET_ATON */
101 server_address
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
102 #endif /* HAVE_WINSOCK2_H */
104 server_address
.sin_family
= AF_INET
;
105 server_address
.sin_port
= htons (url
->port
);
107 if(reuse_socket
&& setsockopt(socket_server_fd
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(reuse
)))
108 mp_msg(MSGT_NETWORK
, MSGL_ERR
, "SO_REUSEADDR failed! ignore.\n");
110 if (bind (socket_server_fd
, (struct sockaddr
*) &server_address
,
111 sizeof (server_address
)) == -1)
113 #ifndef HAVE_WINSOCK2_H
114 if (errno
!= EINPROGRESS
)
116 if (WSAGetLastError () != WSAEINPROGRESS
)
117 #endif /* HAVE_WINSOCK2_H */
119 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "Failed to connect to server\n");
120 closesocket (socket_server_fd
);
125 #ifdef HAVE_WINSOCK2_H
126 if (isalpha (url
->hostname
[0]))
128 hp
= (struct hostent
*) gethostbyname (url
->hostname
);
131 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
132 "Could not resolve name: %s\n", url
->hostname
);
133 closesocket (socket_server_fd
);
136 memcpy ((void *) &server_address
.sin_addr
.s_addr
,
137 (void *) hp
->h_addr
, hp
->h_length
);
141 unsigned int addr
= inet_addr (url
->hostname
);
142 memcpy ((void *) &server_address
.sin_addr
, (void *) &addr
, sizeof (addr
));
144 #endif /* HAVE_WINSOCK2_H */
146 /* Increase the socket rx buffer size to maximum -- this is UDP */
147 rxsockbufsz
= 240 * 1024;
148 if (setsockopt (socket_server_fd
, SOL_SOCKET
, SO_RCVBUF
,
149 &rxsockbufsz
, sizeof (rxsockbufsz
)))
151 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
152 "Couldn't set receive socket buffer size\n");
155 if ((ntohl (server_address
.sin_addr
.s_addr
) >> 28) == 0xe)
157 mcast
.imr_multiaddr
.s_addr
= server_address
.sin_addr
.s_addr
;
158 mcast
.imr_interface
.s_addr
= 0;
160 if (setsockopt (socket_server_fd
, IPPROTO_IP
,
161 IP_ADD_MEMBERSHIP
, &mcast
, sizeof (mcast
)))
163 mp_msg (MSGT_NETWORK
, MSGL_ERR
, "IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
164 closesocket (socket_server_fd
);
169 tv
.tv_sec
= 1; /* 1 second timeout */
173 FD_SET (socket_server_fd
, &set
);
175 err
= select (socket_server_fd
+ 1, &set
, NULL
, NULL
, &tv
);
178 mp_msg (MSGT_NETWORK
, MSGL_FATAL
,
179 "Select failed: %s\n", strerror (errno
));
180 closesocket (socket_server_fd
);
186 mp_msg (MSGT_NETWORK
, MSGL_ERR
,
187 "Timeout! No data from host %s\n", url
->hostname
);
188 closesocket (socket_server_fd
);
192 err_len
= sizeof (err
);
193 getsockopt (socket_server_fd
, SOL_SOCKET
, SO_ERROR
, &err
, &err_len
);
196 mp_msg (MSGT_NETWORK
, MSGL_DBG2
, "Socket error: %d\n", err
);
197 closesocket (socket_server_fd
);
201 return socket_server_fd
;