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,68 +332,134 @@ void MqttPacket::handleConnect()
332 332
333 const Settings &settings = *ThreadGlobals::getSettings(); 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 if (protocolVersion == ProtocolVersion::Mqtt5) 459 if (protocolVersion == ProtocolVersion::Mqtt5)
396 { 460 {
  461 + willpublish.constructPropertyBuilder();
  462 +
397 const size_t proplen = decodeVariableByteIntAtPos(); 463 const size_t proplen = decodeVariableByteIntAtPos();
398 const size_t prop_end_at = pos + proplen; 464 const size_t prop_end_at = pos + proplen;
399 465
@@ -403,277 +469,209 @@ void MqttPacket::handleConnect() @@ -403,277 +469,209 @@ void MqttPacket::handleConnect()
403 469
404 switch (prop) 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 break; 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 break; 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 break; 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 break; 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 break; 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 break; 500 break;
433 } 501 }
434 - case Mqtt5Properties::AuthenticationData: 502 + case Mqtt5Properties::UserProperty:
435 { 503 {
436 - authenticationData = readBytesToString(false); 504 + readUserProperty();
437 break; 505 break;
438 } 506 }
439 default: 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 else 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