CLX C++ Libraries - ssl::sockmanager
Author: clown

CLX C++ Libraries
Home >> sockmanager >> ssl::sockmanager

# Declarations

    namespace ssl {
        typedef basic_sockmanager<SOCK_STREAM, AF_INET, 0> sockmanager;
    };

# Overview

ssl::sockmanager は，SSL 通信用の sockmanager です． その他の sockmanager と同様のインターフェースで使用することができます．

# Examples

example_sslmanager_send.cpp

    #include <cstdio>
    #include <iostream>
    #include <string>
    #include "clx/ssl.h"

    /* ------------------------------------------------------------------------- */
    //  send_msg
    /* ------------------------------------------------------------------------- */
    bool send_msg(clx::ssl::rawsocket* s, clx::ssl::sockmanager& sm) {
        // read string from std::cin
        std::string buf;
        if (!std::getline(std::cin, buf)) {
            sm.stop();
            return false;
        }

        // write string to the socket
        for (clx::ssl::sockmanager::iterator pos = sm.begin(); pos != sm.end(); pos++) {
            if (sm.socket(pos)->socket() == s->socket()) continue;
            clx::ssl::sockstream* ss = dynamic_cast<clx::ssl::sockstream*>(sm.socket(pos));
            *ss << buf << std::endl;
        }
        return true;
    }

    /* ------------------------------------------------------------------------- */
    //  recv_msg
    /* ------------------------------------------------------------------------- */
    bool recv_msg(clx::ssl::rawsocket* s, clx::ssl::sockmanager& sm) {
        clx::ssl::sockstream* ss = dynamic_cast<clx::ssl::sockstream*>(s);

        std::string buf;
        if (!std::getline(*ss, buf)) {
            ss->close();
            return false;
        }
        std::cout << buf << std::endl;
        return true;
    }

    /* ------------------------------------------------------------------------- */
    //  main
    /* ------------------------------------------------------------------------- */
    int main(int argc, char* argv[])
    {
        if (argc < 2) {
            std::cerr << "usage: " << argv[0] << " host" << std::endl;
            return -1;
        }

        try {
            clx::ssl::sockmanager sm;
            int port = clx::ssl::port(argv[2]);
            sm.add(new clx::ssl::sockstream(argv[1], port), recv_msg);
            sm.add(new clx::ssl::rawsocket(0), send_msg); // for std::cin
            sm.start();
        }
        catch (clx::socket_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }
        catch (clx::sockaddress_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }
        catch (std::runtime_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }

        return 0;
    }

example_sslmanager_send.cpp

    #include <iostream>
    #include <cstring>
    #include "clx/ssl.h"

    /* ----------------------------------------------------------------- */
    //  accept_handler
    /* ----------------------------------------------------------------- */
    template <class Socket, class Service>
    class accept_handler {
    public:
        typedef Socket socket_type;
        typedef clx::ssl::acceptor acceptor_type;
        typedef Service service_handler;

        explicit accept_handler(const std::string& pub, const std::string& priv) :
            public_(pub), private_(priv) {}

        explicit accept_handler(const char* pub, const char* priv) :
            public_(pub), private_(priv) {}

        virtual ~accept_handler() throw() {}

        template <class T, class SockManager>
        bool operator()(T* s, SockManager& sm) {
            acceptor_type* server = dynamic_cast<acceptor_type*>(s);
            socket_type* client = new socket_type(server->accept(public_, private_));
            if (client == NULL) throw std::bad_alloc();

            sm.add(client, service_handler(server->socket()));
            return true;
        }

    private:
        std::string public_;
        std::string private_;
    };

    /* ------------------------------------------------------------------------- */
    //  chat_service
    /* ------------------------------------------------------------------------- */
    class chat_service {
    public:
        typedef clx::ssl::sockstream socket_type;

        chat_service(socket_int s) : accid_(s) {}

        template <class SockT, class SockManager>
        bool operator()(SockT* s, SockManager& sm) {
            socket_type* ss = dynamic_cast<socket_type*>(s);

            std::string ipaddr = ss->address().ipaddr();
            int port = ss->address().port();
            std::string buf;
            if (!std::getline(*ss, buf)) {
                std::cout << ipaddr << ':' << port << ": connection was closed" << std::endl;
                ss->close();
                return false;
            }

            /*
             * 接続されている全クライアントに受信したメッセージを
             * message (xxx.xxx.xxx.xxx:port)
             * という形で送信する．ただし，sockmanager には接続確立用の
             * ソケットも登録されてあるため，そのソケットには送らないように
             * 注意する．コンストラクタで接続確立用のソケットのソケット番号
             * を知らせてもらっている (accid_) ので，その値を基に判断する．
             */
            buf += " (" + ipaddr + ":" + clx::lexical_cast<std::string>(port) + ")";
            for (typename SockManager::iterator pos = sm.begin(); pos != sm.end(); pos++) {
                if (sm.socket(pos)->socket() == accid_) continue;
                socket_type* os = dynamic_cast<socket_type*>(sm.socket(pos));
                *os << buf << std::endl;
            }

            return true;
        }

    private:
        socket_int accid_; // acceptorのソケット番号
    };

    /* ------------------------------------------------------------------------- */
    //  main
    /* ------------------------------------------------------------------------- */
    int main(int argc, char* argv[]) {
        typedef accept_handler<clx::ssl::sockstream, chat_service> handler_type;

        try {
            clx::ssl::sockmanager s;
            int port = clx::ssl::port(argv[1]);
            s.add(new clx::ssl::acceptor(port), handler_type("public.key", "private.key"));
            s.start();
        }
        catch (clx::socket_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }
        catch (clx::sockaddress_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }
        catch (std::runtime_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }

        return 0;
    }

# Related Pages

1. CLX C++ Libraries - sockmanager
2. CLX C++ Libraries - ssl::socket
3. CLX C++ Libraries - ssl::acceptor

# References

1. OpenSSL: The Open Source toolkit for SSL/TLS
2. OpenSSL 日本語サイト: The Open Source toolkit for SSL/TLS
3. Life like a clown - Hello, OpenSSL!