Newer
Older
uBix-Retro / dump / oa-2.0.9 / apps / inet / httpd.a65
/****************************************************************************

    OS/A65 Version 2.0.0
    lib6502 httpd program

    Copyright (C) 1997-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.

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

/*
 * This is a horribly simple www server to show how listen/accept 
 * should be used.
 * It can only serve one file at a time, accepting other connections
 * after finishing a file. 
 * 
 * The server built into OS/A65 slipd is much better worked out, although
 * it also has its flues...
 */

#include "lib6502.i65"

#define	WWWPORT	8080
#define	BUFLEN	100
#define	FBUFLEN	128

#define	DEBUG

	.(
	.zero
p	.word 0
	.bss
lport	.byt 0
netfn	.byt 0
filefn	.byt 0
buf	.dsb BUFLEN
	.text

+main	.(
	sta p
	sty p+1

	lda #0
	sta lport

	lda #<wwwpath
	ldy #>wwwpath
	jsr chdir

	jsr parsepar
	bcs ret

	lda #<txt1
	ldy #>txt1
	jsr txtout
#ifdef DEBUG
	ldx #STDIN
	sec
	jsr fgetc
#endif
	lda #<listenarg
	ldy #>listenarg
	ldx #IPV4_TCP
	clc
	jsr listen
	bcs ret
	stx lport

	lda #<txt2
	ldy #>txt2
	jsr txtout
#ifdef DEBUG
	ldx #STDIN
	sec
	jsr fgetc
#endif
aloop
	sec
	lda #BUFLEN
	sta abuf
	lda #<abuf
	ldy #>abuf
	ldx lport
	jsr accept
	bcc gotone
ende	
	ldx lport
	sec
	jsr listen

ret	rts

gotone	stx netfn
	jsr getline
	bcs doclose
	jsr parsereq
	bcs doclose
	jsr dofile
	ldx filefn
	jsr fclose
doclose
	ldx netfn
	jsr fclose
	jmp aloop
	.)

	.data
txt1	.asc "^m^jhttpd: start listening",0
txt2	.asc "^m^jhttpd: start accepting",0

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

getline	.(
	ldy #0
	ldx netfn
l0	sec
	jsr fgetc
	bcs ferr
	cmp #13
	beq eol
	sta buf,y
	iny
	cpy #BUFLEN
	bcc l0
ferr	
	; file error or buffer overflow error
	ldx netfn
	jsr fclose
	sec
	rts

eol	; end of line
	lda #0
	sta buf,y

#ifdef DEBUG
	lda #<lt
	ldy #>lt
	jsr txtout
	lda #<buf
	ldy #>buf
	jsr txtout
	jsr crlfout

	.data
lt	.asc "httpd: got request: ",0
	.text

#endif
	clc
	rts
	.)

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

dofile	.(
	.bss
fpars	.dsb 4
fbuf	.dsb FBUFLEN
	.text

	; drain network input, in case it blocks otherwise
	ldx netfn
drain	clc
	jsr fgetc
	bcc drain

	jsr yield

	; read a block from file
	lda #<fbuf
	sta fpars
	lda #>fbuf
	sta fpars+1
	lda #<FBUFLEN
	sta fpars+2
	lda #>FBUFLEN
	sta fpars+3

	lda #<fpars
	ldy #>fpars
	ldx filefn
	clc
	jsr fread
	bcs d1
	lda #E_OK
d1	pha

	lda #<FBUFLEN
	sec
	sbc fpars+2
	sta fpars+2
	lda #>FBUFLEN
	sbc fpars+3
	sta fpars+3
	ora fpars+2
	beq empty

	lda #<fbuf
	sta fpars
	lda #>fbuf
	sta fpars+1

	lda #<fpars
	ldy #>fpars
	ldx netfn	
	sec
	jsr fwrite
empty
	pla
	cmp #E_EOF
	bne dofile
	rts
	.)

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

parsereq .(
	.zero
fp	.word 0
	.text

	ldy #<-1
n0	iny
	lda buf,y
	cmp #" "
	beq n0

	lda buf,y
	cmp #"G"
	bne malformed
	iny
	lda buf,y
	cmp #"E"
	bne malformed
	iny
	lda buf,y
	cmp #"T"
	bne malformed
	
n1	iny
	lda buf,y
	cmp #" "
	beq n1

	; here we have the address of the filename
	tya
	clc
	adc #<buf
	sta fp
	lda #0
	adc #>buf
	sta fp+1

	ldy #<-1
n2	iny
	lda (fp),y
	beq ende
	cmp #" "
	bne n2		; check for extensions...
	lda #0
	sta (fp),y
ende
	lda fp
	ldy fp+1
	ldx #OPEN_RD
	jsr fopen
	bcs notopen
	stx filefn
	rts

notopen	ldx #0
	.byt $2c
malformed
	ldx #1

	txa
	asl
	asl
	tay
	ldx #0
ll	lda eaddrs,y
	sta fwpars,x
	iny
	inx
	cpx #4
	bcc ll
	lda #<fwpars
	ldy #>fwpars
	ldx filefn
	sec
	jsr fwrite

	ldx filefn
	jsr fclose
	sec
	rts

	.bss
fwpars	.dsb 4
	.data
eaddrs	.word err0, err1-err0
	.word err1, err2-err1

err0	.byt "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 httpd server error: file not found^m^j"
        .asc "</BODY>^m^j</HTML>^m^j"
err1	.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 httpd server error: malformed request^m^j"
        .asc "</BODY>^m^j</HTML>^m^j"
err2
	.text
	.)

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

	.bss
digit	.word 0
	.text

parsepar .(
	ldy #0
l1	lda (p),y
	beq l2
	iny
	bne l1
l2	
	iny
	tya
	clc
	adc p
	sta p
	lda #0
	adc p+1
	sta p+1

	ldy #0
	lda (p),y
	beq ret
	lda p
	ldy p+1
	jsr chdir

	ldy #0
l4	lda (p),y
	beq l3
	iny
	bne l4
l3
	sta digit
	sta digit+1

	iny
	lda (p),y
	bne pp
	clc
	rts
pp
        cmp #"0"
        bcc err
        cmp #"9"+1
        bcs err

        jsr nextwdig

        iny
        lda (p),y
        bne pp

        lda digit
        sta wwwport
        lda digit+1
        sta wwwport+1
ret     clc
        rts
err     sec
        rts
	.)

nextwdig .(
        pha
        asl digit
        rol digit+1
        lda digit
        ldx digit+1
        asl digit
        rol digit+1
        asl digit
        rol digit+1
        clc
        adc digit
        sta digit
        txa
        adc digit+1
        sta digit+1
        pla
        and #$0f
        adc digit
        sta digit
        bcc x1
        inc digit+1
x1      rts
        .)

txtout	.(
	.zero
p2	.word 0
	.text

	sta p2
	sty p2+1
	ldy #0
	ldx #STDERR
l	lda (p2),y
	beq ret
	sec
	jsr fputc
	iny
	bne l
ret
	rts
	.)

crlfout	.(
	ldx #STDERR
	lda #13
	sec
	jsr fputc
	lda #10
	sec
	jmp fputc
	.)

	.data
wwwpath	.asc "f:",0

listenarg .byt 3 : wwwport .word WWWPORT

	.bss

abuf	.dsb BUFLEN

	.text
	.)