tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StreamBinder.cpp (3828B)


      1 // StreamBinder.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../Common/MyCom.h"
      6 
      7 #include "StreamBinder.h"
      8 
      9 class CBinderInStream:
     10  public ISequentialInStream,
     11  public CMyUnknownImp
     12 {
     13  CStreamBinder *_binder;
     14 public:
     15  MY_UNKNOWN_IMP1(ISequentialInStream)
     16  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
     17  ~CBinderInStream() { _binder->CloseRead(); }
     18  CBinderInStream(CStreamBinder *binder): _binder(binder) {}
     19 };
     20 
     21 STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
     22  { return _binder->Read(data, size, processedSize); }
     23 
     24 class CBinderOutStream:
     25  public ISequentialOutStream,
     26  public CMyUnknownImp
     27 {
     28  CStreamBinder *_binder;
     29 public:
     30  MY_UNKNOWN_IMP1(ISequentialOutStream)
     31  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
     32  ~CBinderOutStream() { _binder->CloseWrite(); }
     33  CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
     34 };
     35 
     36 STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
     37  { return _binder->Write(data, size, processedSize); }
     38 
     39 
     40 
     41 WRes CStreamBinder::CreateEvents()
     42 {
     43  RINOK(_canWrite_Event.Create());
     44  RINOK(_canRead_Event.Create());
     45  return _readingWasClosed_Event.Create();
     46 }
     47 
     48 void CStreamBinder::ReInit()
     49 {
     50  _canWrite_Event.Reset();
     51  _canRead_Event.Reset();
     52  _readingWasClosed_Event.Reset();
     53 
     54  // _readingWasClosed = false;
     55  _readingWasClosed2 = false;
     56 
     57  _waitWrite = true;
     58  _bufSize = 0;
     59  _buf = NULL;
     60  ProcessedSize = 0;
     61  // WritingWasCut = false;
     62 }
     63 
     64 
     65 void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
     66 {
     67  // _readingWasClosed = false;
     68  _readingWasClosed2 = false;
     69 
     70  _waitWrite = true;
     71  _bufSize = 0;
     72  _buf = NULL;
     73  ProcessedSize = 0;
     74  // WritingWasCut = false;
     75 
     76  CBinderInStream *inStreamSpec = new CBinderInStream(this);
     77  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
     78  *inStream = inStreamLoc.Detach();
     79 
     80  CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
     81  CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
     82  *outStream = outStreamLoc.Detach();
     83 }
     84 
     85 // (_canRead_Event && _bufSize == 0) means that stream is finished.
     86 
     87 HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
     88 {
     89  if (processedSize)
     90    *processedSize = 0;
     91  if (size != 0)
     92  {
     93    if (_waitWrite)
     94    {
     95      RINOK(_canRead_Event.Lock());
     96      _waitWrite = false;
     97    }
     98    if (size > _bufSize)
     99      size = _bufSize;
    100    if (size != 0)
    101    {
    102      memcpy(data, _buf, size);
    103      _buf = ((const Byte *)_buf) + size;
    104      ProcessedSize += size;
    105      if (processedSize)
    106        *processedSize = size;
    107      _bufSize -= size;
    108      if (_bufSize == 0)
    109      {
    110        _waitWrite = true;
    111        _canRead_Event.Reset();
    112        _canWrite_Event.Set();
    113      }
    114    }
    115  }
    116  return S_OK;
    117 }
    118 
    119 HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
    120 {
    121  if (processedSize)
    122    *processedSize = 0;
    123  if (size == 0)
    124    return S_OK;
    125 
    126  if (!_readingWasClosed2)
    127  {
    128    _buf = data;
    129    _bufSize = size;
    130    _canRead_Event.Set();
    131    
    132    /*
    133    _canWrite_Event.Lock();
    134    if (_readingWasClosed)
    135      _readingWasClosed2 = true;
    136    */
    137 
    138    HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
    139    DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
    140    if (waitResult >= WAIT_OBJECT_0 + 2)
    141      return E_FAIL;
    142 
    143    size -= _bufSize;
    144    if (size != 0)
    145    {
    146      if (processedSize)
    147        *processedSize = size;
    148      return S_OK;
    149    }
    150    // if (waitResult == WAIT_OBJECT_0 + 1)
    151      _readingWasClosed2 = true;
    152  }
    153 
    154  // WritingWasCut = true;
    155  return k_My_HRESULT_WritingWasCut;
    156 }