diff options
Diffstat (limited to 'src/3rd_party-static/message_broker/src/server/networking.cpp')
-rw-r--r-- | src/3rd_party-static/message_broker/src/server/networking.cpp | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/src/3rd_party-static/message_broker/src/server/networking.cpp b/src/3rd_party-static/message_broker/src/server/networking.cpp new file mode 100644 index 0000000000..f054431690 --- /dev/null +++ b/src/3rd_party-static/message_broker/src/server/networking.cpp @@ -0,0 +1,189 @@ +/* + * JsonRpc-Cpp - JSON-RPC implementation. + * Copyright (C) 2008-2011 Sebastien Vincent <sebastien.vincent@cppextrem.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * \file networking.cpp + * \brief Networking utils. + * \author Sebastien Vincent + */ + +#include <cstdio> +#include <cstring> + +#include "networking.h" + +namespace networking { +#ifdef _WIN32 +/** + * \var wsaData + * \brief MS Windows object to start + * networking stuff. + */ +static WSAData wsaData; +#endif + +bool init() { + bool ret = false; + +#ifdef _WIN32 + ret = (WSAStartup(MAKEWORD(2, 0), &wsaData) == 0); +#else + /* unix-like */ + ret = true; +#endif + + return ret; +} + +void cleanup() { +#ifdef _WIN32 + WSACleanup(); +#endif +} + +int connect(enum TransportProtocol protocol, + const std::string& address, + uint16_t port, struct sockaddr_storage* sockaddr, + socklen_t* addrlen) { + struct addrinfo hints; + struct addrinfo* res = NULL; + struct addrinfo* p = NULL; + char service[8]; + int sock = -1; + + if (!port || address == "") { + return -1; + } + + snprintf(service, sizeof(service), "%u", port); + service[sizeof(service) - 1] = 0x00; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = protocol == UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = protocol; + hints.ai_flags = 0; + + if (getaddrinfo(address.c_str(), + service, &hints, &res) != 0) { + return -1; + } + + for (p = res ; p ; p = p->ai_next) { + sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + + if (sock == -1) { + continue; + } + + if (protocol == TCP && ::connect(sock, (struct sockaddr*)p->ai_addr, p->ai_addrlen) == -1) { + ::close(sock); + sock = -1; + continue; + } + + if (sockaddr) { + memcpy(sockaddr, p->ai_addr, p->ai_addrlen); + } + + if (addrlen) { + *addrlen = p->ai_addrlen; + } + + /* ok so now we have a socket bound, break the loop */ + break; + } + + freeaddrinfo(res); + p = NULL; + + return sock; +} + +int bind(enum TransportProtocol protocol, + const std::string& address, uint16_t port, + struct sockaddr_storage* sockaddr, socklen_t* addrlen) { + struct addrinfo hints; + struct addrinfo* res = NULL; + struct addrinfo* p = NULL; + char service[8]; + int sock = -1; + + if (!port || address == "") { + return -1; + } + + snprintf(service, sizeof(service), "%u", port); + service[sizeof(service) - 1] = 0x00; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = protocol == UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = protocol; + hints.ai_flags = AI_PASSIVE; + + if (getaddrinfo(address.c_str(), service, &hints, &res) != 0) { + return -1; + } + + for (p = res ; p ; p = p->ai_next) { + int on = 1; + on = on; + + sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + + if (sock == -1) { + continue; + } + +#ifndef _WIN32 + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)); + + /* accept IPv6 OR IPv4 on the same socket */ + on = 1; + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); +#else + on = 0; +#endif + + if (::bind(sock, p->ai_addr, p->ai_addrlen) == -1) { + ::close(sock); + sock = -1; + continue; + } + + if (sockaddr) { + memcpy(sockaddr, p->ai_addr, p->ai_addrlen); + } + + if (addrlen) { + *addrlen = p->ai_addrlen; + } + + /* ok so now we have a socket bound, break the loop */ + break; + } + + freeaddrinfo(res); + p = NULL; + + return sock; +} + +} /* namespace networking */ + |