NEW
  AUTO 3,1
				.LIST OFF
*/--------------------------------------
* # Socket
* Create a new socket
* ## C
* `hFD socket(short int type, short int protocol);`
* ## ASM
* **In:**
* `>PUSHB protocol`
* `lda type`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.socket`
* ## RETURN VALUE
* CC: A = hSOCKET
* CS: A = EC
*\--------------------------------------
SKT.Socket		tax
				>PULLA					get protocol (RAW)
SKT.Socket.I	jmp (J.SKT.Socket,x)

SKT.Socket.RAW	ldy #S.SOCKET
				bra SKT.Socket.DSOCK
SKT.Socket.DGRAM
				lda #S.IP.PROTOCOL.UDP
				ldy #S.SOCKET
				bra SKT.Socket.DSOCK
SKT.Socket.SEQPACKET
				lda #S.IP.PROTOCOL.TCP
				ldy #S.SOCKET.TCP
SKT.Socket.DSOCK
				stx FD.DSOCK+S.SOCKET.T		save type
				sta FD.DSOCK+S.SOCKET.PROTO		ICMP,UDP,TCP
				lda #0					Y = socket.size
				>SYSCALL2 GetMem0
				bcs .9
				>STYA ZPTmpPtr1

				jsr SKT.Socket.FindFree
				bcs .9

				ldy #FD.DSOCK.SIZE-1

.1				lda FD.DSOCK,y
				sta (ZPTmpPtr1),y
				dey
				bpl .1

				txa
				clc
.9				rts
SKT.Socket.STREAM
				lda #S.IP.PROTOCOL.TCP
				ldy #S.SOCKET.TCP

				stx FD.SSOCK+S.SOCKET.T		save type
				sta FD.SSOCK+S.SOCKET.PROTO
				lda #0					Y = socket.size
				>SYSCALL2 GetMem0
				bcs .9
				>STYA ZPTmpPtr1

				jsr SKT.Socket.FindFree
				bcs .9

				ldy #FD.SSOCK.SIZE-1

.1				lda FD.SSOCK,y
				sta (ZPTmpPtr1),y
				dey
				bpl .1

				txa
				clc
.9				rts
SKT.Socket.FindFree
				ldy #0
				
.1				lda SKT.TABLE,y
				beq .2
				iny
				cpy #K.SKTTABLE.SIZE
				bne .1
				
				txa
				>SYSCALL2 freemem
				lda #E.OOH
				sec
				rts

.2				txa
				sta SKT.TABLE,y
				clc
				rts
*/--------------------------------------
* # Bind
* bind a name to a socket
* ## C
* `int bind(hFD fd, const struct sockaddr *addr);`
* ## ASM
* **In:**
* `>PUSHW addr`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.socket`
* ## RETURN VALUE
* CC: A = hSOCKET
* CS: A = EC
*\--------------------------------------
SKT.bind		>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT
				jsr SKT.PullLocAddr

				lda SKT.LOC.ADDR+S.SOCKADDR.PORT
				ora SKT.LOC.ADDR+S.SOCKADDR.PORT+1
				bne .1

				jsr GetDynPort

				sta SKT.LOC.ADDR+S.SOCKADDR.PORT
				stx SKT.LOC.ADDR+S.SOCKADDR.PORT+1

.1				ldx #0

.2				lda SKT.TABLE,x
				beq .7

				phx
				>SYSCALL2 GetMemPtr
				>STYA ZPTmpPtr1
				plx

				ldy #S.SOCKET.AF
				lda (ZPTmpPtr1),y
				cmp #AF.INET
				bne .7

				ldy #S.SOCKET.LOC.ADDR

.3				lda (ZPTmpPtr1),y
				cmp SKT.LOC.ADDR+S.SOCKADDR.ADDR-S.SOCKET.LOC.ADDR,y
				bne .7
				iny
				cpy #S.SOCKET.LOC.PORT+2
				bne .3

				lda #ERR.SKT.BUSY
*				sec
				rts
				
.7				inx
				cpx #K.SKTTABLE.SIZE
				bne .2

				jmp SKT.SetLocAddr
