Skip to content

Commit 142e2d3

Browse files
sapiersapier
sapier
authored and
sapier
committedApr 8, 2014
Cleanup client init states by bumping protocol version
Don't use TOSERVER_RECEIVED_MEDIA but TOSERVER_CLIENT_READY as indicatio for client ready Handle clients with protocol version < 23 (almost) same way as before Make client tell server about it's version Add client state to not send bogus player position updates prior init complete Add access to statistics information (peer connction time,rtt,version) Fix clients standing stalled in world while preloading item visuals (new clients only) Add get_player_information to read client specific information from lua
1 parent 556bdc2 commit 142e2d3

15 files changed

+625
-144
lines changed
 

‎doc/lua_api.txt

+23
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,29 @@ minetest.features
12001200
minetest.has_feature(arg) -> bool, missing_features
12011201
^ arg: string or table in format {foo=true, bar=true}
12021202
^ missing_features: {foo=true, bar=true}
1203+
minetest.get_player_information(playername)
1204+
^ table containing information about player peer:
1205+
{
1206+
address = "127.0.0.1", -- ip address of client
1207+
ip_version = 4, -- IPv4 / IPv6
1208+
min_rtt = 0.01, -- minimum round trip time
1209+
max_rtt = 0.2, -- maximum round trip time
1210+
avg_rtt = 0.02, -- average round trip time
1211+
min_jitter = 0.01, -- minimum packet time jitter
1212+
max_jitter = 0.5, -- maximum packet time jitter
1213+
avg_jitter = 0.03, -- average packet time jitter
1214+
connection_uptime = 200, -- seconds since client connected
1215+
1216+
-- following information is available on debug build only!!!
1217+
-- DO NOT USE IN MODS
1218+
--ser_vers = 26, -- serialization version used by client
1219+
--prot_vers = 23, -- protocol version used by client
1220+
--major = 0, -- major version number
1221+
--minor = 4, -- minor version number
1222+
--patch = 10, -- patch version number
1223+
--vers_string = "0.4.9-git", -- full version string
1224+
--state = "Active" -- current client state
1225+
}
12031226

12041227
Logging:
12051228
minetest.debug(line)

‎src/client.cpp

+33-24
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
4747
#include "serialization.h"
4848
#include "util/serialize.h"
4949
#include "config.h"
50+
#include "cmake_config_githash.h"
5051
#include "util/directiontables.h"
5152
#include "util/pointedthing.h"
5253
#include "version.h"
@@ -252,7 +253,8 @@ Client::Client(
252253
m_last_time_of_day_f(-1),
253254
m_time_of_day_update_timer(0),
254255
m_recommended_send_interval(0.1),
255-
m_removed_sounds_check_timer(0)
256+
m_removed_sounds_check_timer(0),
257+
m_state(LC_Created)
256258
{
257259
m_packetcounter_timer = 0.0;
258260
//m_delete_unused_sectors_timer = 0.0;
@@ -325,17 +327,6 @@ void Client::connect(Address address)
325327
m_con.Connect(address);
326328
}
327329

328-
bool Client::connectedAndInitialized()
329-
{
330-
if(m_con.Connected() == false)
331-
return false;
332-
333-
if(m_server_ser_ver == SER_FMT_VER_INVALID)
334-
return false;
335-
336-
return true;
337-
}
338-
339330
void Client::step(float dtime)
340331
{
341332
DSTACK(__FUNCTION_NAME);
@@ -372,9 +363,6 @@ void Client::step(float dtime)
372363
m_packetcounter.clear();
373364
}
374365
}
375-
376-
// Get connection status
377-
bool connected = connectedAndInitialized();
378366

379367
#if 0
380368
{
@@ -467,7 +455,7 @@ void Client::step(float dtime)
467455
}
468456
#endif
469457

