xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/qbone/platform/kernel_interface.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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