ip65 technical reference
File : ip65/udp.s
UDP (user datagram protocol) functions
functions
function | description |
---|
udp_add_listener | add a udp listener
inputs:
udp_callback: vector to call when udp packet arrives on specified port
AX: set to udp port to listen on
outputs:
carry flag set if too may listeners already installed, clear otherwise
|
udp_init | initialize udp
inputs: none
outputs: none
|
udp_process | process incoming udp packet
inputs:
eth_inp: should contain an ethernet frame encapsulating an inbound udp packet
outputs:
carry flag set if any error occured (including if no handler for specified port
was found)
carry flag clear if no error
if handler was found, an outbound message may be created, overwriting eth_outp
|
udp_remove_listener | remove an udp listener
inputs:
AX = port to stop listening on
outputs:
carry flag clear of handler found and removed
carry flag set if handler for specified port not found
|
udp_send | send udp packet
inputs:
udp_send_dest: destination ip address (4 bytes)
udp_send_dest_port: destination port (2 bytes)
udp_send_src_port: source port (2 bytes)
udp_send_len: length of data to send (exclusive of any headers)
AX: pointer to buffer containing data to be sent
outputs:
carry flag is set if an error occured, clear otherwise
|
variables
variable | description | size (bytes) |
---|
udp_callback | vector to routine to be called when a udp packet arrives
| 2 |
udp_send_dest | set to ip address that udp packet will be sent to
| 4 |
udp_send_dest_port | set to port that udp packet will be sent to
| 2 |
udp_send_len | set to length of data to be sent in udp packet (excluding ethernet,ip & udp headers)
| 2 |
udp_send_src_port | set to port that udp packet will be sent from
| 2 |
constants
constants | description | value |
---|
udp_cksum | offset of checksum field in udp packet
| 6 |
udp_data | offset of data in udp packet
| 8 |
udp_dest_port | offset of destination port field in udp packet
| 2 |
udp_inp | pointer to udp packet inside inbound ethernet frame
| ip_inp + ip_data |
udp_len | offset of length field in udp packet
| 4 |
udp_outp | pointer to udp packet inside outbound ethernet frame
| ip_outp + ip_data |
udp_src_port | offset of source port field in udp packet
| 0 |
implementation
;UDP (user datagram protocol) functions
.include "../inc/common.i"
.ifndef KPR_API_VERSION_NUMBER
.define EQU =
.include "../inc/kipper_constants.i"
.endif
;.import dbg_dump_udp_header
.import ip65_error
.export udp_init
.export udp_process
.export udp_add_listener
.export udp_remove_listener
.export udp_send
.export udp_callback
.export udp_inp
.export udp_outp
.exportzp udp_src_port
.exportzp udp_dest_port
.exportzp udp_len
.exportzp udp_cksum
.exportzp udp_data
.export udp_send_dest
.export udp_send_src_port
.export udp_send_dest_port
.export udp_send_len
.import ip_calc_cksum
.import ip_send
.import ip_create_packet
.import ip_inp
.import ip_outp
.importzp ip_cksum_ptr
.importzp ip_header_cksum
.importzp ip_src
.importzp ip_dest
.importzp ip_data
.importzp ip_proto
.importzp ip_proto_udp
.importzp ip_id
.importzp ip_len
.import copymem
.importzp copy_src
.importzp copy_dest
.import cfg_ip
.data
udp_cbtmp: jmp $ffff ; temporary vector - gets filled in later
.bss
; argument for udp_add_listener
udp_callback: .res 2 ;vector to routine to be called when a udp packet arrives
; arguments for udp_send
udp_send_dest: .res 4 ;set to ip address that udp packet will be sent to
udp_send_src_port: .res 2 ;set to port that udp packet will be sent from
udp_send_dest_port: .res 2 ;set to port that udp packet will be sent to
udp_send_len: .res 2 ;set to length of data to be sent in udp packet (excluding ethernet,ip & udp headers)
; udp listener callbacks
udp_cbmax = 4
udp_cbveclo: .res udp_cbmax ; table of listener vectors (lsb)
udp_cbvechi: .res udp_cbmax ; table of listener vectors (msb)
udp_cbportlo: .res udp_cbmax ; table of ports (lsb)
udp_cbporthi: .res udp_cbmax ; table of ports (msb)
udp_cbcount: .res 1 ; number of active listeners
; udp packet offsets
udp_inp = ip_inp + ip_data ;pointer to udp packet inside inbound ethernet frame
udp_outp = ip_outp + ip_data ;pointer to udp packet inside outbound ethernet frame
udp_src_port = 0 ;offset of source port field in udp packet
udp_dest_port = 2 ;offset of destination port field in udp packet
udp_len = 4 ;offset of length field in udp packet
udp_cksum = 6 ;offset of checksum field in udp packet
udp_data = 8 ;offset of data in udp packet
; virtual header
udp_vh = udp_outp - 12
udp_vh_src = 0
udp_vh_dest = 4
udp_vh_zero = 8
udp_vh_proto = 9
udp_vh_len = 10
; temp for port comparison
port: .res 2
.code
; initialize udp
; inputs: none
; outputs: none
udp_init:
lda #0
sta udp_cbcount
rts
;process incoming udp packet
;inputs:
; eth_inp: should contain an ethernet frame encapsulating an inbound udp packet
;outputs:
; carry flag set if any error occured (including if no handler for specified port
; was found)
; carry flag clear if no error
; if handler was found, an outbound message may be created, overwriting eth_outp
udp_process:
lda udp_cbcount ; any installed udp listeners?
beq @drop
tax ; check ports
dex
@checkport:
lda udp_cbportlo,x
cmp udp_inp + udp_dest_port + 1
bne :+
lda udp_cbporthi,x
cmp udp_inp + udp_dest_port
beq @handle
: dex
bpl @checkport
@drop:
sec
rts
@handle:
lda udp_cbveclo,x ; copy vector
sta udp_cbtmp + 1
lda udp_cbvechi,x
sta udp_cbtmp + 2
jsr udp_cbtmp ; call listener
clc
rts
;add a udp listener
;inputs:
; udp_callback: vector to call when udp packet arrives on specified port
; AX: set to udp port to listen on
;outputs:
; carry flag set if too may listeners already installed, clear otherwise
udp_add_listener:
sta port
stx port + 1
ldy udp_cbcount ; any listeners at all?
beq @add
cpy #udp_cbmax ; max?
beq @full
ldy #0
@check:
lda udp_cbportlo,y ; check if port is already handled
cmp port
bne :+
lda udp_cbporthi,y
cmp port + 1
beq @busy
: iny
cpy udp_cbcount
bne @check
@add:
inc udp_cbcount ; increase counter
sta udp_cbportlo,y ; add port
txa
sta udp_cbporthi,y ; add port
lda udp_callback ; and vector
sta udp_cbveclo,y
lda udp_callback + 1
sta udp_cbvechi,y
clc
rts
@full:
@busy:
lda #KPR_ERROR_LISTENER_NOT_AVAILABLE
sta ip65_error
sec
sec
rts
; remove an udp listener
; inputs:
; AX = port to stop listening on
; outputs:
; carry flag clear of handler found and removed
; carry flag set if handler for specified port not found
udp_remove_listener:
sta port
stx port + 1
ldy udp_cbcount ; any listeners installed?
beq @notfound
dey
@check:
lda udp_cbportlo,y ; check if port is handled
cmp port
bne :+
lda udp_cbporthi,y
cmp port + 1
beq @remove
: dey
bpl @check
@notfound:
sec
rts
@remove:
tya ; number of listeners below
eor #$ff
clc
adc udp_cbcount
beq @done
@move:
tax ; number of items to move
: lda udp_cbportlo + 1,y ; move ports
sta udp_cbportlo,y
lda udp_cbporthi + 1,y
sta udp_cbporthi,y
lda udp_cbveclo + 1,y ; move vectors
sta udp_cbveclo,y
lda udp_cbvechi + 1,y
sta udp_cbvechi,y
iny
dex
bne :-
@done:
dec udp_cbcount ; decrement counter
clc
rts
;send udp packet
;inputs:
; udp_send_dest: destination ip address (4 bytes)
; udp_send_dest_port: destination port (2 bytes)
; udp_send_src_port: source port (2 bytes)
; udp_send_len: length of data to send (exclusive of any headers)
; AX: pointer to buffer containing data to be sent
;outputs:
; carry flag is set if an error occured, clear otherwise
udp_send:
stax copy_src ; copy data to output buffer
ldax #udp_outp + udp_data
stax copy_dest
ldax udp_send_len
jsr copymem
ldx #3 ; copy virtual header addresses
: lda udp_send_dest,x
sta udp_vh + udp_vh_dest,x ; set virtual header destination
lda cfg_ip,x
sta udp_vh + udp_vh_src,x ; set virtual header source
dex
bpl :-
lda udp_send_src_port ; copy source port
sta udp_outp + udp_src_port + 1
lda udp_send_src_port + 1
sta udp_outp + udp_src_port
lda udp_send_dest_port ; copy destination port
sta udp_outp + udp_dest_port + 1
lda udp_send_dest_port + 1
sta udp_outp + udp_dest_port
lda #ip_proto_udp
sta udp_vh + udp_vh_proto
lda #0 ; clear checksum
sta udp_outp + udp_cksum
sta udp_outp + udp_cksum + 1
sta udp_vh + udp_vh_zero ; clear virtual header zero byte
ldax #udp_vh ; checksum pointer to virtual header
stax ip_cksum_ptr
lda udp_send_len ; copy length + 8
clc
adc #8
sta udp_outp + udp_len + 1 ; lsb for udp header
sta udp_vh + udp_vh_len + 1 ; lsb for virtual header
tay
lda udp_send_len + 1
adc #0
sta udp_outp + udp_len ; msb for udp header
sta udp_vh + udp_vh_len ; msb for virtual header
tax ; length to A/X
tya
clc ; add 12 bytes for virtual header
adc #12
bcc :+
inx
:
jsr ip_calc_cksum ; calculate checksum
stax udp_outp + udp_cksum
ldx #3 ; copy addresses
: lda udp_send_dest,x
sta ip_outp + ip_dest,x ; set ip destination address
dex
bpl :-
jsr ip_create_packet ; create ip packet template
lda udp_outp + udp_len + 1 ; ip len = udp len + 20
ldx udp_outp + udp_len
clc
adc #20
bcc :+
inx
: sta ip_outp + ip_len + 1 ; set length
stx ip_outp + ip_len
ldax #$1234 ; set ID
stax ip_outp + ip_id
lda #ip_proto_udp ; set protocol
sta ip_outp + ip_proto
;jsr dbg_dump_udp_header
jmp ip_send ; send packet, sec on error
;-- LICENSE FOR udp.s --
; The contents of this file are subject to the Mozilla Public License
; Version 1.1 (the "License"); you may not use this file except in
; compliance with the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS"
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
; License for the specific language governing rights and limitations
; under the License.
;
; The Original Code is ip65.
;
; The Initial Developer of the Original Code is Per Olofsson,
; MagerValp@gmail.com.
; Portions created by the Initial Developer are Copyright (C) 2009
; Per Olofsson. All Rights Reserved.
; -- LICENSE END --