Home | History | Annotate | Download | only in netdutils
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef NETDUTILS_SYSCALLS_H
     18 #define NETDUTILS_SYSCALLS_H
     19 
     20 #include <memory>
     21 
     22 #include <poll.h>
     23 #include <unistd.h>
     24 #include <sys/eventfd.h>
     25 #include <sys/socket.h>
     26 #include <sys/types.h>
     27 #include <sys/uio.h>
     28 
     29 #include "netdutils/Slice.h"
     30 #include "netdutils/Socket.h"
     31 #include "netdutils/Status.h"
     32 #include "netdutils/StatusOr.h"
     33 #include "netdutils/UniqueFd.h"
     34 #include "netdutils/UniqueFile.h"
     35 
     36 namespace android {
     37 namespace netdutils {
     38 
     39 class Syscalls {
     40   public:
     41     virtual ~Syscalls() = default;
     42 
     43     virtual StatusOr<UniqueFd> open(const std::string& pathname, int flags,
     44                                     mode_t mode = 0) const = 0;
     45 
     46     virtual StatusOr<UniqueFd> socket(int domain, int type, int protocol) const = 0;
     47 
     48     virtual Status getsockname(Fd sock, sockaddr* addr, socklen_t* addrlen) const = 0;
     49 
     50     virtual Status getsockopt(Fd sock, int level, int optname, void *optval,
     51                               socklen_t *optlen) const = 0;
     52 
     53     virtual Status setsockopt(Fd sock, int level, int optname, const void* optval,
     54                               socklen_t optlen) const = 0;
     55 
     56     virtual Status bind(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0;
     57 
     58     virtual Status connect(Fd sock, const sockaddr* addr, socklen_t addrlen) const = 0;
     59 
     60     virtual StatusOr<UniqueFd> eventfd(unsigned int initval, int flags) const = 0;
     61 
     62     virtual StatusOr<int> ppoll(pollfd* fds, nfds_t nfds, double timeout) const = 0;
     63 
     64     virtual StatusOr<size_t> writev(Fd fd, const std::vector<iovec>& iov) const = 0;
     65 
     66     virtual StatusOr<size_t> write(Fd fd, const Slice buf) const = 0;
     67 
     68     virtual StatusOr<Slice> read(Fd fd, const Slice buf) const = 0;
     69 
     70     virtual StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const sockaddr* dst,
     71                                     socklen_t dstlen) const = 0;
     72 
     73     virtual StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags, sockaddr* src,
     74                                      socklen_t* srclen) const = 0;
     75 
     76     virtual Status shutdown(Fd fd, int how) const = 0;
     77 
     78     virtual Status close(Fd fd) const = 0;
     79 
     80     virtual StatusOr<UniqueFile> fopen(const std::string& path, const std::string& mode) const = 0;
     81 
     82     virtual StatusOr<int> vfprintf(FILE* file, const char* format, va_list ap) const = 0;
     83 
     84     virtual StatusOr<int> vfscanf(FILE* file, const char* format, va_list ap) const = 0;
     85 
     86     virtual Status fclose(FILE* file) const = 0;
     87 
     88     virtual StatusOr<pid_t> fork() const = 0;
     89 
     90     // va_args helpers
     91     // va_start doesn't work when the preceding argument is a reference
     92     // type so we're forced to use const char*.
     93     StatusOr<int> fprintf(FILE* file, const char* format, ...) const {
     94         va_list ap;
     95         va_start(ap, format);
     96         auto result = vfprintf(file, format, ap);
     97         va_end(ap);
     98         return result;
     99     }
    100 
    101     // va_start doesn't work when the preceding argument is a reference
    102     // type so we're forced to use const char*.
    103     StatusOr<int> fscanf(FILE* file, const char* format, ...) const {
    104         va_list ap;
    105         va_start(ap, format);
    106         auto result = vfscanf(file, format, ap);
    107         va_end(ap);
    108         return result;
    109     }
    110 
    111     // Templated helpers that forward directly to methods declared above
    112     template <typename SockaddrT>
    113     StatusOr<SockaddrT> getsockname(Fd sock) const {
    114         SockaddrT addr = {};
    115         socklen_t addrlen = sizeof(addr);
    116         RETURN_IF_NOT_OK(getsockname(sock, asSockaddrPtr(&addr), &addrlen));
    117         return addr;
    118     }
    119 
    120     template <typename SockoptT>
    121     Status getsockopt(Fd sock, int level, int optname, void* optval, socklen_t* optlen) const {
    122         return getsockopt(sock, level, optname, optval, optlen);
    123     }
    124 
    125     template <typename SockoptT>
    126     Status setsockopt(Fd sock, int level, int optname, const SockoptT& opt) const {
    127         return setsockopt(sock, level, optname, &opt, sizeof(opt));
    128     }
    129 
    130     template <typename SockaddrT>
    131     Status bind(Fd sock, const SockaddrT& addr) const {
    132         return bind(sock, asSockaddrPtr(&addr), sizeof(addr));
    133     }
    134 
    135     template <typename SockaddrT>
    136     Status connect(Fd sock, const SockaddrT& addr) const {
    137         return connect(sock, asSockaddrPtr(&addr), sizeof(addr));
    138     }
    139 
    140     template <size_t size>
    141     StatusOr<std::array<uint16_t, size>> ppoll(const std::array<Fd, size>& fds, uint16_t events,
    142                                                double timeout) const {
    143         std::array<pollfd, size> tmp;
    144         for (size_t i = 0; i < size; ++i) {
    145             tmp[i].fd = fds[i].get();
    146             tmp[i].events = events;
    147             tmp[i].revents = 0;
    148         }
    149         RETURN_IF_NOT_OK(ppoll(tmp.data(), tmp.size(), timeout).status());
    150         std::array<uint16_t, size> out;
    151         for (size_t i = 0; i < size; ++i) {
    152             out[i] = tmp[i].revents;
    153         }
    154         return out;
    155     }
    156 
    157     template <typename SockaddrT>
    158     StatusOr<size_t> sendto(Fd sock, const Slice buf, int flags, const SockaddrT& dst) const {
    159         return sendto(sock, buf, flags, asSockaddrPtr(&dst), sizeof(dst));
    160     }
    161 
    162     // Ignore src sockaddr
    163     StatusOr<Slice> recvfrom(Fd sock, const Slice dst, int flags) const {
    164         return recvfrom(sock, dst, flags, nullptr, nullptr);
    165     }
    166 
    167     template <typename SockaddrT>
    168     StatusOr<std::pair<Slice, SockaddrT>> recvfrom(Fd sock, const Slice dst, int flags) const {
    169         SockaddrT addr = {};
    170         socklen_t addrlen = sizeof(addr);
    171         ASSIGN_OR_RETURN(auto used, recvfrom(sock, dst, flags, asSockaddrPtr(&addr), &addrlen));
    172         return std::make_pair(used, addr);
    173     }
    174 };
    175 
    176 // Specialized singleton that supports zero initialization and runtime
    177 // override of contained pointer.
    178 class SyscallsHolder {
    179   public:
    180     ~SyscallsHolder();
    181 
    182     // Return a pointer to an unowned instance of Syscalls.
    183     Syscalls& get();
    184 
    185     // Testing only: set the value returned by getSyscalls. Return the old value.
    186     // Callers are responsible for restoring the previous value returned
    187     // by getSyscalls to avoid leaks.
    188     Syscalls& swap(Syscalls& syscalls);
    189 
    190   private:
    191     std::atomic<Syscalls*> mSyscalls{nullptr};
    192 };
    193 
    194 // Syscalls instance used throughout netdutils
    195 extern SyscallsHolder sSyscalls;
    196 
    197 }  // namespace netdutils
    198 }  // namespace android
    199 
    200 #endif /* NETDUTILS_SYSCALLS_H */
    201