Commit 6cd50fa2ad6d2600a8201dc591f2a403f3b3e8ee

Authored by Wiebe Cazemier
1 parent 5a7d3066

Reverse if-guard to remove indentation

Diff with 'ignore whitespace' looks clean.
Showing 1 changed file with 264 additions and 266 deletions
mqttpacket.cpp
... ... @@ -332,68 +332,134 @@ void MqttPacket::handleConnect()
332 332  
333 333 const Settings &settings = *ThreadGlobals::getSettings();
334 334  
335   - if (variable_header_length == 4 || variable_header_length == 6)
  335 + if (!(variable_header_length == 4 || variable_header_length == 6))
336 336 {
337   - char *c = readBytes(variable_header_length);
338   - std::string magic_marker(c, variable_header_length);
  337 + throw ProtocolError("Invalid variable header length. Garbage?", ReasonCodes::MalformedPacket);
  338 + }
339 339  
340   - char protocol_level = readByte();
  340 + char *c = readBytes(variable_header_length);
  341 + std::string magic_marker(c, variable_header_length);
341 342  
342   - if (magic_marker == "MQTT")
343   - {
344   - if (protocol_level == 0x04)
345   - protocolVersion = ProtocolVersion::Mqtt311;
346   - if (protocol_level == 0x05)
347   - protocolVersion = ProtocolVersion::Mqtt5;
348   - }
349   - else if (magic_marker == "MQIsdp" && protocol_level == 0x03)
350   - {
351   - protocolVersion = ProtocolVersion::Mqtt31;
352   - }
353   - else
354   - {
355   - // The specs are unclear when to use the version 3 codes or version 5 codes.
356   - ProtocolVersion fuzzyProtocolVersion = protocol_level < 0x05 ? ProtocolVersion::Mqtt31 : ProtocolVersion::Mqtt5;
  343 + char protocol_level = readByte();
357 344  
358   - ConnAck connAck(fuzzyProtocolVersion, ReasonCodes::UnsupportedProtocolVersion);
359   - MqttPacket response(connAck);
360   - sender->setReadyForDisconnect();
361   - sender->writeMqttPacket(response);
362   - logger->logf(LOG_ERR, "Rejecting because of invalid protocol version: %s", sender->repr().c_str());
363   - return;
364   - }
  345 + if (magic_marker == "MQTT")
  346 + {
  347 + if (protocol_level == 0x04)
  348 + protocolVersion = ProtocolVersion::Mqtt311;
  349 + if (protocol_level == 0x05)
  350 + protocolVersion = ProtocolVersion::Mqtt5;
  351 + }
  352 + else if (magic_marker == "MQIsdp" && protocol_level == 0x03)
  353 + {
  354 + protocolVersion = ProtocolVersion::Mqtt31;
  355 + }
  356 + else
  357 + {
  358 + // The specs are unclear when to use the version 3 codes or version 5 codes.
  359 + ProtocolVersion fuzzyProtocolVersion = protocol_level < 0x05 ? ProtocolVersion::Mqtt31 : ProtocolVersion::Mqtt5;
  360 +
  361 + ConnAck connAck(fuzzyProtocolVersion, ReasonCodes::UnsupportedProtocolVersion);
  362 + MqttPacket response(connAck);
  363 + sender->setReadyForDisconnect();
  364 + sender->writeMqttPacket(response);
  365 + logger->logf(LOG_ERR, "Rejecting because of invalid protocol version: %s", sender->repr().c_str());
  366 + return;
  367 + }
365 368  
366   - char flagByte = readByte();
367   - bool reserved = !!(flagByte & 0b00000001);
  369 + char flagByte = readByte();
  370 + bool reserved = !!(flagByte & 0b00000001);
368 371  
369   - if (reserved)
370   - throw ProtocolError("Protocol demands reserved flag in CONNECT is 0", ReasonCodes::MalformedPacket);
  372 + if (reserved)
  373 + throw ProtocolError("Protocol demands reserved flag in CONNECT is 0", ReasonCodes::MalformedPacket);
