clientpackethandler.cpp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. /*
  2. Minetest
  3. Copyright (C) 2015 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include "client.h"
  17. #include "util/base64.h"
  18. #include "chatmessage.h"
  19. #include "clientmedia.h"
  20. #include "log.h"
  21. #include "map.h"
  22. #include "mapsector.h"
  23. #include "minimap.h"
  24. #include "modchannels.h"
  25. #include "nodedef.h"
  26. #include "serialization.h"
  27. #include "server.h"
  28. #include "util/strfnd.h"
  29. #include "client/clientevent.h"
  30. #include "client/sound.h"
  31. #include "network/clientopcodes.h"
  32. #include "network/connection.h"
  33. #include "script/scripting_client.h"
  34. #include "util/serialize.h"
  35. #include "util/srp.h"
  36. #include "tileanimation.h"
  37. #include "gettext.h"
  38. void Client::handleCommand_Deprecated(NetworkPacket* pkt)
  39. {
  40. infostream << "Got deprecated command "
  41. << toClientCommandTable[pkt->getCommand()].name << " from peer "
  42. << pkt->getPeerId() << "!" << std::endl;
  43. }
  44. void Client::handleCommand_Hello(NetworkPacket* pkt)
  45. {
  46. if (pkt->getSize() < 1)
  47. return;
  48. u8 serialization_ver;
  49. u16 proto_ver;
  50. u16 compression_mode;
  51. u32 auth_mechs;
  52. std::string username_legacy; // for case insensitivity
  53. *pkt >> serialization_ver >> compression_mode >> proto_ver
  54. >> auth_mechs >> username_legacy;
  55. // Chose an auth method we support
  56. AuthMechanism chosen_auth_mechanism = choseAuthMech(auth_mechs);
  57. infostream << "Client: TOCLIENT_HELLO received with "
  58. << "serialization_ver=" << (u32)serialization_ver
  59. << ", auth_mechs=" << auth_mechs
  60. << ", proto_ver=" << proto_ver
  61. << ", compression_mode=" << compression_mode
  62. << ". Doing auth with mech " << chosen_auth_mechanism << std::endl;
  63. if (!ser_ver_supported(serialization_ver)) {
  64. infostream << "Client: TOCLIENT_HELLO: Server sent "
  65. << "unsupported ser_fmt_ver"<< std::endl;
  66. return;
  67. }
  68. m_server_ser_ver = serialization_ver;
  69. m_proto_ver = proto_ver;
  70. //TODO verify that username_legacy matches sent username, only
  71. // differs in casing (make both uppercase and compare)
  72. // This is only neccessary though when we actually want to add casing support
  73. if (m_chosen_auth_mech != AUTH_MECHANISM_NONE) {
  74. // we recieved a TOCLIENT_HELLO while auth was already going on
  75. errorstream << "Client: TOCLIENT_HELLO while auth was already going on"
  76. << "(chosen_mech=" << m_chosen_auth_mech << ")." << std::endl;
  77. if (m_chosen_auth_mech == AUTH_MECHANISM_SRP ||
  78. m_chosen_auth_mech == AUTH_MECHANISM_LEGACY_PASSWORD) {
  79. srp_user_delete((SRPUser *) m_auth_data);
  80. m_auth_data = 0;
  81. }
  82. }
  83. // Authenticate using that method, or abort if there wasn't any method found
  84. if (chosen_auth_mechanism != AUTH_MECHANISM_NONE) {
  85. if (chosen_auth_mechanism == AUTH_MECHANISM_FIRST_SRP
  86. && !m_simple_singleplayer_mode) {
  87. promptConfirmRegistration(chosen_auth_mechanism);
  88. } else {
  89. startAuth(chosen_auth_mechanism);
  90. }
  91. } else {
  92. m_chosen_auth_mech = AUTH_MECHANISM_NONE;
  93. m_access_denied = true;
  94. m_access_denied_reason = "Unknown";
  95. m_con->Disconnect();
  96. }
  97. }
  98. void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
  99. {
  100. deleteAuthData();
  101. v3f playerpos;
  102. *pkt >> playerpos >> m_map_seed >> m_recommended_send_interval
  103. >> m_sudo_auth_methods;
  104. playerpos -= v3f(0, BS / 2, 0);
  105. // Set player position
  106. LocalPlayer *player = m_env.getLocalPlayer();
  107. assert(player != NULL);
  108. player->setPosition(playerpos);
  109. infostream << "Client: received map seed: " << m_map_seed << std::endl;
  110. infostream << "Client: received recommended send interval "
  111. << m_recommended_send_interval<<std::endl;
  112. // Reply to server
  113. std::string lang = gettext("LANG_CODE");
  114. if (lang == "LANG_CODE")
  115. lang = "";
  116. NetworkPacket resp_pkt(TOSERVER_INIT2, sizeof(u16) + lang.size());
  117. resp_pkt << lang;
  118. Send(&resp_pkt);
  119. m_state = LC_Init;
  120. }
  121. void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
  122. {
  123. deleteAuthData();
  124. m_password = m_new_password;
  125. verbosestream << "Client: Recieved TOCLIENT_ACCEPT_SUDO_MODE." << std::endl;
  126. // send packet to actually set the password
  127. startAuth(AUTH_MECHANISM_FIRST_SRP);
  128. // reset again
  129. m_chosen_auth_mech = AUTH_MECHANISM_NONE;
  130. }
  131. void Client::handleCommand_DenySudoMode(NetworkPacket* pkt)
  132. {
  133. ChatMessage *chatMessage = new ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
  134. L"Password change denied. Password NOT changed.");
  135. pushToChatQueue(chatMessage);
  136. // reset everything and be sad
  137. deleteAuthData();
  138. }
  139. void Client::handleCommand_AccessDenied(NetworkPacket* pkt)
  140. {
  141. // The server didn't like our password. Note, this needs
  142. // to be processed even if the serialisation format has
  143. // not been agreed yet, the same as TOCLIENT_INIT.
  144. m_access_denied = true;
  145. m_access_denied_reason = "Unknown";
  146. if (pkt->getCommand() != TOCLIENT_ACCESS_DENIED) {
  147. // 13/03/15 Legacy code from 0.4.12 and lesser but is still used
  148. // in some places of the server code
  149. if (pkt->getSize() >= 2) {
  150. std::wstring wide_reason;
  151. *pkt >> wide_reason;
  152. m_access_denied_reason = wide_to_utf8(wide_reason);
  153. }
  154. return;
  155. }
  156. if (pkt->getSize() < 1)
  157. return;
  158. u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
  159. *pkt >> denyCode;
  160. if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN ||
  161. denyCode == SERVER_ACCESSDENIED_CRASH) {
  162. *pkt >> m_access_denied_reason;
  163. if (m_access_denied_reason.empty()) {
  164. m_access_denied_reason = accessDeniedStrings[denyCode];
  165. }
  166. u8 reconnect;
  167. *pkt >> reconnect;
  168. m_access_denied_reconnect = reconnect & 1;
  169. } else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
  170. *pkt >> m_access_denied_reason;
  171. } else if (denyCode < SERVER_ACCESSDENIED_MAX) {
  172. m_access_denied_reason = accessDeniedStrings[denyCode];
  173. } else {
  174. // Allow us to add new error messages to the
  175. // protocol without raising the protocol version, if we want to.
  176. // Until then (which may be never), this is outside
  177. // of the defined protocol.
  178. *pkt >> m_access_denied_reason;
  179. if (m_access_denied_reason.empty()) {
  180. m_access_denied_reason = "Unknown";
  181. }
  182. }
  183. }
  184. void Client::handleCommand_RemoveNode(NetworkPacket* pkt)
  185. {
  186. if (pkt->getSize() < 6)
  187. return;
  188. v3s16 p;
  189. *pkt >> p;
  190. removeNode(p);
  191. }
  192. void Client::handleCommand_AddNode(NetworkPacket* pkt)
  193. {
  194. if (pkt->getSize() < 6 + MapNode::serializedLength(m_server_ser_ver))
  195. return;
  196. v3s16 p;
  197. *pkt >> p;
  198. MapNode n;
  199. n.deSerialize(pkt->getU8Ptr(6), m_server_ser_ver);
  200. bool remove_metadata = true;
  201. u32 index = 6 + MapNode::serializedLength(m_server_ser_ver);
  202. if ((pkt->getSize() >= index + 1) && pkt->getU8(index)) {
  203. remove_metadata = false;
  204. }
  205. addNode(p, n, remove_metadata);
  206. }
  207. void Client::handleCommand_BlockData(NetworkPacket* pkt)
  208. {
  209. // Ignore too small packet
  210. if (pkt->getSize() < 6)
  211. return;
  212. v3s16 p;
  213. *pkt >> p;
  214. std::string datastring(pkt->getString(6), pkt->getSize() - 6);
  215. std::istringstream istr(datastring, std::ios_base::binary);
  216. MapSector *sector;
  217. MapBlock *block;
  218. v2s16 p2d(p.X, p.Z);
  219. sector = m_env.getMap().emergeSector(p2d);
  220. assert(sector->getPos() == p2d);
  221. block = sector->getBlockNoCreateNoEx(p.Y);
  222. if (block) {
  223. /*
  224. Update an existing block
  225. */
  226. block->deSerialize(istr, m_server_ser_ver, false);
  227. block->deSerializeNetworkSpecific(istr);
  228. }
  229. else {
  230. /*
  231. Create a new block
  232. */
  233. block = new MapBlock(&m_env.getMap(), p, this);
  234. block->deSerialize(istr, m_server_ser_ver, false);
  235. block->deSerializeNetworkSpecific(istr);
  236. sector->insertBlock(block);
  237. }
  238. if (m_localdb) {
  239. ServerMap::saveBlock(block, m_localdb);
  240. }
  241. /*
  242. Add it to mesh update queue and set it to be acknowledged after update.
  243. */
  244. addUpdateMeshTaskWithEdge(p, true);
  245. }
  246. void Client::handleCommand_Inventory(NetworkPacket* pkt)
  247. {
  248. if (pkt->getSize() < 1)
  249. return;
  250. std::string datastring(pkt->getString(0), pkt->getSize());
  251. std::istringstream is(datastring, std::ios_base::binary);
  252. LocalPlayer *player = m_env.getLocalPlayer();
  253. assert(player != NULL);
  254. player->inventory.deSerialize(is);
  255. m_inventory_updated = true;
  256. delete m_inventory_from_server;
  257. m_inventory_from_server = new Inventory(player->inventory);
  258. m_inventory_from_server_age = 0.0;
  259. }
  260. void Client::handleCommand_TimeOfDay(NetworkPacket* pkt)
  261. {
  262. if (pkt->getSize() < 2)
  263. return;
  264. u16 time_of_day;
  265. *pkt >> time_of_day;
  266. time_of_day = time_of_day % 24000;
  267. float time_speed = 0;
  268. if (pkt->getSize() >= 2 + 4) {
  269. *pkt >> time_speed;
  270. }
  271. else {
  272. // Old message; try to approximate speed of time by ourselves
  273. float time_of_day_f = (float)time_of_day / 24000.0f;
  274. float tod_diff_f = 0;
  275. if (time_of_day_f < 0.2 && m_last_time_of_day_f > 0.8)
  276. tod_diff_f = time_of_day_f - m_last_time_of_day_f + 1.0f;
  277. else
  278. tod_diff_f = time_of_day_f - m_last_time_of_day_f;
  279. m_last_time_of_day_f = time_of_day_f;
  280. float time_diff = m_time_of_day_update_timer;
  281. m_time_of_day_update_timer = 0;
  282. if (m_time_of_day_set) {
  283. time_speed = (3600.0f * 24.0f) * tod_diff_f / time_diff;
  284. infostream << "Client: Measured time_of_day speed (old format): "
  285. << time_speed << " tod_diff_f=" << tod_diff_f
  286. << " time_diff=" << time_diff << std::endl;
  287. }
  288. }
  289. // Update environment
  290. m_env.setTimeOfDay(time_of_day);
  291. m_env.setTimeOfDaySpeed(time_speed);
  292. m_time_of_day_set = true;
  293. u32 dr = m_env.getDayNightRatio();
  294. infostream << "Client: time_of_day=" << time_of_day
  295. << " time_speed=" << time_speed
  296. << " dr=" << dr << std::endl;
  297. }
  298. void Client::handleCommand_ChatMessage(NetworkPacket *pkt)
  299. {
  300. /*
  301. u8 version
  302. u8 message_type
  303. u16 sendername length
  304. wstring sendername
  305. u16 length
  306. wstring message
  307. */
  308. ChatMessage *chatMessage = new ChatMessage();
  309. u8 version, message_type;
  310. *pkt >> version >> message_type;
  311. if (version != 1 || message_type >= CHATMESSAGE_TYPE_MAX) {
  312. delete chatMessage;
  313. return;
  314. }
  315. *pkt >> chatMessage->sender >> chatMessage->message >> chatMessage->timestamp;
  316. chatMessage->type = (ChatMessageType) message_type;
  317. // @TODO send this to CSM using ChatMessage object
  318. if (!moddingEnabled() || !m_script->on_receiving_message(
  319. wide_to_utf8(chatMessage->message))) {
  320. pushToChatQueue(chatMessage);
  321. } else {
  322. // Message was consumed by CSM and should not handled by client, destroying
  323. delete chatMessage;
  324. }
  325. }
  326. void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
  327. {
  328. /*
  329. u16 count of removed objects
  330. for all removed objects {
  331. u16 id
  332. }
  333. u16 count of added objects
  334. for all added objects {
  335. u16 id
  336. u8 type
  337. u32 initialization data length
  338. string initialization data
  339. }
  340. */
  341. try {
  342. u8 type;
  343. u16 removed_count, added_count, id;
  344. // Read removed objects
  345. *pkt >> removed_count;
  346. for (u16 i = 0; i < removed_count; i++) {
  347. *pkt >> id;
  348. m_env.removeActiveObject(id);
  349. }
  350. // Read added objects
  351. *pkt >> added_count;
  352. for (u16 i = 0; i < added_count; i++) {
  353. *pkt >> id >> type;
  354. m_env.addActiveObject(id, type, pkt->readLongString());
  355. }
  356. } catch (PacketError &e) {
  357. infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
  358. << ". The packet is unreliable, ignoring" << std::endl;
  359. }
  360. }
  361. void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
  362. {
  363. /*
  364. for all objects
  365. {
  366. u16 id
  367. u16 message length
  368. string message
  369. }
  370. */
  371. std::string datastring(pkt->getString(0), pkt->getSize());
  372. std::istringstream is(datastring, std::ios_base::binary);
  373. try {
  374. while (is.good()) {
  375. u16 id = readU16(is);
  376. if (!is.good())
  377. break;
  378. std::string message = deSerializeString(is);
  379. // Pass on to the environment
  380. m_env.processActiveObjectMessage(id, message);
  381. }
  382. } catch (SerializationError &e) {
  383. errorstream << "Client::handleCommand_ActiveObjectMessages: "
  384. << "caught SerializationError: " << e.what() << std::endl;
  385. }
  386. }
  387. void Client::handleCommand_Movement(NetworkPacket* pkt)
  388. {
  389. LocalPlayer *player = m_env.getLocalPlayer();
  390. assert(player != NULL);
  391. float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
  392. *pkt >> mad >> maa >> maf >> msw >> mscr >> msf >> mscl >> msj
  393. >> lf >> lfs >> ls >> g;
  394. player->movement_acceleration_default = mad * BS;
  395. player->movement_acceleration_air = maa * BS;
  396. player->movement_acceleration_fast = maf * BS;
  397. player->movement_speed_walk = msw * BS;
  398. player->movement_speed_crouch = mscr * BS;
  399. player->movement_speed_fast = msf * BS;
  400. player->movement_speed_climb = mscl * BS;
  401. player->movement_speed_jump = msj * BS;
  402. player->movement_liquid_fluidity = lf * BS;
  403. player->movement_liquid_fluidity_smooth = lfs * BS;
  404. player->movement_liquid_sink = ls * BS;
  405. player->movement_gravity = g * BS;
  406. }
  407. void Client::handleCommand_HP(NetworkPacket* pkt)
  408. {
  409. LocalPlayer *player = m_env.getLocalPlayer();
  410. assert(player != NULL);
  411. u16 oldhp = player->hp;
  412. u16 hp;
  413. *pkt >> hp;
  414. player->hp = hp;
  415. if (moddingEnabled()) {
  416. m_script->on_hp_modification(hp);
  417. }
  418. if (hp < oldhp) {
  419. // Add to ClientEvent queue
  420. ClientEvent *event = new ClientEvent();
  421. event->type = CE_PLAYER_DAMAGE;
  422. event->player_damage.amount = oldhp - hp;
  423. m_client_event_queue.push(event);
  424. }
  425. }
  426. void Client::handleCommand_Breath(NetworkPacket* pkt)
  427. {
  428. LocalPlayer *player = m_env.getLocalPlayer();
  429. assert(player != NULL);
  430. u16 breath;
  431. *pkt >> breath;
  432. player->setBreath(breath);
  433. }
  434. void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
  435. {
  436. LocalPlayer *player = m_env.getLocalPlayer();
  437. assert(player != NULL);
  438. v3f pos;
  439. f32 pitch, yaw;
  440. *pkt >> pos >> pitch >> yaw;
  441. player->setPosition(pos);
  442. infostream << "Client got TOCLIENT_MOVE_PLAYER"
  443. << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
  444. << " pitch=" << pitch
  445. << " yaw=" << yaw
  446. << std::endl;
  447. /*
  448. Add to ClientEvent queue.
  449. This has to be sent to the main program because otherwise
  450. it would just force the pitch and yaw values to whatever
  451. the camera points to.
  452. */
  453. ClientEvent *event = new ClientEvent();
  454. event->type = CE_PLAYER_FORCE_MOVE;
  455. event->player_force_move.pitch = pitch;
  456. event->player_force_move.yaw = yaw;
  457. m_client_event_queue.push(event);
  458. }
  459. void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
  460. {
  461. bool set_camera_point_target;
  462. v3f camera_point_target;
  463. *pkt >> set_camera_point_target;
  464. *pkt >> camera_point_target;
  465. ClientEvent *event = new ClientEvent();
  466. event->type = CE_DEATHSCREEN;
  467. event->deathscreen.set_camera_point_target = set_camera_point_target;
  468. event->deathscreen.camera_point_target_x = camera_point_target.X;
  469. event->deathscreen.camera_point_target_y = camera_point_target.Y;
  470. event->deathscreen.camera_point_target_z = camera_point_target.Z;
  471. m_client_event_queue.push(event);
  472. }
  473. void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt)
  474. {
  475. u16 num_files;
  476. *pkt >> num_files;
  477. infostream << "Client: Received media announcement: packet size: "
  478. << pkt->getSize() << std::endl;
  479. if (m_media_downloader == NULL ||
  480. m_media_downloader->isStarted()) {
  481. const char *problem = m_media_downloader ?
  482. "we already saw another announcement" :
  483. "all media has been received already";
  484. errorstream << "Client: Received media announcement but "
  485. << problem << "! "
  486. << " files=" << num_files
  487. << " size=" << pkt->getSize() << std::endl;
  488. return;
  489. }
  490. // Mesh update thread must be stopped while
  491. // updating content definitions
  492. sanity_check(!m_mesh_update_thread.isRunning());
  493. for (u16 i = 0; i < num_files; i++) {
  494. std::string name, sha1_base64;
  495. *pkt >> name >> sha1_base64;
  496. std::string sha1_raw = base64_decode(sha1_base64);
  497. m_media_downloader->addFile(name, sha1_raw);
  498. }
  499. try {
  500. std::string str;
  501. *pkt >> str;
  502. Strfnd sf(str);
  503. while(!sf.at_end()) {
  504. std::string baseurl = trim(sf.next(","));
  505. if (!baseurl.empty())
  506. m_media_downloader->addRemoteServer(baseurl);
  507. }
  508. }
  509. catch(SerializationError& e) {
  510. // not supported by server or turned off
  511. }
  512. m_media_downloader->step(this);
  513. }
  514. void Client::handleCommand_Media(NetworkPacket* pkt)
  515. {
  516. /*
  517. u16 command
  518. u16 total number of file bunches
  519. u16 index of this bunch
  520. u32 number of files in this bunch
  521. for each file {
  522. u16 length of name
  523. string name
  524. u32 length of data
  525. data
  526. }
  527. */
  528. u16 num_bunches;
  529. u16 bunch_i;
  530. u32 num_files;
  531. *pkt >> num_bunches >> bunch_i >> num_files;
  532. infostream << "Client: Received files: bunch " << bunch_i << "/"
  533. << num_bunches << " files=" << num_files
  534. << " size=" << pkt->getSize() << std::endl;
  535. if (num_files == 0)
  536. return;
  537. if (!m_media_downloader || !m_media_downloader->isStarted()) {
  538. const char *problem = m_media_downloader ?
  539. "media has not been requested" :
  540. "all media has been received already";
  541. errorstream << "Client: Received media but "
  542. << problem << "! "
  543. << " bunch " << bunch_i << "/" << num_bunches
  544. << " files=" << num_files
  545. << " size=" << pkt->getSize() << std::endl;
  546. return;
  547. }
  548. // Mesh update thread must be stopped while
  549. // updating content definitions
  550. sanity_check(!m_mesh_update_thread.isRunning());
  551. for (u32 i=0; i < num_files; i++) {
  552. std::string name;
  553. *pkt >> name;
  554. std::string data = pkt->readLongString();
  555. m_media_downloader->conventionalTransferDone(
  556. name, data, this);
  557. }
  558. }
  559. void Client::handleCommand_NodeDef(NetworkPacket* pkt)
  560. {
  561. infostream << "Client: Received node definitions: packet size: "
  562. << pkt->getSize() << std::endl;
  563. // Mesh update thread must be stopped while
  564. // updating content definitions
  565. sanity_check(!m_mesh_update_thread.isRunning());
  566. // Decompress node definitions
  567. std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
  568. std::ostringstream tmp_os;
  569. decompressZlib(tmp_is, tmp_os);
  570. // Deserialize node definitions
  571. std::istringstream tmp_is2(tmp_os.str());
  572. m_nodedef->deSerialize(tmp_is2);
  573. m_nodedef_received = true;
  574. }
  575. void Client::handleCommand_ItemDef(NetworkPacket* pkt)
  576. {
  577. infostream << "Client: Received item definitions: packet size: "
  578. << pkt->getSize() << std::endl;
  579. // Mesh update thread must be stopped while
  580. // updating content definitions
  581. sanity_check(!m_mesh_update_thread.isRunning());
  582. // Decompress item definitions
  583. std::istringstream tmp_is(pkt->readLongString(), std::ios::binary);
  584. std::ostringstream tmp_os;
  585. decompressZlib(tmp_is, tmp_os);
  586. // Deserialize node definitions
  587. std::istringstream tmp_is2(tmp_os.str());
  588. m_itemdef->deSerialize(tmp_is2);
  589. m_itemdef_received = true;
  590. }
  591. void Client::handleCommand_PlaySound(NetworkPacket* pkt)
  592. {
  593. /*
  594. [0] u32 server_id
  595. [4] u16 name length
  596. [6] char name[len]
  597. [ 6 + len] f32 gain
  598. [10 + len] u8 type
  599. [11 + len] (f32 * 3) pos
  600. [23 + len] u16 object_id
  601. [25 + len] bool loop
  602. [26 + len] f32 fade
  603. [30 + len] f32 pitch
  604. */
  605. s32 server_id;
  606. std::string name;
  607. float gain;
  608. u8 type; // 0=local, 1=positional, 2=object
  609. v3f pos;
  610. u16 object_id;
  611. bool loop;
  612. float fade = 0.0f;
  613. float pitch = 1.0f;
  614. *pkt >> server_id >> name >> gain >> type >> pos >> object_id >> loop;
  615. try {
  616. *pkt >> fade;
  617. *pkt >> pitch;
  618. } catch (PacketError &e) {};
  619. // Start playing
  620. int client_id = -1;
  621. switch(type) {
  622. case 0: // local
  623. client_id = m_sound->playSound(name, loop, gain, fade, pitch);
  624. break;
  625. case 1: // positional
  626. client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
  627. break;
  628. case 2:
  629. { // object
  630. ClientActiveObject *cao = m_env.getActiveObject(object_id);
  631. if (cao)
  632. pos = cao->getPosition();
  633. client_id = m_sound->playSoundAt(name, loop, gain, pos, pitch);
  634. // TODO: Set up sound to move with object
  635. break;
  636. }
  637. default:
  638. break;
  639. }
  640. if (client_id != -1) {
  641. m_sounds_server_to_client[server_id] = client_id;
  642. m_sounds_client_to_server[client_id] = server_id;
  643. if (object_id != 0)
  644. m_sounds_to_objects[client_id] = object_id;
  645. }
  646. }
  647. void Client::handleCommand_StopSound(NetworkPacket* pkt)
  648. {
  649. s32 server_id;
  650. *pkt >> server_id;
  651. std::unordered_map<s32, int>::iterator i = m_sounds_server_to_client.find(server_id);
  652. if (i != m_sounds_server_to_client.end()) {
  653. int client_id = i->second;
  654. m_sound->stopSound(client_id);
  655. }
  656. }
  657. void Client::handleCommand_FadeSound(NetworkPacket *pkt)
  658. {
  659. s32 sound_id;
  660. float step;
  661. float gain;
  662. *pkt >> sound_id >> step >> gain;
  663. std::unordered_map<s32, int>::const_iterator i =
  664. m_sounds_server_to_client.find(sound_id);
  665. if (i != m_sounds_server_to_client.end())
  666. m_sound->fadeSound(i->second, step, gain);
  667. }
  668. void Client::handleCommand_Privileges(NetworkPacket* pkt)
  669. {
  670. m_privileges.clear();
  671. infostream << "Client: Privileges updated: ";
  672. u16 num_privileges;
  673. *pkt >> num_privileges;
  674. for (u16 i = 0; i < num_privileges; i++) {
  675. std::string priv;
  676. *pkt >> priv;
  677. m_privileges.insert(priv);
  678. infostream << priv << " ";
  679. }
  680. infostream << std::endl;
  681. }
  682. void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
  683. {
  684. LocalPlayer *player = m_env.getLocalPlayer();
  685. assert(player != NULL);
  686. // Store formspec in LocalPlayer
  687. player->inventory_formspec = pkt->readLongString();
  688. }
  689. void Client::handleCommand_DetachedInventory(NetworkPacket* pkt)
  690. {
  691. std::string datastring(pkt->getString(0), pkt->getSize());
  692. std::istringstream is(datastring, std::ios_base::binary);
  693. std::string name = deSerializeString(is);
  694. infostream << "Client: Detached inventory update: \"" << name
  695. << "\"" << std::endl;
  696. Inventory *inv = NULL;
  697. if (m_detached_inventories.count(name) > 0)
  698. inv = m_detached_inventories[name];
  699. else {
  700. inv = new Inventory(m_itemdef);
  701. m_detached_inventories[name] = inv;
  702. }
  703. inv->deSerialize(is);
  704. }
  705. void Client::handleCommand_ShowFormSpec(NetworkPacket* pkt)
  706. {
  707. std::string formspec = pkt->readLongString();
  708. std::string formname;
  709. *pkt >> formname;
  710. ClientEvent *event = new ClientEvent();
  711. event->type = CE_SHOW_FORMSPEC;
  712. // pointer is required as event is a struct only!
  713. // adding a std:string to a struct isn't possible
  714. event->show_formspec.formspec = new std::string(formspec);
  715. event->show_formspec.formname = new std::string(formname);
  716. m_client_event_queue.push(event);
  717. }
  718. void Client::handleCommand_SpawnParticle(NetworkPacket* pkt)
  719. {
  720. std::string datastring(pkt->getString(0), pkt->getSize());
  721. std::istringstream is(datastring, std::ios_base::binary);
  722. v3f pos = readV3F1000(is);
  723. v3f vel = readV3F1000(is);
  724. v3f acc = readV3F1000(is);
  725. float expirationtime = readF1000(is);
  726. float size = readF1000(is);
  727. bool collisiondetection = readU8(is);
  728. std::string texture = deSerializeLongString(is);
  729. bool vertical = false;
  730. bool collision_removal = false;
  731. TileAnimationParams animation;
  732. animation.type = TAT_NONE;
  733. u8 glow = 0;
  734. try {
  735. vertical = readU8(is);
  736. collision_removal = readU8(is);
  737. animation.deSerialize(is, m_proto_ver);
  738. glow = readU8(is);
  739. } catch (...) {}
  740. ClientEvent *event = new ClientEvent();
  741. event->type = CE_SPAWN_PARTICLE;
  742. event->spawn_particle.pos = new v3f (pos);
  743. event->spawn_particle.vel = new v3f (vel);
  744. event->spawn_particle.acc = new v3f (acc);
  745. event->spawn_particle.expirationtime = expirationtime;
  746. event->spawn_particle.size = size;
  747. event->spawn_particle.collisiondetection = collisiondetection;
  748. event->spawn_particle.collision_removal = collision_removal;
  749. event->spawn_particle.vertical = vertical;
  750. event->spawn_particle.texture = new std::string(texture);
  751. event->spawn_particle.animation = animation;
  752. event->spawn_particle.glow = glow;
  753. m_client_event_queue.push(event);
  754. }
  755. void Client::handleCommand_AddParticleSpawner(NetworkPacket* pkt)
  756. {
  757. u16 amount;
  758. float spawntime;
  759. v3f minpos;
  760. v3f maxpos;
  761. v3f minvel;
  762. v3f maxvel;
  763. v3f minacc;
  764. v3f maxacc;
  765. float minexptime;
  766. float maxexptime;
  767. float minsize;
  768. float maxsize;
  769. bool collisiondetection;
  770. u32 server_id;
  771. *pkt >> amount >> spawntime >> minpos >> maxpos >> minvel >> maxvel
  772. >> minacc >> maxacc >> minexptime >> maxexptime >> minsize
  773. >> maxsize >> collisiondetection;
  774. std::string texture = pkt->readLongString();
  775. *pkt >> server_id;
  776. bool vertical = false;
  777. bool collision_removal = false;
  778. TileAnimationParams animation;
  779. animation.type = TAT_NONE;
  780. u8 glow = 0;
  781. u16 attached_id = 0;
  782. try {
  783. *pkt >> vertical;
  784. *pkt >> collision_removal;
  785. *pkt >> attached_id;
  786. // This is horrible but required (why are there two ways to deserialize pkts?)
  787. std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
  788. std::istringstream is(datastring, std::ios_base::binary);
  789. animation.deSerialize(is, m_proto_ver);
  790. glow = readU8(is);
  791. } catch (...) {}
  792. u32 client_id = m_particle_manager.getSpawnerId();
  793. m_particles_server_to_client[server_id] = client_id;
  794. ClientEvent *event = new ClientEvent();
  795. event->type = CE_ADD_PARTICLESPAWNER;
  796. event->add_particlespawner.amount = amount;
  797. event->add_particlespawner.spawntime = spawntime;
  798. event->add_particlespawner.minpos = new v3f (minpos);
  799. event->add_particlespawner.maxpos = new v3f (maxpos);
  800. event->add_particlespawner.minvel = new v3f (minvel);
  801. event->add_particlespawner.maxvel = new v3f (maxvel);
  802. event->add_particlespawner.minacc = new v3f (minacc);
  803. event->add_particlespawner.maxacc = new v3f (maxacc);
  804. event->add_particlespawner.minexptime = minexptime;
  805. event->add_particlespawner.maxexptime = maxexptime;
  806. event->add_particlespawner.minsize = minsize;
  807. event->add_particlespawner.maxsize = maxsize;
  808. event->add_particlespawner.collisiondetection = collisiondetection;
  809. event->add_particlespawner.collision_removal = collision_removal;
  810. event->add_particlespawner.attached_id = attached_id;
  811. event->add_particlespawner.vertical = vertical;
  812. event->add_particlespawner.texture = new std::string(texture);
  813. event->add_particlespawner.id = client_id;
  814. event->add_particlespawner.animation = animation;
  815. event->add_particlespawner.glow = glow;
  816. m_client_event_queue.push(event);
  817. }
  818. void Client::handleCommand_DeleteParticleSpawner(NetworkPacket* pkt)
  819. {
  820. u32 server_id;
  821. *pkt >> server_id;
  822. u32 client_id;
  823. auto i = m_particles_server_to_client.find(server_id);
  824. if (i != m_particles_server_to_client.end())
  825. client_id = i->second;
  826. else
  827. return;
  828. ClientEvent *event = new ClientEvent();
  829. event->type = CE_DELETE_PARTICLESPAWNER;
  830. event->delete_particlespawner.id = client_id;
  831. m_client_event_queue.push(event);
  832. }
  833. void Client::handleCommand_HudAdd(NetworkPacket* pkt)
  834. {
  835. std::string datastring(pkt->getString(0), pkt->getSize());
  836. std::istringstream is(datastring, std::ios_base::binary);
  837. u32 server_id;
  838. u8 type;
  839. v2f pos;
  840. std::string name;
  841. v2f scale;
  842. std::string text;
  843. u32 number;
  844. u32 item;
  845. u32 dir;
  846. v2f align;
  847. v2f offset;
  848. v3f world_pos;
  849. v2s32 size;
  850. *pkt >> server_id >> type >> pos >> name >> scale >> text >> number >> item
  851. >> dir >> align >> offset;
  852. try {
  853. *pkt >> world_pos;
  854. }
  855. catch(SerializationError &e) {};
  856. try {
  857. *pkt >> size;
  858. } catch(SerializationError &e) {};
  859. ClientEvent *event = new ClientEvent();
  860. event->type = CE_HUDADD;
  861. event->hudadd.server_id = server_id;
  862. event->hudadd.type = type;
  863. event->hudadd.pos = new v2f(pos);
  864. event->hudadd.name = new std::string(name);
  865. event->hudadd.scale = new v2f(scale);
  866. event->hudadd.text = new std::string(text);
  867. event->hudadd.number = number;
  868. event->hudadd.item = item;
  869. event->hudadd.dir = dir;
  870. event->hudadd.align = new v2f(align);
  871. event->hudadd.offset = new v2f(offset);
  872. event->hudadd.world_pos = new v3f(world_pos);
  873. event->hudadd.size = new v2s32(size);
  874. m_client_event_queue.push(event);
  875. }
  876. void Client::handleCommand_HudRemove(NetworkPacket* pkt)
  877. {
  878. u32 server_id;
  879. *pkt >> server_id;
  880. auto i = m_hud_server_to_client.find(server_id);
  881. if (i != m_hud_server_to_client.end()) {
  882. int client_id = i->second;
  883. m_hud_server_to_client.erase(i);
  884. ClientEvent *event = new ClientEvent();
  885. event->type = CE_HUDRM;
  886. event->hudrm.id = client_id;
  887. m_client_event_queue.push(event);
  888. }
  889. }
  890. void Client::handleCommand_HudChange(NetworkPacket* pkt)
  891. {
  892. std::string sdata;
  893. v2f v2fdata;
  894. v3f v3fdata;
  895. u32 intdata = 0;
  896. v2s32 v2s32data;
  897. u32 server_id;
  898. u8 stat;
  899. *pkt >> server_id >> stat;
  900. if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE ||
  901. stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET)
  902. *pkt >> v2fdata;
  903. else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT)
  904. *pkt >> sdata;
  905. else if (stat == HUD_STAT_WORLD_POS)
  906. *pkt >> v3fdata;
  907. else if (stat == HUD_STAT_SIZE )
  908. *pkt >> v2s32data;
  909. else
  910. *pkt >> intdata;
  911. std::unordered_map<u32, u32>::const_iterator i = m_hud_server_to_client.find(server_id);
  912. if (i != m_hud_server_to_client.end()) {
  913. ClientEvent *event = new ClientEvent();
  914. event->type = CE_HUDCHANGE;
  915. event->hudchange.id = i->second;
  916. event->hudchange.stat = (HudElementStat)stat;
  917. event->hudchange.v2fdata = new v2f(v2fdata);
  918. event->hudchange.v3fdata = new v3f(v3fdata);
  919. event->hudchange.sdata = new std::string(sdata);
  920. event->hudchange.data = intdata;
  921. event->hudchange.v2s32data = new v2s32(v2s32data);
  922. m_client_event_queue.push(event);
  923. }
  924. }
  925. void Client::handleCommand_HudSetFlags(NetworkPacket* pkt)
  926. {
  927. u32 flags, mask;
  928. *pkt >> flags >> mask;
  929. LocalPlayer *player = m_env.getLocalPlayer();
  930. assert(player != NULL);
  931. bool was_minimap_visible = player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE;
  932. bool was_minimap_radar_visible = player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE;
  933. player->hud_flags &= ~mask;
  934. player->hud_flags |= flags;
  935. m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
  936. bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
  937. // Hide minimap if it has been disabled by the server
  938. if (m_minimap && m_minimap_disabled_by_server && was_minimap_visible)
  939. // defers a minimap update, therefore only call it if really
  940. // needed, by checking that minimap was visible before
  941. m_minimap->setMinimapMode(MINIMAP_MODE_OFF);
  942. // Switch to surface mode if radar disabled by server
  943. if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible)
  944. m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1);
  945. }
  946. void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
  947. {
  948. u16 param; std::string value;
  949. *pkt >> param >> value;
  950. LocalPlayer *player = m_env.getLocalPlayer();
  951. assert(player != NULL);
  952. if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
  953. s32 hotbar_itemcount = readS32((u8*) value.c_str());
  954. if (hotbar_itemcount > 0 && hotbar_itemcount <= HUD_HOTBAR_ITEMCOUNT_MAX)
  955. player->hud_hotbar_itemcount = hotbar_itemcount;
  956. }
  957. else if (param == HUD_PARAM_HOTBAR_IMAGE) {
  958. // If value not empty verify image exists in texture source
  959. if (!value.empty() && !getTextureSource()->isKnownSourceImage(value)) {
  960. errorstream << "Server sent wrong Hud hotbar image (sent value: '"
  961. << value << "')" << std::endl;
  962. return;
  963. }
  964. player->hotbar_image = value;
  965. }
  966. else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
  967. // If value not empty verify image exists in texture source
  968. if (!value.empty() && !getTextureSource()->isKnownSourceImage(value)) {
  969. errorstream << "Server sent wrong Hud hotbar selected image (sent value: '"
  970. << value << "')" << std::endl;
  971. return;
  972. }
  973. player->hotbar_selected_image = value;
  974. }
  975. }
  976. void Client::handleCommand_HudSetSky(NetworkPacket* pkt)
  977. {
  978. std::string datastring(pkt->getString(0), pkt->getSize());
  979. std::istringstream is(datastring, std::ios_base::binary);
  980. video::SColor *bgcolor = new video::SColor(readARGB8(is));
  981. std::string *type = new std::string(deSerializeString(is));
  982. u16 count = readU16(is);
  983. std::vector<std::string> *params = new std::vector<std::string>;
  984. for (size_t i = 0; i < count; i++)
  985. params->push_back(deSerializeString(is));
  986. bool clouds = true;
  987. try {
  988. clouds = readU8(is);
  989. } catch (...) {}
  990. ClientEvent *event = new ClientEvent();
  991. event->type = CE_SET_SKY;
  992. event->set_sky.bgcolor = bgcolor;
  993. event->set_sky.type = type;
  994. event->set_sky.params = params;
  995. event->set_sky.clouds = clouds;
  996. m_client_event_queue.push(event);
  997. }
  998. void Client::handleCommand_CloudParams(NetworkPacket* pkt)
  999. {
  1000. f32 density;
  1001. video::SColor color_bright;
  1002. video::SColor color_ambient;
  1003. f32 height;
  1004. f32 thickness;
  1005. v2f speed;
  1006. *pkt >> density >> color_bright >> color_ambient
  1007. >> height >> thickness >> speed;
  1008. ClientEvent *event = new ClientEvent();
  1009. event->type = CE_CLOUD_PARAMS;
  1010. event->cloud_params.density = density;
  1011. // use the underlying u32 representation, because we can't
  1012. // use struct members with constructors here, and this way
  1013. // we avoid using new() and delete() for no good reason
  1014. event->cloud_params.color_bright = color_bright.color;
  1015. event->cloud_params.color_ambient = color_ambient.color;
  1016. event->cloud_params.height = height;
  1017. event->cloud_params.thickness = thickness;
  1018. // same here: deconstruct to skip constructor
  1019. event->cloud_params.speed_x = speed.X;
  1020. event->cloud_params.speed_y = speed.Y;
  1021. m_client_event_queue.push(event);
  1022. }
  1023. void Client::handleCommand_OverrideDayNightRatio(NetworkPacket* pkt)
  1024. {
  1025. bool do_override;
  1026. u16 day_night_ratio_u;
  1027. *pkt >> do_override >> day_night_ratio_u;
  1028. float day_night_ratio_f = (float)day_night_ratio_u / 65536;
  1029. ClientEvent *event = new ClientEvent();
  1030. event->type = CE_OVERRIDE_DAY_NIGHT_RATIO;
  1031. event->override_day_night_ratio.do_override = do_override;
  1032. event->override_day_night_ratio.ratio_f = day_night_ratio_f;
  1033. m_client_event_queue.push(event);
  1034. }
  1035. void Client::handleCommand_LocalPlayerAnimations(NetworkPacket* pkt)
  1036. {
  1037. LocalPlayer *player = m_env.getLocalPlayer();
  1038. assert(player != NULL);
  1039. *pkt >> player->local_animations[0];
  1040. *pkt >> player->local_animations[1];
  1041. *pkt >> player->local_animations[2];
  1042. *pkt >> player->local_animations[3];
  1043. *pkt >> player->local_animation_speed;
  1044. }
  1045. void Client::handleCommand_EyeOffset(NetworkPacket* pkt)
  1046. {
  1047. LocalPlayer *player = m_env.getLocalPlayer();
  1048. assert(player != NULL);
  1049. *pkt >> player->eye_offset_first >> player->eye_offset_third;
  1050. }
  1051. void Client::handleCommand_UpdatePlayerList(NetworkPacket* pkt)
  1052. {
  1053. u8 type;
  1054. u16 num_players;
  1055. *pkt >> type >> num_players;
  1056. PlayerListModifer notice_type = (PlayerListModifer) type;
  1057. for (u16 i = 0; i < num_players; i++) {
  1058. std::string name;
  1059. *pkt >> name;
  1060. switch (notice_type) {
  1061. case PLAYER_LIST_INIT:
  1062. case PLAYER_LIST_ADD:
  1063. m_env.addPlayerName(name);
  1064. continue;
  1065. case PLAYER_LIST_REMOVE:
  1066. m_env.removePlayerName(name);
  1067. continue;
  1068. }
  1069. }
  1070. }
  1071. void Client::handleCommand_SrpBytesSandB(NetworkPacket* pkt)
  1072. {
  1073. if (m_chosen_auth_mech != AUTH_MECHANISM_SRP &&
  1074. m_chosen_auth_mech != AUTH_MECHANISM_LEGACY_PASSWORD) {
  1075. errorstream << "Client: Received SRP S_B login message,"
  1076. << " but wasn't supposed to (chosen_mech="
  1077. << m_chosen_auth_mech << ")." << std::endl;
  1078. return;
  1079. }
  1080. char *bytes_M = 0;
  1081. size_t len_M = 0;
  1082. SRPUser *usr = (SRPUser *) m_auth_data;
  1083. std::string s;
  1084. std::string B;
  1085. *pkt >> s >> B;
  1086. infostream << "Client: Received TOCLIENT_SRP_BYTES_S_B." << std::endl;
  1087. srp_user_process_challenge(usr, (const unsigned char *) s.c_str(), s.size(),
  1088. (const unsigned char *) B.c_str(), B.size(),
  1089. (unsigned char **) &bytes_M, &len_M);
  1090. if ( !bytes_M ) {
  1091. errorstream << "Client: SRP-6a S_B safety check violation!" << std::endl;
  1092. return;
  1093. }
  1094. NetworkPacket resp_pkt(TOSERVER_SRP_BYTES_M, 0);
  1095. resp_pkt << std::string(bytes_M, len_M);
  1096. Send(&resp_pkt);
  1097. }
  1098. void Client::handleCommand_CSMFlavourLimits(NetworkPacket *pkt)
  1099. {
  1100. *pkt >> m_csm_flavour_limits >> m_csm_noderange_limit;
  1101. // Now we have flavours, load mods if it's enabled
  1102. // Note: this should be moved after mods receptions from server instead
  1103. loadMods();
  1104. }
  1105. /*
  1106. * Mod channels
  1107. */
  1108. void Client::handleCommand_ModChannelMsg(NetworkPacket *pkt)
  1109. {
  1110. std::string channel_name, sender, channel_msg;
  1111. *pkt >> channel_name >> sender >> channel_msg;
  1112. verbosestream << "Mod channel message received from server " << pkt->getPeerId()
  1113. << " on channel " << channel_name << ". sender: `" << sender << "`, message: "
  1114. << channel_msg << std::endl;
  1115. if (!m_modchannel_mgr->channelRegistered(channel_name)) {
  1116. verbosestream << "Server sent us messages on unregistered channel "
  1117. << channel_name << ", ignoring." << std::endl;
  1118. return;
  1119. }
  1120. m_script->on_modchannel_message(channel_name, sender, channel_msg);
  1121. }
  1122. void Client::handleCommand_ModChannelSignal(NetworkPacket *pkt)
  1123. {
  1124. u8 signal_tmp;
  1125. ModChannelSignal signal;
  1126. std::string channel;
  1127. *pkt >> signal_tmp >> channel;
  1128. signal = (ModChannelSignal)signal_tmp;
  1129. bool valid_signal = true;
  1130. // @TODO: send Signal to Lua API
  1131. switch (signal) {
  1132. case MODCHANNEL_SIGNAL_JOIN_OK:
  1133. m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
  1134. infostream << "Server ack our mod channel join on channel `" << channel
  1135. << "`, joining." << std::endl;
  1136. break;
  1137. case MODCHANNEL_SIGNAL_JOIN_FAILURE:
  1138. // Unable to join, remove channel
  1139. m_modchannel_mgr->leaveChannel(channel, 0);
  1140. infostream << "Server refused our mod channel join on channel `" << channel
  1141. << "`" << std::endl;
  1142. break;
  1143. case MODCHANNEL_SIGNAL_LEAVE_OK:
  1144. #ifndef NDEBUG
  1145. infostream << "Server ack our mod channel leave on channel " << channel
  1146. << "`, leaving." << std::endl;
  1147. #endif
  1148. break;
  1149. case MODCHANNEL_SIGNAL_LEAVE_FAILURE:
  1150. infostream << "Server refused our mod channel leave on channel `" << channel
  1151. << "`" << std::endl;
  1152. break;
  1153. case MODCHANNEL_SIGNAL_CHANNEL_NOT_REGISTERED:
  1154. #ifndef NDEBUG
  1155. // Generally unused, but ensure we don't do an implementation error
  1156. infostream << "Server tells us we sent a message on channel `" << channel
  1157. << "` but we are not registered. Message was dropped." << std::endl;
  1158. #endif
  1159. break;
  1160. case MODCHANNEL_SIGNAL_SET_STATE: {
  1161. u8 state;
  1162. *pkt >> state;
  1163. if (state == MODCHANNEL_STATE_INIT || state >= MODCHANNEL_STATE_MAX) {
  1164. infostream << "Received wrong channel state " << state
  1165. << ", ignoring." << std::endl;
  1166. return;
  1167. }
  1168. m_modchannel_mgr->setChannelState(channel, (ModChannelState) state);
  1169. infostream << "Server sets mod channel `" << channel
  1170. << "` in read-only mode." << std::endl;
  1171. break;
  1172. }
  1173. default:
  1174. #ifndef NDEBUG
  1175. warningstream << "Received unhandled mod channel signal ID "
  1176. << signal << ", ignoring." << std::endl;
  1177. #endif
  1178. valid_signal = false;
  1179. break;
  1180. }
  1181. // If signal is valid, forward it to client side mods
  1182. if (valid_signal)
  1183. m_script->on_modchannel_signal(channel, signal);
  1184. }