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
            }
        }
Exemple #3
0
        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++;
        }