diff options
author | ShadowNinja <shadowninja@minetest.net> | 2014-02-05 21:24:46 +0100 |
---|---|---|
committer | sapier <Sapier at GMX dot net> | 2014-02-05 21:24:46 +0100 |
commit | 85fe75d1cbaf372f0a98558adcd5a612a0e19602 (patch) | |
tree | 8a552ca0e7bb69b192568037bb2857501abe0674 /src | |
parent | 7f743178db2a45bd3f68ef2c9c7df6deca1f3ab6 (diff) | |
download | minetest-85fe75d1cbaf372f0a98558adcd5a612a0e19602.tar.gz minetest-85fe75d1cbaf372f0a98558adcd5a612a0e19602.tar.bz2 minetest-85fe75d1cbaf372f0a98558adcd5a612a0e19602.zip |
Add the option to bind to a specific address
Diffstat (limited to 'src')
-rw-r--r-- | src/connection.cpp | 27 | ||||
-rw-r--r-- | src/connection.h | 9 | ||||
-rw-r--r-- | src/defaultsettings.cpp | 1 | ||||
-rw-r--r-- | src/game.cpp | 26 | ||||
-rw-r--r-- | src/main.cpp | 17 | ||||
-rw-r--r-- | src/server.cpp | 10 | ||||
-rw-r--r-- | src/server.h | 2 | ||||
-rw-r--r-- | src/socket.cpp | 27 | ||||
-rw-r--r-- | src/socket.h | 2 | ||||
-rw-r--r-- | src/test.cpp | 9 |
10 files changed, 95 insertions, 35 deletions
diff --git a/src/connection.cpp b/src/connection.cpp index 92f9f8ec2..f8c68ed2e 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1597,8 +1597,8 @@ void ConnectionSendThread::processNonReliableCommand(ConnectionCommand &c) return; case CONNCMD_SERVE: LOG(dout_con<<m_connection->getDesc()<<" UDP processing CONNCMD_SERVE port=" - <<c.port<<std::endl); - serve(c.port); + <<c.address.serializeString()<<std::endl); + serve(c.address); return; case CONNCMD_CONNECT: LOG(dout_con<<m_connection->getDesc()<<" UDP processing CONNCMD_CONNECT"<<std::endl); @@ -1631,11 +1631,12 @@ void ConnectionSendThread::processNonReliableCommand(ConnectionCommand &c) } } -void ConnectionSendThread::serve(u16 port) +void ConnectionSendThread::serve(Address bind_address) { - LOG(dout_con<<m_connection->getDesc()<<"UDP serving at port "<<port<<std::endl); + LOG(dout_con<<m_connection->getDesc() + <<"UDP serving at port " << bind_address.serializeString() <<std::endl); try{ - m_connection->m_udpSocket.Bind(port); + m_connection->m_udpSocket.Bind(bind_address); m_connection->SetPeerID(PEER_ID_SERVER); } catch(SocketException &e){ @@ -1658,7 +1659,14 @@ void ConnectionSendThread::connect(Address address) e.peerAdded(peer->id, peer->address); m_connection->putEvent(e); - m_connection->m_udpSocket.Bind(0); + Address bind_addr; + + if (address.isIPv6()) + bind_addr.setAddress((IPv6AddressBytes*) NULL); + else + bind_addr.setAddress(0,0,0,0); + + m_connection->m_udpSocket.Bind(bind_addr); // Send a dummy packet to server with peer_id = PEER_ID_INEXISTENT m_connection->SetPeerID(PEER_ID_INEXISTENT); @@ -1716,7 +1724,8 @@ void ConnectionSendThread::send(u16 peer_id, u8 channelnum, assert(channelnum < CHANNEL_COUNT); PeerHelper peer = m_connection->getPeerNoEx(peer_id); - if(!peer) { + if(!peer) + { LOG(dout_con<<m_connection->getDesc()<<" peer: peer_id="<<peer_id << ">>>NOT<<< found on sending packet" << ", channel " << (channelnum % 0xFF) @@ -2766,10 +2775,10 @@ void Connection::putCommand(ConnectionCommand &c) } } -void Connection::Serve(unsigned short port) +void Connection::Serve(Address bind_addr) { ConnectionCommand c; - c.serve(port); + c.serve(bind_addr); putCommand(c); } diff --git a/src/connection.h b/src/connection.h index c9474032d..9d646f499 100644 --- a/src/connection.h +++ b/src/connection.h @@ -406,7 +406,6 @@ enum ConnectionCommandType{ struct ConnectionCommand { enum ConnectionCommandType type; - u16 port; Address address; u16 peer_id; u8 channelnum; @@ -416,10 +415,10 @@ struct ConnectionCommand ConnectionCommand(): type(CONNCMD_NONE), peer_id(PEER_ID_INEXISTENT), reliable(false), raw(false) {} - void serve(u16 port_) + void serve(Address address_) { type = CONNCMD_SERVE; - port = port_; + address = address_; } void connect(Address address_) { @@ -912,7 +911,7 @@ private: void processReliableCommand (ConnectionCommand &c); void processNonReliableCommand (ConnectionCommand &c); - void serve (u16 port); + void serve (Address bind_address); void connect (Address address); void disconnect (); void disconnect_peer(u16 peer_id); @@ -996,7 +995,7 @@ public: void putCommand(ConnectionCommand &c); void SetTimeoutMs(int timeout){ m_bc_receive_timeout = timeout; } - void Serve(unsigned short port); + void Serve(Address bind_addr); void Connect(Address address); bool Connected(); void Disconnect(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index bac5e0e2d..9d1aadad9 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -175,6 +175,7 @@ void set_default_settings(Settings *settings) settings->setDefault("workaround_window_size","5"); settings->setDefault("max_packets_per_iteration","1024"); settings->setDefault("port", "30000"); + settings->setDefault("bind_address",""); settings->setDefault("default_game", "minetest"); settings->setDefault("motd", ""); settings->setDefault("max_users", "15"); diff --git a/src/game.cpp b/src/game.cpp index 56519d30a..b540e3314 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -909,8 +909,8 @@ bool nodePlacementPrediction(Client &client, // Dont place node when player would be inside new node // NOTE: This is to be eventually implemented by a mod as client-side Lua - if (!nodedef->get(n).walkable || - (client.checkPrivilege("noclip") && g_settings->getBool("noclip")) || + if (!nodedef->get(n).walkable || + (client.checkPrivilege("noclip") && g_settings->getBool("noclip")) || (nodedef->get(n).walkable && neighbourpos != player->getStandingNodePos() + v3s16(0,1,0) && neighbourpos != player->getStandingNodePos() + v3s16(0,2,0))) { @@ -1029,7 +1029,27 @@ void the_game( infostream<<"Creating server"<<std::endl; server = new Server(map_dir, gamespec, simple_singleplayer_mode); - server->start(port); + + std::string bind_str = g_settings->get("bind_address"); + Address bind_addr(0,0,0,0, port); + + if (bind_str != "") + { + try { + bind_addr.Resolve(bind_str.c_str()); + address = bind_str; + } catch (ResolveError &e) { + infostream << "Resolving bind address \"" << bind_str + << "\" failed: " << e.what() + << " -- Listening on all addresses." << std::endl; + + if (g_settings->getBool("ipv6_server")) { + bind_addr.setAddress((IPv6AddressBytes*) NULL); + } + } + } + + server->start(bind_addr); } do{ // Client scope (breakable do-while(0)) diff --git a/src/main.cpp b/src/main.cpp index 8186e26c8..b5de4b93f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1024,6 +1024,21 @@ int main(int argc, char *argv[]) if(port == 0) port = 30000; + // Bind address + std::string bind_str = g_settings->get("bind_address"); + Address bind_addr(0,0,0,0, port); + try { + bind_addr.Resolve(bind_str.c_str()); + } catch (ResolveError &e) { + infostream << "Resolving bind address \"" << bind_str + << "\" failed: " << e.what() + << " -- Listening on all addresses." << std::endl; + + if (g_settings->getBool("ipv6_server")) { + bind_addr.setAddress((IPv6AddressBytes*) NULL); + } + } + // World directory std::string commanded_world = ""; if(cmd_args.exists("world")) @@ -1270,7 +1285,7 @@ int main(int argc, char *argv[]) return 0; } - server.start(port); + server.start(bind_addr); // Run server dedicated_server_loop(server, kill); diff --git a/src/server.cpp b/src/server.cpp index 00db9128d..151bcada1 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -452,17 +452,18 @@ Server::~Server() } } -void Server::start(unsigned short port) +void Server::start(Address bind_addr) { DSTACK(__FUNCTION_NAME); - infostream<<"Starting server on port "<<port<<"..."<<std::endl; + infostream<<"Starting server on " + << bind_addr.serializeString() <<"..."<<std::endl; // Stop thread if already running m_thread->Stop(); // Initialize connection m_con.SetTimeoutMs(30); - m_con.Serve(port); + m_con.Serve(bind_addr); // Start thread m_thread->Start(); @@ -477,7 +478,8 @@ void Server::start(unsigned short port) <<" \\/ \\/ \\/ \\/ \\/ "<<std::endl; actionstream<<"World at ["<<m_path_world<<"]"<<std::endl; actionstream<<"Server for gameid=\""<<m_gamespec.id - <<"\" listening on port "<<port<<"."<<std::endl; + <<"\" listening on "<<bind_addr.serializeString()<<":" + <<bind_addr.getPort() << "."<<std::endl; } void Server::stop() diff --git a/src/server.h b/src/server.h index 19bedf74a..54078defc 100644 --- a/src/server.h +++ b/src/server.h @@ -177,7 +177,7 @@ public: bool simple_singleplayer_mode ); ~Server(); - void start(unsigned short port); + void start(Address bind_addr); void stop(); // This is mainly a way to pass the time to the server. // Actual processing is done in an another thread. diff --git a/src/socket.cpp b/src/socket.cpp index 78ff364e5..00856fb00 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -92,24 +92,27 @@ void sockets_cleanup() Address::Address() { m_addr_family = 0; - memset(&m_address, 0, sizeof m_address); + memset(&m_address, 0, sizeof(m_address)); m_port = 0; } Address::Address(u32 address, u16 port) { + memset(&m_address, 0, sizeof(m_address)); setAddress(address); setPort(port); } Address::Address(u8 a, u8 b, u8 c, u8 d, u16 port) { + memset(&m_address, 0, sizeof(m_address)); setAddress(a, b, c, d); setPort(port); } Address::Address(const IPv6AddressBytes * ipv6_bytes, u16 port) { + memset(&m_address, 0, sizeof(m_address)); setAddress(ipv6_bytes); setPort(port); } @@ -334,12 +337,20 @@ UDPSocket::~UDPSocket() #endif } -void UDPSocket::Bind(u16 port) +void UDPSocket::Bind(Address addr) { if(socket_enable_debug_output) { dstream << "UDPSocket(" << (int) m_handle << ")::Bind(): " - << "port=" << port << std::endl; + << addr.serializeString() << ":" + << addr.getPort() << std::endl; + } + + if (addr.getFamily() != m_addr_family) + { + char errmsg[] = "Socket and bind address families do not match"; + errorstream << "Bind failed: " << errmsg << std::endl; + throw SocketException(errmsg); } if(m_addr_family == AF_INET6) @@ -347,12 +358,12 @@ void UDPSocket::Bind(u16 port) struct sockaddr_in6 address; memset(&address, 0, sizeof(address)); + address = addr.getAddress6(); address.sin6_family = AF_INET6; - address.sin6_addr = in6addr_any; - address.sin6_port = htons(port); + address.sin6_port = htons(addr.getPort()); if(bind(m_handle, (const struct sockaddr *) &address, - sizeof(struct sockaddr_in6)) < 0) + sizeof(struct sockaddr_in6)) < 0) { dstream << (int) m_handle << ": Bind failed: " << strerror(errno) << std::endl; @@ -364,9 +375,9 @@ void UDPSocket::Bind(u16 port) struct sockaddr_in address; memset(&address, 0, sizeof(address)); + address = addr.getAddress(); address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(port); + address.sin_port = htons(addr.getPort()); if(bind(m_handle, (const struct sockaddr *) &address, sizeof(struct sockaddr_in)) < 0) diff --git a/src/socket.h b/src/socket.h index ba88b0142..7d35a32da 100644 --- a/src/socket.h +++ b/src/socket.h @@ -115,7 +115,7 @@ class UDPSocket public: UDPSocket(bool ipv6); ~UDPSocket(); - void Bind(unsigned short port); + void Bind(Address addr); //void Close(); //bool IsOpen(); void Send(const Address & destination, const void * data, int size); diff --git a/src/test.cpp b/src/test.cpp index c969c0951..dd2691947 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1506,11 +1506,13 @@ struct TestSocket: public TestBase void Run() { const int port = 30003; + Address address(0,0,0,0, port); + Address address6((IPv6AddressBytes*) NULL, port); // IPv6 socket test { UDPSocket socket6(true); - socket6.Bind(port); + socket6.Bind(address6); const char sendbuffer[] = "hello world!"; IPv6AddressBytes bytes; @@ -1536,7 +1538,7 @@ struct TestSocket: public TestBase // IPv4 socket test { UDPSocket socket(false); - socket.Bind(port); + socket.Bind(address); const char sendbuffer[] = "hello world!"; socket.Send(Address(127,0,0,1,port), sendbuffer, sizeof(sendbuffer)); @@ -1656,7 +1658,8 @@ struct TestConnection: public TestBase infostream<<"** Creating server Connection"<<std::endl; con::Connection server(proto_id, 512, 5.0, false, &hand_server); - server.Serve(30001); + Address address(0,0,0,0, 30001); + server.Serve(address); infostream<<"** Creating client Connection"<<std::endl; con::Connection client(proto_id, 512, 5.0, false, &hand_client); |