*/--------------------------------------
* # Connect
* Initiate a connection on a socket
* ## C
* `int connect(hFD fd, const struct sockaddr *addr);`
* ## ASM
* **In:**
* `>PUSHW addr`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.socket`
* ## RETURN VALUE
* CC: A = hSOCKET
* CS: A = EC
*\--------------------------------------
SKT.connect		>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				jsr SKT.PullRemAddr

				ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				tax
				jmp (J.SKT.connect,x)
SKT.connect.RAW
SKT.connect.DGRAM
				jmp SKT.SetRemAddr
SKT.connect.STREAM
SKT.connect.SEQPACKET
				jsr SKT.SetRemAddr
				jsr SKT.NewTCB
				bcs SKT.listen.RTS

				lda #S.TCP.OPTIONS.SYN
				jsr TCP.OUT.SendOptA	Send SYN
*				bcs .9					could be queued for ARP....

				lda #S.SOCKET.TCP.S.SYNSENT
				jmp SKT.StoreTCB.S

*.9				lda #ERR.SKT.BAD
*				sec
*				clc
*.99			rts
*/--------------------------------------
* # Listen
* Listen for connections on a socket
* ## C
* `int listen(hFD fd);`
* ## ASM
* **In:**
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.listen`
* ## RETURN VALUE
* CS: A = EC
*\--------------------------------------
SKT.listen		>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.SEQPACKET+1
				bcc .9

				ldy #S.SOCKET.TCP.S
				lda (ZPPtrSKT),y
				bne .9

				lda #S.SOCKET.TCP.S.LISTEN
				sta (ZPPtrSKT),y

				ldy #S.SOCKET.O
				lda #S.SOCKET.O.ACCEPTCONN
				sta (ZPPtrSKT),y

				clc
				rts

.9				lda #ERR.SKT.BAD
				sec
SKT.listen.RTS				
				rts
*/--------------------------------------
* # Accept
* Accept a connection on a socket
* ## C
* `hFD Accept(hFD fd);`
* ## ASM
* **In:** 
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.accept`
* ## RETURN VALUE 
* A = hSocket
*\--------------------------------------
SKT.Accept		>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
				and #S.SOCKET.O.ACCEPTCONN
				beq .99

				ldy #S.SOCKET.HQ.TAIL
				lda (ZPPtrSKT),y
				ldy #S.SOCKET.HQ.HEAD
				cmp (ZPPtrSKT),y
				beq .9					CS

				pha
				inc
				cmp #S.SOCKET.HQ.MAX
				bne .1

				lda #0

.1				ldy #S.SOCKET.HQ.TAIL
				sta (ZPPtrSKT),y
				pla
				clc
				adc #S.SOCKET.HQ
				tay
				lda (ZPPtrSKT),y
				clc
				rts

.99				lda #ERR.SKT.BAD
				sec
.9				rts
*/--------------------------------------
* # Shutdown
* Close socket
* ## C
* `int shutdown(int fd);`
* ## ASM
* **In:**
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.shutdown`
* ## RETURN VALUE
*\--------------------------------------
SKT.shutdown	pha
				>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
				and #S.SOCKET.O.ACCEPTCONN
				bne SKT.shutdown.LISTEN

				ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.STREAM
				beq SKT.shutdown.STREAM
*--------------------------------------				
SKT.shutdown.LISTEN				
SKT.shutdown.RAW
SKT.shutdown.DGRAM
SKT.shutdown.SEQPACKET
.1				ldy #S.SOCKET.HQ.TAIL
				lda (ZPPtrSKT),y
				ldy #S.SOCKET.HQ.HEAD
				cmp (ZPPtrSKT),y
				beq .3					No frame in Queue, close..

				pha						save tail...
				clc
				adc #S.SOCKET.HQ
				tax
				pla
				inc
				cmp #S.SOCKET.HQ.MAX
				beq .2

				lda #0

.2				ldy #S.SOCKET.HQ.TAIL
				sta (ZPPtrSKT),y

				txa
				tay
				lda (ZPPtrSKT),y
				>SYSCALL2 FreeMem
				bra .1

.3				pla					get hFD...

				ldx #0

.4				cmp SKT.TABLE,x
				beq .5

				inx
				cpx #K.SKTTABLE.SIZE
				bne .4

.5				stz SKT.TABLE,x
				>SYSCALL2 freemem
*				clc
				rts
*--------------------------------------				
SKT.shutdown.STREAM
				pla
				jsr SKT.GetTCB
				
				ldy #S.SOCKET.TCP.S
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.TCP.S.ESTBLSH
				bne .1

				lda #S.TCP.OPTIONS.FIN+S.TCP.OPTIONS.ACK
				jsr TCP.OUT.SendOptA	Send FIN/ACK
				bcs .9

				lda #S.SOCKET.TCP.S.FINWT1
				jmp SKT.StoreTCB.S
				
