xref: /haiku/src/add-ons/kernel/network/protocols/unix/UnixFifo.h (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2  * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef UNIX_FIFO_H
6 #define UNIX_FIFO_H
7 
8 #include <Referenceable.h>
9 
10 #include <condition_variable.h>
11 #include <lock.h>
12 #include <util/AutoLock.h>
13 #include <util/DoublyLinkedList.h>
14 
15 #include <net_buffer.h>
16 
17 
18 #define UNIX_FIFO_SHUTDOWN_READ		1
19 #define UNIX_FIFO_SHUTDOWN_WRITE	2
20 
21 #define UNIX_FIFO_SHUTDOWN			(B_ERRORS_END + 1)
22 	// error code returned by Read()/Write()
23 
24 #define UNIX_FIFO_MINIMAL_CAPACITY	1024
25 #define UNIX_FIFO_MAXIMAL_CAPACITY	(128 * 1024)
26 
27 
28 enum class UnixFifoType {
29 	Stream,
30 	Datagram
31 };
32 
33 
34 struct ring_buffer;
35 
36 class UnixRequest : public DoublyLinkedListLinkImpl<UnixRequest> {
37 public:
38 	UnixRequest(const iovec* vecs, size_t count,
39 			ancillary_data_container* ancillaryData,
40 			struct sockaddr_storage* address);
41 
42 	off_t TotalSize() const			{ return fTotalSize; }
43 	off_t BytesTransferred() const	{ return fBytesTransferred; }
44 	off_t BytesRemaining() const	{ return fTotalSize - fBytesTransferred; }
45 
46 	void AddBytesTransferred(size_t size);
47 	bool GetCurrentChunk(void*& data, size_t& size);
48 
49 	ancillary_data_container* AncillaryData() const	 { return fAncillaryData; }
50 	void SetAncillaryData(ancillary_data_container* data);
51 	void AddAncillaryData(ancillary_data_container* data);
52 
53 	struct sockaddr_storage* Address() const	{ return fAddress; }
54 
55 private:
56 	const iovec*					fVecs;
57 	size_t							fVecCount;
58 	ancillary_data_container*		fAncillaryData;
59 	off_t							fTotalSize;
60 	off_t							fBytesTransferred;
61 	size_t							fVecIndex;
62 	size_t							fVecOffset;
63 	struct sockaddr_storage*		fAddress;
64 };
65 
66 
67 class UnixBufferQueue {
68 public:
69 	UnixBufferQueue(size_t capacity, UnixFifoType type);
70 	~UnixBufferQueue();
71 
72 	status_t Init();
73 
74 	size_t	Readable() const;
75 	size_t	Writable() const;
76 
77 	status_t Read(UnixRequest& request);
78 	status_t Write(UnixRequest& request);
79 
80 	size_t Capacity() const				{ return fCapacity; }
81 	status_t SetCapacity(size_t capacity);
82 
83 private:
84 	struct AncillaryDataEntry : DoublyLinkedListLinkImpl<AncillaryDataEntry> {
85 		ancillary_data_container*	data;
86 		size_t						offset;
87 	};
88 
89 	typedef DoublyLinkedList<AncillaryDataEntry> AncillaryDataList;
90 
91 	struct DatagramEntry : DoublyLinkedListLinkImpl<DatagramEntry> {
92 		struct sockaddr_storage	address;
93 		size_t	size;
94 	};
95 
96 	typedef DoublyLinkedList<DatagramEntry> DatagramList;
97 
98 	ring_buffer*		fBuffer;
99 	size_t				fCapacity;
100 	AncillaryDataList	fAncillaryData;
101 	DatagramList		fDatagrams;
102 	UnixFifoType		fType;
103 };
104 
105 
106 class UnixFifo : public BReferenceable {
107 public:
108 	UnixFifo(size_t capacity, UnixFifoType type);
109 	~UnixFifo();
110 
111 	status_t Init();
112 
113 	bool Lock()
114 	{
115 		return mutex_lock(&fLock) == B_OK;
116 	}
117 
118 	void Unlock()
119 	{
120 		mutex_unlock(&fLock);
121 	}
122 
123 	void Shutdown(uint32 shutdown);
124 
125 	bool IsReadShutdown() const
126 	{
127 		return (fShutdown & UNIX_FIFO_SHUTDOWN_READ);
128 	}
129 
130 	bool IsWriteShutdown() const
131 	{
132 		return (fShutdown & UNIX_FIFO_SHUTDOWN_WRITE);
133 	}
134 
135 	ssize_t Read(const iovec* vecs, size_t vecCount,
136 		ancillary_data_container** _ancillaryData,
137 		struct sockaddr_storage* address, bigtime_t timeout);
138 	ssize_t Write(const iovec* vecs, size_t vecCount,
139 		ancillary_data_container* ancillaryData,
140 		const struct sockaddr_storage* address, bigtime_t timeout);
141 
142 	size_t Readable() const;
143 	size_t Writable() const;
144 
145 	status_t SetBufferCapacity(size_t capacity);
146 
147 private:
148 	typedef DoublyLinkedList<UnixRequest> RequestList;
149 
150 private:
151 	status_t _Read(UnixRequest& request, bigtime_t timeout);
152 	status_t _Write(UnixRequest& request, bigtime_t timeout);
153 	status_t _WriteNonBlocking(UnixRequest& request);
154 	size_t _MinimumWritableSize(const UnixRequest& request) const;
155 
156 private:
157 	mutex				fLock;
158 	UnixBufferQueue		fBuffer;
159 	RequestList			fReaders;
160 	RequestList			fWriters;
161 	off_t				fReadRequested;
162 	off_t				fWriteRequested;
163 	ConditionVariable	fReadCondition;
164 	ConditionVariable	fWriteCondition;
165 	uint32				fShutdown;
166 	UnixFifoType		fType;
167 };
168 
169 
170 typedef AutoLocker<UnixFifo> UnixFifoLocker;
171 
172 
173 #endif	// UNIX_FIFO_H
174