gamedata.selected_world = filterlist.get_raw_index(worldlist,selected)
engine.setting_set("port",gamedata.port)
+ if fields["te_serveraddr"] ~= nil then
+ engine.setting_set("bind_address",fields["te_serveraddr"])
+ end
menu.update_last_game(gamedata.selected_world)
engine.start()
dump(engine.setting_getbool("enable_damage")) .. "]"..
"checkbox[0.5,1.15;cb_server_announce;".. fgettext("Public") .. ";" ..
dump(engine.setting_getbool("server_announce")) .. "]"..
- "field[0.8,3.2;3,0.5;te_playername;".. fgettext("Name") .. ";" ..
+ "field[0.8,3.2;3.5,0.5;te_playername;".. fgettext("Name") .. ";" ..
engine.setting_get("name") .. "]" ..
- "pwdfield[0.8,4.2;3,0.5;te_passwd;".. fgettext("Password") .. "]" ..
- "field[0.8,5.2;3,0.5;te_serverport;".. fgettext("Server Port") .. ";" ..
- engine.setting_get("port") .."]" ..
+ "pwdfield[0.8,4.2;3.5,0.5;te_passwd;".. fgettext("Password") .. "]"
+
+ local bind_addr = engine.setting_get("bind_address")
+ if bind_addr ~= nil and bind_addr ~= "" then
+ retval = retval ..
+ "field[0.8,5.2;2.25,0.5;te_serveraddr;".. fgettext("Bind Address") .. ";" ..
+ engine.setting_get("bind_address") .."]" ..
+ "field[3.05,5.2;1.25,0.5;te_serverport;".. fgettext("Port") .. ";" ..
+ engine.setting_get("port") .."]"
+ else
+ retval = retval ..
+ "field[0.8,5.2;3.5,0.5;te_serverport;".. fgettext("Server Port") .. ";" ..
+ engine.setting_get("port") .."]"
+ end
+
+ retval = retval ..
"textlist[4,0.25;7.5,3.7;srv_worlds;" ..
menu.render_world_list() ..
";" .. index .. "]"
# Server stuff
#
# Network port to listen (UDP)
-#port =
+#port = 30000
+# Bind address
+#bind_address =
# Name of server
#server_name = Minetest server
# Description of server
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);
}
}
-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){
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);
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)
}
}
-void Connection::Serve(unsigned short port)
+void Connection::Serve(Address bind_addr)
{
ConnectionCommand c;
- c.serve(port);
+ c.serve(bind_addr);
putCommand(c);
}
struct ConnectionCommand
{
enum ConnectionCommandType type;
- u16 port;
Address address;
u16 peer_id;
u8 channelnum;
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_)
{
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);
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();
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");
// 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))) {
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))
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"))
return 0;
}
- server.start(port);
+ server.start(bind_addr);
// Run server
dedicated_server_loop(server, kill);
}
}
-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();
<<" \\/ \\/ \\/ \\/ \\/ "<<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()
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.
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);
}
#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)
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;
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)
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);
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;
// 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));
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);