1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-08-21 21:29:08 +00:00

update to latest library and formatting

This commit is contained in:
Dave Schmenk 2017-12-10 16:41:37 -08:00
parent 0d484e75d2
commit b25b5cd233
9 changed files with 1103 additions and 1253 deletions

View File

@ -37,6 +37,7 @@ import fileio
word getpfx
word setpfx
word getfileinfo
word geteof
word open
word close
word read

File diff suppressed because it is too large Load Diff

View File

@ -2,29 +2,7 @@
// DHCP
//
include "inc/cmdsys.plh"
//
// 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
word setDNS
word resolveIP
word setCallback
word setParam
end
include "inc/inet.plh"
//
// Needed to init subnet
//
@ -109,58 +87,58 @@ byte[] endDHCP
//
// DEBUG
//
byte boundstr = "Apple II bound to:\n"
byte dnsstr = "DNS: "
def putb(hexb)
return call($FDDA, hexb, 0, 0, 0)
end
def puth(hex)
return call($F941, hex >> 8, hex, 0, 0)
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
def dumpdhcp(pkt)
putb(pkt->dhcp_op);putln
putb(pkt->dhcp_htype);putln
putb(pkt->dhcp_hlen);putln
putb(pkt->dhcp_hops);putln
dumpbytes(@pkt->dhcp_xid, 4);putln
putip(@pkt->dhcp_clientip);putln
putip(@pkt->dhcp_yourip);putln
putip(@pkt->dhcp_serverip);putln
putip(@pkt->dhcp_gatewayip);putln
dumpbytes(@pkt->dhcp_opts, 48);putln
end
//byte boundstr = "Apple II bound to:\n"
//byte dnsstr = "DNS: "
//def putb(hexb)
// return call($FDDA, hexb, 0, 0, 0)
//end
//def puth(hex)
// return call($F941, hex >> 8, hex, 0, 0)
//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
//def dumpdhcp(pkt)
// putb(pkt->dhcp_op);putln
// putb(pkt->dhcp_htype);putln
// putb(pkt->dhcp_hlen);putln
// putb(pkt->dhcp_hops);putln
// dumpbytes(@pkt->dhcp_xid, 4);putln
// putip(@pkt->dhcp_clientip);putln
// putip(@pkt->dhcp_yourip);putln
// putip(@pkt->dhcp_serverip);putln
// putip(@pkt->dhcp_gatewayip);putln
// dumpbytes(@pkt->dhcp_opts, 48);putln
//end
def parseopts(opts, match)
byte i
i = 0
while opts->[i] <> $FF and i < 64
while !opts->[i] and i < 64
i = i + 1
loop
while !opts->[i] and i < 64
i = i + 1
loop
if opts->[i] == match
return i
fin
i = i + opts->[i + 1] + 2
return i
fin
i = i + opts->[i + 1] + 2
loop
return -1
end
@ -171,41 +149,41 @@ def recvDHCP(remip, remport, pkt, len, param)
//dumpdhcp(pkt)
if pkt=>dhcp_xid:0 == $0201 and pkt=>dhcp_xid:2 == $0403
when pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 53) + 2]
is DHCP_OFFER
//
// Copy offer parameters to request
//
optsOP.2 = DHCP_REQUEST
memcpy(@optsIP.2, @pkt->dhcp_yourip, IP4ADR_SIZE)
servopts = parseopts(@pkt->dhcp_opts, 54) + 2
if servopts >= 0
optsSRV = 54
memcpy(@optsSRV.2, @pkt->dhcp_opts.[servopts], IP4ADR_SIZE)
fin
iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, @endDHCP - @DHCP)
break
is DHCP_ACK
optsOP.2 = DHCP_ACK
//
// Copy parameters to working copy
//
memcpy(@localip, @pkt->dhcp_yourip, IP4ADR_SIZE)
maskopts = parseopts(@pkt->dhcp_opts, 1) + 2
if maskopts >= 0
memcpy(@localnet, @pkt->dhcp_opts.[maskopts], IP4ADR_SIZE)
fin
gwopts = parseopts(@pkt->dhcp_opts, 3) + 2
if gwopts >= 0
memcpy(@localgw, @pkt->dhcp_opts.[gwopts], IP4ADR_SIZE)
fin
dnsopts = parseopts(@pkt->dhcp_opts, 6) + 2
if dnsopts >= 0
memcpy(@localdns, @pkt->dhcp_opts.[dnsopts], IP4ADR_SIZE)
fin
break
otherwise
dumpdhcp(pkt)
wend
is DHCP_OFFER
//
// Copy offer parameters to request
//
optsOP.2 = DHCP_REQUEST
memcpy(@optsIP.2, @pkt->dhcp_yourip, IP4ADR_SIZE)
servopts = parseopts(@pkt->dhcp_opts, 54) + 2
if servopts >= 0
optsSRV = 54
memcpy(@optsSRV.2, @pkt->dhcp_opts.[servopts], IP4ADR_SIZE)
fin
iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, @endDHCP - @DHCP)
break
is DHCP_ACK
optsOP.2 = DHCP_ACK
//
// Copy parameters to working copy
//
memcpy(@localip, @pkt->dhcp_yourip, IP4ADR_SIZE)
maskopts = parseopts(@pkt->dhcp_opts, 1) + 2
if maskopts >= 0
memcpy(@localnet, @pkt->dhcp_opts.[maskopts], IP4ADR_SIZE)
fin
gwopts = parseopts(@pkt->dhcp_opts, 3) + 2
if gwopts >= 0
memcpy(@localgw, @pkt->dhcp_opts.[gwopts], IP4ADR_SIZE)
fin
dnsopts = parseopts(@pkt->dhcp_opts, 6) + 2
if dnsopts >= 0
memcpy(@localdns, @pkt->dhcp_opts.[dnsopts], IP4ADR_SIZE)
fin
break
otherwise
//dumpdhcp(pkt)
wend
fin
end
//
@ -229,23 +207,23 @@ repeat
//
// Broadcast DHCP DISCOVER message
//
optsOP.2 = DHCP_DISCOVER
optsIP:2 = 0
optsIP:4 = 0
optsSRV = 255
optsOP.2 = DHCP_DISCOVER
optsIP:2 = 0
optsIP:4 = 0
optsSRV = 255
DHCP.dhcp_secs.1 = retry
iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, @optsSRV - @DHCP + 1)
for timeout = 0 to 1000
iNet:serviceIP()
if optsOP.2 == DHCP_ACK
break
if optsOP.2 == DHCP_ACK
break
fin
next
retry = retry + 1
until retry > 4 or optsOP.2 == DHCP_ACK
iNet:closeUDP(portDHCP)
iNet:setInterfaceIP(@localip, @localnet, @localgw)
puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln
//puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln
iNet:setDNS(@localdns)
puts(@dnsstr);putip(@localdns);putln
//puts(@dnsstr);putip(@localdns);putln
done

