summaryrefslogblamecommitdiff
path: root/src/io/fd.hpp
blob: 2a6c7bdba2cf95789bdc634efb595ba082bd206d (plain) (tree)
1
            


















                                                                           
                  
 

                       
 

                             
 

              




















                                               
                                     
              
                                      
              
                                      


                                             
              


                                                                            






                                                             
 







                                                     
                                                               








                                                                        

                                                                      

                                                            

                                                                             



























































                                                                                     

                                   
                                             
                       


                         

                                   
                                                      
                       


                       

                                   
                                             
                       







                                                                                                                                             
                   
#pragma once
//    io/fd.hpp - typesafe (but not scopesafe) file descriptors
//
//    Copyright © 2014 Ben Longbons <b.r.longbons@gmail.com>
//
//    This file is part of The Mana World (Athena server)
//
//    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 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 General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "fwd.hpp"

#include <sys/select.h>
#include <sys/socket.h>

#include "../diagnostics.hpp"


namespace tmwa
{
namespace io
{
    class FD
    {
    private:
        int fd;

        explicit
        FD(int f)
        : fd(f)
        {}
    public:
        FD()
        : fd(-1)
        {}

        int uncast_dammit() { return fd; }
        static
        FD cast_dammit(int f) { return FD(f); }

        static
        FD stdin_() { return FD(0); }
        static
        FD stdout_() { return FD(1); }
        static
        FD stderr_() { return FD(2); }

        static const int DEFAULT_MODE = 0666;

        static
        FD open(ZString path, int flags, int mode=DEFAULT_MODE);
        static
        FD openat(FD dirfd, ZString path, int flags, int mode=DEFAULT_MODE);
        static
        FD socket(int domain, int type, int protocol);
        FD accept(struct sockaddr *addr, socklen_t *addrlen);
        static
        int pipe(FD& r, FD& w);
        static
        int pipe2(FD& r, FD& w, int flags);

        static
        FD sysconf_SC_OPEN_MAX();

        FD next() { return FD(fd + 1); }
        FD prev() { return FD(fd - 1); }

        ssize_t read(void *buf, size_t count);
        ssize_t write(const void *buf, size_t count);
        ssize_t send(const void *buf, size_t count, int flags);
        ssize_t sendto(const void *buf, size_t count, int flags,
                   const struct sockaddr *dest_addr, socklen_t addrlen);
        ssize_t sendmsg(const struct msghdr *msg, int flags);
        int sendmmsg(struct mmsghdr *msgvec, unsigned int vlen,
             unsigned int flags);
        ssize_t recv(void *buf, size_t len, int flags);
        ssize_t recvfrom(void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
        ssize_t recvmsg(struct msghdr *msg, int flags);
        ssize_t pread(void *buf, size_t count, int64_t offset);
        ssize_t pwrite(const void *buf, size_t count, int64_t offset);
        ssize_t readv(const struct iovec *iov, int iovcnt);
        ssize_t writev(const struct iovec *iov, int iovcnt);
        ssize_t preadv(const struct iovec *iov, int iovcnt, int64_t offset);
        ssize_t pwritev(const struct iovec *iov, int iovcnt, int64_t offset);

        int close();
        int shutdown(int);
        int getsockopt(int level, int optname, void *optval, socklen_t *optlen);
        int setsockopt(int level, int optname, const void *optval, socklen_t optlen);
        // ...
        int fcntl(int cmd);
        int fcntl(int cmd, int arg);
        int fcntl(int cmd, void *arg);
        int listen(int backlog);
        int bind(const struct sockaddr *addr, socklen_t addrlen);
        int connect(const struct sockaddr *addr, socklen_t addrlen);
        FD dup();
        FD dup2(FD newfd);
        FD dup3(FD newfd, int flags);


        friend
        bool operator == (FD l, FD r)
        {
            return l.fd == r.fd;
        }
        friend
        bool operator != (FD l, FD r)
        {
            return l.fd != r.fd;
        }
        friend
        bool operator < (FD l, FD r)
        {
            return l.fd < r.fd;
        }
        friend
        bool operator <= (FD l, FD r)
        {
            return l.fd <= r.fd;
        }
        friend
        bool operator > (FD l, FD r)
        {
            return l.fd > r.fd;
        }
        friend
        bool operator >= (FD l, FD r)
        {
            return l.fd >= r.fd;
        }
    };

    class FD_Set
    {
    private:
        fd_set fds;
    public:
        FD_Set()
        {
            FD_ZERO(&fds);
        }
        void clr(FD fd)
        {
            DIAG_PUSH();
            DIAG_I(old_style_cast);
            FD_CLR(fd.uncast_dammit(), &fds);
            DIAG_POP();
        }
        bool isset(FD fd)
        {
            DIAG_PUSH();
            DIAG_I(old_style_cast);
            return FD_ISSET(fd.uncast_dammit(), &fds);
            DIAG_POP();
        }
        void set(FD fd)
        {
            DIAG_PUSH();
            DIAG_I(old_style_cast);
            FD_SET(fd.uncast_dammit(), &fds);
            DIAG_POP();
        }

        static
        int select(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, struct timeval *timeout);
        static
        int pselect(int nfds, FD_Set *readfds, FD_Set *writefds, FD_Set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);
    };
} // namespace io
} // namespace tmwa