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