1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-07-05 04:28:57 +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
byte MACHID
end
//
// Net object
//
import inet
predef swab, sendUDP, openUDP, closeUDP, serviceIP
predef setInterfaceIP, getInterfaceHA
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
//
// Needed to init subnet
@ -178,7 +193,7 @@ def recvDHCP(remip, remport, pkt, len, param)
memcpy(@optsDHCP.5, @pkt->dhcp_yourip, 4)
memcpy(@optsDHCP.11, @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
is DHCP_ACK
stateDHCP = DHCP_ACK
@ -204,15 +219,15 @@ end
//
// Get the local hardware address into the DHCP packet
//
getInterfaceHA(@DHCP.dhcp_clientha)
iNet:getInterfaceHA(@DHCP.dhcp_clientha)
//
// Clear our local IP address
//
setInterfaceIP(@zeros,@ones, @zeros)
iNet:setInterfaceIP(@zeros,@ones, @zeros)
//
// 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
//
@ -220,24 +235,17 @@ while retry < 3 and stateDHCP <> DHCP_ACK
//
// 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
serviceIP
iNet:serviceIP()
if stateDHCP == DHCP_ACK
break
fin
next
retry = retry + 1
loop
closeUDP(portDHCP)
setInterfaceIP(@localip, @localnet, @localgw)
iNet:closeUDP(portDHCP)
iNet:setInterfaceIP(@localip, @localnet, @localgw)
puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln
//
// Service IP
//
repeat
serviceIP
until ^$C000 > 127
^$C010
done

View File

@ -4,16 +4,35 @@ import cmdsys
predef memset, memcpy, modaddr, modexec
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
byte MACHID
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
end
//
// Module don't free memory
// Net object
//
const modkeep = $2000
const modinitkeep = $4000
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
//
// Predefine service routine
//
predef serviceIP
predef etherServiceIP
//
// Segment list element
//
@ -183,7 +202,7 @@ end
//
// Swap bytes in word
//
export asm swab
asm swab
LDA ESTKL,X
LDY ESTKH,X
STA ESTKH,X
@ -194,7 +213,7 @@ end
// 1'S COMPLIMENT SUM BE format
// sum1(PREVSUM, BUF, LEN)
//
export asm sum1
asm sum1
LDY #$00
LDA ESTKL+1,X
STA SRCL
@ -242,7 +261,7 @@ end
//
// Send IP datagram
//
export def sendIP(ipdst, proto, seglist, size)
def etherSendIP(ipdst, proto, seglist, size)
byte[t_iphdr] hdr
byte retry
word timeout
@ -275,7 +294,7 @@ export def sendIP(ipdst, proto, seglist, size)
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0
serviceIP
etherServiceIP
if remoteha:0 | remoteha:2 | remoteha:4
break
fin
@ -312,7 +331,7 @@ end
//
// 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
byte[t_udphdr] hdr
@ -324,12 +343,12 @@ export def sendUDP(port, ipdst, portdst, data, len)
seglist:0:seg_len = t_udphdr
seglist:4:seg_buf = data
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
//
// Notify on UDP datagram received
//
export def openUDP(localport, callback, param)
def etherOpenUDP(localport, callback, param)
word port
byte i
@ -363,7 +382,7 @@ end
//
// Clear notify on UDP port
//
export def closeUDP(port)
def etherCloseUDP(port)
word port
byte i
@ -382,9 +401,29 @@ export def closeUDP(port)
return -1
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
//
export def serviceIP
def etherServiceIP
word rxsize, rxpacket, rxptr
word iphdr, opt, optlen, port, lclport, remport
byte i, echolen
@ -470,7 +509,7 @@ export def serviceIP
echo_reply:icmp_chksm = 0
seglist:seg_buf = @echo_reply
seglist:seg_len = echolen
sendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
etherSendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
fin
if hookICMP
hookICMP(@iphdr=>ip_src, rxptr, rxsize)
@ -516,7 +555,7 @@ end
//
// 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 newSubnet; memcpy(@subnet, newSubnet, IP4ADR_SIZE); fin
if newGateway; memcpy(@gateway, newGateway, IP4ADR_SIZE); fin
@ -524,9 +563,22 @@ end
//
// Get the interface hardware address
//
export def getInterfaceHA(ha)
def getEtherHA(ha)
if ha; memcpy(ha, @myMAC, MAC_SIZE); fin
return MAC_SIZE
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

View File

@ -5,6 +5,31 @@ import cmdsys
byte MACHID
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
//
byte netDrivers = "WIZNET"
@ -15,22 +40,28 @@ word driver = @netDrivers
// DHCP module to load
//
byte dhcp = "DHCP"
//
// Look for net hardware
//
while ^driver
puts(driver);putln
if modexec(driver) >= 0
break
export def iNetInit
//
// Look for net hardware
//
while ^driver
//puts(driver);putln
if modexec(driver) >= 0
break
fin
driver = driver + ^driver + 1
loop
if !^driver
return 0
fin
driver = driver + ^driver + 1
loop
if !^driver
return -1
fin
//
// Get an IP address
//
modexec(@dhcp)
//
// Get an IP address
//
modexec(@dhcp)
return @iNet
end
iNet:initIP = @iNetInit
done

View File

@ -12,6 +12,25 @@ import cmdsys
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
//
// Module don't free memory
//
const modkeep = $2000
@ -96,7 +115,7 @@ byte[4] gateway
//
// Predefine service routine
//
predef serviceIP
predef wizServiceIP
//
// Segment list element
//
@ -190,18 +209,35 @@ end
//
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
//
struc t_channel
byte channel_proto
word channel_regs
word channel_txmem
word channel_rxmem
word channel_lclport
word channel_remport
word channel_remip
word channel_recv_func
word channel_recv_parm
byte channel_proto
byte channel_state
word channel_regs
word channel_txmem
word channel_rxmem
word channel_lclport
word channel_remport
byte[4] channel_remip
word channel_recv_func
word channel_recv_parm
end
byte[t_channel * MAX_WIZ_CHANNELS] wizChannel
//
@ -217,7 +253,7 @@ end
//
// Swap bytes in word
//
export asm swab
asm swab
LDA ESTKL,X
LDY ESTKH,X
STA ESTKH,X
@ -225,55 +261,6 @@ export asm swab
RTS
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
//
// POKE WORD TO I/O SPACE
@ -440,6 +427,7 @@ def peekregw(reg)
_pokeiow(reg)
dataw.1 = _peekio()
_pokeiow(reg + 1)
dataw.0 = _peekio()
return dataw
end
@ -475,7 +463,7 @@ end
//
// Send UDP datagram
//
export def sendUDP(wiz, ipdst, portdst, data, len)
def wizSendUDP(wiz, ipdst, portdst, data, len)
word wizregs, wizdata, txrr, txwr, splitlen
wizregs = wiz=>channel_regs
@ -512,7 +500,7 @@ end
//
// Open UDP channel and set datagram received callback
//
export def openUDP(localport, callback, param)
def wizOpenUDP(localport, callback, param)
word wiz
byte i
@ -520,6 +508,7 @@ export def openUDP(localport, callback, param)
//
// Look for an existing notification on localport
//
putc('O')
wiz = @wizChannel
for i = 1 to MAX_WIZ_CHANNELS
if wiz->channel_proto == IP_PROTO_UDP and wiz=>channel_lclport == localport
@ -542,10 +531,11 @@ export def openUDP(localport, callback, param)
return 0
fin
fin
putc('0' + i);putln
//
// 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_recv_func = callback
wiz=>channel_recv_parm = param
@ -557,14 +547,170 @@ end
//
// Close UDP port
//
export def closeUDP(wiz)
if isuge(wiz, wizChannel) and isult(wiz, wizChannel + MAX_WIZ_CHANNELS * t_channel)
def wizCloseUDP(wiz)
putc('S')
if isuge(wiz, @wizChannel) and isult(wiz, @wizChannel + MAX_WIZ_CHANNELS * t_channel)
//
// Clear notiications on this port
//
if wiz->channel_proto == IP_PROTO_UDP
wiz->channel_proto = 0
pokereg(wiz=>channel_regs + WIZ_SnCR, $00) // CLOSE
if wiz->channel_proto == WIZ_PROTO_UDP
putc('1' + ((wiz=>channel_regs - WIZ_SREGS) >> 8));putln
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
fin
fin
@ -576,13 +722,13 @@ end
//
// Service incoming packets
//
export def serviceIP
def wizServiceIP
word wiz, wizregs, wizdata, rxlen, rxrr, rxwr, rxpkt, splitlen
byte ir, i, sir
ir = peekreg(WIZ_IR)
if ir and ir <> $FF // Ignore spurious read of IR
//putc('I');putb(ir)
putc('I');putb(ir)
wiz = @wizChannel
for i = 0 to 3
when ir & (1 << i)
@ -594,7 +740,86 @@ export def serviceIP
wizdata = wiz=>channel_rxmem
sir = peekreg(wizregs + WIZ_SnIR)
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)
if sir & $04
//putc('R')
@ -622,8 +847,6 @@ export def serviceIP
heaprelease(rxpkt)
fin
break
is IP_PROTO_TCP
break
otherwise
wend
pokereg(wiz=>channel_regs + WIZ_SnIR, sir) // Clear SnIR
@ -643,7 +866,7 @@ end
//
// Set the local IP addresses
//
export def setInterfaceIP(newIP, newSubnet, newGateway)
def setWizIP(newIP, newSubnet, newGateway)
if newIP
localip:0 = newIP=>0; localip:2 = newIP=>2
pokeregs(WIZ_SIPR, newIP, IP4ADR_SIZE)
@ -660,7 +883,7 @@ end
//
// Get the interface hardware address
//
export def getInterfaceHA(ha)
def getWizHA(ha)
if ha
ha=>0 = wizMAC:0; ha=>2 = wizMAC:2; ha=>4 = wizMAC:4
fin
@ -708,6 +931,19 @@ for slot = $F0 downto $90 step $10
saveidx=>channel_rxmem = WIZ_RXMEM + (WIZ_RXSIZE * slot)
saveidx = saveidx + t_channel
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
fin
fin

View File

@ -14,6 +14,7 @@ UTHERNET= UTHERNET\#FE1000
ETHERIP = ETHERIP\#FE1000
INET = INET\#FE1000
DHCP = DHCP\#FE1000
HTTPD = HTTPD\#FE1000
ROGUE = ROGUE\#FE1000
ROGUEIO = ROGUEIO\#FE1000
ROGUEMAP= ROGUEMAP\#FE1000
@ -46,7 +47,7 @@ TXTTYPE = .TXT
#SYSTYPE = \#FF2000
#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:
-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
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)
./$(PLASM) -AM < samplesrc/rogue.pla > 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