Panda3D
socket_udp_incoming.h
1 #ifndef __SOCKET_UDP_INCOMING_H__
2 #define __SOCKET_UDP_INCOMING_H__
3 
4 #include "pandabase.h"
5 #include "socket_ip.h"
6 
7 /**
8  * Base functionality for a UDP Reader
9  */
10 class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP {
11 PUBLISHED:
12  inline Socket_UDP_Incoming() {}
13 
14  inline bool OpenForInput(unsigned short port);
15  inline bool OpenForInput(const Socket_Address &address);
16  inline bool OpenForInputMCast(const Socket_Address &address);
17  inline bool GetPacket(char *data, int *max_len, Socket_Address &address);
18  inline bool SendTo(const char *data, int len, const Socket_Address &address);
19  inline bool InitNoAddress();
20  inline bool SetToBroadCast();
21 
22 public:
23  static TypeHandle get_class_type() {
24  return _type_handle;
25  }
26  static void init_type() {
27  Socket_IP::init_type();
28  register_type(_type_handle, "Socket_UDP_Incoming",
29  Socket_IP::get_class_type());
30  }
31  virtual TypeHandle get_type() const {
32  return get_class_type();
33  }
34  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
35 
36 private:
37  static TypeHandle _type_handle;
38 };
39 
40 /**
41  * Flips the OS bits that allow for brodcast packets to come in on this port.
42  */
43 inline bool Socket_UDP_Incoming::
45  int optval = 1;
46 
47  if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) {
48  return false;
49  }
50  return true;
51 }
52 
53 /**
54  * Set this socket to work without a bound external address.
55  */
56 inline bool Socket_UDP_Incoming::
58  Close();
59 
60  if (support_ipv6) {
61  // Create a socket supporting both IPv4 and IPv6.
62  _socket = DO_NEWUDP(AF_INET6);
63  SetV6Only(false);
64  } else {
65  _socket = DO_NEWUDP(AF_INET);
66  }
67 
68  return (_socket != BAD_SOCKET);
69 }
70 
71 /**
72  * Starts a UDP socket listening on a port
73  */
74 inline bool Socket_UDP_Incoming::
75 OpenForInput(unsigned short port) {
76  Close();
77 
78  Socket_Address address;
79  if (support_ipv6) {
80  // Create a socket supporting both IPv4 and IPv6.
81  address.set_any_IPv6(port);
82  _socket = DO_NEWUDP(AF_INET6);
83  SetV6Only(false);
84  } else {
85  address.set_any_IP(port);
86  _socket = DO_NEWUDP(AF_INET);
87  }
88 
89  if (_socket == BAD_SOCKET) {
90  return ErrorClose();
91  }
92 
93  if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
94  return ErrorClose();
95  }
96 
97  return true;
98 }
99 
100 /**
101  * Starts a UDP socket listening on a port
102  */
103 inline bool Socket_UDP_Incoming::
104 OpenForInput(const Socket_Address &address) {
105  Close();
106  _socket = DO_NEWUDP(address.get_family());
107  if (_socket == BAD_SOCKET) {
108  return ErrorClose();
109  }
110 
111  if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
112  return ErrorClose();
113  }
114 
115  return true;
116 }
117 
118 /**
119  * Starts a UDP socket listening on a port
120  */
121 inline bool Socket_UDP_Incoming::
123  Close();
124  _socket = DO_NEWUDP(address.get_family());
125  if (_socket == BAD_SOCKET) {
126  return ErrorClose();
127  }
128 
129  Socket_Address wa1(address.get_port());
130  if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0) {
131  return ErrorClose();
132  }
133 
134  int status = -1;
135 
136  const sockaddr *addr = &address.GetAddressInfo();
137  if (addr->sa_family == AF_INET) {
138  struct ip_mreq imreq;
139  memset(&imreq, 0, sizeof(imreq));
140  imreq.imr_multiaddr.s_addr = ((sockaddr_in*)addr)->sin_addr.s_addr;
141  imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface
142 
143  status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
144  (const char *)&imreq, sizeof(imreq));
145 
146  } else if (addr->sa_family == AF_INET6) {
147  struct ipv6_mreq imreq;
148  memcpy(&imreq.ipv6mr_multiaddr,
149  &(((struct sockaddr_in6 *)addr)->sin6_addr),
150  sizeof(struct in6_addr));
151  imreq.ipv6mr_interface = 0; // use DEFAULT interface
152 
153  status = setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_JOIN_GROUP,
154  (const char *)&imreq, sizeof(imreq));
155  }
156 
157  return (status == 0);
158 }
159 
160 /**
161  * Grabs a dataset off the listening UDP socket and fills in the source
162  * address information
163  *
164  */
165 inline bool Socket_UDP_Incoming::
166 GetPacket(char *data, int *max_len, Socket_Address &address) {
167  int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo());
168  *max_len = 0;
169 
170  if (val <= 0) {
171  if (GetLastError() != LOCAL_BLOCKING_ERROR) { // im treating a blocking error as a 0 lenght read
172  return false;
173  }
174  } else {
175  *max_len = val;
176  }
177 
178  return true;
179 }
180 
181 /**
182  * Send data to specified address
183  */
184 inline bool Socket_UDP_Incoming::
185 SendTo(const char *data, int len, const Socket_Address &address) {
186  return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
187 }
188 
189 #endif //__SOCKET_UDP_INCOMING_H__
bool OpenForInputMCast(const Socket_Address &address)
Starts a UDP socket listening on a port.
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition: socket_ip.h:27
bool set_any_IP(unsigned short port)
Set to any address and a specified port.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...
Definition: register_type.I:22
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool SetV6Only(bool flag)
Sets a flag indicating whether this IPv6 socket should operate in dual-stack mode or not.
Definition: socket_ip.h:225
bool GetPacket(char *data, int *max_len, Socket_Address &address)
Grabs a dataset off the listening UDP socket and fills in the source address information.
bool SendTo(const char *data, int len, const Socket_Address &address)
Send data to specified address.
unsigned short get_port() const
Get the port portion as an integer.
Base functionality for a UDP Reader.
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
bool set_any_IPv6(unsigned short port)
Set to any IPv6 address and a specified port.
sa_family_t get_family() const
Returns AF_INET if this is an IPv4 address, or AF_INET6 if this is an IPv6 address.
A simple place to store and manipulate tcp and port address for communication layer.
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
SOCKET GetSocket()
Gets the base socket type.
Definition: socket_ip.h:237
bool InitNoAddress()
Set this socket to work without a bound external address.
bool SetToBroadCast()
Flips the OS bits that allow for brodcast packets to come in on this port.