.1				bcs .8					Already Closing			
*				cmp #S.SOCKET.TCP.S.TIMEWT
*				beq .8
				
				lda #S.TCP.OPTIONS.RST
				jsr TCP.OUT.SendOptA	Send RST
				bcs .9

				lda #S.SOCKET.TCP.S.TIMEWT
				jmp SKT.StoreTCB.S

.8				clc				
.9				rts				
*/--------------------------------------
* # Read (STREAM)
* ## C
* `int skt.read(hFD fd, void *buf, int count);`
* ## ASM
* **In:**
* `>PUSHWI count`
* `>PUSHW buf`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.read`
* ## RETURN VALUE
* CC: Y,A = bytes read
* CS: A = EC
*\--------------------------------------
SKT.Read 		jsr SKT.PullhFDDataInPtrLen

				ldy #S.SOCKET.TCP.INUSED
				lda (ZPPtrSKT),y
				tax
				iny
				ora (ZPPtrSKT),y
				beq .7					no data, go check SKT status

				cpx ZPDataInLen			XA = Data in pipe
				lda (ZPPtrSKT),y
				sbc ZPDataInLen+1
				bcs SKT.GetDataFromSktIn	more data in pipe, get full buffer of data
				
				stx ZPDataInLen			less data than INUSED, Get only INUSED data
				lda (ZPPtrSKT),y
				sta ZPDataInLen+1

				bra SKT.GetDataFromSktIn
				
.7				jsr SKT.CheckStream
				bcs .99					I/O error

				lda #E.NODATA
				sec
.99				rts
*--------------------------------------
* In:
*  Src : hInMem/INTAIL
*  Dst : ZPDataOutPtr/ZPDataOutLen
* Out:
*  Y,A = bytes read
*--------------------------------------
SKT.GetDataFromSktIn
				jsr SKT.GetTCB
				
				ldy #S.SOCKET.SQ.hInMem
				lda (ZPPtrSKT),y
				
				.DO AUXPIPE=1
				>SYSCALL2 GetStkObjPtr
				.ELSE
				>SYSCALL2 GetMemPtr
				.FIN
				
				sty ZPTmpPtr1

*				clc
				adc SKT.Cache+S.SOCKET.TCP.INTAIL+1
				sta ZPTmpPtr1+1

				lda ZPDataInLen
				eor #$FF
				tax

				lda ZPDataInLen+1
				eor #$FF
				pha
				
				.DO AUXPIPE=1
				jsr SKT.SetupZPCode
				.FIN
				
				ldy SKT.Cache+S.SOCKET.TCP.INTAIL

.1				inx						Check if room left in dest buffer
				bne .2
				pla
				inc
				beq .8

				pha

.2				.DO AUXPIPE=1
				jsr ZPCode
				.ELSE
				lda (ZPTmpPtr1),y
				.FIN
				
				sta (ZPDataInPtr)
				inc ZPDataInPtr
				bne .3
				inc ZPDataInPtr+1

.3				iny
				bne .1
				
				inc ZPTmpPtr1+1

				inc SKT.Cache+S.SOCKET.TCP.INTAIL+1
				lda SKT.Cache+S.SOCKET.TCP.INTAIL+1
				cmp /K.TCP.WSIZE
				bne .1

				stz SKT.Cache+S.SOCKET.TCP.INTAIL+1
				lda ZPTmpPtr1+1
*				sec
				sbc /K.TCP.WSIZE
				sta ZPTmpPtr1+1
				bra .1
				
.8				sty SKT.Cache+S.SOCKET.TCP.INTAIL

				>ADC16 SKT.Cache+S.SOCKET.TCP.INFREE,ZPDataInLen
				>SBC16 SKT.Cache+S.SOCKET.TCP.INUSED,ZPDataInLen

				jsr SKT.StoreTCB
				
				jsr TCP.SetSocketTCPO.ACK 	ACK=1 -> send WSIZE

				>LDYA ZPDataInLen
				clc
				rts
*--------------------------------------
* From TCP.IN
* Src : ZPDataInPtr/ZPDataInLen
* Dst : hInMem/INHEAD
*--------------------------------------
SKT.AddDataToSktIn
				lda SKT.Cache+S.SOCKET.TCP.INFREE
				sec
				sbc ZPDataInLen
				tax
				lda SKT.Cache+S.SOCKET.TCP.INFREE+1
				sbc ZPDataInLen+1
				bcc .9					Not enough room in Q

				stx SKT.Cache+S.SOCKET.TCP.INFREE
				sta SKT.Cache+S.SOCKET.TCP.INFREE+1

				ldy #S.SOCKET.SQ.hInMem
				lda (ZPPtrSKT),y

				.DO AUXPIPE=1
				>SYSCALL2 GetStkObjPtr
				.ELSE
				>SYSCALL2 GetMemPtr
				.FIN

				sty ZPTmpPtr1

*				clc
				adc SKT.Cache+S.SOCKET.TCP.INHEAD+1
				sta ZPTmpPtr1+1

				lda ZPDataInLen
				eor #$FF
				tax

				lda ZPDataInLen+1
				eor #$FF
				pha

				ldy SKT.Cache+S.SOCKET.TCP.INHEAD

.1				.DO AUXPIPE=1
				sta SETWRITEAUX
				.FIN

.2				inx
				bne .3
				pla
				inc
				beq .8

				pha

.3				lda (ZPDataInPtr)
				sta (ZPTmpPtr1),y
				inc ZPDataInPtr
				bne .4
				inc ZPDataInPtr+1

.4				iny
				bne .2
				
				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN

				inc ZPTmpPtr1+1
				
				inc SKT.Cache+S.SOCKET.TCP.INHEAD+1
				lda SKT.Cache+S.SOCKET.TCP.INHEAD+1
				cmp /K.TCP.WSIZE
				bne .1
				
				stz SKT.Cache+S.SOCKET.TCP.INHEAD+1
				
				lda ZPTmpPtr1+1
*				sec
				sbc /K.TCP.WSIZE
				sta ZPTmpPtr1+1
				bra .1
				
.9				sec
				rts

.8				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN
				
				sty SKT.Cache+S.SOCKET.TCP.INHEAD

				>ADC16 SKT.Cache+S.SOCKET.TCP.INUSED,ZPDataInLen

				clc
				rts
*/--------------------------------------
* # Write (STREAM)
* ## C
* `int skt.write(hFD fd, const void *buf, int count);`
* ## ASM
* **In:**
* `>PUSHWI count`
* `>PUSHW buf`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.write`
* ## RETURN VALUE
* CC: Y,A = bytes written
* CS: A = EC
*\--------------------------------------
SKT.Write		jsr SKT.PullhFDDataInPtrLen

				jsr SKT.CheckStream
				bcs .99
				
				jsr SKT.GetTCB

				ldx SKT.Cache+S.SOCKET.TCP.OUTFREE
				cpx ZPDataInLen
				lda SKT.Cache+S.SOCKET.TCP.OUTFREE+1
				sbc ZPDataInLen+1
				
				bcs SKT.AddDataToSktOut

				lda #E.NODATA			Not enough room in Q,no data transfered
				sec
