Click here to Skip to main content
15,896,298 members
Home / Discussions / C#
   

C#

 
QuestionImpersonation using C# Pin
JohnLBevan4-Nov-10 1:45
professionalJohnLBevan4-Nov-10 1:45 
AnswerRe: Impersonation using C# Pin
Adam R Harris4-Nov-10 4:49
Adam R Harris4-Nov-10 4:49 
AnswerRe: Impersonation using C# Pin
Manfred Rudolf Bihy4-Nov-10 5:06
professionalManfred Rudolf Bihy4-Nov-10 5:06 
GeneralRe: Impersonation using C# Pin
JohnLBevan9-Nov-10 5:43
professionalJohnLBevan9-Nov-10 5:43 
GeneralRe: Impersonation using C# Pin
Manfred Rudolf Bihy12-Nov-10 2:07
professionalManfred Rudolf Bihy12-Nov-10 2:07 
QuestionServer based on AsyncCallback not running as expected Pin
Tichaona J4-Nov-10 1:08
Tichaona J4-Nov-10 1:08 
AnswerRe: Server based on AsyncCallback not running as expected Pin
jschell4-Nov-10 8:32
jschell4-Nov-10 8:32 
QuestionGot a working ICMP listener; but how does it work? Pin
nebbukadnezzar4-Nov-10 0:28
nebbukadnezzar4-Nov-10 0:28 
It’s always pleasing when a piece of software works the way you want to, but as long as I don’t understand precisely why (or how) it works I consider that a big problem. I made an ICMP listener to compensate for a flaw in the ’UdpClient’ class, that will not return appropriate ICMP messages resulting from requests made when unexpectedly the remote host becomes unavailable. (ICMP Type 3, any Code). Instead of replying with an ICMP code, it simply throws an error: (WSACONNRESET) and ‘Cannot access a disposed object’.

The code as I have it running now uses ManualResetEvents as signaling, which is acceptable. The resulting data has been carefully checked, even at time-slot and sequence number level, and all is well. I just don’t understand why a new ‘StateObject’ is required for every iteration of the loop.
There is no reason that I am aware of that states that the current buffer cannot be re-used. Nevertheless, if I don’t use a new one every iteration, the buffer returned is invalid (no errors though); the buffer then refers to a packet from my host to an external destination instead of a buffer from a remote host. Therefore, I see my system’s reply to an echo (Type 0) request, instead of the actual echo request (Type 8) received (as seen in Wireshark). As soon as I change the loop to use a new ‘StateObject’, all is well again. The examples of Microsoft did not include a disposable ‘StateObject’, so I made a new class that inherits from IDisposable for that purpose.

Furthermore, when switching from ManualResetEvent signaling to ‘AsyncWaitHandle’ signaling, the process only works when using a recursive call to the callback delegate. If I don’t, the ’IASyncResult’ ‘IsCompleted’ is not always set (even though all buffers are the same 60 bytes), so it will wait indefinitely on the handle.

A long story (and a lot of code) but I hope someone will be able to shed some light on these issues.

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Linq;
using System.Text;
using System.Threading;
using log4net;

namespace ICMPTest
{
    public class ICMPCheck
    {
        private static ManualResetEvent gotMessage;
        private static IPAddress ipAddress;
        private static IntPtr stateHandle; // Dont know what it is for, or what to do with it
        private static ICMP.Disposables.StateObject so = null;
        private static Socket icmpClient;
        private static EndPoint remoteRawEndPoint = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
        public static Queue<byte[]> m_icmpQueue = new Queue<byte[]>();
        public static object m_syncLock = new object();
        private static IPEndPoint NIC = null;
        private static int Queued = 0;
        private static int DeQueued = 0;
        private static int CallCount = 0;
        public static IAsyncResult iar;

