mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-11-12 14:04:34 +00:00
git-svn-id: http://svn.code.sf.net/p/netboot65/code@159 93682198-c243-4bdb-bd91-e943c89aac3b
This commit is contained in:
parent
263566690b
commit
7980547871
@ -93,7 +93,7 @@ found_nb65_signature
|
||||
nb65call #NB65_INPUT_HOSTNAME
|
||||
bcc .host_entered
|
||||
;if no host entered, then bail.
|
||||
jmp reset_after_keypress
|
||||
rts
|
||||
.host_entered
|
||||
stax nb65_param_buffer
|
||||
print_cr
|
||||
@ -133,16 +133,30 @@ found_nb65_signature
|
||||
beq .petscii_mode
|
||||
jmp .char_mode_input
|
||||
.ascii_mode
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
|
||||
lda #0
|
||||
jmp .character_mode_set
|
||||
.petscii_mode
|
||||
lda #142
|
||||
jsr print_a ;switch to upper case
|
||||
lda #1
|
||||
.character_mode_set
|
||||
sta character_mode
|
||||
|
||||
lda #147 ; 'CLR/HOME'
|
||||
jsr print_a
|
||||
ldaxi #tcp_callback
|
||||
stax nb65_param_buffer+NB65_TCP_CALLBACK
|
||||
print #connecting
|
||||
lda character_mode
|
||||
beq .a_mode
|
||||
print #petscii
|
||||
jmp .c_mode
|
||||
.a_mode
|
||||
print #ascii
|
||||
.c_mode
|
||||
print #mode
|
||||
ldaxi #nb65_param_buffer
|
||||
nb65call #NB65_TCP_CONNECT
|
||||
bcc .connect_ok
|
||||
@ -165,25 +179,41 @@ found_nb65_signature
|
||||
;is there anything in the input buffer?
|
||||
lda $c6 ;NDX - chars in keyboard buffer
|
||||
beq .main_polling_loop
|
||||
tay
|
||||
dey
|
||||
ldx #0
|
||||
stax nb65_param_buffer+NB65_TCP_PAYLOAD_LENGTH
|
||||
ldaxi #output_buffer
|
||||
stax nb65_param_buffer+NB65_TCP_PAYLOAD_POINTER
|
||||
.copy_char_from_KEYD
|
||||
lda $277,y ;read direct from keyboard buffer
|
||||
tax
|
||||
lda #0
|
||||
sta nb65_param_buffer+NB65_TCP_PAYLOAD_LENGTH
|
||||
sta nb65_param_buffer+NB65_TCP_PAYLOAD_LENGTH+1
|
||||
.get_next_char
|
||||
jsr $ffe4 ;getkey - 0 means no input
|
||||
tax
|
||||
beq .no_more_input
|
||||
cmp #$03 ;RUN/STOP
|
||||
bne .not_runstop
|
||||
lda #0
|
||||
sta $cb ;overwrite "current key pressed" else it's seen by the tcp stack and the close aborts
|
||||
|
||||
print #closing_connection
|
||||
nb65call #NB65_TCP_CLOSE_CONNECTION
|
||||
bcs .error_on_disconnect
|
||||
print #disconnected
|
||||
jmp .get_hostname
|
||||
.error_on_disconnect
|
||||
jsr print_errorcode
|
||||
print_cr
|
||||
jmp .get_hostname
|
||||
.not_runstop
|
||||
lda character_mode
|
||||
bne .no_conversion_required
|
||||
lda petscii_to_ascii_table,x
|
||||
tax
|
||||
.no_conversion_required
|
||||
.no_conversion_required
|
||||
txa
|
||||
ldy nb65_param_buffer+NB65_TCP_PAYLOAD_LENGTH
|
||||
sta output_buffer,y
|
||||
dey
|
||||
bne .copy_char_from_KEYD
|
||||
sty $c6 ;set length of keyboard buffer back to 0
|
||||
inc nb65_param_buffer+NB65_TCP_PAYLOAD_LENGTH
|
||||
jmp .get_next_char
|
||||
.no_more_input
|
||||
ldaxi #output_buffer
|
||||
stax nb65_param_buffer+NB65_TCP_PAYLOAD_POINTER
|
||||
ldaxi #nb65_param_buffer
|
||||
nb65call #NB65_SEND_TCP_PACKET
|
||||
bcs .error_on_send
|
||||
@ -209,18 +239,33 @@ tcp_callback
|
||||
|
||||
ldax nb65_param_buffer+NB65_PAYLOAD_POINTER
|
||||
stax temp_ptr
|
||||
ldx nb65_param_buffer+NB65_PAYLOAD_LENGTH ;assumes length of inbound data is < 255
|
||||
lda nb65_param_buffer+NB65_PAYLOAD_LENGTH ;assumes length of inbound data is < 255
|
||||
sta buffer_length
|
||||
dec buffer_length
|
||||
ldy #0
|
||||
.next_byte
|
||||
; tya
|
||||
; pha
|
||||
; lda (temp_ptr),y
|
||||
; nb65call #NB65_PRINT_HEX
|
||||
; pla
|
||||
; tay
|
||||
lda (temp_ptr),y
|
||||
tax
|
||||
lda character_mode
|
||||
bne .no_conversion_req
|
||||
lda ascii_to_petscii_table,x
|
||||
tax
|
||||
.no_conversion_req
|
||||
tya
|
||||
pha
|
||||
txa
|
||||
jsr print_a
|
||||
pla
|
||||
tay
|
||||
iny
|
||||
dex
|
||||
bpl .next_byte
|
||||
|
||||
print_cr
|
||||
|
||||
|
||||
dec buffer_length
|
||||
bpl .next_byte
|
||||
rts
|
||||
|
||||
;look for NB65 signature at location pointed at by AX
|
||||
@ -280,11 +325,16 @@ nb65_signature dc.b $4E,$42,$36,$35 ; "NB65" - API signature
|
||||
initializing dc.b "INITIALIZING ",13,0
|
||||
error_code dc.b "ERROR CODE: $",0
|
||||
resolving dc.b "RESOLVING ",0
|
||||
connecting dc.b "CONNECTING ",0
|
||||
closing_connection dc.b "CLOSING CONNECTION",13,0
|
||||
connecting dc.b "CONNECTING IN ",0
|
||||
|
||||
ascii dc.b "ASCII",0
|
||||
petscii dc.b "PETSCII",0
|
||||
mode dc.b " MODE",13,0
|
||||
disconnected dc.b 13,"CONNECTION CLOSED",13,0
|
||||
remote_host dc.b "REMOTE HOST - BLANK TO QUIT",13,": ",0
|
||||
remote_port dc.b "REMOTE PORT - BLANK FOR TELNET DEFAULT",13,": ",0
|
||||
char_mode_prompt dc.b "CHARACTER MODE - A=ASCII, P=PETSCII",13,": ",0
|
||||
char_mode_prompt dc.b "CHARACTER MODE - A=ASCII, P=PETSCII",13,0
|
||||
press_a_key_to_continue dc.b "PRESS A KEY TO CONTINUE",13,0
|
||||
failed dc.b "FAILED ", 0
|
||||
ok dc.b "OK ", 0
|
||||
@ -329,5 +379,8 @@ petscii_to_ascii_table
|
||||
;variables
|
||||
connection_closed ds.b 1
|
||||
character_mode ds.b 1
|
||||
buffer_offset: ds.b 1
|
||||
nb65_param_buffer DS.B $20
|
||||
buffer_length: ds.b 2
|
||||
|
||||
output_buffer: DS.B $100
|
||||
|
@ -32,7 +32,6 @@
|
||||
.import ip65_error
|
||||
.import cls
|
||||
.import get_filtered_input
|
||||
.import filter_text
|
||||
.import filter_dns
|
||||
|
||||
.segment "IP65ZP" : zeropage
|
||||
@ -86,7 +85,7 @@ RESOURCE_HISTORY_ENTRIES=8
|
||||
resource_history:
|
||||
.res $100*RESOURCE_HISTORY_ENTRIES
|
||||
|
||||
input_buffer:
|
||||
scratch_buffer:
|
||||
.res 16000
|
||||
|
||||
.code
|
||||
@ -94,7 +93,7 @@ input_buffer:
|
||||
;display whatever is in the buffer either as plain text or gopher text
|
||||
|
||||
display_resource_in_buffer:
|
||||
ldax #input_buffer
|
||||
ldax #scratch_buffer
|
||||
stax get_next_byte+1
|
||||
|
||||
lda #0
|
||||
@ -449,7 +448,7 @@ show_history:
|
||||
|
||||
;load the 'current_resource' into the buffer
|
||||
load_resource_into_buffer:
|
||||
ldax #input_buffer
|
||||
ldax #scratch_buffer
|
||||
stax tcp_buffer_ptr
|
||||
ldax #resolving
|
||||
jsr print
|
||||
@ -603,6 +602,7 @@ print_resource_description:
|
||||
prompt_for_gopher_resource:
|
||||
ldax #gopher_server
|
||||
jsr print
|
||||
ldy #40
|
||||
ldax #filter_dns
|
||||
jsr get_filtered_input
|
||||
bcs @no_server_entered
|
||||
|
@ -483,6 +483,14 @@ ip_configured:
|
||||
|
||||
:
|
||||
|
||||
|
||||
.import tcp_close
|
||||
cpy #NB65_TCP_CLOSE_CONNECTION
|
||||
bne :+
|
||||
jmp tcp_close
|
||||
:
|
||||
|
||||
|
||||
.import filter_dns
|
||||
.import get_filtered_input
|
||||
.import filter_number
|
||||
|
@ -23,6 +23,7 @@ MAX_TCP_PACKETS_SENT=8 ;timeout after sending 8 messages will be about 7 sec
|
||||
.export tcp_connect_ip
|
||||
.export tcp_send_data_len
|
||||
.export tcp_send
|
||||
.export tcp_close
|
||||
|
||||
.export tcp_inbound_data_ptr
|
||||
.export tcp_inbound_data_length
|
||||
@ -121,7 +122,7 @@ tcp_send_data_ptr: .res 2
|
||||
tcp_send_data_len: .res 2 ;length (in bytes) of data to be sent over tcp connection
|
||||
tcp_callback: .res 2 ;vector to routine to be called when data is received over tcp connection
|
||||
tcp_flags: .res 1
|
||||
|
||||
tcp_fin_sent: .res 1
|
||||
|
||||
tcp_inbound_data_ptr: .res 2 ;pointer to data just recieved over tcp connection
|
||||
tcp_inbound_data_length: .res 2 ;length of data just received over tcp connection
|
||||
@ -169,7 +170,8 @@ tcp_connect:
|
||||
sta tcp_state
|
||||
lda #0 ;reset the "packet sent" counter
|
||||
sta tcp_packet_sent_count
|
||||
|
||||
sta tcp_fin_sent
|
||||
|
||||
;set the low word of seq number to $0000, high word to something random
|
||||
sta tcp_connect_sequence_number
|
||||
sta tcp_connect_sequence_number+1
|
||||
@ -224,7 +226,6 @@ tcp_connect:
|
||||
dec tcp_loop_count
|
||||
bne @outer_delay_loop
|
||||
|
||||
@break_polling_loop:
|
||||
|
||||
inc tcp_packet_sent_count
|
||||
lda tcp_packet_sent_count
|
||||
@ -257,6 +258,80 @@ tcp_connect:
|
||||
clc
|
||||
rts
|
||||
|
||||
tcp_close:
|
||||
;close the current connection
|
||||
;inputs:
|
||||
; none
|
||||
;outputs:
|
||||
; carry flag is set if an error occured, clear otherwise
|
||||
|
||||
;increment the expected sequence number for the SYN we are about to send
|
||||
ldax #tcp_connect_expected_ack_number
|
||||
stax acc32
|
||||
ldax #1
|
||||
sta tcp_fin_sent
|
||||
jsr add_16_32
|
||||
|
||||
|
||||
@send_fin_loop:
|
||||
lda #tcp_flag_FIN+tcp_flag_ACK
|
||||
sta tcp_flags
|
||||
ldax #0
|
||||
stax tcp_data_len
|
||||
ldx #3 ;
|
||||
: lda tcp_connect_ip,x
|
||||
sta tcp_remote_ip,x
|
||||
lda tcp_connect_ack_number,x
|
||||
sta tcp_ack_number,x
|
||||
lda tcp_connect_sequence_number,x
|
||||
sta tcp_sequence_number,x
|
||||
dex
|
||||
bpl :-
|
||||
ldax tcp_connect_local_port
|
||||
stax tcp_local_port
|
||||
ldax tcp_connect_remote_port
|
||||
stax tcp_remote_port
|
||||
|
||||
jsr tcp_send_packet
|
||||
|
||||
lda tcp_packet_sent_count
|
||||
adc #1
|
||||
sta tcp_loop_count ;we wait a bit longer between each resend
|
||||
@outer_delay_loop:
|
||||
jsr timer_read
|
||||
stx tcp_timer ;we only care about the high byte
|
||||
@inner_delay_loop:
|
||||
jsr ip65_process
|
||||
lda tcp_state
|
||||
cmp #tcp_cxn_state_established
|
||||
bne @connection_closed
|
||||
|
||||
jsr timer_read
|
||||
cpx tcp_timer ;this will tick over after about 1/4 of a second
|
||||
beq @inner_delay_loop
|
||||
|
||||
dec tcp_loop_count
|
||||
bne @outer_delay_loop
|
||||
|
||||
inc tcp_packet_sent_count
|
||||
lda tcp_packet_sent_count
|
||||
cmp #MAX_TCP_PACKETS_SENT-1
|
||||
bpl @too_many_messages_sent
|
||||
jmp @send_fin_loop
|
||||
@connection_closed:
|
||||
clc
|
||||
rts
|
||||
@too_many_messages_sent:
|
||||
@failed:
|
||||
lda #tcp_cxn_state_closed
|
||||
sta tcp_state
|
||||
lda #NB65_ERROR_TIMEOUT_ON_RECEIVE
|
||||
sta ip65_error
|
||||
sec ;signal an error
|
||||
rts
|
||||
|
||||
|
||||
tcp_send:
|
||||
;send tcp data
|
||||
;inputs:
|
||||
; tcp connection should already be opened
|
||||
@ -264,8 +339,8 @@ tcp_connect:
|
||||
; AX: pointer to buffer containing data to be sent
|
||||
;outputs:
|
||||
; carry flag is set if an error occured, clear otherwise
|
||||
tcp_send:
|
||||
stax tcp_send_data_ptr
|
||||
|
||||
stax tcp_send_data_ptr
|
||||
lda tcp_state
|
||||
cmp #tcp_cxn_state_established
|
||||
beq @connection_established
|
||||
@ -273,6 +348,8 @@ tcp_send:
|
||||
sta ip65_error
|
||||
sec
|
||||
rts
|
||||
lda #0 ;reset the "packet sent" counter
|
||||
sta tcp_packet_sent_count
|
||||
|
||||
@connection_established:
|
||||
;increment the expected sequence number
|
||||
@ -337,7 +414,6 @@ tcp_send:
|
||||
dec tcp_loop_count
|
||||
bne @outer_delay_loop
|
||||
|
||||
@break_polling_loop:
|
||||
|
||||
inc tcp_packet_sent_count
|
||||
lda tcp_packet_sent_count
|
||||
@ -716,24 +792,41 @@ tcp_process:
|
||||
sta tcp_inbound_data_length+1
|
||||
jsr jmp_to_callback ;let the caller see the connection has closed
|
||||
|
||||
; move ack ptr along
|
||||
ldax #tcp_connect_ack_number
|
||||
stax acc32
|
||||
ldax #$01
|
||||
jsr add_16_32
|
||||
|
||||
lda #tcp_cxn_state_closed
|
||||
sta tcp_state
|
||||
|
||||
;send a FIN/ACK
|
||||
; jsr @send_ack
|
||||
; move ack ptr along for the inbound FIN
|
||||
ldax #tcp_connect_ack_number
|
||||
stax acc32
|
||||
ldax #$01
|
||||
sta tcp_fin_sent
|
||||
jsr add_16_32
|
||||
|
||||
;send a FIN
|
||||
;if we've already sent a FIN then just send back an ACK
|
||||
lda tcp_fin_sent
|
||||
beq @send_fin_ack
|
||||
;if we get here, we've sent a FIN, and just received an inbound FIN.
|
||||
;when we sent the fin, we didn't update the sequence number, since
|
||||
;we want to use the old sequence on every resend of that FIN
|
||||
;now that our fin has been ACKed, we need to inc the sequence number
|
||||
;and then send another ACK.
|
||||
|
||||
ldax #tcp_connect_sequence_number
|
||||
stax acc32
|
||||
ldax #$0001 ;
|
||||
jsr add_16_32 ;increment the SEQ counter by 1, for the FIN we have been sending
|
||||
|
||||
lda #tcp_flag_ACK
|
||||
jmp @send_packet
|
||||
|
||||
@send_fin_ack:
|
||||
|
||||
lda #tcp_flag_FIN+tcp_flag_ACK
|
||||
|
||||
jsr @send_packet
|
||||
jmp @send_packet
|
||||
|
||||
rts
|
||||
|
||||
@not_fin:
|
||||
|
||||
|
@ -27,10 +27,10 @@ all: nb65_std_cart.bin nb65_tcp_cart.bin
|
||||
nb65_c64_ram.o: nb65_c64.s $(INCFILES)
|
||||
$(AS) -DBANKSWITCH_SUPPORT=0 $(AFLAGS) -o $@ $<
|
||||
|
||||
nb65_std_cart.o: nb65_c64.s $(INCFILES)
|
||||
nb65_std_cart.o: nb65_c64.s $(INCFILES)
|
||||
$(AS) -DBANKSWITCH_SUPPORT=1 $(AFLAGS) -o $@ $<
|
||||
|
||||
nb65_tcp_cart.o: nb65_c64.s $(INCFILES)
|
||||
nb65_tcp_cart.o: nb65_c64.s $(INCFILES) ../inc/gopher.i ../inc/telnet.i
|
||||
$(AS) -DBANKSWITCH_SUPPORT=3 $(AFLAGS) -o $@ $<
|
||||
|
||||
nb65_rrnet.o: nb65_c64.s $(INCFILES)
|
||||
|
@ -47,6 +47,7 @@
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
.include "../inc/char_conv.i"
|
||||
.include "../inc/gopher.i"
|
||||
.include "../inc/telnet.i"
|
||||
.endif
|
||||
.import cls
|
||||
.import beep
|
||||
@ -215,6 +216,7 @@ main_menu:
|
||||
jsr print_cr
|
||||
|
||||
@get_key:
|
||||
jsr ip65_process
|
||||
jsr get_key
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_tftp
|
||||
@ -224,11 +226,7 @@ main_menu:
|
||||
cmp #KEYCODE_F3
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
bne @not_f3
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
jsr prompt_for_gopher_resource ;only returns if no server was entered.
|
||||
jmp exit_gopher
|
||||
jmp net_apps_menu
|
||||
.else
|
||||
beq @exit_to_basic
|
||||
.endif
|
||||
@ -257,7 +255,8 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_ip_config
|
||||
jsr print_cr
|
||||
@get_key_config_menu:
|
||||
@get_key_config_menu:
|
||||
jsr ip65_process
|
||||
jsr get_key
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_ip
|
||||
@ -267,6 +266,7 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_ip_address_entered
|
||||
jsr parse_dotted_quad
|
||||
@ -291,6 +291,7 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_netmask_entered
|
||||
jsr parse_dotted_quad
|
||||
@ -315,6 +316,7 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_gateway_entered
|
||||
jsr parse_dotted_quad
|
||||
@ -341,6 +343,7 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_ip
|
||||
ldy #20
|
||||
jsr get_filtered_input
|
||||
bcs @no_dns_server_entered
|
||||
jsr parse_dotted_quad
|
||||
@ -366,6 +369,7 @@ main_menu:
|
||||
jsr print
|
||||
jsr print_cr
|
||||
ldax #filter_dns
|
||||
ldy #40
|
||||
jsr get_filtered_input
|
||||
bcs @no_server_entered
|
||||
stax nb65_param_buffer
|
||||
@ -533,6 +537,39 @@ exit_cart_via_ax:
|
||||
stx call_downloaded_prg+2
|
||||
jmp exit_cart
|
||||
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
net_apps_menu:
|
||||
jsr cls
|
||||
ldax #netboot65_msg
|
||||
jsr print
|
||||
ldax #net_apps_menu_msg
|
||||
jsr print
|
||||
@get_key:
|
||||
jsr ip65_process
|
||||
jsr get_key
|
||||
cmp #KEYCODE_F1
|
||||
bne @not_telnet
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
jmp telnet_main_entry
|
||||
@not_telnet:
|
||||
cmp #KEYCODE_F3
|
||||
bne @not_gopher
|
||||
jsr cls
|
||||
lda #14
|
||||
jsr print_a ;switch to lower case
|
||||
jsr prompt_for_gopher_resource ;only returns if no server was entered.
|
||||
jmp exit_gopher
|
||||
@not_gopher:
|
||||
cmp #KEYCODE_F7
|
||||
bne @not_main
|
||||
jmp main_menu
|
||||
@not_main:
|
||||
jmp @get_key
|
||||
|
||||
.endif
|
||||
|
||||
print_errorcode:
|
||||
ldax #error_code
|
||||
jsr print
|
||||
@ -594,6 +631,7 @@ cfg_get_configuration_ptr:
|
||||
rts
|
||||
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
exit_telnet:
|
||||
exit_gopher:
|
||||
lda #142
|
||||
jsr print_a ;switch to upper case
|
||||
@ -602,14 +640,14 @@ exit_gopher:
|
||||
.rodata
|
||||
|
||||
netboot65_msg:
|
||||
.byte 13," NETBOOT65 - C64 CLIENT VERSION "
|
||||
.byte 13," NETBOOT65 - C64 CLIENT VERSION "
|
||||
.include "nb65_version.i"
|
||||
.byte 13,0
|
||||
main_menu_msg:
|
||||
.byte 13," MAIN MENU",13,13
|
||||
.byte "F1: TFTP BOOT"
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
.byte " F3: GOPHER"
|
||||
.byte " F3: NET APPS"
|
||||
.else
|
||||
.byte " F3: BASIC"
|
||||
.endif
|
||||
@ -617,6 +655,7 @@ main_menu_msg:
|
||||
.byte "F5: ARP TABLE F7: CONFIG",13,13
|
||||
.byte 0
|
||||
|
||||
|
||||
config_menu_msg:
|
||||
.byte 13," CONFIGURATION",13,13
|
||||
.byte "F1: IP ADDRESS F2: NETMASK",13
|
||||
@ -625,6 +664,14 @@ config_menu_msg:
|
||||
.byte "F7: MAIN MENU",13,13
|
||||
.byte 0
|
||||
|
||||
|
||||
.if (BANKSWITCH_SUPPORT=$03)
|
||||
net_apps_menu_msg:
|
||||
.byte 13," NET APPS",13,13
|
||||
.byte "F1: TELNET F3: GOPHER",13
|
||||
.byte "F5: F7: MAIN MENU",13,13
|
||||
.byte 0
|
||||
.endif
|
||||
downloading_msg: .asciiz "DOWNLOADING "
|
||||
|
||||
getting_dir_listing_msg: .byte "FETCHING DIRECTORY",13,0
|
||||
|
Loading…
Reference in New Issue
Block a user