.99				rts
*--------------------------------------
* Src : ZPDataInPtr/ZPDataInLen
* Dst : hOutMem/OUTHEAD
*--------------------------------------
SKT.AddDataToSktOut
				ldy #S.SOCKET.SQ.hOutMem
				lda (ZPPtrSKT),y

				.DO AUXPIPE=1
				>SYSCALL2 GetStkObjPtr
				.ELSE
				>SYSCALL2 GetMemPtr
				.FIN

				sty ZPTmpPtr1

*				clc

				adc SKT.Cache+S.SOCKET.TCP.OUTHEAD+1
				sta ZPTmpPtr1+1

				ldy SKT.Cache+S.SOCKET.TCP.OUTHEAD

				lda ZPDataInLen
				eor #$FF
				tax

				lda ZPDataInLen+1
				eor #$FF
				pha
				
.1				.DO AUXPIPE=1
				sta SETWRITEAUX
				.FIN

.2				inx
				bne .3
				pla
				inc
				beq .8

				pha

.3				lda (ZPDataInPtr)
				sta (ZPTmpPtr1),y

				inc ZPDataInPtr
				bne .4
				inc ZPDataInPtr+1

.4				iny
				bne .2
				
				inc ZPTmpPtr1+1
				
				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN
				
				inc SKT.Cache+S.SOCKET.TCP.OUTHEAD+1
				lda SKT.Cache+S.SOCKET.TCP.OUTHEAD+1
				cmp /K.TCP.WSIZE
				bne .1

				stz SKT.Cache+S.SOCKET.TCP.OUTHEAD+1

				lda ZPTmpPtr1+1
*				sec
				sbc /K.TCP.WSIZE
				sta ZPTmpPtr1+1
				bra .1

.8				.DO AUXPIPE=1
				sta CLRWRITEAUX
				.FIN
				
				sty SKT.Cache+S.SOCKET.TCP.OUTHEAD

				>SBC16 SKT.Cache+S.SOCKET.TCP.OUTFREE,ZPDataInLen
				>ADC16 SKT.Cache+S.SOCKET.TCP.OUTUSED,ZPDataInLen
				>ADC16 SKT.Cache+S.SOCKET.TCP.OUTTOSEND,ZPDataInLen
				jsr SKT.StoreTCB

				>LDYA ZPDataInLen
				clc
				rts