        public static void Start()
        {
            try
            {
                using (icmpClient = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp))
                {
                    IPHostEntry hostEntry = Dns.GetHostEntry(Dns.GetHostName());
                    IPHostEntry hostInfo = Dns.Resolve(Dns.GetHostName());
                    IPAddress[] address = hostInfo.AddressList;
                    ipAddress = address[0];
                    NIC = new IPEndPoint(ipAddress, 0);
                    icmpClient.Bind(NIC); // Bind to localhost, port any
                    byte[] inBytes = new byte[] { 1, 0, 0, 0 };
                    byte[] outBytes = new byte[] { 0, 0, 0, 0 };
                    icmpClient.IOControl(IOControlCode.ReceiveAll, inBytes, outBytes); //only outgoing packets
                    icmpClient.ReceiveBufferSize = 1024;

                    while (true)
                    {
                        //gotMessage = new ManualResetEvent(false);
                        using (so = new ICMP.Disposables.StateObject(stateHandle))
                        {
                            so.workSocket = icmpClient;

                            iar = icmpClient.BeginReceiveFrom(so.buffer, 0, ICMP.Disposables.StateObject.BUFFER_SIZE, 0, ref remoteRawEndPoint, new AsyncCallback(ReceiveFromCallback), so); //blocking

                            //gotMessage.WaitOne(); //iar.AsyncWaitHandle.WaitOne(); // seems to be unreliable
                            iar.AsyncWaitHandle.WaitOne();

                            for (int i = DeQueued; i < Queued; i++)
                            {
                                //DequeueParse.DequeueAndParse(ref so);
                                Interlocked.Increment(ref DeQueued);
                                ICMP.ICMPProgram.logger.Debug("ICMPCheck-0: Signal + Message received: " + remoteRawEndPoint.ToString() + " Queue: " + m_icmpQueue.Count.ToString() + " " + Queued.ToString() + " " + DeQueued.ToString());
                            }
                        } // using StateObject
                        //gotMessage.Dispose();
                    }// while
                }//using Socket
            } // try
            catch (Exception excp)
            {
                ICMP.ICMPProgram.logger.Error("ICMPCheck: Exception Mainblock. " + excp.Message);
            }
            return;
        }
        // Your callback method should implement the EndReceiveFrom method. When your application calls BeginReceiveFrom, the system will use a separate thread to execute the 
        // specified callback method, and it will block on EndReceiveFrom until the Socket reads data or throws an exception. If you want the original thread to block after you 
        // call the BeginReceiveFrom method, use WaitHandle.WaitOne. Call ManualResetEvent.Set in the callback method when you want the original thread to continue executing. 
        // For additional information on writing callback methods, see Callback Sample.

        private static void ReceiveFromCallback(IAsyncResult iar) // The callback method must accept the IAsyncResult returned by the BeginReceiveFrom method as a parameter.
        { //Monitor.Enter(((StateObject)ar.AsyncState).workSocket); is equivalent to: lock (((StateObject)ar.AsyncState).workSocket) without try..catch //Monitor.Exit(((StateObject)ar.AsyncState).workSocket);
            Interlocked.Increment(ref CallCount);
            try
            {
                ICMP.Disposables.StateObject state = (ICMP.Disposables.StateObject)iar.AsyncState;
                Socket client = ((ICMP.Disposables.StateObject)iar.AsyncState).workSocket;
                EndPoint tempRemoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);

                int bytesRead = client.EndReceiveFrom(iar, ref tempRemoteEP);

                if (bytesRead > 0)
                {
                    if (!(((IPEndPoint)tempRemoteEP).Address).Equals(NIC.Address)) // ignore packages from local host
                    {
                        byte[] _icmpData = new byte[bytesRead];
                        byte[] icmpType = new byte[1];
                        Buffer.BlockCopy(state.buffer, 20, icmpType, 0, 1);

                        //if (((int)icmpType[0] == 3)) // only Type 3
                        if (true) // all ICMP packages for now
                        {
                            Buffer.BlockCopy(state.buffer, 0, _icmpData, 0, bytesRead); // Socket to local copy
                            lock (m_syncLock)
                            {
                                m_icmpQueue.Enqueue(_icmpData);
                                Interlocked.Increment(ref Queued);
                            }
                        }
                        // the next callback is required when using AsyncWaitHandle.WaitOne signaling, not required (but useful for high volume) for ManualResetEvents
                        client.BeginReceiveFrom(state.buffer, 0, ICMP.Disposables.StateObject.BUFFER_SIZE, 0, ref tempRemoteEP, new AsyncCallback(ReceiveFromCallback), state); // suitable for high volume
                        remoteRawEndPoint = tempRemoteEP;
                        ICMP.ICMPProgram.logger.Debug("ICMPCheck: Bytes: " + bytesRead.ToString() + ", Type: " + icmpType[0].ToString() + " " + tempRemoteEP.ToString() + " " + m_icmpQueue.Count.ToString() + " " + Queued.ToString() + " " + CallCount.ToString() + " " + iar.IsCompleted.ToString());
                        //ICMPProgram.logger.Debug("ICMPCheck: Bytes: " + bytesRead.ToString() + ", Type: " + icmpType[0].ToString() + " " + tempRemoteEP.ToString() + " " + SrcIPStr + " " + sequence.ToString() + " " + CallCount.ToString() + " " + iar.IsCompleted.ToString());
                    }
                }
                else
                {
                    ICMP.ICMPProgram.logger.Debug("ICMPCheck: bytesRead = 0 ");
                }
            }
            catch (Exception excp)
            {
                ICMP.ICMPProgram.logger.Debug("ICMPCheck:ReceiveFromCallback main " + excp.Message);
            }
            finally
            {
                //gotMessage.Set();
            }
        }
    }
}


StateObject:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Net.Sockets;

namespace ICMP
{
    public class Disposables
    {
        // A base class that implements IDisposable.
        // By implementing IDisposable, you are announcing that
        // instances of this type allocate scarce resources.
        public class StateObject : IDisposable
        {
            public Socket workSocket = null;
            public const int BUFFER_SIZE = 1024;
            public byte[] buffer = new byte[BUFFER_SIZE];
            public StringBuilder sb = new StringBuilder();

