예제 #1
0
        internal override async Task <bool> Stop(ulong timeout)
        {
            WSLOG("Stop");
            _mustStop = true;
            if (_reconnectionTimer != null)
            {
                _reconnectionTimer.Cancel();
            }

            foreach (Queue <WSRequest> queue in _workingRequests)
            {
                while (queue.Count > 0)
                {
                    WSRequest wsRequest = queue.Peek();
                    await wsRequest.getResponseBytes();

                    if (queue.Contains(wsRequest))
                    {
                        queue.Dequeue();
                    }
                }
            }

            _webSock.Close(1000, "");
            //_outDataWriter = null;
            WSLOG("Stop end");
            return(false);
        }
예제 #2
0
        internal override async Task <byte[]> hubRequestSync(string req_first_line, byte[] req_head_and_body, uint mstimeout)
        {
            WSRequest wsRequest = await sendRequest(req_first_line, req_head_and_body, HUB_TCP_CHANNEL, false, null, null);

            byte[] full_result = await wsRequest.getResponseBytes();

            byte[] immVerifyHttPheader = imm_verifyHTTPheader(full_result);
            return(immVerifyHttPheader);
        }
예제 #3
0
        internal override async Task <byte[]> devRequestSync(YDevice device, string req_first_line, byte[] req_head_and_body, uint mstimeout, YGenericHub.RequestProgress progress, object context)
        {
            if (mstimeout == 0)
            {
                // simulate a wait indefinitely
                mstimeout = 86400000; //24h
            }

            WSRequest wsRequest = await sendRequest(req_first_line, req_head_and_body, DEVICE_TCP_CHANNEL, false, progress, context);

            byte[] full_result = await wsRequest.getResponseBytes();

            return(imm_verifyHTTPheader(full_result));
        }
예제 #4
0
 internal override async Task devRequestAsync(YDevice device, string req_first_line, byte[] req_head_and_body, YGenericHub.RequestAsyncResult asyncResult, object asyncContext)
 {
     WSRequest wsRequest = await sendRequest(req_first_line, req_head_and_body, DEVICE_TCP_CHANNEL, true, null, null);
 }
예제 #5
0
        /*
         *   look through all pending request if there is some data that we can send
         *
         */
        private async Task processRequests(WSRequest request)
        {
            int tcpchan = request.Channel;

            int throttle_start = request.ReqPosition;
            int throttle_end   = request.ReqSize;

            if (throttle_end > 2108 && _remoteVersion >= YGenericHub.USB_META_WS_PROTO_V2 && tcpchan == 0)
            {
                // Perform throttling on large uploads
                if (request.ReqPosition == 0)
                {
                    // First chunk is always first multiple of full window (124 bytes) above 2KB
                    throttle_end = 2108;
                    // Prepare to compute effective transfer rate
                    _lastUploadAckBytes[tcpchan] = 0;
                    _lastUploadAckTime[tcpchan]  = 0;
                    // Start with initial RTT based estimate
                    _uploadRate = (int)(_tcpMaxWindowSize * 1000 / (int)_tcpRoundTripTime);
                }
                else if (_lastUploadAckTime[tcpchan] == 0)
                {
                    // first block not yet acked, wait more
                    throttle_end = 0;
                }
                else
                {
                    // adapt window frame to available bandwidth
                    long  bytesOnTheAir = request.ReqPosition - _lastUploadAckBytes[tcpchan];
                    ulong timeOnTheAir  = YAPI.GetTickCount() - _lastUploadAckTime[tcpchan];
                    int   uploadRate    = _uploadRate;
                    int   toBeSent      = (int)(2 * uploadRate + 1024 - bytesOnTheAir + (uploadRate * (int)timeOnTheAir / 1000));
                    if (toBeSent + bytesOnTheAir > DEFAULT_TCP_MAX_WINDOW_SIZE)
                    {
                        toBeSent = (int)(DEFAULT_TCP_MAX_WINDOW_SIZE - bytesOnTheAir);
                    }

                    WSLOG(string.Format("throttling: {0} bytes/s ({1} + {2} = {3})", _uploadRate, toBeSent, bytesOnTheAir, bytesOnTheAir + toBeSent));
                    if (toBeSent < 64)
                    {
                        ulong waitTime = (ulong)(1000 * (128 - toBeSent) / _uploadRate);
                        if (waitTime < 2)
                        {
                            waitTime = 2;
                        }
                        //_next_transmit_tm = YAPI.GetTickCount() + waitTime;
                        WSLOG(string.Format("WS: {0} sent {1}ms ago, waiting {2}ms...", bytesOnTheAir, timeOnTheAir, waitTime));
                        throttle_end = 0;
                    }

                    if (throttle_end > request.ReqPosition + toBeSent)
                    {
                        // when sending partial content, round up to full frames
                        if (toBeSent > 124)
                        {
                            toBeSent = (toBeSent / 124) * 124;
                        }

                        throttle_end = request.ReqPosition + toBeSent;
                    }
                }
            }

            while (request.ReqPosition < throttle_end)
            {
                IBuffer data;
                int     datalen = throttle_end - request.ReqPosition;
                if (datalen > MAX_DATA_LEN)
                {
                    datalen = MAX_DATA_LEN;
                }

                if (request.imm_isAsync() && (request.ReqPosition + datalen == request.ReqSize))
                {
                    if (datalen == MAX_DATA_LEN)
                    {
                        // last frame is already full we must send the async close in another one
                        data = request.imm_GetRequestData(request.ReqPosition, datalen);
                        await Send_WSStream(_webSock, YGenericHub.YSTREAM_TCP, tcpchan, data, 0);

                        //WSLOG(string.Format("ws_req:{0}: sent {1} bytes on chan{2} ({3}/{4})", request, datalen, tcpchan, request.ReqPosition, request.ReqSize));
                        request.imm_reportDataSent();
                        request.ReqPosition += datalen;
                        datalen              = 0;
                    }

                    data = request.imm_GetRequestData(request.ReqPosition, datalen);
                    await Send_WSStream(_webSock, YGenericHub.YSTREAM_TCP_ASYNCCLOSE, tcpchan, data, request.AsyncId);

                    //WSLOG(string.Format("ws_req:{0}: sent async close {1}", request, request.AsyncId));
                    request.ReqPosition += datalen;
                }
                else
                {
                    data = request.imm_GetRequestData(request.ReqPosition, datalen);
                    await Send_WSStream(_webSock, YGenericHub.YSTREAM_TCP, tcpchan, data, 0);

                    request.imm_reportDataSent();
                    //WSLOG(string.Format("ws_req:{0}: sent {1} bytes on chan{2} ({3}/{4})", request, datalen, tcpchan, request.ReqPosition, request.ReqSize));
                    request.ReqPosition += datalen;
                }
            }

            if (request.ReqPosition < request.ReqSize)
            {
                int sent = request.ReqPosition - throttle_start;
                // not completely sent, cannot do more for now
                if (sent > 0 && _uploadRate > 0)
                {
                    ulong waitTime = (ulong)(1000 * sent / _uploadRate);
                    if (waitTime < 2)
                    {
                        waitTime = 2;
                    }
                    //_next_transmit_tm = YAPI.GetTickCount() + waitTime;
                    WSLOG(string.Format("Sent {0}bytes, waiting {1}ms...", sent, waitTime));
                }
                else
                {
                    //_next_transmit_tm = YAPI.GetTickCount() + 100;
                }
            }
        }
