The Pedigree Project 0.1
net-syscalls.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef NET_SYSCALLS_H
21#define NET_SYSCALLS_H
22
23#include "pedigree/kernel/Atomic.h"
24#include "pedigree/kernel/LockGuard.h"
25#include "pedigree/kernel/process/Mutex.h"
26#include "pedigree/kernel/process/OperationBarrier.h"
27#include "pedigree/kernel/process/Readiness.h"
28#include "pedigree/kernel/utilities/List.h"
29#include "pedigree/kernel/utilities/String.h"
30#include "pedigree/kernel/utilities/Tree.h"
31
32#include "logging.h"
33#include "modules/subsys/posix/UnixFilesystem.h"
34#include <sys/socket.h>
35#include <sys/types.h>
36
37// Must be after sys/types.h to avoid problems with endian.h
39
40extern Filesystem* g_pUnixSocketBacking;
41
42struct sockaddr;
43struct pbuf;
44struct netbuf;
45struct netconn;
46
47class Semaphore;
48class FileDescriptor;
49class DescriptorLease;
50class UnixSocket;
53class Process;
54class Thread;
55class Event;
56
62bool finishInterruptibleSocketCall(Thread* thread, ssize_t result);
63bool finishInterruptibleSocketCall(Thread* thread, bool result) = delete;
64
65#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
66using UnixEndpointMutationLockHook = void (*)();
67using UnixEndpointReadinessLeaseHook = void (*)();
68void setUnixEndpointMutationLockHookForTest(UnixEndpointMutationLockHook hook);
69void setUnixEndpointReadinessLeaseHookForTest(UnixEndpointReadinessLeaseHook hook);
70#endif
71
72ssize_t posix_send_descriptor(const DescriptorLease& descriptor, const void* buffer,
73 size_t bufferLength, int flags, bool kernelBuffer = false);
74ssize_t posix_recv_descriptor(const DescriptorLease& descriptor, void* buffer, size_t bufferLength,
75 int flags);
76ssize_t posix_sendmsg_descriptor(
77 const DescriptorLease& descriptor, const struct msghdr* message,
79 bool kernelBuffer = false);
80ssize_t posix_recvmsg_descriptor(const DescriptorLease& descriptor, struct msghdr* message,
81 SharedPointer<SocketRights>* rights = nullptr);
82
84 public:
85 NetworkSyscalls(int domain, int type, int protocol);
86 virtual ~NetworkSyscalls();
87
90 virtual bool create();
91 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen) = 0;
92
93 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
94 const SharedPointer<SocketRights>& rights) = 0;
95 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights) = 0;
96
97 virtual ssize_t sendto(const void* buffer, size_t bufferlen, int flags,
98 const struct sockaddr_storage* address, socklen_t addrlen);
99 virtual ssize_t recvfrom(void* buffer, size_t bufferlen, int flags,
100 struct sockaddr_storage* address, socklen_t* addrlen);
101
102 virtual int listen(int backlog) = 0;
103 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen) = 0;
104 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
105 DescriptorLease* accepted = nullptr) = 0;
106
107 virtual int shutdown(int how);
108
109 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len) = 0;
110 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len) = 0;
111
112 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen) = 0;
113 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen) = 0;
114
115 virtual bool canPoll() const;
116 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
117 virtual void unPoll(Semaphore* waiter);
118
120 virtual ReadyMask queryReady(bool reading, bool writing);
122
125 void removeDescriptorOwner();
126
129
136 virtual void lastDescriptorClosed();
137
138 virtual bool monitor(Thread* pThread, Event* pEvent);
139 virtual bool unmonitor(Event* pEvent);
140
141 void associate(FileDescriptor* fd);
142
143 int getDomain() const {
144 return m_Domain;
145 }
146
147 int getType() const {
148 return m_Type;
149 }
150
151 int getProtocol() const {
152 return m_Protocol;
153 }
154
155 bool isBlocking() const;
156
157 virtual void setBlocking(bool blocking);
158
159 int takeReceiveError();
160 void deferReceiveError(int error);
161
162 protected:
163 ReadyMask pendingReceiveReadiness() const;
164 ReadinessGenerations withReceiveErrorGeneration(ReadinessGenerations generations) const;
165
168
169 bool hasLastDescriptorClosed() const;
170
171 SharedPointer<NetworkSyscalls> acquireDescriptorLifetime() const;
172 SharedPointer<NetworkSyscalls> releaseDescriptorLifetime();
173
174 int m_Domain;
175 int m_Type;
176 int m_Protocol;
177
178 Atomic<bool> m_Blocking;
179 mutable Mutex m_ReceiveErrorLock;
180 int m_ReceiveError = 0;
181 uint64_t m_ReceiveErrorGeneration = 0;
182
185
186 private:
187 mutable Mutex m_LifecycleLock;
188 size_t m_DescriptorOwners;
189 bool m_DescriptorAdmissionOpen;
190 bool m_LastDescriptorClosed;
191 SharedPointer<NetworkSyscalls> m_DescriptorLifetime;
192};
193
195 public:
196 LwipSocketSyscalls(int domain, int type, int protocol);
197 virtual ~LwipSocketSyscalls();
198
200 virtual bool create();
201 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen);
202
203 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
204 const SharedPointer<SocketRights>& rights);
205 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights);
206
207 virtual int listen(int backlog);
208 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen);
209 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
210 DescriptorLease* accepted = nullptr);
211
212 virtual int shutdown(int how);
213
214 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len);
215 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len);
216
217 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen);
218 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen);
219
220 virtual bool canPoll() const;
221 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
222 virtual void unPoll(Semaphore* waiter);
223 virtual ReadyMask queryReady(bool reading, bool writing);
225 virtual void lastDescriptorClosed();
226
227 virtual void setBlocking(bool blocking);
228
229 private:
230 static Tree<struct netconn*, LwipSocketSyscalls*> m_SyscallObjects;
231 static Mutex m_SyscallObjectsLock;
232
233 static void netconnCallback(struct netconn* conn, enum netconn_evt evt, uint16_t len);
234 static void lwipToSyscallError(err_t err);
235 void registerSocket();
236 ReadyMask readinessLevelLocked() const;
237 void recordReadinessRisesLocked(ReadyMask previous);
238
239 struct netconn* m_Socket;
240 Mutex m_ReceiveLock;
241
243 LwipMetadata();
244
245 ssize_t recv;
246 ssize_t send;
247 err_t error;
248 bool closed;
249 bool peerClosed;
250 bool writeClosed;
251 bool listening;
252 bool partialRead;
253 bool receivingQueuedData;
254
255 Mutex lock;
256 List<Semaphore*> semaphores;
257
258 size_t offset;
259 struct pbuf* pb;
260 struct netbuf* buf;
261 ReadinessGenerations generations;
262 } m_Metadata;
263};
264
266 public:
267 UnixSocketSyscalls(int domain, int type, int protocol);
268 virtual ~UnixSocketSyscalls();
269
271 virtual bool create();
272 virtual int connect(const struct sockaddr_storage* address, socklen_t addrlen);
273
274 virtual ssize_t sendto_msg(const struct msghdr* msghdr,
275 const SharedPointer<SocketRights>& rights);
276 virtual ssize_t recvfrom_msg(struct msghdr* msghdr, SharedPointer<SocketRights>* rights);
277
278 virtual int listen(int backlog);
279 virtual int bind(const struct sockaddr_storage* address, socklen_t addrlen);
280 virtual int accept(struct sockaddr_storage* address, socklen_t* addrlen, int flags,
281 DescriptorLease* accepted = nullptr);
282
283 virtual int shutdown(int how);
284
285 virtual int getpeername(struct sockaddr_storage* address, socklen_t* address_len);
286 virtual int getsockname(struct sockaddr_storage* address, socklen_t* address_len);
287
288 virtual int setsockopt(int level, int optname, const void* optvalue, socklen_t optlen);
289 virtual int getsockopt(int level, int optname, void* optvalue, socklen_t* optlen);
290
291 virtual bool canPoll() const;
292 virtual bool poll(bool& read, bool& write, bool& error, Semaphore* waiter);
293 virtual void unPoll(Semaphore* waiter);
294 virtual ReadyMask queryReady(bool reading, bool writing);
296 virtual void lastDescriptorClosed();
297
298 virtual bool monitor(Thread* pThread, Event* pEvent);
299 virtual bool unmonitor(Event* pEvent);
300
303 bool pairWith(UnixSocketSyscalls* other);
304
305 private:
306 friend class UnixSocketGeneration;
307 friend bool runHostedUnixEndpointLifetimeRegression(Process* process);
308
309 // Endpoint generations and their ownership must not be duplicated implicitly.
310 NOT_COPYABLE_OR_ASSIGNABLE(UnixSocketSyscalls);
311
312 static Tree<UnixSocket*, UnixSocketSyscalls*> m_SyscallObjects;
313 static Tree<UnixSocket*, UnixSocket*> m_Peers;
314 static Tree<UnixSocket*, UnixSocket*> m_PendingListeners;
315 static Mutex m_SyscallObjectsLock;
317 public:
320
321 private:
322 UnixSocketSyscalls& m_Socket;
323 LockGuard<Mutex> m_Guard;
324 };
325
327 public:
330
331 private:
332 UnixSocketSyscalls& m_First;
333 UnixSocketSyscalls& m_Second;
334 LockGuard<Mutex> m_FirstGuard;
335 LockGuard<Mutex> m_SecondGuard;
336 };
337
339 public:
343
344 MUST_USE_RESULT bool acquire(UnixSocketSyscalls& socket);
345
346 explicit operator bool() const {
347 return m_Acquired;
348 }
349
350 private:
351 UnixSocketSyscalls* m_Socket;
354 bool m_Acquired;
355 };
356
357 void registerSocket(UnixSocket* socket);
358 void registerPeer(UnixSocket* socket, UnixSocket* peer, UnixSocket* listener = nullptr);
359 void unregisterPeer(UnixSocket* socket, UnixSocket* peer);
360 static void unregisterSocket(UnixSocket* socket, List<UnixSocket*>& peers);
361 void notifyPeer(UnixSocket* socket, ReadyMask mask);
362 static void notifySocket(UnixSocket* socket, ReadyMask mask);
363 static bool publishAbstractSocket(const String& address,
364 const SharedPointer<UnixSocketReference>& reference);
365 static SharedPointer<UnixSocketReference> acquireSocket(const String& address);
366 static void removeAbstractSocket(const String& address, UnixSocket* socket);
367
368 SharedPointer<UnixSocketGeneration> acquireLocalEndpoint() const;
369 void replaceLocalEndpoint(UnixSocket* socket, bool tracked, const String* localPath = nullptr);
370 void replaceLocalEndpoint(const SharedPointer<UnixSocketReference>& reference,
371 const String* localPath, bool ownsAbstractName);
372 void tryCompleteEndpointClose();
373
374 UnixSocket::SocketType getSocketType() const;
375
380 Atomic<bool> m_EndpointMutationReleaseInProgress;
381 Atomic<bool> m_EndpointClosePending;
382 Atomic<bool> m_EndpointRetired;
383 Atomic<bool> m_EndpointCloseFinalized;
385 SharedPointer<UnixSocketReference> m_RemoteEndpoint;
386 SharedPointer<UnixSocketGeneration> m_ClosingLocalEndpoint;
387 SharedPointer<UnixSocketReference> m_ClosingRemoteEndpoint;
388
389 String m_LocalPath;
390 String m_RemotePath;
391 bool m_OwnsAbstractName;
392};
393
395struct netconnMetadata* getNetconnMetadata(struct netconn* conn);
396
397int posix_socket(int domain, int type, int protocol);
398int posix_socketpair(int domain, int type, int protocol, int sv[2]);
399int posix_connect(int sock, const struct sockaddr_storage* address, socklen_t addrlen);
400
401ssize_t posix_send(int sock, const void* buff, size_t bufflen, int flags);
402ssize_t posix_sendto(int sock, const void* buff, size_t bufflen, int flags,
403 struct sockaddr_storage* address, socklen_t addrlen);
404ssize_t posix_recv(int sock, void* buff, size_t bufflen, int flags);
405ssize_t posix_recvfrom(int sock, void* buff, size_t bufflen, int flags,
406 struct sockaddr_storage* address, socklen_t* addrlen);
407
408int posix_listen(int sock, int backlog);
409int posix_bind(int sock, const struct sockaddr_storage* address, socklen_t addrlen);
410int posix_accept(int sock, struct sockaddr_storage* address, socklen_t* addrlen);
411int posix_accept4(int sock, struct sockaddr_storage* address, socklen_t* addrlen, int flags);
412
413int posix_shutdown(int socket, int how);
414
415int posix_getpeername(int socket, struct sockaddr_storage* address, socklen_t* address_len);
416int posix_getsockname(int socket, struct sockaddr_storage* address, socklen_t* address_len);
417
418int posix_setsockopt(int sock, int level, int optname, const void* optvalue, socklen_t optlen);
419int posix_getsockopt(int sock, int level, int optname, void* optvalue, socklen_t* optlen);
420
421int posix_sethostname(const char* name, size_t len);
422
423ssize_t posix_sendmsg(int sockfd, const struct msghdr* msg, int flags);
424ssize_t posix_recvmsg(int sockfd, struct msghdr* msg, int flags);
425
426#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
427bool runHostedUnixEndpointLifetimeRegression(Process* process);
428#endif
429
430#endif
Definition Event.h:49
Definition List.h:61
static void netconnCallback(struct netconn *conn, enum netconn_evt evt, uint16_t len)
ReadinessGenerations readinessGenerations() override
virtual int connect(const struct sockaddr_storage *address, socklen_t addrlen)
virtual void lastDescriptorClosed()
virtual int getpeername(struct sockaddr_storage *address, socklen_t *address_len)
virtual int accept(struct sockaddr_storage *address, socklen_t *addrlen, int flags, DescriptorLease *accepted=nullptr)
virtual ReadyMask queryReady(bool reading, bool writing)
virtual bool poll(bool &read, bool &write, bool &error, Semaphore *waiter)
virtual bool create()
Implementation-specific final socket creation logic.
virtual int getsockname(struct sockaddr_storage *address, socklen_t *address_len)
Definition Mutex.h:56
bool beginDescriptorClose()
virtual ReadyMask queryReady(bool reading, bool writing)
MUST_USE_RESULT bool addDescriptorOwner()
virtual void lastDescriptorClosed()
OperationBarrier m_ReadinessNotifications
virtual bool create()
ReadinessGenerations readinessGenerations() override
void retainDescriptorLifetime(const SharedPointer< NetworkSyscalls > &lifetime)
A key/value dictionary.
Definition Tree.h:33
virtual int listen(int backlog)
virtual void lastDescriptorClosed()
ReadinessGenerations readinessGenerations() override
bool pairWith(UnixSocketSyscalls *other)
virtual int bind(const struct sockaddr_storage *address, socklen_t addrlen)
virtual bool create()
Implementation-specific final socket creation logic.
virtual ReadyMask queryReady(bool reading, bool writing)
s8_t err_t
Definition err.h:76
Definition pbuf.h:161