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. 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. 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; } -- cinap