371 374  
372 375  
373   - bool user_name_flag = !!(flagByte & 0b10000000);
374   - bool password_flag = !!(flagByte & 0b01000000);
375   - bool will_retain = !!(flagByte & 0b00100000);
376   - char will_qos = (flagByte & 0b00011000) >> 3;
377   - bool will_flag = !!(flagByte & 0b00000100);
378   - bool clean_start = !!(flagByte & 0b00000010);
  376 + bool user_name_flag = !!(flagByte & 0b10000000);
  377 + bool password_flag = !!(flagByte & 0b01000000);
  378 + bool will_retain = !!(flagByte & 0b00100000);
  379 + char will_qos = (flagByte & 0b00011000) >> 3;
  380 + bool will_flag = !!(flagByte & 0b00000100);
  381 + bool clean_start = !!(flagByte & 0b00000010);
379 382  
380   - if (will_qos > 2)
381   - throw ProtocolError("Invalid QoS for will.", ReasonCodes::MalformedPacket);
  383 + if (will_qos > 2)
  384 + throw ProtocolError("Invalid QoS for will.", ReasonCodes::MalformedPacket);
382 385  
383   - uint16_t keep_alive = readTwoBytesToUInt16();
  386 + uint16_t keep_alive = readTwoBytesToUInt16();
384 387  
385   - uint16_t max_qos_packets = settings.maxQosMsgPendingPerClient;
386   - uint32_t session_expire = settings.getExpireSessionAfterSeconds();
387   - uint32_t max_outgoing_packet_size = settings.maxPacketSize;
388   - uint16_t max_outgoing_topic_aliases = 0; // Default MUST BE 0, meaning server won't initiate aliases
389   - bool request_response_information = false;
390   - bool request_problem_information = false;
  388 + uint16_t max_qos_packets = settings.maxQosMsgPendingPerClient;
  389 + uint32_t session_expire = settings.getExpireSessionAfterSeconds();
  390 + uint32_t max_outgoing_packet_size = settings.maxPacketSize;
  391 + uint16_t max_outgoing_topic_aliases = 0; // Default MUST BE 0, meaning server won't initiate aliases
  392 + bool request_response_information = false;
  393 + bool request_problem_information = false;
391 394  
392   - std::string authenticationMethod;
393   - std::string authenticationData;
  395 + std::string authenticationMethod;
  396 + std::string authenticationData;
