401 lines
9.7 KiB
NASM
401 lines
9.7 KiB
NASM
FUNC_CNT SET -30
|
|
FUNCDEF MACRO
|
|
_LVO\1 EQU FUNC_CNT
|
|
FUNC_CNT SET FUNC_CNT-6
|
|
ENDM
|
|
|
|
INCDIR "AsmPro:Include/include_i/"
|
|
INCLUDE "exec/exec_lib.i"
|
|
INCLUDE "dos/dos_lvo.i"
|
|
INCLUDE "exec/libraries.i"
|
|
INCLUDE "exec/memory.i"
|
|
INCLUDE "dos/dos.i"
|
|
INCLUDE "socket_lvo.i"
|
|
|
|
PrintString MACRO
|
|
MOVE.L \1,D1
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOPutStr ; dos/PutStr
|
|
ENDM
|
|
|
|
OpenLibrary MACRO
|
|
MOVEQ \2,D0
|
|
MOVE.L \1,A1
|
|
MOVEA.L 4,A6
|
|
CALLLIB _LVOOpenLibrary ; exec/OpenLibrary
|
|
ENDM
|
|
|
|
ExitProgram MACRO
|
|
MOVEQ \1,D0
|
|
RTS
|
|
ENDM
|
|
|
|
DoCloseDOSLibrary MACRO
|
|
MOVEA.L DOSBase,A1
|
|
MOVEA.L 4,A6
|
|
CALLLIB _LVOCloseLibrary ; exec/CloseLibrary
|
|
ENDM
|
|
|
|
DoCloseBSDSocketLibrary MACRO
|
|
MOVEA.L BSDSocketBase,A1
|
|
MOVEA.L 4,A6
|
|
CALLLIB _LVOCloseLibrary ; exec/CloseLibrary
|
|
ENDM
|
|
|
|
DeallocateBuffer MACRO
|
|
MOVE.L ReadBuffer,A1
|
|
MOVE.L #READ_BUFFER_SIZE,D0
|
|
MOVEA.L 4,A6
|
|
CALLLIB _LVOFreeMem ; exec/FreeMem
|
|
ENDM
|
|
|
|
DoCloseSocket MACRO
|
|
MOVE.L SocketID,D0
|
|
MOVE.L BSDSocketBase,A6
|
|
CALLLIB _LVOCloseSocket ; bsdsocket/CloseSocket
|
|
ENDM
|
|
|
|
; our user message has a limit of this many characters
|
|
READ_BUFFER_SIZE EQU 1024
|
|
|
|
; bsdsocket library stuff
|
|
; ported from the various C include headers
|
|
SOCK_STREAM EQU 1
|
|
PF_INET EQU 2
|
|
AF_INET EQU PF_INET
|
|
IPPROTO_TCP EQU 6
|
|
|
|
len_sockaddr_in EQU 16
|
|
sockaddr_in_sin_len EQU 0
|
|
sockaddr_in_sin_family EQU 1
|
|
sockaddr_in_sin_port EQU 2
|
|
sockaddr_in_sin_addr EQU 4
|
|
|
|
Start:
|
|
OpenLibrary #DOSLibrary,#36
|
|
MOVE.L D0,DOSBase
|
|
TST.L D0
|
|
BNE OpenBSDSocketLibrary
|
|
|
|
; if this fails, we have bigger problems
|
|
MOVE.L #20,ExitCode
|
|
BRA Teardown
|
|
|
|
OpenBSDSocketLibrary:
|
|
OpenLibrary #BSDSocketLibrary,#4
|
|
MOVE.L D0,BSDSocketBase
|
|
TST.L D0
|
|
BNE ReserveBuffer
|
|
|
|
PrintString #UnableToOpenBSDSocketLibrary
|
|
|
|
; be sure to unwind everything we've opened so far
|
|
; i tried using this with codewatcher and i think there's
|
|
; something up with trying to read command line argument
|
|
; when run under codewatcher.
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ReserveBuffer:
|
|
MOVE.L #READ_BUFFER_SIZE,D0
|
|
; we don't care where the memory comes from
|
|
; nor should we!
|
|
MOVE.L #MEMF_CLEAR,D1
|
|
MOVEA.L 4,A6
|
|
CALLLIB _LVOAllocMem ; dos/AllocMem
|
|
MOVE.L D0,ReadBuffer
|
|
TST.L D0
|
|
BNE ReadIPAddress
|
|
|
|
PrintString #UnableToAllocateBuffer
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ReadIPAddress:
|
|
MOVE.L ReadBuffer,D1
|
|
MOVE.L #READ_BUFFER_SIZE,D2
|
|
MOVEQ #0,D3
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOReadItem ; dos/ReadItem
|
|
|
|
; fail on an error or a missing parameter
|
|
CMP.L #ITEM_ERROR,D0
|
|
BEQ NoIPAddress
|
|
CMP.L #ITEM_NOTHING,D0
|
|
BEQ NoIPAddress
|
|
|
|
BRA ParseIPAddress
|
|
|
|
NoIPAddress:
|
|
PrintString #UnableToReadArguments
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ParseIPAddress:
|
|
MOVE.L ReadBuffer,A0
|
|
MOVE.L BSDSocketBase,A6
|
|
CALLLIB _LVOinet_addr ; bsdsocket/inet_addr
|
|
MOVE.L D0,IPAddress
|
|
|
|
TST.L D0
|
|
BNE ReadPort
|
|
|
|
PrintString #UnableToParseIPAddress
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ReadPort:
|
|
MOVE.L ReadBuffer,D1
|
|
MOVE.L #READ_BUFFER_SIZE,D2
|
|
MOVEQ #0,D3
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOReadItem ; dos/ReadItem
|
|
|
|
; fail on an error or a missing parameter
|
|
CMP.L #ITEM_ERROR,D0
|
|
BEQ NoPort
|
|
CMP.L #ITEM_NOTHING,D0
|
|
BEQ NoPort
|
|
|
|
BRA ParsePort
|
|
|
|
NoPort:
|
|
PrintString #UnableToReadArguments
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
|
|
ParsePort:
|
|
; the Amiga library way to do atol()
|
|
MOVE.L ReadBuffer,D1
|
|
MOVE.L #PortLong,D2
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOStrToLong ; dos/StrToLong
|
|
|
|
CMP.L #-1,D0
|
|
BNE _ParsePort_Continue
|
|
|
|
PrintString #UnableToParsePort
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
_ParsePort_Continue:
|
|
MOVE.L PortLong,D0
|
|
|
|
; we could just crop the provided port at a word boundary,
|
|
; but let's be nice and tell the user they entered in a bad
|
|
; port number.
|
|
CMP.L #65536,D0
|
|
BLT ReadRemainingCommandLine
|
|
|
|
PrintString #PortOutOfRange
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ReadRemainingCommandLine:
|
|
; lop off the actual port number
|
|
MOVE.W D0,Port
|
|
|
|
; this is the Amiga equivalent of stdin?
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOInput ; dos/Input
|
|
MOVE.L D0,Stdin
|
|
|
|
MOVE.L ReadBuffer,FGetCLocation
|
|
MOVEQ #0,D2
|
|
|
|
_ReadRemainingCommandLine_Loop:
|
|
; loop until fgetc returns -1 or 10
|
|
MOVE.L Stdin,D1
|
|
MOVE.L DOSBase,A6
|
|
CALLLIB _LVOFGetC ; dos/FGetC
|
|
|
|
MOVE.L FGetCLocation,A0
|
|
CMP.L #-1,D0 ; end on EOF...
|
|
BEQ _ReadRemainingCommandLine_Finish
|
|
CMP.L #10,D0 ; or a 10, from you physically hitting enter in the CLI
|
|
BEQ _ReadRemainingCommandLine_Finish
|
|
|
|
MOVE.B D0,(A0)+
|
|
ADDQ #1,D2
|
|
MOVE.L A0,FGetCLocation
|
|
BRA _ReadRemainingCommandLine_Loop
|
|
|
|
_ReadRemainingCommandLine_Finish:
|
|
; add the chr(10) back, and end the string with a null
|
|
MOVE.B #10,(A0)+
|
|
MOVE.B #0,(A0)+
|
|
|
|
; we need to know how many characters total we read
|
|
ADDQ #2,D2
|
|
MOVE.L D2,ReadBufferLength
|
|
|
|
CreateSocket:
|
|
MOVE.L #PF_INET,D0
|
|
MOVE.L #SOCK_STREAM,D1
|
|
MOVE.L #IPPROTO_TCP,D2
|
|
MOVE.L BSDSocketBase,A6
|
|
CALLLIB _LVOsocket ; exec/socket
|
|
MOVE.L D0,SocketID
|
|
|
|
PrintIPAddress:
|
|
; exec/RawDoFmt is basically sprintf.
|
|
LEA IPAddrString,A0
|
|
|
|
; load up the printf arguments
|
|
LEA DoFmtBuffer,A1
|
|
MOVE.L IPAddress,(A1)+
|
|
MOVE.W Port,(A1)+
|
|
MOVE.L SocketID,(A1)+
|
|
LEA DoFmtBuffer,A1
|
|
|
|
LEA _StuffChar,A2
|
|
LEA PrintBuffer,A3
|
|
|
|
MOVE.L 4,A6
|
|
CALLLIB _LVORawDoFmt ; exec/RawDoFmt
|
|
|
|
PrintString #PrintBuffer
|
|
|
|
MOVE.L SocketID,D0
|
|
CMP.L #-1,D0
|
|
BNE ConnectSocket
|
|
|
|
PrintString #UnableToOpenSocket
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
ConnectSocket:
|
|
; populate sockaddr_in
|
|
LEA ConnectSockAddrIn,A0
|
|
MOVE.B #AF_INET,sockaddr_in_sin_family(A0)
|
|
MOVE.W Port,sockaddr_in_sin_port(A0)
|
|
MOVE.L IPAddress,sockaddr_in_sin_addr(A0)
|
|
|
|
MOVE.L SocketID,D0
|
|
MOVE.L #len_sockaddr_in,D1
|
|
MOVE.L BSDSocketBase,A6
|
|
CALLLIB _LVOconnect ; bsdsocket/connect
|
|
|
|
; a socket is connected if the response is 0
|
|
TST.L D0
|
|
BEQ SendData
|
|
|
|
PrintString #UnableToConnectSocket
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
SendData:
|
|
MOVE.L SocketID,D0
|
|
MOVE.L ReadBuffer,A0
|
|
MOVE.L ReadBufferLength,D1
|
|
MOVEQ #0,D2
|
|
MOVE.L BSDSocketBase,A6
|
|
CALLLIB _LVOsend ; bsdsocket/send
|
|
|
|
CMP.L #-1,D0
|
|
BNE CloseSocket
|
|
|
|
PrintString #UnableToSendData
|
|
|
|
MOVE.L #1,ExitCode
|
|
BRA Teardown
|
|
|
|
CloseSocket:
|
|
MOVE.L #0,ExitCode
|
|
|
|
; check all of the things we might have allocated and
|
|
; tear them down if we did, then return the appropriate exit code.
|
|
Teardown:
|
|
MOVE.L SocketID,D0
|
|
CMP.L #-1,D0
|
|
BEQ _Teardown_DeallocateBuffer
|
|
|
|
DoCloseSocket
|
|
_Teardown_DeallocateBuffer:
|
|
MOVE.L ReadBuffer,D0
|
|
BEQ _Teardown_CloseBSDSocketLibrary
|
|
|
|
DeallocateBuffer
|
|
_Teardown_CloseBSDSocketLibrary:
|
|
MOVE.L BSDSocketBase,D0
|
|
BEQ _Teardown_CloseDOSLibrary
|
|
|
|
DoCloseBSDSocketLibrary
|
|
_Teardown_CloseDOSLibrary:
|
|
MOVE.L DOSBase,D0
|
|
BEQ _Teardown_Exit
|
|
|
|
DoCloseDOSLibrary
|
|
_Teardown_Exit:
|
|
MOVEQ #0,D0
|
|
MOVE.L ExitCode,D0
|
|
RTS
|
|
|
|
; RawDoFmt helper
|
|
_StuffChar:
|
|
MOVE.B D0,(a3)+
|
|
RTS
|
|
|
|
|
|
; libraries we open
|
|
DOSBase DCB.L 1,0
|
|
BSDSocketBase DCB.L 1,0
|
|
|
|
; allocated memory
|
|
ReadBuffer DCB.L 1,0
|
|
ReadBufferLength DS.L 1
|
|
|
|
; return code for the program
|
|
ExitCode DS.L 1
|
|
|
|
; reading command line args
|
|
Stdin DS.L 1
|
|
|
|
; user parameters
|
|
IPAddress DS.L 1
|
|
Port DS.W 1
|
|
PortLong DS.L 1
|
|
|
|
; message to send
|
|
FGetCChar DS.L 1
|
|
FGetCLocation DS.L 1
|
|
|
|
; establishing a connection
|
|
SocketID DCB.L 1,-1
|
|
ConnectSockAddrIn DCB.B 16,0
|
|
|
|
; place to build a string for printing via RawDoFmt
|
|
PrintBuffer DS.B 100
|
|
|
|
; stack for accepting RawDoFmt arguments as values
|
|
DoFmtBuffer DS.B 32
|
|
|
|
DOSLibrary DC.B "dos.library",0
|
|
BSDSocketLibrary DC.B "bsdsocket.library",0
|
|
|
|
;FakeIP DC.B "1.2.3.4",0
|
|
;FakePort DC.B "1234",0
|
|
|
|
; user messages
|
|
UnableToOpenBSDSocketLibrary DC.B "Unable to open bsdsocket.library. Have you started a TCP stack?",10,0
|
|
UnableToAllocateBuffer DC.B "Unable to allocate buffer",10,0
|
|
UnableToReadArguments DC.B "client <ip address> <port> <message...>",10,0
|
|
UnableToParseIPAddress DC.B "Unable to parse IP Address",10,0
|
|
UnableToOpenSocket DC.B "Unable to open socket",10,0
|
|
UnableToConnectSocket DC.B "Unable to connect socket",10,0
|
|
UnableToSendData DC.B "Unable to send data",10,0
|
|
UnableToParsePort DC.B "Unable to parse port",10,0
|
|
PortOutOfRange DC.B "Port out of range (0-65535)",10,0
|
|
;Here DC.B "Here",10,0
|
|
IPAddrString DC.B "IP address is %8lx, port is %d, socket is %ld",10,0
|
|
;FGetCResult DC.B "%ld %ld %ld",10,0
|