-
Notifications
You must be signed in to change notification settings - Fork 68
A Simple NetCat Program
To help get started, we've provided a simple netcat 'nc' like program that echoes received data, and sends keypresses to the specified host.
The BASIC version uses the N: handler, and thus is very compact and easy to understand. It is described in detail in this video: https://www.youtube.com/watch?v=LxT6w9JHfKk
100 OPEN #1,12,3,"N1:TCP://BBS.FOZZTEXX.NET/":OPEN #2,4,0,"K:"
101 TRAP 140
110 IF PEEK(764)<>255 THEN GET #2,K:PUT #1,K:XIO 15,#1,12,3,"N:"
120 STATUS #1,A:BW=PEEK(747)*256+PEEK(746):IF BW=0 THEN 110
130 FOR M=1 TO BW:GET #1,C:PUT #16,C:NEXT M:GOTO 110
140 CLOSE #1:? "DISCONNECTED.":END
You can load a copy of it by loading "D:DUMBTERM.BAS" from the atari-apps.irata.online/Networking/n-handler/n-handler.atr via TNFS.
Modifying:
- Change the hostname on line 100.
- You can set the translation on line 100, 3 = CR/LF, 2 = LF, 1 = CR, 0 = NONE. Also change it on line 110.
The C version can be found here: https://github.com/FujiNetWIFI/fujinet-apps/tree/master/netcat/src
It can be compiled with CC65: http://cc65.github.io/
It shows:
- How to use SIO directly to talk to FujiNet https://github.com/FujiNetWIFI/fujinet-apps/blob/master/netcat/src/nio.c
- How to set the interrupt so that polls only occur when needed. https://github.com/FujiNetWIFI/fujinet-apps/blob/master/netcat/src/main.c#L66
https://github.com/FujiNetWIFI/fujinet-apps/tree/master/netcat-action
;
; #FujiNet Network I/O Library
; For ACTION!
;
; Author: Thomas Cherryhomes
; <thom.cherryhomes@gmail.com>
;
; These routines call the #Fujinet
; directly from SIO, and thus do
; not need the N: handler (NDEV)
;
MODULE
;
; PROCEED interrupt vars
;
CARD VPRCEDSAVE ; Save vector for vprced
CARD VPRCED = $0202 ; Proceed vector
BYTE PACTL = $D302 ; PIA Control for Proceed
BYTE trip ; Trip FLAG.
;
; DVSTAT (Status)
;
BYTE DVSTAT = $02EA ; PTR TO DVSTAT
BYTE EXTERR = $02ED ; DVSTAT+3
;
; DEVICE CONTROL BLOCK (DCB)
;
BYTE DDEVIC = $0300 ; Device #
BYTE DUNIT = $0301 ; Unit #
BYTE DCOMND = $0302 ; Command
BYTE DSTATS = $0303 ; <-> and error
CARD DBUF = $0304 ; buffer
BYTE DTIMLO = $0306 ; timeout secs
BYTE DUNUSE = $0307 ; reserved
CARD DBYT = $0308 ; pyld byte len
CARD DAUX = $030A ; daux1/daux2
BYTE DAUX1 = $030A ; daux1
BYTE DAUX2 = $030B ; daux2
;
; Interrupt handler
;
; A9 01 LDA #$01
; 8D XX XX STA trip
; 68 PLA
; 40 RTI
;
PROC ninterrupt_handler=*()
[$A9$01$8D trip $68$40]
;
; Enable Interrupt handler.
;
PROC nenableproc()
trip=0
VPRCEDSAVE=VPRCED
VPRCED=ninterrupt_handler
PACTL = PACTL % 1
RETURN
;
; Disable Interrupt handler.
;
PROC ndisableproc()
trip=0
VPRCED=VPRCEDSAVE
RETURN
;
; PROC to call SIO Vector (SIOV)
;
PROC siov=$E459()
;
; Get the unit number from devicespec
;
BYTE FUNC ngetunit(BYTE ARRAY ds)
BYTE unit=1
IF ds(2)=': THEN
unit=1
ELSEIF ds(3)=': THEN
unit=ds(2)-$30
ELSE
unit=1
FI
RETURN (unit)
;
; Get status of last NIO operation,
; Return in DVSTAT
;
; @param devicespec N: devicespec
;
PROC nstatus(BYTE ARRAY ds)
DDEVIC = $71
DUNIT = ngetunit(ds)
DCOMND = 'S ; STATUS
DSTATS = $40 ; Payload to Atari
DBUF = $02EA ; status buffer
DTIMLO = $1F ; 32 second timeout
DBYT = 4 ; 4 byte payload
DAUX1 = 0 ; R/W
DAUX2 = 0 ; translation
siov()
RETURN
;
; Return error of last NIO operation.
; If SIO error = 144, then a status
; is done, and the extended err is
; returned.
;
; @param devicespec N: devicespec
; @return error 1=successful
;
BYTE FUNC geterror(BYTE ARRAY ds)
BYTE errno
IF DSTATS=144 THEN
nstatus(ds)
errno=EXTERR
ELSE
errno=DSTATS
FI
RETURN (errno)
;
; Open the N: device pointed to by
; devicespec.
;
; @param devicespec N: devicespec
; @param trans - translation mode
; 0=NONE, 1=CR, 2=LF, 3=CR/LF
; @return error, 1=successful.
;
BYTE FUNC nopen(BYTE ARRAY ds, BYTE t)
DDEVIC = $71
DUNIT = ngetunit(ds)
DCOMND = 'O ; OPEN
DSTATS = $80 ; Write to fujinet
DBUF = ds ; send devicespec
DTIMLO = $1F ; 32 second timeout
DBYT = 256 ; 256 byte payload
DAUX1 = 12 ; R/W
DAUX2 = t ; translation
siov();
IF DSTATS=1 THEN
nenableproc()
FI
RETURN (geterror(ds))
;
; Close the N: device pointed to by
; devicespec.
;
; @param devicespec N: devicespec
; @return error, 1=successful.
;
BYTE FUNC nclose(BYTE ARRAY ds)
DDEVIC = $71
DUNIT = ngetunit(ds)
DCOMND = 'C ; CLOSE
DSTATS = $00 ; No Payload
DBUF = 0 ; send devicespec
DTIMLO = $1F ; 32 second timeout
DBYT = 0 ; No payload
DAUX1 = 0
DAUX2 = 0
siov();
ndisableproc()
RETURN (geterror(ds))
;
; Read len bytes from N: device
; pointed to by devicespec.
;
; @param devicespec N: devicespec
; @param buf The dest buffer
; @param len # of bytes to read
; @return error 1=successful
;
BYTE FUNC nread(BYTE ARRAY ds, BYTE ARRAY buf, CARD len)
DDEVIC = $71
DUNIT = ngetunit(ds)
DCOMND = 'R ; READ
DSTATS = $40 ; Atari<-Payload
DBUF = buf ; send devicespec
DTIMLO = $1F ; 32 second timeout
DBYT = len ; No payload
DAUX = len
siov();
RETURN (geterror(ds))
;
; Write len bytes to N: device
; pointed to by devicespec.
;
; @param devicespec N: devicespec
; @param buf The src buffer
; @param len # of bytes to read
; @return error 1=successful
;
BYTE FUNC nwrite(BYTE ARRAY ds, BYTE ARRAY buf, CARD len)
DDEVIC = $71
DUNIT = ngetunit(ds)
DCOMND = 'W ; WRITE
DSTATS = $80 ; Payload->FujiNet
DBUF = buf ; send devicespec
DTIMLO = $1F ; 32 second timeout
DBYT = len ; No payload
DAUX = len
siov();
RETURN (geterror(ds))
;
; A simple netcat program
; to show how to do basic network
; input and output.
;
; Author: Thomas Cherryhomes
; <thom.cherryhomes@gmail.com>
;
INCLUDE "D2:SYS.ACT" ; ACTION! Runtime!
INCLUDE "D2:NIO.ACT" ; NETWORK I/O
MODULE
CARD BYTESWAITING=$02EA ; # of bytes waiting
BYTE KP=$02FC ; Key pressed?
BYTE ARRAY devicespec(256) ; DeviceSpec
BYTE trans ; translation mode
BYTE localEcho ; local echo off/on?
BYTE running ; is program running?
BYTE ARRAY rxbuf(8192) ; receive buffer
DEFINE KEYBOARD_IOCB="2"
DEFINE TRUE="1"
DEFINE FALSE="0"
;
; Prompt for URL
;
PROC getURL()
PrintE("NETCAT--ENTER DEVICE SPEC?")
InputS(devicespec)
PutE()
PrintE("TRANS--0=NONE, 1=CR, 2=LF, 3=CR/LF?")
trans=InputB()
PutE()
PrintE("LOCAL ECHO--0=NO, 1=YES?")
localEcho=InputB()
PutE()
RETURN
;
; Handle nc output
;
PROC ncoutput()
BYTE ARRAY ch(1)
BYTE err
IF KP=$FF THEN
RETURN
FI
ch(0)=GetD(KEYBOARD_IOCB)
IF localEcho=1 THEN
Put(ch(0))
FI
err=nwrite(devicespec,ch,1)
IF err<>1 THEN
Print("Write Error: ")
PrintB(err)
running=FALSE
FI
RETURN
;
; Handle nc input
;
PROC ncinput()
BYTE err
CARD I
IF trip=0 THEN
RETURN
FI
nstatus()
IF EXTERR=136 THEN
PrintE("Disconnected.")
running=FALSE
RETURN
FI
IF BYTESWAITING=0 THEN
RETURN
FI
IF BYTESWAITING>8192 THEN
BYTESWAITING=8192
FI
; Do the network read.
err=nread(devicespec,rxbuf,BYTESWAITING)
IF err<>1 THEN
Print("Read Error: ")
PrintB(err)
running=FALSE
RETURN
FI
; Drain/display rx buffer
FOR I=0 TO BYTESWAITING-1
DO
Put(rxbuf(I))
OD
; Done, reset interrupt
trip=0
PACTL=PACTL%1
RETURN
;
; The main Netcat function
;
PROC nc()
BYTE err
err=nopen(deviceSpec,trans)
IF err<>1 THEN
Print("Open Error: ")
PrintB(err)
RETURN
FI
; flag program as running.
running=1
; Open keyboard
Open(KEYBOARD_IOCB,"K:",4,0)
WHILE running = TRUE
DO
ncoutput()
ncinput()
OD
PrintE("Bye.")
; Clean up
Close(KEYBOARD_IOCB) ; close kybd
nclose(deviceSpec)
RETURN
;
; Main entrypoint
;
PROC main()
getURL()
nc()
RETURN
N:TCP://BBS.FOZZTEXX.NET/ (trans 3, local echo N)
N:TCP://CAVEMUSH.COM:6116/ (trans 3 local echo Y)
N:TCP://SOUTHERNAMIS.COM/ (trans 0, local echo N)
Do you have an equivalent in other languages to put here, add it!
Copyright 2024 Contributors to the FujiNetWIFI project.
Join us on Discord: https://discord.gg/7MfFTvD
- Home
- What is FujiNet?
- The Definition of Done
- Board bring up for FujiNet Platform.IO code
- The Complete Linux CLI Guide
- The Complete macOS CLI Guide
- Development Env for Apps
- FujiNet-Development-Guidelines
- System Quickstarts
- FujiNet Flasher
- Setting up a TNFS Server
- FujiNet Configuration File: fnconfig.ini
- AppKey Registry - SIO Command $DC Open App Key
- CP-M Support
- BBS
- Official Hardware Versions
- Prototype Board Revisions
- FujiNet Development Guidelines
- Atari Programming
- Apple Programming
- C64 Programming
- ADAM Programming
- Testing Plan
- Hacker List
- FujiNet VirtualMachine