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");
28 namespace edash_packager {
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);
190 if (bind(new_socket.get(),
191 reinterpret_cast<struct sockaddr*
>(&local_sock_addr),
192 sizeof(local_sock_addr))) {
193 LOG(ERROR) <<
"Could not bind UDP socket";
197 if (IsIpv4MulticastAddress(dest_addr)) {
199 if (!StringToIpv4Address(FLAGS_udp_interface_address, &if_addr)) {
200 LOG(ERROR) <<
"Malformed IPv4 address for interface.";
203 struct ip_mreq multicast_group;
204 multicast_group.imr_multiaddr.s_addr = htonl(dest_addr);
205 multicast_group.imr_interface.s_addr = htonl(if_addr);
206 if (setsockopt(new_socket.get(),
210 sizeof(multicast_group)) < 0) {
211 LOG(ERROR) <<
"Failed to join multicast group.";
216 socket_ = new_socket.release();