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); }