1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-08-14 02:26:10 +00:00

Very preliminary HTTP server

This commit is contained in:
dschmenk
2015-02-09 19:32:54 -08:00
parent 175898913c
commit 9686ef8ca6
6 changed files with 687 additions and 125 deletions

View File

@@ -7,9 +7,24 @@ import cmdsys
predef heapmark, heapallocalign, heapalloc, heaprelease predef heapmark, heapallocalign, heapalloc, heaprelease
byte MACHID byte MACHID
end end
//
// Net object
//
import inet import inet
predef swab, sendUDP, openUDP, closeUDP, serviceIP word iNet
predef setInterfaceIP, getInterfaceHA end
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
end end
// //
// Needed to init subnet // Needed to init subnet
@@ -178,7 +193,7 @@ def recvDHCP(remip, remport, pkt, len, param)
memcpy(@optsDHCP.5, @pkt->dhcp_yourip, 4) memcpy(@optsDHCP.5, @pkt->dhcp_yourip, 4)
memcpy(@optsDHCP.11, @pkt->dhcp_serverip, 4) memcpy(@optsDHCP.11, @pkt->dhcp_serverip, 4)
memcpy(@DHCP.dhcp_serverip, @pkt->dhcp_serverip, 4) memcpy(@DHCP.dhcp_serverip, @pkt->dhcp_serverip, 4)
sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, t_dhcp) iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, t_dhcp)
break break
is DHCP_ACK is DHCP_ACK
stateDHCP = DHCP_ACK stateDHCP = DHCP_ACK
@@ -204,15 +219,15 @@ end
// //
// Get the local hardware address into the DHCP packet // Get the local hardware address into the DHCP packet
// //
getInterfaceHA(@DHCP.dhcp_clientha) iNet:getInterfaceHA(@DHCP.dhcp_clientha)
// //
// Clear our local IP address // Clear our local IP address
// //
setInterfaceIP(@zeros,@ones, @zeros) iNet:setInterfaceIP(@zeros,@ones, @zeros)
// //
// Prepare to receive DHCP packets from a server // Prepare to receive DHCP packets from a server
// //
portDHCP = openUDP(DHCP_CLIENT_PORT, @recvDHCP, 0) portDHCP = iNet:openUDP(DHCP_CLIENT_PORT, @recvDHCP, 0)
// //
// Service IP // Service IP
// //
@@ -220,24 +235,17 @@ while retry < 3 and stateDHCP <> DHCP_ACK
// //
// Broadcast DHCP DISCOVER message // Broadcast DHCP DISCOVER message
// //
sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, t_dhcp) iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, t_dhcp)
for timeout = 1 to 1000 for timeout = 1 to 1000
serviceIP iNet:serviceIP()
if stateDHCP == DHCP_ACK if stateDHCP == DHCP_ACK
break break
fin fin
next next
retry = retry + 1 retry = retry + 1
loop loop
closeUDP(portDHCP) iNet:closeUDP(portDHCP)
setInterfaceIP(@localip, @localnet, @localgw) iNet:setInterfaceIP(@localip, @localnet, @localgw)
puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln
//
// Service IP
//
repeat
serviceIP
until ^$C000 > 127
^$C010
done done

View File

