private void DoHmux(HttpContext context) { HttpRequest request = context.Request; HttpResponse response = context.Response; String sessionId; if (!_isStickySessions) { sessionId = null; } else { sessionId = GetRequestedSessionId(request); } TempBuffer tempBuf = TempBuffer.Allocate(); byte[] buf = tempBuf.GetBuffer(); try { Stream is_ = request.InputStream; int len = is_.Read(buf, 0, buf.Length); bool isComplete; if (len < 0) { isComplete = true; } else if (len < buf.Length) { int sublen = is_.Read(buf, len, 1); if (sublen == 0) //.NET return 0 for Stream.EOF { isComplete = true; } else { len += sublen; isComplete = false; } } else { isComplete = false; } Server client = null; int result = OK | EXIT; HmuxConnection channel = _loadBalancer.OpenServer(sessionId, null); // If everything fails, return an error if (channel == null) { SendNotAvailable(response); return; } client = channel.GetPool(); BufferedStream rs = channel.GetSocketStream(); BufferedStream ws = channel.GetSocketStream(); result = FAIL | EXIT; long requestStartTime = Utils.CurrentTimeMillis(); try { result = HandleRequest(context, request, response, channel, rs, ws, buf, len, isComplete, isComplete); if ((result & STATUS_MASK) == OK) { client.ClearBusy(); return; } else if ((result & STATUS_MASK) == BUSY) { client.Busy(); } else { client.FailSocket(); } } catch (ClientDisconnectException) { _log.Info("Client disconnect detected for '{0}'", channel.GetTraceId()); return; } catch (IOException e) { client.FailSocket(); _log.Error("IOException '{0}': '{1}' {2}", channel.GetTraceId(), e.Message, e.StackTrace); } finally { if ((result & EXIT_MASK) == QUIT) { channel.Free(requestStartTime); } else { channel.Close(); } } // server/2675 if (isComplete && (result & STATUS_MASK) == BUSY || "GET".Equals(request.HttpMethod)) { channel = _loadBalancer.OpenServer(sessionId, client); // If everything fails, return an error if (channel == null) { _log.Info("load-balance failed" + (client != null ? (" for " + client.GetDebugId()) : "")); SendNotAvailable(response); return; } Server client2 = channel.GetPool(); if (_log.IsLoggable(EventLogEntryType.Information)) { _log.Info("load-balance failing over" + (client != null ? (" from " + client.GetDebugId()) : "") + " to " + client2.GetDebugId()); } rs = channel.GetSocketStream(); ws = channel.GetSocketStream(); result = FAIL | EXIT; requestStartTime = Utils.CurrentTimeMillis(); try { result = HandleRequest(context, request, response, channel, rs, ws, buf, len, isComplete, false); if ((result & STATUS_MASK) == OK) { client2.ClearBusy(); return; } else if ((result & STATUS_MASK) == BUSY) { client2.Busy(); } else { client2.FailSocket(); } } catch (IOException e) { client2.FailSocket(); _log.Info("Failover to '{0}' did not succeed '{1}', {2} ", client2.GetDebugId(), e.Message, e.StackTrace); } finally { if ((result & EXIT_MASK) == QUIT) { channel.Free(requestStartTime); } else { channel.Close(); } } } SendNotAvailable(response); } finally { TempBuffer.Free(tempBuf); tempBuf = null; } }
private int HandleRequest(HttpContext context, HttpRequest request, HttpResponse response, HmuxConnection hmuxChannel, BufferedStream rs, BufferedStream ws, byte[] buf, int length, bool isComplete, bool allowBusy) { Trace.TraceInformation("Handle request: length: {0}, complete: {1}, allowBusy {2}", length, isComplete, allowBusy); String traceId = hmuxChannel.GetTraceId(); StringBuilder cb = new StringBuilder(); bool isDebugFiner = true; String uri = request.Path; uri = Uri.EscapeUriString(uri); Trace.TraceInformation("Hmux[{0}] >>U:uri {1}->{2}", traceId, request.RawUrl, uri); WriteRequestString(ws, HmuxConnection.HMUX_URI, uri, traceId); String rawUri = request.RawUrl; int queryIdx = rawUri.IndexOf('?'); if (queryIdx > -1 && queryIdx + 1 < rawUri.Length) { String query = rawUri.Substring(queryIdx + 1); Trace.TraceInformation("Hmux[{0}] >>U:query {1}", traceId, query); WriteRequestString(ws, HmuxConnection.CSE_QUERY_STRING, query, traceId); } Trace.TraceInformation("Hmux[{0}] >>m:method {1}", traceId, request.HttpMethod); WriteRequestString(ws, HmuxConnection.HMUX_METHOD, request.HttpMethod, traceId); Trace.TraceInformation("Hmux[{0}] >>u:server type {1}", traceId, "IIS"); WriteRequestString(ws, HmuxConnection.CSE_SERVER_TYPE, "IIS", traceId); NameValueCollection serverVariables = request.ServerVariables; String serverPort = serverVariables.Get("SERVER_PORT"); String serverName = serverVariables.Get("SERVER_NAME") + ':' + serverPort; Trace.TraceInformation("Hmux[{0}] >>v:server name {1}", traceId, serverName); WriteRequestString(ws, HmuxConnection.HMUX_SERVER_NAME, serverName, traceId); Trace.TraceInformation("Hmux[{0}] >>g:server port {1}", traceId, serverPort); WriteRequestString(ws, HmuxConnection.CSE_SERVER_PORT, serverPort, traceId); String remoteAddr = serverVariables.Get("REMOTE_ADDR"); Trace.TraceInformation("Hmux[{0}] >>i:remote address {1}", traceId, remoteAddr); WriteRequestString(ws, HmuxConnection.CSE_REMOTE_ADDR, remoteAddr, traceId); String remoteHost = serverVariables.Get("REMOTE_HOST"); if (remoteHost == null) { remoteHost = remoteAddr; } Trace.TraceInformation("Hmux[{0}] >>h:remote host {1}", traceId, remoteHost); WriteRequestString(ws, HmuxConnection.CSE_REMOTE_HOST, remoteHost, traceId); String protocol = serverVariables.Get("HTTP_VERSION"); Trace.TraceInformation("Hmux[{0}] >>c:protocol {1}", traceId, protocol); WriteRequestString(ws, HmuxConnection.CSE_PROTOCOL, protocol, traceId); HttpClientCertificate clientCertificate = request.ClientCertificate; if (request.IsSecureConnection) { Trace.TraceInformation("Hmux[{0}] >>r:secure", traceId); WriteRequestString(ws, HmuxConnection.CSE_IS_SECURE, "", traceId); WriteRequestHeader(ws, "HTTPS", "on", traceId); WriteRequestHeader(ws, "SSL_SECRETKEYSIZE", clientCertificate.KeySize.ToString(), traceId); } if (clientCertificate.IsPresent) { Trace.TraceInformation("Hmux[{0}] >>r:certificate ({1})", traceId, clientCertificate.Certificate.Length); ws.WriteByte(HmuxConnection.CSE_CLIENT_CERT); WriteHmuxLength(ws, clientCertificate.Certificate.Length); ws.Write(clientCertificate.Certificate, 0, clientCertificate.Certificate.Length); } if (request.IsAuthenticated) { /* * String remoteUser = request.LogonUserIdentity.Name; */ String remoteUser = context.Current.User.Identity.Name; WriteRequestString(ws, HmuxConnection.CSE_REMOTE_USER, remoteUser, traceId); } NameValueCollection headers = request.Headers; foreach (String key in headers.AllKeys) { if ("Connection".Equals(key, StringComparison.OrdinalIgnoreCase)) { continue; } String[] values = headers.GetValues(key); foreach (String value in values) { WriteRequestHeader(ws, key, value, traceId); } } if (_isDebug) { WriteRequestHeader(ws, "X-Resin-Debug", traceId, traceId); } Stream requestStream = request.InputStream; Stream responseStream = null; bool hasHeader = true; bool hasStatus = false; if (length > 0) { Trace.TraceInformation("Hmux[{0}] >>D: data ({1})", traceId, length); WriteRequestData(ws, HmuxConnection.HMUX_DATA, buf, length, traceId); } int len; int code; while (!isComplete && (len = requestStream.Read(buf, 0, buf.Length)) > 0) { Trace.TraceInformation("Hmux[{0}] >>D: data ({1})", traceId, length); WriteRequestData(ws, HmuxConnection.HMUX_DATA, buf, len, traceId); Trace.TraceInformation("Hmux[{0}] >>Y: (yield)", traceId); ws.WriteByte(HmuxConnection.HMUX_YIELD); ws.Flush(); while (true) { code = rs.ReadByte(); if (code < 0) { Trace.TraceInformation("Hmux[{0}] <<w: end of file", traceId); if (hasStatus) { return(OK | EXIT); } else { // Trace.TraceInformation("Hmux[{0}] <<w: unexpected end of file", traceId); return(FAIL | EXIT); } } else if (code == HmuxConnection.HMUX_QUIT) { Trace.TraceInformation("Hmux[{0}] <<Q: (keepalive)", traceId); if (hasStatus) { return(OK | QUIT); } else { Trace.TraceInformation("Hmux[{0}] <<Q: unexpected quit file", traceId); return(FAIL | QUIT); } } else if (code == HmuxConnection.HMUX_EXIT) { Trace.TraceInformation("Hmux[{0}] <<X: (exit)", traceId); if (hasStatus) { return(OK | EXIT); } else { Trace.TraceInformation("Hmux[{0}] <<X: unexpected exit", traceId); return(FAIL | EXIT); } } else if (code == HmuxConnection.HMUX_YIELD) { Trace.TraceInformation("Hmux[{0}] <<Y: (yield)", traceId); continue; } int sublen = ReadHmuxLength(rs); if (code == HmuxConnection.HMUX_ACK) { if (isDebugFiner) { Trace.TraceInformation("Hmux[{0}] <<A: (ack) ({1})", traceId, sublen); } break; } else if (code == HmuxConnection.HMUX_CHANNEL) { int channel = sublen; Trace.TraceInformation("Hmux[{0}] <<C: (channel) ({1})", traceId, channel); } else if (code == HmuxConnection.HMUX_STATUS && hasHeader) { String status = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<s: (status) ({1})", traceId, status); int statusCode = 0; for (int i = 0; i < 3; i++) { statusCode = 10 * statusCode + status[i] - '0'; } if (statusCode != 200) { response.StatusCode = statusCode; } hasStatus = true; } else if (code == HmuxConnection.HMUX_HEADER && hasHeader) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<H,S: (header) ({1}={2})", traceId, name, value); RelayResponseHeader(response, name, value); } else if (code == HmuxConnection.HMUX_DATA) { Trace.TraceInformation("Hmux[{0}] <<D: (data)({1})", traceId, sublen); if (responseStream == null) { responseStream = response.OutputStream; } RelayResponseData(rs, responseStream, sublen); } else if (code == HmuxConnection.HMUX_META_HEADER) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<M,S: header ({1}={2})", traceId, name, value); if ("cpu-load".Equals(name)) { double loadAvg = 0.001 * long.Parse(value); hmuxChannel.GetPool().SetCpuLoadAvg(loadAvg); } } else { Skip(rs, sublen); } } } ws.WriteByte(HmuxConnection.HMUX_QUIT); ws.Flush(); code = rs.ReadByte(); // #2369 - A slow modem can cause the app-tier and web-tier times // to get out of sync, with the app-tier thinking it's completed // (and starts the keepalive timeout) 30s before the web-tier reads // its data. // As a temporary measure, we start the idle time at the first data // read (later we might mark the time it takes to read an app-tier // packet. If it's short, e.g. 250ms, don't update the time.) hmuxChannel.SetIdleStartTime(Utils.CurrentTimeMillis()); bool isBusy = false; for (; code >= 0; code = rs.ReadByte()) { if (code == HmuxConnection.HMUX_QUIT) { if (isDebugFiner) { Trace.TraceInformation("Hmux[{0}] <<Q: (keepalive)", traceId); } return(isBusy ? BUSY | QUIT : OK | QUIT); } else if (code == HmuxConnection.HMUX_EXIT) { Trace.TraceInformation("Hmux[{0}] <<X: (exit)", traceId); return((isBusy || !hasStatus) ? BUSY | EXIT : OK | EXIT); } else if (code == HmuxConnection.HMUX_YIELD) { Trace.TraceInformation("Hmux[{0}] <<Y: (yield)", traceId); continue; } int sublen = (rs.ReadByte() << 8) + rs.ReadByte(); if (code == HmuxConnection.HMUX_DATA) { if (responseStream == null) { responseStream = response.OutputStream; } Trace.TraceInformation("Hmux[{0}] <<D: (data)({1})", traceId, sublen); if (!isBusy) { RelayResponseData(rs, responseStream, sublen); } else { Skip(rs, sublen); } } else if (code == HmuxConnection.HMUX_STATUS && hasHeader) { hasStatus = true; String status = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<s: (status) ({1})", traceId, status); int statusCode = 0; for (int i = 0; i < 3; i++) { statusCode = 10 * statusCode + status[i] - '0'; } if (statusCode == 503 && allowBusy) { isBusy = true; } else if (statusCode != 200) { response.StatusCode = statusCode; } } else if (code == HmuxConnection.HMUX_HEADER && hasHeader) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<H,S: (header) ({1}={2})", traceId, name, value); if (!isBusy) { RelayResponseHeader(response, name, value); } } else if (code == HmuxConnection.HMUX_META_HEADER) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<M,S: header ({1}={2})", traceId, name, value); if ("cpu-load".Equals(name)) { double loadAvg = 0.001 * long.Parse(value); hmuxChannel.GetPool().SetCpuLoadAvg(loadAvg); } } else if (code == HmuxConnection.HMUX_CHANNEL) { int channel = sublen; Trace.TraceInformation("Hmux[{0}] <<C: (channel) ({1})", traceId, channel); } else if (code == HmuxConnection.CSE_SEND_HEADER) { Trace.TraceInformation("Hmux[{0}] <<G: send headers", traceId); Skip(rs, sublen); } else if (code == 0) { Trace.TraceInformation("Hmux[{0}] <<0: unknown code (0)", traceId); return(FAIL | EXIT); } else { Trace.TraceInformation("Hmux[{0}] <<?: unknown code ({1})", traceId, code); Skip(rs, sublen); } } Trace.TraceInformation("Hmux[{0}] end of file", traceId); // server/269q if (hasStatus) { return(isBusy ? BUSY | EXIT : OK | EXIT); } else { // Trace.TraceInformation("Hmux[{0}] unexpected end of file", traceId, code); return(FAIL | EXIT); } }
private int HandleRequest(HttpRequest request, HttpResponse response, HmuxConnection hmuxChannel, BufferedStream rs, BufferedStream ws, byte[] buf, int length, bool isComplete, bool allowBusy) { Trace.TraceInformation("Handle request: length: {0}, complete: {1}, allowBusy {2}", length, isComplete, allowBusy); String traceId = hmuxChannel.GetTraceId(); StringBuilder cb = new StringBuilder(); bool isDebugFiner = true; String uri = request.Path; uri = Uri.EscapeUriString(uri); Trace.TraceInformation("Hmux[{0}] >>U:uri {1}->{2}", traceId, request.RawUrl, uri); WriteRequestString(ws, HmuxConnection.HMUX_URI, uri, traceId); String rawUri = request.RawUrl; int queryIdx = rawUri.IndexOf('?'); if (queryIdx > -1 && queryIdx + 1 < rawUri.Length) { String query = rawUri.Substring(queryIdx + 1); Trace.TraceInformation("Hmux[{0}] >>U:query {1}", traceId, query); WriteRequestString(ws, HmuxConnection.CSE_QUERY_STRING, query, traceId); } Trace.TraceInformation("Hmux[{0}] >>m:method {1}", traceId, request.HttpMethod); WriteRequestString(ws, HmuxConnection.HMUX_METHOD, request.HttpMethod, traceId); Trace.TraceInformation("Hmux[{0}] >>u:server type {1}", traceId, "IIS"); WriteRequestString(ws, HmuxConnection.CSE_SERVER_TYPE, "IIS", traceId); NameValueCollection serverVariables = request.ServerVariables; String serverPort = serverVariables.Get("SERVER_PORT"); String serverName = serverVariables.Get("SERVER_NAME") + ':' + serverPort; Trace.TraceInformation("Hmux[{0}] >>v:server name {1}", traceId, serverName); WriteRequestString(ws, HmuxConnection.HMUX_SERVER_NAME, serverName, traceId); Trace.TraceInformation("Hmux[{0}] >>g:server port {1}", traceId, serverPort); WriteRequestString(ws, HmuxConnection.CSE_SERVER_PORT, serverPort, traceId); String remoteAddr = serverVariables.Get("REMOTE_ADDR"); Trace.TraceInformation("Hmux[{0}] >>i:remote address {1}", traceId, remoteAddr); WriteRequestString(ws, HmuxConnection.CSE_REMOTE_ADDR, remoteAddr, traceId); String remoteHost = serverVariables.Get("REMOTE_HOST"); if (remoteHost == null) remoteHost = remoteAddr; Trace.TraceInformation("Hmux[{0}] >>h:remote host {1}", traceId, remoteHost); WriteRequestString(ws, HmuxConnection.CSE_REMOTE_HOST, remoteHost, traceId); String protocol = serverVariables.Get("HTTP_VERSION"); Trace.TraceInformation("Hmux[{0}] >>c:protocol {1}", traceId, protocol); WriteRequestString(ws, HmuxConnection.CSE_PROTOCOL, protocol, traceId); HttpClientCertificate clientCertificate = request.ClientCertificate; if (request.IsSecureConnection) { Trace.TraceInformation("Hmux[{0}] >>r:secure", traceId); WriteRequestString(ws, HmuxConnection.CSE_IS_SECURE, "", traceId); WriteRequestHeader(ws, "HTTPS", "on", traceId); WriteRequestHeader(ws, "SSL_SECRETKEYSIZE", clientCertificate.KeySize.ToString(), traceId); } if (clientCertificate.IsPresent) { Trace.TraceInformation("Hmux[{0}] >>r:certificate ({1})", traceId, clientCertificate.Certificate.Length); ws.WriteByte(HmuxConnection.CSE_CLIENT_CERT); WriteHmuxLength(ws, clientCertificate.Certificate.Length); ws.Write(clientCertificate.Certificate, 0, clientCertificate.Certificate.Length); } NameValueCollection headers = request.Headers; foreach (String key in headers.AllKeys) { if ("Connection".Equals(key, StringComparison.OrdinalIgnoreCase)) continue; String[] values = headers.GetValues(key); foreach (String value in values) { WriteRequestHeader(ws, key, value, traceId); } } if (_isDebug) { WriteRequestHeader(ws, "X-Resin-Debug", traceId, traceId); } Stream requestStream = request.InputStream; Stream responseStream = null; bool hasHeader = true; bool hasStatus = false; if (length > 0) { Trace.TraceInformation("Hmux[{0}] >>D: data ({1})", traceId, length); WriteRequestData(ws, HmuxConnection.HMUX_DATA, buf, length, traceId); } int len; int code; while (!isComplete && (len = requestStream.Read(buf, 0, buf.Length)) > 0) { Trace.TraceInformation("Hmux[{0}] >>D: data ({1})", traceId, length); WriteRequestData(ws, HmuxConnection.HMUX_DATA, buf, len, traceId); Trace.TraceInformation("Hmux[{0}] >>Y: (yield)", traceId); ws.WriteByte(HmuxConnection.HMUX_YIELD); ws.Flush(); while (true) { code = rs.ReadByte(); if (code < 0) { Trace.TraceInformation("Hmux[{0}] <<w: end of file", traceId); if (hasStatus) return OK | EXIT; else { Trace.TraceInformation("Hmux[{0}] <<w: unexpected end of file", traceId); return FAIL | EXIT; } } else if (code == HmuxConnection.HMUX_QUIT) { Trace.TraceInformation("Hmux[{0}] <<Q: (keepalive)", traceId); if (hasStatus) return OK | QUIT; else { Trace.TraceInformation("Hmux[{0}] <<Q: unexpected quit file", traceId); return FAIL | QUIT; } } else if (code == HmuxConnection.HMUX_EXIT) { Trace.TraceInformation("Hmux[{0}] <<X: (exit)", traceId); if (hasStatus) { return OK | EXIT; } else { Trace.TraceInformation("Hmux[{0}] <<X: unexpected exit", traceId); return FAIL | EXIT; } } else if (code == HmuxConnection.HMUX_YIELD) { Trace.TraceInformation("Hmux[{0}] <<Y: (yield)", traceId); continue; } int sublen = ReadHmuxLength(rs); if (code == HmuxConnection.HMUX_ACK) { if (isDebugFiner) Trace.TraceInformation("Hmux[{0}] <<A: (ack) ({1})", traceId, sublen); break; } else if (code == HmuxConnection.HMUX_CHANNEL) { int channel = sublen; Trace.TraceInformation("Hmux[{0}] <<C: (channel) ({1})", traceId, channel); } else if (code == HmuxConnection.HMUX_STATUS && hasHeader) { String status = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<s: (status) ({1})", traceId, status); int statusCode = 0; for (int i = 0; i < 3; i++) statusCode = 10 * statusCode + status[i] - '0'; if (statusCode != 200) response.StatusCode = statusCode; hasStatus = true; } else if (code == HmuxConnection.HMUX_HEADER && hasHeader) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<H,S: (header) ({1}={2})", traceId, name, value); RelayResponseHeader(response, name, value); } else if (code == HmuxConnection.HMUX_DATA) { Trace.TraceInformation("Hmux[{0}] <<D: (data)({1})", traceId, sublen); if (responseStream == null) responseStream = response.OutputStream; RelayResponseData(rs, responseStream, sublen); } else if (code == HmuxConnection.HMUX_META_HEADER) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<M,S: header ({1}={2})", traceId, name, value); if ("cpu-load".Equals(name)) { double loadAvg = 0.001 * long.Parse(value); hmuxChannel.GetPool().SetCpuLoadAvg(loadAvg); } } else { Skip(rs, sublen); } } } ws.WriteByte(HmuxConnection.HMUX_QUIT); ws.Flush(); code = rs.ReadByte(); // #2369 - A slow modem can cause the app-tier and web-tier times // to get out of sync, with the app-tier thinking it's completed // (and starts the keepalive timeout) 30s before the web-tier reads // its data. // As a temporary measure, we start the idle time at the first data // read (later we might mark the time it takes to read an app-tier // packet. If it's short, e.g. 250ms, don't update the time.) hmuxChannel.SetIdleStartTime(Utils.CurrentTimeMillis()); bool isBusy = false; for (; code >= 0; code = rs.ReadByte()) { if (code == HmuxConnection.HMUX_QUIT) { if (isDebugFiner) Trace.TraceInformation("Hmux[{0}] <<Q: (keepalive)", traceId); return isBusy ? BUSY | QUIT : OK | QUIT; } else if (code == HmuxConnection.HMUX_EXIT) { Trace.TraceInformation("Hmux[{0}] <<X: (exit)", traceId); return (isBusy || !hasStatus) ? BUSY | EXIT : OK | EXIT; } else if (code == HmuxConnection.HMUX_YIELD) { Trace.TraceInformation("Hmux[{0}] <<Y: (yield)", traceId); continue; } int sublen = (rs.ReadByte() << 8) + rs.ReadByte(); if (code == HmuxConnection.HMUX_DATA) { if (responseStream == null) responseStream = response.OutputStream; Trace.TraceInformation("Hmux[{0}] <<D: (data)({1})", traceId, sublen); if (!isBusy) RelayResponseData(rs, responseStream, sublen); else Skip(rs, sublen); } else if (code == HmuxConnection.HMUX_STATUS && hasHeader) { hasStatus = true; String status = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<s: (status) ({1})", traceId, status); int statusCode = 0; for (int i = 0; i < 3; i++) statusCode = 10 * statusCode + status[i] - '0'; if (statusCode == 503 && allowBusy) { isBusy = true; } else if (statusCode != 200) { response.StatusCode = statusCode; } } else if (code == HmuxConnection.HMUX_HEADER && hasHeader) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<H,S: (header) ({1}={2})", traceId, name, value); if (!isBusy) RelayResponseHeader(response, name, value); } else if (code == HmuxConnection.HMUX_META_HEADER) { String name = ReadHmuxString(rs, sublen); rs.ReadByte(); sublen = ReadHmuxLength(rs); String value = ReadHmuxString(rs, sublen); Trace.TraceInformation("Hmux[{0}] <<M,S: header ({1}={2})", traceId, name, value); if ("cpu-load".Equals(name)) { double loadAvg = 0.001 * long.Parse(value); hmuxChannel.GetPool().SetCpuLoadAvg(loadAvg); } } else if (code == HmuxConnection.HMUX_CHANNEL) { int channel = sublen; Trace.TraceInformation("Hmux[{0}] <<C: (channel) ({1})", traceId, channel); } else if (code == 0) { Trace.TraceInformation("Hmux[{0}] <<0: unknown code (0)", traceId); return FAIL | EXIT; } else { Trace.TraceInformation("Hmux[{0}] <<?: unknown code ({1})", traceId, code); Skip(rs, sublen); } } Trace.TraceInformation("Hmux[{0}] end of file", traceId); // server/269q if (hasStatus) return isBusy ? BUSY | EXIT : OK | EXIT; else { Trace.TraceInformation("Hmux[{0}] unexpected end of file", traceId, code); return FAIL | EXIT; } }