|
From: <don...@is...> - 2008-12-29 22:08:28
|
Sam Steingold writes:
> We have a stream which will signal ECONNRESET on read.
> What should we return from SOCKET-STATUS?
> The doc seems to imply :ERROR,
How about whatever it returns for a closed stream?
I guess that's also an error.
> but select() (which we advertise to interface to) returns the FD as
It seems odd that select returns readable when a read will cause an
error.
> readable. Also, what should we return from LISTEN? CLHS says: On
> a non-interactive input-stream, listen returns true except when at
> end of file.
In that case I think the socket stream should be viewed as interactive.
It is certainly the case that there will be times when more data will
be available later but is not yet.
> What does ECONNRESET mean?
Evidently that the connection has been reset.
> SUS says that the peer did a shutdown(), so this is a kind of an EOF.
(SUS ?)
Or perhaps a form of error.
I think of it as analogous to a disk error when you read a file.
> but why then select says that it is readable?
I agree with you on that, but I guess there's not much we can do about
it.
> At any rate, I am tempted to treat this as an EOF (not least
> because it seems easiest to fit this condition into the trichotomy
> of ls_avail/ls_eof/ls_wait.
The easiest alternative I see is to simply document that
socket-status may signal an error, and that it has been known to do
so under the following circumstances...
> > BTW, as part of my search I started to suspect the checksum routines
> > and I did find a few small problems with them. More on that later...
> waiting.
I noticed first that ipcsum returns a value of the checksum with the
bytes swapped. Perhaps this is not an error since I saw no doc on
what value it should return. But the tcp checksum returns the
checksum without the bytes swapped.
I also thought I'd just compare the checksums of incomimg packets, on
the assumption that they are probably correct, with those computed by
clisp code:
(defmacro 16bits(buffer index)
`(+ (aref ,buffer (1+ ,index))
(ash (aref ,buffer ,index) 8)))
(defun checkpktsums()
(loop with i = 0 do
(setf (fill-pointer default-buffer) 1518)
(setf len (rawsock:recvfrom default-socket default-buffer default-device))
(when (and (>= len 52)
(= (aref default-buffer 12) 8) ;; ip
(= (aref default-buffer 13) 0)
(= (aref default-buffer 14) 69) ;; ipv4, len 5
(= (aref default-buffer 23) 6) ;; tcp
)
(setf oldcsum (16bits default-buffer (+ 14 10)))
(rawsock:ipcsum default-buffer)
(setf fredcsum (16bits default-buffer (+ 14 10)))
(unless (= oldcsum fredcsum )
(break "ip sums differ ~a ~a" oldcsum fredcsum))
(setf oldcsum (16bits default-buffer
(+ 14 16 (ash (logand (aref buffer 14) 15) 2))))
(rawsock:tcpcsum default-buffer)
(setf fredcsum (16bits default-buffer
(+ 14 16 (ash (logand (aref buffer 14) 15) 2))))
(unless (= oldcsum fredcsum )
(break "tcp sums differ ~a ~a" oldcsum fredcsum))
(when (= 0 (mod (incf i) 100))(princ "*")))))
#|
[216]> (CHECKPKTSUMS)
*************************************************************************************************************************************************************************************************************************************************************** - Continuable Error
tcp sums differ FFFF 0
|#
This suggests that clisp code is adding the carry bit one time when it
should not. When I looked at the code I thought the IP looked
suspect, like it's swapping bytes, but it does seem to agree with the
incoming packets. Although it might well contain an extra carry add.
The error above was just the first that arrived.
> > Now in another process on the same client machine
> >
> > $ telnet 64.27.16.100 1234
> > Trying 64.27.16.100...
> > Connected to 64.27.16.100 (64.27.16.100).
> > Escape character is '^]'.
>
> I wish this could be folded into reset.lisp.
> it appears that it does matter that waitforpkt is started before
> telnet though.
The telnet could have been simulated entirely from the raw socket.
It was just easier to use some program that was already prepared to
open a connection.
Now that you mention it, the telnet is really no different from
opening a tcp connection from lisp. Or equivalently, lisp could start
a telnet from a shell command. The fact that the wait is running
during that time I think is really not essential cause I think the raw
socket does its own buffering. So you can open the raw socket, then
open the tcp connection, then read from the raw socket. Of course, if
you want to try out multithreading ...
If you were looking for something to add to the test suite, I think
the bigger problem is that you have to be root.
|