1 // Copyright (c) 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef QUICHE_QUIC_QBONE_PLATFORM_KERNEL_INTERFACE_H_ 6 #define QUICHE_QUIC_QBONE_PLATFORM_KERNEL_INTERFACE_H_ 7 8 #include <errno.h> 9 #include <fcntl.h> 10 #include <sys/ioctl.h> 11 #include <sys/socket.h> 12 #include <sys/types.h> 13 #include <unistd.h> 14 15 #include <type_traits> 16 #include <utility> 17 18 namespace quic { 19 20 // A wrapper for making syscalls to the kernel, so that syscalls can be 21 // mocked during testing. 22 class KernelInterface { 23 public: ~KernelInterface()24 virtual ~KernelInterface() {} 25 virtual int bind(int fd, const struct sockaddr* addr, socklen_t addr_len) = 0; 26 virtual int close(int fd) = 0; 27 virtual int ioctl(int fd, int request, void* argp) = 0; 28 virtual int open(const char* pathname, int flags) = 0; 29 virtual ssize_t read(int fd, void* buf, size_t count) = 0; 30 virtual ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, 31 struct sockaddr* src_addr, socklen_t* addrlen) = 0; 32 virtual ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags) = 0; 33 virtual ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, 34 const struct sockaddr* dest_addr, 35 socklen_t addrlen) = 0; 36 virtual int socket(int domain, int type, int protocol) = 0; 37 virtual int setsockopt(int fd, int level, int optname, const void* optval, 38 socklen_t optlen) = 0; 39 virtual ssize_t write(int fd, const void* buf, size_t count) = 0; 40 }; 41 42 // It is unfortunate to have R here, but std::result_of cannot be used. 43 template <typename F, typename R, typename... Params> 44 auto SyscallRetryOnError(R r, F f, Params&&... params) 45 -> decltype(f(std::forward<Params>(params)...)) { 46 static_assert( 47 std::is_same<decltype(f(std::forward<Params>(params)...)), R>::value, 48 "Return type does not match"); 49 decltype(f(std::forward<Params>(params)...)) result; 50 do { 51 result = f(std::forward<Params>(params)...); 52 } while (result == r && errno == EINTR); 53 return result; 54 } 55 56 template <typename F, typename... Params> 57 auto SyscallRetry(F f, Params&&... params) 58 -> decltype(f(std::forward<Params>(params)...)) { 59 return SyscallRetryOnError(-1, f, std::forward<Params>(params)...); 60 } 61 62 template <typename Runner> 63 class ParametrizedKernel final : public KernelInterface { 64 public: 65 static_assert(std::is_trivially_destructible<Runner>::value, 66 "Runner is used as static, must be trivially destructible"); 67 ~ParametrizedKernel()68 ~ParametrizedKernel() override {} 69 bind(int fd,const struct sockaddr * addr,socklen_t addr_len)70 int bind(int fd, const struct sockaddr* addr, socklen_t addr_len) override { 71 static Runner syscall("bind"); 72 return syscall.Retry(&::bind, fd, addr, addr_len); 73 } close(int fd)74 int close(int fd) override { 75 static Runner syscall("close"); 76 return syscall.Retry(&::close, fd); 77 } ioctl(int fd,int request,void * argp)78 int ioctl(int fd, int request, void* argp) override { 79 static Runner syscall("ioctl"); 80 return syscall.Retry(&::ioctl, fd, request, argp); 81 } open(const char * pathname,int flags)82 int open(const char* pathname, int flags) override { 83 static Runner syscall("open"); 84 return syscall.Retry(&::open, pathname, flags); 85 } read(int fd,void * buf,size_t count)86 ssize_t read(int fd, void* buf, size_t count) override { 87 static Runner syscall("read"); 88 return syscall.Run(&::read, fd, buf, count); 89 } recvfrom(int sockfd,void * buf,size_t len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)90 ssize_t recvfrom(int sockfd, void* buf, size_t len, int flags, 91 struct sockaddr* src_addr, socklen_t* addrlen) override { 92 static Runner syscall("recvfrom"); 93 return syscall.RetryOnError(&::recvfrom, static_cast<ssize_t>(-1), sockfd, 94 buf, len, flags, src_addr, addrlen); 95 } sendmsg(int sockfd,const struct msghdr * msg,int flags)96 ssize_t sendmsg(int sockfd, const struct msghdr* msg, int flags) override { 97 static Runner syscall("sendmsg"); 98 return syscall.RetryOnError(&::sendmsg, static_cast<ssize_t>(-1), sockfd, 99 msg, flags); 100 } sendto(int sockfd,const void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)101 ssize_t sendto(int sockfd, const void* buf, size_t len, int flags, 102 const struct sockaddr* dest_addr, socklen_t addrlen) override { 103 static Runner syscall("sendto"); 104 return syscall.RetryOnError(&::sendto, static_cast<ssize_t>(-1), sockfd, 105 buf, len, flags, dest_addr, addrlen); 106 } socket(int domain,int type,int protocol)107 int socket(int domain, int type, int protocol) override { 108 static Runner syscall("socket"); 109 return syscall.Retry(&::socket, domain, type, protocol); 110 } setsockopt(int fd,int level,int optname,const void * optval,socklen_t optlen)111 int setsockopt(int fd, int level, int optname, const void* optval, 112 socklen_t optlen) override { 113 static Runner syscall("setsockopt"); 114 return syscall.Retry(&::setsockopt, fd, level, optname, optval, optlen); 115 } write(int fd,const void * buf,size_t count)116 ssize_t write(int fd, const void* buf, size_t count) override { 117 static Runner syscall("write"); 118 return syscall.Run(&::write, fd, buf, count); 119 } 120 }; 121 122 class DefaultKernelRunner { 123 public: DefaultKernelRunner(const char * name)124 explicit DefaultKernelRunner(const char* name) {} 125 126 template <typename F, typename R, typename... Params> 127 static auto RetryOnError(F f, R r, Params&&... params) 128 -> decltype(f(std::forward<Params>(params)...)) { 129 return SyscallRetryOnError(r, f, std::forward<Params>(params)...); 130 } 131 132 template <typename F, typename... Params> 133 static auto Retry(F f, Params&&... params) 134 -> decltype(f(std::forward<Params>(params)...)) { 135 return SyscallRetry(f, std::forward<Params>(params)...); 136 } 137 138 template <typename F, typename... Params> 139 static auto Run(F f, Params&&... params) 140 -> decltype(f(std::forward<Params>(params)...)) { 141 return f(std::forward<Params>(params)...); 142 } 143 }; 144 145 using Kernel = ParametrizedKernel<DefaultKernelRunner>; 146 147 } // namespace quic 148 149 #endif // QUICHE_QUIC_QBONE_PLATFORM_KERNEL_INTERFACE_H_ 150