*--------------------------------------
* From TCP.OUT
* Src : hOutMem/OUTTAIL
* Dst : ZPDataOutPtr/ZPDataOutLen
*--------------------------------------
SKT.GetDataFromSktOut
				ldy #S.SOCKET.SQ.hOutMem
				lda (ZPPtrSKT),y

				.DO AUXPIPE=1
				>SYSCALL2 GetStkObjPtr
				.ELSE
				>SYSCALL2 GetMemPtr
				.FIN

				sty ZPTmpPtr1

*				clc
				adc SKT.Cache+S.SOCKET.TCP.OUTTAILSENT+1
				sta ZPTmpPtr1+1
				
				lda ZPDataOutLen
				eor #$FF
				tax

				lda ZPDataOutLen+1
				eor #$FF
				pha

				.DO AUXPIPE=1
				jsr SKT.SetupZPCode
				.FIN

				ldy SKT.Cache+S.SOCKET.TCP.OUTTAILSENT

.1				inx
				bne .2
				pla
				inc
				beq .8

				pha

.2				.DO AUXPIPE=1
				jsr ZPCode
				.ELSE
				lda (ZPTmpPtr1),y
				.FIN
				sta (ZPDataOutPtr)
				inc ZPDataOutPtr
				bne .3
				inc ZPDataOutPtr+1

.3				iny
				bne .1
				
				inc ZPTmpPtr1+1
				
				inc SKT.Cache+S.SOCKET.TCP.OUTTAILSENT+1
				lda SKT.Cache+S.SOCKET.TCP.OUTTAILSENT+1
				cmp /K.TCP.WSIZE
				bne .1
				
				stz SKT.Cache+S.SOCKET.TCP.OUTTAILSENT+1

				lda ZPTmpPtr1+1
*				sec
				sbc /K.TCP.WSIZE
				sta ZPTmpPtr1+1
				bra .1

.8				sty SKT.Cache+S.SOCKET.TCP.OUTTAILSENT

				>SBC16 SKT.Cache+S.SOCKET.TCP.OUTTOSEND,ZPDataOutLen

				clc
				rts
*/--------------------------------------
* # Recv (RAW,DGRAM,SEQPACKET)
* # RecvFrom (RAW,DGRAM,SEQPACKET)
* ## C
* `hMem recv(hFD fd);`
* `hMem recvfrom(hFD fd, struct sockaddr *addr);`
* ## ASM
* **In:**
* `>PUSHW addr`		(RecvFrom)
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.Recv`
* ## RETURN VALUE
* CC: A = hMem
* CS: A = EC
*\--------------------------------------
SKT.RecvFrom	pha
				>PULLW ZPTmpPtr1		addr
				pla
				sec
				.HS 90					BCC
SKT.Recv		clc
				php
				>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

				ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.STREAM
				beq .99

				ldy #S.SOCKET.HQ.TAIL
				lda (ZPPtrSKT),y
				tax

				ldy #S.SOCKET.HQ.HEAD
				cmp (ZPPtrSKT),y
				beq .90

				inc
				cmp #S.SOCKET.HQ.MAX
				bne .1
				lda #0

.1				ldy #S.SOCKET.HQ.TAIL
				sta	(ZPPtrSKT),y

				txa
				clc
				adc #S.SOCKET.HQ
				tay
				lda (ZPPtrSKT),y
				plp
				bcc .9					Exit with CC and A=hFrame

				pha
				>SYSCALL2 GetMemPtr
				>STYA ZPFrameInPtr

				ldy #S.IP.SRC

.2				lda (ZPFrameInPtr),y
				sta SA.REMOTE+S.SOCKADDR.ADDR-S.IP.SRC,y
				iny
				cpy #S.IP.SRC+4
				bne .2

				ldy #S.IP.PROTOCOL
				lda (ZPFrameInPtr),y
				cmp #S.IP.PROTOCOL.ICMP
				bne .3

				ldy #S.ICMP.IDENTIFIER
				bra .7

.3				cmp #S.IP.PROTOCOL.TCP
				beq .6
				cmp #S.IP.PROTOCOL.UDP
				bne .8

.6				ldy #S.TCPUDP.SRCPORT

.7				lda (ZPFrameInPtr),y
				sta SA.REMOTE+S.SOCKADDR+1
				iny
				lda (ZPFrameInPtr),y
				sta SA.REMOTE+S.SOCKADDR

.8				lda #S.SOCKADDR-1

.80				lda SA.REMOTE,y
				sta (ZPTmpPtr1),y
				dey
				bpl .80

				pla
				clc
.9				rts

.99				plp
				lda #ERR.SKT.BAD
				sec
				rts

.90				plp
				lda #0					no data
				sec
				rts
*/--------------------------------------
* # Send (RAW,DGRAM,SEQPACKET)
* # SendTo (RAW,DGRAM,SEQPACKET)
* ## C
* `int skt.send(hFD fd, const void *buf, int count);`
* `int skt.sendto(hFD fd, const void *buf, int count, const struct sockaddr *addr);`
* ## ASM
* **In:**
* `>PUSHW addr`		(SendTo)
* `>PUSHWI count`
* `>PUSHW buf`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.send`
* ## RETURN VALUE
* CC: Y,A = bytes written
* CS: A = EC
*\--------------------------------------
SKT.SendTo		sec
				.HS 90					BCC