            private IntPtr handle; // Pointer to an external unmanaged resource.
            private Component component = new Component(); // Other managed resource this class uses.
            private bool disposed = false; // Track whether Dispose has been called.

            // The class constructor.
            public StateObject(IntPtr handle)
            {
                this.handle = handle;
            }

            // Implement IDisposable.
            // Do not make this method virtual.
            // A derived class should not be able to override this method.
            public void Dispose()
            {
                Dispose(true);
                // This object will be cleaned up by the Dispose method.
                // Therefore, you should call GC.SupressFinalize to
                // take this object off the finalization queue
                // and prevent finalization code for this object
                // from executing a second time.
                GC.SuppressFinalize(this);
            }

            // Dispose(bool disposing) executes in two distinct scenarios.
            // If disposing equals true, the method has been called directly
            // or indirectly by a user's code. Managed and unmanaged resources
            // can be disposed.
            // If disposing equals false, the method has been called by the
            // runtime from inside the finalizer and you should not reference
            // other objects. Only unmanaged resources can be disposed.
            private void Dispose(bool disposing)
            {
                // Check to see if Dispose has already been called.
                if (!this.disposed)
                {
                    // If disposing equals true, dispose all managed
                    // and unmanaged resources.
                    if (disposing)
                    {
                        // Dispose managed resources.
                        component.Dispose();
                    }

                    // Call the appropriate methods to clean up
                    // unmanaged resources here.
                    // If disposing is false,
                    // only the following code is executed.
                    CloseHandle(handle);
                    handle = IntPtr.Zero;

                    // Note disposing has been done.
                    disposed = true;

                }
            }

            // Use interop to call the method necessary
            // to clean up the unmanaged resource.
            [System.Runtime.InteropServices.DllImport("Kernel32")]
            private extern static Boolean CloseHandle(IntPtr handle);

            // Use C# destructor syntax for finalization code.
            // This destructor will run only if the Dispose method
            // does not get called.
            // It gives your base class the opportunity to finalize.
            // Do not provide destructors in types derived from this class.
            ~StateObject()
            {
                // Do not re-create Dispose clean-up code here.
                // Calling Dispose(false) is optimal in terms of
                // readability and maintainability.
                Dispose(false);
            }
        }
    }
}

QuestionRetrieve Value from TextBox Which is created in the code behind Pin
HatakeKaKaShi3-Nov-10 22:54
HatakeKaKaShi3-Nov-10 22:54 
AnswerRe: Retrieve Value from TextBox Which is created in the code behind Pin
John Gathogo4-Nov-10 1:00
John Gathogo4-Nov-10 1:00 
AnswerRe: Retrieve Value from TextBox Which is created in the code behind Pin
alrosan4-Nov-10 8:05
alrosan4-Nov-10 8:05 
Questionhow to find toolstrip button on a form by name Pin
Tridip Bhattacharjee3-Nov-10 21:27
professionalTridip Bhattacharjee3-Nov-10 21:27 
AnswerRe: how to find toolstrip button on a form by name [modified] Pin
Eddy Vluggen3-Nov-10 22:30
professionalEddy Vluggen3-Nov-10 22:30 
AnswerRe: how to find toolstrip button on a form by name Pin
_Erik_4-Nov-10 5:47
_Erik_4-Nov-10 5:47 
QuestionAdd Custom Utility Toolbar To VS2010 Pin
Kevin Marois3-Nov-10 12:52
professionalKevin Marois3-Nov-10 12:52 
AnswerRe: Add Custom Utility Toolbar To VS2010 Pin
Henry Minute3-Nov-10 12:56
Henry Minute3-Nov-10 12:56 
Questiondebugging mode behaves differently than final build Pin
kruegs353-Nov-10 6:02
kruegs353-Nov-10 6:02 
AnswerRe: debugging mode behaves differently than final build Pin
_Erik_3-Nov-10 6:14
_Erik_3-Nov-10 6:14 
GeneralRe: debugging mode behaves differently than final build Pin
kruegs353-Nov-10 6:41
kruegs353-Nov-10 6:41 
GeneralRe: debugging mode behaves differently than final build Pin
_Erik_3-Nov-10 6:49
_Erik_3-Nov-10 6:49 
AnswerRe: debugging mode behaves differently than final build Pin
Eddy Vluggen3-Nov-10 22:35
professionalEddy Vluggen3-Nov-10 22:35 
QuestionHow to set pixel into bitmap with Pixel format of Format8bppIndexed ? [modified] Pin
Yanshof3-Nov-10 4:14
Yanshof3-Nov-10 4:14 
AnswerRe: Hot to set pixel into bitmap with Pixel format of Format8bppIndexed ? Pin
Covean3-Nov-10 4:27
Covean3-Nov-10 4:27 
AnswerRe: How to set pixel into bitmap with Pixel format of Format8bppIndexed ? [modified] Pin
_Erik_3-Nov-10 5:02
_Erik_3-Nov-10 5:02 
Questionscreen capture help Pin
ramsayra3-Nov-10 3:38
ramsayra3-Nov-10 3:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.