From: Maxim Mamontov Date: Mon, 11 May 2015 16:25:41 +0000 (+0300) Subject: Introduced SGCP library. X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/a8690e044055da20e4cf7d7d7e51d182b5e09154?hp=1538d6276533140505fddb71c99a0bafe6ca9182 Introduced SGCP library. --- diff --git a/stglibs/sgcp.lib/Makefile b/stglibs/sgcp.lib/Makefile new file mode 100644 index 00000000..01ec3373 --- /dev/null +++ b/stglibs/sgcp.lib/Makefile @@ -0,0 +1,16 @@ +include ../../Makefile.conf + +LIB_NAME = stgsgcp + +SRCS = proto.cpp \ + transport.cpp \ + unix.cpp \ + udp.cpp \ + tcp.cpp \ + crypto.cpp + +INCS = sgcp_proto.h \ + sgcp_types.h \ + sgcp_transport.h + +include ../Makefile.in diff --git a/stglibs/sgcp.lib/crypto.cpp b/stglibs/sgcp.lib/crypto.cpp new file mode 100644 index 00000000..2b2bb8f3 --- /dev/null +++ b/stglibs/sgcp.lib/crypto.cpp @@ -0,0 +1,30 @@ +#include "crypto.h" + +using STG::SGCP::CryptoProto; + +CryptoProto::CryptoProto(const std::string& key, TransportProto* underlying) + : m_underlying(underlying) +{ +} + +CryptoProto::~CryptoProto() +{ + delete m_underlying; +} + +void CryptoProto::connect(const std::string& address, uint16_t port) +{ + m_underlying->connect(address, port); +} + +ssize_t CryptoProto::write(const void* buf, size_t size) +{ + // TODO: to implement + return m_underlying->write(buf, size); +} + +ssize_t CryptoProto::read(void* buf, size_t size) +{ + // TODO: to implement + return m_underlying->read(buf, size); +} diff --git a/stglibs/sgcp.lib/crypto.h b/stglibs/sgcp.lib/crypto.h new file mode 100644 index 00000000..5f720d04 --- /dev/null +++ b/stglibs/sgcp.lib/crypto.h @@ -0,0 +1,54 @@ +#ifndef __STG_SGCP_CRYPTO_H__ +#define __STG_SGCP_CRYPTO_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/sgcp_transport.h" + +#include "stg/os_int.h" + +#include + +#include // ssize_t + +namespace STG +{ +namespace SGCP +{ + +class CryptoProto : public TransportProto +{ + public: + CryptoProto(const std::string& key, TransportProto* underlying); + virtual ~CryptoProto(); + + virtual void connect(const std::string& address, uint16_t port); + virtual ssize_t write(const void* buf, size_t size); + virtual ssize_t read(void* buf, size_t size); + + private: + TransportProto* m_underlying; +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/include/stg/sgcp_proto.h b/stglibs/sgcp.lib/include/stg/sgcp_proto.h new file mode 100644 index 00000000..3cc35b19 --- /dev/null +++ b/stglibs/sgcp.lib/include/stg/sgcp_proto.h @@ -0,0 +1,108 @@ +#ifndef __STG_SGCP_PROTO_H__ +#define __STG_SGCP_PROTO_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "sgcp_types.h" // TransportType +#include "sgcp_utils.h" // hton/ntoh + +#include "stg/os_int.h" + +#include +#include +#include + +namespace STG +{ +namespace SGCP +{ + +class TransportProto; + +class Proto +{ + public: + struct Error : public std::runtime_error + { + Error(const std::string& mesage); + Error(); + }; + + Proto(TransportType transport, const std::string& key); + ~Proto(); + + void connect(const std::string& address, uint16_t port); + + void writeAllBuf(const void* buf, size_t size); + void readAllBuf(void* buf, size_t size); + + template + void writeAll(const T& value); + + template + T readAll(); + + private: + TransportProto* m_transport; +}; + +template <> +inline +void Proto::writeAll(const uint64_t& value) +{ + uint64_t temp = hton(value); + writeAllBuf(&temp, sizeof(temp)); +} + +template <> +inline +void Proto::writeAll(const std::string& value) +{ + uint64_t size = hton(value.size()); + writeAllBuf(&size, sizeof(size)); + writeAllBuf(value.c_str(), value.size()); +} + +template <> +inline +uint64_t Proto::readAll() +{ + uint64_t temp = 0; + readAllBuf(&temp, sizeof(temp)); + return ntoh(temp); +} + +template <> +inline +std::string Proto::readAll() +{ + uint64_t size = 0; + readAllBuf(&size, sizeof(size)); + size = ntoh(size); + std::vector res(size); + readAllBuf(res.data(), res.size()); + return res.data(); +} + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/include/stg/sgcp_transport.h b/stglibs/sgcp.lib/include/stg/sgcp_transport.h new file mode 100644 index 00000000..88a7d0c4 --- /dev/null +++ b/stglibs/sgcp.lib/include/stg/sgcp_transport.h @@ -0,0 +1,58 @@ +#ifndef __STG_SGCP_TRANSPORT_H__ +#define __STG_SGCP_TRANSPORT_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/sgcp_types.h" + +#include "stg/os_int.h" + +#include +#include + +#include // ssize_t + +namespace STG +{ +namespace SGCP +{ + +class TransportProto +{ + public: + struct Error : public std::runtime_error { + Error(const std::string& message) : runtime_error(message) {} + }; + + static TransportProto* create(TransportType transport, const std::string& key); + static TransportProto* create(TransportType transport); + + virtual ~TransportProto() {} + + virtual void connect(const std::string& address, uint16_t port) = 0; + virtual ssize_t write(const void* buf, size_t size) = 0; + virtual ssize_t read(void* buf, size_t size) = 0; +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/include/stg/sgcp_types.h b/stglibs/sgcp.lib/include/stg/sgcp_types.h new file mode 100644 index 00000000..47920077 --- /dev/null +++ b/stglibs/sgcp.lib/include/stg/sgcp_types.h @@ -0,0 +1,39 @@ +#ifndef __STG_SGCP_TYPES_H__ +#define __STG_SGCP_TYPES_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +namespace STG +{ +namespace SGCP +{ + +enum TransportType +{ + UNIX, + UDP, + TCP +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/include/stg/sgcp_utils.h b/stglibs/sgcp.lib/include/stg/sgcp_utils.h new file mode 100644 index 00000000..7e5004c1 --- /dev/null +++ b/stglibs/sgcp.lib/include/stg/sgcp_utils.h @@ -0,0 +1,67 @@ +#ifndef __STG_SGCP_UTILS_H__ +#define __STG_SGCP_UTILS_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/os_int.h" + +#include +#include + +#include // hton* +#include // in_addr + +namespace STG +{ +namespace SGCP +{ + +template inline T hton(T value) { return value; } +template inline T ntoh(T value) { return hton(value); } + +template <> inline uint16_t hton(uint16_t value) { return htons(value); } +template <> inline int16_t hton(int16_t value) { return htons(value); } + +template <> inline uint32_t hton(uint32_t value) { return htonl(value); } +template <> inline int32_t hton(int32_t value) { return htonl(value); } + +inline +uint64_t htonll(uint64_t value) +{ +#ifdef ARCH_LE + const uint32_t high_part = htonl(static_cast(value >> 32)); + const uint32_t low_part = htonl(static_cast(value & 0xFFFFFFFFLL)); + + return (static_cast(low_part) << 32) | high_part; +#else + return value; +#endif +} + +template <> inline uint64_t hton(uint64_t value) { return htonll(value); } +template <> inline int64_t hton(int64_t value) { return htonll(value); } + +std::vector resolve(const std::string& address); + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/proto.cpp b/stglibs/sgcp.lib/proto.cpp new file mode 100644 index 00000000..96b6285b --- /dev/null +++ b/stglibs/sgcp.lib/proto.cpp @@ -0,0 +1,63 @@ +#include "stg/sgcp_proto.h" + +#include "stg/sgcp_transport.h" + +#include +#include + +using STG::SGCP::Proto; + +Proto::Error::Error(const std::string& message) + : runtime_error(message) +{} + +Proto::Error::Error() + : runtime_error(strerror(errno)) +{} + +Proto::Proto(TransportType transport, const std::string& key) + : m_transport(TransportProto::create(transport, key)) +{ +} + +Proto::~Proto() +{ + delete m_transport; +} + +void Proto::connect(const std::string& address, uint16_t port) +{ + try { + m_transport->connect(address, port); + } catch (const TransportProto::Error& ex) { + throw Error(ex.what()); + } +} + +void Proto::writeAllBuf(const void* buf, size_t size) +{ + const char* pos = static_cast(buf); + while (size > 0) { + ssize_t res = m_transport->write(pos, size); + if (res < 0) + throw Error(); + if (res == 0) + return; + size -= res; + pos += res; + } +} + +void Proto::readAllBuf(void* buf, size_t size) +{ + char* pos = static_cast(buf); + while (size > 0) { + ssize_t res = m_transport->read(pos, size); + if (res < 0) + throw Error(); + if (res == 0) + return; + size -= res; + pos += res; + } +} diff --git a/stglibs/sgcp.lib/tcp.cpp b/stglibs/sgcp.lib/tcp.cpp new file mode 100644 index 00000000..414d5ec8 --- /dev/null +++ b/stglibs/sgcp.lib/tcp.cpp @@ -0,0 +1,52 @@ +#include "tcp.h" + +#include "stg/sgcp_utils.h" + +#include +#include + +#include +#include +#include +#include + +using STG::SGCP::TCPProto; + +TCPProto::TCPProto() + : m_sock(socket(AF_INET, SOCK_STREAM, 0)) +{ +} + +TCPProto::~TCPProto() +{ + close(m_sock); +} + +void TCPProto::connect(const std::string& address, uint16_t port) +{ + std::vector addrs = resolve(address); + + for (size_t i = 0; i < addrs.size(); ++i) { + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = hton(port); + addr.sin_addr = addrs[i]; + + if (::connect(m_sock, reinterpret_cast(&addr), sizeof(addr)) == 0) + return; + + close(m_sock); + m_sock = socket(AF_INET, SOCK_STREAM, 0); + } + throw Error("No more addresses to connect to."); +} + +ssize_t TCPProto::write(const void* buf, size_t size) +{ + return ::write(m_sock, buf, size); +} + +ssize_t TCPProto::read(void* buf, size_t size) +{ + return ::read(m_sock, buf, size); +} diff --git a/stglibs/sgcp.lib/tcp.h b/stglibs/sgcp.lib/tcp.h new file mode 100644 index 00000000..8afa0b5e --- /dev/null +++ b/stglibs/sgcp.lib/tcp.h @@ -0,0 +1,54 @@ +#ifndef __STG_SGCP_TCP_H__ +#define __STG_SGCP_TCP_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/sgcp_transport.h" + +#include "stg/os_int.h" + +#include + +#include // ssize_t + +namespace STG +{ +namespace SGCP +{ + +class TCPProto : public TransportProto +{ + public: + TCPProto(); + virtual ~TCPProto(); + + virtual void connect(const std::string& address, uint16_t port); + virtual ssize_t write(const void* buf, size_t size); + virtual ssize_t read(void* buf, size_t size); + + private: + int m_sock; +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/transport.cpp b/stglibs/sgcp.lib/transport.cpp new file mode 100644 index 00000000..1e94fa58 --- /dev/null +++ b/stglibs/sgcp.lib/transport.cpp @@ -0,0 +1,27 @@ +#include "stg/sgcp_transport.h" + +#include "crypto.h" +#include "unix.h" +#include "udp.h" +#include "tcp.h" + +using STG::SGCP::TransportProto; + +TransportProto* TransportProto::create(TransportType transport, const std::string& key) +{ + TransportProto* underlying = create(transport); + if (key.empty()) + return underlying; + else + return new CryptoProto(key, underlying); +} + +TransportProto* TransportProto::create(TransportType transport) +{ + switch (transport) { + case UNIX: return new UnixProto; + case UDP: return new UDPProto; + case TCP: return new TCPProto; + }; + return NULL; +} diff --git a/stglibs/sgcp.lib/udp.cpp b/stglibs/sgcp.lib/udp.cpp new file mode 100644 index 00000000..ebbb98e6 --- /dev/null +++ b/stglibs/sgcp.lib/udp.cpp @@ -0,0 +1,52 @@ +#include "udp.h" + +#include "stg/sgcp_utils.h" + +#include +#include + +#include +#include +#include +#include + +using STG::SGCP::UDPProto; + +UDPProto::UDPProto() + : m_sock(socket(AF_INET, SOCK_DGRAM, 0)) +{ +} + +UDPProto::~UDPProto() +{ + close(m_sock); +} + +void UDPProto::connect(const std::string& address, uint16_t port) +{ + std::vector addrs = resolve(address); + + for (size_t i = 0; i < addrs.size(); ++i) { + sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = hton(port); + addr.sin_addr = addrs[i]; + + if (::connect(m_sock, reinterpret_cast(&addr), sizeof(addr)) == 0) + return; + + close(m_sock); + m_sock = socket(AF_INET, SOCK_DGRAM, 0); + } + throw Error("No more addresses to connect to."); +} + +ssize_t UDPProto::write(const void* buf, size_t size) +{ + return ::write(m_sock, buf, size); +} + +ssize_t UDPProto::read(void* buf, size_t size) +{ + return ::read(m_sock, buf, size); +} diff --git a/stglibs/sgcp.lib/udp.h b/stglibs/sgcp.lib/udp.h new file mode 100644 index 00000000..b08978b4 --- /dev/null +++ b/stglibs/sgcp.lib/udp.h @@ -0,0 +1,54 @@ +#ifndef __STG_SGCP_UDP_H__ +#define __STG_SGCP_UDP_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/sgcp_transport.h" + +#include "stg/os_int.h" + +#include + +#include // ssize_t + +namespace STG +{ +namespace SGCP +{ + +class UDPProto : public TransportProto +{ + public: + UDPProto(); + virtual ~UDPProto(); + + virtual void connect(const std::string& address, uint16_t port); + virtual ssize_t write(const void* buf, size_t size); + virtual ssize_t read(void* buf, size_t size); + + private: + int m_sock; +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/unix.cpp b/stglibs/sgcp.lib/unix.cpp new file mode 100644 index 00000000..15002e5e --- /dev/null +++ b/stglibs/sgcp.lib/unix.cpp @@ -0,0 +1,41 @@ +#include "unix.h" + +#include +#include + +#include +#include +#include + +using STG::SGCP::UnixProto; + +UnixProto::UnixProto() + : m_sock(socket(AF_UNIX, SOCK_STREAM, 0)) +{ +} + +UnixProto::~UnixProto() +{ + close(m_sock); +} + +void UnixProto::connect(const std::string& address, uint16_t /*port*/) +{ + sockaddr_un addr; + addr.sun_family = AF_UNIX; + size_t max = sizeof(addr.sun_path); + strncpy(addr.sun_path, address.c_str(), max - 1); + addr.sun_path[max - 1] = 0; // Just in case. + if (::connect(m_sock, reinterpret_cast(&addr), sizeof(addr)) < 0) + throw Error(strerror(errno)); +} + +ssize_t UnixProto::write(const void* buf, size_t size) +{ + return ::write(m_sock, buf, size); +} + +ssize_t UnixProto::read(void* buf, size_t size) +{ + return ::read(m_sock, buf, size); +} diff --git a/stglibs/sgcp.lib/unix.h b/stglibs/sgcp.lib/unix.h new file mode 100644 index 00000000..e5b645f2 --- /dev/null +++ b/stglibs/sgcp.lib/unix.h @@ -0,0 +1,54 @@ +#ifndef __STG_SGCP_UNIX_H__ +#define __STG_SGCP_UNIX_H__ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/sgcp_transport.h" + +#include "stg/os_int.h" + +#include + +#include // ssize_t + +namespace STG +{ +namespace SGCP +{ + +class UnixProto : public TransportProto +{ + public: + UnixProto(); + virtual ~UnixProto(); + + virtual void connect(const std::string& address, uint16_t /*port*/); + virtual ssize_t write(const void* buf, size_t size); + virtual ssize_t read(void* buf, size_t size); + + private: + int m_sock; +}; + +} // namespace SGCP +} // namespace STG + +#endif diff --git a/stglibs/sgcp.lib/utils.cpp b/stglibs/sgcp.lib/utils.cpp new file mode 100644 index 00000000..4c33e42f --- /dev/null +++ b/stglibs/sgcp.lib/utils.cpp @@ -0,0 +1,30 @@ +#include "stg/sgcp_utils.h" + +#include +#include +#include + +std::vector STG::SGCP::resolve(const std::string& address) +{ + addrinfo* result = NULL; + + addrinfo hints; + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET; /* Allow IPv4 */ + hints.ai_socktype = 0; /* Datagram socket */ + hints.ai_flags = 0; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + int res = getaddrinfo(address.c_str(), NULL, &hints, &result); + if (res != 0) + throw TransportProto::Error(gai_error(res)); + + std::vector as; + for (const addrinfo* p = result; p != NULL; p = p->next) + as.push_back(p->ai_addr.sin_addr); + return as; +}