394 397  
  398 + if (protocolVersion == ProtocolVersion::Mqtt5)
  399 + {
  400 + const size_t proplen = decodeVariableByteIntAtPos();
  401 + const size_t prop_end_at = pos + proplen;
  402 +
  403 + while (pos < prop_end_at)
  404 + {
  405 + const Mqtt5Properties prop = static_cast<Mqtt5Properties>(readByte());
  406 +
  407 + switch (prop)
  408 + {
  409 + case Mqtt5Properties::SessionExpiryInterval:
  410 + session_expire = std::min<uint32_t>(readFourBytesToUint32(), session_expire);
  411 + break;
  412 + case Mqtt5Properties::ReceiveMaximum:
  413 + max_qos_packets = std::min<int16_t>(readTwoBytesToUInt16(), max_qos_packets);
  414 + break;
  415 + case Mqtt5Properties::MaximumPacketSize:
  416 + max_outgoing_packet_size = std::min<uint32_t>(readFourBytesToUint32(), max_outgoing_packet_size);
  417 + break;
  418 + case Mqtt5Properties::TopicAliasMaximum:
  419 + max_outgoing_topic_aliases = std::min<uint16_t>(readTwoBytesToUInt16(), settings.maxOutgoingTopicAliasValue);
  420 + break;
  421 + case Mqtt5Properties::RequestResponseInformation:
  422 + request_response_information = !!readByte();
  423 + UNUSED(request_response_information);
  424 + break;
  425 + case Mqtt5Properties::RequestProblemInformation:
  426 + request_problem_information = !!readByte();
  427 + UNUSED(request_problem_information);
  428 + break;
  429 + case Mqtt5Properties::UserProperty:
  430 + readUserProperty();
  431 + break;
  432 + case Mqtt5Properties::AuthenticationMethod:
  433 + {
  434 + authenticationMethod = readBytesToString();
  435 + break;
  436 + }
  437 + case Mqtt5Properties::AuthenticationData:
  438 + {
  439 + authenticationData = readBytesToString(false);
  440 + break;
  441 + }
  442 + default:
  443 + throw ProtocolError("Invalid connect property.", ReasonCodes::ProtocolError);
  444 + }
  445 + }
  446 + }
  447 +
  448 + std::string client_id = readBytesToString();
  449 +
  450 + std::string username;
  451 + std::string password;
  452 +
  453 + WillPublish willpublish;
  454 + willpublish.qos = will_qos;
  455 + willpublish.retain = will_retain;
  456 +
  457 + if (will_flag)
  458 + {
395 459 if (protocolVersion == ProtocolVersion::Mqtt5)
396 460 {
  461 + willpublish.constructPropertyBuilder();
  462 +
397 463 const size_t proplen = decodeVariableByteIntAtPos();
398 464 const size_t prop_end_at = pos + proplen;
399 465  
... ... @@ -403,277 +469,209 @@ void MqttPacket::handleConnect()
403 469  
404 470 switch (prop)
405 471 {
406   - case Mqtt5Properties::SessionExpiryInterval:
407   - session_expire = std::min<uint32_t>(readFourBytesToUint32(), session_expire);
408   - break;
409   - case Mqtt5Properties::ReceiveMaximum:
410   - max_qos_packets = std::min<int16_t>(readTwoBytesToUInt16(), max_qos_packets);
  472 + case Mqtt5Properties::WillDelayInterval:
  473 + willpublish.will_delay = readFourBytesToUint32();
411 474 break;
412   - case Mqtt5Properties::MaximumPacketSize:
413   - max_outgoing_packet_size = std::min<uint32_t>(readFourBytesToUint32(), max_outgoing_packet_size);
  475 + case Mqtt5Properties::PayloadFormatIndicator:
  476 + willpublish.propertyBuilder->writePayloadFormatIndicator(readByte());
414 477 break;
415   - case Mqtt5Properties::TopicAliasMaximum:
416   - max_outgoing_topic_aliases = std::min<uint16_t>(readTwoBytesToUInt16(), settings.maxOutgoingTopicAliasValue);
417   - break;
418   - case Mqtt5Properties::RequestResponseInformation:
419   - request_response_information = !!readByte();
420   - UNUSED(request_response_information);
  478 + case Mqtt5Properties::ContentType:
  479 + {
  480 + const std::string contentType = readBytesToString();
  481 + willpublish.propertyBuilder->writeContentType(contentType);
421 482 break;
422   - case Mqtt5Properties::RequestProblemInformation:
423   - request_problem_information = !!readByte();
424   - UNUSED(request_problem_information);
  483 + }
  484 + case Mqtt5Properties::ResponseTopic:
  485 + {
  486 + const std::string responseTopic = readBytesToString();
  487 + willpublish.propertyBuilder->writeResponseTopic(responseTopic);
425 488 break;
426   - case Mqtt5Properties::UserProperty:
427   - readUserProperty();
  489 + }
  490 + case Mqtt5Properties::MessageExpiryInterval:
  491 + {
  492 + const uint32_t expiresAfter = readFourBytesToUint32();
  493 + willpublish.setExpireAfter(expiresAfter);
428 494 break;
429   - case Mqtt5Properties::AuthenticationMethod:
  495 + }
  496 + case Mqtt5Properties::CorrelationData:
430 497 {
431   - authenticationMethod = readBytesToString();
  498 + const std::string correlationData = readBytesToString(false);
  499 + willpublish.propertyBuilder->writeCorrelationData(correlationData);
432 500 break;
433 501 }
434   - case Mqtt5Properties::AuthenticationData:
  502 + case Mqtt5Properties::UserProperty:
435 503 {
436   - authenticationData = readBytesToString(false);
  504 + readUserProperty();
437 505 break;
438 506 }
439 507 default:
440   - throw ProtocolError("Invalid connect property.", ReasonCodes::ProtocolError);
  508 + throw ProtocolError("Invalid will property in connect.", ReasonCodes::ProtocolError);
441 509 }
442 510 }
443 511 }
444 512  
445   - std::string client_id = readBytesToString();
  513 + willpublish.topic = readBytesToString(true, true);
