Panda3D
Loading...
Searching...
No Matches
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 */
10class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP {
11PUBLISHED:
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
22public:
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
36private:
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 */
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 */
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 */
75OpenForInput(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 */
104OpenForInput(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 */
122OpenForInputMCast(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 */
166GetPacket(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 */
185SendTo(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__
A simple place to store and manipulate tcp and port address for communication layer.
sa_family_t get_family() const
Returns AF_INET if this is an IPv4 address, or AF_INET6 if this is an IPv6 address.
bool set_any_IPv6(unsigned short port)
Set to any IPv6 address and a specified port.
bool set_any_IP(unsigned short port)
Set to any address and a specified port.
unsigned short get_port() const
Get the port portion as an integer.
Base functionality for a INET domain Socket This call should be the starting point for all other unix...
Definition socket_ip.h:27
SOCKET GetSocket()
Gets the base socket type.
Definition socket_ip.h:237
static int GetLastError()
Gets the last errcode from a socket operation.
Definition socket_ip.h:140
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
void Close()
Closes a socket if it is open (allocated).
Definition socket_ip.h:128
Base functionality for a UDP Reader.
bool OpenForInputMCast(const Socket_Address &address)
Starts a UDP socket listening on a port.
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.
bool OpenForInput(unsigned short port)
Starts a UDP socket listening on a port.
bool SendTo(const char *data, int len, const Socket_Address &address)
Send data to specified address.
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.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_type(TypeHandle &type_handle, const std::string &name)
This inline function is just a convenient way to call TypeRegistry::register_type(),...