470-
if(connected == false)
458+
if(m_state == LC_Created)
471459
{
472460
float &counter = m_connection_reinit_timer;
473461
counter -= dtime;
@@ -632,7 +620,7 @@ void Client::step(float dtime)
632620
{
633621
counter = 0.0;
634622
// connectedAndInitialized() is true, peer exists.
635-
float avg_rtt = m_con.GetPeerAvgRTT(PEER_ID_SERVER);
623+
float avg_rtt = getRTT();
636624
infostream<<"Client: avg_rtt="<<avg_rtt<<std::endl;
637625
}
638626
}
@@ -643,7 +631,7 @@ void Client::step(float dtime)
643631
{
644632
float &counter = m_playerpos_send_timer;
645633
counter += dtime;
646-
if(counter >= m_recommended_send_interval)
634+
if((m_state == LC_Ready) && (counter >= m_recommended_send_interval))
647635
{
648636
counter = 0.0;
649637
sendPlayerPos();
@@ -1051,6 +1039,8 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
10511039
// Send as reliable
10521040
m_con.Send(PEER_ID_SERVER, 1, reply, true);
10531041

1042+
m_state = LC_Init;
1043+
10541044
return;
10551045
}
10561046

@@ -1937,7 +1927,7 @@ void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
19371927

19381928
void Client::interact(u8 action, const PointedThing& pointed)
19391929
{
1940-
if(connectedAndInitialized() == false){
1930+
if(m_state != LC_Ready){
19411931
infostream<<"Client::interact() "
19421932
"cancelled (not connected)"
19431933
<<std::endl;
@@ -2152,6 +2142,27 @@ void Client::sendRespawn()
21522142
Send(0, data, true);
21532143
}
21542144

2145+
void Client::sendReady()
2146+
{
2147+
DSTACK(__FUNCTION_NAME);
2148+
std::ostringstream os(std::ios_base::binary);
2149+
2150+
writeU16(os, TOSERVER_CLIENT_READY);
2151+
writeU8(os,VERSION_MAJOR);
2152+
writeU8(os,VERSION_MINOR);
2153+
writeU8(os,VERSION_PATCH_ORIG);
2154+
writeU8(os,0);
2155+
2156+
writeU16(os,strlen(CMAKE_VERSION_GITHASH));
2157+
os.write(CMAKE_VERSION_GITHASH,strlen(CMAKE_VERSION_GITHASH));
2158+
2159+
// Make data buffer
2160+
std::string s = os.str();
2161+
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2162+
// Send as reliable
2163+
Send(0, data, true);
2164+
}
2165+
21552166
void Client::sendPlayerPos()
21562167
{
21572168
LocalPlayer *myplayer = m_env.getLocalPlayer();
@@ -2650,16 +2661,14 @@ void Client::afterContentReceived(IrrlichtDevice *device, gui::IGUIFont* font)
26502661
infostream<<"- Starting mesh update thread"<<std::endl;
26512662
m_mesh_update_thread.Start();
26522663

2664+
m_state = LC_Ready;
2665+
sendReady();
26532666
infostream<<"Client::afterContentReceived() done"<<std::endl;
26542667
}
26552668

26562669
float Client::getRTT(void)
26572670
{
2658-
try{
2659-
return m_con.GetPeerAvgRTT(PEER_ID_SERVER);
2660-
} catch(con::PeerNotFoundException &e){
2661-
return 1337;
2662-
}
2671+
return m_con.getPeerStat(PEER_ID_SERVER,con::AVG_RTT);
26632672
}
26642673

26652674
// IGameDef interface

‎src/client.h

+13-8
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ struct QueuedMeshUpdate
5757
~QueuedMeshUpdate();
5858
};
5959

60+
enum LocalClientState {
61+
LC_Created,
62+
LC_Init,
63+
LC_Ready
64+
};
65+
6066
/*
6167
A thread-safe queue of mesh update tasks
6268
*/
@@ -319,14 +325,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
319325
calling this, as it is sent in the initialization.
320326
*/
321327
void connect(Address address);
322-
/*
323-
returns true when
324-
m_con.Connected() == true
325-
AND m_server_ser_ver != SER_FMT_VER_INVALID
326-
throws con::PeerNotFoundException if connection has been deleted,
327-
eg. timed out.
328-
*/
329-
bool connectedAndInitialized();
328+
330329
/*
331330
Stuff that references the environment is valid only as
332331
long as this is not called. (eg. Players)
@@ -354,6 +353,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
354353
void sendDamage(u8 damage);
355354
void sendBreath(u16 breath);
356355
void sendRespawn();
356+
void sendReady();
357357

358358
ClientEnvironment& getEnv()
359359
{ return m_env; }
@@ -454,6 +454,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
454454
// Send a notification that no conventional media transfer is needed
455455
void received_media();
456456

457+
LocalClientState getState() { return m_state; }
458+
457459
private:
458460

459461
// Virtual methods from con::PeerHandler
@@ -537,6 +539,9 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
537539

538540
// Storage for mesh data for creating multiple instances of the same mesh
539541
std::map<std::string, std::string> m_mesh_data;
542+
543+
// own state
544+
LocalClientState m_state;
540545
};
541546

542547
#endif // !CLIENT_HEADER

‎src/clientiface.cpp

+37-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
1717
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1818
*/
1919

20+
#include <sstream>
21+
2022
#include "clientiface.h"
2123
#include "player.h"
2224
#include "settings.h"
@@ -397,10 +399,11 @@ void RemoteClient::SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks)
397399

398400
void RemoteClient::notifyEvent(ClientStateEvent event)
399401
{
402+
std::ostringstream myerror;
400403
switch (m_state)
401404
{
402405
case Invalid:
403-
assert("State update for client in invalid state" != 0);
406+
//intentionally do nothing
404407
break;
405408

406409
case Created:
@@ -420,7 +423,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
420423

421424
/* GotInit2 SetDefinitionsSent SetMediaSent */
422425
default:
423-
assert("Invalid client state transition!" == 0);
426+
myerror << "Created: Invalid client state transition! " << event;
427+
throw ClientStateError(myerror.str());
424428
}
425429
break;
426430

@@ -446,7 +450,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
446450

447451
/* Init SetDefinitionsSent SetMediaSent */
448452
default:
449-
assert("Invalid client state transition!" == 0);
453+
myerror << "InitSent: Invalid client state transition! " << event;
454+
throw ClientStateError(myerror.str());
450455
}
451456
break;
452457

@@ -467,14 +472,15 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
467472

468473
/* Init GotInit2 SetMediaSent */
469474
default:
470-
assert("Invalid client state transition!" == 0);
475+
myerror << "InitDone: Invalid client state transition! " << event;
476+
throw ClientStateError(myerror.str());
471477
}
472478
break;
473479