@@ -4,16 +4,35 @@ import cmdsys
predef memset, memcpy, modaddr, modexec predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID byte MACHID
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
end end
// //
// Module don't free memory // Net object
// //
const modkeep = $2000 import inet
const modinitkeep = $4000 word iNet
end
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
end
// //
// Predefine service routine // Predefine service routine
// //
predef serviceIP predef etherServiceIP
// //
// Segment list element // Segment list element
// //
@@ -183,7 +202,7 @@ end
// //
// Swap bytes in word // Swap bytes in word
// //
export asm swab asm swab
LDA ESTKL,X LDA ESTKL,X
LDY ESTKH,X LDY ESTKH,X
STA ESTKH,X STA ESTKH,X
@@ -194,7 +213,7 @@ end
// 1'S COMPLIMENT SUM BE format // 1'S COMPLIMENT SUM BE format
// sum1(PREVSUM, BUF, LEN) // sum1(PREVSUM, BUF, LEN)
// //
export asm sum1 asm sum1
LDY #$00 LDY #$00
LDA ESTKL+1,X LDA ESTKL+1,X
STA SRCL STA SRCL
@@ -242,7 +261,7 @@ end
// //
// Send IP datagram // Send IP datagram
// //
export def sendIP(ipdst, proto, seglist, size) def etherSendIP(ipdst, proto, seglist, size)
byte[t_iphdr] hdr byte[t_iphdr] hdr
byte retry byte retry
word timeout word timeout
@@ -275,7 +294,7 @@ export def sendIP(ipdst, proto, seglist, size)
setFrameLen(t_earp) setFrameLen(t_earp)
writeFrame(@eFrame, t_earp) writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0 for timeout = 1000 downto 0
serviceIP etherServiceIP
if remoteha:0 | remoteha:2 | remoteha:4 if remoteha:0 | remoteha:2 | remoteha:4
break break
fin fin
@@ -312,7 +331,7 @@ end
// //
// Send UDP datagram // Send UDP datagram
// //
export def sendUDP(port, ipdst, portdst, data, len) def etherSendUDP(port, ipdst, portdst, data, len)
word[8] seglist // list of data and header segments word[8] seglist // list of data and header segments
byte[t_udphdr] hdr byte[t_udphdr] hdr
@@ -324,12 +343,12 @@ export def sendUDP(port, ipdst, portdst, data, len)
seglist:0:seg_len = t_udphdr seglist:0:seg_len = t_udphdr
seglist:4:seg_buf = data seglist:4:seg_buf = data
seglist:4:seg_len = len seglist:4:seg_len = len
return sendIP(ipdst, IP_PROTO_UDP, @seglist, t_udphdr + len) return etherSendIP(ipdst, IP_PROTO_UDP, @seglist, t_udphdr + len)
end end
// //
// Notify on UDP datagram received // Notify on UDP datagram received
// //
export def openUDP(localport, callback, param) def etherOpenUDP(localport, callback, param)
word port word port
byte i byte i
@@ -363,7 +382,7 @@ end
// //
// Clear notify on UDP port // Clear notify on UDP port
// //
export def closeUDP(port) def etherCloseUDP(port)
word port word port
byte i byte i
@@ -382,9 +401,29 @@ export def closeUDP(port)
return -1 return -1
end end
// //
// Open TCP socket in SERVER mode
//
def etherListenTCP(lclport, callback, param)
end
//
// Open TCP socket in CLIENT mode
//
def etherConnectTCP(remip, remport, lclport, callback, param)
end
//
// Write to TCP socket
//
def etherSendTCP(wiz, data, len)
end
//
// Close TCP socket
//
def etherCloseTCP(wiz)
end
//
// Service incoming packets // Service incoming packets
// //
export def serviceIP def etherServiceIP
word rxsize, rxpacket, rxptr word rxsize, rxpacket, rxptr
word iphdr, opt, optlen, port, lclport, remport word iphdr, opt, optlen, port, lclport, remport
byte i, echolen byte i, echolen
@@ -470,7 +509,7 @@ export def serviceIP
echo_reply:icmp_chksm = 0 echo_reply:icmp_chksm = 0
seglist:seg_buf = @echo_reply seglist:seg_buf = @echo_reply
seglist:seg_len = echolen seglist:seg_len = echolen
sendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen) etherSendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
fin fin
if hookICMP if hookICMP
hookICMP(@iphdr=>ip_src, rxptr, rxsize) hookICMP(@iphdr=>ip_src, rxptr, rxsize)
@@ -516,7 +555,7 @@ end
// //
// Set the local IP addresses // Set the local IP addresses
// //
export def setInterfaceIP(newIP, newSubnet, newGateway) def setEtherIP(newIP, newSubnet, newGateway)
if newIP; memcpy(@localip, newIP, IP4ADR_SIZE); fin if newIP; memcpy(@localip, newIP, IP4ADR_SIZE); fin
if newSubnet; memcpy(@subnet, newSubnet, IP4ADR_SIZE); fin if newSubnet; memcpy(@subnet, newSubnet, IP4ADR_SIZE); fin
if newGateway; memcpy(@gateway, newGateway, IP4ADR_SIZE); fin if newGateway; memcpy(@gateway, newGateway, IP4ADR_SIZE); fin
@@ -524,9 +563,22 @@ end
// //
// Get the interface hardware address // Get the interface hardware address
// //
export def getInterfaceHA(ha) def getEtherHA(ha)
if ha; memcpy(ha, @myMAC, MAC_SIZE); fin if ha; memcpy(ha, @myMAC, MAC_SIZE); fin
return MAC_SIZE return MAC_SIZE
end end
//
// Fill in Net class
//
iNet:serviceIP = @etherServiceIP
iNet:openUDP = @etherOpenUDP
iNet:sendUDP = @etherSendUDP
iNet:closeUDP = @etherCloseUDP
iNet:listenTCP = @etherListenTCP
iNet:connectTCP = @etherConnectTCP
iNet:sendTCP = @etherSendTCP
iNet:closeTCP = @etherCloseTCP
iNet:setInterfaceIP = @setEtherIP
iNet:getInterfaceHA = @getEtherHA
done done

