7 #include "packager/media/file/udp_file.h"
12 #include <sys/socket.h>
17 #include "packager/base/logging.h"
18 #include "packager/media/file/udp_options.h"
27 const int kInvalidSocket(-1);
29 bool IsIpv4MulticastAddress(
const struct in_addr& addr) {
30 return (ntohl(addr.s_addr) & 0xf0000000) == 0xe0000000;
37 socket_(kInvalidSocket) {}
39 UdpFile::~UdpFile() {}
42 if (socket_ != kInvalidSocket) {
44 socket_ = kInvalidSocket;
52 DCHECK_GE(length, 65535u)
53 <<
"Buffer may be too small to read entire datagram.";
55 if (socket_ == kInvalidSocket)
60 result = recvfrom(socket_, buffer, length, 0, NULL, 0);
61 }
while ((result == -1) && (errno == EINTR));
72 if (socket_ == kInvalidSocket)
75 return std::numeric_limits<int64_t>::max();
95 explicit ScopedSocket(
int sock_fd)
96 : sock_fd_(sock_fd) {}
99 if (sock_fd_ != kInvalidSocket)
103 int get() {
return sock_fd_; }
106 int socket = sock_fd_;
107 sock_fd_ = kInvalidSocket;
114 DISALLOW_COPY_AND_ASSIGN(ScopedSocket);
118 DCHECK_EQ(kInvalidSocket, socket_);
120 std::unique_ptr<UdpOptions> options =
125 ScopedSocket new_socket(socket(AF_INET, SOCK_DGRAM, 0));
126 if (new_socket.get() == kInvalidSocket) {
127 LOG(ERROR) <<
"Could not allocate socket.";
131 struct sockaddr_in local_sock_addr;
132 bzero(&local_sock_addr,
sizeof(local_sock_addr));
134 local_sock_addr.sin_family = AF_INET;
135 local_sock_addr.sin_port = htons(options->port());
136 if (inet_pton(AF_INET, options->address().c_str(),
137 &local_sock_addr.sin_addr) != 1) {
138 LOG(ERROR) <<
"Malformed IPv4 address " << options->address();
142 if (options->reuse()) {
143 const int optval = 1;
144 if (setsockopt(new_socket.get(), SOL_SOCKET, SO_REUSEADDR, &optval,
145 sizeof(optval)) < 0) {
147 <<
"Could not apply the SO_REUSEADDR property to the UDP socket";
152 if (bind(new_socket.get(),
153 reinterpret_cast<struct sockaddr*
>(&local_sock_addr),
154 sizeof(local_sock_addr))) {
155 LOG(ERROR) <<
"Could not bind UDP socket";
159 if (IsIpv4MulticastAddress(local_sock_addr.sin_addr)) {
160 struct ip_mreq multicast_group;
161 multicast_group.imr_multiaddr = local_sock_addr.sin_addr;
163 if (options->interface_address().empty()) {
164 LOG(ERROR) <<
"Interface address is required for multicast, which can be "
165 "specified in udp url, e.g. "
166 "udp://ip:port?interface=interface_ip.";
169 if (inet_pton(AF_INET, options->interface_address().c_str(),
170 &multicast_group.imr_interface) != 1) {
171 LOG(ERROR) <<
"Malformed IPv4 interface address "
172 << options->interface_address();
176 if (setsockopt(new_socket.get(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
177 &multicast_group,
sizeof(multicast_group)) < 0) {
178 LOG(ERROR) <<
"Failed to join multicast group.";
184 if (options->timeout_us() != 0) {
186 tv.tv_sec = options->timeout_us() / 1000000;
187 tv.tv_usec = options->timeout_us() % 1000000;
188 if (setsockopt(new_socket.get(), SOL_SOCKET, SO_RCVTIMEO,
189 reinterpret_cast<char*
>(&tv),
sizeof(tv)) < 0) {
190 LOG(ERROR) <<
"Failed to set socket timeout.";
195 socket_ = new_socket.release();