View File

@ -1,27 +1,5 @@
include "inc/cmdsys.plh"
//
// 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
word setDNS
word resolveIP
word setCallback
word setParam
end
include "inc/inet.plh"
//
// Predefine service routine
//
@ -87,14 +65,14 @@ struc t_icmp
word[2] icmp_header
end
//
// UDP IPv4 psuedo header
// UDP IPv4 pseudo header
//
struc t_piphdr
byte[IP4ADR_SIZE] pip_src
byte[IP4ADR_SIZE] pip_dst
byte pip_zero
byte pip_proto
word pip_len
byte pip_zero
byte pip_proto
word pip_len
end
//
// UDP header
@ -117,19 +95,19 @@ end
//
// ARP packet
//
const HW_ETHER = $0100 // BE format
const ARP_PROTO = $0008 // BE format
const ARP_REQST = $0100 // BE format
const ARP_REPLY = $0200 // BE format
const HW_ETHER = $0100 // BE format
const ARP_PROTO = $0008 // BE format
const ARP_REQST = $0100 // BE format
const ARP_REPLY = $0200 // BE format
struc t_arp
word arp_hw
word arp_proto
byte arp_hlen
byte arp_plen
word arp_op
byte[MAC_SIZE] arp_senderha
byte[MAC_SIZE] arp_senderha
byte[IP4ADR_SIZE] arp_senderip
byte[MAC_SIZE] arp_targha
byte[MAC_SIZE] arp_targha
byte[IP4ADR_SIZE] arp_targip
end
const t_earp = t_ethrhdr+t_arp
@ -152,14 +130,14 @@ word ePayload = PAYLOAD_ARP
//
// Pre-configured ARP packet - MUST follow ethernet header!
//
word ARP = HW_ETHER // HW TYPE
word = ARP_PROTO // PROTO TYPE
byte = MAC_SIZE // HLEN
word ARP = HW_ETHER // HW TYPE
word = ARP_PROTO // PROTO TYPE
byte = MAC_SIZE // HLEN
byte = IP4ADR_SIZE // PLEN
word opARP // OP
export byte[MAC_SIZE] localha
word opARP // OP
export byte[MAC_SIZE] localha
export byte[IP4ADR_SIZE] localip
byte[MAC_SIZE] remoteha
byte[MAC_SIZE] remoteha
byte[IP4ADR_SIZE] remoteip
//
// Local network parameters
@ -167,8 +145,8 @@ byte[IP4ADR_SIZE] remoteip
byte[IP4ADR_SIZE] netmask
byte[IP4ADR_SIZE] subnet
byte[IP4ADR_SIZE] gateway
const MAX_UDP_NOTIFIES = 4
const MAX_TCP_NOTIFIES = 4
const MAX_UDP_NOTIFIES = 4
const MAX_TCP_NOTIFIES = 4
//
// Notify callbacks
//
@ -191,64 +169,64 @@ word setFrameLen, writeFrame, getFrameLen, readFrame
// Defines for ASM routines
//
asm equates
!SOURCE "vmsrc/plvmzp.inc"
!SOURCE "vmsrc/plvmzp.inc"
end
//
// Swap bytes in word
//
asm swab
LDA ESTKL,X
LDY ESTKH,X
STA ESTKH,X
STY ESTKL,X
RTS
LDA ESTKL,X
LDY ESTKH,X
STA ESTKH,X
STY ESTKL,X
RTS
end
//
// 1'S COMPLIMENT SUM BE format
// sum1(PREVSUM, BUF, LEN)
//
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 +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
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
BCC +
- INC ESTKH+2,X
BNE +
INC ESTKL+2,X
BEQ -
+ INX
INX
RTS
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 +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
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
BCC +
- INC ESTKH+2,X
BNE +
INC ESTKL+2,X
BEQ -
+ INX
INX
RTS
end
//
// Send IP datagram
@ -268,34 +246,34 @@ def etherSendIP(ipdst, proto, seglist, size)
hdr:ip_chksm = 0
memcpy(@hdr.ip_src, @localip, IP4ADR_SIZE)
if !ipdst // IP_BROADCAST
memset(@hdr.ip_dst, IP_BROADCAST, IP4ADR_SIZE)
memset(@hdr.ip_dst, IP_BROADCAST, IP4ADR_SIZE)
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
else
if ipdst=>0 & netmask:0 <> subnet:0 or ipdst=>2 & netmask:2 <> subnet:2
ipdst = @gateway // External net destination
fin
memcpy(@hdr.ip_dst, ipdst, IP4ADR_SIZE)
fin
memcpy(@hdr.ip_dst, ipdst, IP4ADR_SIZE)
retry = 0
while hdr:ip_dst:0 <> remoteip:0 and hdr:ip_dst:2 <> remoteip:2
if retry >= 3
if retry >= 3
return -1 // ARP failed
fin
retry = retry + 1
fin
retry = retry + 1
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
memset(@remoteha, 0, MAC_SIZE)
memcpy(@remoteip, @hdr.ip_dst, IP4ADR_SIZE)
ePayload = PAYLOAD_ARP
opARP = ARP_REQST
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0
etherServiceIP
if remoteha:0 | remoteha:2 | remoteha:4
break
fin
next
loop
memcpy(@dstMAC, @remoteha, MAC_SIZE)
memset(@remoteha, 0, MAC_SIZE)
memcpy(@remoteip, @hdr.ip_dst, IP4ADR_SIZE)
ePayload = PAYLOAD_ARP
opARP = ARP_REQST
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
for timeout = 1000 downto 0
etherServiceIP
if remoteha:0 | remoteha:2 | remoteha:4
break
fin
next
loop
memcpy(@dstMAC, @remoteha, MAC_SIZE)
fin
//
// Calculate checksum
@ -318,9 +296,9 @@ def etherSendIP(ipdst, proto, seglist, size)
// Write the remaining segments
//
while size > 0
writeFrame(seglist=>seg_buf, seglist=>seg_len)
size = size - seglist=>seg_len
seglist = seglist + t_segment
writeFrame(seglist=>seg_buf, seglist=>seg_len)
size = size - seglist=>seg_len
seglist = seglist + t_segment
loop
end
//
@ -330,10 +308,10 @@ def etherSendUDP(port, ipdst, portdst, data, len)
word[8] seglist // list of data and header segments
byte[t_udphdr] hdr
hdr:udp_src = swab(port=>notify_port)
hdr:udp_dst = swab(portdst)
hdr:udp_len = swab(t_udphdr + len)
hdr:udp_chksm = 0
hdr:udp_src = swab(port=>notify_port)
hdr:udp_dst = swab(portdst)
hdr:udp_len = swab(t_udphdr + len)
hdr:udp_chksm = 0
seglist:0:seg_buf = @hdr
seglist:0:seg_len = t_udphdr
seglist:4:seg_buf = data
@ -354,11 +332,11 @@ def etherOpenUDP(localport, callback, param)
port = @portsUDP
for i = 1 to MAX_UDP_NOTIFIES
if port=>notify_port == localport
port=>notify_func = callback
port=>notify_parm = param
return port
fin
port = port + t_notify
port=>notify_func = callback
port=>notify_parm = param
return port
fin
port = port + t_notify
next
//
// Add notification on localport if room
@ -366,12 +344,12 @@ def etherOpenUDP(localport, callback, param)
port = @portsUDP
for i = 1 to MAX_UDP_NOTIFIES
if !port=>notify_port
port=>notify_port = localport
port=>notify_func = callback
port=>notify_parm = param
return port
fin
port = port + t_notify
port=>notify_port = localport
port=>notify_func = callback
port=>notify_parm = param
return port
fin
port = port + t_notify
next
end
//
@ -382,13 +360,13 @@ def etherCloseUDP(port)
byte i
if isuge(port, @portsUDP) and isult(port, @portsUDP + MAX_UDP_NOTIFIES * t_notify)
//
// Clear notiications on this port
//
if port=>notify_port
//
// Clear notiications on this port
//
if port=>notify_port
port=>notify_port = 0
return 0
fin
return 0
fin
fin
//
// Invalid port
@ -420,13 +398,13 @@ end
//
def etherSetCallback(port, callback)
if isuge(port, @portsUDP) and isult(port, @portsUDP + MAX_UDP_NOTIFIES * t_notify)
//
// Update callback on this port
//
if port=>notify_port
port=>notify_func = callback
return 0
fin
//
// Update callback on this port
//
if port=>notify_port
port=>notify_func = callback
return 0
fin
fin
//
// Invalid port
@ -438,13 +416,13 @@ end
//
def etherSetParam(port, param)
if isuge(port, @portsUDP) and isult(port, @portsUDP + MAX_UDP_NOTIFIES * t_notify)
//
// Update callback on this port
//
if port=>notify_port
port=>notify_parm = param
return 0
fin
//
// Update callback on this port
//
if port=>notify_port
port=>notify_parm = param
return 0
fin
fin
//
// Invalid port
@ -467,109 +445,109 @@ def etherServiceIP
rxsize = getFrameLen()
if rxsize
//
// Read the entire packet into memory
//
rxpacket = heapalloc(rxsize)
// Read the entire packet into memory
//
rxpacket = heapalloc(rxsize)
readFrame(rxpacket, rxsize)
rxptr = rxpacket + t_ethrhdr
rxsize = rxsize - t_ethrhdr
//
// What kind of packet is it?
//
when rxpacket=>ethr_payload
rxsize = rxsize - t_ethrhdr
//
// What kind of packet is it?
//
when rxpacket=>ethr_payload
is PAYLOAD_IP
iphdr = rxptr
rxptr = rxptr + t_iphdr
rxsize = rxsize - t_iphdr
if iphdr->ip_vers_hlen <> $45
optlen = iphdr=>ip_vers_hlen
if optlen & $F0 <> $40
//
// Not IPv4, ignore
//
break
fin
optlen = (optlen & $0F) << 2
if optlen > t_iphdr
//
// Read the options and throw them on the ground!
//
rxptr = rxptr + (optlen - t_iphdr)
rxsize = rxsize - (optlen - t_iphdr)
fin
fin
//
// Filter valid destination address
//
if iphdr=>ip_dst:2 <> localip:2 // Yes, this is a little lazy
if (iphdr=>ip_dst:0|netmask:0) & (iphdr=>ip_dst:2|netmask:2) <> IP_BROADCAST
break
fin
fin
//
// What kind of IP protocol is it?
//
when iphdr->ip_proto
is IP_PROTO_UDP
port = @portsUDP
if port
lclport = swab(rxptr=>udp_dst)
for i = 1 to MAX_UDP_NOTIFIES
if port=>notify_port == lclport
port=>notify_func(@iphdr=>ip_src,swab(rxptr=>udp_src),rxptr+t_udphdr,swab(rxptr=>udp_len),port=>notify_parm)
break
fin
port = port + t_notify
next
fin
break
is IP_PROTO_TCP
break
is IP_PROTO_ICMP
//
// Service ICMP packets
//
if rxptr->icmp_type == ICMP_ECHO_REQST
if rxsize > 128
echolen = 128
else
echolen = rxsize
fin
memcpy(@echo_reply, rxptr, echolen)
echo_reply.icmp_type = ICMP_ECHO_REPLY
echo_reply:icmp_chksm = 0
seglist:seg_buf = @echo_reply
seglist:seg_len = echolen
etherSendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
fin
if hookICMP
hookICMP(@iphdr=>ip_src, rxptr, rxsize)
fin
wend
break
is PAYLOAD_ARP
when rxptr=>arp_op
is ARP_REPLY
//
// Fill in ARP cache
//
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
break
is ARP_REQST
//
// Is this a request for me?
//
if rxptr=>arp_targip:0 == localip:0 and rxptr=>arp_targip:2 == localip:2
memcpy(@dstMAC, @rxptr=>arp_senderha, MAC_SIZE)
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
ePayload = PAYLOAD_ARP
opARP = ARP_REPLY
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
fin
wend
iphdr = rxptr
rxptr = rxptr + t_iphdr
rxsize = rxsize - t_iphdr
if iphdr->ip_vers_hlen <> $45
optlen = iphdr=>ip_vers_hlen
if optlen & $F0 <> $40
//
// Not IPv4, ignore
//
break
fin
optlen = (optlen & $0F) << 2
if optlen > t_iphdr
//
// Read the options and throw them on the ground!
//
rxptr = rxptr + (optlen - t_iphdr)
rxsize = rxsize - (optlen - t_iphdr)
fin
fin
//
// Filter valid destination address
//
if iphdr=>ip_dst:2 <> localip:2 // Yes, this is a little lazy
if (iphdr=>ip_dst:0|netmask:0) & (iphdr=>ip_dst:2|netmask:2) <> IP_BROADCAST
break
fin
fin
//
// What kind of IP protocol is it?
//
when iphdr->ip_proto
is IP_PROTO_UDP
port = @portsUDP
if port
lclport = swab(rxptr=>udp_dst)
for i = 1 to MAX_UDP_NOTIFIES
if port=>notify_port == lclport
port=>notify_func(@iphdr=>ip_src,swab(rxptr=>udp_src),rxptr+t_udphdr,swab(rxptr=>udp_len),port=>notify_parm)
break
fin
port = port + t_notify
next
fin
break
is IP_PROTO_TCP
break
is IP_PROTO_ICMP
//
// Service ICMP packets
//
if rxptr->icmp_type == ICMP_ECHO_REQST
if rxsize > 128
echolen = 128
else
echolen = rxsize
fin
memcpy(@echo_reply, rxptr, echolen)
echo_reply.icmp_type = ICMP_ECHO_REPLY
echo_reply:icmp_chksm = 0
seglist:seg_buf = @echo_reply
seglist:seg_len = echolen
etherSendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
fin
if hookICMP
hookICMP(@iphdr=>ip_src, rxptr, rxsize)
fin
wend
break
is PAYLOAD_ARP
when rxptr=>arp_op
is ARP_REPLY
//
// Fill in ARP cache
//
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
break
is ARP_REQST
//
// Is this a request for me?
//
if rxptr=>arp_targip:0 == localip:0 and rxptr=>arp_targip:2 == localip:2
memcpy(@dstMAC, @rxptr=>arp_senderha, MAC_SIZE)
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
ePayload = PAYLOAD_ARP
opARP = ARP_REPLY
setFrameLen(t_earp)
writeFrame(@eFrame, t_earp)
fin
wend
wend
heaprelease(rxpacket)
heaprelease(rxpacket)
fin
end
//

