7 #include "packager/media/file/udp_file.h"
11 #include <gflags/gflags.h>
13 #include <sys/socket.h>
18 #include "packager/base/logging.h"
19 #include "packager/base/strings/string_number_conversions.h"
23 DEFINE_string(udp_interface_address,
25 "IP address of the interface over which to receive UDP unicast"
26 " or multicast streams");
33 const int kInvalidSocket(-1);
35 bool StringToIpv4Address(
const std::string& addr_in, uint32_t* addr_out) {
41 for (
int i = 0; i < 4; ++i) {
42 end_pos = addr_in.find(
'.', start_pos);
43 if ((end_pos == std::string::npos) != (i == 3))
46 if (!base::StringToUint(addr_in.substr(start_pos, end_pos - start_pos),
51 *addr_out |= addr_byte;
52 start_pos = end_pos + 1;
57 bool StringToIpv4AddressAndPort(
const std::string& addr_and_port,
63 size_t colon_pos = addr_and_port.find(
':');
64 if (colon_pos == std::string::npos) {
67 if (!StringToIpv4Address(addr_and_port.substr(0, colon_pos), addr))
70 if (!base::StringToUint(addr_and_port.substr(colon_pos + 1),
78 bool IsIpv4MulticastAddress(uint32_t addr) {
79 return (addr & 0xf0000000) == 0xe0000000;
86 socket_(kInvalidSocket) {}
88 UdpFile::~UdpFile() {}
91 if (socket_ != kInvalidSocket) {
93 socket_ = kInvalidSocket;
101 DCHECK_GE(length, 65535u)
102 <<
"Buffer may be too small to read entire datagram.";
104 if (socket_ == kInvalidSocket)
109 result = recvfrom(socket_, buffer, length, 0, NULL, 0);
110 }
while ((result == -1) && (errno == EINTR));
121 if (socket_ == kInvalidSocket)
124 return std::numeric_limits<int64_t>::max();
144 explicit ScopedSocket(
int sock_fd)
145 : sock_fd_(sock_fd) {}
148 if (sock_fd_ != kInvalidSocket)
152 int get() {
return sock_fd_; }
155 int socket = sock_fd_;
156 sock_fd_ = kInvalidSocket;
163 DISALLOW_COPY_AND_ASSIGN(ScopedSocket);
167 DCHECK_EQ(kInvalidSocket, socket_);
172 if (!StringToIpv4AddressAndPort(
file_name(),
175 LOG(ERROR) <<
"Malformed IPv4 address:port UDP stream specifier.";
179 ScopedSocket new_socket(socket(AF_INET, SOCK_DGRAM, 0));
180 if (new_socket.get() == kInvalidSocket) {
181 LOG(ERROR) <<
"Could not allocate socket.";
185 struct sockaddr_in local_sock_addr;
186 bzero(&local_sock_addr,
sizeof(local_sock_addr));
187 local_sock_addr.sin_family = AF_INET;
188 local_sock_addr.sin_port = htons(dest_port);
189 local_sock_addr.sin_addr.s_addr = htonl(dest_addr);
191 const int optval = 1;
192 if (setsockopt(new_socket.get(), SOL_SOCKET, SO_REUSEADDR, &optval,
193 sizeof(optval)) < 0) {
195 <<
"Could not apply the SO_REUSEADDR property to the UDP socket";
198 if (bind(new_socket.get(),
199 reinterpret_cast<struct sockaddr*
>(&local_sock_addr),
200 sizeof(local_sock_addr))) {
201 LOG(ERROR) <<
"Could not bind UDP socket";
205 if (IsIpv4MulticastAddress(dest_addr)) {
207 if (!StringToIpv4Address(FLAGS_udp_interface_address, &if_addr)) {
208 LOG(ERROR) <<
"Malformed IPv4 address for interface.";
211 struct ip_mreq multicast_group;
212 multicast_group.imr_multiaddr.s_addr = htonl(dest_addr);
213 multicast_group.imr_interface.s_addr = htonl(if_addr);
214 if (setsockopt(new_socket.get(),
218 sizeof(multicast_group)) < 0) {
219 LOG(ERROR) <<
"Failed to join multicast group.";
224 socket_ = new_socket.release();