'***************************************************

'* This code belongs to Terry R. Olsen

'* You are free to use this code in whole or

'* in part for your own programs. But you may

'* not use this code in any way to create

'* the same type of program for public release.

'* My Email: tolsen64@hotmail.com

'***************************************************

 

Imports System.Net

Imports System.Net.Sockets

Imports System.Windows.forms

Imports System.Text.ASCIIEncoding

Imports System.IO

Imports System.IO.Ports

 

Module Module1

 

#Region "Telnet Commands"

    ' Telnet main commands  -  list copied from somewhere on the net - thank you to them

    Const TN_IAC As Int32 = 255   ' Interpret as command escape sequence, Prefix to all telnet commands. 1, 2 or sometimes more commands normally follow this character

    Const TN_DONT As Int32 = 254  ' You are not to use this option

    Const TN_DO As Int32 = 253    ' Please, you use this option

    Const TN_WONT As Int32 = 252  ' I won't use option

    Const TN_WILL As Int32 = 251  ' I will use option

    Const TN_SB As Int32 = 250    ' Subnegotiate, X number of commands follow

    Const TN_GA As Int32 = 249    ' Go ahead

    Const TN_EL As Int32 = 248    ' Erase line

    Const TN_EC As Int32 = 247    ' Erase character

    Const TN_AYT As Int32 = 246   ' Are you there

    Const TN_AO As Int32 = 245    ' Abort output

    Const TN_IP As Int32 = 244    ' Interrupt process

    Const TN_BRK As Int32 = 243   ' Break

    Const TN_DM As Int32 = 242    ' Data mark

    Const TN_NOP As Int32 = 241   ' No operation.

    Const TN_SE As Int32 = 240    ' End of subnegotiation, from above

    Const TN_EOR As Int32 = 239   ' End of record

    Const TN_ABORT As Int32 = 238 ' About process

    Const TN_SUSP As Int32 = 237  ' Suspend process

    Const TO_EOF As Int32 = 236  ' End of file

 

    ' Telnet (option) mainly return commands from above

    Const TN_BIN As Int32 = 0     ' Binary transmission

    Const TN_ECHO As Int32 = 1    ' Echo

    Const TN_RECN As Int32 = 2    ' Reconnection

    Const TN_SUPP As Int32 = 3    ' Suppress go ahead

    Const TN_APRX As Int32 = 4    ' Approx message size negotiation

    Const TN_STAT As Int32 = 5    ' Status

    Const TN_TIM As Int32 = 6     ' Timing mark

    Const TN_REM As Int32 = 7     ' Remote controlled trans/echo

    Const TN_OLW As Int32 = 8     ' Output line width

    Const TN_OPS As Int32 = 9     ' Output page size

    Const TN_OCRD As Int32 = 10   ' Out carriage-return disposition

    Const TN_OHT As Int32 = 11    ' Output horizontal tabstops

    Const TN_OHTD As Int32 = 12   ' Out horizontal tab disposition

    Const TN_OFD As Int32 = 13    ' Output formfeed disposition

    Const TN_OVT As Int32 = 14    ' Output vertical tabstops

    Const TN_OVTD As Int32 = 15   ' Output vertical tab disposition

    Const TN_OLD As Int32 = 16    ' Output linefeed disposition

    Const TN_EXT As Int32 = 17    ' Extended ascii character set

    Const TN_LOGO As Int32 = 18   ' Logout

    Const TN_BYTE As Int32 = 19   ' Byte macro

    Const TN_DATA As Int32 = 20   ' Data entry terminal

    Const TN_SUP As Int32 = 21    ' supdup protocol

    Const TN_SUPO As Int32 = 22   ' supdup output

    Const TN_SNDL As Int32 = 23   ' Send location

    Const TN_TERM As Int32 = 24   ' Terminal type

    Const TO_EOR As Int32 = 25    ' End of record

    Const TN_TACACS As Int32 = 26 ' Tacacs user identification

    Const TN_OM As Int32 = 27     ' Output marking

    Const TN_TLN As Int32 = 28    ' Terminal location number

    Const TN_3270 As Int32 = 29   ' Telnet 3270 regime

    Const TN_X3 As Int32 = 30     ' X.3 PAD

    Const TN_NAWS As Int32 = 31   ' Negotiate about window size

    Const TN_TS As Int32 = 32     ' Terminal speed

    Const TN_RFC As Int32 = 33    ' Remote flow control

    Const TN_LINE As Int32 = 34   ' Linemode

    Const TN_XDL As Int32 = 35    ' X display location

    Const TN_ENVIR As Int32 = 36  ' Telnet environment option

    Const TN_AUTH As Int32 = 37   ' Telnet authentication option

    Const TN_NENVIR As Int32 = 39 ' Telnet environment option

    Const TN_EXTOP As Int32 = 25  ' Extended-options-list

#End Region

 

    'Serial Port Stuff

    Dim WithEvents Ser As New SerialPort

 

    'Telnet Stuff

    Dim LineSize As Integer

    Dim TcpPort As Integer = 23

    Dim TcpSvr As Socket    'TCP Listener Socket, listens for incoming calls

    Dim TcpClt As Socket    'TCP Client Socket, handles incoming calls

    Dim TcpMsg As Socket    'Tells Clients that we're busy right now...

   

    'Send & Receive Buffers

    Dim RcvBuf() As Byte    'In from TCP/Out to Serial

    Dim XmtBuf() As Byte    'In from Serial/Out to TCP

    Dim SerByt As Integer   'Bytes to read from serial port

    Dim Throttle As Integer 'Some slower terminals may need to slow it down

 

    'BBS not available message

    Dim msg() As Byte = ASCII.GetBytes("The line is busy. Please try again later.")

 

    'Stopwatch for measuring +++ Guard Time

    Dim swGuardTimer As New System.Timers.Timer

 

    'Application variables

    Dim logFile As String

    Dim iniFile As String

    Dim keepLog As Boolean = False

    Dim ver As String = "6.7.29.1"

 

    'Modem Emulator Stuff

    Enum ModemEcho

        EchoOff = 0

        EchoOn = 1

    End Enum

    Enum ModemResultCodeFormat

        Numeric = 0

        Text = 1

    End Enum

    Enum ModemResultCodes

        Enabled = 0

        Disabled = 1

    End Enum

    Enum ModemRingMode

        SendRing = 0

        SendConnect = 1

    End Enum

    Enum ModemHookState

        OnHook = 0

        OffHook = 1

    End Enum

 

    Const OK As Integer = 0

    Const CONNECT As Integer = 1

    Const RING As Integer = 2

    Const NO_CARRIER As Integer = 3

    Const ERR As Integer = 4

    Const NO_DIAL_TONE As Integer = 6

    Const BUSY As Integer = 7

    Const NO_ANSWER As Integer = 8

 

    Dim MdmErr As Integer

    Dim MdmErrorCode() As String = {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR", "", "NO DIAL TONE", "BUSY", "NO ANSWER"}

    Dim MdmCmdMode As Boolean = True  'Are we in command mode?

    Dim MdmCmdStr As String

    Dim MdmResultCodeFormat As ModemResultCodeFormat = ModemResultCodeFormat.Numeric

    Dim MdmEcho As ModemEcho = ModemEcho.EchoOn

    Dim MdmResultCodes As ModemResultCodes = ModemResultCodes.Enabled

    Dim MdmRingMode As ModemRingMode = ModemRingMode.SendConnect

    Dim MdmHookState As ModemHookState = ModemHookState.OnHook

    Dim MdmBaud As String

 

    Sub Main()

        'Display Program & Author Information

        Console.WriteLine("Internet Modem v" & ver & " by Terry R. Olsen")

        Console.WriteLine("Call The BoycoT BBS: telnet://boycot.no-ip.com:9999")

        Console.WriteLine("Get the latest version of this program: http://boycot.no-ip.com/InternetModem")

        Console.WriteLine("Email: tolsen64@hotmail.com")

        Console.WriteLine("=============================================================================")

 

        'Load the INI file. This defines our variables.

        WriteStatus("Loading Initialization Data")

        Dim tmpPth As String = My.Application.Info.DirectoryPath

        If Right(tmpPth, 1) <> "\" Then tmpPth += "\"

        iniFile = tmpPth + "InternetModem.ini"

        logFile = tmpPth + "InternetModem.log"

        Dim r As New StreamReader(iniFile)

        Dim tmp() As String

        While r.Peek > 0

            tmp = Split(r.ReadLine, "=")

            Select Case tmp(0)

                Case "TcpPort"

                    TcpPort = CInt(tmp(1))

                Case "SerPort"

                    Ser.PortName = "COM" & Trim(tmp(1))

                Case "SerBaud"

                    Ser.BaudRate = CInt(tmp(1))

                    MdmBaud = Trim(tmp(1))

                Case "SerDataBits"

                    Ser.DataBits = CInt(tmp(1))

                Case "SerParity"

                    If tmp(1) = "None" Then Ser.Parity = Parity.None

                    If tmp(1) = "Odd" Then Ser.Parity = Parity.Odd

                    If tmp(1) = "Even" Then Ser.Parity = Parity.Even

                    If tmp(1) = "Mark" Then Ser.Parity = Parity.Mark

                    If tmp(1) = "Space" Then Ser.Parity = Parity.Space

                Case "SerStopBits"

                    If tmp(1) = 1 Then Ser.StopBits = StopBits.One

                    If tmp(1) = 1.5 Then Ser.StopBits = StopBits.OnePointFive

                    If tmp(1) = 2 Then Ser.StopBits = StopBits.Two

                Case "Handshake"

                    If tmp(1) = "None" Then Ser.Handshake = Handshake.None

                    If tmp(1) = "RTS" Then Ser.Handshake = Handshake.RequestToSend

                    If tmp(1) = "RTS/XonXoff" Then Ser.Handshake = Handshake.RequestToSendXOnXOff

                    If tmp(1) = "XonXoff" Then Ser.Handshake = Handshake.XOnXOff

                Case "RcvBuf"

                    Ser.WriteBufferSize = CInt(tmp(1))

                    ReDim RcvBuf(CInt(tmp(1)))

                Case "XmtBuf"

                    Ser.ReadBufferSize = CInt(tmp(1))

                    ReDim XmtBuf(CInt(tmp(1)))

                Case "KeepLog"

                    keepLog = CBool(tmp(1))

                Case "BBSName"

                    msg = ASCII.GetBytes(tmp(1) & " is currently in use." & vbCrLf & vbCrLf & _

                          "Please try again soon!" & vbCrLf & vbCrLf & _

                          "While you're waiting...give The BoycoT BBS a call..." & vbCrLf & _

                          "telnet://boycot.no-ip.com:9999")

                Case "Throttle"

                    Throttle = CInt(tmp(1))

                Case "LineSize"

                    LineSize = CInt(tmp(1))

            End Select

        End While

        r.Close()

 

        Ser.ReceivedBytesThreshold = 1   'Raise an event for each character received

        'Open the serial port

        WriteStatus("Opening " & Ser.PortName & "," & Ser.BaudRate & "," & Ser.DataBits & _

                    "," & Ser.Parity.ToString & "," & Ser.StopBits & "," & Ser.Handshake.ToString)

        Try

            Ser.Open()

            Ser.DtrEnable = True

            Ser.RtsEnable = True

        Catch ex As Exception

            WriteStatus(ex.Message)

            WriteStatus("Failed!")

            Console.WriteLine("Press ENTER to exit.")

            Console.ReadLine()

            Exit Sub

        End Try

        StartTCPServer()

        AddHandler swGuardTimer.Elapsed, AddressOf swGuardTimerFired

        swGuardTimer.Interval = 1000

        'swGuardTimer.Enabled = True

        swGuardTimer.Stop()

        Application.Run()   'Keeps us running...

    End Sub

 

    '====================================================================

    'Our TCP Server Routines.

    Private Sub StartTCPServer()

        Dim addr As IPAddress = IPAddress.Parse("0.0.0.0")

        Dim ep As New IPEndPoint(addr, TcpPort)

        TcpSvr = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

        TcpSvr.Bind(ep)

        TcpSvr.Listen(2)

        TcpSvr.BeginAccept(AddressOf AcceptCallback, TcpSvr)

        WriteStatus("Listening for calls on TCP Port " & TcpPort)

    End Sub

 

    Private Sub AcceptCallback(ByVal ar As IAsyncResult)

        Debug.WriteLine(Now.ToLongTimeString & " AcceptCallback")

        If TcpClt Is Nothing And MdmHookState = ModemHookState.OnHook Then

            Debug.WriteLine("TcpClt=Nothing, MdmHookState=" & MdmHookState.ToString)

            TcpClt = TcpSvr.EndAccept(ar)

            WriteStatus("Connected to " & CType(TcpClt.RemoteEndPoint, IPEndPoint).ToString)

            TcpClt.BeginReceive(RcvBuf, 0, RcvBuf.Length, SocketFlags.None, AddressOf ReceiveCallback, RcvBuf)

            MdmCmdMode = False

            MdmHookState = ModemHookState.OffHook

            ModemError(1)

        Else

            Debug.WriteLine(Now.ToLongTimeString & " TcpMsg started")

            TcpMsg = TcpSvr.EndAccept(ar)

            TcpMsg.Send(msg)

            WriteStatus("Sent busy message to " & CType(TcpMsg.RemoteEndPoint, IPEndPoint).ToString)

            TcpMsg.Shutdown(SocketShutdown.Both)

            TcpMsg.Close()

            TcpMsg = Nothing

        End If

        TcpSvr.BeginAccept(AddressOf AcceptCallback, TcpSvr)

        WriteStatus("Listening for calls on TCP Port " & TcpPort)

    End Sub

 

    Private Sub ReceiveCallback(ByVal ar As IAsyncResult)

        RcvBuf = CType(ar.AsyncState, Byte())

        Dim numbytes As Int32

        Try

            numbytes = TcpClt.EndReceive(ar)

        Catch

            Exit Sub

        End Try

        If numbytes = 0 Then    'client has disconnected.

            Ser.DtrEnable = False

            Ser.RtsEnable = False

            HangUp(False)       'False = Remote initiated disconnect

            MdmHookState = ModemHookState.OnHook

            Ser.DtrEnable = True

            Ser.RtsEnable = True

            ModemError(NO_CARRIER)

            Exit Sub

        End If

        If MdmCmdMode = False Then ProcessIncoming(numbytes)

 

        TcpClt.BeginReceive(RcvBuf, 0, RcvBuf.Length, SocketFlags.None, AddressOf ReceiveCallback, RcvBuf)

    End Sub

 

    Sub ProcessIncoming(ByVal numbytes As Int32)

        For i As Integer = 0 To numbytes - 1

            Select Case RcvBuf(i)

                Case TN_IAC

                    'WriteStatus("Telnet Protocol in use.")

                    Dim byt(0 To 2) As Byte

                    byt(0) = TN_IAC

                    i += 1

                    Select Case RcvBuf(i)

                        Case TN_SB

                            'ToChatWindow("  TN_SB" & vbCrLf)

                            WriteStatus("TN_SB Received! Subnegotiate Incomplete.")

                            Do

                                i += 1

                            Loop Until RcvBuf(i) = TN_SE Or i = numbytes - 1

 

                        Case TN_DO      'Server asking you to do something

                            'ToChatWindow("  TN_DO " & Str(buffer(i + 1)) & vbCrLf)

                            i += 1

                            Select Case RcvBuf(i)

                                Case TN_NAWS

                                    byt(1) = TN_WILL

                                    byt(2) = RcvBuf(i)

                                    SendBytesToHost(byt)

                                    SetLineSize()

                                Case Else

                                    byt(1) = TN_WONT

                                    byt(2) = RcvBuf(i)

                                    SendBytesToHost(byt)

                            End Select

                        Case TN_DONT    'Server asking you to NOT do something

                            'ToChatWindow("  TN_DONT" & Str(buffer(i + 1)) & vbCrLf)

                            byt(1) = TN_WONT

                            i += 1

                            byt(2) = RcvBuf(i)

                            SendBytesToHost(byt)

                        Case TN_WILL    'Server telling you it will do something

                            'ToChatWindow("  TN_WILL" & Str(buffer(i + 1)) & vbCrLf)

                            byt(1) = TN_DONT

                            i += 1

                            byt(2) = RcvBuf(i)

                            SendBytesToHost(byt)

                        Case TN_WONT    'Server telling you it won't do someting

                            'ToChatWindow("  TN_WONT" & Str(buffer(i + 1)) & vbCrLf)

                            byt(1) = TN_DONT

                            i += 1

                            byt(2) = RcvBuf(i)

                            SendBytesToHost(byt)

                    End Select

                Case Else

                    Try

                        Threading.Thread.Sleep(Throttle)

                        'Debug.Write(ASCII.GetString(RcvBuf, i, 1))

                        Ser.Write(RcvBuf, i, 1)

                    Catch ex As Exception

                        WriteStatus("----------------------------")

                        WriteStatus("Routine: ReceiveCallBack")

                        WriteStatus("Exception: " & ex.Message)

                        WriteStatus("Chat Msg: " & Chr(RcvBuf(i)))

                    End Try

            End Select

        Next

    End Sub

 

    Private Sub SetLineSize()

        'The syntax for the subnegotiation is: IAC SB NAWS WIDTH[1] WIDTH[0] HEIGHT[1] HEIGHT[0] IAC SE

        Dim byt() As Byte = {TN_IAC, TN_SB, TN_NAWS, LineSize \ 256, LineSize Mod 256, 0, 24, TN_IAC, TN_SE}

        SendBytesToHost(byt)

    End Sub

 

    Private Sub SendBytesToHost(ByVal byt() As Byte)

        TcpClt.Send(byt, byt.Length, SocketFlags.None)

    End Sub

 

    Private Sub HangUp(ByVal local As Boolean)

        MdmErr = OK

        If Not TcpClt Is Nothing Then

            Try

                TcpClt.Shutdown(SocketShutdown.Both)

                TcpClt.Close()

                TcpClt = Nothing

                MdmErr = NO_CARRIER

                If local = True Then

                    WriteStatus("Locally initiated disconnect")

                Else

                    WriteStatus("Remote initiated disconnect")

                End If

            Catch ex As Exception

                WriteStatus("Locally initiated disconnect, already offline")

            End Try

        Else

            WriteStatus("Locally initiated disconnect, already offline")

        End If

        MdmCmdMode = True

        Debug.WriteLine(MdmCmdMode.ToString)

    End Sub

 

    'Routine to write status to console window...

    'and to log file if set.

    Private Sub WriteStatus(ByVal msg As String)

        Dim dt As String = Date.Now.ToShortDateString & " " & Date.Now.ToShortTimeString

        msg = dt & " - " & msg

        Console.WriteLine(msg)

        Exit Sub

        If keepLog = True Then

            Dim sw As New StreamWriter(logFile, True)

            'w = My.Computer.FileSystem.OpenTextFileWriter(logFile, True)

            sw.WriteLine(msg)

            sw.Close()

        End If

    End Sub

 

    Private Sub SerRcvEvent(ByVal sender As Object, ByVal e As SerialDataReceivedEventArgs) Handles Ser.DataReceived

        SerByt = Ser.BytesToRead

        Ser.Read(XmtBuf, 0, SerByt)

        Dim rcvString As String = ASCII.GetString(XmtBuf, 0, SerByt)

        Debug.Write(rcvString)

 

        ' --Did we get a Modem Esc Command?

        '   If so, start the 1 second timer.

        If InStr(rcvString, "+++") Then

            swGuardTimer.Start()

        End If

 

        ' --If we're in command mode, send characters received to be processed

        If MdmCmdMode = True Then

            ProcessMdmCmd(rcvString)

            Exit Sub

        End If

 

        ' --Otherwise, send it out to our connected user.

        If TcpClt Is Nothing Then Exit Sub

        Try

            TcpClt.Send(XmtBuf, SerByt, SocketFlags.None)

        Catch

        End Try

    End Sub

 

    Private Sub ProcessMdmCmd(ByVal CmdStr As String)

        MdmErr = OK

        MdmCmdStr += UCase(CmdStr)

        If MdmEcho = ModemEcho.EchoOn Then Ser.Write(CmdStr)

 

        '--Command is still coming in if we haven't received the CR

        If Right(MdmCmdStr, 1) <> Chr(13) Then Exit Sub

        '--CR only does not a command make...

        If MdmCmdStr.Equals(vbCr) Then

            MdmCmdStr = ""

            Exit Sub

        End If

 

        '--Get rid of the +'s from the ESC sequence, and trim off the CR

        MdmCmdStr = MdmCmdStr.Replace("+", "").Trim(Chr(13))

        Debug.WriteLine("MdmCmdStr: " & MdmCmdStr)

 

        '--All good command strings begin with AT

        If Left(MdmCmdStr, 2) <> "AT" Then

            Debug.WriteLine("MdmCmdStr doesn't begin with AT")

            MdmCmdStr = ""

            ModemError(ERR)

            Exit Sub

        End If

 

        '--Sometimes they just type AT to see if the modem is responding.

        If MdmCmdStr = "AT" Then

            MdmCmdStr = ""

            ModemError(OK)

            Exit Sub

        End If

 

        '--Now start dealing with the command strings...

        Dim tmpCmd As String

        If InStr(MdmCmdStr, "ATA") Then

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "ATD ") Or InStr(MdmCmdStr, "ATDT ") Then

            GoDialOut(MdmCmdStr)

            MdmCmdStr = ""

            Exit Sub

        End If

        If InStr(MdmCmdStr, "ATI") Then

            Ser.Write("Internet Modem Emulator v" & ver & " by Terry Olsen" & vbCr)

            MdmErr = OK

            MdmCmdStr = ""

            'Exit Sub

        End If

        If InStr(MdmCmdStr, "AT&V") Then

            Ser.Write("This will be our &V display page." & vbCr)

            MdmErr = OK

            MdmCmdStr = ""

            'Exit Sub

        End If

        If InStr(MdmCmdStr, "ATZ") Then

            HangUp(True)

            MdmCmdMode = True

            MdmHookState = ModemHookState.OnHook

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "E") Then

            tmpCmd = Mid(MdmCmdStr, InStr(MdmCmdStr, "E") + 1, 1)

            Debug.Write("E" & tmpCmd & ":")

            If Val(tmpCmd) > 1 Then

                MdmErr = ERR

            Else

                MdmEcho = Val(tmpCmd)

            End If

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "H") Then

            tmpCmd = Mid(MdmCmdStr, InStr(MdmCmdStr, "H") + 1, 1)

            Debug.Write("H" & tmpCmd & ":")

            If Val(tmpCmd) > 1 Then

                MdmErr = ERR

            Else

                MdmHookState = Val(tmpCmd)

                HangUp(True)    'True = Locally initiated disconnect

            End If

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "Q") Then

            tmpCmd = Mid(MdmCmdStr, InStr(MdmCmdStr, "Q") + 1, 1)

            Debug.Write("Q" & tmpCmd & ":")

            If Val(tmpCmd) > 1 Then

                MdmErr = ERR

            Else

                MdmEcho = Val(tmpCmd)

            End If

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "S0") Then

            tmpCmd = Mid(MdmCmdStr, InStr(MdmCmdStr, "S0=") + 3, 1)

            Debug.Write("S0=" & tmpCmd & ":")

            If Val(tmpCmd) > 1 Then

                MdmErr = ERR

            Else

                MdmRingMode = Val(tmpCmd)

            End If

            MdmCmdStr = ""

        End If

        If InStr(MdmCmdStr, "V") Then

            tmpCmd = Mid(MdmCmdStr, InStr(MdmCmdStr, "V") + 1, 1)

            Debug.Write("V" & tmpCmd & ":")

            If Val(tmpCmd) > 1 Then

                MdmErr = ERR

            Else

                MdmResultCodeFormat = Val(tmpCmd)

            End If

            MdmCmdStr = ""

        End If

 

        ModemError(MdmErr)

    End Sub

 

    Private Sub ModemError(ByVal code As Integer)

        If MdmResultCodes = ModemResultCodes.Enabled Then

            If MdmResultCodeFormat = ModemResultCodeFormat.Text Then

                Debug.WriteLine("MdmErrCode: " & MdmErrorCode(code))

                Ser.Write(vbCr & MdmErrorCode(code))

                If code = 1 Then Ser.Write(" " & MdmBaud)

                Ser.Write(vbCr)

            Else

                Ser.Write(vbCr & code & vbCr)

                Debug.WriteLine("MdmErrCode: " & code)

            End If

        End If

    End Sub

 

    Private Sub GoDialOut(ByVal cmd As String)

        Dim port As Integer

        Dim IP As IPAddress

        Dim host As String

 

        '--First, get rid of the AT command

        cmd = cmd.Replace("ATDT ", "").Trim

        cmd = cmd.Replace("ATD ", "").Trim

 

        cmd = cmd.Trim(Chr(13))

        'Debug.WriteLine("CMD=" & cmd)

 

        '--Next, see if a port is specified

        cmd = cmd.Replace(",", ":")   'Change comma separator to colon

        cmd = cmd.Replace(" ", ":")   'change space separator to colon

        'Debug.WriteLine("CMD=" & cmd)

 

        '--Define the port we'll use to dial out

        If cmd.Contains(":") Then

            port = Val(Mid(cmd, InStr(cmd, ":") + 1))

            cmd = cmd.Remove(cmd.IndexOf(":"))

        Else

            port = 23

        End If

        'Debug.WriteLine("CMD=" & cmd)

        'Debug.WriteLine("PORT=" & port)

        'Exit Sub

 

        '--Now we check what kind of address we have.  It could be:

        '   hostname.com, xx.xxx.xx.x, or WWWXXXYYYZZZ

        Dim IpNoDots As Boolean = True

        If Not cmd.Contains(".") Then

            If cmd.Length = 12 Then

                For i As Integer = 1 To 12

                    If Not (Mid(cmd, i, 1) >= "0" And Mid(cmd, i, 1) <= "9") Then

                        IpNoDots = False : Exit For

                    End If

                Next

                If IpNoDots = True Then

                    cmd = cmd.Insert(9, ".")

                    cmd = cmd.Insert(6, ".")

                    cmd = cmd.Insert(3, ".")

                End If

            End If

        End If

        'Debug.WriteLine("CMD=" & cmd)

        'Debug.WriteLine("PORT=" & port)

        'Exit Sub

 

        '--By the time we get here, we should have either a hostname or

        '   an IP address in the form of xxx.xx.xx.x

        Try

            IP = Dns.GetHostEntry(cmd).AddressList(0)

            Try

                host = Dns.GetHostEntry(IP).HostName

            Catch

                host = cmd

            End Try

            WriteStatus("Dialing: " & host & " (" & IP.ToString & ") on port " & port.ToString)

        Catch ex As SocketException

            WriteStatus("Error dialing " & cmd & ":" & port.ToString)

            WriteStatus("Error message:" & ex.Message)

            ModemError(NO_DIAL_TONE)

            Exit Sub

        End Try

 

        MdmCmdMode = False

        Dim IPE As New IPEndPoint(IP, port)

 

        Try

            TcpClt = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

            TcpClt.BeginConnect(IPE, AddressOf DialOutConnected, Nothing)

        Catch ex As SocketException

            ModemError(NO_DIAL_TONE)

            WriteStatus(ex.Message)

        End Try

 

    End Sub

 

    Private Sub DialOutConnected(ByVal ar As IAsyncResult)

        Try

            TcpClt.EndConnect(ar)

        Catch ex As SocketException

            WriteStatus(ex.Message)

            MdmCmdMode = True

            ModemError(NO_ANSWER)

            Exit Sub

        End Try

        WriteStatus("Connection established.")

        ModemError(CONNECT)

        TcpClt.BeginReceive(RcvBuf, 0, RcvBuf.Length, SocketFlags.None, AddressOf ReceiveCallback, RcvBuf)

    End Sub

 

    Private Sub swGuardTimerFired(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs)

        swGuardTimer.Stop()

        If Ser.BytesToRead < 1 Then

            MdmCmdMode = True

            ModemError(OK)

        Else

            MdmCmdMode = False

            If TcpClt Is Nothing Then Exit Sub

            TcpClt.Send(XmtBuf, SerByt, SocketFlags.None)

        End If

    End Sub

 

End Module