474480
case DefinitionsSent:
475481
switch(event)
476482
{
477-
case SetMediaSent:
483+
case SetClientReady:
478484
m_state = Active;
479485
break;
480486

@@ -488,7 +494,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
488494

489495
/* Init GotInit2 SetDefinitionsSent */
490496
default:
491-
assert("Invalid client state transition!" == 0);
497+
myerror << "DefinitionsSent: Invalid client state transition! " << event;
498+
throw ClientStateError(myerror.str());
492499
}
493500
break;
494501

@@ -505,7 +512,8 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
505512

506513
/* Init GotInit2 SetDefinitionsSent SetMediaSent SetDenied */
507514
default:
508-
assert("Invalid client state transition!" == 0);
515+
myerror << "Active: Invalid client state transition! " << event;
516+
throw ClientStateError(myerror.str());
509517
break;
510518
}
511519
break;
@@ -516,6 +524,11 @@ void RemoteClient::notifyEvent(ClientStateEvent event)
516524
}
517525
}
518526

527+
u32 RemoteClient::uptime()
528+
{
529+
return getTime(PRECISION_SECONDS) - m_connection_time;
530+
}
531+
519532
ClientInterface::ClientInterface(con::Connection* con)
520533
:
521534
m_con(con),
@@ -749,7 +762,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event)
749762
n->second->notifyEvent(event);
750763
}
751764

752-
if ((event == SetMediaSent) || (event == Disconnect) || (event == SetDenied))
765+
if ((event == SetClientReady) || (event == Disconnect) || (event == SetDenied))
753766
{
754767
UpdatePlayerList();
755768
}
@@ -763,9 +776,24 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id)
763776
std::map<u16, RemoteClient*>::iterator n;
764777
n = m_clients.find(peer_id);
765778

766-
// No client to deliver event
779+
// No client to get version
767780
if (n == m_clients.end())
768781
return 0;
769782

770783
return n->second->net_proto_version;
771784
}
785+
786+
void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full)
787+
{
788+
JMutexAutoLock conlock(m_clients_mutex);
789+
790+
// Error check
791+
std::map<u16, RemoteClient*>::iterator n;
792+
n = m_clients.find(peer_id);
793+
794+
// No client to set versions
795+
if (n == m_clients.end())
796+
return;
797+
798+
n->second->setVersionInfo(major,minor,patch,full);
799+
}

0 commit comments

Comments
 (0)
Please sign in to comment.