Wiser ReadClientSocket

Discussion in 'C-Bus Wiser 1 Controller' started by djaggar, Aug 6, 2009.

  1. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    This call appears to be ignoring Null bytes (0x00) read from the IP port ... is this the expected behaviour?

    Thanks,
    Dave
     
    djaggar, Aug 6, 2009
    #1
  2. djaggar

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    This isn't the expected behaviour. We will look into it.

    Null bytes are a common problem for programs written in C because it is used as the string terminator.
     
    Darren, Aug 6, 2009
    #2
  3. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Thanks, for what it's worth I'm not reading strings of ASCII, I'm reading strings of integers from a PentAir ComPool swimming pool controller. It outputs packets that contains a 2 bytes sync (0xff 0xaa), a 4 byte header, and a variable length info field (1 to 16 bytes), and a 2 byte CRC. One byte in the 4 byte header is the length of the info field. Because there is no teminator, reading from this thing is a bit of a pain in Pascal, so I've written
    ReadClientSocketN which puts a ringbuffer on top of ReadClientSocket to buffer the greedy read ahead and dish out N bytes at a time as required ... it'd be really nice if this call was a first class citizen in the Logic engine.

    Also, in the code below the line
    newbytes := ord(localreadbuffer[0]);
    ought to be
    newbytes := length(localreadbuffer);

    but calling length also has random problems (it sometimes returns a variable error) ...

    Lastly, there is something weird with code pasted into the Logic Editor (from DreamWeaver in my case), sometimes the white space used for indentation seems to cause an error. Deleting it and replacing it makes the error go away ...

    Let me know if a sample project with these last two problems present is helpful and I'll try to recreate them.

    Thanks again,
    Dave

    {Code To Read "Length" bytes from IP Port "SocketNumber" into string "DataString" ... could be made into a function that returns false on error or timeout ... for the latter count the number of sequential calls to ReadClientSocket that return nothing and give up after what is deemed too many}

    ReadBufferSize = 1024;

    ReadBuffer: array[1..ReadBufferSize] of char;
    ReadBufferFirst: integer;
    ReadBufferLast: integer;

    procedure ReadClientSocketN(SocketNumber: integer; var DataString: string; Length: integer);
    var
    localreadbuffer: string;
    bytesinbuffer, newbytes: integer;
    i: integer;
    begin
    if (ReadBufferFirst <= ReadBufferLast) then
    bytesinbuffer := ReadBufferLast - ReadBufferFirst
    else
    bytesinbuffer := (ReadBufferSize - ReadBufferFirst) + ReadBufferLast;

    while (bytesinbuffer < Length) do begin {we need to get some more data first}
    ReadClientSocket(SocketNumber, localreadbuffer, ''); {perhaps check for overflow or timeout here}
    newbytes := ord(localreadbuffer[0]);
    for i := 1 to newbytes do begin
    ReadBuffer[ReadBufferLast] := localreadbuffer;
    ReadBufferLast := ReadBufferLast + 1;
    if (ReadBufferLast > ReadBufferSize) then
    ReadBufferLast := 1;
    if (ReadBufferLast = ReadBufferFirst) then
    Halt; {the buffer is too small}
    end;
    bytesinbuffer := bytesinbuffer + newbytes;
    end;

    for i := 1 to Length do begin
    DataString := ReadBuffer[ReadBufferFirst];
    ReadBufferFirst := ReadBufferFirst + 1;
    if (ReadBufferFirst > ReadBufferSize) then
    ReadBufferFirst := 1;
    end;
    end;
     
    djaggar, Aug 7, 2009
    #3
  4. djaggar

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    OK. The problem is that the null character was being treated as a terminator. We have fixed this problem and an update will be released reasonably soon.
     
    Darren, Aug 7, 2009
    #4
  5. djaggar

    kjayakumar

    Joined:
    Oct 27, 2008
    Messages:
    448
    Likes Received:
    0
    The engineer responsible for the mistake with the null terminator has been reported to have been seen scurrying away while saying "I'll be baaacckk... with a fix".
     
    kjayakumar, Aug 7, 2009
    #5
  6. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Answering my own problem here ... it appears at least parameter names and (in built) function names are sharing the same name space in the logic engine ... so if you have a parameter called length, a call to the function length() will fail with a variable error ...
     
    djaggar, Aug 10, 2009
    #6
  7. djaggar

    MHeaton

    Joined:
    Apr 22, 2008
    Messages:
    103
    Likes Received:
    1
    Location:
    London
    Hi there,
    Was this ever fixed - am building a telnet implementation in the Wiser 2 simulator in PICED and observing a similar problem

    Dumping the results of a buffer with this code
    procedure dump_buffer( var b : Buffer);
    var
    i, c :integer;
    sz : string;
    begin
    WriteLn('Length = ', Length(b), '');
    c:= Length(b);
    if c > 10 then c:= 15;
    for i:= 1 to c do
    begin
    if (ord(b) <= 32) then
    begin
    sz:= ''; {Non printable}
    end
    else if (ord(b) < 126) then
    sz := ''{b} {Printable}
    else if (ord(b) >= 236) then
    begin
    case ord(b) of
    TELNET_IAC: sz:= 'IAC';
    TELNET_DONT: sz:= 'DONT';
    TELNET_DO: sz:= 'DO';
    TELNET_WONT: sz:= 'WONT';
    TELNET_WILL: sz:= 'WILL';
    TELNET_SB: sz:= 'SB';
    TELNET_SE: sz:= 'SE';
    TELNET_GA: sz:= 'GA';
    TELNET_EL: sz:= 'EL';
    TELNET_EC: sz:= 'EC';
    TELNET_AYT: sz:= 'AYT';
    TELNET_AO: sz:= 'AO';
    TELNET_IP: sz:= 'IP';
    TELNET_BREAK: sz:= 'BREAK';
    TELNET_DM: sz:= 'DM';
    TELNET_NOP: sz:= 'NOP';
    TELNET_EOR: sz:= 'EOR';
    TELNET_ABORT: sz:= 'ABORT';
    TELNET_SUSP: sz:= 'SUSP';
    TELNET_xEOF: sz:= 'EOF';
    else sz:= '';
    end;
    WriteLn('b[', i, ']=');
    {WriteLn('b[', i, ']=', ord(b), ' ', sz); }
    end;
    end;
    end;


    I get
    Length = 32
    b[ 1]=
    b[ 2]=
    b[ 4]=
    b[ 5]=
    b[ 7]=
    b[ 8]=
    b[ 10]=
    b[ 11]=


    Note that third byte is not being returned when I look for the Ord, or even if I don't request the ord and just iterate the loop, nor the 6th. I believe these will be ASCII 1 or 2 e.g. the TELNET ECHO command.

    While I am asking this it would be lovely if you could implement the @ function for procedures - writing standardised libraries for these is so much easier!!

    Thanks
    Mark



    Thanks
    Mark
     
    MHeaton, May 30, 2015
    #7
  8. djaggar

    djaggar

    Joined:
    Jul 18, 2009
    Messages:
    66
    Likes Received:
    0
    Location:
    New Zealand
    Yes, Clipsal fixed the zero byte thing very quickly.

    I'm sorry if I'm missing something, but it looks to me like your last writeln is just in the wrong place, if you move it after the following 'end;' won't you get every byte of the buffer displayed ? At the moment it is in the if (ord(b) >= 236) then clause ...
     
    djaggar, May 31, 2015
    #8
  9. djaggar

    MHeaton

    Joined:
    Apr 22, 2008
    Messages:
    103
    Likes Received:
    1
    Location:
    London
    Thank you for pointing out the obvious!!
    :mad:
    You are spot on!
    Thanks
    Mark
     
    MHeaton, May 31, 2015
    #9
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.