OK, for the benefit of others listening in, this is what I've briefly
described to Steve and Anders on suse-linux-e - who both said "it's
impossible" - which I agree with. Reality however seems to be of a
different opinion.
I'm writing a simple, multi-threaded SMTP proxy. New connections are
received/accepted, packed into a unit-of-work, then queued for one of X
worker-threads to pick up. Each UOW has the socket returned by the
accept call. I refer to this as the "left side". When a UOW is picked
up for processing, the thread will connect to the outbound side (the
"right side"), and then start processing.
Here's roughly what happens: (code attached)
check that the socket is still valid - the client could have gone away
whilst the UOW was queued.
connect to right side (create socket etc.)
create a copy of the socket - new one is called right2.
The original is set nonblocking.
Now create streams, one on each socket.
Similar thing for the left side.
The main code (not attached) now uses select() on the left and right
inbound, nonblocking sockets, and when e.g. the left side has some data
for us,:
if ( FD_ISSET(left,&readfds) )
{
closed=1;
while( NULL!=fgets( buffer, sizeof(buffer), left_in ) )
{
closed=0;
while( EOF==(rc=fputs( buffer, right_out )) )
{
if ( errno!=EAGAIN ) break;
log_error( "[%02u.%04u] %d.2: unable to write to
right; error %d: %s\n", c->id, work->id, stage, errno,
strerror(errno) );
sleep(1);
}
if ( EOF==rc )
{
stage=99;
break;
}
}
fflush( right_out );
// if the left side closed the connection
if ( closed )
{
log_error( "right side closed??\n");
stage=99;
}
}
/Per Jessen, Zürich