thinking about it... why not just let stream() fail and let the program
decide if it makes sense to continue without it?
way simpler than the struct Stream bookkeeping or returning a pipe
and spawning a relay process in the background.
fd = open(....);
/* use streaming if possible */
if((sfd = stream(fd)) >= 0)
dup(sfd, fd);
--
cinap
--- Begin Message ---
On Sat, Jan 8, 2011 at 4:31 PM, <[email protected]> wrote:
> the use of tcp to get flow control is an interesting idea.
>
> some remaks:
>
> the client only gets the dial string of a new tcp connection. an
> attacker could guess the port numbers and take over the stream. or
> the client might be delayed before it makes the dial() causing it to
> get the wrong stream or some other random tcp connection at the same
> port.
>
> the initial 9p channel might be encrypted (common when you use
> cpu), but the stream data excapes as cleartext... compromising security.
>
I had thought about the security problem. I acknowledge that it's
possible for an attacker to guess the port, but he has to guess in
that small time frame between when the server opens the port and the
client connects. I haven't heard of FTP having problems with that,
though.
And, of course, if you encrypt the streaming data, it doesn't matter
if an attacker guesses the port.
> on the implementation, the server might give the wrong ip address
> (because he is behind some nat gateway) causing the dial to fail. i think
> the stream() call should fallback to the original filedescriptor then.
I had considered this case (the server doesn't know which IP to give)
but managed to forget to include the simple check "did dial fail?"
> why do we pass the offset and mode in the pstream syscall? devmnt
> should know the current offset and mode from the Chan structure right?
>
> i think you could simplify the userspace interface a little bit
> further. for example, i see no use for the Stream structure and
> sread/swrite as they never fall back on the old filedescriptor and all
> the decisions are already made in the stream() call (except the
> isread check).
>
> what about this:
>
> newfd = stream(oldfd, ....);
>
> int
> stream(int fd, vlong offset, char isread)
> {
> for(;;){
> char addr[Maxstring];
> int r;
>
> if((r = pstream(fd, addr, offset, isread)) < 0)
> break;
> if(addr[0] == 0)
> break;
> if((r = dial(addr, 0, 0, 0)) < 0)
> break;
>
> return r;
> }
>
> /* server doesnt support Tstream */
> if((fd = dup(fd, -1)) >= 0)
> seek(fd, offset, 0);
> return fd;
> }
>
This ought to work, but I wanted to establish a difference between
regular fds, which you can read and write and seek and all that
goodness, and streams, which are for reading OR writing sequentially.
I also wanted to give an error if you tried to read from a write
stream and vice versa; your stream() doesn't seem to do that.
Like I said, it's not perfect, and there's probably a better way to do it.
John
--- End Message ---