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::
44 SetToBroadCast() {
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::
57 InitNoAddress() {
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::
122 OpenForInputMCast(const Socket_Address &address) {
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__
Socket_Address
A simple place to store and manipulate tcp and port address for communication layer.
Definition: socket_address.h:25
Socket_Address::get_family
sa_family_t get_family() const
Returns AF_INET if this is an IPv4 address, or AF_INET6 if this is an IPv6 address.
Definition: socket_address.I:179
Socket_Address::set_any_IPv6
bool set_any_IPv6(unsigned short port)
Set to any IPv6 address and a specified port.
Definition: socket_address.I:147
Socket_Address::set_any_IP
bool set_any_IP(unsigned short port)
Set to any address and a specified port.
Definition: socket_address.I:136
Socket_Address::get_port
unsigned short get_port() const
Get the port portion as an integer.
Definition: socket_address.I:187
Socket_IP
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition: socket_ip.h:27
Socket_IP::GetSocket
SOCKET GetSocket()
Gets the base socket type.
Definition: socket_ip.h:237
Socket_IP::GetLastError
static int GetLastError()
Gets the last errcode from a socket operation.
Definition: socket_ip.h:140
Socket_IP::SetV6Only
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
Socket_IP::Close
void Close()
Closes a socket if it is open (allocated).
Definition: socket_ip.h:128
Socket_UDP_Incoming
Base functionality for a UDP Reader.
Definition: socket_udp_incoming.h:10
Socket_UDP_Incoming::OpenForInputMCast
bool OpenForInputMCast(const Socket_Address &address)
Starts a UDP socket listening on a port.
Definition: socket_udp_incoming.h:122
Socket_UDP_Incoming::InitNoAddress
bool InitNoAddress()
Set this socket to work without a bound external address.
Definition: socket_udp_incoming.h:57
Socket_UDP_Incoming::SetToBroadCast
bool SetToBroadCast()
Flips the OS bits that allow for brodcast packets to come in on this port.
Definition: socket_udp_incoming.h:44
Socket_UDP_Incoming::OpenForInput
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
Definition: socket_udp_incoming.h:75
Socket_UDP_Incoming::SendTo
bool SendTo(const char *data, int len, const Socket_Address &address)
Send data to specified address.
Definition: socket_udp_incoming.h:185
Socket_UDP_Incoming::GetPacket
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.
Definition: socket_udp_incoming.h:166
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
pandabase.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
register_type
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