446 514  
447   - std::string username;
448   - std::string password;
  515 + uint16_t will_payload_length = readTwoBytesToUInt16();
  516 + willpublish.payload = std::string(readBytes(will_payload_length), will_payload_length);
  517 + }
  518 + if (user_name_flag)
  519 + {
  520 + username = readBytesToString(false);
449 521  
450   - WillPublish willpublish;
451   - willpublish.qos = will_qos;
452   - willpublish.retain = will_retain;
  522 + if (username.empty())
  523 + throw ProtocolError("Username flagged as present, but it's 0 bytes.", ReasonCodes::MalformedPacket);
453 524  
454   - if (will_flag)
  525 + if (!settings.allowUnsafeUsernameChars && containsDangerousCharacters(username))
  526 + throw ProtocolError(formatString("Username '%s' contains unsafe characters and 'allow_unsafe_username_chars' is false.", username.c_str()),
  527 + ReasonCodes::BadUserNameOrPassword);
  528 + }
  529 + if (password_flag)
  530 + {
  531 + if (this->protocolVersion <= ProtocolVersion::Mqtt311 && !user_name_flag)
455 532 {
456   - if (protocolVersion == ProtocolVersion::Mqtt5)
457   - {
458   - willpublish.constructPropertyBuilder();
459   -
460   - const size_t proplen = decodeVariableByteIntAtPos();
461   - const size_t prop_end_at = pos + proplen;
462   -
463   - while (pos < prop_end_at)
464   - {
465   - const Mqtt5Properties prop = static_cast<Mqtt5Properties>(readByte());
466   -
467   - switch (prop)
468   - {
469   - case Mqtt5Properties::WillDelayInterval:
470   - willpublish.will_delay = readFourBytesToUint32();
471   - break;
472   - case Mqtt5Properties::PayloadFormatIndicator:
473   - willpublish.propertyBuilder->writePayloadFormatIndicator(readByte());
474   - break;
475   - case Mqtt5Properties::ContentType:
476   - {
477   - const std::string contentType = readBytesToString();
478   - willpublish.propertyBuilder->writeContentType(contentType);
479   - break;
480   - }
481   - case Mqtt5Properties::ResponseTopic:
482   - {
483   - const std::string responseTopic = readBytesToString();
484   - willpublish.propertyBuilder->writeResponseTopic(responseTopic);
485   - break;
486   - }
487   - case Mqtt5Properties::MessageExpiryInterval:
488   - {
489   - const uint32_t expiresAfter = readFourBytesToUint32();
490   - willpublish.setExpireAfter(expiresAfter);
491   - break;
492   - }
493   - case Mqtt5Properties::CorrelationData:
494   - {
495   - const std::string correlationData = readBytesToString(false);
496   - willpublish.propertyBuilder->writeCorrelationData(correlationData);
497   - break;
498   - }
499   - case Mqtt5Properties::UserProperty:
500   - {
501   - readUserProperty();
502   - break;
503   - }
504   - default:
505   - throw ProtocolError("Invalid will property in connect.", ReasonCodes::ProtocolError);
506   - }
507   - }
508   - }
  533 + throw ProtocolError("MQTT 3.1.1: If the User Name Flag is set to 0, the Password Flag MUST be set to 0.");
  534 + }
509 535  
510   - willpublish.topic = readBytesToString(true, true);
  536 + password = readBytesToString(false);
511 537  
512   - uint16_t will_payload_length = readTwoBytesToUInt16();
513   - willpublish.payload = std::string(readBytes(will_payload_length), will_payload_length);
514   - }
515   - if (user_name_flag)
516   - {
517   - username = readBytesToString(false);
  538 + if (password.empty())
  539 + throw ProtocolError("Password flagged as present, but it's 0 bytes.", ReasonCodes::MalformedPacket);
  540 + }
518 541  
519   - if (username.empty())
520   - throw ProtocolError("Username flagged as present, but it's 0 bytes.", ReasonCodes::MalformedPacket);
  542 + // I deferred the initial UTF8 check on username to be able to give an appropriate connack here, but to me, the specs
  543 + // are actually vague whether 'BadUserNameOrPassword' should be given on invalid UTF8.
  544 + if (!isValidUtf8(username))
  545 + {
  546 + ConnAck connAck(protocolVersion, ReasonCodes::BadUserNameOrPassword);
  547 + MqttPacket response(connAck);
  548 + sender->setReadyForDisconnect();
  549 + sender->writeMqttPacket(response);
  550 + logger->logf(LOG_ERR, "Username has invalid UTF8: %s", username.c_str());
  551 + return;
  552 + }
