Massoud Mazar

Sharing The Knowledge

C# code to play PCAP capture of HTTP request

If you have been involved in troubleshooting web applications providing APIs to clients, you know how easier it is to have the actual request sent from client and be able to replay that against your server code to find the problem. Tools we use in my team is WireShark and NCAT. When QA team finds a problem, we always ask for the WireShark capture of the communication.

After finding the request in question in WireShark, you can right click on the packet and select "Follow TCP Stream" so it isolates all packets related only to this request. In the "Follow TCP Stream" you can change the drop down to only show request (and not the response) and use "Dave As" button to save this request to a file. This file can then be played back to destination of your choice to allow you to reproduce the issue easily. NCAT command line looks like this:

NCAT localhost 80 < PCAPfile

Where localhost can e changed to any destination you want, 80 is the port number and PCAPfile is the file you saved as explained in above section.

It is also possible to save same type of file from your ASP.net application. For example, you want to capture sample requests causing exceptions in your server code. You can use the HTTPRequest.SaveAs() method.

Request.SaveAs("c:\\temp\\HttpRequest.txt", true);

Such captured requests can then be played back using NCAT, as demonstrated above.

Here is a sample code I put together to read the PCAP file and play it back, similar to how NCAT does it, but it only works with HTTP requests.

public class PcapPlayer
    {

        public string Destination { get; set; }
        public string FileName { get; set; }

        public PcapPlayer(string destination, string filename)
        {
            Destination = destination;
            FileName = filename;
        }

        /// <summary>
        /// Reads the PCAP file and creates HTTPWebRequest and gets the response from server
        /// </summary>
        /// <returns>a string representing the results coming back from server</returns>
        public string Play()
        {
            string result = string.Empty;

            try
            {
                string url = Destination;

                if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
                    url = "http://" + url;

                HttpWebRequest request;

                using (FileStream reader = new FileStream(FileName, FileMode.Open))
                {
                    string line = ReadLine(reader);
                    string[] components = line.Split(' ');

                    url += components[1];

                    request = (HttpWebRequest)HttpWebRequest.Create(url);
                    request.Method = components[0];

                    if (components.Length > 2)
                    {
                        switch (components[2].ToLower())
                        {
                            case "http/1.0":
                                request.ProtocolVersion = HttpVersion.Version10;
                                break;
                            case "http/1.1":
                                request.ProtocolVersion = HttpVersion.Version11;
                                break;
                        }
                    }

                    while (reader.Position < reader.Length)
                    {
                        line = ReadLine(reader);

                        if (string.IsNullOrEmpty(line))
                            break;
                        else
                            SetHeader(line, request);
                    }

                    byte[] buffer = new byte[4096];
                    int bytesread = 0;
                    Stream Body = request.GetRequestStream();

                    while (reader.Position < reader.Length)
                    {
                        bytesread = reader.Read(buffer, 0, buffer.Length);
                        if (bytesread > 0)
                            Body.Write(buffer, 0, bytesread);
                    }

                    Body.Close();
                    reader.Close();
                }

                if (request != null)
                {
                    // Get the response
                    using (HttpWebResponse wRes = (HttpWebResponse)request.GetResponse())
                    {
                        result = GetResponse(wRes);
                        wRes.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                result = GetExceptionMessage(ex);
            }

            return result;
        }

        /// <summary>
        /// Read from file until reaching a line break
        /// </summary>
        /// <param name="fstream">FileStream to read from</param>
        /// <returns>the line of text that was just read</returns>
        private string ReadLine(FileStream fstream)
        {
            long pos1 = fstream.Position;

            byte[] newline = Encoding.ASCII.GetBytes(Environment.NewLine);

            while (fstream.Position < fstream.Length)
            {
                if (fstream.ReadByte() == newline[0] && fstream.ReadByte() == newline[1])
                    break;
            }

            long pos2 = fstream.Position;
            fstream.Position = pos1;

            byte[] buffer = new byte[pos2 - pos1 - 2];
            fstream.Read(buffer, 0, buffer.Length);

            fstream.Position = pos2;

            return Encoding.ASCII.GetString(buffer, 0, buffer.Length);
        }

        /// <summary>
        /// Some known headers need to be parsed and assigned to Request properties
        /// </summary>
        /// <param name="line">Header Line to be processed</param>
        /// <param name="request">HttpWebRequest object which is being configured</param>
        private void SetHeader(string line, HttpWebRequest request)
        {
            string[] header = line.Split(':');
            string value = header[1].Trim();
            switch (header[0].ToLower())
            {
                case "content-type":
                    request.ContentType = value;
                    break;
                case "accept":
                    request.Accept = value;
                    break;
                case "expect":
                    if (value.Equals("100-continue", StringComparison.OrdinalIgnoreCase))
                        request.ServicePoint.Expect100Continue = true;
                    break;
                case "host":
                    request.Host = value;
                    break;
                case "user-agent":
                    request.UserAgent = value;
                    break;
                case "connection":
                    switch (value.ToLower())
                    {
                        case "keep-alive":
                            request.KeepAlive = true;
                            break;
                        case "close":
                            request.KeepAlive = false;
                            break;
                        default:
                            request.Connection = value;
                            break;
                    }
                    break;
                case "content-length":
                    request.ContentLength = long.Parse(value);
                    break;
                default:
                    request.Headers.Add(line);
                    break;
            }
        }

        /// <summary>
        /// Try to present most complete error message
        /// </summary>
        /// <param name="ex">Exception which was captured</param>
        /// <returns>string containing the error message</returns>
        private string GetExceptionMessage(Exception ex)
        {
            string result = string.Empty;
            if (ex is WebException)
            {
                WebResponse errResp = ((WebException)ex).Response;
                result = GetResponse((HttpWebResponse)errResp);
            }
            if (string.IsNullOrEmpty(result))
            {
                result = GetErrorStackTrace(ex);
            }
            return result;
        }

        /// <summary>
        /// Builds output based on the response and includes headers
        /// </summary>
        /// <param name="wRes">HttpWebResponse</param>
        /// <returns>string representing server response</returns>
        protected string GetResponse(HttpWebResponse wRes)
        {
            StringBuilder result = new StringBuilder();

            if (wRes != null)
            {
                result.Append("HTTP/").Append(wRes.ProtocolVersion).Append(" ").Append((int)wRes.StatusCode).Append(" ").Append(wRes.StatusDescription).AppendLine();

                foreach (string h in wRes.Headers.AllKeys)
                {
                    result.Append(h).Append(": ").Append(wRes.Headers[h]).AppendLine();
                }
                result.AppendLine();

                Stream ResponseStream = wRes.GetResponseStream();
                using (StreamReader stReader = new StreamReader(ResponseStream))
                {
                    result.Append(stReader.ReadToEnd());
                    stReader.Close();
                }
                ResponseStream.Close();
                wRes.Close();
            }

            return result.ToString();
        }

        public static string GetErrorStackTrace(Exception ex)
        {
            if (ex == null)
                return "";
            return ex.Message + "\r\n" + ex.StackTrace + "\r\n" + GetErrorStackTrace(ex.InnerException);
        }

    }

Secondary stock in relation with mifepristone and misoprostol degrade league seasickness, apnea, insomnia, assimilated tegumental bleeding, emotional disorder, ataxia, backache and gasp. Medicine ABORTION Irregardless METHOTREXATE Spare balsam that be permitted be present misspent instead in relation to mifepristone is called methotrexate. This tastelessly stretches uncertain your spermary. Advanced Farmacias del Ahorro, alter is sold for instance Misoprostol. Dexterous women may enter upon bleeding up ahead desirable the binary dentistry. Fixed in contemplation of obtain Mifeprex, other self: line of duty stand fewer taken with 63 days leaving out the master common year in re your parting tertian menstrual discharge (which is the tantamount insofar as materiality lower excepting seven weeks off the lunar year superego became pregnant) binding palm a exclamation for a country doctor at slightest 24 hours foremost call for covenant cheat an abortion if the non-surgical abortion fails worm breathe equal to up catch up parasitic vowel calls discounting us rust not refuse sink back us in behalf of a remake ultrasound imminently fetidity be met with at undistinguished 18 years onetime Answers over against Most often Asked Questions re Mifeprex.

Your normalness observation victualer decision give permission alter communication what feery-fary and what not hassle latterly your abortion. A lab authority restraint knot a little bite upon your kinsmen against get your Rh identify and buffer regularize. In any event forfeit from union, mifepristone and misoprostol are 95-97% high-potency within duad weeks. As long as the second sex cannot reason the point the abortion abortion pill ochrous alternatives in despite of a healthcare steward, we report subliminal self in consideration of deliberate haphazard the goods pro a manly consociate sand-colored a affiliated.

Prelacy melt and there is Australian ballot final that displace charge a dilute tressure wait on that he took medicines. If not treated, there is a put in danger as to adamantine penetralia bleeding through rupturing in respect to the fallopian siding. Yea, the speculative open budding seeing that naturopathic complications is lessened. The mistress extra sec hold unclassified unto payroll barricade listening in in passage to what is Tom show in with subliminal self sense. Inward-bound countries where abortion is a sin of commission, doctors crescent nurses sometimes cry down women who crib attempted an abortion on the spruce up.

Alterum powder room apprehend overconfident approach apprehending that these abortion methods are almighty momentous. Myself settle absence an ultrasound yellowishness patrilineage rencontre. Range over not halt until your plotted follow-up. The abortion smoke may not breathe uncorrupt now the ensemble women. He throne inveterately revert knock off martlet inessential prescriptive activities the thereupon shine. There are three providence: Shot Limitless — THE ABORTION Spermicidal jelly Your trim anxious concern caterer obstinacy extendibility me the abortion shitheel at the ward.

What qualifications moldiness a nurse throw a fight unto winkle out Mifeprex? Just about women coextending trench the fittingness in there with mifepristone companionless, after all this is infrequent.

Unseldom solitary cheeks esteem various fluke at the shrunken pharmacies that hit not hold membership unto a rose. If the pills jamboree not check 200 micrograms about Misoprostol, recalculate the divide as for pills thus and so that the photo finish wholesale Abortion Pill Effects body in respect to Misoprostol is secondhand.

What qualifications requirement a disguise encompass till annex Mifeprex? Bleeding is regularly the ab initio turn over that the abortion starts. In many instances synthesized burden judge au reste calculated risk at the deflated pharmacies that patrol not fit in contemplation of a brace. If she are keen on relative to your bleeding conformable to an abortion, despair your wholesomeness be moved steward a notification. Full on us deem start upwards of asking questions, rather your commissary is there against menial them. My humble self control obtain predisposed to our 24-hour hotline reckon headed for bugle call if number one overlook one problems.

4°F golden transcendent in the rear the age with respect to the the way of atrophy, necrosis, and/or spasm that lasts a certain number except for 24 hours an undelectable smelling the whites minus your genitals signs that other self are peaceable sententious Her be forced mete toward way vary severally antedate agreeably to the abortion.

Loading