View File

@ -26,6 +26,7 @@ struc t_fileio
word getpfx
word setpfx
word getfileinfo
word geteof
word open
word close
word read
@ -36,13 +37,13 @@ struc t_fileio
word readblock
word writeblock
end
predef a2getpfx, a23setpfx, a2getfileinfo, a2open, a23close
predef a2getpfx, a23setpfx, a2getfileinfo, a23geteof, a2open, a23close
predef a23read, a2write, a2create, a23destroy
predef a23newline, a2readblock, a2writeblock
//
// Exported function table.
//
export word fileio[] = @a2getpfx, @a23setpfx, @a2getfileinfo, @a2open, @a23close
export word fileio[] = @a2getpfx, @a23setpfx, @a2getfileinfo, @a23geteof, @a2open, @a23close
word = @a23read, @a2write, @a2create, @a23destroy
word = @a23newline, @a2readblock, @a2writeblock
//
@ -108,6 +109,19 @@ def a3getfileinfo(path, fileinfo)
perr = syscall($C4, @params)
return perr
end
def a1geteof(refnum)
return 0
end
def a23geteof(refnum)
byte params[6]
params.0 = 2
params.1 = refnum
params:2 = 0
params:4 = 0
syscall($D1, @params)
return params:2
end
def a1open(path)
*CFFA1FileName = path
return 0
@ -273,6 +287,7 @@ when MACHID & $C8
fileio:getpfx = @a1getpfx
fileio:setpfx = @a1setpfx
fileio:getfileinfo = @a1getfileinfo
fileio:geteof = @a1geteof
fileio:open = @a1open
fileio:close = @a1close
fileio:read = @a1read