SKT.Send		clc
				php
				jsr SKT.PullhFDDataInPtrLen
				plp
				bcc .1
				jsr SKT.PullRemAddr
				jsr SKT.SetRemAddr
.1				ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				tax
				jmp (J.SKT.send,x)
*--------------------------------------
SKT.Send.RAW	ldy #S.SOCKET.PROTO
				lda (ZPPtrSKT),y
				tax
				>LDYA ZPDataInLen
				jsr FRM.NewIP
				bcs SKT.Send.9
				bra SKT.Send.DGRAM.8
*--------------------------------------
SKT.Send.DGRAM	ldx #S.IP.PROTOCOL.UDP
				>LDYA ZPDataInLen
				jsr FRM.NewIP
				bcs SKT.Send.9
				jsr SKT.SetFrameOutTCPUDPPorts
SKT.Send.DGRAM.8
				jsr SKT.SetFrameOutDstIP
				jsr SKT.CopyDataInToOut
				jmp FRM.SendIP
*--------------------------------------
SKT.Send.STREAM	lda #ERR.SKT.BAD
				sec
SKT.Send.9		rts
*--------------------------------------
SKT.Send.SEQPACKET
				bra *
*/--------------------------------------
* # GetSockOpt
* Set Socket Options
* ## C
* `int getsockopt(hFD fd);`
* ## ASM
* **In:**
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.GetSockOpt`
* ## RETURN VALUE
*\--------------------------------------
SKT.getsockopt	>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT
				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
*				clc
				rts
*/--------------------------------------
* # SetSockOpt
* Set Socket Options
* ## C
* `int setsockopt(hFD fd, short int opts);`
* ## ASM
* **In:**
* `>PUSHBI opts`
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.SetSockOpt`
* ## RETURN VALUE
*\--------------------------------------
SKT.setsockopt	>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT
				>PULLA
				ldy #S.SOCKET.O
				sta (ZPPtrSKT),y
*				clc
				rts
*/--------------------------------------
* # EOF
* End Of File
* ## C
* `int eof(hFD fd);`
* ## ASM
* **In:**
* `lda fd`
* `>LIBCALL hLIBTCPIP,LIBTCPIP.EOF`
* ## RETURN VALUE
* CC : A = 0 if some data, A = $ff if EOF
* CS : A = Socket Error
*\--------------------------------------
SKT.EOF			>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT

SKT.EOF.I		ldy #S.SOCKET.TCP.INUSED
				lda (ZPPtrSKT),y
				iny
				ora (ZPPtrSKT),y
				bne .8					some DATA...
				
				jsr SKT.CheckStream
				bcs .9
				
				lda #$ff				no DATA, EOF = true
*				clc
				rts
				
.8				lda #0					...EOF = false
*				clc
.9				rts
*--------------------------------------
SKT.CheckStream	ldy #S.SOCKET.T
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.T.STREAM
				bne .99

				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
				and #S.SOCKET.O.ACCEPTCONN
				bne .99

				ldy #S.SOCKET.TCP.S	
				lda (ZPPtrSKT),y
				cmp #S.SOCKET.TCP.S.ESTBLSH
				bcc .8
				cmp #S.SOCKET.TCP.S.CLWAIT
				bcs .91
.8				lda #0
				rts						CC=ESTBLSH...or less

.91				lda #MLI.E.IO
				sec
				rts

.99				lda #ERR.SKT.BAD
				sec
				rts
