Click here to Skip to main content
15,896,453 members
Articles / Programming Languages / C#

Network Stuff (easy socket v3)

Rate me:
Please Sign up or sign in to vote.
4.87/5 (52 votes)
2 Jun 2005 217.3K   6.1K   137  
A class with event handlers for TCP, UDP or ICMP sockets; includes ping, traceroute, whois, ARP, and IPHelper functions and raw packets forging/ capturing.
/*
Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>
Dynamic aspect ratio code Copyright (C) 2004 Jacquelin POTIER <jacquelin.potier@free.fr>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
using System;

namespace Network_Stuff
{
    /// <summary>
    /// Summary description for Telnet.
    /// Small class used only to remove unwanted data and give command to remove echo
    /// To be improved for other functions
    /// </summary>
    public class Telnet
    {
        public static string COMMAND_TO_REMOVE_ECHO=new string(new char[6]{(char)(byte)TELNET_COMMANDS.IAC,(char)(byte)TELNET_COMMANDS.WONT,(char)(byte)TELNET_OPTIONS.ECHO,(char)(byte)TELNET_COMMANDS.IAC,(char)(byte)TELNET_COMMANDS.DONT,(char)(byte)TELNET_OPTIONS.ECHO});
        public bool b_clear_screen;
        public bool b_erase_char;
        public bool b_erase_line;
        public bool b_remote_echo;
        public bool b_local_echo;
        public bool b_remove_local_echo_and_ask_to_remove_remote_echo;
        public bool b_allow_beep;

        public char end_of_prompt;
        private string last_sent_command;
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool Beep(int frequency, int duration);

        public Telnet()
        {
            this.b_clear_screen=false;
            this.b_erase_char=false;
            this.b_erase_line=false;
            this.b_remote_echo=true;
            this.b_local_echo=false;
            this.b_allow_beep=true;
            this.last_sent_command="";
            this.b_remove_local_echo_and_ask_to_remove_remote_echo=true;
            this.end_of_prompt='>';
        }

        private void reset_command_members()
        {
            this.b_clear_screen=false;
            this.b_erase_char=false;
            this.b_erase_line=false;
        }

        #region telnet const
        private const byte TELNET_BEL=7;
        private const byte TELNET_BS=8;
        private const byte TELNET_HT=9;
        private const byte TELNET_VT=11;
        private const byte TELNET_FF=12;
        
        private enum TELNET_OPTIONS:byte
        {
            SUPPRESS_GO_AHEAD        =3,  // RFC 858 
            STATUS                    =5,  // RFC 859 
            ECHO                    =1,  // RFC 857 
            TIMING_MARK                =6,  // RFC 860 
            TERMINAL_TYPE            =24, // RFC 1091 
            WINDOW_SIZE                =31, // RFC 1073 
            TERMINAL_SPEED            =32, // RFC 1079 
            REMOTE_FLOW_CONTROL        =33, // RFC 1372 
            LINEMODE                =34, // RFC 1184 
            ENVIRONMENT_VARIABLES    =36  // RFC 1408 
        }
        private enum TELNET_COMMANDS:byte
        {
            SE=240,// End of subnegotiation parameters  
            NOP,//241 No operation  
            DM,// 242 Data mark Indicates the position of a Synch event within the data stream. This should always be accompanied by a TCP urgent notification. 
            BRK,// 243 Break Indicates that the "break" or "attention" key was hi.  
            IP,// 244 Suspend Interrupt or abort the process to which the NVT is connected. 
            AO,// 245 Abort output Allows the current process to run to completion but does not send its output to the user.  
            AYT,// 246 Are you there Send back to the NVT some visible evidence that the AYT was received. 
            EC,// 247 Erase character The receiver should delete the last preceding undeleted character from the data stream.  
            EL,// 248 Erase line Delete characters from the data stream back to but not including the previous CRLF.  
            GA,// 249 Go ahead Under certain circumstances used to tell the other end that it can transmit. 
            SB,// 250 Subnegotiation Subnegotiation of the indicated option follows. 
            WILL,// 251 will Indicates the desire to begin performing, or confirmation that you are now performing, the indicated option. 
            WONT,// 252 wont Indicates the refusal to perform, or continue performing, the indicated option. 
            DO,// 253 do Indicates the request that the other party perform, or confirmation that you are expecting the other party to perform, the indicated option. 
            DONT,// 254 dont Indicates the demand that the other party stop performing, or confirmation that you are no longer expecting the other party to perform, the indicated option.  
            IAC// 255 
        }
        #endregion

        #region parse
        public void parse(ref string txt)
        {
            int pos;
            int pos2;
            string buffer;
            this.reset_command_members();

            //char[] c1=txt.ToCharArray(); // for debug only

            // clear screen
            pos=txt.LastIndexOf((char)TELNET_FF);
            if (pos>-1)
            {
                // put clear_screen flag at true (the caller should clear data)
                this.b_clear_screen=true;
                // removes that is before last pos
                if (txt.Length<pos+1)
                {
                    txt="";
                    // non more data --> nothing to do
                    return;
                }
                txt=txt.Substring(pos+1);
            }

            // BELL
            if (txt.IndexOf((char)TELNET_BEL)>-1)
            {
                if (this.b_allow_beep)
                    Beep(400,100);
                txt=txt.Replace(new string((char)TELNET_BEL,1),"");
            }

            // Vertical Tabulation
            if (txt.IndexOf((char)TELNET_VT)>-1)
            {
                txt=txt.Replace(new string((char)TELNET_VT,1),"\r\n");
            }

            // Horizontal tabulation
            if (txt.IndexOf((char)TELNET_HT)>-1)
            {
                txt=txt.Replace(new string((char)TELNET_HT,1),"\t");
            }

            // Erase char
            pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.EC));// byte cast because of compilation error on .NET 2002
            while (pos>-1)
            {
                buffer="";
                if (pos>1)
                    buffer=txt.Substring(0,pos-1);
                else
                    this.b_erase_char=true;// the caller should remove previous char
                buffer+=txt.Substring(pos+1);
                txt=buffer;
                pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.EC));
            }

            // Erase line
            pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.EL));
            while (pos>-1)
            {
                buffer="";
                if (pos>1)
                    buffer=txt.Substring(0,pos-1);
                pos2=buffer.LastIndexOf("\r\n");
                if (pos2>-1)
                    buffer=buffer.Substring(0,pos2+2);// let \r\n
                else
                {
                    buffer="";
                    this.b_erase_line=true;// the caller should remove previous line
                }
                buffer+=txt.Substring(pos+1);
                txt=buffer;
                pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.EL));
            }

            pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.IAC));
            while (pos>-1)
            {
                switch ((byte)(System.Convert.ToChar(txt.Substring(pos+1,1))))
                {
                    case (byte)TELNET_COMMANDS.SB:
                        // remove data between sb and se
                        // look for se
                        pos2=txt.IndexOf((char)(byte)TELNET_COMMANDS.SE,pos);
                        if (pos2<0)
                        {
                            txt=txt.Substring(0,pos);
                            return;
                        }
                        txt=txt.Substring(0,pos)+txt.Substring(pos2);
                        break;
                    case (byte)TELNET_COMMANDS.DO:
                        if ((byte)(System.Convert.ToChar(txt.Substring(pos+2,1)))==(byte)TELNET_OPTIONS.ECHO)
                            this.b_local_echo=true;
                        // remove the following command
                        txt=txt.Substring(0,pos)+txt.Substring(pos+3);
                        break;
                    case (byte)TELNET_COMMANDS.DONT:
                        if ((byte)(System.Convert.ToChar(txt.Substring(pos+2,1)))==(byte)TELNET_OPTIONS.ECHO)
                            this.b_local_echo=false;
                        // remove the following command
                        txt=txt.Substring(0,pos)+txt.Substring(pos+3);
                        break;
                    case (byte)TELNET_COMMANDS.WILL:
                        if ((byte)(System.Convert.ToChar(txt.Substring(pos+2,1)))==(byte)TELNET_OPTIONS.ECHO)
                            this.b_remote_echo=true;
                        // remove the following command
                        txt=txt.Substring(0,pos)+txt.Substring(pos+3);
                        break;
                    case (byte)TELNET_COMMANDS.WONT:
                        if ((byte)(System.Convert.ToChar(txt.Substring(pos+2,1)))==(byte)TELNET_OPTIONS.ECHO)
                            this.b_remote_echo=false;
                        // remove the following command
                        txt=txt.Substring(0,pos)+txt.Substring(pos+3);
                        break;
                    default:
                        txt=txt.Substring(0,pos)+txt.Substring(pos+2);
                        break;
                }
                pos=txt.IndexOf((char)((byte)TELNET_COMMANDS.IAC));
            }

            // remove all non 7 bits characters
            for (pos=127;pos<256;pos++)
                txt=txt.Replace(new string((char)pos,1),"");
            // remove other control chars
            for (pos=0;pos<30;pos++)
            {
                if ((pos==10) || (pos==13))
                    continue;
                txt=txt.Replace(new string((char)pos,1),"");
            }

            // char[] c2=txt.ToCharArray(); // for debug only
        }
        #endregion

        #region remove echo
        public void set_sent_command(string cmd)
        {
            this.last_sent_command=cmd;
        }
        public void remove_echo_from_command(ref string cmd)
        {
            int prompt_size=0;
            if (this.last_sent_command.Length==0)
                return;
            
            System.Collections.ArrayList al=new System.Collections.ArrayList();
            
            // split cmd on \r and \n
            string[] str_array=cmd.Split(new char[2]{'\r','\n'});
            // for each line
            for (int cpt=0;cpt<str_array.Length;cpt++)
            {
                if (str_array[cpt].Length==0)
                    continue;
                prompt_size=str_array[cpt].IndexOf(this.end_of_prompt)+1;
                if (prompt_size<=0)// end of prompt not found
                    prompt_size=0;
                // if line ends with the begin of the first not echoed command and line length <command length(+prompt size)--> echo
                if (
                    (this.cmd_ends_with_begin_of_not_echoed_cmd(str_array[cpt],this.last_sent_command,prompt_size))
                    && (str_array[cpt].Length-prompt_size<=this.last_sent_command.Length)
                    )
                {
                    // --> remove line
                    str_array[cpt]="";
                }
                if (str_array[cpt].Length!=0)
                    al.Add(str_array[cpt]);
            }
            // join not empty elements of Array
            str_array=(string[])al.ToArray(typeof(string));
            cmd=System.String.Join("\n",str_array);
        }
        private bool cmd_ends_with_begin_of_not_echoed_cmd(string cmd,string not_echoed_cmd,int prompt_size)
        {
            if (prompt_size>0)
                cmd=cmd.Substring(prompt_size);
            if (not_echoed_cmd.StartsWith(cmd))
                return true;
            return false;
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
France France

Comments and Discussions