Author Topic: Flagging end of data (code problem)  (Read 9170 times)

Offline mik3ca

  • Jr. Member
  • *
  • Posts: 30
Flagging end of data (code problem)
« on: January 15, 2021, 04:57:49 PM »
I have a custom microcontroller that connects to an old MS-DOS PC with a serial port and I'm having that old PC connect to my router using RJ45 ethernet cable so other computers can connect and I'm making my own DOS webserver program to allow that connection to happen.

I'm using Trumpet sockets NTCPDRV for DOS interrupt routines to help me, but I am struggling with receiving maximum data.

First, this is the function I'm dealing with (as taken from TCP201.SPE file which may be downloaded from files within http://wiki.freedos.org/wiki/index.php/Networking_FreeDOS_complete):

Code: [Select]
   tcp_status     get status of a TCP session
          call
               ah   = 14H
               al   = option flags
                         0    = normal
                         128  =   asynchronous.      Notify    by
     event_call
               bx   = handle
          return
               dl   = error code
                    bad_handle
               dh   = tcp_state
               ax   = bytes available for reading
               cx   = bytes still being transmitted
               es:di     = pointer to session info
                         ip_srce   dword
                         ip_dest   dword
                         ip_prot   byte
                         active    byte  (> 0 is active)

And I have my code.
ES:DI is an address of a struct that's already been initialized.
Int 61h in this case points to the NTCPDRV routines.
A TCP handle has already been allocated before this call is made.
I'll comment my code as I go through it.

CS:BP+breadt is an internal variable in code space as our flag.
CS:BP+iptabls is an internal struct in code space to store extended IP data


Code: [Select]
  ;on entry, BP=start of this code offset
  mov AX,[ES:DI+errc] ;Get error code as input option
  cmp AX,0000h           ;See if code is 0
  je noherr
    xor AX,AX                 ;Code is not 0 so reset internal read status
    mov [CS:BP+breadt],AX
  noherr:
  mov BX,[ES:DI+handle]  ;Get our TCP handle into BX
  push ES    ;Save our pointer so we don't corrupt results
  push DI
  mov ax,1400h ;get status normally (better than setting AH and AL separately)
  int 61h              ;Call driver interrupt.
  push ES   ; Driver returns its own ES:DI value for IP address info.
  pop DS     ; So we make DS:SI equal ES:DI for data extraction.
  push DI
  pop SI
  push CS
  pop ES    ; Make ES our segment for internal ip address info data
  add BP,iptbls
  mov DI,BP ;Make ES:DI = location where the IP address info goes
  movsd ; copy 10 bytes over
  movsd
  movsw
  pop DI ;restore our struct address
  pop ES
  and DX,00FFh ;We don't care about tcp_state from driver, just the error code.

;This is where the problem lies???

  mov BX,[CS:BP+breadt]  ;load our last bytes available to read value
  cmp BX,0000h  ;See how much there is
  je nobts
    cmp AX,0000h ;Last time there was 1+ bytes available to read
    jne nobts ;See if new bytes available is 1+
      or DX,1000h ;New bytes available is 0 so we set high byte of error flag
  nobts:
  mov [ES:DI+errc],DX ;store TCP error code to our struct
  mov [ES:DI+bsend],CX ;store bytes being sent to our struct
  mov [ES:DI+bread],AX ;store bytes available to read to our struct
  mov [CS:BP+breadt],AX ;save bytes available to read for the next time we are called

;End of possible problem section

ret

breadt:
dd 0

iptbls:
  iptsrc dd 0h   ;Source IP
  iptdest dd 0h   ;Dest IP
  iptstat dw 0h ;IP table status. Low byte=active, High byte=protocol


Now with my code, I could get away with putting this call in an endless loop until the bytes available to read (returned in AX from the driver call) is > 0, but that only allows for one chunk of data to read, not necessarily all of it.

What I want to do is have this run until there are bytes available to read and then have this run again until there are no more bytes available to read so I know I got all chunks possible. Maybe I'll later enhance the lack of data with a timeout.

The problem is with my function when I run it, I do receive 0 for bytes available to read (AX return value) and error 0 (DX return value), but after a period of time, the error value (DX) is 1000h but bytes available to read (AX) is STILL 0!. I was expecting AX to be > 0 so I can read data then DX can be 1000h when AX returns to 0 again.

When I call the function at first, I used -1 for input error code to reset the internal bytes read status (defined as breadt) then on subsequent calls, I use 0 for input error code so we don't modify breadt directly.

Is there something in my code here that I'm doing wrong?