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:
@@ -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
|
@@ -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
|
||||||
|
@@ -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
|
@@ -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
|
||||||
|
@@ -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
230
src/samplesrc/httpd.pla
Normal 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
|
Reference in New Issue
Block a user