521 553  
522   - if (!settings.allowUnsafeUsernameChars && containsDangerousCharacters(username))
523   - throw ProtocolError(formatString("Username '%s' contains unsafe characters and 'allow_unsafe_username_chars' is false.", username.c_str()),
524   - ReasonCodes::BadUserNameOrPassword);
525   - }
526   - if (password_flag)
527   - {
528   - if (this->protocolVersion <= ProtocolVersion::Mqtt311 && !user_name_flag)
529   - {
530   - throw ProtocolError("MQTT 3.1.1: If the User Name Flag is set to 0, the Password Flag MUST be set to 0.");
531   - }
  554 + bool validClientId = true;
532 555  
533   - password = readBytesToString(false);
  556 + // Check for wildcard chars in case the client_id ever appears in topics.
  557 + if (!settings.allowUnsafeClientidChars && containsDangerousCharacters(client_id))
  558 + {
  559 + logger->logf(LOG_ERR, "ClientID '%s' has + or # in the id and 'allow_unsafe_clientid_chars' is false.", client_id.c_str());
  560 + validClientId = false;
  561 + }
  562 + else if (!clean_start && client_id.empty())
  563 + {
  564 + logger->logf(LOG_ERR, "ClientID empty and clean start 0, which is incompatible");
  565 + validClientId = false;
  566 + }
  567 + else if (protocolVersion < ProtocolVersion::Mqtt311 && client_id.empty())
  568 + {
  569 + logger->logf(LOG_ERR, "Empty clientID. Connect with protocol 3.1.1 or higher to have one generated securely.");
  570 + validClientId = false;
  571 + }
534 572  
535   - if (password.empty())
536   - throw ProtocolError("Password flagged as present, but it's 0 bytes.", ReasonCodes::MalformedPacket);
537   - }
  573 + if (!validClientId)
  574 + {
  575 + ConnAck connAck(protocolVersion, ReasonCodes::ClientIdentifierNotValid);
  576 + MqttPacket response(connAck);
  577 + sender->setDisconnectReason("Invalid clientID");
  578 + sender->setReadyForDisconnect();
  579 + sender->writeMqttPacket(response);
  580 + return;
  581 + }
538 582  
539   - // I deferred the initial UTF8 check on username to be able to give an appropriate connack here, but to me, the specs
540   - // are actually vague whether 'BadUserNameOrPassword' should be given on invalid UTF8.
541   - if (!isValidUtf8(username))
542   - {
543   - ConnAck connAck(protocolVersion, ReasonCodes::BadUserNameOrPassword);
544   - MqttPacket response(connAck);
545   - sender->setReadyForDisconnect();
546   - sender->writeMqttPacket(response);
547   - logger->logf(LOG_ERR, "Username has invalid UTF8: %s", username.c_str());
548   - return;
549   - }
  583 + bool clientIdGenerated = false;
  584 + if (client_id.empty())
  585 + {
  586 + client_id = getSecureRandomString(23);
  587 + clientIdGenerated = true;
  588 + }
550 589  
551   - bool validClientId = true;
  590 + sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_outgoing_packet_size, max_outgoing_topic_aliases);
552 591  
553   - // Check for wildcard chars in case the client_id ever appears in topics.
554   - if (!settings.allowUnsafeClientidChars && containsDangerousCharacters(client_id))
555   - {
556   - logger->logf(LOG_ERR, "ClientID '%s' has + or # in the id and 'allow_unsafe_clientid_chars' is false.", client_id.c_str());
557   - validClientId = false;
558   - }
559   - else if (!clean_start && client_id.empty())
560   - {
561   - logger->logf(LOG_ERR, "ClientID empty and clean start 0, which is incompatible");
562   - validClientId = false;
563   - }
564   - else if (protocolVersion < ProtocolVersion::Mqtt311 && client_id.empty())
565   - {
566   - logger->logf(LOG_ERR, "Empty clientID. Connect with protocol 3.1.1 or higher to have one generated securely.");
567   - validClientId = false;
568   - }
  592 + if (will_flag)
  593 + sender->setWill(std::move(willpublish));