View File

@@ -5,6 +5,31 @@ import cmdsys
byte MACHID byte MACHID
end end
// //
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
//
// Net object
//
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
end
//
// External interface to net class. Must be first.
//
export byte[t_inet] iNet
//
// List of loadable network device drivers // List of loadable network device drivers
// //
byte netDrivers = "WIZNET" byte netDrivers = "WIZNET"
@@ -15,22 +40,28 @@ word driver = @netDrivers
// DHCP module to load // DHCP module to load
// //
byte dhcp = "DHCP" byte dhcp = "DHCP"
//
// Look for net hardware export def iNetInit
// //
while ^driver // Look for net hardware
puts(driver);putln //
if modexec(driver) >= 0 while ^driver
break //puts(driver);putln
if modexec(driver) >= 0
break
fin
driver = driver + ^driver + 1
loop
if !^driver
return 0
fin fin
driver = driver + ^driver + 1 //
loop // Get an IP address
if !^driver //
return -1 modexec(@dhcp)
fin return @iNet
// end
// Get an IP address
// iNet:initIP = @iNetInit
modexec(@dhcp)
done done

View File

@@ -12,6 +12,25 @@ import cmdsys
byte MACHID byte MACHID
end end
// //
// Net object
//
import inet
word iNet
end
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
end
//
// Module don't free memory // Module don't free memory
// //
const modkeep = $2000 const modkeep = $2000
@@ -96,7 +115,7 @@ byte[4] gateway
// //
// Predefine service routine // Predefine service routine
// //
predef serviceIP predef wizServiceIP
// //
// Segment list element // Segment list element
// //
@@ -190,18 +209,35 @@ end
// //
const MAX_WIZ_CHANNELS = 4 const MAX_WIZ_CHANNELS = 4
// //
// Channel protocols
//
const WIZ_PROTO_CLOSED = 0
const WIZ_PROTO_TCP = 1
const WIZ_PROTO_UDP = 2
const WIZ_PROTO_IP = 3
const WIZ_PROTO_RAW = 4
//
// State transistions
//
const TCP_STATE_CLOSED = 0
const TCP_STATE_CLOSING = 1
const TCP_STATE_LISTEN = 2
const TCP_STATE_CONNECT = 3
const TCP_STATE_OPEN = 4
//
// HW channels // HW channels
// //
struc t_channel struc t_channel
byte channel_proto byte channel_proto
word channel_regs byte channel_state
word channel_txmem word channel_regs
word channel_rxmem word channel_txmem
word channel_lclport word channel_rxmem
word channel_remport word channel_lclport
word channel_remip word channel_remport
word channel_recv_func byte[4] channel_remip
word channel_recv_parm word channel_recv_func
word channel_recv_parm
end end
byte[t_channel * MAX_WIZ_CHANNELS] wizChannel byte[t_channel * MAX_WIZ_CHANNELS] wizChannel
// //
@@ -217,7 +253,7 @@ end
// //
// Swap bytes in word // Swap bytes in word
// //
export asm swab asm swab
LDA ESTKL,X LDA ESTKL,X
LDY ESTKH,X LDY ESTKH,X
STA ESTKH,X STA ESTKH,X
@@ -225,55 +261,6 @@ export asm swab
RTS RTS
end end
// //
// 1'S COMPLIMENT SUM BE format
// sum1(PREVSUM, BUF, LEN)
//
export asm sum1
LDY #$00
LDA ESTKL+1,X
STA SRCL
LDA ESTKH+1,X
STA SRCH
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
LDA ESTKL,X
ROR
ADC #$00
STA ESTKL,X
BEQ +
INC ESTKH,X
BCC CHKLP
INC ESTKH,X
CLC
CHKLP LDA (SRC),Y
PHA
INY
BNE +
INC SRCH
+ LDA (SRC),Y
ADC ESTKH+2,X
STA ESTKH+2,X
PLA
ADC ESTKL+2,X
STA ESTKL+2,X
INY
BNE +
INC SRCH
+ DEC ESTKL,X
BNE CHKLP
DEC ESTKH,X
BNE CHKLP
- LDA #$00
ADC ESTKH+2,X
STA ESTKH+2,X
LDA #$00
ADC ESTKL+2,X
STA ESTKL+2,X
BCS -
INX
INX
RTS
end
//
// Wiznet I/O functions // Wiznet I/O functions
// //
// POKE WORD TO I/O SPACE // POKE WORD TO I/O SPACE
@@ -440,6 +427,7 @@ def peekregw(reg)
_pokeiow(reg) _pokeiow(reg)
dataw.1 = _peekio() dataw.1 = _peekio()
_pokeiow(reg + 1)
dataw.0 = _peekio() dataw.0 = _peekio()
return dataw return dataw
end end
@@ -475,7 +463,7 @@ end
// //
// Send UDP datagram // Send UDP datagram
// //
export def sendUDP(wiz, ipdst, portdst, data, len) def wizSendUDP(wiz, ipdst, portdst, data, len)
word wizregs, wizdata, txrr, txwr, splitlen word wizregs, wizdata, txrr, txwr, splitlen
wizregs = wiz=>channel_regs wizregs = wiz=>channel_regs
@@ -512,7 +500,7 @@ end
// //
// Open UDP channel and set datagram received callback // Open UDP channel and set datagram received callback
// //
export def openUDP(localport, callback, param) def wizOpenUDP(localport, callback, param)
word wiz word wiz
byte i byte i
@@ -520,6 +508,7 @@ export def openUDP(localport, callback, param)
// //
// Look for an existing notification on localport // Look for an existing notification on localport
// //
putc('O')
wiz = @wizChannel wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS for i = 1 to MAX_WIZ_CHANNELS
if wiz->channel_proto == IP_PROTO_UDP and wiz=>channel_lclport == localport if wiz->channel_proto == IP_PROTO_UDP and wiz=>channel_lclport == localport
@@ -542,10 +531,11 @@ export def openUDP(localport, callback, param)
return 0 return 0
fin fin
fin fin
putc('0' + i);putln
// //
// Fill in this channel and open it // Fill in this channel and open it
// //
wiz->channel_proto = IP_PROTO_UDP wiz->channel_proto = WIZ_PROTO_UDP
wiz=>channel_lclport = localport wiz=>channel_lclport = localport
wiz=>channel_recv_func = callback wiz=>channel_recv_func = callback
wiz=>channel_recv_parm = param wiz=>channel_recv_parm = param
@@ -557,14 +547,170 @@ end
// //
// Close UDP port // Close UDP port
// //
export def closeUDP(wiz) def wizCloseUDP(wiz)
if isuge(wiz, wizChannel) and isult(wiz, wizChannel + MAX_WIZ_CHANNELS * t_channel) putc('S')
if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel)
// //
// Clear notiications on this port // Clear notiications on this port
// //
if wiz->channel_proto == IP_PROTO_UDP if wiz->channel_proto == WIZ_PROTO_UDP
wiz->channel_proto = 0 putc('1' + ((wiz=>channel_regs - WIZ_SREGS) >> 8));putln
pokereg(wiz=>channel_regs + WIZ_SnCR, $00) // CLOSE wiz->channel_proto = WIZ_PROTO_CLOSED
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
return 0
fin
fin
putc('!');putln
//
// Invalid port
//
return -1
end
//
// Open TCP socket in SERVER mode
//
def wizListenTCP(lclport, callback, param)
word wiz
byte i
//
// Look for an existing notification on localport
//
putc('L')
wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS
if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_LISTEN and wiz=>channel_lclport == lclport
break
fin
wiz = wiz + t_channel
next
if i > MAX_WIZ_CHANNELS
//
// Add notification on localport if room
//
wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS
if !wiz->channel_proto
break
fin
wiz = wiz + t_channel
next
if i > MAX_WIZ_CHANNELS
return 0
fin
fin
putc('0' + i);putln
//
// Fill in this channel and open it
//
wiz->channel_proto = WIZ_PROTO_TCP
wiz->channel_state = TCP_STATE_LISTEN
wiz=>channel_remip:0 = 0
wiz=>channel_remip:2 = 0
wiz=>channel_remport = 0
wiz=>channel_lclport = lclport
wiz=>channel_recv_func = callback
wiz=>channel_recv_parm = param
pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport)
pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol
pokereg(wiz=>channel_regs + WIZ_SnCR, $02) // LISTEN
return wiz
end
//
// Open TCP socket in CLIENT mode
//
def wizConnectTCP(remip, remport, lclport, callback, param)
word wiz
byte i
//
// Look for an existing notification on localport
//
wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS
if wiz->channel_proto == WIZ_PROTO_TCP and wiz->channel_state == TCP_STATE_CONNECT and wiz=>channel_lclport == lclport
break
fin
wiz = wiz + t_channel
next
if i > MAX_WIZ_CHANNELS
//
// Add notification on localport if room
//
wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS
if !wiz->channel_proto
break
fin
wiz = wiz + t_channel
next
if i > MAX_WIZ_CHANNELS
return 0
fin
fin
//
// Fill in this channel and open it
//
wiz->channel_proto = WIZ_PROTO_TCP
wiz->channel_state = TCP_STATE_CONNECT
wiz=>channel_remip:0 = remip=>0
wiz=>channel_remip:2 = remip=>2
wiz=>channel_remport = remport
wiz=>channel_lclport = lclport
wiz=>channel_recv_func = callback
wiz=>channel_recv_parm = param
pokeregs(wiz=>channel_regs + WIZ_SnDIPR, remip, IP4ADR_SIZE)
pokeregw(wiz=>channel_regs + WIZ_SnDPORT, remport)
pokeregw(wiz=>channel_regs + WIZ_SnPORT, lclport)
pokereg(wiz=>channel_regs + WIZ_SnMR, $01) // TCP protocol
pokereg(wiz=>channel_regs + WIZ_SnCR, $04) // CONNECT
return wiz
end
//
// Write to TCP socket
//
def wizSendTCP(wiz, data, len)
word wizregs, wizdata, txrr, txwr, splitlen
if wiz->channel_state <> TCP_STATE_OPEN; return -1; fin
wizregs = wiz=>channel_regs
wizdata = wiz=>channel_txmem
//
// Wait for Tx room
//
repeat
txrr = peekregw(wizregs + WIZ_SnTXRD)
txwr = peekregw(wizregs + WIZ_SnTXWR)
until txrr == txwr
//
// Calc new write ptr, check for split
//
txwr = txrr + len
if txwr >= WIZ_TXSIZE
splitlen = WIZ_TXSIZE - txrr
pokeregs(wizdata + txrr, data, splitlen)
pokeregs(wizdata, data + splitlen, len - splitlen)
else
pokeregs(wizdata + txrr, data, len)
fin
pokeregw(wizregs + WIZ_SnTXWR, txwr)
pokereg(wizregs + WIZ_SnCR, $20) // SEND
end
//
// Close TCP socket
//
def wizCloseTCP(wiz)
if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel)
//
// Clear notiications on this port
//
if wiz->channel_proto == WIZ_PROTO_TCP and (wiz->channel_state == TCP_STATE_OPEN or wiz->channel_state == TCP_STATE_CLOSING)
wiz->channel_state = TCP_STATE_CLOSING
pokereg(wiz=>channel_regs + WIZ_SnCR, $08) // DISCON
repeat
wizServiceIP()
until wiz->channel_state == TCP_STATE_CLOSED
wiz->channel_proto = WIZ_PROTO_CLOSED
return 0 return 0
fin fin
fin fin
@@ -576,13 +722,13 @@ end
// //
// Service incoming packets // Service incoming packets
// //
export def serviceIP def wizServiceIP
word wiz, wizregs, wizdata, rxlen, rxrr, rxwr, rxpkt, splitlen word wiz, wizregs, wizdata, rxlen, rxrr, rxwr, rxpkt, splitlen
byte ir, i, sir byte ir, i, sir
ir = peekreg(WIZ_IR) ir = peekreg(WIZ_IR)
if ir and ir <> $FF // Ignore spurious read of IR if ir and ir <> $FF // Ignore spurious read of IR
//putc('I');putb(ir) putc('I');putb(ir)
wiz = @wizChannel wiz = @wizChannel
for i = 0 to 3 for i = 0 to 3
when ir & (1 << i) when ir & (1 << i)
@@ -594,7 +740,86 @@ export def serviceIP
wizdata = wiz=>channel_rxmem wizdata = wiz=>channel_rxmem
sir = peekreg(wizregs + WIZ_SnIR) sir = peekreg(wizregs + WIZ_SnIR)
when wiz->channel_proto when wiz->channel_proto
is IP_PROTO_UDP is WIZ_PROTO_TCP
if sir & $01
putc('C')
//
// Connect TCP socket
//
when wiz->channel_state
is TCP_STATE_LISTEN
peekregs(wiz=>channel_regs + WIZ_SnDIPR, @wiz=>channel_remip, IP4ADR_SIZE)
wiz=>channel_remport = peekregw(wiz=>channel_regs + WIZ_SnDPORT)
is TCP_STATE_CONNECT
wiz->channel_state = TCP_STATE_OPEN
break
otherwise
putc('?')
wend
fin
if sir & $04
putc('R')
//
// Receive TCP packet
//
rxlen = peekregw(wizregs + WIZ_SnRSR)
rxrr = peekregw(wizregs + WIZ_SnRXRD)
rxwr = rxrr + rxlen
rxpkt = heapalloc(rxlen)
if rxwr >= WIZ_RXSIZE
putc('!')
splitlen = WIZ_RXSIZE - rxrr
peekregs(wizdata + rxrr, rxpkt, splitlen)
peekregs(wizdata, rxpkt + splitlen, rxlen - splitlen)
else
peekregs(wizdata + rxrr, rxpkt, rxlen)
fin
putc('=');putip(@wiz=>channel_remip);putc(':');puti(wiz=>channel_remport);putln
pokeregw(wizregs + WIZ_SnRXRD, rxwr)
pokereg(wizregs + WIZ_SnCR, $40) // RECV
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,rxpkt,rxlen,wiz=>channel_recv_parm)
heaprelease(rxpkt)
fin
if sir & $02
putc('S')
//
// Close TCP socket
//
when wiz->channel_state
is TCP_STATE_OPEN
wiz->channel_state = TCP_STATE_CLOSING
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,0,wiz=>channel_lclport,0,wiz=>channel_recv_parm)
break
is TCP_STATE_CLOSING
wiz->channel_state = TCP_STATE_CLOSED
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
break
otherwise
putc('?')
wend
fin
if sir & $08
putc('T')
//
// Timeout on TCP socket
//
when wiz->channel_state
is TCP_STATE_OPEN
wiz->channel_state = TCP_STATE_CLOSING
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
break
is TCP_STATE_CONNECT
wiz=>channel_recv_func(@wiz=>channel_remip,wiz=>channel_remport,wiz=>channel_lclport,0,0,wiz=>channel_recv_parm)
is TCP_STATE_CLOSING
wiz->channel_state = TCP_STATE_CLOSED
pokereg(wiz=>channel_regs + WIZ_SnCR, $10) // CLOSE
break
otherwise
putc('?')
wend
fin
break
is WIZ_PROTO_UDP
//putc('U');putb(sir) //putc('U');putb(sir)
if sir & $04 if sir & $04
//putc('R') //putc('R')
@@ -622,8 +847,6 @@ export def serviceIP
heaprelease(rxpkt) heaprelease(rxpkt)
fin fin
break break
is IP_PROTO_TCP
break
otherwise otherwise
wend wend
pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR
@@ -643,7 +866,7 @@ end
// //
// Set the local IP addresses // Set the local IP addresses
// //
export def setInterfaceIP(newIP, newSubnet, newGateway) def setWizIP(newIP, newSubnet, newGateway)
if newIP if newIP
localip:0 = newIP=>0; localip:2 = newIP=>2 localip:0 = newIP=>0; localip:2 = newIP=>2
pokeregs(WIZ_SIPR, newIP, IP4ADR_SIZE) pokeregs(WIZ_SIPR, newIP, IP4ADR_SIZE)
@@ -660,7 +883,7 @@ end
// //
// Get the interface hardware address // Get the interface hardware address
// //
export def getInterfaceHA(ha) def getWizHA(ha)
if ha if ha
ha=>0 = wizMAC:0; ha=>2 = wizMAC:2; ha=>4 = wizMAC:4 ha=>0 = wizMAC:0; ha=>2 = wizMAC:2; ha=>4 = wizMAC:4
fin fin
@@ -708,6 +931,19 @@ for slot = $F0 downto $90 step $10
saveidx=>channel_rxmem = WIZ_RXMEM + (WIZ_RXSIZE * slot) saveidx=>channel_rxmem = WIZ_RXMEM + (WIZ_RXSIZE * slot)
saveidx = saveidx + t_channel saveidx = saveidx + t_channel
next next
//
// Fill in Net class
//
iNet:serviceIP = @wizServiceIP
iNet:openUDP = @wizOpenUDP
iNet:sendUDP = @wizSendUDP
iNet:closeUDP = @wizCloseUDP
iNet:listenTCP = @wizListenTCP
iNet:connectTCP = @wizConnectTCP
iNet:sendTCP = @wizSendTCP
iNet:closeTCP = @wizCloseTCP
iNet:setInterfaceIP = @setWizIP
iNet:getInterfaceHA = @getWizHA
return modkeep return modkeep
fin fin
fin fin

