commit - 5b8701be75c5767827e3c7e500de5980f55deb3c
commit + 230a46c6267df18bb9b48a66399e9db3b3ece434
blob - bac6ee8a28ac35fd3ae1bfb912fa65b04e0e7d4d
blob + ef50e08bc2f5a86b92048b4cb1f110df6803ff2c
--- shared/transport.cc
+++ shared/transport.cc
ctx.swap(ret_ctx);
}
+
+void accept(struct tls *server_ctx, int client_socket, context_t &ret_ctx)
+{
+ struct tls *client_ctx = nullptr;
+ if (tls_accept_socket(server_ctx, &client_ctx, client_socket) == -1)
+ {
+ error::occurred("TLS accept", error::no_error_code);
+ ret_ctx.reset();
+ return;
+ }
+ ret_ctx.reset(client_ctx);
+}
+
} // namespace transport
} // namespace vostok
blob - /dev/null
blob + 91f18102c1d60cd52c7e585c92c8329e80f99ca7 (mode 644)
--- /dev/null
+++ shared/non_copiable
+/** Non-copiable objects */
+
+
+#pragma once
+
+
+namespace vostok
+{
+
+struct non_copiable
+{
+ non_copiable() = default;
+ non_copiable(const non_copiable &) = delete;
+ non_copiable &operator =(const non_copiable &) = delete;
+};
+
+} // namespace vostok
blob - 758da8456ae8a8edca0ae2926b70bc3bf7dd34a2
blob + 674b353f1e4433e3260fd17613a369a41a292999
--- shared/transport.h
+++ shared/transport.h
/** Wrap libtls for gemini protocol */
-#include <vtl>
+#include <zstring>
+#include <not_null>
#include <tls.h>
/* Create new TLS context for gemini server */
void create_gemini_server_ctx(not_null<czstring> cert_file, not_null<czstring> key_file, context_t &ctx);
+/** Accept new client */
+void accept(struct tls *server_ctx, int client_socket, context_t &ctx);
} // namespace transport
} // namespace vostok
blob - /dev/null
blob + 61c3190a7d73098284fab48113e2ea55ec0fa3ff (mode 644)
--- /dev/null
+++ shared/not_null
+/** Restricts a pointer or smart pointer to only hold non-null values. */
+
+
+#pragma once
+
+
+namespace vostok
+{
+
+template <class T>
+class not_null
+{
+public:
+ not_null(T p) :m_p{p} {}
+
+ T get() const {return m_p;}
+ operator T() const {return m_p;}
+ T operator->() const {return m_p;}
+
+
+ // prevents compilation when someone attempts to assign a null pointer constant
+ not_null(std::nullptr_t) = delete;
+ not_null& operator=(std::nullptr_t) = delete;
+
+ // unwanted operators...pointers only point to single objects!
+ not_null& operator++() = delete;
+ not_null& operator--() = delete;
+ not_null operator++(int) = delete;
+ not_null operator--(int) = delete;
+ not_null& operator+=(std::ptrdiff_t) = delete;
+ not_null& operator-=(std::ptrdiff_t) = delete;
+ void operator[](std::ptrdiff_t) const = delete;
+
+private:
+ T m_p;
+};
+
+
+} // namespace vostok
blob - 98c2467b729567bd41fd41dc587ce957a843551f (mode 644)
blob + /dev/null
--- shared/vtl
+++ /dev/null
-/** vostok template library */
-
-#include <cstddef>
-
-#pragma once
-
-
-namespace vostok
-{
-
-using czstring=const char *;
-
-template <class T>
-class not_null
-{
-public:
- not_null(T p) :m_p{p} {}
-
- T get() const {return m_p;}
- operator T() const {return m_p;}
- T operator->() const {return m_p;}
-
-
- // prevents compilation when someone attempts to assign a null pointer constant
- not_null(std::nullptr_t) = delete;
- not_null& operator=(std::nullptr_t) = delete;
-
- // unwanted operators...pointers only point to single objects!
- not_null& operator++() = delete;
- not_null& operator--() = delete;
- not_null operator++(int) = delete;
- not_null operator--(int) = delete;
- not_null& operator+=(std::ptrdiff_t) = delete;
- not_null& operator-=(std::ptrdiff_t) = delete;
- void operator[](std::ptrdiff_t) const = delete;
-
-private:
- T m_p;
-};
-
-
-} // namespace vostok
blob - /dev/null
blob + e791df4a9bb41ae6998d77d98b0702074eda9ecc (mode 644)
--- /dev/null
+++ shared/unique_fd
+/** Smart pointer for file descriptor */
+
+#include <unistd.h>
+#include <non_copiable>
+
+#pragma once
+
+
+namespace vostok
+{
+
+
+class unique_fd : non_copiable
+{
+public:
+ explicit unique_fd(int fd = -1) : m_fd(fd) {}
+ ~unique_fd(){ reset();}
+
+ operator bool() const {return m_fd != -1;}
+
+ int get() const { return m_fd; }
+ void reset(int fd = -1)
+ {
+ if (*this)
+ close(m_fd);
+ m_fd = fd;
+ }
+ int release()
+ {
+ const auto fd = m_fd;
+ m_fd = -1;
+ return fd;
+ }
+
+private:
+ int m_fd;
+};
+
+
+} // namespace vostok
blob - /dev/null
blob + 72f350aae70828f2d30d40217c557c58f297dba5 (mode 644)
--- /dev/null
+++ shared/zstring
+/** C-style (null-terminated) string */
+
+
+#pragma once
+
+
+namespace vostok
+{
+
+
+using czstring=const char *;
+
+
+} // namespace vostok
blob - 61c6711f170126093bf8a2860933d30de8897990
blob + 7455e658ed0f78bb460d284f6809c819fde5b551
--- vostokd/Makefile
+++ vostokd/Makefile
CXXFLAGS += -ltls
CXXFILES = vostokd.cc
-HXXFILES = ${.PATH}../shared/vtl
+HXXFILES = ${.PATH}../shared/not_null
+HXXFILES += ${.PATH}../shared/zstring
+HXXFILES += ${.PATH}../shared/unique_fd
+HXXFILES += ${.PATH}../shared/non_copiable
+HXXFILES += ${.PATH}../shared/unique_fd
CXXFILES += ${.PATH}../shared/transport.cc
HXXFILES += ${.PATH}../shared/transport.h
CXXFILES += ${.PATH}../shared/error.cc
blob - cc83600a34f1662f5336c556196b1a8667c481a7
blob + 33d9148d832623c639854216d5b805f0452db1e2
--- vostokd/vostokd.cc
+++ vostokd/vostokd.cc
#include <error.h>
#include <transport.h>
#include <unistd.h>
+#include <unique_fd>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
namespace vostok
{
namespace
{
-
struct command_line_arguments
{
not_null<czstring> m_addr{"127.0.0.1"};
};
-} // namespace <unnamed>
+bool server_loop(int server_socket, struct tls *ctx)
+{
+ error::g_log << "Enter to server loop..." << std::endl;
+ for (; ; )
+ {
+ if (listen(server_socket, 1024) == -1)
+ {
+ error::occurred("Listen socket", error::print{});
+ return false;
+ }
+ struct sockaddr_in addr{};
+ socklen_t addrlen = sizeof(addr);
+ unique_fd client_socket{accept(server_socket, (struct sockaddr *)&addr, &addrlen)};
+ if (!client_socket)
+ {
+ error::occurred("Accept socket", error::print{});
+ return false;
+ }
+
+ transport::context_t client_ctx{nullptr, tls_free};
+ transport::accept(ctx, client_socket.get(), client_ctx);
+ if (!client_ctx)
+ return false;
+
+ error::g_log << inet_ntoa(addr.sin_addr) << " accepted" << std::endl;
+ }
+ return true;
+}
+
+
/** C++ entry point */
-bool
-main(int argc, char *argv[])
+bool main(const command_line_arguments &args)
{
- command_line_arguments args;
- if (!args.parse_command_line(argc, argv))
- return false;
-
if (!transport::init())
return false;
if (!ctx)
return false;
- return true;
+ const unique_fd server_socket{socket(AF_INET, SOCK_STREAM, 0)};
+ if (!server_socket)
+ {
+ error::occurred("Create socket", error::print{});
+ return false;
+ }
+
+ struct sockaddr_in sockaddr{};
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_addr.s_addr = inet_addr(args.m_addr);
+ sockaddr.sin_port = htons(args.m_port);
+
+ if (bind(server_socket.get(), (struct sockaddr *)&sockaddr, sizeof(sockaddr)) == -1)
+ {
+ error::occurred(
+ [=](){error::g_log << "Bind to " << args.m_addr << ":" << std::dec << args.m_port;},
+ error::print{}
+ );
+ return false;
+ }
+
+ return server_loop(server_socket.get(), ctx.get());
}
+} // namespace <unnamed>
} // namespace vostok
int
main(int argc, char *argv[])
{
- return vostok::main(argc, argv) ? 0 : 1;
+ vostok::command_line_arguments args;
+ if (!args.parse_command_line(argc, argv))
+ return 1;
+
+ return vostok::main(args) ? 0 : 1;
}