569 594  
570   - if (!validClientId)
571   - {
572   - ConnAck connAck(protocolVersion, ReasonCodes::ClientIdentifierNotValid);
573   - MqttPacket response(connAck);
574   - sender->setDisconnectReason("Invalid clientID");
575   - sender->setReadyForDisconnect();
576   - sender->writeMqttPacket(response);
577   - return;
578   - }
  595 + // Stage connack, for immediate or delayed use when auth succeeds.
  596 + {
  597 + bool sessionPresent = false;
  598 + std::shared_ptr<Session> existingSession;
579 599  
580   - bool clientIdGenerated = false;
581   - if (client_id.empty())
  600 + if (protocolVersion >= ProtocolVersion::Mqtt311 && !clean_start)
582 601 {
583   - client_id = getSecureRandomString(23);
584   - clientIdGenerated = true;
  602 + existingSession = subscriptionStore->lockSession(client_id);
  603 + if (existingSession)
  604 + sessionPresent = true;
585 605 }
586 606  
587   - sender->setClientProperties(protocolVersion, client_id, username, true, keep_alive, max_outgoing_packet_size, max_outgoing_topic_aliases);
  607 + std::unique_ptr<ConnAck> connAck = std::make_unique<ConnAck>(protocolVersion, ReasonCodes::Success, sessionPresent);
588 608  
589   - if (will_flag)
590   - sender->setWill(std::move(willpublish));
591   -
592   - // Stage connack, for immediate or delayed use when auth succeeds.
  609 + if (protocolVersion >= ProtocolVersion::Mqtt5)
593 610 {
594   - bool sessionPresent = false;
595   - std::shared_ptr<Session> existingSession;
596   -
597   - if (protocolVersion >= ProtocolVersion::Mqtt311 && !clean_start)
598   - {
599   - existingSession = subscriptionStore->lockSession(client_id);
600   - if (existingSession)
601   - sessionPresent = true;
602   - }
603   -
604   - std::unique_ptr<ConnAck> connAck = std::make_unique<ConnAck>(protocolVersion, ReasonCodes::Success, sessionPresent);
605   -
606   - if (protocolVersion >= ProtocolVersion::Mqtt5)
  611 + connAck->propertyBuilder = std::make_shared<Mqtt5PropertyBuilder>();
  612 + connAck->propertyBuilder->writeSessionExpiry(session_expire);
  613 + connAck->propertyBuilder->writeReceiveMax(max_qos_packets);
  614 + connAck->propertyBuilder->writeRetainAvailable(1);
  615 + connAck->propertyBuilder->writeMaxPacketSize(sender->getMaxIncomingPacketSize());
  616 + if (clientIdGenerated)
  617 + connAck->propertyBuilder->writeAssignedClientId(client_id);
  618 + connAck->propertyBuilder->writeMaxTopicAliases(settings.maxIncomingTopicAliasValue);
  619 + connAck->propertyBuilder->writeWildcardSubscriptionAvailable(1);
  620 + connAck->propertyBuilder->writeSubscriptionIdentifiersAvailable(0);
  621 + connAck->propertyBuilder->writeSharedSubscriptionAvailable(0);
  622 +
  623 + if (!authenticationMethod.empty())
607 624 {
608   - connAck->propertyBuilder = std::make_shared<Mqtt5PropertyBuilder>();
609   - connAck->propertyBuilder->writeSessionExpiry(session_expire);
610   - connAck->propertyBuilder->writeReceiveMax(max_qos_packets);
611   - connAck->propertyBuilder->writeRetainAvailable(1);
612   - connAck->propertyBuilder->writeMaxPacketSize(sender->getMaxIncomingPacketSize());
613   - if (clientIdGenerated)
614   - connAck->propertyBuilder->writeAssignedClientId(client_id);
615   - connAck->propertyBuilder->writeMaxTopicAliases(settings.maxIncomingTopicAliasValue);
616   - connAck->propertyBuilder->writeWildcardSubscriptionAvailable(1);
617   - connAck->propertyBuilder->writeSubscriptionIdentifiersAvailable(0);
618   - connAck->propertyBuilder->writeSharedSubscriptionAvailable(0);
619   -
620   - if (!authenticationMethod.empty())
621   - {
622   - connAck->propertyBuilder->writeAuthenticationMethod(authenticationMethod);
623   - }
  625 + connAck->propertyBuilder->writeAuthenticationMethod(authenticationMethod);
624 626 }
625   -
626   - sender->stageConnack(std::move(connAck));
627 627 }
628 628  
629   - sender->setRegistrationData(clean_start, max_qos_packets, session_expire);
  629 + sender->stageConnack(std::move(connAck));
  630 + }
