Newer
Older
uBix-Retro / dump / oa-2.0.9 / sysapps / slipd / wwwsrv.a65
/****************************************************************************
   
    OS/A65 Version 2.0.0
    Multitasking Operating System for 6502 Computers

    Copyright (C) 1989-1998 Andre Fachat

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

****************************************************************************/

	.(

#define	TCB_WS		TCB_CONN
#define	TCB_WSLOT	(TCB_CONN+1)
#define	TCB_WSTR	(TCB_CONN+2)
#define	TCB_WTASK	(TCB_CONN+3)
#define	TCB_WCNT	(TCB_CONN+4)
#define	TCB_WPREFIX	(TCB_CONN+5)

#define	WS_FREE		0
#define	WS_RXD		1	/* filename received */
#define	WS_FSENT	2	/* filename sent to filesystem */
#define	WS_WR		3	/* get data and send it */
#define	WS_WR_WAIT	4	/* send prepared data block */
#define	WS_WR_WEOF	5	/* send last data block */
#define	WS_CLOSING	6	/* closing */
#define	WS_CLOSED	7	/* closed */

#define	WE_ILLFORMED	1	/* illformed request */
#define	WE_TRYAGAIN	2	/* temporary resource shortage */
#define	WE_NOTFOUND	3	/* file not found */

www_srv	.byte 0,0,0,0, 0,0, 80,0, SFL_MULT
        .word wwwsrv_open-1, wwwsrv_queue-1, wwwsrv_loop-1, wwwsrv_signal-1

	.zero
zp	.word 0
	.text

&wwwsrv_init .(
	lda #<www_srv
	ldy #>www_srv
	jmp tcp_listen
	.)

wwwsrv_open
	rts

wwwsrv_queue .(
	stx pslot
	jsr getbadr
	sta pp
	sty pp+1

#ifdef DEBUGWWW
DB("wwwsrv_queue: tcbp=")
lda tcbp+1:jsr EHexout:lda tcbp:jsr EHexout:jsr ECrlfout
#endif

	ldy #TCB_WS
	lda (tcbp),y
	cmp #WS_FREE
	beq noclose
	jmp close
noclose
	ldy #TCB_WPREFIX
	lda #<-1
	sta (tcbp),y

	ldy #0
	lda (pp),y
	clc
	adc pp
	sta pd
	iny
	lda (pp),y
	adc pp+1
	sta pd+1
	iny
	lda (pp),y
	sta pdl
	iny
	lda (pp),y
	sta pdl+1
#ifdef DEBUGWWW
ldy #0:x4 lda (pd),y:jsr ECout:iny:cpy pdl:bcc x4
#endif

	lda pdl+1
	bne oklen
	lda pdl
	cmp #5		/* at least GET + space + one_char_URL */
	bcc noget1
oklen
	ldy #0
	lda (pd),y
	cmp #"G"
	beq get2
	cmp #"g"
	bne noget1
get2	iny
	lda (pd),y
	cmp #"E"
	beq get3
	cmp #"e"
	bne noget1
get3	iny
	lda (pd),y
	cmp #"T"
	beq get4
	cmp #"t"
	beq get4
noget1	jmp noget
get4	
	iny
	beq noget1	/* length overflow */
	cpy pdl
	bcc ok		/* low counter below length */
	lda pdl+1
	beq noget1	/* gotten to end length */
ok
	lda (pd),y
	cmp #" "
	beq get4

	tya
	sta ppl		/* well, we need temp. storage... */
	clc
	adc pd
	sta pd
	bcc a0
	inc pd+1
a0	lda pdl
	sec
	sbc ppl
	sta pdl
	bcs a1
	dec pdl+1
a1	
	ldy #0
	beq a2a
a2	iny
	beq noget1	/* length overflow */
a2a	cpy pdl
	bcc ok1		/* low counter below length */
	lda pdl+1
	beq noget1	/* gotten to end length */
ok1
	lda (pd),y
	cmp #32
	bcc end
	cmp #" "
	beq end
	cmp #"#"
	beq end
	cmp #"/"
	bne a2
	lda #DIRSIGN
	sta (pd),y
	jmp a2
end	sty pdl
	lda #0
	sta pdl+1

	cpy #64		/* filename too long! */
	bcs noget	

#ifdef DEBUGWWW
DB("GET detected:")
ldy #0:x3 lda (pd),y:jsr ECout:iny:cpy pdl:bcc x3
DB(", len=")
lda pdl:jsr EHexout:jsr ECrlfout
#endif

	ldy #0
	lda pd
	sec
	sbc pp
	sta (pp),y
	iny
	lda pd+1
	sbc pp+1
	sta (pp),y
	iny
	lda pdl
	sta (pp),y
	iny
	lda pdl+1
	sta (pp),y

	lda pslot
	ldy #TCB_WSLOT
	sta (tcbp),y
	ldy #TCB_WS
	lda #WS_RXD
	sta (tcbp),y
	ldy #TCB_WCNT
	lda #100
	sta (tcbp),y
	clc
	rts

noget	lda pslot
	pha
	ldx #WE_ILLFORMED
	jsr senderr
	pla
	sta pslot
	lda #WS_CLOSING
set
	ldy #TCB_WS
	sta (tcbp),y
close 
	ldx pslot
	jsr bfree

	clc
	rts
	.)

senderr	.(
	dex
	txa
	asl
	tax

	lda msgtab,x
	sta zp
	lda msgtab+1,x
	sta zp+1

	lda lentab+1,x
	tay
	lda lentab,x
	sec

&sendprefix
	php
	clc
	adc #TCP_DOFFSET
	pha
	tya
	adc #0
	tay
	pla
	jsr balloc
	bcc xerrp
	jmp errp
xerrp
	lda #TCP_DOFFSET
	jsr getpinfo
/*
DB("sendprefix: pd=")
lda pd+1:jsr EHexout:lda pd:jsr EHexout
DB(" pp=")
lda pp+1:jsr EHexout:lda pp:jsr EHexout
jsr ECrlfout
*/
	ldy #0
	lda pd
	sec
	sbc pp
	sta (pp),y
	iny
	lda pd+1
	sbc pp+1
	sta (pp),y
	iny
	lda pdl
	sta (pp),y
	iny
	lda pdl+1
	sta (pp),y

	ldy #0
loop	cpy pdl
	bcc okl
	lda pdl+1
	beq end
okl	
	lda (zp),y
	sta (pd),y
	iny
	bne loop
	dec pdl+1
	jmp loop

end
/*
DB("sendprefix: pd=")
lda pd+1:jsr EHexout:lda pd:jsr EHexout
DB(" pp=")
lda pp+1:jsr EHexout:lda pp:jsr EHexout
jsr ECrlfout
*/
	ldx pslot
	plp
	bcc notx

	jmp tx_queue_packet
errp
	plp
	sec
notx	lda #<-1
	sta pslot
	rts

	.data

msgtab	.word m_illf, m_again, m_notf
lentab	.word e_illf-m_illf, e_again-m_again, e_notf-m_notf

m_illf	.asc "HTTP/1.0 400^m^jContent-Type: text/html^m^j^m^j"
	.asc "<HTML>^m^j<HEAD>^m^j<TITLE>Error</TITLE>^m^j</HEAD>^m^j"
	.asc "<BODY>^m^j<H1>Error 400</H1>^m^j^m^j"
	.asc "<A HREF=",34,"http://www.tu-chemnitz.de/~fachat/8bit/osa/index.html",34,">OS/A65</A>"
	.asc " TCP simple WWW server error: malformed request^m^j"
	.asc "</BODY>^m^j</HTML>^m^j"
e_illf
m_again	.asc "HTTP/1.0 400^m^jContent-Type: text/html^m^j^m^j"
	.asc "<HTML>^m^j<HEAD>^m^j<TITLE>Error</TITLE>^m^j</HEAD>^m^j"
	.asc "<BODY>^m^j<H1>Error 400</H1>^m^j^m^j"
	.asc "<A HREF=",34,"http://www.tu-chemnitz.de/~fachat/8bit/osa/index.html",34,">OS/A65</A>"
	.asc " TCP simple WWW server error: try again^m^j"
	.asc "</BODY>^m^j</HTML>^m^j"
e_again
m_notf	.asc "HTTP/1.0 400^m^jContent-Type: text/html^m^j^m^j"
	.asc "<HTML>^m^j<HEAD>^m^j<TITLE>Error</TITLE>^m^j</HEAD>^m^j"
	.asc "<BODY>^m^j<H1>Error 400</H1>^m^j^m^j"
	.asc "<A HREF=",34,"http://www.tu-chemnitz.de/~fachat/8bit/osa/index.html",34,">OS/A65</A>"
	.asc " TCP simple WWW server error: file not found^m^j"
	.asc "</BODY>^m^j</HTML>^m^j"
e_notf
	.text

	.)

wwwsrv_loop .(
	ldy #TCB_WS
	lda (tcbp),y
	cmp #WS_CLOSED+1
	bcc noerr
	jmp err
noerr
	asl
	tay
	lda looptab+1,y
	pha
	lda looptab,y
	pha
	rts

looptab	.word loop_free-1, loop_rxd-1, loop_sent-1, loop_wr-1
	.word loop_wait-1, loop_wait-1, loop_close-1, loop_closed-1

loop_rxd .(
	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr getbadr
	sta pp
	sty pp+1
	ldy #0
	lda (pp),y
	clc
	adc pp
	sta pd
	iny
	lda (pp),y
	adc pp+1
	sta pd+1
	iny
	lda (pp),y
	sta pdl
	iny
	lda (pp),y
	sta pdl+1

#if 1  /* def NOMMU */
	ldx #SEM_SENDBUF
	sec
	jsr PSEM
	bcc semerrok
	jmp semerr
semerrok
#endif
	inc sendbuf

	lda www_drv
	sta PCBUF+FS_OPEN_DRV
	lda #0
	sta PCBUF+FS_OPEN_PFAD
	
	jsr GETSTR
	bcs strerr

	txa
	sta PCBUF+FS_OPEN_STR
	ldy #TCB_WSTR
	sta (tcbp),y

	ldx #0
l0	lda wwwpath,x
	beq l1
	sta PCBUF+FS_OPEN_NAME,x
	inx
	bne l0
l1
	ldy #0
	lda (pd),y
	cmp #"/"	;DIRSIGN
	bne l2
	iny
l2
	cpy pdl
	bcs l3
	lda (pd),y
	cmp #" "
	beq l3
	sta PCBUF+FS_OPEN_NAME,x
	iny
	inx
	bne l2
l3
	txa
	beq def
	lda PCBUF+FS_OPEN_NAME-1,x
	cmp #DIRSIGN
	bne l4
def
	ldy #0
l5	lda wwwdef,y
	beq l4
	sta PCBUF+FS_OPEN_NAME,x
	iny
	inx
	bne l5
l4
	lda #0
	sta PCBUF+FS_OPEN_NAME,x
	inx
	txa
	clc
	adc #FS_OPEN_NAME

	jsr send_filetype

	tay
	lda #FS_OPEN_RD
	ldx #SEND_FM
	jsr SEND	/* warning: this blocks if own task or weird confs! */
	bcs send_err

	txa
	ldy #TCB_WTASK
	sta (tcbp),y

	lda #WS_FSENT
	ldy #TCB_WS
	sta (tcbp),y

	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr bfree

	clc
	rts

send_err
	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	jsr FRESTR
strerr	
	dec sendbuf
#if 1 /* def NOMMU */
	ldx #SEM_SENDBUF
	jsr VSEM
semerr
#endif
	ldy #TCB_WCNT
	lda (tcbp),y
	sec
	sbc #1
	sta (tcbp),y
	bne end

	ldx #WE_TRYAGAIN
	jsr senderr

	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr bfree

	ldy #TCB_WS
	lda #WS_CLOSING
	sta (tcbp),y

end	rts

wwwpath	.byte WWW_PATH,0
wwwdef	.byte WWW_DEFAULT,0
	.)

send_filetype .(
	.bss
cnt	.byt 0
	.text

	pha
/*
DB("filtetype for ")
lda #<PCBUF+FS_OPEN_NAME:ldy #>PCBUF+FS_OPEN_NAME:jsr ETxtout
DB("^m^jprefix=")
ldy #TCB_WPREFIX:lda (tcbp),y:jsr EHexout:jsr ECrlfout
*/
	jsr clrprefix
fo
	pla
	pha
	tax
	ldy #TCB_WPREFIX
	lda #<-1
	sta (tcbp),y

	ldy #0
	sty cnt
l0	lda types,y
	beq found
	cmp PCBUF-2,x
	bne next
	dex
	iny
	bne l0

next	pla
	pha
	tax
	inc cnt
n2	iny
	lda types,y
	bne n2
	iny
	lda types,y
	bne l0
	pla
	rts

found	asl cnt
	ldx cnt
	lda tadrs,x
	sta zp
	lda tadrs+1,x
	sta zp+1
/*
DB("header="):lda zp:ldy zp+1:jsr ETxtout:jsr ECrlfout
DB("len="):lda tlens+1,x:jsr EHexout:lda tlens:jsr EHexout:jsr ECrlfout
*/
	lda tlens+1,x
	tay
	lda tlens,x
	clc		; do not send, just get slot
	jsr sendprefix
	ldy #TCB_WPREFIX
	txa
	sta (tcbp),y
/*
DB("send packet:")
.( :ldy #0: lll lda (pp),y:jsr EHexout:iny: cpy #4:bcc lll: .): jsr ECrlfout
*/
ret
	pla
	rts

types	.asc "lmth.",0, "fig.",0, "gpj.",0, 0
tadrs	.word tt0,       tt1,       tt2
tlens	.word tt1-tt0-1, tt2-tt1-1, tt3-tt2-1

tt0	.asc "HTTP/1.0 200 OK^m^jContent-Type: text/html^m^j^m^j",0
tt1	.asc "HTTP/1.0 200 OK^m^jContent-Type: image/gif^m^j^m^j",0
tt2	.asc "HTTP/1.0 200 OK^m^jContent-Type: image/jpg^m^j^m^j",0
tt3
	.)

&clrprefix .(
	ldy #TCB_WPREFIX
	lda (tcbp),y
	tax
	lda #<-1
	sta (tcbp),y
	cpx #<-1
	beq nopr
	jsr bfree
nopr	rts
	.)

loop_sent .(
	ldy #TCB_WTASK
	lda (tcbp),y
	tax
	clc
	jsr XRECEIVE
	bcc gotit
	rts
gotit
	dec sendbuf
#if 1 /* def NOMMU */
	pha
	ldx #SEM_SENDBUF
	jsr VSEM
	pla
#endif
	cmp #0
	bne err1

	ldy #TCB_WPREFIX
	lda (tcbp),y

	cmp #<-1
	beq ll
	tax
	lda #<-1
	sta (tcbp),y
	; jsr tx_queue_packet
	txa
	ldy #TCB_WSLOT
	sta (tcbp),y
	jmp qslot
ll	
	lda #WS_WR
set
	ldy #TCB_WS
	sta (tcbp),y
	rts

err1	jsr clrprefix

	ldx #WE_NOTFOUND
	jsr senderr

	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	jsr FRESTR

	lda #WS_CLOSING
	jmp set
	.)

loop_wr	.(
/*
DB("loop_wr:")
jsr printlist:jsr printmem
*/
	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	lda #SC_STAT
	jsr STRCMD
	cmp #E_SFULL
	beq send2
	cmp #E_SHWM
	beq send2
	lda #SC_RWANZ
	jsr STRCMD
	cmp #0
	beq send2
l0c1	rts
send2
        lda #TCP_DOFFSET+64
        ldy #0
        jsr balloc
        bcs l0c1
	;stx pslot
	;sta pp
	;sty pp+1
        txa
        ldy #TCB_WSLOT
        sta (tcbp),y
        lda #TCP_DOFFSET
	jsr getpinfo
/*
DB("Write block to pp=")
lda pp+1:jsr EHexout:lda pp:jsr EHexout:DB(", pd=")
lda pd+1:jsr EHexout:lda pd:jsr EHexout
jsr ECrlfout

DB("sadr=") 
ldy #TCB_WSLOT: lda (tcbp),y: tax: jsr getbadr: pha: tya: jsr EHexout: pla: jsr EHexout: jsr ECrlfout
*/
	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	ldy #0
wrl	jsr GETC
	bcs wrle
	sta (pd),y
	iny
	cpy #64
	bcc wrl
	lda #E_OK
wrle	pha
	tya

	pha
	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
/*
DB("pd=")
lda pd+1:jsr EHexout:lda pd:jsr EHexout:jsr ECrlfout
DB("sadr=")
ldy #TCB_WSLOT:lda (tcbp),y:tax:jsr getbadr:pha:tya:jsr EHexout:pla:jsr EHexout:jsr ECrlfout
*/
	pla

	sta pdl
        ldy #0
        clc
        adc #TCP_DOFFSET
        bcc w2
        iny
w2      jsr btrunc
/*
DB("pp=")
lda pp+1:jsr EHexout:lda pp:jsr EHexout
DB("sadr=")
ldy #TCB_WSLOT:lda (tcbp),y:tax:jsr getbadr:pha:tya:jsr EHexout:pla:jsr EHexout:jsr ECrlfout
*/
        ldy #0
        lda #<TCP_DOFFSET
        sta (pp),y
        iny
        lda #>TCP_DOFFSET
        sta (pp),y
        iny
        lda pdl
        sta (pp),y
        iny
        lda #0
        sta (pp),y
        pla

        cmp #E_EOF
        beq wend
&qslot  lda #WS_WR_WAIT
	.byt $2c
wend    lda #WS_WR_WEOF
	ldy #TCB_WS
	sta (tcbp),y

	ldy #TCB_WSLOT
	lda (tcbp),y
/*pha:DB("slot="):pla:pha:jsr EHexout:jsr ECrlfout:pla*/
	tax
	jsr incownr
	jsr tx_queue_packet
	bcc send_ok
	cmp #0
	bne error
	rts
error	lda #TE_SIG_RESET
	jmp wwwsrv_signal
	.)

loop_wait .(
	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr incownr
/* DB("requeue^m^j") */
	jsr tx_requeue_packet
	bcs end
&send_ok
;jsr wwwprint
	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr bfree

	ldy #TCB_WS
	lda (tcbp),y
	cmp #WS_WR_WEOF
	bne noeof

	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	lda #SC_NUL
	jsr STRCMD

	lda #WS_CLOSING
	.byt $2c
noeof	lda #WS_WR
	ldy #TCB_WS
	sta (tcbp),y
end	rts
	.)
	
loop_close
err	ldy #TCB_WS
	lda #WS_CLOSED
	sta (tcbp),y

	ldx conn
	jsr tcp_close
loop_closed
loop_free rts
	.)

wwwsrv_signal .(
#ifdef DEBUGTCP2
pha:
DB("wwwsrv_signal = "):pla:pha:jsr EHexout
DB(", tcbp="):lda tcbp+1:jsr EHexout:lda tcbp:jsr EHexout:jsr ECrlfout
pla
;inc $d020
#endif
	pha

	jsr clrprefix

	ldy #TCB_WS
	lda (tcbp),y
	cmp #WS_FSENT
	bne nosent

	ldy #TCB_WTASK		/* unlock filesystem by receiving msg */
	lda (tcbp),y
	tax
	sec
	jsr XRECEIVE

	ldy #TCB_WSTR
	lda (tcbp),y
	tax	
	lda PCBUF+FS_X_ERR
	beq relbuf
	lda #SC_EOF
	jsr STRCMD
relbuf
	dec sendbuf
#if 1 /* def NOMMU */
	ldx #SEM_SENDBUF
	jsr VSEM
#endif
	jmp checkstr

nosent	cmp #WS_WR_WAIT
	beq wait
	cmp #WS_WR_WEOF
	bne nowait
wait	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr bfree
nowait	
checkstr
	ldy #TCB_WS
	lda (tcbp),y
	cmp #WS_FSENT
	bcc end1
	cmp #WS_CLOSING
	bcc end1
	ldy #TCB_WSTR
	lda (tcbp),y
	tax
	lda #SC_NUL
	jsr STRCMD

end1	lda #WS_CLOSED
	ldy #TCB_WS
	sta (tcbp),y

	pla
	jmp tcp_signal
	.)

#iflused wwwprint
wwwprint .(
	.zero
wp	.word 0
l	.word 0
	.text

;	lda tcbp
;	cmp #<tcb+TCB_LEN
;	beq print
;	rts
;print
	DB("www sent:")
	ldy #TCB_WSLOT
	lda (tcbp),y
	tax
	jsr getbadr
	sta wp
	sty wp+1
	jsr getblen
	clc
	adc wp
	sta l
	tya
	adc wp+1
	sta l+1

	lda #TCP_DOFFSET
	clc
	adc wp
	sta wp
	lda #0
	adc wp+1
	sta wp+1

loop	lda wp+1
	cmp l+1
	bcc doit
	bne end
	lda wp
	cmp l
	bcs end
doit
	ldy #0
	lda (wp),y
	jsr ECout
	inc wp
	bne loop
	inc wp+1
	bne loop
end	jmp ECrlfout
	.)
#endif

	.)