GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/nfs4/rpc.h
Date: 2026-10-18 02:40:11
Exec Total Coverage
Lines: 12 12 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 *
4 * ONC RPC v2 over TCP (RFC 5531) for the built-in NFS server.
5 */
6
7 #ifndef CVMFS_NFS4_RPC_H_
8 #define CVMFS_NFS4_RPC_H_
9
10 #include <stdint.h>
11
12 #include <atomic>
13 #include <condition_variable>
14 #include <deque>
15 #include <memory>
16 #include <mutex>
17 #include <set>
18 #include <string>
19 #include <thread>
20 #include <vector>
21
22 #include "nfs4/backend.h"
23 #include "nfs4/nfs4_const.h"
24 #include "nfs4/xdr.h"
25
26 namespace nfs4 {
27
28 struct RpcCall {
29 312 RpcCall()
30 312 : xid(0)
31 312 , program(0)
32 312 , version(0)
33 312 , procedure(0)
34 312 , cred_flavor(kAuthNone)
35 312 , args(NULL)
36 312 , args_size(0) { }
37
38 uint32_t xid;
39 uint32_t program;
40 uint32_t version;
41 uint32_t procedure;
42 uint32_t cred_flavor;
43 /** Only meaningful for AUTH_SYS; nobody otherwise */
44 Credentials creds;
45 const unsigned char *args;
46 size_t args_size;
47 };
48
49 class RpcProgram {
50 public:
51 494 virtual ~RpcProgram() { }
52 virtual uint32_t program() const = 0;
53 virtual uint32_t min_version() const = 0;
54 virtual uint32_t max_version() const = 0;
55 /**
56 * Decodes the arguments and appends the procedure's results to res. On
57 * anything but kAcceptSuccess, res is discarded.
58 */
59 virtual AcceptStat Dispatch(const RpcCall &call, XdrReader *args,
60 XdrWriter *res) = 0;
61 };
62
63 /**
64 * Turns one RPC record (without record marking) into a reply record. Returns
65 * false if the record cannot be answered (not a call, or too garbled to
66 * extract the xid).
67 */
68 bool HandleRpcRecord(RpcProgram *program, const std::string &record,
69 std::string *reply);
70
71
72 /**
73 * Threaded TCP server. One reader thread per connection collects records;
74 * a pool of workers runs the procedures, so a call that blocks in the backend
75 * (e.g. a download) does not stall other calls on the same connection.
76 */
77 class RpcServer {
78 public:
79 struct Options {
80 26 Options() : workers(16), allow_remote(false), max_record(4u << 20) { }
81 unsigned workers;
82 /** Accept connections from non-loopback peers (testing only) */
83 bool allow_remote;
84 uint32_t max_record;
85 };
86
87 RpcServer(RpcProgram *program, const Options &options);
88 ~RpcServer();
89
90 /** Binds and listens; port 0 picks an ephemeral port. */
91 bool Listen(const std::string &address, uint16_t port);
92 /** Serves on an already listening socket, e.g. inherited from a parent */
93 bool Adopt(int listen_fd);
94 39 uint16_t port() const { return port_; }
95 int listen_fd() const { return listen_fd_; }
96 /** Only effective before Start() */
97 void SetWorkers(unsigned workers) { options_.workers = workers; }
98 /** Can be restarted after Stop(); the listening socket stays open */
99 void Start();
100 /** Joins all threads and closes client connections */
101 void Stop();
102 /** Number of open client connections */
103 unsigned NumConnections();
104
105 private:
106 struct Connection {
107 26 explicit Connection(int f) : fd(f) { }
108 ~Connection();
109 int fd;
110 std::mutex write_lock;
111 std::mutex inflight_lock;
112 std::set<uint32_t> inflight;
113 };
114 typedef std::shared_ptr<Connection> ConnectionPtr;
115
116 struct Job {
117 ConnectionPtr connection;
118 uint32_t xid;
119 std::string record;
120 };
121
122 void AcceptLoop();
123 void ReadLoop(ConnectionPtr connection);
124 void WorkerLoop();
125 void Send(const ConnectionPtr &connection, const std::string &reply);
126
127 RpcProgram *program_;
128 Options options_;
129 int listen_fd_;
130 uint16_t port_;
131 std::atomic<bool> stopping_;
132
133 std::thread accept_thread_;
134 std::vector<std::thread> workers_;
135
136 std::mutex connections_lock_;
137 std::vector<std::weak_ptr<Connection> > connections_;
138 // Readers are detached; Stop() waits for this to drop to zero
139 unsigned active_readers_;
140 std::condition_variable readers_cond_;
141
142 std::mutex queue_lock_;
143 std::condition_variable queue_cond_;
144 std::deque<Job> queue_;
145 };
146
147 } // namespace nfs4
148
149 #endif // CVMFS_NFS4_RPC_H_
150