*/--------------------------------------
* # GetTable
* Get socket table
* ## C
* `void * gettable();`
* ## ASM
* **In:**
* `>LIBCALL hLIBTCPIP,LIBTCPIP.GetTable`
* ## RETURN VALUE
*\--------------------------------------
SKT.GetTable	>LDYA L.SKT.Table
				clc
				rts
*--------------------------------------
SKT.PullhFDDataInPtrLen
				>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT
				>PULLW ZPDataInPtr		!!!DataOut trashed when sending ACK in TCP.OUT	
				>PULLW ZPDataInLen		!!!use DataInPtr/Len
				rts
*--------------------------------------
SKT.PullLocAddr	>PULLW ZPTmpPtr1
				ldy #S.SOCKADDR-1
.1				lda (ZPTmpPtr1),y
				sta SKT.LOC.ADDR,y
				dey
				bpl .1
				rts
*--------------------------------------
SKT.PullRemAddr	>PULLW ZPTmpPtr1
				ldy #S.SOCKADDR-1
.1				lda (ZPTmpPtr1),y
				sta SKT.REM.ADDR,y
				dey
				bpl .1
				rts
*--------------------------------------
SKT.SetLocAddr	ldy #S.SOCKET.LOC.PORT+1
.1				lda SKT.LOC.ADDR+S.SOCKADDR.ADDR-S.SOCKET.LOC.ADDR,y
				sta (ZPPtrSKT),y
				dey
				cpy #S.SOCKET.LOC.ADDR
				bcs .1
				rts
*--------------------------------------
SKT.SetRemAddr	ldy #S.SOCKET.REM.PORT+1
.1				lda SKT.REM.ADDR+S.SOCKADDR.ADDR-S.SOCKET.REM.ADDR,y
				sta (ZPPtrSKT),y
				dey
				cpy #S.SOCKET.REM.ADDR
				bcs .1
				rts
*--------------------------------------
SKT.FindMatchingLocRem
				.DO IPDEBUG=1
				jsr FRM.Dump
				.FIN
				ldx #0

.1				lda SKT.TABLE,x
				beq .8

				phx
				>SYSCALL2 GetMemPtr
				>STYA ZPPtrSKT
				.DO IPDEBUG=1
				jsr SKT.Dump
				.FIN
				plx

				ldy #S.SOCKET.AF
				lda (ZPPtrSKT),y
				cmp #AF.INET
				bne .8

				ldy #S.SOCKET.LOC.ADDR

.2				lda (ZPPtrSKT),y
				bne .4

				ldy #S.SOCKET.LOC.PORT	bound to 0.0.0.0,check only LOC port

.3				lda (ZPPtrSKT),y

.4				cmp SKT.LOC.ADDR+S.SOCKADDR.ADDR-S.SOCKET.LOC.ADDR,y
				bne .8
				iny
				cpy #S.SOCKET.LOC.PORT+2
				bne .3

				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
				and #S.SOCKET.O.ACCEPTCONN
				beq .6

				ldy #S.TCP.OPTIONS		Listening, only SYN packet....
				lda (ZPFrameInPtr),y
				cmp #S.TCP.OPTIONS.SYN
				beq .7					SYN recieved on a LISTEN socket, ok
				bne .8					bad packet for this listening

.6				lda SKT.REM.ADDR+S.SOCKADDR.ADDR

				cmp #$ff				FF.FF.FF.FF, Broadcast ?
				bne .41
*				ldy #S.SOCKET.O
				lda (ZPPtrSKT),y
				and #S.SOCKET.O.BROADCAST
				beq .9					this socket does not accept broadcast

				bra .43
				
.41				ldy #S.SOCKET.REM.ADDR

.5				lda (ZPPtrSKT),y

				cmp #$ff				accept 255.255.255.255 ?
				bne .42
				
.43				ldy #S.SOCKET.REM.PORT	Boradcast, check port only
		
.42				lda (ZPPtrSKT),y

				cmp SKT.REM.ADDR+S.SOCKADDR.ADDR-S.SOCKET.REM.ADDR,y
				bne .8					wrong remote host, exit....
				iny
				cpy #S.SOCKET.REM.PORT+2
				bne .42

.7				stx SKT.Index			x = SKT.TABLE index
				clc
				rts

.8				inx
				cpx #K.SKTTABLE.SIZE
				bne .1

.9				sec
				rts
*--------------------------------------
SKT.AddToQueueA pha
				ldy #S.SOCKET.HQ.HEAD
				lda (ZPPtrSKT),y
				tax
				inc 
				cmp #S.SOCKET.HQ.MAX
				bne .1
				lda #0

