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 AddAncillaryData(ancillary_data_container* data); 51 void UnsetAncillaryData(); 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 final : 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