Advertisement
andrewb

iServer.vb

Dec 30th, 2014
563
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 9.94 KB | None | 0 0
  1. ' --------------------
  2. ' The bulk of the iServer class code is based on the C# code written
  3. ' by Imtiaz Alman (http://www.codeproject.com/KB/IP/mywebserver.aspx).
  4. ' iServer is just a VB.NET port of his basic, web sering subroutines,
  5. ' repackaged here to act as a simple XML-RPC server.
  6. ' --------------------
  7. Imports System
  8. Imports System.IO
  9. Imports System.IO.Stream
  10. Imports System.Net
  11. Imports System.Net.Sockets
  12. Imports System.Text
  13. Imports System.Text.RegularExpressions
  14. Imports System.Text.StringBuilder
  15. Imports System.Text.UTF8Encoding
  16. Imports System.Threading
  17. Imports System.Xml
  18.  
  19. Public Class iServer
  20.  
  21.     ' "Global variables" within the class
  22.     Private iListener As TcpListener
  23.     Private iPort As Integer = 10240
  24.     Private goon As Boolean = True
  25.     Private dirloc As String
  26.  
  27.     ' Events
  28.     Public Event SrvError(ByVal msg As String, ByVal stack As String)
  29.     Public Event SrvLog(ByVal msg As String)
  30.  
  31.     ' Constructor
  32.     Public Sub New()
  33.         Me.iPort = 80
  34.         Me.dirloc = Environment.CurrentDirectory
  35.     End Sub
  36.  
  37.     Public Sub New(ByVal PortNum As Integer)
  38.         ' Sets the port number the server listens on
  39.         Me.iPort = PortNum
  40.         Me.dirloc = Environment.CurrentDirectory
  41.     End Sub
  42.  
  43.     Public Sub New(ByVal PortNum As Integer, ByVal Location As String)
  44.         Me.iPort = PortNum
  45.         Me.dirloc = Location
  46.     End Sub
  47.  
  48.     ' Properties
  49.     Public WriteOnly Property SetPort() As Integer
  50.         Set(ByVal Value As Integer)
  51.             Me.iPort = Value
  52.         End Set
  53.     End Property
  54.  
  55.     Public ReadOnly Property GetPort() As Integer
  56.         Get
  57.             Return Me.iPort
  58.         End Get
  59.     End Property
  60.  
  61.     Public WriteOnly Property SetLocation() As String
  62.         Set(ByVal Value As String)
  63.             Me.dirloc = Value
  64.         End Set
  65.     End Property
  66.  
  67.     Public ReadOnly Property GetLocation() As String
  68.         Get
  69.             Return Me.dirloc
  70.         End Get
  71.     End Property
  72.  
  73.     ' Functions and subroutines
  74.     Public Sub SendHeader(ByVal len As Integer, ByRef iSocket As Socket, ByVal contentType As String)
  75.         Dim strHeader As New StringBuilder
  76.         Dim dateNow As DateTime = DateTime.Now()
  77.  
  78.         strHeader.Append("HTTP/1.0 200 OK").Append(vbCrLf)
  79.         strHeader.Append("Server: iServer for iTunes").Append(vbCrLf)
  80.         strHeader.Append("Date: ").Append(dateNow.DayOfWeek).Append(" ").Append(dateNow.ToLocalTime).Append(vbCrLf)
  81.         strHeader.Append("Content-Length: ").Append(len.ToString()).Append(vbCrLf)
  82.         strHeader.Append("Content-Type: ").Append(contentType).Append(vbCrLf).Append(vbCrLf)
  83.  
  84.         SendToBrowser(strHeader.ToString(), iSocket)
  85.     End Sub
  86.  
  87.     Public Sub SendToBrowser(ByVal sData As String, ByRef iSocket As Socket)
  88.         Me.SendToBrowser(Encoding.UTF8.GetBytes(sData), iSocket)
  89.     End Sub
  90.  
  91.     Public Sub SendToBrowser(ByVal bSendData() As Byte, ByRef iSocket As Socket)
  92.         Dim numBytes As Integer = 0
  93.  
  94.         Try
  95.             If iSocket.Connected = True Then
  96.                 If (numBytes = iSocket.Send(bSendData, bSendData.Length, 0)) = -1 Then
  97.                     RaiseEvent SrvError("No bytes to send.", "")
  98.                     Exit Sub
  99.                 End If
  100.             End If
  101.         Catch ex As Exception
  102.             RaiseEvent SrvError(ex.Message, ex.StackTrace)
  103.         End Try
  104.     End Sub
  105.  
  106.     ' The main listener
  107.     Private Sub StartListen()
  108.         Do While goon = True
  109.  
  110.             Dim iSocket As Socket = iListener.AcceptSocket()
  111.  
  112.             If iSocket.Connected = True Then
  113.  
  114.                 Dim reqReceive() As Byte = New Byte(1024) {}
  115.                 Dim reqLen As Integer = iSocket.Receive(reqReceive, reqReceive.Length, 0)
  116.                 Dim reqBuffer As String = Encoding.UTF8.GetString(reqReceive)
  117.                 Dim headers As Hashtable = ParseHeader(reqBuffer)
  118.                 Dim contentType As String = "text/html; charset=UTF-8"
  119.                 Dim dataString As String = ""
  120.  
  121.                 If reqBuffer.Substring(0, 3) = "GET" Then
  122.                     Dim methodLen As Integer = "GET ".Length
  123.                     Dim endPos As Integer = reqBuffer.IndexOf(" HTTP") - methodLen
  124.                     Dim path As String = reqBuffer.Substring(methodLen, endPos)
  125.                     Dim pathTemp As String = System.Web.HttpUtility.UrlDecode(path)
  126.                     pathTemp = pathTemp.Replace("/", "\\")
  127.  
  128.                     RaiseEvent SrvLog(path)
  129.  
  130.                     If File.Exists(Me.dirloc + pathTemp) Then
  131.                         Dim fs As New FileStream(Me.dirloc + pathTemp, FileMode.Open, FileAccess.Read)
  132.                         Dim br As New BinaryReader(fs)
  133.                         Dim bytes(fs.Length) As Byte
  134.                         Dim read As Integer
  135.  
  136.                         contentType = selectMimeType(path)
  137.  
  138.                         read = br.Read(bytes, 0, bytes.Length)
  139.  
  140.                         br.Close()
  141.                         fs.Close()
  142.  
  143.                         SendHeader(bytes.Length, iSocket, contentType)
  144.                         SendToBrowser(bytes, iSocket)
  145.                     Else
  146.                         If path.IndexOf("?") > -1 Then
  147.                             Dim pathAndArgs() As String = path.Split({"?"c}, 2)
  148.                             Command(pathAndArgs(0), pathAndArgs(1), headers, "GET", iSocket, contentType)
  149.                         Else
  150.                             Command(path, "", headers, "GET", iSocket, contentType)
  151.                         End If
  152.  
  153.                     End If
  154.                 ElseIf reqBuffer.Substring(0, 4) = "POST" Then
  155.                     Dim methodLen As Integer = "POST ".Length
  156.                     Dim endPos As Integer = reqBuffer.IndexOf(" HTTP") - methodLen
  157.                     If reqBuffer.IndexOf("?") > -1 Then
  158.                         endPos = reqBuffer.IndexOf("?") - methodLen
  159.                     End If
  160.                     Dim path As String = reqBuffer.Substring(methodLen, endPos)
  161.                     Dim contentLen As Integer = Integer.Parse(headers.Item("Content-Length"))
  162.  
  163.                     RaiseEvent SrvLog(path)
  164.  
  165.                     Command(path, ParseRequest(reqBuffer, contentLen), headers, "POST", iSocket, contentType)
  166.                 Else
  167.                     iSocket.Close()
  168.                     Return
  169.                 End If
  170.  
  171.                 iSocket.Close()
  172.             End If
  173.         Loop
  174.     End Sub
  175.  
  176.     ' Command Sub
  177.     Public Overridable Sub Command(ByVal path As String, ByVal args As String, _
  178.                                    ByVal headers As Hashtable, ByVal method As String, _
  179.                                    ByRef iSocket As Socket, ByVal contentType As String)
  180.         Dim x As String = "<p>" + path + "</p><p>" + args + "</p>"
  181.  
  182.         SendHeader(x.Length, iSocket, contentType)
  183.         SendToBrowser(Encoding.UTF8.GetBytes(x), iSocket)
  184.     End Sub
  185.  
  186.     ' Gets the MIME type based on file extension
  187.     Private Function selectMimeType(ByVal file As String) As String
  188.         Dim retval As String = "text/plain"
  189.         Dim parts() As String = file.Split(".")
  190.         Dim ext As String = parts(parts.Length - 1).ToLower
  191.  
  192.         Select Case ext
  193.             Case "jpg"
  194.                 retval = "image/jpeg"
  195.             Case "gif"
  196.                 retval = "image/gif"
  197.             Case "png"
  198.                 retval = "image/png"
  199.             Case "swf"
  200.                 retval = "application/x-shockwave-flash"
  201.             Case "js"
  202.                 retval = "application/x-javascript"
  203.             Case "xml"
  204.                 retval = "application/xml"
  205.             Case "rss"
  206.                 retval = "application/xml"
  207.             Case "opml"
  208.                 retval = "application/xml"
  209.             Case "pdf"
  210.                 retval = "application/pdf"
  211.             Case "htm"
  212.                 retval = "text/html"
  213.             Case "html"
  214.                 retval = "text/html"
  215.             Case "txt"
  216.                 retval = "text/plain"
  217.         End Select
  218.  
  219.         Return retval
  220.     End Function
  221.  
  222.     ' Parses the request header
  223.     Private Function ParseHeader(ByVal header As String) As Hashtable
  224.         header = header.Replace(vbLf, "")
  225.  
  226.         Dim vals As New Hashtable
  227.         Dim headers() As String = header.Split(vbCr)
  228.         Dim cnt As Integer = 0
  229.  
  230.         For Each line As String In headers
  231.             If cnt > 0 Then
  232.                 If line.Length > 0 Then
  233.                     Dim parts() As String = line.Split({": "}, 2, StringSplitOptions.None)
  234.                     vals.Add(parts(0), parts(1))
  235.                 Else
  236.                     Exit For
  237.                 End If
  238.             End If
  239.  
  240.             cnt = cnt + 1
  241.         Next
  242.  
  243.         Return vals
  244.     End Function
  245.  
  246.     ' Parses the header and pulls out the data
  247.     Private Function ParseRequest(ByVal header As String, ByVal length As Integer) As String
  248.         header = header.Replace(vbLf, "")
  249.  
  250.         Dim data As String = ""
  251.         Dim headers() As String = header.Split(vbCr)
  252.         Dim keeploop As Integer = 0
  253.  
  254.         For Each line As String In headers
  255.             If keeploop = 0 Then
  256.                 If line.Length = 0 Then
  257.                     keeploop = 1
  258.                 End If
  259.             ElseIf keeploop = 1 Then
  260.                 data = line.Substring(0, length)
  261.                 keeploop = -1
  262.             ElseIf keeploop = -1 Then
  263.                 Exit For
  264.             End If
  265.         Next
  266.  
  267.         Return data
  268.     End Function
  269.  
  270.     ' Starts the server running
  271.     Public Sub StartServer()
  272.         Try
  273.             iListener = New TcpListener(IPAddress.Any, iPort)
  274.             iListener.Start()
  275.  
  276.             ' Allows for the creation of multiple threads
  277.             Dim th As New Thread(AddressOf StartListen)
  278.             th.Start()
  279.  
  280.         Catch ex As Exception
  281.             RaiseEvent SrvError(ex.Message, ex.StackTrace)
  282.         End Try
  283.     End Sub
  284.  
  285.     ' Stops the server thread
  286.     Public Sub StopServer()
  287.         Me.goon = False
  288.     End Sub
  289. End Class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement