yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_CORE_HTTP_H 2#define SLANG_CORE_HTTP_H 3 4#include "slang-com-helper.h" 5#include "slang-com-ptr.h" 6#include "slang-list.h" 7#include "slang-memory-arena.h" 8#include "slang-stream.h" 9#include "slang-string.h" 10#include "slang.h" 11 12namespace Slang 13{ 14 15/// All of the contained UnownedStringSlice can be stored in m_header. This can be checked via 16/// testing if the memory overlaps. 17/// 18/// The m_arena can be used to store slices in an ad-hoc manner to keep in scope with the Header. 19struct HTTPHeader 20{ 21struct Pair 22 { 23UnownedStringSlice key ; 24UnownedStringSlice value ; 25 }; 26 27/// Append the header (including termination) to out 28void append (StringBuilder & out )const ; 29 30/// Reset the contents 31void reset (); 32 33SLANG_INLINE Index indexOfKey (const UnownedStringSlice & slice )const ; 34 35/// Ctor 36HTTPHeader () 37 :m_arena (1024 ) 38 { 39 } 40 41/// Reads from stream until the buffer contains all of the header. The outEndIndex will point 42/// past the header termination. 43static SlangResult readHeaderText (BufferedReadStream * stream ,Index & outEndIndex ); 44 45/// Returns the index of the end of the header (index of first byte *after* the header), or < if 46/// doesn't have an end 47static Index findHeaderEnd (BufferedReadStream * stream ); 48 49/// Parse the slice (holding a header) into out. 50/// Will allocate the slice on the array and store in m_header. 51/// Slices will reference sections of m_header, that may be useful in some scenarios. 52static SlangResult parse (const UnownedStringSlice & slice ,HTTPHeader & out ); 53 54/// Read from buffered stream header, and place parsed header into out 55static SlangResult read (BufferedReadStream * stream ,HTTPHeader & out ); 56 57size_t m_contentLength ;///< Content length in bytes 58 59UnownedStringSlice m_mimeType ;///< The mime type 60UnownedStringSlice m_encoding ;///< The character encoding 61 62UnownedStringSlice m_header ;///< Optionally holds the whole of the header 63 64List < Pair > m_valuePairs ;/// All of the value pairs 65 66MemoryArena m_arena ;///< Used to store backing memory 67 68private : 69// Disable 70HTTPHeader (const HTTPHeader & )= delete ; 71void operator = (const HTTPHeader & )= delete ; 72}; 73 74// ----------------------------------------------------------------- 75Index HTTPHeader ::indexOfKey (const UnownedStringSlice & slice )const 76{ 77return m_valuePairs .findFirstIndex ( 78 [& ](const HTTPHeader::Pair & pair) -> bool { return pair. key == slice; }); 79} 80 81/// Implements a way to communicate over Streams via the HTTP *protocol*. 82/// 83/// Allows for reading without blocking, via calls to 'update'. When a complete 84/// HTTP 'packet' (combination of header and content) is available, the ReadState will 85/// become 'Done'. For this to work without blocking it relies on the stream backing the 86/// BufferedReadStream to be non blocking. 87/// 88/// If it is only necessary to respond on complete packets 'waitForContent' can be used. 89/// If this returns and ReadState is Done, then getHeader holds the current header, and getContent 90/// holds the content of the 'packet'. 91/// 92/// Once the packet has been processed 'consumeContent' can be used. Once consumeContent is called 93/// both contents of getContent and getReadHeader will no longer be valid. 94/// 95/// Ie using the slice returned from getContent *after* consumeContent is called is *undefined 96/// behavior*. 97/// 98/// NOTE! that this does not implement HTTP over TCP/IP. 99/// That said it could be used to communicate via the HTTP protocol over TCP/IP 100/// if the Streams supplied were TCP/IP sockets. 101class HTTPPacketConnection : public RefObject 102{ 103public : 104enum class ReadState 105{ 106Header, ///< Reading reader 107Content, ///< Reading content (ie header is read) 108Done, ///< The content is read 109Closed, ///< The read stream is closed - no further packets can be read 110Error, ///< In an error state - no further packets can be read 111}; 112 113/// Update state 114SlangResult update (); 115/// Get the current read staet 116ReadState getReadState () const { return m_readState; } 117/// Get the read header 118const HTTPHeader & getReadHeader () const 119{ 120SLANG_ASSERT ( hasHeader ()); 121return m_readHeader; 122} 123/// Get the content 124ConstArrayView < Byte > getContent () const 125{ 126SLANG_ASSERT ( m_readState == ReadState::Done); 127return ConstArrayView < Byte > ( 128( const Byte * )m_readStream -> getBuffer (), 129m_readHeader.m_contentLength); 130} 131 132/// Write. Will potentially block if write stream is blocking. 133SlangResult write ( const void * content, size_t sizeInBytes); 134 135/// Blocks until some result - a packet, closure, or some kind of error or timeout. 136/// TimeOut of -1 means no timeout. 137SlangResult waitForResult ( Int timeOutInMs = -1 ); 138/// Consume the content - so can read next content 139void consumeContent (); 140 141/// True if connection is active. 142bool isActive () const 143{ 144return m_readState != ReadState::Error && m_readState != ReadState::Closed; 145} 146 147bool hasHeader () const 148{ 149return m_readState == ReadState::Content || m_readState == ReadState::Done; 150} 151/// True if has content (implies has header) 152bool hasContent () const { return m_readState == ReadState::Done; } 153 154/// Ctor 155HTTPPacketConnection (BufferedReadStream * readStream, Stream * writeStream); 156 157protected : 158SlangResult _updateReadResult ( SlangResult res) 159{ 160if ( SLANG_FAILED (res) && SLANG_SUCCEEDED (m_readResult)) 161{ 162m_readState = ReadState::Error; 163m_readResult = res; 164} 165return res; 166} 167 168SlangResult _handleHeader (); 169SlangResult _handleContent (); 170 171SlangResult m_readResult; 172HTTPHeader m_readHeader; 173 174ReadState m_readState; 175 176RefPtr < BufferedReadStream > m_readStream; 177RefPtr < Stream > m_writeStream; 178}; 179 180} // namespace Slang 181 182#endif // SLANG_CORE_HTTP_H