예제 #6
0
        private async Task <WSRequest> sendRequest(string req_first_line, byte[] req_head_and_body, int tcpchanel, bool async, YGenericHub.RequestProgress progress, Object context)
        {
            WSRequest request;
            string    debug = req_first_line.Trim();

            byte[] full_request;
            byte[] req_first_lineBytes;
            if (req_head_and_body == null)
            {
                req_first_line     += "\r\n\r\n";
                req_first_lineBytes = YAPI.DefaultEncoding.GetBytes(req_first_line);
                full_request        = req_first_lineBytes;
            }
            else
            {
                req_first_line     += "\r\n";
                req_first_lineBytes = YAPI.DefaultEncoding.GetBytes(req_first_line);
                full_request        = new byte[req_first_lineBytes.Length + req_head_and_body.Length];
                Array.Copy(req_first_lineBytes, 0, full_request, 0, req_first_lineBytes.Length);
                Array.Copy(req_head_and_body, 0, full_request, req_first_lineBytes.Length, req_head_and_body.Length);
            }

            ulong timeout = YAPI.GetTickCount() + WS_REQUEST_MAX_DURATION;

            while ((_connectionState != ConnectionState.CONNECTED && _connectionState != ConnectionState.DEAD))
            {
                if (timeout < YAPI.GetTickCount())
                {
                    if (_connectionState != ConnectionState.CONNECTED && _connectionState != ConnectionState.CONNECTING)
                    {
                        throw new YAPI_Exception(YAPI.IO_ERROR, "IO error with hub");
                    }
                    else
                    {
                        throw new YAPI_Exception(YAPI.TIMEOUT, "Last request did not finished correctly");
                    }
                }

                if (_connectionState == ConnectionState.DEAD)
                {
                    throw new YAPI_Exception(_session_errno, _session_error);
                }
            }

            if (async)
            {
                request = new WSRequest(debug, tcpchanel, _nextAsyncId++, full_request);
                if (_nextAsyncId >= 127)
                {
                    _nextAsyncId = 48;
                }
            }
            else
            {
                request = new WSRequest(debug, tcpchanel, full_request, progress, context);
            }

            _workingRequests[tcpchanel].Enqueue(request);

            //todo: handle timeout
            await processRequests(request);

            if (request.ErrorCode != YAPI.SUCCESS)
            {
                throw new YAPI_Exception(request.ErrorCode, request.ErrorMsg);
            }

            return(request);
        }