View File

@@ -14,6 +14,7 @@ UTHERNET= UTHERNET\#FE1000
ETHERIP = ETHERIP\#FE1000 ETHERIP = ETHERIP\#FE1000
INET = INET\#FE1000 INET = INET\#FE1000
DHCP = DHCP\#FE1000 DHCP = DHCP\#FE1000
HTTPD = HTTPD\#FE1000
ROGUE = ROGUE\#FE1000 ROGUE = ROGUE\#FE1000
ROGUEIO = ROGUEIO\#FE1000 ROGUEIO = ROGUEIO\#FE1000
ROGUEMAP= ROGUEMAP\#FE1000 ROGUEMAP= ROGUEMAP\#FE1000
@@ -46,7 +47,7 @@ TXTTYPE = .TXT
#SYSTYPE = \#FF2000 #SYSTYPE = \#FF2000
#TXTTYPE = \#040000 #TXTTYPE = \#040000
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(WIZNET) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1) all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(WIZNET) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
clean: clean:
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) -rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
@@ -143,6 +144,10 @@ $(DHCP): libsrc/dhcp.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < libsrc/dhcp.pla > libsrc/dhcp.a ./$(PLASM) -AM < libsrc/dhcp.pla > libsrc/dhcp.a
acme --setpc 4094 -o $(DHCP) libsrc/dhcp.a acme --setpc 4094 -o $(DHCP) libsrc/dhcp.a
$(HTTPD): samplesrc/httpd.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/httpd.pla > samplesrc/httpd.a
acme --setpc 4094 -o $(HTTPD) samplesrc/httpd.a
$(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM) $(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM)
./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a ./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a
acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a acme --setpc 4094 -o $(ROGUE) samplesrc/rogue.a

