/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Copyright 2017 Danny Robson <danny@nerdcruft.net>
 */

#ifndef CRUFT_UTIL_POSIX_SOCKET_HPP
#define CRUFT_UTIL_POSIX_SOCKET_HPP

#include "fd.hpp"

#include "except.hpp"

#if !defined(PLATFORM_WIN32)
    #include <sys/types.h>
    #include <sys/socket.h>
#else
    #include <winsock2.h>
#endif


struct sockaddr_in;

namespace cruft::posix {
     class socket : public fd {
     public:
         explicit socket (int _fd);

         socket (int domain, int type);
         socket (int domain, int type, int protocol);

         socket (cruft::view<const char*> host, int port);

         socket (const socket&) = delete;
         socket& operator= (const socket&) = delete;

         socket (socket &&rhs) noexcept;
         socket& operator= (socket &&) noexcept;

         // the destructor is provided so that we can operate more cleanly on
         // win32 where we must call closesocket instead of the normal close.
         // because windows...
         ~socket ();

         void bind (::sockaddr_in const&);

         void connect (::sockaddr_in const&);
         void connect (cruft::view<const char*> host, int port);
         void shutdown ();

         template <typename ByteT>
         ssize_t sendto (cruft::view<ByteT const*> data, int flags, ::sockaddr_in const &dst);

         template <typename ByteT>
         cruft::view<ByteT*> recvfrom (cruft::view<ByteT*> buffer, int flags);

         template <typename ByteT>
         auto recvfrom (cruft::view<ByteT*> buffer)
         { return recvfrom (buffer, 0); }

         template <typename ValueT>
         void setoption (int _level, int _name, const ValueT &_value)
         {
            error::try_value (
                setsockopt (
                    native (),
                    _level,
                    _name,
                    &_value, sizeof (_value)
                )
            );
         }
     };
};

#endif