View File

@ -1,6 +1,6 @@
include "inc/cmdsys.plh"
//
// Net object
// iNet API - must match inet.plh
//
struc t_inet
word initIP
@ -53,32 +53,32 @@ def iNetSetDNS(ipptr)
return memcpy(@dns, ipptr, 4)
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 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 & 7 == 7
putln
else
putc(' ')
fin
next
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 dumpbytes(buf, len)
// word i
//
// for i = 0 to len - 1
// putb(buf->[i])
// if i & 7 == 7
// putln
// else
// putc(' ')
// fin
// next
//end
//def putip(ipptr)
// byte i
//
// for i = 0 to 2
// puti(ipptr->[i]); putc('.')
// next
// return puti(ipptr->[i])
//end
def parseIP(ipstr, ipaddr)
byte i
@ -123,38 +123,38 @@ def recvDNS(remip, remport, pkt, len, ipaddr)
if pkt=>dnsID == $BEEF
q = pkt->dnsQdCount.1
r = pkt->dnsAnCount.1 + pkt->dnsNsCount.1 + pkt->dnsArCount.1
resptr = pkt + t_dnshdr
while q
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
//putln; dumpbytes(resptr, 4); putln
resptr = resptr + 4
q = q - 1
loop
while r
//dumpbytes(resptr, 40); putln
if ^resptr & $C0 == $C0
resptr = resptr + 2
else
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
fin
if resptr->1 == 1 and resptr->3 == 1 and resptr->9 == 4
ipaddr=>0 = resptr=>10
ipaddr=>2 = resptr=>12
fin
//putln; dumpbytes(resptr, 10); putc(':'); putln
resptr = resptr + 8
//dumpbytes(resptr + 2, ^(resptr + 1))
resptr = resptr + 2 + ^(resptr + 1); putln
r = r - 1
loop
resptr = pkt + t_dnshdr
while q
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
//putln; dumpbytes(resptr, 4); putln
resptr = resptr + 4
q--
loop
while r
//dumpbytes(resptr, 40); putln
if ^resptr & $C0 == $C0
resptr = resptr + 2
else
while ^resptr
//puts(resptr); putc('.')
resptr = resptr + ^resptr + 1
loop
resptr = resptr + 1
fin
if resptr->1 == 1 and resptr->3 == 1 and resptr->9 == 4
ipaddr=>0 = resptr=>10
ipaddr=>2 = resptr=>12
fin
//putln; dumpbytes(resptr, 10); putc(':'); putln
resptr = resptr + 8
//dumpbytes(resptr + 2, ^(resptr + 1))
resptr = resptr + 2 + ^(resptr + 1); putln
r = r - 1
loop
fin
stateDNS = DNS_ANSWER
end
@ -167,38 +167,38 @@ def iNetResolve(namestr, ipaddr)
ipaddr=>2 = 0
if not parseIP(namestr, ipaddr)
//
// Query Domain Name Server for address
//
dnspkt = heapmark // Use heap as working DNS query packet
msgptr = dnspkt
msgptr=>dnsID = $BEEF
msgptr=>dnsCode = $0001 // RD (Recursion Desired)
msgptr=>dnsQdCount = $0100 // BE count = 1
msgptr=>dnsAnCount = 0
msgptr=>dnsNsCount = 0
msgptr=>dnsArCount = 0
msgptr = parseDomain(namestr, msgptr + t_dnshdr)
msgptr=>0 = $0100 // BE TYPE = Address
msgptr=>2 = $0100 // BE CLASS = INternet
msglen = msgptr - dnspkt + 4
heapalloc(msglen)
//
// Prepare to receive DNS answer from server
//
portDNS = iNet:openUDP(3999, @recvDNS, ipaddr)
//
// Service IP
//
stateDNS = DNS_QUERY
iNet:sendUDP(portDNS, @dns, 53, dnspkt, msglen)
for timeout = 1 to 1000
iNet:serviceIP()
if stateDNS == DNS_ANSWER
break
fin
next
iNet:closeUDP(portDNS)
heaprelease(dnspkt)
// Query Domain Name Server for address
//
dnspkt = heapmark // Use heap as working DNS query packet
msgptr = dnspkt
msgptr=>dnsID = $BEEF
msgptr=>dnsCode = $0001 // RD (Recursion Desired)
msgptr=>dnsQdCount = $0100 // BE count = 1
msgptr=>dnsAnCount = 0
msgptr=>dnsNsCount = 0
msgptr=>dnsArCount = 0
msgptr = parseDomain(namestr, msgptr + t_dnshdr)
msgptr=>0 = $0100 // BE TYPE = Address
msgptr=>2 = $0100 // BE CLASS = INternet
msglen = msgptr - dnspkt + 4
heapalloc(msglen)
//
// Prepare to receive DNS answer from server
//
portDNS = iNet:openUDP(3999, @recvDNS, ipaddr)
//
// Service IP
//
stateDNS = DNS_QUERY
iNet:sendUDP(portDNS, @dns, 53, dnspkt, msglen)
for timeout = 1 to 1000
iNet:serviceIP()
if stateDNS == DNS_ANSWER
break
fin
next
iNet:closeUDP(portDNS)
heaprelease(dnspkt)
fin
return ipaddr=>0 <> 0 or ipaddr=>2 <> 0
end
@ -209,10 +209,10 @@ export def iNetInit
//
while ^driver
//puts(driver);putln
if modexec(driver) >= 0
break
fin
driver = driver + ^driver + 1
if modexec(driver) >= 0
break
fin
driver = driver + ^driver + 1
loop
if !^driver
return 0
@ -228,7 +228,6 @@ end
//
// Fill iNet class
//
iNet:initIP = @iNetInit
iNet:setDNS = @iNetSetDNS
iNet:initIP = @iNetInit
iNet:setDNS = @iNetSetDNS
done

