IPv6 support, improve URL handling/comparison
This commit is contained in:
parent
f068a8613b
commit
7e08b87ff7
|
|
@ -0,0 +1,17 @@
|
|||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
typedef uint32_t in_addr_t;
|
||||
struct in_addr;
|
||||
typedef uint16_t in_port_t;
|
||||
struct in6_addr;
|
||||
struct sockaddr_in;
|
||||
struct sockaddr_in6;
|
||||
struct ip_mreq;
|
||||
struct ip_mreq_source;
|
||||
struct ipv6_mreq;
|
||||
struct group_req;
|
||||
struct group_source_req;
|
||||
struct ip_msfilter;
|
||||
struct group_filter;
|
||||
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
typedef int SOCKET ;
|
||||
|
||||
struct sockaddr_in
|
||||
{
|
||||
};
|
||||
|
||||
typedef struct fd_set {
|
||||
unsigned int fd_count; /* how many are SET? */
|
||||
SOCKET fd_array[10]; /* an array of SOCKETs */
|
||||
} fd_set;
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
typedef int socklen_t;
|
||||
typedef unsigned short int sa_family_t;
|
||||
|
||||
struct sockaddr {
|
||||
sa_family_t sa_family;
|
||||
char sa_data[];
|
||||
};
|
||||
|
||||
struct sockaddr_storage {
|
||||
sa_family_t ss_family;
|
||||
};
|
||||
|
||||
typedef struct fd_set {
|
||||
unsigned int fd_count; /* how many are SET? */
|
||||
int fd_array[10]; /* an array of SOCKETs */
|
||||
} fd_set;
|
||||
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
typedef unsigned long SOCKET;
|
||||
|
||||
struct sockaddr;
|
||||
struct sockaddr_in;
|
||||
struct sockaddr_in6;
|
||||
struct sockaddr_storage;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
typedef DWORD socklen_t;
|
||||
|
|
@ -18,6 +18,14 @@ INLINE BioPtr::
|
|||
BioPtr(BIO *bio) : _bio(bio) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool BioPtr::
|
||||
should_retry() const {
|
||||
return (_bio != NULL) && BIO_should_retry(_bio);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -18,13 +18,46 @@
|
|||
#include "urlSpec.h"
|
||||
#include "config_downloader.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static string format_error() {
|
||||
PVOID buffer;
|
||||
DWORD len;
|
||||
len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, WSAGetLastError(), 0, (LPTSTR)&buffer, 0, NULL);
|
||||
if (len == 0) {
|
||||
return string("Unknown error message");
|
||||
}
|
||||
|
||||
const char *text = (const char *)buffer;
|
||||
while (len > 0 && isspace(text[len - 1])) {
|
||||
--len;
|
||||
}
|
||||
|
||||
string result(text, len);
|
||||
LocalFree(buffer);
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
#define format_error() strerror(errno)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This flavor of the constructor automatically creates a socket BIO and feeds
|
||||
* it the server and port name from the indicated URL. It doesn't call
|
||||
* BIO_do_connect(), though.
|
||||
*/
|
||||
BioPtr::
|
||||
BioPtr(const URLSpec &url) {
|
||||
BioPtr(const URLSpec &url) : _connecting(false) {
|
||||
if (url.get_scheme() == "file") {
|
||||
// We're just reading a disk file.
|
||||
string filename = URLSpec::unquote(url.get_path());
|
||||
|
|
@ -48,14 +81,143 @@ BioPtr(const URLSpec &url) {
|
|||
_bio = BIO_new_file(filename.c_str(), "rb");
|
||||
|
||||
} else {
|
||||
// A normal network-based URL.
|
||||
// A normal network-based URL. We don't use BIO_new_connect since it
|
||||
// doesn't handle IPv6 properly.
|
||||
_server_name = url.get_server();
|
||||
_port = url.get_port();
|
||||
_bio = BIO_new_connect((char *)_server_name.c_str());
|
||||
BIO_set_conn_int_port(_bio, &_port);
|
||||
_bio = NULL;
|
||||
|
||||
// These hints tell getaddrinfo what kind of address to return.
|
||||
struct addrinfo hints, *res = NULL;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
|
||||
hints.ai_family = support_ipv6 ? AF_UNSPEC : AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
// Resolve the hostname or address string.
|
||||
int result = getaddrinfo(_server_name.c_str(), NULL, &hints, &res);
|
||||
if (result != 0) {
|
||||
const char *errmsg;
|
||||
#ifndef _WIN32
|
||||
if (result == EAI_SYSTEM && errno != 0) {
|
||||
errmsg = strerror(errno);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
errmsg = gai_strerror(result);
|
||||
}
|
||||
downloader_cat.error()
|
||||
<< "Failed to resolve " << url.get_server() << ": " << errmsg << "\n";
|
||||
return;
|
||||
}
|
||||
nassertv(res != NULL && res->ai_addr != NULL);
|
||||
|
||||
// Store the real resolved address.
|
||||
char buf[48];
|
||||
buf[0] = 0;
|
||||
#ifdef _WIN32
|
||||
DWORD bufsize = sizeof(buf);
|
||||
WSAAddressToStringA(res->ai_addr, res->ai_addrlen, NULL, buf, &bufsize);
|
||||
#else
|
||||
if (res->ai_addr->sa_family == AF_INET) {
|
||||
inet_ntop(AF_INET, (char *)&((sockaddr_in *)res->ai_addr)->sin_addr, buf, sizeof(buf));
|
||||
|
||||
} else if (res->ai_addr->sa_family == AF_INET6) {
|
||||
inet_ntop(AF_INET6, (char *)&((sockaddr_in6 *)res->ai_addr)->sin6_addr, buf, sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (buf[0]) {
|
||||
_server_name = buf;
|
||||
}
|
||||
if (downloader_cat.is_debug()) {
|
||||
downloader_cat.debug()
|
||||
<< "Resolved " << url.get_server() << " to " << buf << "\n";
|
||||
}
|
||||
|
||||
// Create the socket.
|
||||
int fd = socket(res->ai_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (fd < 0) {
|
||||
downloader_cat.error()
|
||||
<< "Failed to create socket: " << format_error() << "\n";
|
||||
_bio = NULL;
|
||||
freeaddrinfo(res);
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the address and length for later use in connect().
|
||||
nassertv(res->ai_addrlen <= sizeof(_addr));
|
||||
memcpy(&_addr, res->ai_addr, res->ai_addrlen);
|
||||
_addrlen = res->ai_addrlen;
|
||||
freeaddrinfo(res);
|
||||
|
||||
// Also set the port we'd like to connect to.
|
||||
if (_addr.ss_family == AF_INET) {
|
||||
((sockaddr_in &)_addr).sin_port = htons(_port);
|
||||
} else if (_addr.ss_family == AF_INET6) {
|
||||
((sockaddr_in6 &)_addr).sin6_port = htons(_port);
|
||||
}
|
||||
|
||||
_bio = BIO_new_socket(fd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the non-blocking flag on the socket.
|
||||
*/
|
||||
void BioPtr::
|
||||
set_nbio(bool nbio) {
|
||||
if (_bio == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = -1;
|
||||
BIO_get_fd(_bio, &fd);
|
||||
nassertv_always(fd >= 0);
|
||||
|
||||
BIO_socket_nbio(fd, nbio);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the socket. Returns true on success.
|
||||
*/
|
||||
bool BioPtr::
|
||||
connect() {
|
||||
if (_bio == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int fd = -1;
|
||||
BIO_get_fd(_bio, &fd);
|
||||
nassertr(fd >= 0, false);
|
||||
|
||||
int result;
|
||||
if (_connecting) {
|
||||
result = BIO_sock_error(fd);
|
||||
} else {
|
||||
result = ::connect(fd, (sockaddr *)&_addr, _addrlen);
|
||||
|
||||
if (result != 0 && BIO_sock_should_retry(-1)) {
|
||||
// It's still in progress; we should retry later. This causes
|
||||
// should_reply() to return true.
|
||||
BIO_set_flags(_bio, BIO_FLAGS_SHOULD_RETRY);
|
||||
_connecting = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
BIO_clear_retry_flags(_bio);
|
||||
_connecting = false;
|
||||
|
||||
if (result != 0) {
|
||||
downloader_cat.warning()
|
||||
<< "Failed to connect to " << _server_name << " port " << _port
|
||||
<< ": " << format_error() << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -64,7 +226,7 @@ BioPtr::
|
|||
if (_bio != (BIO *)NULL) {
|
||||
if (downloader_cat.is_debug() && !_server_name.empty()) {
|
||||
downloader_cat.debug()
|
||||
<< "Dropping connection to " << _server_name << ":" << _port << "\n";
|
||||
<< "Dropping connection to " << _server_name << " port " << _port << "\n";
|
||||
}
|
||||
|
||||
BIO_free_all(_bio);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@
|
|||
#include "openSSLWrapper.h" // must be included before any other openssl.
|
||||
#include "openssl/ssl.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
class URLSpec;
|
||||
|
||||
/**
|
||||
|
|
@ -41,6 +49,11 @@ public:
|
|||
BioPtr(const URLSpec &url);
|
||||
virtual ~BioPtr();
|
||||
|
||||
void set_nbio(bool nbio);
|
||||
bool connect();
|
||||
|
||||
INLINE bool should_retry() const;
|
||||
|
||||
INLINE BIO &operator *() const;
|
||||
INLINE BIO *operator -> () const;
|
||||
INLINE operator BIO * () const;
|
||||
|
|
@ -55,6 +68,9 @@ private:
|
|||
BIO *_bio;
|
||||
string _server_name;
|
||||
int _port;
|
||||
struct sockaddr_storage _addr;
|
||||
socklen_t _addrlen;
|
||||
bool _connecting;
|
||||
};
|
||||
|
||||
#include "bioPtr.I"
|
||||
|
|
|
|||
|
|
@ -111,6 +111,12 @@ ConfigVariableInt tcp_header_size
|
|||
"length when writing a datagram on a TCP stream. This may be "
|
||||
"0, 2, or 4. The server and client must agree on this value."));
|
||||
|
||||
ConfigVariableBool support_ipv6
|
||||
("support-ipv6", true,
|
||||
PRC_DESC("Specifies whether IPv6 support should be enabled. This should "
|
||||
"be true unless you are experiencing issues with Panda's IPv6 "
|
||||
"support or are using a misconfigured system."));
|
||||
|
||||
ConfigureFn(config_downloader) {
|
||||
init_libdownloader();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ extern ConfigVariableDouble http_idle_timeout;
|
|||
extern ConfigVariableInt http_max_connect_count;
|
||||
|
||||
extern EXPCL_PANDAEXPRESS ConfigVariableInt tcp_header_size;
|
||||
extern EXPCL_PANDAEXPRESS ConfigVariableBool support_ipv6;
|
||||
|
||||
extern EXPCL_PANDAEXPRESS void init_libdownloader();
|
||||
|
||||
|
|
|
|||
|
|
@ -375,26 +375,28 @@ run() {
|
|||
}
|
||||
|
||||
// No connection. Attempt to establish one.
|
||||
URLSpec url;
|
||||
if (_proxy.empty()) {
|
||||
_bio = new BioPtr(_request.get_url());
|
||||
url = _request.get_url();
|
||||
} else {
|
||||
_bio = new BioPtr(_proxy);
|
||||
url = _proxy;
|
||||
}
|
||||
_bio = new BioPtr(url);
|
||||
_source = new BioStreamPtr(new BioStream(_bio));
|
||||
if (_nonblocking) {
|
||||
BIO_set_nbio(*_bio, 1);
|
||||
_bio->set_nbio(true);
|
||||
}
|
||||
|
||||
if (downloader_cat.is_debug()) {
|
||||
if (_connect_count > 0) {
|
||||
downloader_cat.debug()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
<< "Reconnecting to " << _bio->get_server_name() << ":"
|
||||
<< "Reconnecting to " << _bio->get_server_name() << " port "
|
||||
<< _bio->get_port() << "\n";
|
||||
} else {
|
||||
downloader_cat.debug()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
<< "Connecting to " << _bio->get_server_name() << ":"
|
||||
<< "Connecting to " << _bio->get_server_name() << " port "
|
||||
<< _bio->get_port() << "\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -941,14 +943,14 @@ bool HTTPChannel::
|
|||
run_connecting() {
|
||||
_status_entry = StatusEntry();
|
||||
|
||||
if (BIO_do_connect(*_bio) <= 0) {
|
||||
if (BIO_should_retry(*_bio)) {
|
||||
if (!_bio->connect()) {
|
||||
if (_bio->should_retry()) {
|
||||
_state = S_connecting_wait;
|
||||
return false;
|
||||
}
|
||||
downloader_cat.info()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
<< "Could not connect to " << _bio->get_server_name() << ":"
|
||||
<< "Could not connect to " << _bio->get_server_name() << " port "
|
||||
<< _bio->get_port() << "\n";
|
||||
OpenSSLWrapper::get_global_ptr()->notify_ssl_errors();
|
||||
_status_entry._status_code = SC_no_connection;
|
||||
|
|
@ -959,7 +961,7 @@ run_connecting() {
|
|||
if (downloader_cat.is_debug()) {
|
||||
downloader_cat.debug()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
<< "Connected to " << _bio->get_server_name() << ":"
|
||||
<< "Connected to " << _bio->get_server_name() << " port "
|
||||
<< _bio->get_port() << "\n";
|
||||
}
|
||||
|
||||
|
|
@ -1362,6 +1364,10 @@ run_socks_proxy_connect_reply() {
|
|||
total_bytes += (unsigned int)reply[4];
|
||||
break;
|
||||
|
||||
case 0x04: // IPv6
|
||||
total_bytes += 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
downloader_cat.info()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
|
|
@ -1396,6 +1402,18 @@ run_socks_proxy_connect_reply() {
|
|||
case 0x03: // DNS
|
||||
connect_host = string(&reply[5], (unsigned int)reply[4]);
|
||||
break;
|
||||
|
||||
case 0x04: // IPv6
|
||||
{
|
||||
char buf[48];
|
||||
sprintf(buf, "[%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx"
|
||||
":%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx]",
|
||||
reply[4], reply[5], reply[6], reply[7], reply[8], reply[9],
|
||||
reply[10], reply[11], reply[12], reply[13], reply[14],
|
||||
reply[15], reply[16], reply[17], reply[18], reply[19]);
|
||||
total_bytes += 16;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int connect_port =
|
||||
|
|
@ -2742,8 +2760,8 @@ server_getline(string &str) {
|
|||
}
|
||||
str = str.substr(0, p);
|
||||
}
|
||||
if (downloader_cat.is_debug()) {
|
||||
downloader_cat.debug()
|
||||
if (downloader_cat.is_spam()) {
|
||||
downloader_cat.spam()
|
||||
<< _NOTIFY_HTTP_CHANNEL_ID
|
||||
<< "recv: " << str << "\n";
|
||||
}
|
||||
|
|
@ -2915,7 +2933,7 @@ server_send(const string &str, bool secret) {
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!secret && downloader_cat.is_debug()) {
|
||||
if (!secret && downloader_cat.is_spam()) {
|
||||
show_send(str.substr(0, write_count));
|
||||
}
|
||||
#endif
|
||||
|
|
@ -3486,14 +3504,19 @@ make_header() {
|
|||
|
||||
if (_client->get_http_version() >= HTTPEnum::HV_11) {
|
||||
|
||||
stream
|
||||
<< "Host: " << _request.get_url().get_server();
|
||||
if (!_request.get_url().is_default_port()) {
|
||||
if (_request.get_url().has_port() && _request.get_url().is_default_port()) {
|
||||
// It appears that some servers (notably gstatic.com) might return a 404
|
||||
// if you include an explicit port number in with the Host: header, even
|
||||
// if it is the default port. So, don't include the port number unless
|
||||
// we need to.
|
||||
stream << ":" << _request.get_url().get_port();
|
||||
string server = _request.get_url().get_server();
|
||||
if (server.find(':') != string::npos) {
|
||||
stream << "Host: [" << server << "]";
|
||||
} else {
|
||||
stream << "Host: " << server;
|
||||
}
|
||||
} else {
|
||||
stream << "Host: " << _request.get_url().get_server_and_port();
|
||||
}
|
||||
stream << "\r\n";
|
||||
if (!get_persistent_connection()) {
|
||||
|
|
@ -3703,14 +3726,14 @@ show_send(const string &message) {
|
|||
size_t newline = message.find('\n', start);
|
||||
while (newline != string::npos) {
|
||||
// Assume every \n is preceded by a \r.
|
||||
downloader_cat.debug()
|
||||
downloader_cat.spam()
|
||||
<< "send: " << message.substr(start, newline - start - 1) << "\n";
|
||||
start = newline + 1;
|
||||
newline = message.find('\n', start);
|
||||
}
|
||||
|
||||
if (start < message.length()) {
|
||||
downloader_cat.debug()
|
||||
downloader_cat.spam()
|
||||
<< "send: " << message.substr(start) << " (no newline)\n";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,14 +19,6 @@ URLSpec(const string &url, bool server_name_expected) {
|
|||
set_url(url, server_name_expected);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE URLSpec::
|
||||
URLSpec(const URLSpec ©) {
|
||||
(*this) = copy;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -40,7 +32,7 @@ operator = (const string &url) {
|
|||
*/
|
||||
INLINE bool URLSpec::
|
||||
operator == (const URLSpec &other) const {
|
||||
return _url == other._url;
|
||||
return compare_to(other) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -48,7 +40,7 @@ operator == (const URLSpec &other) const {
|
|||
*/
|
||||
INLINE bool URLSpec::
|
||||
operator != (const URLSpec &other) const {
|
||||
return !operator == (other);
|
||||
return compare_to(other) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,16 +48,7 @@ operator != (const URLSpec &other) const {
|
|||
*/
|
||||
INLINE bool URLSpec::
|
||||
operator < (const URLSpec &other) const {
|
||||
return _url < other._url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a number less than zero if this URLSpec sorts before the other one,
|
||||
* greater than zero if it sorts after, or zero if they are equivalent.
|
||||
*/
|
||||
INLINE int URLSpec::
|
||||
compare_to(const URLSpec &other) const {
|
||||
return strcmp(_url.c_str(), other._url.c_str());
|
||||
return compare_to(other) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -148,7 +131,8 @@ get_username() const {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the server name specified by the URL, if any.
|
||||
* Returns the server name specified by the URL, if any. In case of an IPv6
|
||||
* address, does not include the enclosing brackets.
|
||||
*/
|
||||
INLINE string URLSpec::
|
||||
get_server() const {
|
||||
|
|
@ -218,13 +202,23 @@ c_str() const {
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns false if the URLSpec is valid (not empty), or true if it is an
|
||||
* empty string.
|
||||
*/
|
||||
INLINE bool URLSpec::
|
||||
empty() const {
|
||||
return _url.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the URLSpec is valid (not empty), or false if it is an
|
||||
* empty string.
|
||||
*/
|
||||
INLINE URLSpec::
|
||||
operator bool() const {
|
||||
return !_url.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -233,12 +227,20 @@ length() const {
|
|||
return _url.length();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE size_t URLSpec::
|
||||
size() const {
|
||||
return _url.size();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE char URLSpec::
|
||||
operator [] (int n) const {
|
||||
nassertr(n >= 0 && n < (int)_url.length(), '\0');
|
||||
operator [] (size_t n) const {
|
||||
nassertr(n < _url.length(), '\0');
|
||||
return _url[n];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
*/
|
||||
|
||||
#include "urlSpec.h"
|
||||
#include "filename.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -35,24 +36,88 @@ URLSpec() {
|
|||
_query_start = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a URLSpec by appending a path to the end of the old URLSpec,
|
||||
* inserting an intervening forward slash if necessary.
|
||||
*/
|
||||
URLSpec::
|
||||
URLSpec(const URLSpec &url, const Filename &path) {
|
||||
(*this) = url;
|
||||
if (!path.empty()) {
|
||||
string dirname = get_path();
|
||||
|
||||
// Check if the path already ends in a slash.
|
||||
if (!dirname.empty() && dirname.back() == '/') {
|
||||
if (path[0] == '/') {
|
||||
// And the filename begins with one. Remove the extra slash.
|
||||
dirname.resize(dirname.size() - 1);
|
||||
}
|
||||
} else {
|
||||
if (path[0] != '/') {
|
||||
// Neither has a slash, so insert one.
|
||||
dirname += '/';
|
||||
}
|
||||
}
|
||||
set_path(dirname + path.get_fullpath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a number less than zero if this URLSpec sorts before the other one,
|
||||
* greater than zero if it sorts after, or zero if they are equivalent.
|
||||
*/
|
||||
int URLSpec::
|
||||
compare_to(const URLSpec &other) const {
|
||||
int cmp;
|
||||
if (has_scheme() != other.has_scheme()) {
|
||||
return (has_scheme() < other.has_scheme()) ? -1 : 1;
|
||||
}
|
||||
if (has_scheme()) {
|
||||
cmp = cmp_nocase(get_scheme(), other.get_scheme());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
if (has_username() != other.has_username()) {
|
||||
return (has_username() < other.has_username()) ? -1 : 1;
|
||||
}
|
||||
if (has_username()) {
|
||||
cmp = get_username().compare(other.get_username());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
if (has_server() != other.has_server()) {
|
||||
return (has_server() < other.has_server()) ? -1 : 1;
|
||||
}
|
||||
if (has_server()) {
|
||||
cmp = cmp_nocase(get_server(), other.get_server());
|
||||
if (cmp != 0) {
|
||||
return cmp;
|
||||
}
|
||||
}
|
||||
return get_path_and_query().compare(other.get_path_and_query());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void URLSpec::
|
||||
operator = (const URLSpec ©) {
|
||||
_url = copy._url;
|
||||
_port = copy._port;
|
||||
_flags = copy._flags;
|
||||
_scheme_end = copy._scheme_end;
|
||||
_username_start = copy._username_start;
|
||||
_username_end = copy._username_end;
|
||||
_server_start = copy._server_start;
|
||||
_server_end = copy._server_end;
|
||||
_port_start = copy._port_start;
|
||||
_port_end = copy._port_end;
|
||||
_path_start = copy._path_start;
|
||||
_path_end = copy._path_end;
|
||||
_query_start = copy._query_start;
|
||||
size_t URLSpec::
|
||||
get_hash() const {
|
||||
size_t hash = 0;
|
||||
hash = int_hash::add_hash(hash, _flags & (F_has_scheme | F_has_username | F_has_server));
|
||||
if (has_scheme()) {
|
||||
hash = string_hash::add_hash(hash, downcase(get_scheme()));
|
||||
}
|
||||
if (has_username()) {
|
||||
hash = string_hash::add_hash(hash, get_username());
|
||||
}
|
||||
if (has_server()) {
|
||||
hash = string_hash::add_hash(hash, downcase(get_server()));
|
||||
}
|
||||
hash = int_hash::add_hash(hash, get_port());
|
||||
hash = string_hash::add_hash(hash, get_path_and_query());
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,7 +136,7 @@ get_scheme() const {
|
|||
* Returns the port number specified by the URL, or the default port if not
|
||||
* specified.
|
||||
*/
|
||||
int URLSpec::
|
||||
uint16_t URLSpec::
|
||||
get_port() const {
|
||||
if (has_port()) {
|
||||
return _port;
|
||||
|
|
@ -115,14 +180,25 @@ get_default_port_for_scheme(const string &scheme) {
|
|||
* Returns a string consisting of the server name, followed by a colon,
|
||||
* followed by the port number. If the port number is not explicitly given in
|
||||
* the URL, this string will include the implicit port number.
|
||||
* If the server is an IPv6 address, it will be enclosed in square brackets.
|
||||
*/
|
||||
string URLSpec::
|
||||
get_server_and_port() const {
|
||||
if (has_port()) {
|
||||
return _url.substr(_server_start, _port_end - _server_start);
|
||||
}
|
||||
ostringstream strm;
|
||||
strm << get_server() << ":" << get_port();
|
||||
string server = get_server();
|
||||
if (server.find(':') != string::npos) {
|
||||
// Protect an IPv6 address by enclosing it in square brackets.
|
||||
strm << '[' << server << ']';
|
||||
|
||||
} else {
|
||||
if (!has_port()) {
|
||||
return server;
|
||||
}
|
||||
strm << server;
|
||||
}
|
||||
if (has_port()) {
|
||||
strm << ":" << get_port();
|
||||
}
|
||||
return strm.str();
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +361,15 @@ set_username(const string &username) {
|
|||
if (!username.empty()) {
|
||||
authority = username + "@";
|
||||
}
|
||||
authority += get_server();
|
||||
|
||||
string server = get_server();
|
||||
if (server.find(':') != string::npos) {
|
||||
// Protect an IPv6 address by enclosing it in square brackets.
|
||||
authority += "[" + server + "]";
|
||||
} else {
|
||||
authority += server;
|
||||
}
|
||||
|
||||
if (has_port()) {
|
||||
authority += ":";
|
||||
authority += get_port_str();
|
||||
|
|
@ -296,6 +380,8 @@ set_username(const string &username) {
|
|||
|
||||
/**
|
||||
* Replaces the server part of the URL specification.
|
||||
* Unlike set_server_and_port, this method does not require IPv6 addresses to
|
||||
* be enclosed in square brackets.
|
||||
*/
|
||||
void URLSpec::
|
||||
set_server(const string &server) {
|
||||
|
|
@ -307,7 +393,14 @@ set_server(const string &server) {
|
|||
if (has_username()) {
|
||||
authority = get_username() + "@";
|
||||
}
|
||||
authority += server;
|
||||
|
||||
if (server.find(':') != string::npos) {
|
||||
// Protect an IPv6 address by enclosing it in square brackets.
|
||||
authority += "[" + server + "]";
|
||||
} else {
|
||||
authority += server;
|
||||
}
|
||||
|
||||
if (has_port()) {
|
||||
authority += ":";
|
||||
authority += get_port_str();
|
||||
|
|
@ -329,7 +422,14 @@ set_port(const string &port) {
|
|||
if (has_username()) {
|
||||
authority = get_username() + "@";
|
||||
}
|
||||
authority += get_server();
|
||||
|
||||
string server = get_server();
|
||||
if (server.find(':') != string::npos) {
|
||||
// Protect an IPv6 address by enclosing it in square brackets.
|
||||
authority += "[" + server + "]";
|
||||
} else {
|
||||
authority += server;
|
||||
}
|
||||
|
||||
if (!port.empty()) {
|
||||
authority += ":";
|
||||
|
|
@ -344,16 +444,15 @@ set_port(const string &port) {
|
|||
* number.
|
||||
*/
|
||||
void URLSpec::
|
||||
set_port(int port) {
|
||||
ostringstream str;
|
||||
str << port;
|
||||
set_port(str.str());
|
||||
set_port(uint16_t port) {
|
||||
set_port(format_string(port));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the server and port parts of the URL specification simultaneously.
|
||||
* The input string should be of the form "server:port", or just "server" to
|
||||
* make the port number implicit.
|
||||
* Any IPv6 address must be enclosed in square brackets.
|
||||
*/
|
||||
void URLSpec::
|
||||
set_server_and_port(const string &server_and_port) {
|
||||
|
|
@ -476,6 +575,18 @@ set_url(const string &url, bool server_name_expected) {
|
|||
}
|
||||
}
|
||||
|
||||
// Now normalize the percent-encoding sequences by making them uppercase.
|
||||
for (p = 0; p + 2 < _url.length();) {
|
||||
if (_url[p++] == '%') {
|
||||
if (_url[p] != '%') {
|
||||
_url[p] = toupper(_url[p]);
|
||||
++p;
|
||||
_url[p] = toupper(_url[p]);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
}
|
||||
|
||||
// What have we got?
|
||||
_flags = 0;
|
||||
_port = 0;
|
||||
|
|
@ -781,18 +892,39 @@ parse_authority() {
|
|||
_server_start = at_sign + 1;
|
||||
}
|
||||
|
||||
// Is there a port?
|
||||
size_t colon = _url.find(':', _server_start);
|
||||
if (colon < _port_end) {
|
||||
// Yep.
|
||||
// Is this an IPv6 address in square brackets?
|
||||
size_t bracket = _url.find('[', _server_start);
|
||||
if (bracket < _port_end) {
|
||||
// We won't include the brackets in the server name.
|
||||
++_server_start;
|
||||
|
||||
bracket = _url.find(']');
|
||||
if (bracket < _server_end) {
|
||||
_server_end = bracket;
|
||||
|
||||
// Is it followed directly by a port colon?
|
||||
size_t colon = _url.find(':', _server_end);
|
||||
if (colon < _port_end) {
|
||||
_port_start = colon + 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Is there a port?
|
||||
size_t colon = _url.find(':', _server_start);
|
||||
if (colon < _port_end) {
|
||||
// Yep.
|
||||
_server_end = colon;
|
||||
_port_start = colon + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (_port_start < _port_end) {
|
||||
_flags |= F_has_port;
|
||||
_server_end = colon;
|
||||
_port_start = colon + 1;
|
||||
|
||||
// Decode the port into an integer. Don't bother to error check if it's
|
||||
// not really an integer.
|
||||
string port_str = _url.substr(_port_start, _port_end - _port_start);
|
||||
_port = atoi(port_str.c_str());
|
||||
_port = (uint16_t)atoi(port_str.c_str());
|
||||
}
|
||||
|
||||
// Make sure the server name is lowercase only.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include "pandabase.h"
|
||||
#include "pnotify.h"
|
||||
|
||||
class Filename;
|
||||
|
||||
/**
|
||||
* A container for a URL, e.g. "http://server:port/path".
|
||||
*
|
||||
|
|
@ -27,14 +29,14 @@ class EXPCL_PANDAEXPRESS URLSpec {
|
|||
PUBLISHED:
|
||||
URLSpec();
|
||||
INLINE URLSpec(const string &url, bool server_name_expected = false);
|
||||
INLINE URLSpec(const URLSpec ©);
|
||||
URLSpec(const URLSpec &url, const Filename &path);
|
||||
INLINE void operator = (const string &url);
|
||||
void operator = (const URLSpec ©);
|
||||
|
||||
INLINE bool operator == (const URLSpec &other) const;
|
||||
INLINE bool operator != (const URLSpec &other) const;
|
||||
INLINE bool operator < (const URLSpec &other) const;
|
||||
INLINE int compare_to(const URLSpec &other) const;
|
||||
int compare_to(const URLSpec &other) const;
|
||||
size_t get_hash() const;
|
||||
|
||||
INLINE bool has_scheme() const;
|
||||
INLINE bool has_authority() const;
|
||||
|
|
@ -49,7 +51,7 @@ PUBLISHED:
|
|||
INLINE string get_username() const;
|
||||
INLINE string get_server() const;
|
||||
INLINE string get_port_str() const;
|
||||
int get_port() const;
|
||||
uint16_t get_port() const;
|
||||
string get_server_and_port() const;
|
||||
bool is_default_port() const;
|
||||
static int get_default_port_for_scheme(const string &scheme);
|
||||
|
|
@ -65,7 +67,7 @@ PUBLISHED:
|
|||
void set_username(const string &username);
|
||||
void set_server(const string &server);
|
||||
void set_port(const string &port);
|
||||
void set_port(int port);
|
||||
void set_port(uint16_t port);
|
||||
void set_server_and_port(const string &server_and_port);
|
||||
void set_path(const string &path);
|
||||
void set_query(const string &query);
|
||||
|
|
@ -75,8 +77,10 @@ PUBLISHED:
|
|||
INLINE operator const string & () const;
|
||||
INLINE const char *c_str() const;
|
||||
INLINE bool empty() const;
|
||||
INLINE operator bool() const;
|
||||
INLINE size_t length() const;
|
||||
INLINE char operator [] (int n) const;
|
||||
INLINE size_t size() const;
|
||||
INLINE char operator [] (size_t n) const;
|
||||
|
||||
bool input(istream &in);
|
||||
void output(ostream &out) const;
|
||||
|
|
@ -86,6 +90,16 @@ PUBLISHED:
|
|||
static string unquote(const string &source);
|
||||
static string unquote_plus(const string &source);
|
||||
|
||||
MAKE_PROPERTY(scheme, get_scheme, set_scheme);
|
||||
MAKE_PROPERTY(authority, get_authority, set_authority);
|
||||
MAKE_PROPERTY(username, get_username, set_username);
|
||||
MAKE_PROPERTY(server, get_server, set_server);
|
||||
MAKE_PROPERTY(port, get_port, set_port);
|
||||
MAKE_PROPERTY(server_and_port, get_server_and_port, set_server_and_port);
|
||||
MAKE_PROPERTY(path, get_path, set_path);
|
||||
MAKE_PROPERTY(query, get_query, set_query);
|
||||
MAKE_PROPERTY(ssl, is_ssl);
|
||||
|
||||
private:
|
||||
void parse_authority();
|
||||
|
||||
|
|
@ -100,7 +114,7 @@ private:
|
|||
};
|
||||
|
||||
string _url;
|
||||
int _port;
|
||||
uint16_t _port;
|
||||
int _flags;
|
||||
|
||||
size_t _scheme_end;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "config_nativenet.cxx"
|
||||
#include "buffered_datagramconnection.cxx"
|
||||
#include "socket_address.cxx"
|
||||
#include "socket_ip.cxx"
|
||||
#include "socket_tcp.cxx"
|
||||
#include "socket_tcp_listen.cxx"
|
||||
|
|
|
|||
|
|
@ -11,42 +11,69 @@
|
|||
* @date 2014-10-19
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a RAW sockaddr_in
|
||||
*/
|
||||
INLINE unsigned long Socket_Address::
|
||||
GetIPAddressRaw() const {
|
||||
return _addr.sin_addr.s_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor that lets us set a port value
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(unsigned short port) {
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(port);
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr4.sin_port = htons(port);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(const Socket_Address &inaddr) {
|
||||
_addr.sin_family = inaddr._addr.sin_family;
|
||||
_addr.sin_addr.s_addr = inaddr._addr.sin_addr.s_addr;
|
||||
_addr.sin_port = inaddr._addr.sin_port;
|
||||
Socket_Address(const Socket_Address &inaddr) :
|
||||
_storage(inaddr._storage) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(const AddressType &inaddr) {
|
||||
_addr.sin_family = inaddr.sin_family;
|
||||
_addr.sin_addr.s_addr = inaddr.sin_addr.s_addr;
|
||||
_addr.sin_port = inaddr.sin_port;
|
||||
Socket_Address(const struct sockaddr &inaddr) {
|
||||
if (inaddr.sa_family == AF_INET) {
|
||||
_addr4 = (const sockaddr_in &)inaddr;
|
||||
|
||||
} else if (inaddr.sa_family == AF_INET6) {
|
||||
_addr6 = (const sockaddr_in6 &)inaddr;
|
||||
|
||||
} else {
|
||||
nassertv(false);
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(const struct sockaddr_in &inaddr) :
|
||||
_addr4(inaddr) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(const struct sockaddr_in6 &inaddr) :
|
||||
_addr6(inaddr) {
|
||||
|
||||
if (IN6_IS_ADDR_V4MAPPED(&_addr6.sin6_addr) != 0) {
|
||||
// This is really an IPv4 address disguised as an IPv6 address.
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_addr.s_addr = ((uint32_t *)&_addr6.sin6_addr)[3];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE Socket_Address::
|
||||
Socket_Address(const struct sockaddr_storage &inaddr) :
|
||||
_storage(inaddr) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -61,9 +88,24 @@ INLINE Socket_Address::
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
operator == (const Socket_Address &in) const {
|
||||
return ((_addr.sin_family == in._addr.sin_family) &&
|
||||
(_addr.sin_addr.s_addr == in._addr.sin_addr.s_addr) &&
|
||||
(_addr.sin_port == in._addr.sin_port));
|
||||
if (_storage.ss_family != in._storage.ss_family) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
return _addr4.sin_port == in._addr4.sin_port &&
|
||||
_addr4.sin_addr.s_addr == in._addr4.sin_addr.s_addr;
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
return _addr6.sin6_port != in._addr6.sin6_port &&
|
||||
memcmp((char *) &_addr6.sin6_addr,
|
||||
(char *) &in._addr6.sin6_addr,
|
||||
sizeof(_addr6.sin6_addr)) == 0;
|
||||
}
|
||||
|
||||
// Unsupported address family.
|
||||
nassertr(false, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,9 +113,7 @@ operator == (const Socket_Address &in) const {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
operator != (const Socket_Address &in) const {
|
||||
return ((_addr.sin_family != in._addr.sin_family) ||
|
||||
(_addr.sin_addr.s_addr != in._addr.sin_addr.s_addr) ||
|
||||
(_addr.sin_port != in._addr.sin_port));
|
||||
return !operator ==(in);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -81,9 +121,9 @@ operator != (const Socket_Address &in) const {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_broadcast(unsigned short port) {
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = 0xffffffff;
|
||||
_addr.sin_port = htons(port);
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_addr.s_addr = 0xffffffff;
|
||||
_addr4.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -92,9 +132,21 @@ set_broadcast(unsigned short port) {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_any_IP(unsigned short port) {
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(port);
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr4.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to any IPv6 address and a specified port.
|
||||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_any_IPv6(unsigned short port) {
|
||||
_addr6.sin6_family = AF_INET6;
|
||||
_addr6.sin6_addr = in6addr_any;
|
||||
_addr6.sin6_port = htons(port);
|
||||
_addr6.sin6_scope_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +155,7 @@ set_any_IP(unsigned short port) {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_port(unsigned short port) {
|
||||
_addr.sin_port = htons(port);
|
||||
_addr4.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -112,9 +164,18 @@ set_port(unsigned short port) {
|
|||
*/
|
||||
INLINE void Socket_Address::
|
||||
clear() {
|
||||
_addr.sin_family = AF_INET;
|
||||
_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr.sin_port = htons(0);
|
||||
_addr4.sin_family = AF_INET;
|
||||
_addr4.sin_addr.s_addr = INADDR_ANY;
|
||||
_addr4.sin_port = htons(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns AF_INET if this is an IPv4 address, or AF_INET6 if this is an IPv6
|
||||
* address.
|
||||
*/
|
||||
INLINE sa_family_t Socket_Address::
|
||||
get_family() const {
|
||||
return _storage.ss_family;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -122,73 +183,7 @@ clear() {
|
|||
*/
|
||||
INLINE unsigned short Socket_Address::
|
||||
get_port() const {
|
||||
return ntohs(_addr.sin_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IP address portion in dot notation string
|
||||
*/
|
||||
INLINE std::string Socket_Address::
|
||||
get_ip() const {
|
||||
return std::string(inet_ntoa(_addr.sin_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ip address/port in dot notation string
|
||||
*/
|
||||
INLINE std::string Socket_Address::
|
||||
get_ip_port() const {
|
||||
char buf1[100]; // 100 is more than enough for any ip address:port combo..
|
||||
sprintf(buf1, "%s:%d", inet_ntoa(_addr.sin_addr), get_port());
|
||||
return std::string(buf1);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will take a port and string-based TCP address and initialize
|
||||
* the address with this information. Returns true on success; on failure, it
|
||||
* returns false and the address may be undefined.
|
||||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_host(const std::string &hostname, unsigned short port) {
|
||||
struct hostent *hp = NULL;
|
||||
|
||||
// hmm inet_addr does not resolve 255.255.255.255 on ME98 ?? * HACK * ??
|
||||
if (hostname == "255.255.255.255") {
|
||||
return set_broadcast(port);
|
||||
}
|
||||
|
||||
|
||||
uint32_t addr = (uint32_t)inet_addr(hostname.c_str());
|
||||
if (addr == INADDR_NONE) {
|
||||
hp = gethostbyname(hostname.c_str());
|
||||
if (hp == NULL) {
|
||||
return false;
|
||||
} else {
|
||||
memcpy(&_addr.sin_addr, hp->h_addr_list[0], (unsigned int) hp->h_length);
|
||||
}
|
||||
} else {
|
||||
memcpy(&_addr.sin_addr, &addr, sizeof(addr));
|
||||
}
|
||||
|
||||
_addr.sin_port = htons(port);
|
||||
_addr.sin_family = AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_host(const std::string &hostname) {
|
||||
std::string::size_type pos = hostname.find(':');
|
||||
if (pos == std::string::npos)
|
||||
return false;
|
||||
|
||||
std::string host = hostname.substr(0, pos);
|
||||
std::string port = hostname.substr(pos + 1, 100);;
|
||||
|
||||
unsigned short port_dig = (unsigned short)atoi(port.c_str());
|
||||
return set_host(host, port_dig);
|
||||
return ntohs(_addr4.sin_port);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -196,9 +191,9 @@ set_host(const std::string &hostname) {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
set_host(uint32_t in_hostname, unsigned short port) {
|
||||
memcpy(&_addr.sin_addr, &in_hostname, sizeof(in_hostname));
|
||||
_addr.sin_port = htons(port);
|
||||
_addr.sin_family = AF_INET;
|
||||
memcpy(&_addr4.sin_addr, &in_hostname, sizeof(in_hostname));
|
||||
_addr4.sin_port = htons(port);
|
||||
_addr4.sin_family = AF_INET;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -207,27 +202,61 @@ set_host(uint32_t in_hostname, unsigned short port) {
|
|||
*/
|
||||
INLINE bool Socket_Address::
|
||||
operator < (const Socket_Address &in) const {
|
||||
if (_addr.sin_port < in._addr.sin_port)
|
||||
if (_storage.ss_family != in._storage.ss_family) {
|
||||
return _storage.ss_family < in._storage.ss_family;
|
||||
}
|
||||
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
if (_addr4.sin_port != in._addr4.sin_port) {
|
||||
return _addr4.sin_port < in._addr4.sin_port;
|
||||
}
|
||||
|
||||
return _addr4.sin_addr.s_addr < in._addr4.sin_addr.s_addr;
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
if (_addr6.sin6_port != in._addr6.sin6_port) {
|
||||
return _addr6.sin6_port < in._addr6.sin6_port;
|
||||
}
|
||||
|
||||
return IN6_ARE_ADDR_EQUAL(&_addr6.sin6_addr, &in._addr6.sin6_addr) != 0;
|
||||
}
|
||||
|
||||
// Unsupported address family.
|
||||
nassertr(false, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the address is zero.
|
||||
*/
|
||||
INLINE bool Socket_Address::
|
||||
is_any() const {
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
return (_addr4.sin_addr.s_addr == 0);
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
return IN6_IS_ADDR_UNSPECIFIED(&_addr6.sin6_addr) != 0;
|
||||
|
||||
} else {
|
||||
return true;
|
||||
|
||||
if (_addr.sin_port > in._addr.sin_port)
|
||||
return false;
|
||||
|
||||
if (_addr.sin_addr.s_addr < in._addr.sin_addr.s_addr)
|
||||
return true;
|
||||
|
||||
if (_addr.sin_addr.s_addr > in._addr.sin_addr.s_addr)
|
||||
return false;
|
||||
|
||||
return (_addr.sin_family < in._addr.sin_family);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the address is in the multicast range.
|
||||
*/
|
||||
INLINE bool Socket_Address::
|
||||
is_mcast_range(void) const {
|
||||
uint32_t address = ntohl(_addr.sin_addr.s_addr);
|
||||
// 224.0.0.0-239.255.255.255 .. e0,ef
|
||||
return (address >= 0xe0000000 && address < 0xefffffff);
|
||||
is_mcast_range() const {
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
uint32_t address = ntohl(_addr4.sin_addr.s_addr);
|
||||
// 224.0.0.0-239.255.255.255 .. e0,ef
|
||||
return (address >= 0xe0000000 && address < 0xefffffff);
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
// ff00::/8
|
||||
return IN6_IS_ADDR_MULTICAST(&_addr6.sin6_addr) != 0;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
/**
|
||||
* PANDA 3D SOFTWARE
|
||||
* Copyright (c) Carnegie Mellon University. All rights reserved.
|
||||
*
|
||||
* All use of this software is subject to the terms of the revised BSD
|
||||
* license. You should have received a copy of this license along
|
||||
* with this source code in a file named "LICENSE."
|
||||
*
|
||||
* @file socket_address.h
|
||||
* @author rdb
|
||||
* @date 2016-06-17
|
||||
*/
|
||||
|
||||
#include "socket_address.h"
|
||||
#include "config_downloader.h"
|
||||
|
||||
/**
|
||||
* This function will take a port and string-based TCP address and initialize
|
||||
* the address with this information. Returns true on success; on failure, it
|
||||
* returns false and the address may be undefined.
|
||||
*/
|
||||
bool Socket_Address::
|
||||
set_host(const std::string &hostname, unsigned short port) {
|
||||
// hmm inet_addr4 does not resolve 255.255.255.255 on ME98 ?? * HACK * ??
|
||||
if (hostname == "255.255.255.255") {
|
||||
return set_broadcast(port);
|
||||
}
|
||||
|
||||
struct addrinfo hints, *res = NULL;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
hints.ai_family = support_ipv6 ? AF_UNSPEC : AF_INET;
|
||||
|
||||
if (getaddrinfo(hostname.c_str(), NULL, &hints, &res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nassertr(res->ai_addrlen <= sizeof(_storage), false);
|
||||
memcpy(&_storage, res->ai_addr, res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
|
||||
_addr4.sin_port = htons(port);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the address from a string specifying both the address and port,
|
||||
* separated by a colon. An IPv6 address must be enclosed in brackets.
|
||||
*/
|
||||
bool Socket_Address::
|
||||
set_host(const std::string &hostname) {
|
||||
std::string::size_type pos = hostname.rfind(':');
|
||||
if (pos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string::size_type host_begin = 0;
|
||||
std::string::size_type host_end = pos;
|
||||
|
||||
// Strip spaces.
|
||||
while (host_begin < host_end && isspace(hostname[host_begin])) {
|
||||
++host_begin;
|
||||
}
|
||||
|
||||
while (host_begin < host_end && isspace(hostname[host_end - 1])) {
|
||||
--host_end;
|
||||
}
|
||||
|
||||
if (host_begin < host_end && hostname[host_begin] == '[') {
|
||||
// Looks like an IPv6 address; extract from the brackets.
|
||||
host_begin += 1;
|
||||
if (hostname[host_end - 1] == ']') {
|
||||
host_end -= 1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string host = hostname.substr(host_begin, host_end - host_begin);
|
||||
std::string port = hostname.substr(pos + 1, 100);
|
||||
|
||||
unsigned short port_dig = (unsigned short)atoi(port.c_str());
|
||||
return set_host(host, port_dig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IP address portion in dot notation string.
|
||||
*/
|
||||
std::string Socket_Address::
|
||||
get_ip() const {
|
||||
char buf[48];
|
||||
buf[0] = 0;
|
||||
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
getnameinfo(&_addr, sizeof(sockaddr_in6), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
} else {
|
||||
nassertr(false, std::string());
|
||||
}
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ip address/port in dot notation string. If this is an IPv6
|
||||
* address, it will be enclosed in square brackets.
|
||||
*/
|
||||
std::string Socket_Address::
|
||||
get_ip_port() const {
|
||||
char buf[100]; // 100 is more than enough for any ip address:port combo..
|
||||
buf[0] = 0;
|
||||
|
||||
if (_storage.ss_family == AF_INET) {
|
||||
getnameinfo(&_addr, sizeof(sockaddr_in), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
|
||||
sprintf(buf + strlen(buf), ":%hu", get_port());
|
||||
|
||||
} else if (_storage.ss_family == AF_INET6) {
|
||||
// Protect the IPv6 address within square brackets.
|
||||
buf[0] = '[';
|
||||
getnameinfo(&_addr, sizeof(sockaddr_in6), buf + 1, sizeof(buf) - 1, NULL, 0, NI_NUMERICHOST);
|
||||
sprintf(buf + strlen(buf), "]:%hu", get_port());
|
||||
|
||||
} else {
|
||||
nassertr(false, std::string());
|
||||
}
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a raw 32-bit unsigned integer representing the IPv4 address.
|
||||
* @deprecated Does not work with IPv6 addresses.
|
||||
*/
|
||||
unsigned long Socket_Address::
|
||||
GetIPAddressRaw() const {
|
||||
if (_addr.sa_family == AF_INET) {
|
||||
return _addr4.sin_addr.s_addr;
|
||||
}
|
||||
if (_addr.sa_family == AF_INET6) {
|
||||
// Okay, if we got here, something probably went wrong, but let's see if
|
||||
// we can offer a meaningful translation for mapped addresses.
|
||||
uint32_t *parts = (uint32_t *)&_addr6.sin6_addr;
|
||||
if (parts[0] == 0 && parts[1] == 0 && (parts[2] == 0 || parts[2] == htonl(0xffff))) {
|
||||
if (parts[2] == 0 && parts[3] == htonl(1)) {
|
||||
// Special exception for localhost.
|
||||
return 0x1000007f;
|
||||
} else {
|
||||
return parts[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
nassert_raise("GetIPAddressRaw() can only be called on an IPv4 address");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@
|
|||
* @date 2014-10-19
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SOCKET_ADDRESS_H
|
||||
#define SOCKET_ADDRESS_H
|
||||
|
||||
|
|
@ -20,15 +19,17 @@
|
|||
#include "socket_portable.h"
|
||||
|
||||
/**
|
||||
* A simple place to store and munipulate tcp and port address for
|
||||
* A simple place to store and manipulate tcp and port address for
|
||||
* communication layer
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_Address {
|
||||
public:
|
||||
typedef struct sockaddr_in AddressType;
|
||||
Socket_Address(const AddressType &inaddr);
|
||||
AddressType &GetAddressInfo() { return _addr; }
|
||||
const AddressType &GetAddressInfo() const { return _addr; }
|
||||
INLINE Socket_Address(const struct sockaddr &inaddr);
|
||||
INLINE Socket_Address(const struct sockaddr_in &inaddr);
|
||||
INLINE Socket_Address(const struct sockaddr_in6 &inaddr);
|
||||
INLINE Socket_Address(const struct sockaddr_storage &inaddr);
|
||||
INLINE struct sockaddr &GetAddressInfo() { return _addr; }
|
||||
INLINE const struct sockaddr &GetAddressInfo() const { return _addr; }
|
||||
|
||||
PUBLISHED:
|
||||
INLINE Socket_Address(unsigned short port = 0);
|
||||
|
|
@ -37,27 +38,35 @@ PUBLISHED:
|
|||
INLINE virtual ~Socket_Address();
|
||||
|
||||
INLINE bool set_any_IP(unsigned short port);
|
||||
INLINE bool set_any_IPv6(unsigned short port);
|
||||
INLINE bool set_port(unsigned short port);
|
||||
INLINE bool set_broadcast(unsigned short port);
|
||||
|
||||
INLINE bool set_host(const std::string &hostname, unsigned short port) ;
|
||||
INLINE bool set_host(const std::string &hostname) ;
|
||||
INLINE bool set_host(unsigned int ip4adr, unsigned short port);
|
||||
bool set_host(const std::string &hostname, unsigned short port);
|
||||
bool set_host(const std::string &hostname);
|
||||
INLINE bool set_host(uint32_t ip4addr, unsigned short port);
|
||||
INLINE void clear();
|
||||
|
||||
INLINE sa_family_t get_family() const;
|
||||
INLINE unsigned short get_port() const;
|
||||
INLINE std::string get_ip() const ;
|
||||
INLINE std::string get_ip_port() const;
|
||||
INLINE unsigned long GetIPAddressRaw() const;
|
||||
std::string get_ip() const ;
|
||||
std::string get_ip_port() const;
|
||||
unsigned long GetIPAddressRaw() const;
|
||||
|
||||
INLINE bool operator ==(const Socket_Address &in) const;
|
||||
INLINE bool operator !=(const Socket_Address &in) const;
|
||||
INLINE bool operator < (const Socket_Address &in) const;
|
||||
|
||||
INLINE bool is_any() const;
|
||||
INLINE bool is_mcast_range() const;
|
||||
|
||||
private:
|
||||
AddressType _addr;
|
||||
union {
|
||||
sockaddr _addr;
|
||||
sockaddr_in _addr4;
|
||||
sockaddr_in6 _addr6;
|
||||
sockaddr_storage _storage;
|
||||
};
|
||||
};
|
||||
|
||||
#include "socket_address.I"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "socket_portable.h"
|
||||
#include "socket_address.h"
|
||||
#include "typedObject.h"
|
||||
#include "config_downloader.h"
|
||||
|
||||
// forward declarations for friends...
|
||||
class Socket_TCP;
|
||||
|
|
@ -35,6 +36,7 @@ PUBLISHED:
|
|||
inline int SetNonBlocking();
|
||||
inline int SetBlocking();
|
||||
inline bool SetReuseAddress(bool flag = true);
|
||||
inline bool SetV6Only(bool flag);
|
||||
inline bool Active();
|
||||
inline int SetRecvBufferSize(int size);
|
||||
inline void SetSocket(SOCKET ins);
|
||||
|
|
@ -44,7 +46,6 @@ PUBLISHED:
|
|||
|
||||
inline static int InitNetworkDriver() { return init_network(); };
|
||||
|
||||
public:
|
||||
private:
|
||||
inline bool ErrorClose();
|
||||
|
||||
|
|
@ -194,7 +195,7 @@ SetBlocking() {
|
|||
fcntl(_socket, F_SETFL, flags);
|
||||
return ALL_OK;
|
||||
#else
|
||||
unsigned long val = 0;
|
||||
unsigned long val = 0;
|
||||
unsigned lanswer = 0;
|
||||
lanswer = SOCKIOCTL(_socket, LOCAL_FL_SET, &val);
|
||||
if (lanswer != 0) {
|
||||
|
|
@ -209,8 +210,21 @@ SetBlocking() {
|
|||
*/
|
||||
inline bool Socket_IP::
|
||||
SetReuseAddress(bool flag) {
|
||||
int bOption = flag;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&bOption, sizeof(bOption)) != 0) {
|
||||
int value = flag;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&value, sizeof(value)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a flag indicating whether this IPv6 socket should operate in
|
||||
* dual-stack mode or not.
|
||||
*/
|
||||
inline bool Socket_IP::
|
||||
SetV6Only(bool flag) {
|
||||
int value = flag ? 1 : 0;
|
||||
if (setsockopt(_socket, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&value, sizeof(value))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -237,7 +251,7 @@ GetSocket() const {
|
|||
*/
|
||||
inline Socket_Address Socket_IP::
|
||||
GetPeerName(void) const {
|
||||
sockaddr_in name;
|
||||
sockaddr_storage name;
|
||||
socklen_t name_len = sizeof(name);
|
||||
memset(&name, 0, name_len);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,13 @@
|
|||
const int ALL_OK = 0;
|
||||
const int BASIC_ERROR = -1;
|
||||
|
||||
#define SA_SIZEOF(addr) (((addr)->sa_family == AF_INET6) ? sizeof(sockaddr_in6) : sizeof(sockaddr_in))
|
||||
|
||||
#if defined(CPPPARSER)
|
||||
// Interrogate doesn't need to parse any of this.
|
||||
|
||||
typedef unsigned long SOCKET;
|
||||
typedef unsigned short sa_family_t;
|
||||
|
||||
/************************************************************************
|
||||
* HP SOCKET LIBRARY STUFF
|
||||
|
|
@ -46,91 +49,77 @@ typedef unsigned long SOCKET;
|
|||
/************************************************************************
|
||||
* WINSOCK 32 bit STUFF
|
||||
************************************************************************/
|
||||
#elif defined(WIN32) || defined(WIN32_VC) || defined(WIN64_VC)
|
||||
#elif defined(_WIN32)
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
|
||||
typedef u_short sa_family_t;
|
||||
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout)
|
||||
{
|
||||
return select((int) n, readfds, writefds, exceptfds,timeout);
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
|
||||
return select((int)n, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
|
||||
inline int DO_CONNECT( const SOCKET a, const struct sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_CONNECT(const SOCKET a, const struct sockaddr *b) {
|
||||
return connect(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return recv(a, buf, size, 0);
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) {
|
||||
return recv(a, buf, size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return send(a, buff, len, 0);
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) {
|
||||
return send(a, buff, len, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return sendto(a, buffer, buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) {
|
||||
return sendto(a, buffer, buf_len, 0, addr, SA_SIZEOF(addr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
inline SOCKET DO_NEWUDP(sa_family_t family) {
|
||||
return socket(family, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
inline SOCKET DO_NEWTCP(sa_family_t family) {
|
||||
return socket(family, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return ::bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr *b) {
|
||||
return ::bind(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return closesocket(a);
|
||||
inline int DO_CLOSE(const SOCKET a) {
|
||||
return closesocket(a);
|
||||
}
|
||||
inline SOCKET DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
int adrlen = sizeof(sockaddr);
|
||||
return accept(sck, reinterpret_cast<sockaddr *>(adr), &adrlen);
|
||||
};
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
int plen = sizeof(sockaddr);
|
||||
return recvfrom(sck, data, len, 0, reinterpret_cast<sockaddr *>(addr), &plen);
|
||||
inline SOCKET DO_ACCEPT(SOCKET sck, sockaddr *addr) {
|
||||
socklen_t addrlen = sizeof(sockaddr_storage);
|
||||
return accept(sck, addr, &addrlen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) {
|
||||
socklen_t plen = sizeof(sockaddr_storage);
|
||||
return recvfrom(sck, data, len, 0, addr, &plen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size) {
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return WSAGetLastError();
|
||||
inline int GETERROR() {
|
||||
return WSAGetLastError();
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, unsigned long * val)
|
||||
{
|
||||
return ioctlsocket(s, flags, val);
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, unsigned long *val) {
|
||||
return ioctlsocket(s, flags, val);
|
||||
}
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
static struct WSAData mydata;
|
||||
int answer = WSAStartup(0x0101, &mydata);
|
||||
if (answer != 0)
|
||||
return BASIC_ERROR;
|
||||
inline int init_network() {
|
||||
static struct WSAData mydata;
|
||||
int answer = WSAStartup(0x0101, &mydata);
|
||||
if (answer != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
|
||||
return ALL_OK;
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
inline bool do_shutdown_send(SOCKET s)
|
||||
{
|
||||
return (shutdown(s,SD_SEND) == 0);
|
||||
};
|
||||
inline bool do_shutdown_send(SOCKET s) {
|
||||
return (shutdown(s, SD_SEND) == 0);
|
||||
}
|
||||
|
||||
typedef int socklen_t ;
|
||||
typedef int socklen_t;
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
const long LOCAL_FL_SET = FIONBIO ;
|
||||
const long LOCAL_FL_SET = FIONBIO;
|
||||
const int LOCAL_BLOCKING_ERROR = WSAEWOULDBLOCK;
|
||||
const int LOCAL_CONNECT_BLOCKING = WSAEWOULDBLOCK;
|
||||
const int LOCAL_NOTCONNECTED_ERROR = WSAENOTCONN;
|
||||
|
|
@ -162,84 +151,61 @@ const SOCKET BAD_SOCKET = (SOCKET)-1;
|
|||
typedef int SOCKET;
|
||||
const SOCKET BAD_SOCKET = 0xffffffff;
|
||||
|
||||
// #define DO_CONNECT(a,b) connect(a,(sockaddr
|
||||
// *)b,sizeof(sockaddr)) #define DO_SOCKET_READ(a,b,c) recv(a,b,c,0)
|
||||
// #define DO_SOCKET_WRITE(a,b,c) send(a,b,c,0)
|
||||
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr *b) {
|
||||
return connect(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return recv(a, buf, size, 0);
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) {
|
||||
return recv(a, buf, size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return send(a, buff, len, 0);
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) {
|
||||
return send(a, buff, len, 0);
|
||||
}
|
||||
|
||||
// #define DO_SOCKET_WRITE_TO(a,b,c,d) sendto(a,b,c,0,(sockaddr
|
||||
// *)d,sizeof(sockaddr)) #define DO_NEWUDP() socket(AF_INET,
|
||||
// SOCK_DGRAM, 0) #define DO_NEWTCP() socket(AF_INET, SOCK_STREAM, 0)
|
||||
// #define DO_BIND(a,b) ::bind(a,(sockaddr *)b,sizeof(sockaddr)) #define
|
||||
// DO_CLOSE(a) close(a)
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return sendto(a, buffer, buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) {
|
||||
return sendto(a, buffer, buf_len, 0, addr, SA_SIZEOF(addr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
inline SOCKET DO_NEWUDP(sa_family_t family) {
|
||||
return socket(family, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
inline SOCKET DO_NEWTCP(sa_family_t family) {
|
||||
return socket(family, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return ::bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr *b) {
|
||||
return ::bind(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return close(a);
|
||||
inline int DO_CLOSE(const SOCKET a) {
|
||||
return close(a);
|
||||
}
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
int adrlen = sizeof(sockaddr);
|
||||
return accept(sck, ( sockaddr *)adr, &adrlen);
|
||||
};
|
||||
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
int plen = sizeof(sockaddr);
|
||||
return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr *addr) {
|
||||
socklen_t addrlen = sizeof(sockaddr_storage);
|
||||
return accept(sck, (sockaddr *)addr, &addrlen);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return errno;
|
||||
inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) {
|
||||
socklen_t plen = sizeof(sockaddr_storage);
|
||||
return recvfrom(sck, data, len, 0, (sockaddr *)addr, &plen);
|
||||
}
|
||||
inline int DO_LISTEN(const SOCKET a, const int size) {
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void * val)
|
||||
{
|
||||
return ioctl(s, flags, val);
|
||||
inline int GETERROR() {
|
||||
return errno;
|
||||
}
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
return ALL_OK;
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void *val) {
|
||||
return ioctl(s, flags, val);
|
||||
}
|
||||
|
||||
inline int init_network() {
|
||||
return ALL_OK;
|
||||
}
|
||||
#ifndef INADDR_NONE
|
||||
const INADDR_NONE = -1;
|
||||
#endif
|
||||
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
const long LOCAL_FL_SET = FIONBIO ;
|
||||
const long LOCAL_FL_SET = FIONBIO;
|
||||
const int LOCAL_BLOCKING_ERROR = EAGAIN;
|
||||
const int LOCAL_CONNECT_BLOCKING = EINPROGRESS;
|
||||
|
||||
|
|
@ -267,94 +233,75 @@ const int LOCAL_CONNECT_BLOCKING = EINPROGRESS;
|
|||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct sockaddr_in AddressType;
|
||||
|
||||
typedef int SOCKET;
|
||||
const SOCKET BAD_SOCKET = -1;
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout)
|
||||
{
|
||||
return select((int) n, readfds, writefds, exceptfds,timeout);
|
||||
inline int DO_SELECT(SOCKET n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) {
|
||||
return select((int)n, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return connect(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_CONNECT(const SOCKET a, const sockaddr *b) {
|
||||
return connect(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char * buf, const int size)
|
||||
{
|
||||
return (int)recv(a, buf, (size_t)size, 0);
|
||||
inline int DO_SOCKET_READ(const SOCKET a, char *buf, const int size) {
|
||||
return (int)recv(a, buf, (size_t)size, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char * buff, const int len)
|
||||
{
|
||||
return (int)send(a, buff, (size_t)len, 0);
|
||||
inline int DO_SOCKET_WRITE(const SOCKET a, const char *buff, const int len) {
|
||||
return (int)send(a, buff, (size_t)len, 0);
|
||||
}
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char * buffer, const int buf_len, const sockaddr_in * addr)
|
||||
{
|
||||
return (int)sendto(a, buffer, (size_t)buf_len, 0, reinterpret_cast<const struct ::sockaddr *>(addr), sizeof(sockaddr));
|
||||
inline int DO_SOCKET_WRITE_TO(const SOCKET a, const char *buffer, const int buf_len, const sockaddr *addr) {
|
||||
return (int)sendto(a, buffer, (size_t)buf_len, 0, addr, SA_SIZEOF(addr));
|
||||
}
|
||||
inline SOCKET DO_NEWUDP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_DGRAM, 0);
|
||||
inline SOCKET DO_NEWUDP(sa_family_t family) {
|
||||
return socket(family, SOCK_DGRAM, 0);
|
||||
}
|
||||
inline SOCKET DO_NEWTCP()
|
||||
{
|
||||
return socket(AF_INET, SOCK_STREAM, 0);
|
||||
inline SOCKET DO_NEWTCP(sa_family_t family) {
|
||||
return socket(family, SOCK_STREAM, 0);
|
||||
}
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr_in *b)
|
||||
{
|
||||
return ::bind(a, reinterpret_cast<const struct ::sockaddr *>(b), sizeof(sockaddr));
|
||||
inline int DO_BIND(const SOCKET a, const sockaddr *b) {
|
||||
return ::bind(a, b, SA_SIZEOF(b));
|
||||
}
|
||||
inline int DO_CLOSE(const SOCKET a)
|
||||
{
|
||||
return close(a);
|
||||
inline int DO_CLOSE(const SOCKET a) {
|
||||
return close(a);
|
||||
}
|
||||
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr_in * adr)
|
||||
{
|
||||
socklen_t adrlen = sizeof(sockaddr);
|
||||
return accept(sck, ( sockaddr *)adr, &adrlen);
|
||||
};
|
||||
inline int DO_ACCEPT(SOCKET sck, sockaddr *addr) {
|
||||
socklen_t addrlen = sizeof(sockaddr_storage);
|
||||
return accept(sck, (sockaddr *)addr, &addrlen);
|
||||
}
|
||||
|
||||
inline int DO_RECV_FROM(SOCKET sck, char * data, int len, sockaddr_in * addr)
|
||||
{
|
||||
socklen_t plen = sizeof(sockaddr);
|
||||
return (int)recvfrom(sck, data, (size_t)len, 0, (sockaddr *)addr, &plen);
|
||||
inline int DO_RECV_FROM(SOCKET sck, char *data, int len, sockaddr *addr) {
|
||||
socklen_t plen = sizeof(sockaddr_storage);
|
||||
return (int)recvfrom(sck, data, (size_t)len, 0, (sockaddr *)addr, &plen);
|
||||
}
|
||||
|
||||
|
||||
inline int init_network()
|
||||
{
|
||||
signal(SIGPIPE, SIG_IGN); // hmm do i still need this ...
|
||||
return ALL_OK;
|
||||
inline int init_network() {
|
||||
signal(SIGPIPE, SIG_IGN); // hmm do i still need this ...
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
inline int DO_LISTEN(const SOCKET a, const int size)
|
||||
{
|
||||
return listen(a, size);
|
||||
inline int DO_LISTEN(const SOCKET a, const int size) {
|
||||
return listen(a, size);
|
||||
}
|
||||
|
||||
inline int GETERROR()
|
||||
{
|
||||
return errno;
|
||||
inline int GETERROR() {
|
||||
return errno;
|
||||
}
|
||||
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void * val)
|
||||
{
|
||||
return ioctl(s, (unsigned long)flags, val);
|
||||
inline int SOCKIOCTL(const SOCKET s, const long flags, void *val) {
|
||||
return ioctl(s, (unsigned long)flags, val);
|
||||
}
|
||||
|
||||
inline bool do_shutdown_send(SOCKET s)
|
||||
{
|
||||
return (shutdown(s,SHUT_WR) == 0);
|
||||
};
|
||||
|
||||
inline bool do_shutdown_send(SOCKET s) {
|
||||
return (shutdown(s, SHUT_WR) == 0);
|
||||
}
|
||||
|
||||
#define BSDBLOCK
|
||||
|
||||
|
||||
const long LOCAL_NONBLOCK = 1;
|
||||
// With BSDBLOCK defined, we don't need FIONBIO. Solaris doesn't provide it.
|
||||
// const long LOCAL_FL_SET = FIONBIO ;
|
||||
// const long LOCAL_FL_SET = FIONBIO;
|
||||
const int LOCAL_BLOCKING_ERROR = EAGAIN;
|
||||
const int LOCAL_CONNECT_BLOCKING = EINPROGRESS;
|
||||
|
||||
|
|
@ -366,6 +313,4 @@ No Host Type defined !!
|
|||
#error Fatal
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif //__SOCKET_PORTABLE_H__
|
||||
|
|
|
|||
|
|
@ -8,30 +8,27 @@
|
|||
* Base functionality for a TCP connected socket This class is pretty useless
|
||||
* by itself but it does hide some of the platform differences from machine to
|
||||
* machine
|
||||
*
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP : public Socket_IP
|
||||
{
|
||||
public:
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP : public Socket_IP {
|
||||
PUBLISHED:
|
||||
inline Socket_TCP(SOCKET);
|
||||
inline Socket_TCP() { };
|
||||
inline int SetNoDelay(bool flag = true);
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
inline int SetSendBufferSize(int insize);
|
||||
// inline bool ActiveOpen(const Socket_Address & theaddress);
|
||||
inline bool ActiveOpen(const Socket_Address & theaddress, bool setdelay);
|
||||
inline bool ActiveOpenNonBlocking(const Socket_Address & theaddress);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
inline bool ShutdownSend();
|
||||
inline int SendData(const std::string &str);
|
||||
inline Socket_TCP(SOCKET);
|
||||
inline Socket_TCP() {};
|
||||
inline int SetNoDelay(bool flag = true);
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
inline int SetSendBufferSize(int insize);
|
||||
// inline bool ActiveOpen(const Socket_Address &theaddress);
|
||||
inline bool ActiveOpen(const Socket_Address &theaddress, bool setdelay);
|
||||
inline bool ActiveOpenNonBlocking(const Socket_Address &theaddress);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
inline bool ShutdownSend();
|
||||
inline int SendData(const std::string &str);
|
||||
// inline int RecvData( std::string &str, int max_len);
|
||||
|
||||
std::string RecvData(int max_len);
|
||||
std::string RecvData(int max_len);
|
||||
public:
|
||||
inline int SendData(const char * data, int size);
|
||||
inline int RecvData(char * data, int size);
|
||||
inline int SendData(const char *data, int size);
|
||||
inline int RecvData(char *data, int size);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -54,37 +51,35 @@ private:
|
|||
/**
|
||||
*
|
||||
*/
|
||||
inline Socket_TCP::Socket_TCP(SOCKET sck) : ::Socket_IP(sck)
|
||||
{
|
||||
inline Socket_TCP::
|
||||
Socket_TCP(SOCKET sck) : ::Socket_IP(sck) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Nagle algorithm. Don't delay send to coalesce packets
|
||||
*/
|
||||
inline int Socket_TCP::SetNoDelay(bool flag)
|
||||
{
|
||||
int nodel = flag;
|
||||
int ret1;
|
||||
ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel));
|
||||
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
inline int Socket_TCP::
|
||||
SetNoDelay(bool flag) {
|
||||
int value = flag ? 1 : 0;
|
||||
if (setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&value, sizeof(value))) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* will control the behavior of SO_LINGER for a TCP socket
|
||||
*/
|
||||
int Socket_TCP::SetLinger(int interval_seconds)
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP::
|
||||
SetLinger(int interval_seconds) {
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger));
|
||||
if (ret1 != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -92,45 +87,50 @@ int Socket_TCP::SetLinger(int interval_seconds)
|
|||
* and free up OS resources. You may lose a stream if you use this flag and
|
||||
* do not negotiate the close at the application layer.
|
||||
*/
|
||||
int Socket_TCP::DontLinger()
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP::
|
||||
DontLinger() {
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger));
|
||||
if (ret1 != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just like it sounds. Sets a buffered socket recv buffer size. This
|
||||
* function does not refuse ranges outside hard-coded OS limits
|
||||
*/
|
||||
int Socket_TCP::SetSendBufferSize(int insize)
|
||||
{
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int)))
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP::
|
||||
SetSendBufferSize(int insize) {
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (char *)&insize, sizeof(int))) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will try and set the socket up for active open to a specified
|
||||
* address and port provided by the input parameter
|
||||
*/
|
||||
bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress, bool setdelay)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
bool Socket_TCP::
|
||||
ActiveOpen(const Socket_Address &theaddress, bool setdelay) {
|
||||
_socket = DO_NEWTCP(theaddress.get_family());
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(setdelay)
|
||||
SetNoDelay();
|
||||
if (setdelay) {
|
||||
SetNoDelay();
|
||||
}
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -138,85 +138,87 @@ bool Socket_TCP::ActiveOpen(const Socket_Address & theaddress, bool setdelay)
|
|||
* This function will try and set the socket up for active open to a specified
|
||||
* address and port provided by the input parameter (non-blocking version)
|
||||
*/
|
||||
bool Socket_TCP::ActiveOpenNonBlocking(const Socket_Address & theaddress)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
bool Socket_TCP::
|
||||
ActiveOpenNonBlocking(const Socket_Address &theaddress) {
|
||||
_socket = DO_NEWTCP(theaddress.get_family());
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetNonBlocking();
|
||||
SetReuseAddress();
|
||||
SetNonBlocking();
|
||||
SetReuseAddress();
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) {
|
||||
if (GETERROR() != LOCAL_CONNECT_BLOCKING)
|
||||
{
|
||||
printf(" None Blockign Connect Error %d",GETERROR());
|
||||
return ErrorClose();
|
||||
}
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) {
|
||||
if (GETERROR() != LOCAL_CONNECT_BLOCKING) {
|
||||
printf("Non Blocking Connect Error %d", GETERROR());
|
||||
return ErrorClose();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ok Lets Send the Data - if error 0 if socket closed for write or lengh is 0
|
||||
* + bytes writen ( May be smaller than requested)
|
||||
*/
|
||||
inline int Socket_TCP::SendData(const char * data, int size)
|
||||
{
|
||||
return DO_SOCKET_WRITE(_socket, data, size);
|
||||
inline int Socket_TCP::
|
||||
SendData(const char *data, int size) {
|
||||
return DO_SOCKET_WRITE(_socket, data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data from the connection - if error 0 if socket closed for read or
|
||||
* length is 0 + bytes read ( May be smaller than requested)
|
||||
*/
|
||||
inline int Socket_TCP::RecvData(char * data, int len)
|
||||
{
|
||||
int ecode = DO_SOCKET_READ(_socket, data, len);
|
||||
return ecode;
|
||||
inline int Socket_TCP::
|
||||
RecvData(char *data, int len) {
|
||||
int ecode = DO_SOCKET_READ(_socket, data, len);
|
||||
return ecode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data from the connection - if error 0 if socket closed for read or
|
||||
* length is 0 + bytes read ( May be smaller than requested)
|
||||
* length is 0 + bytes read (May be smaller than requested)
|
||||
*/
|
||||
inline std::string Socket_TCP::RecvData(int max_len)
|
||||
{
|
||||
std::string str;
|
||||
char *buffer = (char *) malloc(max_len+1);
|
||||
int ecode = RecvData(buffer,max_len);
|
||||
if(ecode > 0)
|
||||
str.assign(buffer,ecode);
|
||||
inline std::string Socket_TCP::
|
||||
RecvData(int max_len) {
|
||||
std::string str;
|
||||
char *buffer = (char *)malloc(max_len + 1);
|
||||
int ecode = RecvData(buffer, max_len);
|
||||
if (ecode > 0) {
|
||||
str.assign(buffer, ecode);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
return str;
|
||||
};
|
||||
|
||||
|
||||
inline bool Socket_TCP::ErrorIs_WouldBlocking(int err)
|
||||
{
|
||||
return (GETERROR() == LOCAL_BLOCKING_ERROR);
|
||||
free(buffer);
|
||||
return str;
|
||||
}
|
||||
|
||||
inline bool Socket_TCP::ShutdownSend()
|
||||
{
|
||||
return do_shutdown_send(_socket);
|
||||
};
|
||||
|
||||
inline bool Socket_TCP::
|
||||
ErrorIs_WouldBlocking(int err) {
|
||||
return (GETERROR() == LOCAL_BLOCKING_ERROR);
|
||||
}
|
||||
|
||||
inline bool Socket_TCP::
|
||||
ShutdownSend() {
|
||||
return do_shutdown_send(_socket);
|
||||
}
|
||||
|
||||
/*
|
||||
inline bool Socket_TCP::DoNotLinger()
|
||||
{
|
||||
int bOption = 1;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
inline bool Socket_TCP::
|
||||
DoNotLinger() {
|
||||
int bOption = 1;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_DONTLINGER, (const char *)&bOption, sizeof(bOption)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
inline int Socket_TCP::SendData(const std::string &str)
|
||||
{
|
||||
return SendData(str.data(), str.size());
|
||||
};
|
||||
inline int Socket_TCP::
|
||||
SendData(const std::string &str) {
|
||||
return SendData(str.data(), str.size());
|
||||
}
|
||||
|
||||
#endif //__SOCKET_TCP_H__
|
||||
|
|
|
|||
|
|
@ -8,16 +8,17 @@
|
|||
/**
|
||||
* Base functionality for a TCP rendezvous socket
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP_Listen : public Socket_IP
|
||||
{
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP_Listen : public Socket_IP {
|
||||
public:
|
||||
PUBLISHED:
|
||||
Socket_TCP_Listen() {};
|
||||
~Socket_TCP_Listen() {};
|
||||
inline bool OpenForListen(const Socket_Address & Inaddess, int backlog_size = 1024);
|
||||
inline bool GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address);
|
||||
Socket_TCP_Listen() {};
|
||||
~Socket_TCP_Listen() {};
|
||||
inline bool OpenForListen(unsigned short port, int backlog_size = 1024);
|
||||
inline bool OpenForListen(const Socket_Address &address, int backlog_size = 1024);
|
||||
inline bool GetIncomingConnection(Socket_TCP &newsession, Socket_Address &address);
|
||||
|
||||
public:
|
||||
inline bool GetIncomingConnection(SOCKET & newsession, Socket_Address &address);
|
||||
inline bool GetIncomingConnection(SOCKET &newsession, Socket_Address &address);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -40,43 +41,77 @@ private:
|
|||
/**
|
||||
* This function will initialize a listening Socket
|
||||
*/
|
||||
inline bool Socket_TCP_Listen::OpenForListen(const Socket_Address & Inaddess, int backlog_size )
|
||||
{
|
||||
ErrorClose();
|
||||
_socket = DO_NEWTCP();
|
||||
inline bool Socket_TCP_Listen::
|
||||
OpenForListen(unsigned short port, int backlog_size) {
|
||||
ErrorClose();
|
||||
|
||||
SetReuseAddress();
|
||||
Socket_Address address;
|
||||
if (support_ipv6) {
|
||||
// Create a socket supporting both IPv4 and IPv6.
|
||||
address.set_any_IPv6(port);
|
||||
_socket = DO_NEWTCP(AF_INET6);
|
||||
SetV6Only(false);
|
||||
} else {
|
||||
address.set_any_IP(port);
|
||||
_socket = DO_NEWTCP(AF_INET);
|
||||
}
|
||||
|
||||
if (DO_BIND(_socket, &Inaddess.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
SetReuseAddress();
|
||||
|
||||
if (DO_LISTEN(_socket, backlog_size) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
if (DO_LISTEN(_socket, backlog_size) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize a listening Socket
|
||||
*/
|
||||
inline bool Socket_TCP_Listen::
|
||||
OpenForListen(const Socket_Address &address, int backlog_size) {
|
||||
ErrorClose();
|
||||
|
||||
_socket = DO_NEWTCP(address.get_family());
|
||||
|
||||
SetReuseAddress();
|
||||
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
if (DO_LISTEN(_socket, backlog_size) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to accept new connections
|
||||
*/
|
||||
inline bool Socket_TCP_Listen::GetIncomingConnection(SOCKET & newsession, Socket_Address &address)
|
||||
{
|
||||
newsession = DO_ACCEPT(_socket, &address.GetAddressInfo());
|
||||
if (newsession == BAD_SOCKET)
|
||||
return false;
|
||||
return true;
|
||||
inline bool Socket_TCP_Listen::
|
||||
GetIncomingConnection(SOCKET &newsession, Socket_Address &address) {
|
||||
newsession = DO_ACCEPT(_socket, &address.GetAddressInfo());
|
||||
if (newsession == BAD_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Socket_TCP_Listen::
|
||||
GetIncomingConnection(Socket_TCP &newsession, Socket_Address &address) {
|
||||
SOCKET sck;
|
||||
if (!GetIncomingConnection(sck, address)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool Socket_TCP_Listen::GetIncomingConnection(Socket_TCP & newsession, Socket_Address &address)
|
||||
{
|
||||
SOCKET sck;
|
||||
if(!GetIncomingConnection(sck,address))
|
||||
return false;
|
||||
|
||||
newsession.SetSocket(sck);
|
||||
return true;
|
||||
newsession.SetSocket(sck);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //__SOCKET_TCP_LISTEN_H__
|
||||
|
|
|
|||
|
|
@ -15,76 +15,64 @@
|
|||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
*
|
||||
*/
|
||||
|
||||
extern EXPCL_PANDA_NATIVENET SSL_CTX *global_ssl_ctx;
|
||||
|
||||
struct SSlStartup {
|
||||
SSlStartup() {
|
||||
const SSL_METHOD *meth;
|
||||
SSLeay_add_ssl_algorithms();
|
||||
// meth = SSLv23_server_method();
|
||||
meth = SSLv23_method();
|
||||
SSL_load_error_strings();
|
||||
// I hate this cast, but older versions of OpenSSL need it.
|
||||
global_ssl_ctx = SSL_CTX_new((SSL_METHOD *) meth);
|
||||
}
|
||||
|
||||
struct SSlStartup
|
||||
{
|
||||
SSlStartup()
|
||||
{
|
||||
const SSL_METHOD *meth;
|
||||
SSLeay_add_ssl_algorithms();
|
||||
// meth = SSLv23_server_method();
|
||||
meth = SSLv23_method();
|
||||
SSL_load_error_strings();
|
||||
// I hate this cast, but older versions of OpenSSL need it.
|
||||
global_ssl_ctx = SSL_CTX_new ((SSL_METHOD *) meth);
|
||||
}
|
||||
~SSlStartup() {
|
||||
SSL_CTX_free (global_ssl_ctx);
|
||||
global_ssl_ctx = NULL;
|
||||
}
|
||||
|
||||
~SSlStartup()
|
||||
{
|
||||
SSL_CTX_free (global_ssl_ctx);
|
||||
global_ssl_ctx = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool isactive() { return global_ssl_ctx != NULL; };
|
||||
bool isactive() { return global_ssl_ctx != NULL; };
|
||||
};
|
||||
|
||||
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP_SSL : public Socket_IP
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_TCP_SSL : public Socket_IP {
|
||||
public:
|
||||
inline Socket_TCP_SSL(SOCKET);
|
||||
inline Socket_TCP_SSL() : _ssl(NULL) {}
|
||||
|
||||
inline Socket_TCP_SSL(SOCKET);
|
||||
inline Socket_TCP_SSL() : _ssl(NULL) {}
|
||||
virtual inline ~Socket_TCP_SSL()
|
||||
{
|
||||
CleanSslUp();
|
||||
}
|
||||
|
||||
virtual inline ~Socket_TCP_SSL()
|
||||
{
|
||||
CleanSslUp();
|
||||
}
|
||||
inline int SetNoDelay();
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
|
||||
inline int SetNoDelay();
|
||||
inline int SetLinger(int interval_seconds = 0);
|
||||
inline int DontLinger();
|
||||
inline int SetSendBufferSize(int insize);
|
||||
inline bool ActiveOpen(const Socket_Address &theaddress);
|
||||
inline int SendData(const char *data, int size);
|
||||
inline int RecvData(char *data, int size);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
|
||||
inline int SetSendBufferSize(int insize);
|
||||
inline bool ActiveOpen(const Socket_Address & theaddress);
|
||||
inline int SendData(const char * data, int size);
|
||||
inline int RecvData(char * data, int size);
|
||||
inline bool ErrorIs_WouldBlocking(int err);
|
||||
inline SSL *get_ssl() { return _ssl; };
|
||||
|
||||
inline SSL * get_ssl() { return _ssl; };
|
||||
inline void DetailErrorFormat(void);
|
||||
|
||||
inline void DetailErrorFormat(void);
|
||||
private:
|
||||
SSL* _ssl;
|
||||
SSL *_ssl;
|
||||
|
||||
void CleanSslUp()
|
||||
{
|
||||
if(_ssl != NULL)
|
||||
{
|
||||
SSL_shutdown(_ssl);
|
||||
SSL_free(_ssl);
|
||||
_ssl = NULL;
|
||||
}
|
||||
}
|
||||
void CleanSslUp() {
|
||||
if (_ssl != NULL) {
|
||||
SSL_shutdown(_ssl);
|
||||
SSL_free(_ssl);
|
||||
_ssl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -128,30 +116,31 @@ Socket_TCP_SSL(SOCKET sck) : ::Socket_IP(sck) {
|
|||
/**
|
||||
* Disable Nagle algorithm. Don't delay send to coalesce packets
|
||||
*/
|
||||
inline int Socket_TCP_SSL::SetNoDelay()
|
||||
{
|
||||
int nodel = 1;
|
||||
int ret1;
|
||||
ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *) & nodel, sizeof(nodel));
|
||||
inline int Socket_TCP_SSL::
|
||||
SetNoDelay() {
|
||||
int nodel = 1;
|
||||
int ret1;
|
||||
ret1 = setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (char *)&nodel, sizeof(nodel));
|
||||
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
|
||||
return ALL_OK;
|
||||
if (ret1 != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* will control the behavior of SO_LINGER for a TCP socket
|
||||
*/
|
||||
int Socket_TCP_SSL::SetLinger(int interval_seconds)
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP_SSL::
|
||||
SetLinger(int interval_seconds) {
|
||||
linger ll;
|
||||
ll.l_linger = interval_seconds;
|
||||
ll.l_onoff = 1;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger));
|
||||
if (ret1 != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -159,147 +148,150 @@ int Socket_TCP_SSL::SetLinger(int interval_seconds)
|
|||
* and free up OS resources. You may lose a stream if you use this flag and
|
||||
* do not negotiate the close at the application layer.
|
||||
*/
|
||||
int Socket_TCP_SSL::DontLinger()
|
||||
{
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *) & ll, sizeof(linger));
|
||||
if (ret1 != 0)
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP_SSL::
|
||||
DontLinger() {
|
||||
linger ll;
|
||||
ll.l_linger = 0;
|
||||
ll.l_onoff = 0;
|
||||
int ret1 = setsockopt(_socket, SOL_SOCKET, SO_LINGER, (const char *)&ll, sizeof(linger));
|
||||
if (ret1 != 0) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just like it sounds. Sets a buffered socket recv buffer size. This
|
||||
* function does not refuse ranges outside hard-coded OS limits
|
||||
*/
|
||||
int Socket_TCP_SSL::SetSendBufferSize(int insize)
|
||||
{
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int)))
|
||||
return BASIC_ERROR;
|
||||
return ALL_OK;
|
||||
int Socket_TCP_SSL::
|
||||
SetSendBufferSize(int insize) {
|
||||
if (setsockopt(_socket, (int) SOL_SOCKET, (int) SO_SNDBUF, (char *) &insize, sizeof(int))) {
|
||||
return BASIC_ERROR;
|
||||
}
|
||||
return ALL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will try and set the socket up for active open to a specified
|
||||
* address and port provided by the input parameter
|
||||
*/
|
||||
bool Socket_TCP_SSL::ActiveOpen(const Socket_Address & theaddress)
|
||||
{
|
||||
_socket = DO_NEWTCP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
* This function will try and set the socket up for active open to a specified
|
||||
* address and port provided by the input parameter
|
||||
*/
|
||||
bool Socket_TCP_SSL::
|
||||
ActiveOpen(const Socket_Address &theaddress) {
|
||||
_socket = DO_NEWTCP(theaddress.get_family());
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
if (DO_CONNECT(_socket, &theaddress.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
_ssl = SSL_new(global_ssl_ctx);
|
||||
if (_ssl == NULL) {
|
||||
return false;
|
||||
}
|
||||
SSL_set_fd(_ssl, (int)GetSocket());
|
||||
if (SSL_connect(_ssl) == -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
_ssl = SSL_new (global_ssl_ctx);
|
||||
if(_ssl == NULL)
|
||||
return false;
|
||||
SSL_set_fd (_ssl,(int)GetSocket() );
|
||||
if(SSL_connect(_ssl) == -1)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
// return SetSslUp();
|
||||
// return SetSslUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ok Lets Send the Data - if error 0 if socket closed for write or lengh is 0
|
||||
* + bytes writen ( May be smaller than requested)
|
||||
*/
|
||||
inline int Socket_TCP_SSL::SendData(const char * data, int size)
|
||||
{
|
||||
if(_ssl == NULL)
|
||||
return -1;
|
||||
inline int Socket_TCP_SSL::
|
||||
SendData(const char *data, int size) {
|
||||
if (_ssl == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ERR_clear_error();
|
||||
|
||||
return SSL_write(_ssl, data, size);
|
||||
return SSL_write(_ssl, data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data from the connection - if error 0 if socket closed for read or
|
||||
* length is 0 + bytes read ( May be smaller than requested)
|
||||
*/
|
||||
inline int Socket_TCP_SSL::RecvData(char * data, int len)
|
||||
{
|
||||
if(_ssl == NULL)
|
||||
return -1;
|
||||
inline int Socket_TCP_SSL::
|
||||
RecvData(char *data, int len) {
|
||||
if (_ssl == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
ERR_clear_error();
|
||||
|
||||
return SSL_read(_ssl, data, len);
|
||||
return SSL_read(_ssl, data, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is last error a blocking error ?? True is last error was a blocking error
|
||||
*/
|
||||
inline bool Socket_TCP_SSL::ErrorIs_WouldBlocking(int err)
|
||||
{
|
||||
if(_ssl == NULL || err >= 0)
|
||||
{
|
||||
nativenet_cat.warning()
|
||||
<< "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number "
|
||||
<< err << " or _ssl is NULL\n";
|
||||
return false;
|
||||
}
|
||||
inline bool Socket_TCP_SSL::
|
||||
ErrorIs_WouldBlocking(int err) {
|
||||
if (_ssl == NULL || err >= 0) {
|
||||
nativenet_cat.warning()
|
||||
<< "Socket_TCP_SSL::ErrorIs_WouldBlocking->Called With Error number "
|
||||
<< err << " or _ssl is NULL\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
int ssl_error_code = SSL_get_error(_ssl,err);
|
||||
bool answer = false;
|
||||
int ssl_error_code = SSL_get_error(_ssl,err);
|
||||
bool answer = false;
|
||||
|
||||
switch(ssl_error_code)
|
||||
{
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
switch(ssl_error_code) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
case SSL_ERROR_WANT_CONNECT:
|
||||
// case SSL_ERROR_WANT_ACCEPT:
|
||||
answer = true;
|
||||
break;
|
||||
answer = true;
|
||||
break;
|
||||
// hmm not sure we need this .. hmmmm
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if(GETERROR() == LOCAL_BLOCKING_ERROR)
|
||||
answer = true;
|
||||
else
|
||||
{
|
||||
DetailErrorFormat();
|
||||
case SSL_ERROR_SYSCALL:
|
||||
if(GETERROR() == LOCAL_BLOCKING_ERROR) {
|
||||
answer = true;
|
||||
} else {
|
||||
DetailErrorFormat();
|
||||
// LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error1
|
||||
// SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DetailErrorFormat();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DetailErrorFormat();
|
||||
// LOGWARNING("Socket_TCP_SSL::ErrorIs_WouldBlocking-> Not A blocking Error2
|
||||
// SSl_CODe=[%d] OS=[%d]",ssl_error_code,GETERROR());
|
||||
answer = false;
|
||||
break;
|
||||
}
|
||||
answer = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// ERR_clear_error();
|
||||
return answer;
|
||||
return answer;
|
||||
}
|
||||
|
||||
inline void Socket_TCP_SSL::DetailErrorFormat(void)
|
||||
{
|
||||
return; // turn on fir debuging
|
||||
inline void Socket_TCP_SSL::
|
||||
DetailErrorFormat(void) {
|
||||
return; // turn on for debuging
|
||||
|
||||
uint32_t l;
|
||||
char buf[256];
|
||||
char buf2[4096];
|
||||
const char *file,*data;
|
||||
int line,flags;
|
||||
uint32_t es;
|
||||
uint32_t l;
|
||||
char buf[256];
|
||||
char buf2[4096];
|
||||
const char *file,*data;
|
||||
int line,flags;
|
||||
uint32_t es;
|
||||
|
||||
es=CRYPTO_thread_id();
|
||||
while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
|
||||
{
|
||||
ERR_error_string_n(l, buf, sizeof( buf) );
|
||||
BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", (unsigned long) es, buf,file, line, (flags & ERR_TXT_STRING) ? data : "NoText");
|
||||
nativenet_cat.warning()
|
||||
<< "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n";
|
||||
}
|
||||
es = CRYPTO_thread_id();
|
||||
while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
|
||||
ERR_error_string_n(l, buf, sizeof(buf));
|
||||
BIO_snprintf(buf2, sizeof(buf2), "***%lu:%s:%s:%d:%s\n", (unsigned long) es, buf, file, line, (flags & ERR_TXT_STRING) ? data : "NoText");
|
||||
nativenet_cat.warning()
|
||||
<< "Socket_TCP_SSL::DetailErrorFormat->[" << buf2 << "]\n";
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_OPENSSL
|
||||
|
|
|
|||
|
|
@ -21,25 +21,22 @@
|
|||
* duplicates code from Socket_UDP_Outgoing, to avoid the problems of multiple
|
||||
* inheritance.
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP : public Socket_UDP_Incoming
|
||||
{
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP : public Socket_UDP_Incoming {
|
||||
public:
|
||||
PUBLISHED:
|
||||
inline Socket_UDP() { }
|
||||
inline Socket_UDP() {}
|
||||
|
||||
// use this interface for a tagreted UDP connection
|
||||
inline bool InitToAddress(const Socket_Address & address);
|
||||
// use this interface for a tagreted UDP connection
|
||||
inline bool InitToAddress(const Socket_Address &address);
|
||||
public:
|
||||
inline bool Send(const char * data, int len);
|
||||
inline bool Send(const char *data, int len);
|
||||
PUBLISHED:
|
||||
inline bool Send(const string &data);
|
||||
// use this interface for a none tagreted UDP connection
|
||||
inline bool InitNoAddress();
|
||||
inline bool Send(const string &data);
|
||||
public:
|
||||
inline bool SendTo(const char * data, int len, const Socket_Address & address);
|
||||
inline bool SendTo(const char *data, int len, const Socket_Address &address);
|
||||
PUBLISHED:
|
||||
inline bool SendTo(const string &data, const Socket_Address & address);
|
||||
inline bool SetToBroadCast();
|
||||
inline bool SendTo(const string &data, const Socket_Address &address);
|
||||
inline bool SetToBroadCast();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -58,72 +55,64 @@ public:
|
|||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
/**
|
||||
* Ask the OS to let us receive BROADCASt packets on this port..
|
||||
*/
|
||||
inline bool Socket_UDP::SetToBroadCast()
|
||||
{
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
/**
|
||||
* Ask the OS to let us receive broadcast packets on this port.
|
||||
*/
|
||||
inline bool Socket_UDP::
|
||||
SetToBroadCast() {
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the Socket to a Specified address
|
||||
* Connects the socket to a Specified address
|
||||
*/
|
||||
inline bool Socket_UDP::InitToAddress(const Socket_Address & address)
|
||||
{
|
||||
if (InitNoAddress() != true)
|
||||
return false;
|
||||
inline bool Socket_UDP::
|
||||
InitToAddress(const Socket_Address &address) {
|
||||
if (InitNoAddress() != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* This will set a udp up for targeted sends..
|
||||
*/
|
||||
inline bool Socket_UDP::InitNoAddress()
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to connected address
|
||||
*/
|
||||
inline bool Socket_UDP::Send(const char * data, int len)
|
||||
{
|
||||
inline bool Socket_UDP::
|
||||
Send(const char *data, int len) {
|
||||
return (DO_SOCKET_WRITE(_socket, data, len) == len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to connected address
|
||||
*/
|
||||
inline bool Socket_UDP::Send(const string &data)
|
||||
{
|
||||
inline bool Socket_UDP::
|
||||
Send(const string &data) {
|
||||
return Send(data.data(), data.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to specified address
|
||||
*/
|
||||
inline bool Socket_UDP::SendTo(const char * data, int len, const Socket_Address & address)
|
||||
{
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
inline bool Socket_UDP::
|
||||
SendTo(const char *data, int len, const Socket_Address &address) {
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to specified address
|
||||
*/
|
||||
inline bool Socket_UDP::SendTo(const string &data, const Socket_Address & address)
|
||||
{
|
||||
inline bool Socket_UDP::
|
||||
SendTo(const string &data, const Socket_Address &address) {
|
||||
return SendTo(data.data(), data.size(), address);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,21 +6,18 @@
|
|||
|
||||
/**
|
||||
* Base functionality for a UDP Reader
|
||||
*
|
||||
|
||||
*
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP
|
||||
{
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP_Incoming : public Socket_IP {
|
||||
PUBLISHED:
|
||||
inline Socket_UDP_Incoming() { }
|
||||
inline Socket_UDP_Incoming() {}
|
||||
|
||||
inline bool OpenForInput(const Socket_Address & address);
|
||||
inline bool OpenForInputMCast(const Socket_Address & address );
|
||||
inline bool GetPacket(char * data, int *max_len, Socket_Address & address);
|
||||
inline bool SendTo(const char * data, int len, const Socket_Address & address);
|
||||
inline bool InitNoAddress();
|
||||
inline bool SetToBroadCast();
|
||||
inline bool OpenForInput(unsigned short port);
|
||||
inline bool OpenForInput(const Socket_Address &address);
|
||||
inline bool OpenForInputMCast(const Socket_Address &address);
|
||||
inline bool GetPacket(char *data, int *max_len, Socket_Address &address);
|
||||
inline bool SendTo(const char *data, int len, const Socket_Address &address);
|
||||
inline bool InitNoAddress();
|
||||
inline bool SetToBroadCast();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -41,71 +38,123 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* Flips the OS bits that allow for brodcast packets to com in on this port
|
||||
*
|
||||
* Flips the OS bits that allow for brodcast packets to come in on this port.
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::SetToBroadCast()
|
||||
{
|
||||
int optval = 1;
|
||||
inline bool Socket_UDP_Incoming::
|
||||
SetToBroadCast() {
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Set this socket to work with out a bound external address..
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::InitNoAddress()
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
/**
|
||||
* Set this socket to work without a bound external address.
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::
|
||||
InitNoAddress() {
|
||||
Close();
|
||||
|
||||
if (support_ipv6) {
|
||||
// Create a socket supporting both IPv4 and IPv6.
|
||||
_socket = DO_NEWUDP(AF_INET6);
|
||||
SetV6Only(false);
|
||||
} else {
|
||||
_socket = DO_NEWUDP(AF_INET);
|
||||
}
|
||||
|
||||
return (_socket != BAD_SOCKET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a UDP socket listening on a port
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::OpenForInput(const Socket_Address & address)
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return ErrorClose();
|
||||
inline bool Socket_UDP_Incoming::
|
||||
OpenForInput(unsigned short port) {
|
||||
Close();
|
||||
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
Socket_Address address;
|
||||
if (support_ipv6) {
|
||||
// Create a socket supporting both IPv4 and IPv6.
|
||||
address.set_any_IPv6(port);
|
||||
_socket = DO_NEWUDP(AF_INET6);
|
||||
SetV6Only(false);
|
||||
} else {
|
||||
address.set_any_IP(port);
|
||||
_socket = DO_NEWUDP(AF_INET);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a UDP socket listening on a port
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::OpenForInputMCast(const Socket_Address & address)
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return ErrorClose();
|
||||
inline bool Socket_UDP_Incoming::
|
||||
OpenForInput(const Socket_Address &address) {
|
||||
Close();
|
||||
_socket = DO_NEWUDP(address.get_family());
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
Socket_Address wa1(address.get_port());
|
||||
if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
if (DO_BIND(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
struct ip_mreq imreq;
|
||||
memset(&imreq,0,sizeof(imreq));
|
||||
imreq.imr_multiaddr.s_addr = address.GetAddressInfo().sin_addr.s_addr;
|
||||
imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface
|
||||
return true;
|
||||
}
|
||||
|
||||
int status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(const char *)&imreq, sizeof(struct ip_mreq));
|
||||
/**
|
||||
* Starts a UDP socket listening on a port
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::
|
||||
OpenForInputMCast(const Socket_Address &address) {
|
||||
Close();
|
||||
_socket = DO_NEWUDP(address.get_family());
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
if(status != 0)
|
||||
return false;
|
||||
return true;
|
||||
Socket_Address wa1(address.get_port());
|
||||
if (DO_BIND(_socket, &wa1.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
int status = -1;
|
||||
|
||||
const sockaddr *addr = &address.GetAddressInfo();
|
||||
if (addr->sa_family == AF_INET) {
|
||||
struct ip_mreq imreq;
|
||||
memset(&imreq, 0, sizeof(imreq));
|
||||
imreq.imr_multiaddr.s_addr = ((sockaddr_in*)addr)->sin_addr.s_addr;
|
||||
imreq.imr_interface.s_addr = INADDR_ANY; // use DEFAULT interface
|
||||
|
||||
status = setsockopt(GetSocket(), IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(const char *)&imreq, sizeof(imreq));
|
||||
|
||||
} else if (addr->sa_family == AF_INET6) {
|
||||
struct ipv6_mreq imreq;
|
||||
memcpy(&imreq.ipv6mr_multiaddr,
|
||||
&(((struct sockaddr_in6 *)addr)->sin6_addr),
|
||||
sizeof(struct in6_addr));
|
||||
imreq.ipv6mr_interface = 0; // use DEFAULT interface
|
||||
|
||||
status = setsockopt(GetSocket(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
|
||||
(const char *)&imreq, sizeof(imreq));
|
||||
}
|
||||
|
||||
return (status == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -113,30 +162,28 @@ inline bool Socket_UDP_Incoming::OpenForInputMCast(const Socket_Address & addres
|
|||
* address information
|
||||
*
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::GetPacket(char * data, int *max_len, Socket_Address & address)
|
||||
{
|
||||
int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo());
|
||||
*max_len = 0;
|
||||
inline bool Socket_UDP_Incoming::
|
||||
GetPacket(char *data, int *max_len, Socket_Address &address) {
|
||||
int val = DO_RECV_FROM(_socket, data, *max_len, &address.GetAddressInfo());
|
||||
*max_len = 0;
|
||||
|
||||
if (val <= 0)
|
||||
{
|
||||
if (GetLastError() != LOCAL_BLOCKING_ERROR) // im treating a blocking error as a 0 lenght read
|
||||
return false;
|
||||
} else
|
||||
*max_len = val;
|
||||
if (val <= 0) {
|
||||
if (GetLastError() != LOCAL_BLOCKING_ERROR) { // im treating a blocking error as a 0 lenght read
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*max_len = val;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to specified address
|
||||
*/
|
||||
inline bool Socket_UDP_Incoming::SendTo(const char * data, int len, const Socket_Address & address)
|
||||
{
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
inline bool Socket_UDP_Incoming::
|
||||
SendTo(const char *data, int len, const Socket_Address &address) {
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //__SOCKET_UDP_INCOMING_H__
|
||||
|
|
|
|||
|
|
@ -5,30 +5,25 @@
|
|||
#include "socket_ip.h"
|
||||
|
||||
/**
|
||||
* Base functionality for a UDP Sending Socket
|
||||
*
|
||||
|
||||
*
|
||||
* Base functionality for a UDP sending socket
|
||||
*/
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP_Outgoing : public Socket_IP
|
||||
{
|
||||
public:
|
||||
class EXPCL_PANDA_NATIVENET Socket_UDP_Outgoing : public Socket_IP {
|
||||
PUBLISHED:
|
||||
inline Socket_UDP_Outgoing() { }
|
||||
inline Socket_UDP_Outgoing() {}
|
||||
|
||||
// use this interface for a tagreted UDP connection
|
||||
inline bool InitToAddress(const Socket_Address & address);
|
||||
// use this interface for a tagreted UDP connection
|
||||
inline bool InitToAddress(const Socket_Address &address);
|
||||
public:
|
||||
inline bool Send(const char * data, int len);
|
||||
inline bool Send(const char *data, int len);
|
||||
PUBLISHED:
|
||||
inline bool Send(const string &data);
|
||||
// use this interface for a none tagreted UDP connection
|
||||
inline bool InitNoAddress();
|
||||
inline bool Send(const string &data);
|
||||
// use this interface for a none tagreted UDP connection
|
||||
inline bool InitNoAddress();
|
||||
public:
|
||||
inline bool SendTo(const char * data, int len, const Socket_Address & address);
|
||||
inline bool SendTo(const char *data, int len, const Socket_Address &address);
|
||||
PUBLISHED:
|
||||
inline bool SendTo(const string &data, const Socket_Address & address);
|
||||
inline bool SetToBroadCast();
|
||||
inline bool SendTo(const string &data, const Socket_Address &address);
|
||||
inline bool SetToBroadCast();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -47,72 +42,79 @@ public:
|
|||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
/**
|
||||
* Ask the OS to let us receive BROADCASt packets on this port..
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::SetToBroadCast()
|
||||
{
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
/**
|
||||
* Ask the OS to let us receive broadcast packets on this port.
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
SetToBroadCast() {
|
||||
int optval = 1;
|
||||
|
||||
if (setsockopt(_socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the Socket to a Specified address
|
||||
* Connects the Socket to a specified address
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::InitToAddress(const Socket_Address & address)
|
||||
{
|
||||
if (InitNoAddress() != true)
|
||||
return false;
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
InitToAddress(const Socket_Address &address) {
|
||||
if (InitNoAddress() != true) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0)
|
||||
return ErrorClose();
|
||||
if (DO_CONNECT(_socket, &address.GetAddressInfo()) != 0) {
|
||||
return ErrorClose();
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* This will set a udp up for targeted sends..
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::InitNoAddress()
|
||||
{
|
||||
Close();
|
||||
_socket = DO_NEWUDP();
|
||||
if (_socket == BAD_SOCKET)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
/**
|
||||
* This will set a udp up for targeted sends.
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
InitNoAddress() {
|
||||
Close();
|
||||
_socket = DO_NEWUDP(AF_INET);
|
||||
if (_socket == BAD_SOCKET) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to connected address
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::Send(const char * data, int len)
|
||||
{
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
Send(const char *data, int len) {
|
||||
return (DO_SOCKET_WRITE(_socket, data, len) == len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to connected address
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::Send(const string &data)
|
||||
{
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
Send(const string &data) {
|
||||
return Send(data.data(), data.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to specified address
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::SendTo(const char * data, int len, const Socket_Address & address)
|
||||
{
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
SendTo(const char *data, int len, const Socket_Address &address) {
|
||||
return (DO_SOCKET_WRITE_TO(_socket, data, len, &address.GetAddressInfo()) == len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to specified address
|
||||
*/
|
||||
inline bool Socket_UDP_Outgoing::SendTo(const string &data, const Socket_Address & address)
|
||||
{
|
||||
inline bool Socket_UDP_Outgoing::
|
||||
SendTo(const string &data, const Socket_Address &address) {
|
||||
return SendTo(data.data(), data.size(), address);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ process_incoming_data(SocketInfo *sinfo) {
|
|||
|
||||
NetAddress net_addr(addr);
|
||||
net_cat.info()
|
||||
<< "Received TCP connection from client " << net_addr.get_ip_string()
|
||||
<< "Received TCP connection from client " << net_addr
|
||||
<< " on port " << sinfo->_connection->get_address().get_port()
|
||||
<< "\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ ConnectionManager::
|
|||
* communication.
|
||||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_UDP_connection(int port) {
|
||||
open_UDP_connection(uint16_t port) {
|
||||
return open_UDP_connection("", port);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +80,8 @@ open_UDP_connection(int port) {
|
|||
* sending.
|
||||
*
|
||||
* This variant accepts both a hostname and port to listen on a particular
|
||||
* interface; if the hostname is empty, all interfaces will be available.
|
||||
* interface; if the hostname is empty, all interfaces will be available,
|
||||
* both IPv4 and IPv6.
|
||||
*
|
||||
* If for_broadcast is true, this UDP connection will be configured to send
|
||||
* and/or receive messages on the broadcast address (255.255.255.255);
|
||||
|
|
@ -90,24 +91,27 @@ open_UDP_connection(int port) {
|
|||
* communication.
|
||||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_UDP_connection(const string &hostname, int port, bool for_broadcast) {
|
||||
open_UDP_connection(const string &hostname, uint16_t port, bool for_broadcast) {
|
||||
Socket_UDP *socket = new Socket_UDP;
|
||||
|
||||
if (port > 0) {
|
||||
bool okflag;
|
||||
NetAddress address;
|
||||
if (hostname.empty()) {
|
||||
address.set_any(port);
|
||||
// The empty string means to listen on both IPv4 and IPv6 interfaces.
|
||||
okflag = socket->OpenForInput(port);
|
||||
} else {
|
||||
address.set_host(hostname, port);
|
||||
okflag = socket->OpenForInput(address.get_addr());
|
||||
}
|
||||
|
||||
if (!socket->OpenForInput(address.get_addr())) {
|
||||
if (!okflag) {
|
||||
if (hostname.empty()) {
|
||||
net_cat.error()
|
||||
<< "Unable to bind to port " << port << " for UDP.\n";
|
||||
} else {
|
||||
net_cat.error()
|
||||
<< "Unable to bind to " << hostname << ":" << port << " for UDP.\n";
|
||||
<< "Unable to bind to " << address << " for UDP.\n";
|
||||
}
|
||||
delete socket;
|
||||
return PT(Connection)();
|
||||
|
|
@ -124,7 +128,7 @@ open_UDP_connection(const string &hostname, int port, bool for_broadcast) {
|
|||
<< "Creating UDP " << broadcast_note << "connection for port " << port << "\n";
|
||||
} else {
|
||||
net_cat.info()
|
||||
<< "Creating UDP " << broadcast_note << "connection for " << hostname << ":" << port << "\n";
|
||||
<< "Creating UDP " << broadcast_note << "connection for " << address << "\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -150,23 +154,32 @@ open_UDP_connection(const string &hostname, int port, bool for_broadcast) {
|
|||
return connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates a socket to be used as a rendezvous socket for a server to listen
|
||||
* for TCP connections. The socket returned by this call should only be added
|
||||
* to a ConnectionListener (not to a generic ConnectionReader).
|
||||
*
|
||||
* This variant of this method accepts a single port, and will listen to that
|
||||
* port on all available interfaces.
|
||||
* port on all available interfaces, both IPv4 and IPv6.
|
||||
*
|
||||
* backlog is the maximum length of the queue of pending connections.
|
||||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_TCP_server_rendezvous(int port, int backlog) {
|
||||
NetAddress address;
|
||||
address.set_any(port);
|
||||
return open_TCP_server_rendezvous(address, backlog);
|
||||
open_TCP_server_rendezvous(uint16_t port, int backlog) {
|
||||
Socket_TCP_Listen *socket = new Socket_TCP_Listen;
|
||||
if (!socket->OpenForListen(port, backlog)) {
|
||||
net_cat.info()
|
||||
<< "Unable to listen to port " << port << " for TCP.\n";
|
||||
delete socket;
|
||||
return PT(Connection)();
|
||||
}
|
||||
|
||||
net_cat.info()
|
||||
<< "Listening for TCP connections on port " << port << "\n";
|
||||
|
||||
PT(Connection) connection = new Connection(this, socket);
|
||||
new_connection(connection);
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -182,14 +195,14 @@ open_TCP_server_rendezvous(int port, int backlog) {
|
|||
* backlog is the maximum length of the queue of pending connections.
|
||||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_TCP_server_rendezvous(const string &hostname, int port, int backlog) {
|
||||
NetAddress address;
|
||||
open_TCP_server_rendezvous(const string &hostname, uint16_t port, int backlog) {
|
||||
if (hostname.empty()) {
|
||||
address.set_any(port);
|
||||
return open_TCP_server_rendezvous(port, backlog);
|
||||
} else {
|
||||
NetAddress address;
|
||||
address.set_host(hostname, port);
|
||||
return open_TCP_server_rendezvous(address, backlog);
|
||||
}
|
||||
return open_TCP_server_rendezvous(address, backlog);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -204,24 +217,16 @@ open_TCP_server_rendezvous(const string &hostname, int port, int backlog) {
|
|||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_TCP_server_rendezvous(const NetAddress &address, int backlog) {
|
||||
ostringstream strm;
|
||||
if (address.get_ip() == 0) {
|
||||
strm << "port " << address.get_port();
|
||||
} else {
|
||||
strm << address.get_ip_string() << ":" << address.get_port();
|
||||
}
|
||||
|
||||
Socket_TCP_Listen *socket = new Socket_TCP_Listen;
|
||||
bool okflag = socket->OpenForListen(address.get_addr(), backlog);
|
||||
if (!okflag) {
|
||||
if (!socket->OpenForListen(address.get_addr(), backlog)) {
|
||||
net_cat.info()
|
||||
<< "Unable to listen to " << strm.str() << " for TCP.\n";
|
||||
<< "Unable to listen to " << address << " for TCP.\n";
|
||||
delete socket;
|
||||
return PT(Connection)();
|
||||
}
|
||||
|
||||
net_cat.info()
|
||||
<< "Listening for TCP connections on " << strm.str() << "\n";
|
||||
<< "Listening for TCP connections on " << address << "\n";
|
||||
|
||||
PT(Connection) connection = new Connection(this, socket);
|
||||
new_connection(connection);
|
||||
|
|
@ -263,7 +268,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
|
|||
|
||||
if (okflag) {
|
||||
// So, the connect() operation finished, but did it succeed or fail?
|
||||
if (socket->GetPeerName().GetIPAddressRaw() == 0) {
|
||||
if (socket->GetPeerName().is_any()) {
|
||||
// No peer means it failed.
|
||||
okflag = false;
|
||||
}
|
||||
|
|
@ -271,8 +276,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
|
|||
|
||||
if (!okflag) {
|
||||
net_cat.error()
|
||||
<< "Unable to open TCP connection to server "
|
||||
<< address.get_ip_string() << " on port " << address.get_port() << "\n";
|
||||
<< "Unable to open TCP connection to server " << address << "\n";
|
||||
delete socket;
|
||||
return PT(Connection)();
|
||||
}
|
||||
|
|
@ -286,8 +290,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
|
|||
#endif // SIMPLE_THREADS
|
||||
|
||||
net_cat.info()
|
||||
<< "Opened TCP connection to server " << address.get_ip_string()
|
||||
<< " on port " << address.get_port() << "\n";
|
||||
<< "Opened TCP connection to server " << address << "\n";
|
||||
|
||||
PT(Connection) connection = new Connection(this, socket);
|
||||
new_connection(connection);
|
||||
|
|
@ -299,7 +302,7 @@ open_TCP_client_connection(const NetAddress &address, int timeout_ms) {
|
|||
* communications to a named host and port.
|
||||
*/
|
||||
PT(Connection) ConnectionManager::
|
||||
open_TCP_client_connection(const string &hostname, int port,
|
||||
open_TCP_client_connection(const string &hostname, uint16_t port,
|
||||
int timeout_ms) {
|
||||
NetAddress address;
|
||||
if (!address.set_host(hostname, port)) {
|
||||
|
|
@ -474,11 +477,12 @@ scan_interfaces() {
|
|||
|
||||
#ifdef WIN32_VC
|
||||
int flags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_SKIP_UNICAST | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
|
||||
ULONG family = support_ipv6 ? AF_UNSPEC : AF_INET;
|
||||
ULONG buffer_size = 0;
|
||||
ULONG result = GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &buffer_size);
|
||||
ULONG result = GetAdaptersAddresses(family, flags, NULL, NULL, &buffer_size);
|
||||
if (result == ERROR_BUFFER_OVERFLOW) {
|
||||
IP_ADAPTER_ADDRESSES *addresses = (IP_ADAPTER_ADDRESSES *)PANDA_MALLOC_ARRAY(buffer_size);
|
||||
result = GetAdaptersAddresses(AF_INET, flags, NULL, addresses, &buffer_size);
|
||||
result = GetAdaptersAddresses(family, flags, NULL, addresses, &buffer_size);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
IP_ADAPTER_ADDRESSES *p = addresses;
|
||||
while (p != NULL) {
|
||||
|
|
@ -502,7 +506,7 @@ scan_interfaces() {
|
|||
IP_ADAPTER_PREFIX *m = p->FirstPrefix;
|
||||
int mc = 0;
|
||||
while (m != NULL && mc < 3) {
|
||||
addresses[mc] = NetAddress(Socket_Address(*(sockaddr_in *)m->Address.lpSockaddr));
|
||||
addresses[mc] = NetAddress(Socket_Address(*m->Address.lpSockaddr));
|
||||
m = m->Next;
|
||||
++mc;
|
||||
}
|
||||
|
|
@ -517,10 +521,13 @@ scan_interfaces() {
|
|||
// Now, we can infer the netmask by the difference between the
|
||||
// network address (the first address) and the broadcast address
|
||||
// (the last address).
|
||||
uint32_t netmask = addresses[0].get_ip() - addresses[2].get_ip() - 1;
|
||||
Socket_Address sa;
|
||||
sa.set_host(netmask, 0);
|
||||
iface.set_netmask(NetAddress(sa));
|
||||
if (addresses[0].get_addr().get_family() == AF_INET &&
|
||||
addresses[2].get_addr().get_family() == AF_INET) {
|
||||
uint32_t netmask = addresses[0].get_ip() - addresses[2].get_ip() - 1;
|
||||
Socket_Address sa;
|
||||
sa.set_host(netmask, 0);
|
||||
iface.set_netmask(NetAddress(sa));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -545,19 +552,20 @@ scan_interfaces() {
|
|||
|
||||
struct ifaddrs *p = ifa;
|
||||
while (p != NULL) {
|
||||
if (p->ifa_addr->sa_family == AF_INET) {
|
||||
if (p->ifa_addr->sa_family == AF_INET ||
|
||||
(support_ipv6 && p->ifa_addr->sa_family == AF_INET6)) {
|
||||
Interface iface;
|
||||
iface.set_name(p->ifa_name);
|
||||
if (p->ifa_addr != NULL) {
|
||||
iface.set_ip(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_addr)));
|
||||
iface.set_ip(NetAddress(Socket_Address(*p->ifa_addr)));
|
||||
}
|
||||
if (p->ifa_netmask != NULL) {
|
||||
iface.set_netmask(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_netmask)));
|
||||
iface.set_netmask(NetAddress(Socket_Address(*p->ifa_netmask)));
|
||||
}
|
||||
if ((p->ifa_flags & IFF_BROADCAST) && p->ifa_broadaddr != NULL) {
|
||||
iface.set_broadcast(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_broadaddr)));
|
||||
iface.set_broadcast(NetAddress(Socket_Address(*p->ifa_broadaddr)));
|
||||
} else if ((p->ifa_flags & IFF_POINTOPOINT) && p->ifa_dstaddr != NULL) {
|
||||
iface.set_p2p(NetAddress(Socket_Address(*(sockaddr_in *)p->ifa_dstaddr)));
|
||||
iface.set_p2p(NetAddress(Socket_Address(*p->ifa_dstaddr)));
|
||||
}
|
||||
_interfaces.push_back(iface);
|
||||
}
|
||||
|
|
@ -572,10 +580,9 @@ scan_interfaces() {
|
|||
|
||||
/**
|
||||
* This returns the number of usable network interfaces detected on this
|
||||
* machine. (Currently, only IPv4 interfaces are reported.) See
|
||||
* scan_interfaces() to repopulate this list.
|
||||
* machine. See scan_interfaces() to repopulate this list.
|
||||
*/
|
||||
int ConnectionManager::
|
||||
size_t ConnectionManager::
|
||||
get_num_interfaces() {
|
||||
if (!_interfaces_scanned) {
|
||||
scan_interfaces();
|
||||
|
|
@ -586,16 +593,15 @@ get_num_interfaces() {
|
|||
|
||||
/**
|
||||
* Returns the nth usable network interface detected on this machine.
|
||||
* (Currently, only IPv4 interfaces are reported.) See scan_interfaces() to
|
||||
* repopulate this list.
|
||||
* See scan_interfaces() to repopulate this list.
|
||||
*/
|
||||
const ConnectionManager::Interface &ConnectionManager::
|
||||
get_interface(int n) {
|
||||
get_interface(size_t n) {
|
||||
if (!_interfaces_scanned) {
|
||||
scan_interfaces();
|
||||
}
|
||||
LightMutexHolder holder(_set_mutex);
|
||||
nassertr(n >= 0 && n < (int)_interfaces.size(), _interfaces[0]);
|
||||
nassertr(n < _interfaces.size(), _interfaces[0]);
|
||||
return _interfaces[n];
|
||||
}
|
||||
|
||||
|
|
@ -709,9 +715,9 @@ remove_writer(ConnectionWriter *writer) {
|
|||
* Formats a device's MAC address into a string.
|
||||
*/
|
||||
string ConnectionManager::
|
||||
format_mac_address(const unsigned char *data, int data_size) {
|
||||
format_mac_address(const unsigned char *data, size_t data_size) {
|
||||
stringstream strm;
|
||||
for (int di = 0; di < data_size; ++di) {
|
||||
for (size_t di = 0; di < data_size; ++di) {
|
||||
if (di != 0) {
|
||||
strm << "-";
|
||||
}
|
||||
|
|
@ -728,16 +734,16 @@ void ConnectionManager::Interface::
|
|||
output(ostream &out) const {
|
||||
out << get_name() << " [";
|
||||
if (has_ip()) {
|
||||
out << " " << get_ip();
|
||||
out << " " << get_ip().get_ip_string();
|
||||
}
|
||||
if (has_netmask()) {
|
||||
out << " netmask " << get_netmask();
|
||||
out << " netmask " << get_netmask().get_ip_string();
|
||||
}
|
||||
if (has_broadcast()) {
|
||||
out << " broadcast " << get_broadcast();
|
||||
out << " broadcast " << get_broadcast().get_ip_string();
|
||||
}
|
||||
if (has_p2p()) {
|
||||
out << " p2p " << get_p2p();
|
||||
out << " p2p " << get_p2p().get_ip_string();
|
||||
}
|
||||
out << " ]";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,18 +43,18 @@ PUBLISHED:
|
|||
ConnectionManager();
|
||||
virtual ~ConnectionManager();
|
||||
|
||||
PT(Connection) open_UDP_connection(int port = 0);
|
||||
PT(Connection) open_UDP_connection(const string &hostname, int port, bool for_broadcast = false);
|
||||
PT(Connection) open_UDP_connection(uint16_t port = 0);
|
||||
PT(Connection) open_UDP_connection(const string &hostname, uint16_t port, bool for_broadcast = false);
|
||||
|
||||
BLOCKING PT(Connection) open_TCP_server_rendezvous(int port, int backlog);
|
||||
BLOCKING PT(Connection) open_TCP_server_rendezvous(uint16_t port, int backlog);
|
||||
BLOCKING PT(Connection) open_TCP_server_rendezvous(const string &hostname,
|
||||
int port, int backlog);
|
||||
uint16_t port, int backlog);
|
||||
BLOCKING PT(Connection) open_TCP_server_rendezvous(const NetAddress &address,
|
||||
int backlog);
|
||||
BLOCKING PT(Connection) open_TCP_client_connection(const NetAddress &address,
|
||||
int timeout_ms);
|
||||
BLOCKING PT(Connection) open_TCP_client_connection(const string &hostname, int port,
|
||||
int timeout_ms);
|
||||
BLOCKING PT(Connection) open_TCP_client_connection(const string &hostname,
|
||||
uint16_t port, int timeout_ms);
|
||||
|
||||
bool close_connection(const PT(Connection) &connection);
|
||||
BLOCKING bool wait_for_readers(double timeout);
|
||||
|
|
@ -104,8 +104,8 @@ PUBLISHED:
|
|||
};
|
||||
|
||||
void scan_interfaces();
|
||||
int get_num_interfaces();
|
||||
const Interface &get_interface(int n);
|
||||
size_t get_num_interfaces();
|
||||
const Interface &get_interface(size_t n);
|
||||
MAKE_SEQ(get_interfaces, get_num_interfaces, get_interface);
|
||||
|
||||
MAKE_PROPERTY(host_name, get_host_name);
|
||||
|
|
@ -122,7 +122,7 @@ protected:
|
|||
void add_writer(ConnectionWriter *writer);
|
||||
void remove_writer(ConnectionWriter *writer);
|
||||
|
||||
string format_mac_address(const unsigned char *data, int data_size);
|
||||
string format_mac_address(const unsigned char *data, size_t data_size);
|
||||
|
||||
typedef phash_set< PT(Connection) > Connections;
|
||||
typedef phash_set<ConnectionReader *, pointer_hash> Readers;
|
||||
|
|
|
|||
|
|
@ -91,6 +91,14 @@ set_port(int port) {
|
|||
_addr.set_port(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the IP address has only zeroes.
|
||||
*/
|
||||
bool NetAddress::
|
||||
is_any() const {
|
||||
return _addr.is_any();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP address to which this address refers, formatted as a string.
|
||||
*/
|
||||
|
|
@ -102,6 +110,7 @@ get_ip_string() const {
|
|||
/**
|
||||
* Returns the IP address to which this address refers, as a 32-bit integer,
|
||||
* in host byte order.
|
||||
* @deprecated Does not work with IPv6 addresses.
|
||||
*/
|
||||
uint32_t NetAddress::
|
||||
get_ip() const {
|
||||
|
|
@ -135,7 +144,7 @@ get_addr() const {
|
|||
*/
|
||||
void NetAddress::
|
||||
output(ostream &out) const {
|
||||
out << get_ip_string();
|
||||
out << _addr.get_ip_port();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ PUBLISHED:
|
|||
int get_port() const;
|
||||
void set_port(int port);
|
||||
string get_ip_string() const;
|
||||
bool is_any() const;
|
||||
uint32_t get_ip() const;
|
||||
uint8_t get_ip_component(int n) const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue