| /* | 
 |  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #ifndef WEBRTC_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_ | 
 | #define WEBRTC_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_ | 
 |  | 
 | #include "webrtc/api/call/transport.h" | 
 | #include "webrtc/common_types.h" | 
 | #include "webrtc/typedefs.h" | 
 |  | 
 | /* | 
 |  *  WARNING | 
 |  *  This code is not use in production/testing and might have security issues | 
 |  *  for example: http://code.google.com/p/webrtc/issues/detail?id=1028 | 
 |  * | 
 |  */ | 
 |  | 
 | #define SS_MAXSIZE 128 | 
 | #define SS_ALIGNSIZE (sizeof (uint64_t)) | 
 | #define SS_PAD1SIZE  (SS_ALIGNSIZE - sizeof(int16_t)) | 
 | #define SS_PAD2SIZE  (SS_MAXSIZE - (sizeof(int16_t) + SS_PAD1SIZE +\ | 
 |                                     SS_ALIGNSIZE)) | 
 |  | 
 | // BSD requires use of HAVE_STRUCT_SOCKADDR_SA_LEN | 
 | namespace webrtc { | 
 | namespace test { | 
 |  | 
 | struct SocketAddressIn { | 
 |   // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) | 
 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | 
 |   int8_t      sin_length; | 
 |   int8_t      sin_family; | 
 | #else | 
 |   int16_t     sin_family; | 
 | #endif | 
 |   uint16_t    sin_port; | 
 |   uint32_t    sin_addr; | 
 |   int8_t      sin_zero[8]; | 
 | }; | 
 |  | 
 | struct Version6InAddress { | 
 |   union { | 
 |     uint8_t     _s6_u8[16]; | 
 |     uint32_t    _s6_u32[4]; | 
 |     uint64_t    _s6_u64[2]; | 
 |   } Version6AddressUnion; | 
 | }; | 
 |  | 
 | struct SocketAddressInVersion6 { | 
 |   // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) | 
 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | 
 |   int8_t      sin_length; | 
 |   int8_t      sin_family; | 
 | #else | 
 |   int16_t     sin_family; | 
 | #endif | 
 |   // Transport layer port number. | 
 |   uint16_t sin6_port; | 
 |   // IPv6 traffic class and flow info or ip4 address. | 
 |   uint32_t sin6_flowinfo; | 
 |   // IPv6 address | 
 |   struct Version6InAddress sin6_addr; | 
 |   // Set of interfaces for a scope. | 
 |   uint32_t sin6_scope_id; | 
 | }; | 
 |  | 
 | struct SocketAddressStorage { | 
 |   // sin_family should be either AF_INET (IPv4) or AF_INET6 (IPv6) | 
 | #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN | 
 |   int8_t   sin_length; | 
 |   int8_t   sin_family; | 
 | #else | 
 |   int16_t  sin_family; | 
 | #endif | 
 |   int8_t   __ss_pad1[SS_PAD1SIZE]; | 
 |   uint64_t __ss_align; | 
 |   int8_t   __ss_pad2[SS_PAD2SIZE]; | 
 | }; | 
 |  | 
 | struct SocketAddress { | 
 |   union { | 
 |     struct SocketAddressIn _sockaddr_in; | 
 |     struct SocketAddressInVersion6 _sockaddr_in6; | 
 |     struct SocketAddressStorage _sockaddr_storage; | 
 |   }; | 
 | }; | 
 |  | 
 | // Callback class that receives packets from UdpTransport. | 
 | class UdpTransportData { | 
 |  public: | 
 |   virtual ~UdpTransportData()  {}; | 
 |  | 
 |   virtual void IncomingRTPPacket(const int8_t* incomingRtpPacket, | 
 |                                  const size_t rtpPacketLength, | 
 |                                  const char* fromIP, | 
 |                                  const uint16_t fromPort) = 0; | 
 |  | 
 |   virtual void IncomingRTCPPacket(const int8_t* incomingRtcpPacket, | 
 |                                   const size_t rtcpPacketLength, | 
 |                                   const char* fromIP, | 
 |                                   const uint16_t fromPort) = 0; | 
 | }; | 
 |  | 
 | class UdpTransport : public Transport { | 
 |  public: | 
 |     enum | 
 |     { | 
 |         kIpAddressVersion6Length = 64, | 
 |         kIpAddressVersion4Length = 16 | 
 |     }; | 
 |     enum ErrorCode | 
 |     { | 
 |         kNoSocketError            = 0, | 
 |         kFailedToBindPort         = 1, | 
 |         kIpAddressInvalid         = 2, | 
 |         kAddressInvalid           = 3, | 
 |         kSocketInvalid            = 4, | 
 |         kPortInvalid              = 5, | 
 |         kTosInvalid               = 6, | 
 |         kMulticastAddressInvalid  = 7, | 
 |         kQosError                 = 8, | 
 |         kSocketAlreadyInitialized = 9, | 
 |         kIpVersion6Error          = 10, | 
 |         FILTER_ERROR              = 11, | 
 |         kStartReceiveError        = 12, | 
 |         kStopReceiveError         = 13, | 
 |         kCannotFindLocalIp        = 14, | 
 |         kTosError                 = 16, | 
 |         kNotInitialized           = 17, | 
 |         kPcpError                 = 18 | 
 |     }; | 
 |  | 
 |     // Factory method. Constructor disabled. | 
 |     static UdpTransport* Create(const int32_t id, uint8_t& numSocketThreads); | 
 |     static void Destroy(UdpTransport* module); | 
 |  | 
 |     // Prepares the class for sending RTP packets to ipAddr:rtpPort and RTCP | 
 |     // packets to ipAddr:rtpPort+1 if rtcpPort is zero. Otherwise to | 
 |     // ipAddr:rtcpPort. | 
 |     virtual int32_t InitializeSendSockets(const char* ipAddr, | 
 |                                           const uint16_t rtpPort, | 
 |                                           const uint16_t rtcpPort = 0) = 0; | 
 |  | 
 |     // Register packetCallback for receiving incoming packets. Set the local | 
 |     // RTP port to rtpPort. Bind local IP address to ipAddr. If ipAddr is NULL | 
 |     // bind to local IP ANY. Set the local rtcp port to rtcpPort or rtpPort + 1 | 
 |     // if rtcpPort is 0. | 
 |     virtual int32_t InitializeReceiveSockets( | 
 |         UdpTransportData* const packetCallback, | 
 |         const uint16_t rtpPort, | 
 |         const char* ipAddr = NULL, | 
 |         const char* multicastIpAddr = NULL, | 
 |         const uint16_t rtcpPort = 0) = 0; | 
 |  | 
 |     // Set local RTP port to rtpPort and RTCP port to rtcpPort or rtpPort + 1 if | 
 |     // rtcpPort is 0. These ports will be used for sending instead of the local | 
 |     // ports set by InitializeReceiveSockets(..). | 
 |     virtual int32_t InitializeSourcePorts(const uint16_t rtpPort, | 
 |                                           const uint16_t rtcpPort = 0) = 0; | 
 |  | 
 |     // Retrieve local ports used for sending if other than the ports specified | 
 |     // by InitializeReceiveSockets(..). rtpPort is set to the RTP port. | 
 |     // rtcpPort is set to the RTCP port. | 
 |     virtual int32_t SourcePorts(uint16_t& rtpPort, | 
 |                                 uint16_t& rtcpPort) const = 0; | 
 |  | 
 |     // Set ipAddr to the IP address that is currently being listened on. rtpPort | 
 |     // to the RTP port listened to. rtcpPort to the RTCP port listened on. | 
 |     // multicastIpAddr to the multicast IP address group joined (the address | 
 |     // is NULL terminated). | 
 |     virtual int32_t ReceiveSocketInformation( | 
 |         char ipAddr[kIpAddressVersion6Length], | 
 |         uint16_t& rtpPort, | 
 |         uint16_t& rtcpPort, | 
 |         char multicastIpAddr[kIpAddressVersion6Length]) const = 0; | 
 |  | 
 |     // Set ipAddr to the IP address being sent from. rtpPort to the local RTP | 
 |     // port used for sending and rtcpPort to the local RTCP port used for | 
 |     // sending. | 
 |     virtual int32_t SendSocketInformation(char ipAddr[kIpAddressVersion6Length], | 
 |                                           uint16_t& rtpPort, | 
 |                                           uint16_t& rtcpPort) const = 0; | 
 |  | 
 |     // Put the IP address, RTP port and RTCP port from the last received packet | 
 |     // into ipAddr, rtpPort and rtcpPort respectively. | 
 |     virtual int32_t RemoteSocketInformation( | 
 |         char ipAddr[kIpAddressVersion6Length], | 
 |         uint16_t& rtpPort, | 
 |         uint16_t& rtcpPort) const = 0; | 
 |  | 
 |     // Enable/disable quality of service if QoS is true or false respectively. | 
 |     // Set the type of service to serviceType, max bitrate in kbit/s to | 
 |     // maxBitrate and override DSCP if overrideDSCP is not 0. | 
 |     // Note: Must be called both InitializeSendSockets() and | 
 |     // InitializeReceiveSockets() has been called. | 
 |     virtual int32_t SetQoS(const bool QoS, | 
 |                            const int32_t serviceType, | 
 |                            const uint32_t maxBitrate = 0, | 
 |                            const int32_t overrideDSCP = 0, | 
 |                            const bool audio = false) = 0; | 
 |  | 
 |     // Set QoS to true if quality of service has been turned on. If QoS is true, | 
 |     // also set serviceType to type of service and overrideDSCP to override | 
 |     // DSCP. | 
 |     virtual int32_t QoS(bool& QoS, | 
 |                         int32_t& serviceType, | 
 |                         int32_t& overrideDSCP) const = 0; | 
 |  | 
 |     // Set type of service. | 
 |     virtual int32_t SetToS(const int32_t DSCP, | 
 |                            const bool useSetSockOpt = false) = 0; | 
 |  | 
 |     // Get type of service configuration. | 
 |     virtual int32_t ToS(int32_t& DSCP, | 
 |                         bool& useSetSockOpt) const = 0; | 
 |  | 
 |     // Set Priority Code Point (IEEE 802.1Q) | 
 |     // Note: for Linux this function will set the priority for the socket, | 
 |     // which then can be mapped to a PCP value with vconfig. | 
 |     virtual int32_t SetPCP(const int32_t PCP) = 0; | 
 |  | 
 |     // Get Priority Code Point | 
 |     virtual int32_t PCP(int32_t& PCP) const = 0; | 
 |  | 
 |     // Enable IPv6. | 
 |     // Note: this API must be called before any call to | 
 |     // InitializeReceiveSockets() or InitializeSendSockets(). It is not | 
 |     // possible to go back to IPv4 (default) after this call. | 
 |     virtual int32_t EnableIpV6() = 0; | 
 |  | 
 |     // Return true if IPv6 has been enabled. | 
 |     virtual bool IpV6Enabled() const = 0; | 
 |  | 
 |     // Only allow packets received from filterIPAddress to be processed. | 
 |     // Note: must be called after EnableIPv6(), if IPv6 is used. | 
 |     virtual int32_t SetFilterIP( | 
 |         const char filterIPAddress[kIpAddressVersion6Length]) = 0; | 
 |  | 
 |     // Write the filter IP address (if any) to filterIPAddress. | 
 |     virtual int32_t FilterIP( | 
 |         char filterIPAddress[kIpAddressVersion6Length]) const = 0; | 
 |  | 
 |     // Only allow RTP packets from rtpFilterPort and RTCP packets from | 
 |     // rtcpFilterPort be processed. | 
 |     // Note: must be called after EnableIPv6(), if IPv6 is used. | 
 |     virtual int32_t SetFilterPorts(const uint16_t rtpFilterPort, | 
 |                                    const uint16_t rtcpFilterPort) = 0; | 
 |  | 
 |     // Set rtpFilterPort to the filter RTP port and rtcpFilterPort to the | 
 |     // filter RTCP port (if filtering based on port is enabled). | 
 |     virtual int32_t FilterPorts(uint16_t& rtpFilterPort, | 
 |                                 uint16_t& rtcpFilterPort) const = 0; | 
 |  | 
 |     // Set the number of buffers that the socket implementation may use for | 
 |     // receiving packets to numberOfSocketBuffers. I.e. the number of packets | 
 |     // that can be received in parallell. | 
 |     // Note: this API only has effect on Windows. | 
 |     virtual int32_t StartReceiving(const uint32_t numberOfSocketBuffers) = 0; | 
 |  | 
 |     // Stop receive incoming packets. | 
 |     virtual int32_t StopReceiving() = 0; | 
 |  | 
 |     // Return true incoming packets are received. | 
 |     virtual bool Receiving() const = 0; | 
 |  | 
 |     // Return true if send sockets have been initialized. | 
 |     virtual bool SendSocketsInitialized() const = 0; | 
 |  | 
 |     // Return true if local ports for sending has been set. | 
 |     virtual bool SourcePortsInitialized() const = 0; | 
 |  | 
 |     // Return true if receive sockets have been initialized. | 
 |     virtual bool ReceiveSocketsInitialized() const = 0; | 
 |  | 
 |     // Send data with size length to ip:portnr. The same port as the set | 
 |     // with InitializeSendSockets(..) is used if portnr is 0. The same IP | 
 |     // address as set with InitializeSendSockets(..) is used if ip is NULL. | 
 |     // If isRTCP is true the port used will be the RTCP port. | 
 |     virtual int32_t SendRaw(const int8_t* data, | 
 |                             size_t length, | 
 |                             int32_t isRTCP, | 
 |                             uint16_t portnr = 0, | 
 |                             const char* ip = NULL) = 0; | 
 |  | 
 |     // Send RTP data with size length to the address specified by to. | 
 |     virtual int32_t SendRTPPacketTo(const int8_t* data, | 
 |                                     size_t length, | 
 |                                     const SocketAddress& to) = 0; | 
 |  | 
 |  | 
 |     // Send RTCP data with size length to the address specified by to. | 
 |     virtual int32_t SendRTCPPacketTo(const int8_t* data, | 
 |                                      size_t length, | 
 |                                      const SocketAddress& to) = 0; | 
 |  | 
 |     // Send RTP data with size length to ip:rtpPort where ip is the ip set by | 
 |     // the InitializeSendSockets(..) call. | 
 |     virtual int32_t SendRTPPacketTo(const int8_t* data, | 
 |                                     size_t length, | 
 |                                     uint16_t rtpPort) = 0; | 
 |  | 
 |  | 
 |     // Send RTCP data with size length to ip:rtcpPort where ip is the ip set by | 
 |     // the InitializeSendSockets(..) call. | 
 |     virtual int32_t SendRTCPPacketTo(const int8_t* data, | 
 |                                      size_t length, | 
 |                                      uint16_t rtcpPort) = 0; | 
 |  | 
 |     // Set the IP address to which packets are sent to ipaddr. | 
 |     virtual int32_t SetSendIP( | 
 |         const char ipaddr[kIpAddressVersion6Length]) = 0; | 
 |  | 
 |     // Set the send RTP and RTCP port to rtpPort and rtcpPort respectively. | 
 |     virtual int32_t SetSendPorts(const uint16_t rtpPort, | 
 |                                  const uint16_t rtcpPort = 0) = 0; | 
 |  | 
 |     // Retreive the last registered error code. | 
 |     virtual ErrorCode LastError() const = 0; | 
 |  | 
 |     // Put the local IPv4 address in localIP. | 
 |     // Note: this API is for IPv4 only. | 
 |     static int32_t LocalHostAddress(uint32_t& localIP); | 
 |  | 
 |     // Put the local IP6 address in localIP. | 
 |     // Note: this API is for IPv6 only. | 
 |     static int32_t LocalHostAddressIPV6(char localIP[16]); | 
 |  | 
 |     // Return a copy of hostOrder (host order) in network order. | 
 |     static uint16_t Htons(uint16_t hostOrder); | 
 |  | 
 |     // Return a copy of hostOrder (host order) in network order. | 
 |     static uint32_t Htonl(uint32_t hostOrder); | 
 |  | 
 |     // Return IPv4 address in ip as 32 bit integer. | 
 |     static uint32_t InetAddrIPV4(const char* ip); | 
 |  | 
 |     // Convert the character string src into a network address structure in | 
 |     // the af address family and put it in dst. | 
 |     // Note: same functionality as inet_pton(..) | 
 |     static int32_t InetPresentationToNumeric(int32_t af, | 
 |                                              const char* src, | 
 |                                              void* dst); | 
 |  | 
 |     // Set ip and sourcePort according to address. As input parameter ipSize | 
 |     // is the length of ip. As output parameter it's the number of characters | 
 |     // written to ip (not counting the '\0' character). | 
 |     // Note: this API is only implemented on Windows and Linux. | 
 |     static int32_t IPAddress(const SocketAddress& address, | 
 |                              char* ip, | 
 |                              uint32_t& ipSize, | 
 |                              uint16_t& sourcePort); | 
 |  | 
 |     // Set ip and sourcePort according to address. As input parameter ipSize | 
 |     // is the length of ip. As output parameter it's the number of characters | 
 |     // written to ip (not counting the '\0' character). | 
 |     // Note: this API is only implemented on Windows and Linux. | 
 |     // Additional note: this API caches the address of the last call to it. If | 
 |     // address is likley to be the same for multiple calls it may be beneficial | 
 |     // to call this API instead of IPAddress(). | 
 |     virtual int32_t IPAddressCached(const SocketAddress& address, | 
 |                                     char* ip, | 
 |                                     uint32_t& ipSize, | 
 |                                     uint16_t& sourcePort) = 0; | 
 |  | 
 |     // Return true if ipaddr is a valid IP address. | 
 |     // If ipV6 is false ipaddr is interpreted as an IPv4 address otherwise it | 
 |     // is interptreted as IPv6. | 
 |     static bool IsIpAddressValid(const char* ipaddr, const bool ipV6); | 
 | }; | 
 |  | 
 | }  // namespace test | 
 | }  // namespace webrtc | 
 |  | 
 | #endif  // WEBRTC_VOICE_ENGINE_TEST_CHANNEL_TRANSPORT_UDP_TRANSPORT_H_ |