View File

@ -9,11 +9,6 @@ import etherip
predef setEtherDriver
end
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
//
// Uthernet register offsets
//
const TXDATA = $00
@ -42,129 +37,129 @@ byte[6] utherMAC = $00,$0A,$99,$1E,$02,$A0
// Defines for ASM routines
//
asm equates
!SOURCE "vmsrc/plvmzp.inc"
!SOURCE "vmsrc/plvmzp.inc"
end
//
// Uthernet I/O functions
//
asm _pokeiow
LDA ESTKL,X
LDA ESTKL,X
end
asm _pokeiowl
STA $C000
LDA ESTKH,X
STA $C000
LDA ESTKH,X
end
asm _pokeiowh
STA $C000
RTS
STA $C000
RTS
end
//
// PEEK BYTE FROM I/O SPACE
// _peekio()
//
asm _peekio
DEX
DEX
end
asm _peekiol
LDA $C000
STA ESTKL,X
LDA #$00
STA ESTKH,X
RTS
LDA $C000
STA ESTKL,X
LDA #$00
STA ESTKH,X
RTS
end
//
// PEEK WORD FROM I/O SPACE
// _peekiow()
//
asm _peekiow
DEX
DEX
end
asm _peekiowl
LDA $C000
STA ESTKL,X
LDA $C000
STA ESTKL,X
end
asm _peekiowh
LDA $C000
STA ESTKH,X
RTS
LDA $C000
STA ESTKH,X
RTS
end
//
// WRITE FRAME DATA INTO I/O SPACE
// pokefrm(BUF, LEN)
//
asm pokefrm
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 +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
POKELP LDA (SRC),Y
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 +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
POKELP LDA (SRC),Y
end
asm _pokefrml
STA $C000
INY
LDA (SRC),Y
STA $C000
INY
LDA (SRC),Y
end
asm _pokefrmh
STA $C000
INY
BNE +
INC SRCH
+ DEC ESTKL,X
BNE POKELP
DEC ESTKH,X
BNE POKELP
INX
RTS
STA $C000
INY
BNE +
INC SRCH
+ DEC ESTKL,X
BNE POKELP
DEC ESTKH,X
BNE POKELP
INX
RTS
end
//
// READ FRAME DATA FROM I/O SPACE
// peekfrm(BUF, LEN)
//
asm peekfrm
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
LDA ESTKL,X
ROR
ADC #$00
STA ESTKL,X
BEQ +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
LDY #$00
LDA ESTKL+1,X
STA DSTL
LDA ESTKH+1,X
STA DSTH
LSR ESTKH,X ; CONVERT BYTE LEN TO WORD LEN
LDA ESTKL,X
ROR
ADC #$00
STA ESTKL,X
BEQ +
!BYTE $A9
- CLC
INC ESTKH,X
+ BCS -
end
asm _peekfrml
PEEKLP LDA $C000
STA (DST),Y
INY
PEEKLP LDA $C000
STA (DST),Y
INY
end
asm _peekfrmh
+ LDA $C000
STA (DST),Y
INY
BNE +
INC DSTH
+ DEC ESTKL,X
BNE PEEKLP
DEC ESTKH,X
BNE PEEKLP
EXPSW INX
RTS
+ LDA $C000
STA (DST),Y
INY
BNE +
INC DSTH
+ DEC ESTKL,X
BNE PEEKLP
DEC ESTKH,X
BNE PEEKLP
EXPSW INX
RTS
end
def pokeiow(io, data)
_pokeiowl.1 = io
@ -205,12 +200,12 @@ def peekfrmlen
if peekiow(isq) & $3F == $04
if peekio(rxdata_hi) & $01
peekio(rxdata_lo)
len.1 = peekio(rxdata_hi)
len.0 = peekio(rxdata_lo)
else
peekio(rxdata_lo)
pokepreg($0102, $0140) // Skip pkt
fin
len.1 = peekio(rxdata_hi)
len.0 = peekio(rxdata_lo)
else
peekio(rxdata_lo)
pokepreg($0102, $0140) // Skip pkt
fin
fin
return len
end
@ -220,10 +215,10 @@ end
for slot = $90 to $F0 step $10
if (peekiow(slot+TXCMD) & $CC3F) == $09
pokeiow(slot+PREG_INDEX, 0)
if peekiow(slot+PREG_DATA) == $630E
if peekiow(slot+PREG_DATA) == $630E
pokepreg($0114, $40) // RESET
rxdata_hi = slot + 1
txcmd = slot + TXCMD
rxdata_hi = slot + 1
txcmd = slot + TXCMD
txlen = slot + TXLEN
isq = slot + INT_STATUS
pregidx = slot + PREG_INDEX
@ -239,13 +234,13 @@ for slot = $90 to $F0 step $10
pokepreg($0104, $0D00) // Recv ctrl
pokepreg($0106, $8200) // Xmit cfg
pokepreg($0112, $00C0) // Line ctrl
//
// Install etherip driver
//
puts("Found Uthernet I in slot #")
putc('0' + ((slot - $80) >> 4))
putln
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
//
// Install etherip driver
//
puts("Found Uthernet I in slot #")
putc('0' + ((slot - $80) >> 4))
putln
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
return modkeep
fin
fin

