Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Connection::Connection(
- std::string const& username,
- std::string const& password,
- std::string const& database,
- std::map<std::string, std::string> const& options,
- ConectReader& pr,
- ConectWriter& pw)
- : packageReader(pr)
- , packageWriter(pw)
- {
- std::unique_ptr<RespPackage> initPack = recvMessage(
- {{0x0A, [](int firstByte, ConectReader& reader
- )
- {return new RespPackageHandShake(firstByte, reader);}
- }
- });
- std::unique_ptr<RespPackageHandShake> handshake = downcastUniquePtr<RespPackageHandShake>(std::move(initPack));
- packageReader.initFromHandshake(handshake->getCapabilities(), handshake->getCharset());
- packageWriter.initFromHandshake(handshake->getCapabilities(), handshake->getCharset());
- RequPackageHandShakeResponse handshakeresp(username, password, options, database, *handshake);
- std::unique_ptr<RespPackage> ok = sendHandshakeMessage<RespPackage>(handshakeresp,
- {{0xFE, [](int firstByte, ConectReader& reader)
- {return new RespPackageAuthSwitchRequest(firstByte, reader);}
- }
- });
- if (!ok)
- {
- throw std::domain_error("Connection::Connection: Handshake failed: Unexpected Package");
- }
- if (!(ok->isOK()))
- {
- throw std::domain_error(errorMsg("Connection::Connection: Handshake failed: Got: ", (*ok)));
- }
- }
- #ifndef THORS_ANVIL_MYSQL_DETAILS_PACKAGE_RESP_HAND_SHAKE_H
- #define THORS_ANVIL_MYSQL_DETAILS_PACKAGE_RESP_HAND_SHAKE_H
- #include "RespPackage.h"
- #include <string>
- #include <sstream>
- #include <ostream>
- #include <iomanip>
- namespace ThorsAnvil
- {
- namespace MySQL
- {
- class ConectReader;
- class RespPackageHandShake: public RespPackage
- {
- std::string serverVersion;
- long connectionID;
- std::string authPluginData;
- long check;
- //--
- long statusFlag;
- long authPluginLength;
- std::string reserved;
- std::string authPluginName;
- bool isV9;
- long capabilities;
- char charset;
- public:
- RespPackageHandShake(int firstByte, ConectReader& reader);
- virtual std::ostream& print(std::ostream& s) const;
- long getCapabilities() const {return capabilities;}
- long getCharset() const {return charset;}
- std::string const& getAuthPluginName() const {return authPluginName;}
- std::string const& getAuthPluginData() const {return authPluginData;}
- };
- inline std::ostream& RespPackageHandShake::print(std::ostream& s) const
- {
- std::stringstream reservedDecoded;
- for (char x: reserved)
- {
- reservedDecoded << "0x" << std::hex << static_cast<int>(x) << " ";
- }
- std::stringstream authPluginDataDecoded;
- for (char x: authPluginData)
- {
- authPluginDataDecoded << "0x" << std::hex << static_cast<int>(x) << " ";
- }
- return s << "RespPackageHandShake: "
- << "serverVersion(" << serverVersion << ") "
- << "connectionID(" << connectionID << ") "
- << "authPluginData(" << authPluginDataDecoded.str() << ") "
- << "check(" << check << ") "
- << "statusFlag( 0x" << std::hex << std::setw(8) << std::setfill('0') << statusFlag << ") "
- << "authPluginLength(" << authPluginLength << ") "
- << "reserved(" << reservedDecoded.str() << ") "
- << "authPluginName(" << authPluginName << ") "
- << "capabilities(" << capabilities << ") "
- << "isV9(" << isV9 << ") "
- << std::dec;
- }
- }
- }
- #endif
- #include "ThorMySQL.h"
- #include "ConectReader.h"
- #include "RespPackageHandShake.h"
- #include <cassert>
- using namespace ThorsAnvil::MySQL;
- RespPackageHandShake::RespPackageHandShake(int firstbyte, ConectReader& reader)
- : RespPackage(reader, "HandShake")
- , serverVersion(reader.nulTerminatedString())
- , connectionID(reader.fixedLengthInteger<4>())
- , authPluginData(reader.fixedLengthString(8))
- , check(0)
- , statusFlag(0)
- , authPluginLength(0)
- , isV9(false)
- , capabilities(0)
- {
- // https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeV10
- assert(firstbyte = 0x0A);
- if (reader.isEmpty())
- {
- isV9 = true;
- return;
- }
- check = reader.fixedLengthInteger<1>();
- capabilities = reader.fixedLengthInteger<2>();
- if (reader.isEmpty())
- {
- return;
- }
- charset = reader.fixedLengthInteger<1>();
- statusFlag = reader.fixedLengthInteger<2>();
- long cap2 = reader.fixedLengthInteger<2>();
- authPluginLength= 0;
- capabilities = capabilities | (cap2 << 16);
- if (capabilities & CLIENT_PLUGIN_AUTH)
- {
- authPluginLength= reader.fixedLengthInteger<1>();
- }
- else
- {
- int fill = reader.fixedLengthInteger<1>();
- assert(fill == 0);
- }
- reserved = reader.fixedLengthString(10);
- std::string authPluginData2;
- if (capabilities & CLIENT_SECURE_CONNECTION)
- {
- authPluginData2 = reader.variableLengthString(std::max(13L, authPluginLength - 8L));
- }
- if (capabilities & CLIENT_PLUGIN_AUTH)
- {
- authPluginName = reader.nulTerminatedString();
- }
- // Because of the way 13L is the min size for authPluginData2 data
- // This may exceed the actual size of the auth data. So after concatenating the
- // data make sure we only use the required length `authPluginLength`. This means
- // removing the extra terminating '