.1				ldy #S.SOCKET.HQ.TAIL
				cmp (ZPPtrSKT),y
				beq .9					Queue full!!

				ldy #S.SOCKET.HQ.HEAD
				sta (ZPPtrSKT),y
				txa
				clc
				adc #S.SOCKET.HQ
				tay

				pla
				sta (ZPPtrSKT),y
				clc
				rts

.9				pla						dicard hFrame
*				sec
				rts
*--------------------------------------
SKT.NewTCB		ldx #S.SOCKET.TCP.INTAIL
				
.1				stz SKT.Cache,x
				inx
				cpx #S.SOCKET.TCP
				bne .1
				
				>LDYAI K.TCP.WSIZE
				>STYA SKT.Cache+S.SOCKET.TCP.INFREE

				.DO AUXPIPE=1
				>SYSCALL2 NewStkObj
				.ELSE
				>SYSCALL2 getmem
				.FIN
				bcs .9
				txa
				ldy #S.SOCKET.SQ.hInMem
				sta (ZPPtrSKT),y

				>LDYAI K.TCP.WSIZE
				>STYA SKT.Cache+S.SOCKET.TCP.OUTFREE
				.DO AUXPIPE=1
				>SYSCALL2 NewStkObj
				.ELSE
				>SYSCALL2 getmem
				.FIN
				bcs .9
				txa
				ldy #S.SOCKET.SQ.hOutMem
				sta (ZPPtrSKT),y
				
				ldx #3

.2				lda A2osX.TIMER16,x
				sta SKT.Cache+S.SOCKET.TCP.OUTNEXTSEQ,x
				dex
				bpl .2
*				clc				
.9				rts
*--------------------------------------
SKT.GetTCB	 	ldy #S.SOCKET.TCP.INTAIL
.1				lda (ZPPtrSKT),y
				sta SKT.Cache,y
				iny
				cpy #S.SOCKET.TCP
				bne .1
				rts
*--------------------------------------
SKT.StoreTCB.S	ldy #S.SOCKET.TCP.S
				sta (ZPPtrSKT),y

SKT.StoreTCB 	ldy #S.SOCKET.TCP.INTAIL
.1				lda SKT.Cache,y
				sta (ZPPtrSKT),y
				iny
				cpy #S.SOCKET.TCP
				bne .1
				clc
				rts
*--------------------------------------
SKT.SetFrameOutDstIP
				ldy #S.SOCKET.REM.ADDR
				ldx #4

.1				lda (ZPPtrSKT),y
				pha
				iny
				dex
				bne .1

				ldy #S.IP.DST+3
				ldx #4

.2				pla
				sta (ZPFrameOutPtr),y
				dey
				dex
				bne .2
				rts
*--------------------------------------
SKT.SetFrameOutTCPUDPPorts
				ldy #S.SOCKET.LOC.PORT
				lda (ZPPtrSKT),y
				tax
				iny
				lda (ZPPtrSKT),y
 				ldy #S.TCPUDP.SRCPORT
				sta (ZPFrameOutPtr),y
				iny
				txa
				sta (ZPFrameOutPtr),y

				ldy #S.SOCKET.REM.PORT
				lda (ZPPtrSKT),y
				tax
				iny
				lda (ZPPtrSKT),y
 				ldy #S.TCPUDP.DSTPORT
				sta (ZPFrameOutPtr),y
				iny
				txa
				sta (ZPFrameOutPtr),y

				rts
*--------------------------------------
SKT.CopyDataInToOut
				lda ZPDataInPtr+1
				pha
				lda ZPDataOutPtr+1
				pha

				lda ZPDataInLen
				eor #$ff
				tax
				lda ZPDataInLen+1
				eor #$ff
				pha

				ldy #0
				
.1				inx
				bne .2
				pla
				inc
				beq .9
				pha

.2				lda (ZPDataInPtr),y
				sta (ZPDataOutPtr),y
				iny
				bne .1
				inc ZPDataInPtr+1
				inc ZPDataOutPtr+1
				bne .1

.9				pla
				sta ZPDataOutPtr+1
				pla
				sta ZPDataInPtr+1
				rts
*--------------------------------------
				.DO AUXPIPE=1
SKT.SetupZPCode	ldy #ZP.CODE.Len-1

.1				lda ZP.CODE,y
				sta ZPCode,y
				dey
				bpl .1
				rts
				.FIN
*--------------------------------------
MAN
SAVE USR/SRC/LIB/LIBTCPIP.S.SKT
LOAD USR/SRC/LIB/LIBTCPIP.S
ASM
