internal async Task RequestProgress(string req_first_line, HandleIncommingData progressCb)
        {
            //log("STA_Progress:" + req_first_line.TrimEnd());
            await EnsureLastRequestDone();
            await doRequestTask(req_first_line, null, 0, null, null, progressCb);

            //log("END_Progress:" + req_first_line.TrimEnd());
        }
        internal async Task <byte[]> doRequestTask(string firstLine, byte[] rest_of_request, ulong mstimeout, object context, YGenericHub.RequestAsyncResult resultCallback, HandleIncommingData progressCb)
        {
            byte[] full_request;
            int    retrycount = 0;

            _context          = context;
            _resultCallback   = resultCallback;
            _requestTimeout   = mstimeout;
            _progressCallback = progressCb;

retry:
            if (retrycount++ == 2)
            {
                string msg = "too many retry";
                if (resultCallback != null)
                {
                    await resultCallback(context, null, YAPI.IO_ERROR, msg);

                    return(null);
                }
                else
                {
                    throw new YAPI_Exception(YAPI.IO_ERROR, msg);
                }
            }

            log(String.Format("Start({0}):{1}", _reuse_socket ? "reuse" : "new", firstLine));
            _startRequestTime = YAPI.GetTickCount();
            _header_found     = false;
            string persistent_tag = firstLine.Substring(firstLine.Length - 2);

            if (persistent_tag.Equals("&."))
            {
                firstLine += " \r\n";
            }
            else
            {
                firstLine += " \r\nConnection: close\r\n";
            }

            if (rest_of_request == null)
            {
                string str_request = firstLine + _hub.imm_getAuthorization(firstLine) + "\r\n";
                full_request = YAPI.DefaultEncoding.GetBytes(str_request);
            }
            else
            {
                string str_request = firstLine + _hub.imm_getAuthorization(firstLine);
                int    len         = str_request.Length;
                full_request = new byte[len + rest_of_request.Length];
                Array.Copy(YAPI.DefaultEncoding.GetBytes(str_request), 0, full_request, 0, len);
                Array.Copy(rest_of_request, 0, full_request, len, rest_of_request.Length);
            }

            _result.SetLength(0);
            _header.Length = 0;
            byte[]     buffer = new byte[1024];
            Task <int> readTask;

            try {
                if (!_reuse_socket)
                {
                    // Creates an unconnected socket
                    _socket = new StreamSocket();
                    // Connect the socket to the remote endpoint. Catch any errors.
                    HostName serverHost = new HostName(_hub._http_params.Host);
                    int      port       = _hub._http_params.Port;
                    _socket.Control.NoDelay = true;
                    string port_str = port.ToString();
                    await _socket.ConnectAsync(serverHost, port_str);

                    _out = _socket.OutputStream.AsStreamForWrite();
                    _in  = _socket.InputStream.AsStreamForRead();
                    log(String.Format(" - new socket ({0} / {1})", _socket.ToString(), _in.ToString()));
                }

                readTask = _in.ReadAsync(buffer, 0, buffer.Length);
                if (_reuse_socket)
                {
                    try {
                        Task task = await Task.WhenAny(readTask, Task.Delay(0));

                        if (task == readTask)
                        {
                            int read = readTask.Result;
                            if (read == 0)
                            {
                                //socket has been reseted
                                log(String.Format(" - reset socket {0} {1})", _socket.ToString(), read));
                                closeSocket();
                                goto retry;
                            }

                            string msg = "suspect data received before request. Reset the socket";
                            log(msg);
                            throw new Exception(msg);
                        }
                    } catch (Exception e) {
                        log("Reset socket connection:" + e.Message);
                        closeSocket();
                        goto retry;
                    }
                }
            } catch (Exception e) {
                log("Exception on socket connection:" + e.Message);
                closeSocket();
                if (resultCallback != null)
                {
                    await resultCallback(context, null, YAPI.IO_ERROR, e.Message);

                    return(null);
                }
                else
                {
                    throw new YAPI_Exception(YAPI.IO_ERROR, e.Message);
                }
            }

            // write request
            try {
                await _out.WriteAsync(full_request, 0, full_request.Length);

                await _out.FlushAsync();
            } catch (Exception e) {
                closeSocket();
                if (resultCallback != null)
                {
                    await resultCallback(context, null, YAPI.IO_ERROR, e.Message);

                    return(null);
                }
                else
                {
                    throw new YAPI_Exception(YAPI.IO_ERROR, e.Message);
                }
            }

            _reuse_socket = false;
            bool eof = false;

            do
            {
                int read;
                try {
                    int   waitms;
                    ulong now;
                    if (_requestTimeout > 0)
                    {
                        now = YAPI.GetTickCount();
                        ulong read_timeout = _startRequestTime + _requestTimeout;
                        if (read_timeout < now)
                        {
                            string msg = string.Format("Request took too long {0:D}ms", now - _startRequestTime);
                            if (resultCallback != null)
                            {
                                await resultCallback(context, null, YAPI.TIMEOUT, msg);

                                return(null);
                            }
                            else
                            {
                                throw new YAPI_Exception(YAPI.TIMEOUT, msg);
                            }
                        }

                        read_timeout -= now;
                        if (read_timeout > YIO_IDLE_TCP_TIMEOUT)
                        {
                            read_timeout = YIO_IDLE_TCP_TIMEOUT;
                        }

                        waitms = (int)read_timeout;
                    }
                    else
                    {
                        waitms = YIO_IDLE_TCP_TIMEOUT;
                    }

                    Task task = await Task.WhenAny(readTask, Task.Delay(waitms));

                    now = YAPI.GetTickCount();
                    if (task != readTask)
                    {
                        string msg = string.Format("Hub did not send data during {0:D}ms", waitms);
                        if (resultCallback != null)
                        {
                            await resultCallback(context, null, YAPI.IO_ERROR, msg);

                            return(null);
                        }
                        else
                        {
                            throw new YAPI_Exception(YAPI.TIMEOUT, msg);
                        }
                    }

                    read = readTask.Result;
                    log(String.Format("_requestProcesss read ={0:d} after{1}", read, now - _startRequestTime));
                } catch (IOException e) {
                    closeSocket();
                    if (resultCallback != null)
                    {
                        await resultCallback(context, null, YAPI.IO_ERROR, e.Message);

                        return(null);
                    }
                    else
                    {
                        throw new YAPI_Exception(YAPI.IO_ERROR, e.Message);
                    }
                }

                if (read <= 0)
                {
                    // end of connection
                    closeSocket();
                    log("end of connection " + _dbglabel);
                    eof = true;
                }
                else if (read > 0)
                {
                    if (imm_HandleIncommingData(buffer, read))
                    {
                        closeSocket();
                        goto retry;
                    }

                    if (_reuse_socket)
                    {
                        byte[] tmp = _result.ToArray();
                        if (tmp[tmp.Length - 1] == 10 && tmp[tmp.Length - 2] == 13)
                        {
                            log("end of request " + _dbglabel + " let the socket open for later");
                            eof = true;
                        }
                    }
                }

                if (!eof)
                {
                    readTask = _in.ReadAsync(buffer, 0, buffer.Length);
                }
            } while (!eof);

            if (_header.Length == 0 && _result.Length == 0)
            {
                log("Short request detected");
                closeSocket();
                goto retry;
            }


            byte[] final_res = _result.ToArray();
            if (resultCallback != null)
            {
                await resultCallback(context, final_res, YAPI.SUCCESS, "");
            }

            return(final_res);
        }