private void ComunicateWithTomcat() { int numOfBytesReceived = 0; byte[] receivedPacketBuffer = new byte[BonCodeAJP13Consts.MAX_BONCODEAJP13_PACKET_LENGTH]; byte[] notProcessedBytes = null; int sendPacketCount = 0; p_IsLastPacket = false; //send packages. If multiple forward requests (i.e. form data or files) there is a different behavior expected if (p_PacketsToSend.Count > 1) { foreach (Object oIterate in p_PacketsToSend) { //we will continue sending all packets in queue unless tomcat sends us End Comm package if (!p_IsLastPacket) { sendPacketCount++; BonCodeAJP13Packet sendPacket = oIterate as BonCodeAJP13Packet; //only objects derived from this class should be in the collection //send first two packets immediatly p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); //log packet if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); //after the second packet in a packet collection we have to listen and receive a TomcatGetBodyChunk if (sendPacketCount >= 2) { numOfBytesReceived = p_NetworkStream.Read(receivedPacketBuffer, 0, receivedPacketBuffer.Length); notProcessedBytes = AnalyzePackage(receivedPacketBuffer, true); //no flush processing during sending of data //we expect a 7 byte response except for the last package record, if not record a warning if (sendPacketCount != p_PacketsToSend.Count && numOfBytesReceived > 7) { if (p_Logger != null) p_Logger.LogMessageAndType("Incorrect response received from Tomcat", "warning", 1); } } } else { break; } } //if the last received message from tomcat is "GET_BODY_CHUNK" we need to send terminator package if(p_PacketsReceived[p_PacketsReceived.Count-1] is TomcatGetBodyChunk) { BonCodeAJP13Packet sendPacket = new BonCodeAJP13ForwardRequest(new byte[] { }); //create terminator (empty) package p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); //log packet as it is sent if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); } } else if (p_PacketsToSend.Count == 1) { //send package BonCodeAJP13Packet sendPacket = p_PacketsToSend[0] as BonCodeAJP13Packet; //only objects derived from this class should be in the collection p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); //log each packet as it is sent if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); } else { //nothing to do CloseConnectionNoError("Nothing to send. Closing Connection."); return; } //switch into Receiving Mode. Receive the TcpServer.response. if (!p_IsLastPacket) { p_NetworkStream.Read(receivedPacketBuffer, 0, 0); //call empty read so we block this thread until we receive a response or we time out } numOfBytesReceived = 0; try { int readCount = 0; while (p_NetworkStream.CanRead && !p_AbortConnection && !p_IsLastPacket) { //check to see whether we need to send extra termination package if (p_SendTermPacket) { p_SendTermPacket = false; BonCodeAJP13ForwardRequest terminatorFR = new BonCodeAJP13ForwardRequest(new byte[] { }); p_NetworkStream.Write(terminatorFR.GetDataBytes(), 0, terminatorFR.PacketLength); } //clear reading array Array.Clear(receivedPacketBuffer,0,receivedPacketBuffer.Length); //read incoming packets until timeout or last package has been received. readCount++; numOfBytesReceived = p_NetworkStream.Read(receivedPacketBuffer, 0, receivedPacketBuffer.Length); //analyze packet so far (adjust bytes from Receiving buffer):combine notProcessed with new Read bytes into new Received buffer if needed if (notProcessedBytes != null) { //create tempArray that contains new set of bytes to be send a combination of newly received bytes as well as bytes that we were not able to process yet byte[] tempArray = new byte[numOfBytesReceived + notProcessedBytes.Length]; Array.Copy(notProcessedBytes, 0, tempArray, 0, notProcessedBytes.Length); Array.Copy(receivedPacketBuffer, 0, tempArray, notProcessedBytes.Length, numOfBytesReceived); notProcessedBytes = AnalyzePackage(tempArray); } else { //send bytes we received for analysis byte[] tempArray = new byte[numOfBytesReceived]; Array.Copy(receivedPacketBuffer, 0, tempArray, 0, numOfBytesReceived); notProcessedBytes = AnalyzePackage(tempArray); } } } catch (System.IO.IOException ex) { ConnectionError("Server Connection is closing, Read timeout reached and no tomcat activity was detected.", "TimeOut"); if (p_Logger != null) p_Logger.LogException(ex); return; } if (p_AbortConnection) { ConnectionError("Server Connection was aborted:" , "Failed"); return; } if (numOfBytesReceived == 0) { // Nothing received from tomcat! ConnectionError("Nothing received from the tomcat. Closing the Connection.", "Failed"); return; } if (p_IsLastPacket == true) { // keep alive timer needs reset (we are maintaining connection but resetting the timer if (p_KeepAliveTimer != null) { p_KeepAliveTimer.Stop(); p_KeepAliveTimer.Start(); } //CloseConnectionNoError(); } else { //do nothing for now } }
private void ComunicateWithTomcat() { int numOfBytesReceived = 0; byte[] receivedPacketBuffer = new byte[BonCodeAJP13Settings.MAX_BONCODEAJP13_PACKET_LENGTH]; byte[] notProcessedBytes = null; int sendPacketCount = 0; p_IsLastPacket = false; int listenAfterPacket = 2; //this is standard behavior, we sent first two packets for posts then listen if (BonCodeAJP13Settings.BONCODEAJP13_ADOBE_SUPPORT || p_IsChunked) { listenAfterPacket = 1; } //send packages. If multiple forward requests (i.e. form data or files) there is a different behavior expected if (p_PacketsToSend.Count > 1) { bool delayWrite = false; //TODO: move this loop to a function by itself so we can reuse it. foreach (Object oIterate in p_PacketsToSend) { //we will continue sending all packets in queue unless tomcat sends us End Comm package if (!p_IsLastPacket) { sendPacketCount++; BonCodeAJP13Packet sendPacket = oIterate as BonCodeAJP13Packet; //only objects derived from this class should be in the collection //send first packet immediatly (most likely a post), unless there is a delay write indicator (will be set during analysis) if (!delayWrite) { p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); } else { delayWrite = false; } //log packet if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); //after the second packet (first packet for Adobe) in a packet collection we have to listen and receive a TomcatGetBodyChunk if (sendPacketCount >= listenAfterPacket) { bool subRoutineReadInProgress = true; int sanityCheck = 0; while (subRoutineReadInProgress) { sanityCheck++; try { numOfBytesReceived = p_NetworkStream.Read(receivedPacketBuffer, 0, receivedPacketBuffer.Length); notProcessedBytes = AnalyzePackage(ref delayWrite, receivedPacketBuffer, true); //no flush processing during sending of data //we expect a 7 byte response except for the last package record, if not record a warning if (sendPacketCount != p_PacketsToSend.Count && numOfBytesReceived > 7) { if (p_Logger != null) p_Logger.LogMessageAndType("Incorrect response received from Tomcat", "warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_BASIC); } //check whether we are finished with subroutine if (delayWrite) { delayWrite = false; // assume that we will exit with next loop unless Analyze package resets this to true; } else { subRoutineReadInProgress = false; } } catch (Exception e) { if (p_Logger != null) { p_Logger.LogMessageAndType("Stream reading problem (1). Null packet received in stream.", "warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_BASIC); p_Logger.LogException(e); } } //in case we go in cycle without receiving data if (sanityCheck > 500) { if (p_Logger != null) p_Logger.LogMessageAndType("SubRoutine Communication Process suspicious iterations (>500). This indicates problems with communication to tomcat", "warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_BASIC); subRoutineReadInProgress = false; } } } } else { break; } } // if the last received message from tomcat is "GET_BODY_CHUNK" we need to send terminator package // We have to do a complex type multi-comparison rather than using just one 'is' operator since c# seems to have an issue determining class type in collection if (p_PacketsReceived[p_PacketsReceived.Count - 1] is TomcatSendBodyChunk || p_PacketsReceived[p_PacketsReceived.Count - 1].GetType() == typeof(TomcatGetBodyChunk) || p_PacketsReceived[p_PacketsReceived.Count - 1] is BonCodeAJP13.TomcatPackets.TomcatSendBodyChunk) { BonCodeAJP13Packet sendPacket = new BonCodeAJP13ForwardRequest(new byte[] { }); //create terminator (empty) package p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); //log packet as it is sent if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); } } else if (p_PacketsToSend.Count == 1) { //send package BonCodeAJP13Packet sendPacket = p_PacketsToSend[0] as BonCodeAJP13Packet; //only objects derived from this class should be in the collection p_NetworkStream.Write(sendPacket.GetDataBytes(), 0, sendPacket.PacketLength); //log each packet as it is sent if (p_Logger != null) p_Logger.LogPacket(sendPacket, false, BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); } else { //nothing to do CloseConnectionNoError("Nothing to send. Closing Connection."); return; } //switch into Receiving Mode. Receive the TcpServer.response. if (!p_IsLastPacket) { try { p_NetworkStream.Read(receivedPacketBuffer, 0, 0); //call empty read so we block this thread until we receive a response or we time out } catch (Exception e) { p_Logger.LogException(e); } } numOfBytesReceived = 0; try { int readCount = 0; while (p_NetworkStream.CanRead && !p_AbortConnection && !p_IsLastPacket) { //check to see whether we need to send extra termination package if (p_SendTermPacket) { p_SendTermPacket = false; BonCodeAJP13ForwardRequest terminatorFR = new BonCodeAJP13ForwardRequest(new byte[] { }); p_NetworkStream.Write(terminatorFR.GetDataBytes(), 0, terminatorFR.PacketLength); } //clear reading array Array.Clear(receivedPacketBuffer,0,receivedPacketBuffer.Length); //flush detection by ticks check if we we have no data on channel //check whether we need monitor for tomcat flush signs if (!p_NetworkStream.DataAvailable && BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_TICKS > 0) { long elapsedTicks = p_StopWatch.ElapsedTicks; p_TickDelta = elapsedTicks - p_LastTick; p_LastTick = elapsedTicks; if (p_TickDelta > BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_TICKS) { //flush has been detected set the flag. We should flush after this receiveBuffer has been processed. //no flush is needed if we see end marker during receiveBuffer processing since all data would have been transferred p_IsFlush = true; p_TimeFlushOccurred = true; } } //read incoming packets until timeout or last package has been received. readCount++; try { //read or wait on next package numOfBytesReceived = p_NetworkStream.Read(receivedPacketBuffer, 0, receivedPacketBuffer.Length); //flush detection by bytes -- in case where time flush is also defined (ticks>0) we will wait until a time flush occurs (p_TimeFlushOccurred) //before we trigger a byte flushes if (BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_BYTES > 0 && (BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_TICKS == 0 || (BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_TICKS > 0 && p_TimeFlushOccurred)) ) { p_BytesInBuffer = p_BytesInBuffer + numOfBytesReceived; if (p_BytesInBuffer > BonCodeAJP13Settings.BONCODEAJP13_AUTOFLUSHDETECTION_BYTES) { p_IsFlush = true; p_BytesInBuffer = 0; } } //analyze packet so far (adjust bytes from Receiving buffer):combine notProcessed with new Read bytes into new Received buffer if needed if (notProcessedBytes != null) { //create tempArray that contains new set of bytes to be send a combination of newly received bytes as well as bytes that we were not able to process yet byte[] tempArray = new byte[numOfBytesReceived + notProcessedBytes.Length]; Array.Copy(notProcessedBytes, 0, tempArray, 0, notProcessedBytes.Length); Array.Copy(receivedPacketBuffer, 0, tempArray, notProcessedBytes.Length, numOfBytesReceived); notProcessedBytes = AnalyzePackage(tempArray); } else { //send bytes we received for analysis byte[] tempArray = new byte[numOfBytesReceived]; Array.Copy(receivedPacketBuffer, 0, tempArray, 0, numOfBytesReceived); notProcessedBytes = AnalyzePackage(tempArray); } } catch (Exception e) { p_AbortConnection = true; p_Logger.LogMessageAndType("Stream reading problem (2)(" + readCount.ToString() + "), you may have shutdown Tomcat unexpectedly", "warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_BASIC); //p_Logger.LogException(e); } } //check error condition that tomcat produces sometimes where additional data is sent after end_transmission has been indicated int sanityCheck = 0; while (p_NetworkStream.DataAvailable && sanityCheck < 100) { //we need to clear the tcp pipe so the next request does not pick up data we will do this up to 100 times and write warning try { numOfBytesReceived = p_NetworkStream.Read(receivedPacketBuffer, 0, receivedPacketBuffer.Length); } catch { //do nothing here } if (sanityCheck == 0) { if (p_Logger != null) p_Logger.LogMessageAndType("extra data after transmission-end from tomcat" ,"warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_HEADERS); } sanityCheck++; } } catch (System.IO.IOException ex) { ConnectionError("Server Connection is closing, Read timeout reached and no tomcat activity was detected.", "TimeOut"); if (p_Logger != null) p_Logger.LogException(ex); return; } if (p_AbortConnection) { ConnectionError("Server Connection was aborted" , "failed"); return; } if (numOfBytesReceived == 0) { // Nothing received from tomcat, log warning p_Logger.LogMessageAndType("Empty packet received from tomcat", "warning", BonCodeAJP13LogLevels.BONCODEAJP13_LOG_BASIC); //return; } if (p_IsLastPacket == true) { // keep alive timer needs reset (we are maintaining connection but resetting the timer if (p_KeepAliveTimer != null) { p_KeepAliveTimer.Stop(); p_KeepAliveTimer.Start(); } CloseConnectionNoError(); } else { //do nothing for now } }
static void Main(string[] args) { //KeyTest(); //sample setting //Console.WriteLine("Sample Setting " + Properties.Settings.Default.SampleSetting); //read parameters from console first parameter is server second port if (args.Length >= 1) { myURL = (string)args[0]; } if (args.Length >= 2) { myServer = (string)args[1]; } if (args.Length >= 3) { myPort = (string)args[2]; } string myDNS = myServer; // +":" + myPort; ushort iPort = Convert.ToUInt16(myPort); //test search byte[] sourceBytes = new byte[20] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A }; byte[] searchBytes = new byte[2] { 0x02, 0x04 }; int foundPos = ByteSearch(sourceBytes, searchBytes, 0); Console.WriteLine(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache)); Console.WriteLine(BonCodeAJP13Settings.BONCODEAJP13_LOG_DIR); ConnectViaString(myDNS, myData); //test config //Test myTest = new Test(); //myTest.fHeaderTest(); //log level //Console.WriteLine("Log Level " + BonCodeAJP13Settings.BONCODEAJP13_LOG_LEVEL); //create intance of forward request BonCodeAJP13ForwardRequest FR = new BonCodeAJP13ForwardRequest(BonCodeAJP13HTTPMethods.BONCODEAJP13_GET, "HTTP/1.1", myURL, "::1", "::1", myServer,iPort ,false,1); //create cping request BonCodeAJP13ForwardRequest FR2 = new BonCodeAJP13ForwardRequest(BonCodeAJP13HTTPMethods.BONCODEAJP13_GET, "HTTP/1.1", myURL, "::1", "::1", myServer, iPort, false, 1); byte[] testBytes = FR.GetDataBytes(); //this returns the contructed databytes //byte[] testBytes = FR.WriteServerTestPacket(); Console.WriteLine("Server: {0} , Port: {1}, URL: {2}", myServer, myPort, myURL); //call server request BonCodeAJP13ServerConnection sconn = new BonCodeAJP13ServerConnection(FR,true); sconn.Server = myServer; sconn.Port = System.Convert.ToInt32(myPort); sconn.FlushDelegateFunction = PrintFlush; //this function will do the printing to console //run connection sconn.BeginConnection(); //write the response to screen that has not been flushed yet foreach (Object oIterate in sconn.ReceivedDataCollection) { BonCodeAJP13Packet Packet = oIterate as BonCodeAJP13Packet; //only objects derived from this class should be in the collection Console.WriteLine(Packet.GetDataString()); } Console.WriteLine("Last Size:" + sconn.ReceivedDataCollection.Count); //call connect function //ConnectViaString(myDNS, myData); //Connect(myDNS, testBytes); int a = 2; a++; }