我有一段代码将数据包发送到TCP网络。我所做的是将两个新字段username_和password_添加到Packet对象。这是用于服务器端的身份验证。 问题是新数据包与新字段的校验和比较失败。我已经确保新字段到char *的String转换正确完成,但问题尚未解决。
这是数据包对象:
const static uint32_t TAG_START = 0xAA5AAAAAU; // 0x35F4BE07
const std::string USERNAME = "ARG-CO";
const std::string PASSWORD = "FUCK-YOU!";
const static uint32_t TAG_END = 0x555555A5U; // 0xB7DF087A
const static uint16_t VERSION = 0U; // starting version
const static uint16_t CURRENT_VERSION = 1U; // increment, when protocol changes
const static uint32_t CRC_INIT = 0xAFCE9265U; // initial checksum (crc) value
const static unsigned int USERNAME_SIZE = 7;
const static unsigned int PASSWORD_SIZE = 10;
const static unsigned int MAX_DATA_SIZE = 4096; //4113 // packet data size limit in bytes, to limit necessary buffers, for now this is sizeof(car_multi_record)
const static unsigned int PACKET_SIZE = 52 + USERNAME_SIZE + PASSWORD_SIZE; // empty packet size in bytes when serialized, sizeof(header)
const static unsigned int MAX_PACKET_SIZE = PACKET_SIZE + MAX_DATA_SIZE;
并且主要数据包创建在此成员函数内完成:
static Packet::ptr create(RTCINET_COMMANDS cmd, RTCINET_COMMANDS subcmd, Packet::ptr_bytea ba)
// TODO: unsigned short command_seq, data_seq, length
{
//Add user authentication fields, username n password here
std::cout << "creating packet..";
Packet::ptr pack(new Packet());
pack->command_ = cmd;
pack->subcommand_ = subcmd;
pack->data_length_ = ba->size();
pack->data_ = ba;
pack->make_checksum();
//assert(pack->check_checksum());
std::cout << "\n########### creating packet ###########";
std::cout << "\ntag_start_: " << pack->tag_start_ << std::endl;
std::cout << "username_: " << pack->username_ << std::endl;
std::cout << "password_: " << pack->password_ << std::endl;
std::cout << "version_: " << pack->version_ << std::endl;
std::cout << "checksum_: " << pack->checksum_ << std::endl;
std::cout << "connection_id_: " << pack->connection_id_ << std::endl;
std::cout << "timestamp_sec_: " << pack->timestamp_sec_ << std::endl;
std::cout << "timestamp_microsec_: " << pack->timestamp_microsec_ << std::endl;
std::cout << "command_: " << pack->command_ << std::endl;
std::cout << "command_seq_: " << pack->command_seq_ << std::endl;
std::cout << "subcommand: " << pack->subcommand_ << std::endl;
std::cout << "data_seq: " << pack->data_seq_ << std::endl;
std::cout << "data_length: " << pack->data_length_ << std::endl;
std::cout << "data_: " << pack->data_ << std::endl;
std::cout << "tag_end_: " << pack->tag_end_ << std::endl;
assert(pack->is_valid());
return pack;
}
请注意,主要问题是断言程序的断言功能:
assert(pack->is_valid());
但是,我确保在create_packet函数中创建的数据包与is_valid函数中的数据包具有完全相同的值:
bool Packet::is_valid() const
{
/*
std::cout << "TAG_START: " << Packet::TAG_START << "==" << this->tag_start_ << std::endl;
std::cout << "TAG_END: " << Packet::TAG_END << "==" << this->tag_end_ << std::endl;
std::cout << "VERSION: " << Packet::VERSION << "<" << this->version_ << std::endl;
std::cout << "CURRENT_VERSION: " << Packet::CURRENT_VERSION << ">=" << this->version_ << std::endl;
std::cout << "DATA SIZE: " << this->data_->size() << "==" << this->data_length_ << std::endl;
std::cout << "MAX_DATA_SIZE: " << Packet::MAX_DATA_SIZE << ">=" << this->data_length_ << std::endl;
std::cout << "MAX_PACKET_SIZE: " << Packet::MAX_PACKET_SIZE << ">=" << this->size() << std::endl;
std::cout << "check_checksum: " << check_checksum();
*/
std::cout << "\n########### validating . ###########";
std::cout << "\ntag_start_: " << this->tag_start_ << std::endl;
std::cout << "username_: " << this->username_ << std::endl;
std::cout << "password_: " << this->password_ << std::endl;
std::cout << "version_: " << this->version_ << std::endl;
std::cout << "checksum_: " << this->checksum_ << std::endl;
std::cout << "connection_id_: " << this->connection_id_ << std::endl;
std::cout << "timestamp_sec_: " << this->timestamp_sec_ << std::endl;
std::cout << "timestamp_microsec_: " << this->timestamp_microsec_ << std::endl;
std::cout << "command_: " << this->command_ << std::endl;
std::cout << "command_seq_: " << this->command_seq_ << std::endl;
std::cout << "subcommand: " << this->subcommand_ << std::endl;
std::cout << "data_seq: " << this->data_seq_ << std::endl;
std::cout << "data_length: " << this->data_length_ << std::endl;
std::cout << "data_: " << this->data_ << std::endl;
std::cout << "tag_end_: " << this->tag_end_ << std::endl;
std::cout << "############## determine sizes #############\n"
<< "username: " << this->username_.size()
<< "\npassword: " << this->password_.size();
std::cout << "\n########### checking checksum ############" << std::endl;
std::cout << check_checksum() << std::endl;
return
(Packet::TAG_START == this->tag_start_)
and (Packet::TAG_END == this->tag_end_)
and (Packet::VERSION < this->version_)
and (Packet::CURRENT_VERSION >= this->version_)
// TODO: and check command and subcommand fields to exist in commands list
and (this->data_->size() == this->data_length_)
and (Packet::MAX_DATA_SIZE >= this->data_length_)
and (Packet::MAX_PACKET_SIZE >= this->size())
and check_checksum();
}
我怀疑的是
的实施 boost::crc_32_type crc;
与check_checksum functions()中一样:
unsigned int Packet::get_checksum() const
{
//boost::crc_basic<16> crc_ccitt1(0x1021, 0xFFFF, 0, false, false);
//crc_ccitt1.process_bytes(data, data_len);
//assert(crc_ccitt1.checksum() == expected);
// Repeat with the optimal version (assuming a 16-bit type exists)
//boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt2;
//crc_ccitt2 = std::for_each(data, data + data_len, crc_ccitt2);
boost::crc_32_type crc; // predefined CRC class template using 32 bits, used in PKZip, AUTODIN II, Ethernet, FDDI
ptr_bytea ba = get_bin();
for (bytea::const_iterator iter = ba->begin(); iter != ba->end(); iter++)
{
crc.process_byte(*iter);
}
std::cout << "###### get_checksum ######## " << crc.checksum();
return crc(); // or crc.checksum();
}
void Packet::make_checksum()
{
checksum_ = CRC_INIT;
checksum_ = get_checksum();
}
bool Packet::check_checksum() const
{
//unsigned int cs = checksum_;
//checksum_ = CRC_INIT;
//bool check = (get_checksum() == cs);
//checksum_ = cs;
//return check;
// to be able to add const qualifier to method, make a copy of this object, and operate on it.
Packet pack(*this);
pack.checksum_ = CRC_INIT;
return (pack.get_checksum() == this->checksum_);
}
和
Packet::ptr_bytea Packet::get_bin() const
{
std::stringstream ss(std::ios_base::out | std::ios_base::in | std::ios_base::binary | std::ios_base::trunc);
byte b = 0U;
ss.write((char *) & this->tag_start_, sizeof(Packet::tag_start_));
ss.write(this->username_.c_str(), Packet::username_.size());
ss.write(this->password_.c_str(), Packet::password_.size());
ss.write((char *) & this->version_, sizeof(Packet::version_));
ss.write((char *) & this->checksum_, sizeof(Packet::checksum_));
ss.write((char *) & this->connection_id_, sizeof(Packet::connection_id_));
ss.write((char *) & this->packet_seq_, sizeof(Packet::packet_seq_));
ss.write((char *) this->guid_, sizeof(Packet::guid_));
ss.write((char *) & this->timestamp_sec_, sizeof(Packet::timestamp_sec_));
ss.write((char *) & this->timestamp_microsec_, sizeof(Packet::timestamp_microsec_));
ss.write((char *) & this->command_, sizeof(Packet::command_));
ss.write((char *) & this->command_seq_, sizeof(Packet::command_seq_));
ss.write((char *) & this->subcommand_, sizeof(Packet::subcommand_));
ss.write((char *) & this->data_seq_, sizeof(Packet::data_seq_));
ss.write((char *) & this->data_length_, sizeof(Packet::data_length_));
for (bytea::const_iterator iter = this->data_->begin(); iter != this->data_->end(); iter++) {
b = *iter;
ss.write((char *) & b, sizeof(b));
}
ss.write((char *) & this->tag_end_, sizeof(Packet::tag_end_));
ss.flush();
while (ss.read((char *) & b, sizeof(b))) {
//ba->push_back(b);
std::cout << std::hex << b;
}
if (not ss)
std::cerr << "failed to serialize the packet to binary data" << std::endl;
//else
//std::cerr << ss.rdbuf().str();
//std::cerr << *this << std::endl;
Packet::ptr_bytea ba(new bytea);
while (ss.read((char *) & b, sizeof(b))) {
ba->push_back(b);
}
//return ss.rdbuf(); // internal stringbuf object maintained by stringstream
return ba;
}
任何人都可以帮助我阻止两个校验和相等的错误吗?