Esempio n. 1
0
        int ProcessReadOrWrite(ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, LazyAsyncResult lazyResult)
        {
            if (userBuffer == null || userBuffer.Buffer == null)
            {
                throw new ArgumentNullException("buffer");
            }
            if (userBuffer.Offset < 0)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (userBuffer.Size < 0 || userBuffer.Offset + userBuffer.Size > userBuffer.Buffer.Length)
            {
                throw new ArgumentOutOfRangeException("count");
            }

            CheckThrow(true);

            var name = internalBuffer == readBuffer ? "read" : "write";

            Debug("ProcessReadOrWrite: {0} {1}", name, userBuffer);

            var asyncRequest = new AsyncProtocolRequest(this, lazyResult, userBuffer);

            return(StartOperation(ref nestedRequest, ref internalBuffer, operation, asyncRequest, name));
        }
Esempio n. 2
0
        int StartOperation(ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, AsyncProtocolRequest asyncRequest, string name)
        {
            if (Interlocked.CompareExchange(ref nestedRequest, asyncRequest, null) != null)
            {
                throw new InvalidOperationException("Invalid nested call.");
            }

            bool failed = false;

            try {
                internalBuffer.Reset();
                asyncRequest.StartOperation(operation);
                return(asyncRequest.UserResult);
            } catch (Exception e) {
                failed = true;
                if (e is IOException)
                {
                    throw;
                }
                throw new IOException(name + " failed", e);
            } finally {
                if (asyncRequest.UserAsyncResult == null || failed)
                {
                    internalBuffer.Reset();
                    nestedRequest = null;
                }
            }
        }
Esempio n. 3
0
        IAsyncResult BeginReadOrWrite(ref AsyncProtocolRequest nestedRequest, ref BufferOffsetSize2 internalBuffer, AsyncOperation operation, BufferOffsetSize userBuffer, AsyncCallback asyncCallback, object asyncState)
        {
            LazyAsyncResult lazyResult = new LazyAsyncResult(this, asyncState, asyncCallback);

            ProcessReadOrWrite(ref nestedRequest, ref internalBuffer, operation, userBuffer, lazyResult);
            return(lazyResult);
        }
Esempio n. 4
0
        bool InternalWrite(AsyncProtocolRequest asyncRequest, BufferOffsetSize2 internalBuffer, byte[] buffer, int offset, int size)
        {
            Debug("InternalWrite: {0} {1} {2} {3}", asyncRequest != null, internalBuffer, offset, size);

            if (asyncRequest == null)
            {
                /*
                 * The only situation where 'asyncRequest' could possibly be 'null' is when we're called
                 * from within SSLClose() - which might attempt to send the close_notity notification.
                 * Since this notification message is very small, it should definitely fit into our internal
                 * buffer, so we just save it in there and after SSLClose() returns, the final call to
                 * InternalFlush() - just before closing the underlying stream - will send it out.
                 */
                if (lastException != null)
                {
                    return(false);
                }

                if (Interlocked.Exchange(ref closeRequested, 1) == 0)
                {
                    internalBuffer.Reset();
                }
                else if (internalBuffer.Remaining == 0)
                {
                    throw new InvalidOperationException();
                }
            }

            /*
             * Normal write - can be either SSLWrite() or SSLHandshake().
             *
             * It is important that we always accept all the data and queue it.
             */

            internalBuffer.AppendData(buffer, offset, size);

            /*
             * Calling 'asyncRequest.RequestWrite()' here ensures that ProcessWrite() is called next
             * time we regain control from native code.
             *
             * During the handshake, the native code won't actually realize (unless if attempts to send
             * so much that the write buffer gets full) that we only buffered the data.
             *
             * However, it doesn't matter because it will either return with a completed handshake
             * (and doesn't care whether the remote actually received the data) or it will expect more
             * data from the remote and request a read.  In either case, we regain control in managed
             * code and can flush out the data.
             *
             * Note that a calling RequestWrite() followed by RequestRead() will first flush the write
             * queue once we return to managed code - before attempting to read anything.
             */
            if (asyncRequest != null)
            {
                asyncRequest.RequestWrite();
            }

            return(true);
        }
Esempio n. 5
0
        public MobileAuthenticatedStream(Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings, AppleTlsProvider provider)
            : base(innerStream, leaveInnerStreamOpen)
        {
            Settings = settings;
            Provider = provider;

            readBuffer  = new BufferOffsetSize2(16834);
            writeBuffer = new BufferOffsetSize2(16384);
        }