'------------------------------------------------------------------------------ ' webserver11.bas ' a simple webserver adapted from the example by ' MCS Electronics ' You can access the server via http://192.168.0.8 ' There are pages index.htm, post.htm and redirect.htm ' any other name will return the not found page ' The post page allows you to display a message on the LCD display ' and shows the IP address of the person entering the message, ' this meassage is echoed to the web page. '------------------------------------------------------------------------------ $regfile = "m162def.dat" $crystal = 4000000 $baud = 19200 'used constants Const Sock_stream = $01 ' Tcp Const Sock_dgram = $02 ' Udp Const Sock_ipl_raw = $03 ' Ip Layer Raw Sock Const Sock_macl_raw = $04 ' Mac Layer Raw Sock Const Sel_control = 0 ' Confirm Socket Status Const Sel_send = 1 ' Confirm Tx Free Buffer Size Const Sel_recv = 2 ' Confirm Rx Data Size 'socket status Const Sock_closed = $00 ' Status Of Connection Closed Const Sock_arp = $01 ' Status Of Arp Const Sock_listen = $02 ' Status Of Waiting For Tcp Connection Setup Const Sock_synsent = $03 ' Status Of Setting Up Tcp Connection Const Sock_synsent_ack = $04 ' Status Of Setting Up Tcp Connection Const Sock_synrecv = $05 ' Status Of Setting Up Tcp Connection Const Sock_established = $06 ' Status Of Tcp Connection Established Const Sock_close_wait = $07 ' Status Of Closing Tcp Connection Const Sock_last_ack = $08 ' Status Of Closing Tcp Connection Const Sock_fin_wait1 = $09 ' Status Of Closing Tcp Connection Const Sock_fin_wait2 = $0a ' Status Of Closing Tcp Connection Const Sock_closing = $0b ' Status Of Closing Tcp Connection Const Sock_time_wait = $0c ' Status Of Closing Tcp Connection Const Sock_reset = $0d ' Status Of Closing Tcp Connection Const Sock_init = $0e ' Status Of Socket Initialization Const Sock_udp = $0f ' Status Of Udp Const Sock_raw = $10 ' Status of IP RAW 'in debug mode to send some info to the terminal Const Debug = 1 Const Authenticate = 0 ' use 1 to use authentication $lib "tcpip.lbx" $eepleave ' do not delete the EEP file since we generated it with the converter tool Config Watchdog = 2048 Config Lcd = 16 * 2 Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5 Cursor Blink #if Debug Print "init W3100A" #endif Enable Interrupts 'Start Watchdog Config Tcpip = Int0 , Mac = 12.128.12.34.56.78 , Ip = 192.168.0.8 , Submask = 255.255.255.0 , Gateway = 192.168.0.1 , Localport = 80 , Tx = $55 , Rx = $55 'dim used variables Dim S As String * 160 At &H200 , Shtml As String * 15 , Sheader As String * 30 , L As String * 16 , Ip As String * 16 Dim S2 As String * 160 , V As String * 2 , C As String * 1 Dim Buf(160) As Byte At &H200 Overlay ' this is the same data as S but we can treat it as an array now Dim Tempw As Word Dim I As Byte , Bcmd As Byte , P1 As Byte , P2 As Byte , P3 As Byte , Size As Word , J As Byte , K As Byte , Found As Byte Dim Bcontent As Byte Dim Bauth As Byte , Ipcon As Long ' for optional authentication 'note that this webserver demo uses just 1 connection. It can easy be changed to use all 4 connections 'also note that the connection is terminated by the webserver after the data has been sent. 'this is done so more clients can be served, it is not acording to the RFC 'Also included is some simple authentiation. It works by determining the client IP number 'When it differs from the current connection, the user/pwd will be asked. It is decoded with the base64dec() routine 'Usualy we start with creating a connection. This is also tru for this demo. 'Because the socketstat()function will find out that the connection is closed, it will take then ' Case Sock_closed part of the select case statement, and so will create a new socket. 'After that it will listen to the connection for a client. Cls I = 0 ' we use just 1 connection with number 0 Do Tempw = Socketstat(i , 0) ' get status Select Case Tempw Case Sock_established #if Debug Print "sock_est" ' delete it when it sends to much data to the terminal #endif If Getdstip(i) <> Ipcon Then ' the current client is different then the number stored Bauth = 0 ' reset authentication bit End If Tempw = Socketstat(i , Sel_recv) ' get received bytes #if Debug Print "receive buffer size : " ; Tempw #endif If Tempw > 0 Then ' if there is something received Bcmd = 0 Do Tempw = Tcpread(i , S) ' read a line If Left(s , 3) = "GET" Then Bcmd = 1 ' GET /index.htm HTTP/1.1 Gosub Page Elseif Left(s , 4) = "HEAD" Then Bcmd = 2 Gosub Page Elseif Left(s , 4) = "POST" Then Bcmd = 3 Elseif Left(s , 15) = "Content-Length:" Then ' for post S = Mid(s , 16) : Bcontent = Val(s) Elseif Left(s , 20) = "Authorization: Basic" Then ' user and pwd specified Print S S = Mid(s , 22) 'Authorization: Basic bWFyazptYXJr Print "{" ; S ; "}" ' this is the user/pwd part the browser is sending #if Debug Print "Decoded user:pwd " ; Base64dec(s) #endif If Base64dec(s) = "mark:mark" Then 'pwd ok Bauth = 1 ' verified Ipcon = Getdstip(i) ' store current ip number End If Else #if Debug Print S ' print data the client browser sent #endif End If Reset Watchdog Loop Until S = "" ' wait until we get an empty line #if Authenticate If Bauth = 0 Then Tempw = Tcpwrite(i , "HTTP/1.0 401 OK{013}{010}") ' ask for user password Tempw = Tcpwrite(i , "WWW-Authenticate: Basic realm={034}ServerID{034}{013}{010}") Goto Continue Else Tempw = Tcpwrite(i , "HTTP/1.0 200 OK{013}{010}") End If #else ' no authentication used 'Tempw = Tcpwrite(i , "HTTP/1.0 200 OK{013}{010}") 'send ok #endif If Bcmd = 3 Then #if Debug Print "Posted data" #endif Tempw = Tcpread(i , Buf(1) , Bcontent) ' read data Bcontent = Bcontent + 1 Buf(bcontent) = 0 ' put string terminator at end of data so we can handle it as a string Print S P1 = Instr(s , "c1+=") ' find first = P1 = P1 + 4 ' 4 P2 = Instr(s , "&b1") ' find first & If P2 > 0 Then P2 = P2 - P1 Else P2 = Len(s) If P1 = 5 And P2 < 48 Then S = Mid(s , P1 , P2) Else Goto Nogoodpost End If While 0 <> Instr(s , "+") 'replace all "+"s with spaces P1 = Instr(s , "+") P2 = Len(s) - P1 P1 = P1 - 1 S = Left(s , P1) + " " + Right(s , P2) Wend J = 1 Do P1 = J If Mid(s , J , 1) = "%" Then P2 = Len(s) - P1 P2 = P2 - 2 P3 = P1 + 1 P1 = P1 - 1 V = Mid(s , P3 , 2) P3 = Hexval(v) If P1 > 0 Then S = Left(s , P1) + Chr(p3) + Right(s , P2) Else S = Chr(p3) + Right(s , P2) End If End If P1 = J If Buf(j) < 32 Or Buf(j) > 127 Then P2 = Len(s) - P1 P1 = P1 - 1 If P1 > 0 Then S = Left(s , P1) + " " + Right(s , P2) Else S = " " + Right(s , P2) End If End If J = J + 1 Loop Until J > Len(s) L = Left(s , 16) #if Debug Print S #endif Cls Upperline Lcd Left(s , 16) Lowerline Ipcon = Getdstip(i) ' store current ip number Ip = "" For J = 1 To 3 K = Ipcon And 255 Ip = Ip + Str(k) + "." Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Shift Ipcon , Right Next J Ip = Ip + Str(ipcon) Lcd Ip Nogoodpost: Shtml = "/post.htm" ' redirect to index End If Gosub Stuur ' GET or HEAD or POST feedback so send it Continue: Print "closing socket" Closesocket I ' close the connection Print "done" End If Case Sock_close_wait #if Debug Print "CLOSE_WAIT" #endif Closesocket I ' we need to close Case Sock_closed #if Debug Print "CLOSED" #endif I = Getsocket(0 , Sock_stream , 80 , 0) ' get a new socket Socketlisten I ' listen #if Debug Print "Listening on socket : " ; I #endif End Select Reset Watchdog Loop End 'get html page out of data Page: P1 = Instr(s , " ") ' find first space P1 = P1 + 1 ' 4 P2 = Instr(p1 , S , " ") ' find second space P2 = P2 - P1 If P2 > 15 Then P2 = 15 Shtml = Mid(s , P1 , P2) ' dont use too long page names Shtml = Lcase(shtml) ' make lower case #if Debug Print "HTML page:" ; Shtml #endif Return 'send data Stuur: Dim Woffset As Word , Bcontenttype As Byte , Wsize As Word , Bgenerate As Bit , Ihitcounter As Integer Bgenerate = 0 Found = 1 ' by default Select Case Shtml Case "/index.htm" Bcontenttype = 0 : Bgenerate = 1 Case "/" Bcontenttype = 0 : Bgenerate = 1 Case "/post.htm" Bcontenttype = 0 : Bgenerate = 1 Case "/post2.htm" : Wsize = $118 Bcontenttype = 0 : Woffset = 0 Case "/notfound.htm" : Wsize = 131 Bcontenttype = 0 : Woffset = $118 Case Else ' not found Bcontenttype = 0 : Woffset = $118 : Wsize = 131 : Found = 0 End Select If Found = 1 Then Tempw = Tcpwrite(i , "HTTP/1.0 200 OK{013}{010}") 'send ok Else Tempw = Tcpwrite(i , "HTTP/1.0 404 Not Found{013}{010}") 'send not found End If Select Case Bcontenttype Case 0: ' text Tempw = Tcpwrite(i , "Content-Type: text/html{013}{010}") Case 1: ' gif End Select If Bgenerate = 0 Then ' data from eeprom S = "Content-Length: " + Str(wsize) + "{013}{010}" Tempw = Tcpwritestr(i , S , 255) ' add additional CR and LF Tempw = Tcpwrite(i , Eeprom , Woffset , Wsize) ' write data Else ' we generate the data If Shtml = "/index.htm" Or Shtml = "/" Then Incr Ihitcounter 'increase hitcounter S = "Easy TcpIp Page

Webserver on an ATmega162

Hits :" + Str(ihitcounter) + "

Hardware and compiler from MCS Electronics

Send a message to the display on the webserver

" Else S = "LCD control

Message to appear on the LCD display

" S2 = "

Present message: " + L + ", from " + Ip + "" End If Wsize = Len(s) + Len(s2) ' size of body Sheader = "Content-Length: " + Str(wsize) + "{013}{010}" Tempw = Tcpwritestr(i , Sheader , 255) ' add additional CR and LF Wsize = Len(s) Tempw = Tcpwrite(i , S , Wsize) ' send body Wsize = Len(s2) Tempw = Tcpwrite(i , S2 , Wsize) End If Return