Private Sub StartBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartBtn.Click
Dim bgthread As New Threading.Thread(AddressOf StartServer)
bgthread.IsBackground = True
bgthread.Start() 'Start new background thread that runs the StartServer Sub
StartBtn.Enabled = False
Stopbtn.Enabled = True
End Sub
''' <summary>
''' Starts listening on port 25 and passes incoming requests to a ThreadPool thread for processing
''' </summary>
Private Sub StartServer()
Threading.ThreadPool.SetMaxThreads(40, 300) 'Set the maximum amount of threads the ThreadPool can create for us simultaneously
Dim TListener As New TcpListener(Net.IPAddress.Any, 25) 'Create the listener that will accept connections on port 25
TListener.Start() 'Start the listener
'When a new client connection is accepted, start the StartSession Sub on a new ThreadPool thread
'and then loop back to get ready for new client to connect
Do
Threading.ThreadPool.QueueUserWorkItem(AddressOf StartSession, TListener.AcceptTcpClient)
Loop
End Sub
''' <summary>
''' Handles the session and command processing for each connected client
''' </summary>
''' <param name="AcceptedTcpClient">The TcpClient object that represents the connected client</param>
Private Sub StartSession(ByVal AcceptedTcpClient As Object)
Dim TClient As TcpClient = DirectCast(AcceptedTcpClient, TcpClient)
Dim RemoteIP As String = TClient.Client.RemoteEndPoint.ToString
WriteToClientStream(TClient.GetStream, Now.ToShortTimeString & " - Prototype SMTP Server")
BG_WriteToLog(RemoteIP & " connected at " & Now.ToString)
Dim strbuild As New StringBuilder
Dim ExitSession As Boolean = False
Dim CommandEntered As String = String.Empty
Do While ExitSession = False
Do
Dim size As Int32 = 0
Dim DataAsBytes(10) As Byte
size = TClient.GetStream.Read(DataAsBytes, 0, 10)
If DataAsBytes(0) = 13 AndAlso DataAsBytes(1) = 10 Then
Exit Do
End If
Dim ShortDataAsString As String = System.Text.Encoding.ASCII.GetString(DataAsBytes, 0, size)
strbuild.Append(ShortDataAsString)
Loop 'Start listening for new data on the stream again
CommandEntered = strbuild.ToString
BG_WriteToLog(RemoteIP & " : " & CommandEntered)
If String.Compare(CommandEntered, "HELO", True) = 0 Then
WriteToClientStream(TClient.GetStream, "HELO From " & TClient.Client.LocalEndPoint.ToString)
ElseIf String.Compare(CommandEntered, "QUIT", True) = 0 Then
ExitSession = True
TClient.Close()
Else
WriteToClientStream(TClient.GetStream, "Unknown Command: " & CommandEntered)
End If
strbuild.Remove(0, strbuild.Length) 'Clear out the command string ready for next command
Loop 'Start processing commands that are sent from the client again
End Sub
''' <summary>
''' Writes a message back to the client's stream.
''' If the client is a telnet client then this message will appear in the telnet console
''' </summary>
''' <param name="stream">The underlying stream to write to</param>
''' <param name="msg">The string to write to the stream</param>
Private Sub WriteToClientStream(ByVal stream As IO.Stream, ByVal msg As String)
Dim Writer As New IO.StreamWriter(stream)
Writer.WriteLine(msg)
Writer.Flush()
End Sub
''' <summary>
''' Writes to the log file and to the textbox on the screen.
''' Intended to be executed on the UI thread
''' </summary>
''' <param name="msg">The string to write to the log</param>
Private Sub UI_WriteToLog(ByVal msg As String)
logbox.AppendText(msg & vbNewLine)
End Sub
''' <summary>
''' Invokes a delegate to execute the UI_WriteToLog Sub.
''' Intended to be executed from a background thread.
''' </summary>
''' <param name="msg">The string to write to the log</param>
Private Sub BG_WriteToLog(ByVal msg As String)
Me.Invoke(New Action(Of String)(AddressOf UI_WriteToLog), msg)
End Sub