230
src/samplesrc/httpd.pla Normal file
View File

@@ -0,0 +1,230 @@
//
// HTTP Daemon
//
import cmdsys
predef syscall, call, getc, gets, putc, puts, putln
predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease
byte MACHID
end
//
// Net object
//
import inet
word iNet
end
struc t_inet
word initIP
word serviceIP
word openUDP
word sendUDP
word closeUDP
word listenTCP
word connectTCP
word sendTCP
word closeTCP
word setInterfaceIP
word getInterfaceHA
end
word socketHTTP
byte[65] prefix
byte perr
word filebuff, iobuff
byte hello = "Apple II Web Server"
byte defhtml = "INDEX.HTML"
//
// HTTP response
//
byte httpOK = "HTTP/1.1 200 OK\n"
byte = "Content-Type: text/html\n"
byte = "Content-Length: "
byte httpLen = " \n"
byte = ""
byte httpBAD = "HTTP/1.1 404 NOTFOUND\n"
byte = "Content-Type: text/plain\n"
byte = "Content-Length: 12\n"
byte = "\n"
byte = "Bad Request\n"
byte = ""
byte[] httpBAD_end
//
// ProDOS routines
//
def getpfx(path)
byte params[3]
^path = 0
params.0 = 1
params:1 = path
perr = syscall($C7, @params)
return path
end
def setpfx(path)
byte params[3]
params.0 = 1
params:1 = path
perr = syscall($C6, @params)
return path
end
def open(path, buff)
byte params[6]
params.0 = 3
params:1 = path
params:3 = buff
params.5 = 0
perr = syscall($C8, @params)
return params.5
end
def close(refnum)
byte params[2]
params.0 = 1
params.1 = refnum
perr = syscall($CC, @params)
return perr
end
def read(refnum, buff, len)
byte params[8]
params.0 = 4
params.1 = refnum
params:2 = buff
params:4 = len
params:6 = 0
perr = syscall($CA, @params)
return params:6
end
//
// DEBUG
//
def putln
return putc($0D)
end
def putb(hexb)
return call($FDDA, hexb, 0, 0, 0)
end
def puth(hex)
return call($F941, hex >> 8, hex, 0, 0)
end
def puti(i)
if i < 0; putc('-'); i = -i; fin
if i < 10
putc(i + '0')
else
puti(i / 10)
putc(i % 10 + '0')
fin
end
def putip(ipptr)
byte i
for i = 0 to 2
puti(ipptr->[i]); putc('.')
next
return puti(ipptr->[i])
end
def dumpbytes(buf, len)
word i
for i = 0 to len - 1
putb(buf->[i])
if i & 15 == 15
putln
else
putc(' ')
fin
next
end
//
// String functions
//
def strcat(dst, src1, src2)
memcpy(dst + 1, src1 + 1, ^src1)
memcpy(dst + 1 + ^src1, src2 + 1, ^src2)
^dst = ^src1 + ^src2
return dst
end
def itos(dst, i)
if i < 0; ^dst = '-'; i = -i; dst = dst + 1; fin
if i < 10
^dst = i + '0'
else
dst = itos(dst, i / 10)
^dst = i % 10 + '0'
fin
return dst + 1
end
//
// Serve HTTP requests
//
def servHTTP(remip, remport, lclport, data, len, param)
byte i
byte[65] filename
word url
//
// Parse HTTP request
//
if len > 0
//
// Better be 'GET'
//
if data->0 == 'G' and data->1 == 'E' and data->2 == 'T' and data=>3 == ' '
len = len - 1
if len > 64
len = 64
fin
for i = 4 to len
if data->[i] <= ' '
data->3= i - 4
url = data + 3
if url->1 == '/'
if url->0 == 1
url = @defhtml
else
url->1 = url->0 - 1
url = url + 1
fin
fin
strcat(@filename, @prefix, url)
puts(@filename);putln
return
fin
next
else
iNet:sendTCP(socketHTTP, @httpBAD, @httpBAD_end - @httpBAD)
fin
else
iNet:closeTCP(socketHTTP)
socketHTTP = 0
fin
end
if !iNet:initIP()
return -1
fin
puts(@hello)
getpfx(@prefix)
//
// Alloc aligned file/io buffers
//
filebuff = heapallocalign(1024, 8, 0)
iobuff = heapallocalign(1024, 8, 0)
//
// Service IP
//
repeat
//
// (Re)Open HTTPD port
//
if !socketHTTP
socketHTTP = iNet:listenTCP(80, @servHTTP, 0)
fin
iNet:serviceIP()
until ^$C000 > 127
^$C010
done