Support multihomed servers

This commit is contained in:
Keith Winstein
2012-02-02 17:21:49 -05:00
parent 3edccf1f2e
commit 740226e66a
6 changed files with 39 additions and 13 deletions
+17 -2
View File
@@ -84,7 +84,7 @@ void Connection::setup( void )
} }
} }
Connection::Connection() /* server */ Connection::Connection( const char *desired_ip ) /* server */
: sock( -1 ), : sock( -1 ),
remote_addr(), remote_addr(),
server( true ), server( true ),
@@ -103,11 +103,26 @@ Connection::Connection() /* server */
{ {
setup(); setup();
/* Bind to free local port. /* Attempt to bind free local port, with
address client used to connect to us.
This usage does not seem to be endorsed by POSIX. */ This usage does not seem to be endorsed by POSIX. */
struct sockaddr_in local_addr; struct sockaddr_in local_addr;
local_addr.sin_family = AF_INET; local_addr.sin_family = AF_INET;
local_addr.sin_port = htons( 0 ); local_addr.sin_port = htons( 0 );
if ( desired_ip
&& inet_aton( desired_ip, &local_addr.sin_addr )
&& (bind( sock, (sockaddr *)&local_addr, sizeof( local_addr ) ) == 0) ) {
return;
}
if ( desired_ip ) {
fprintf( stderr, "Could not bind to desired local address %s.\n", desired_ip );
}
/* Could not bind to that IP (maybe we are behind NAT).
Try again with any IP. */
local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_addr.s_addr = INADDR_ANY;
if ( bind( sock, (sockaddr *)&local_addr, sizeof( local_addr ) ) < 0 ) { if ( bind( sock, (sockaddr *)&local_addr, sizeof( local_addr ) ) < 0 ) {
throw NetworkException( "bind", errno ); throw NetworkException( "bind", errno );
+2 -2
View File
@@ -85,8 +85,8 @@ namespace Network {
void update_MTU( void ); void update_MTU( void );
public: public:
Connection(); Connection( const char *desired_ip ); /* server */
Connection( const char *key_str, const char *ip, int port ); Connection( const char *key_str, const char *ip, int port ); /* client */
void send( string s ); void send( string s );
string recv( void ); string recv( void );
+3 -2
View File
@@ -9,8 +9,9 @@ using namespace Network;
using namespace std; using namespace std;
template <class MyState, class RemoteState> template <class MyState, class RemoteState>
Transport<MyState, RemoteState>::Transport( MyState &initial_state, RemoteState &initial_remote ) Transport<MyState, RemoteState>::Transport( MyState &initial_state, RemoteState &initial_remote,
: connection(), const char *desired_ip )
: connection( desired_ip ),
sender( &connection, initial_state ), sender( &connection, initial_state ),
received_states( 1, TimestampedState<RemoteState>( timestamp(), 0, initial_remote ) ), received_states( 1, TimestampedState<RemoteState>( timestamp(), 0, initial_remote ) ),
last_receiver_state( initial_remote ), last_receiver_state( initial_remote ),
+1 -1
View File
@@ -34,7 +34,7 @@ namespace Network {
bool verbose; bool verbose;
public: public:
Transport( MyState &initial_state, RemoteState &initial_remote ); Transport( MyState &initial_state, RemoteState &initial_remote, const char *desired_ip );
Transport( MyState &initial_state, RemoteState &initial_remote, Transport( MyState &initial_state, RemoteState &initial_remote,
const char *key_str, const char *ip, int port ); const char *key_str, const char *ip, int port );
+1 -1
View File
@@ -29,7 +29,7 @@ int main( int argc, char *argv[] )
n = new Transport<UserStream, UserStream>( me, remote, key, ip, port ); n = new Transport<UserStream, UserStream>( me, remote, key, ip, port );
} else { } else {
n = new Transport<UserStream, UserStream>( me, remote ); n = new Transport<UserStream, UserStream>( me, remote, NULL );
} }
} catch ( CryptoException e ) { } catch ( CryptoException e ) {
fprintf( stderr, "Fatal error: %s\n", e.text.c_str() ); fprintf( stderr, "Fatal error: %s\n", e.text.c_str() );
+15 -5
View File
@@ -20,12 +20,22 @@
#include "networktransport.cpp" #include "networktransport.cpp"
void serve( int host_fd ); void serve( int host_fd, const char *desired_ip );
using namespace std; using namespace std;
int main( void ) int main( int argc, char *argv[] )
{ {
char *desired_ip = NULL;
if ( argc == 1 ) {
desired_ip = NULL;
} else if ( argc == 2 ) {
desired_ip = argv[ 1 ];
} else {
fprintf( stderr, "Usage: %s [LOCALADDR]\n", argv[ 0 ] );
exit( 1 );
}
int master; int master;
struct termios child_termios; struct termios child_termios;
@@ -98,7 +108,7 @@ int main( void )
exit( 0 ); exit( 0 );
} else { } else {
/* parent */ /* parent */
serve( master ); serve( master, desired_ip );
if ( close( master ) < 0 ) { if ( close( master ) < 0 ) {
perror( "close" ); perror( "close" );
exit( 1 ); exit( 1 );
@@ -110,7 +120,7 @@ int main( void )
return 0; return 0;
} }
void serve( int host_fd ) void serve( int host_fd, const char *desired_ip )
{ {
/* establish fd for shutdown signals */ /* establish fd for shutdown signals */
sigset_t signal_mask; sigset_t signal_mask;
@@ -151,7 +161,7 @@ void serve( int host_fd )
/* open network */ /* open network */
Network::UserStream blank; Network::UserStream blank;
Network::Transport< Terminal::Complete, Network::UserStream > network( terminal, blank ); Network::Transport< Terminal::Complete, Network::UserStream > network( terminal, blank, desired_ip );
network.set_verbose(); network.set_verbose();