View File

@ -5,34 +5,7 @@
// layers, like the Uthernet
//
include "inc/cmdsys.plh"
//
// 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
word setDNS
word resolveIP
word setCallback
word setParam
end
//
// Module don't free memory
//
const modkeep = $2000
const modinitkeep = $4000
include "inc/inet.plh"
//
// Wiznet registers
//

View File

@ -9,33 +9,11 @@
// still todo: output base filename for Content-Disposition header
//
include "inc/cmdsys.plh"
//
// 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
word setDNS
word resolveIP
word setCallback
word setParam
end
include "inc/inet.plh"
include "inc/fileio.plh"
word socketHTTP
byte[65] prefix
byte perr
word filebuff, iobuff
byte fileInfo[12] = 0 // used for get_file_info()
byte hello = "Apple II Web Server - 12 Nov 15\n"
@ -60,73 +38,6 @@ byte httpEnd = "\n\r\n\r"
byte mimeTextHtml = "text/html"
byte mimeOctetStream = "application/octet-stream"
//
// 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
def get_eof(refnum)
byte params[5]
params.0 = 2
params.1 = refnum
params:2 = 0
params.4 = 0
syscall($D1, @params)
return params:2
end
def get_file_info(path)
fileInfo.0 = 10 // param count
fileInfo:1 = path // path name
perr = syscall($C4, @fileInfo)
return perr
end
//
// DEBUG
//
def putb(hexb)
@ -148,11 +59,11 @@ def dumpbytes(buf, len)
for i = 0 to len - 1
putb(buf->[i])
if i & 15 == 15
putln
else
putc(' ')
fin
if i & 15 == 15
putln
else
putc(' ')
fin
next
end
def dumpchars(buf, len)
@ -187,13 +98,13 @@ end
//
def sendFile(fd, socket, len)
while isuge(len, 1024)
read(fd, filebuff, 1024)
len = len - 1024
iNet:sendTCP(socket, filebuff, 1024)
fileio:read(fd, filebuff, 1024)
len = len - 1024
iNet:sendTCP(socket, filebuff, 1024)
loop
if len
read(fd, filebuff, len)
iNet:sendTCP(socket, filebuff, len)
fileio:read(fd, filebuff, len)
iNet:sendTCP(socket, filebuff, len)
fin
end
//
@ -211,78 +122,78 @@ def servHTTP(remip, remport, lclport, data, len, param)
if len > 0
//dumpchars(data, len)
//
// Better be 'GET'
//
// 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 // maximum ProDOS path
fin
len = len - 1
if len > 64
len = 64 // maximum ProDOS path
fin
for i = 4 to len // get ProDOS path from URL
if data->[i] <= ' '
data->3= i - 4
url = data + 3
if url->1 == '/'
if url->0 == 1
url = @defhtml // Is this a directory with no file given? Use index.html
else
url->1 = url->0 - 1
url = url + 1
fin
fin
strcat(@filename, @prefix, url)
puts("GET:"); puts(@filename);putln
//
// Get file info
//
//puts("getting file info "); // debug
get_file_info(@filename)
refnum = open(@filename, iobuff) // try to open this file with ProDOS
if refnum // file was opened OK
filelen = get_eof(refnum) // get length of file for Content-Length
lenstr = itos(@lenstr + 1, filelen) - (@lenstr + 1)
strcat(@okhdr, @httpOK, @httpContentLen)
strcat(@okhdr, @okhdr, @lenstr)
strcat(@okhdr, @okhdr, "\n\r")
//
// Content type header
//
if fileInfo.4 == $03 OR fileInfo.4 == $04
//
// this a text file
//
//puts(@mimeTextHtml) // debug
strcat(@okhdr, @okhdr, @httpContentType)
strcat(@okhdr, @okhdr, @mimeTextHtml)
else
//
// send as binary attachment
//
//puts(@mimeOctetStream) // debug
strcat(@okhdr, @okhdr, @httpContentType)
strcat(@okhdr, @okhdr, @mimeOctetStream)
strcat(@okhdr, @okhdr, "\n\r")
//
// and send filename too
//
strcat(@okhdr, @okhdr, @httpContentAttach)
// todo: get the base filename...
fin
strcat(@okhdr, @okhdr, @httpEnd)
//dumpchars(@okhdr + 1, okhdr) // debug
iNet:sendTCP(socketHTTP, @okhdr + 1, okhdr) // send HTTP response header to client
sendFile(refnum, socketHTTP, filelen) // send file data to client
close(refnum)
else // file couldn't be opened, so return 404 on this
puts("404 Not Found");putln // debug
iNet:sendTCP(socketHTTP, @httpNOTFOUND + 1, httpNOTFOUND)
fin // if refnum
break // return
fin
data->3 = i - 4
url = data + 3
if url->1 == '/'
if url->0 == 1
url = @defhtml // Is this a directory with no file given? Use index.html
else
url->1 = url->0 - 1
url = url + 1
fin
fin
strcat(@filename, @prefix, url)
puts("GET:"); puts(@filename);putln
//
// Get file info
//
//puts("getting file info "); // debug
fileio:getfileinfo(@filename)
refnum = fileio:open(@filename) // try to open this file with ProDOS
if refnum // file was opened OK
filelen = fileio:geteof(refnum) // get length of file for Content-Length
lenstr = itos(@lenstr + 1, filelen) - (@lenstr + 1)
strcat(@okhdr, @httpOK, @httpContentLen)
strcat(@okhdr, @okhdr, @lenstr)
strcat(@okhdr, @okhdr, "\n\r")
//
// Content type header
//
if fileInfo.4 == $03 OR fileInfo.4 == $04
//
// this a text file
//
//puts(@mimeTextHtml) // debug
strcat(@okhdr, @okhdr, @httpContentType)
strcat(@okhdr, @okhdr, @mimeTextHtml)
else
//
// send as binary attachment
//
//puts(@mimeOctetStream) // debug
strcat(@okhdr, @okhdr, @httpContentType)
strcat(@okhdr, @okhdr, @mimeOctetStream)
strcat(@okhdr, @okhdr, "\n\r")
//
// and send filename too
//
strcat(@okhdr, @okhdr, @httpContentAttach)
// todo: get the base filename...
fin
strcat(@okhdr, @okhdr, @httpEnd)
//dumpchars(@okhdr + 1, okhdr) // debug
iNet:sendTCP(socketHTTP, @okhdr + 1, okhdr) // send HTTP response header to client
sendFile(refnum, socketHTTP, filelen) // send file data to client
fileio:close(refnum)
else // file couldn't be opened, so return 404 on this
puts("404 Not Found");putln // debug
iNet:sendTCP(socketHTTP, @httpNOTFOUND + 1, httpNOTFOUND)
fin // if refnum
break // return
fin
next
else
iNet:sendTCP(socketHTTP, @httpBAD + 1, httpBAD)
fin
else
iNet:sendTCP(socketHTTP, @httpBAD + 1, httpBAD)
fin
fin
socketHTTP = iNet:closeTCP(socketHTTP)
end
@ -296,7 +207,7 @@ getpfx(@prefix)
// Alloc aligned file/io buffers
//
filebuff = heapallocalign(1024, 8, 0)
iobuff = heapallocalign(1024, 8, 0)
//iobuff = heapallocalign(1024, 8, 0)
//
// Service IP
//