630 631  
631   - Authentication &authentication = *ThreadGlobals::getAuth();
632   - AuthResult authResult = AuthResult::login_denied;
  632 + sender->setRegistrationData(clean_start, max_qos_packets, session_expire);
633 633  
634   - if (!user_name_flag && authenticationMethod.empty() && settings.allowAnonymous)
635   - {
636   - authResult = AuthResult::success;
637   - }
638   - else if (!authenticationMethod.empty())
639   - {
640   - sender->setExtendedAuthenticationMethod(authenticationMethod);
  634 + Authentication &authentication = *ThreadGlobals::getAuth();
  635 + AuthResult authResult = AuthResult::login_denied;
641 636  
642   - std::string returnData;
643   - authResult = authentication.extendedAuth(client_id, ExtendedAuthStage::Auth, authenticationMethod, authenticationData,
644   - getUserProperties(), returnData, sender->getMutableUsername());
  637 + if (!user_name_flag && authenticationMethod.empty() && settings.allowAnonymous)
  638 + {
  639 + authResult = AuthResult::success;
  640 + }
  641 + else if (!authenticationMethod.empty())
  642 + {
  643 + sender->setExtendedAuthenticationMethod(authenticationMethod);
645 644  
646   - if (authResult == AuthResult::auth_continue)
647   - {
648   - Auth auth(ReasonCodes::ContinueAuthentication, authenticationMethod, returnData);
649   - MqttPacket pack(auth);
650   - sender->writeMqttPacket(pack);
651   - return;
652   - }
653   - if (authResult == AuthResult::success)
654   - {
655   - sender->addAuthReturnDataToStagedConnAck(returnData);
656   - }
657   - }
658   - else
659   - {
660   - authResult = authentication.unPwdCheck(username, password, getUserProperties());
661   - }
  645 + std::string returnData;
  646 + authResult = authentication.extendedAuth(client_id, ExtendedAuthStage::Auth, authenticationMethod, authenticationData,
  647 + getUserProperties(), returnData, sender->getMutableUsername());
662 648  
663   - if (authResult == AuthResult::success)
  649 + if (authResult == AuthResult::auth_continue)
664 650 {
665   - sender->sendConnackSuccess();
666   - subscriptionStore->registerClientAndKickExistingOne(sender);
  651 + Auth auth(ReasonCodes::ContinueAuthentication, authenticationMethod, returnData);
  652 + MqttPacket pack(auth);
  653 + sender->writeMqttPacket(pack);
  654 + return;
667 655 }
668   - else
  656 + if (authResult == AuthResult::success)
669 657 {
670   - const ReasonCodes reason = authResultToReasonCode(authResult);
671   - sender->sendConnackDeny(reason);
  658 + sender->addAuthReturnDataToStagedConnAck(returnData);
672 659 }
673 660 }
674 661 else
675 662 {
676   - throw ProtocolError("Invalid variable header length. Garbage?", ReasonCodes::MalformedPacket);
  663 + authResult = authentication.unPwdCheck(username, password, getUserProperties());
  664 + }
  665 +
  666 + if (authResult == AuthResult::success)
  667 + {
  668 + sender->sendConnackSuccess();
  669 + subscriptionStore->registerClientAndKickExistingOne(sender);
  670 + }
  671 + else
  672 + {
  673 + const ReasonCodes reason = authResultToReasonCode(authResult);
  674 + sender->sendConnackDeny(reason);
677 675 }
678 676 }
679 677  
... ...