加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
hpsocket_s.cpp 34.62 KB
一键复制 编辑 原始数据 按行查看 历史
yala 提交于 2021-06-05 16:20 . 1. 修复文件传输暂停错误
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
#include "hpsocket_s.h"
#include <stdio.h>
#include <QDataStream>
void CListenerImpl::init_listener(void)
{
//db = new lus_db;
//db->lus_database_init();
/*加密模块初始化*/
UCHAR *p = aes_key;
aes->InitializePrivateKey(16, p); //进行初始化
rsa_cache = new char[CRYPT_CACHE_SIZE];
bne=BN_new();
lus_rsa = RSA_new();
BN_set_word(bne,RSA_F4);
if(RSA_generate_key_ex(lus_rsa, 2048, bne, NULL) == NULL){
logger()->error()<<"gen rsa error";
exit(-1);
}
BN_free(bne);
logger()->debug()<<"server rsa size: "<<RSA_size(lus_rsa);
FILE *fp = fopen("rsa_pub.pem", "w");
PEM_write_RSAPublicKey(fp, lus_rsa);
fclose(fp);
QFile rsa_file("rsa_pub.pem");
rsa_file.open(QIODevice::ReadOnly);
local_pub_rsa = rsa_file.readAll();
rsa_file.close();
logger()->debug()<<"local rsa: "<<local_pub_rsa;
//blockSize = 0;
pub_timer = new QTimer;
connect(pub_timer, SIGNAL(timeout()), this, SLOT(timer_public_fun()));
pub_timer->start(2000);
//make_client_pub(NULL, "haha");
//tcp_cache_data = (char *)malloc(sizeof(char)*1024*1024);
}
/*解析msg 的xml语句*/
void CListenerImpl::do_cmd(QByteArray cmd, CONNID dwConnID, uint8_t encrypt_c)
{
struct m_client *client_t;
if(client_map.contains(dwConnID)){
client_t = client_map.find(dwConnID).value();
}else{
return;
}
server_xml.setContent(cmd);
QDomElement rootnode = server_xml.documentElement();
if(rootnode.tagName() == "lus_user_msg" || rootnode.tagName() == "user_msg"){ //传输的文本信息
// special fun
if(rootnode.attributeNode("type").value() == "tank_image"){
// qDebug() << "tk_image";
email_data(cmd, "TANK_IMAGE_ADDR", ENCRYPT_NO, 0);
return;
}
if(rootnode.attributeNode("type").value() == "tk_nrf_status"){
email_data(cmd, "TANK_ADDR", encrypt_c, 0);
return;
}
/*************************************************/
//general fun
if(rootnode.attributeNode("to_addr").isNull()){
log_printf("no to_addr arg, refuse email\n", LG_WARING);
return;
}
QString addr = rootnode.attributeNode("to_addr").value();
if(addr.isEmpty()){
email_data(cmd, "BROADCAST_ADDR", encrypt_c, 0);
log_printf("no addr, broadcast msg!", LG_WARING);
}else{
email_data(cmd, addr, encrypt_c, 0);
}
return;
}
if(rootnode.tagName() == "lus_init_msg"){
QString fix_id;
fix_id = rootnode.attributeNode("fix_id").value();
if(fix_id.isEmpty())
return;
client_t->fix_id = fix_id;
QString rsa_str = rootnode.attributeNode("key_pub").value();
RSA* rsa = RSA_new();
FILE *fp = fopen("tmp", "w");
fwrite(rsa_str.toLatin1().data(), rsa_str.size(), 1, fp);
fclose (fp);
fp = fopen("tmp", "r");
PEM_read_RSAPublicKey(fp, &rsa, NULL, NULL);
fclose (fp);
logger()->debug()<<"client rsa dize: "<<RSA_size(rsa);
client_t->rsa = rsa;
return;
}
emit lus_msg(cmd, dwConnID, encrypt_c);
}
void CListenerImpl::timer_public_fun(void)
{
if(HEART_CHECK){
/*heart 检测*/
for(int i=0; i<msg_clinet_list.size(); i++){
logger()->debug()<<"check "<<msg_clinet_list.at(i)->fix_id<<"heart "<<msg_clinet_list.at(i)->heart;
msg_clinet_list.at(i)->heart -=1;
if(msg_clinet_list.at(i)->heart == 0){
((ITcpServer*)msg_clinet_list.at(i)->socket)->Disconnect(msg_clinet_list.at(i)->var_id);
logger()->info()<<msg_clinet_list.at(i)->fix_id<< " time out";
}
}
}
}
void CListenerImpl::make_client_pub(struct m_client*client, QString pub_str)
{
qDebug()<<"___flag";
RSA* tmp_rsa = nullptr;
qDebug()<<"new rsa: "<<tmp_rsa;
QString ras_str = "-----BEGIN RSA PUBLIC KEY-----\nMEgCQQCwJHFaJUrtpL/mmhLu55WHIRd/jVa2KFfew5ubpIz6Rt842X34DIihA13O\nw7XiyKqTVHGkvkcjCAJXc601t+IPAgMBAAE=\n-----END RSA PUBLIC KEY-----";
BIO * rsa_pub_bio = BIO_new_mem_buf(ras_str.toLatin1().data(), ras_str.size());
qDebug()<<"BIO: "<<rsa_pub_bio;
tmp_rsa = PEM_read_bio_RSAPublicKey(rsa_pub_bio, NULL, NULL, NULL);
qDebug()<<"client pub: \n" << ras_str;
qDebug()<<"rsa :"<<tmp_rsa;
qDebug()<<RSA_size(tmp_rsa);
qDebug()<<"___flag__end";
BIO_free(rsa_pub_bio);
RSA_free(tmp_rsa);
}
/*解析这段状态xml 并在ui显示*/
void hpsocket_s::prase_bd_info( QDomElement rootnode, CONNID dwConnID)
{
QString cpu_info,
hd_info,
client_id,
group_id,
cpu_temp,
client_ver;
struct m_client *client_t = id_2_client(dwConnID);
CHECK_PTR_VOID(client_t);
client_id = rootnode.attributeNode("id").value();
if(client_id.size() == 0)return;
cpu_info = rootnode.attributeNode("cpu_info").value();
hd_info = rootnode.attributeNode("disk_space").value();
group_id = rootnode.attributeNode("group_id").value().simplified();
client_ver = rootnode.attributeNode("version").value().simplified();
cpu_temp = rootnode.attributeNode("cpu_temp").value().simplified();
QString fix_id = client_t->fix_id;
logger()->debug(fix_id + "update bd infor");
/*write group id and fix id to struct*/
if(!group_id.isEmpty())
client_t->group_id = group_id;
if(!cpu_info.isEmpty())
client_t->bd_info.cpu_info = cpu_info;
if(!hd_info.isEmpty())
client_t->bd_info.hd_info = hd_info;
if(!client_ver.isEmpty())
client_t->firmware_ver = client_ver;
if(!cpu_temp.isEmpty())
client_t->bd_info.cpu_temp = cpu_temp;
emit flush_bd_info_signal(client_t->var_id);
//ui info flush
/*根据组ID 应版本最新version*/
if(group_id == "0")return;
logger()->info("check version");
int new_version = -1;
for(int i=0; i<xml_conf->server_conf->version_inf_list.size(); i++){
if(xml_conf->server_conf->version_inf_list.at(i)->group_id== group_id){
logger()->debug("found version info of:"+fix_id +"in group:"+group_id);
new_version = xml_conf->server_conf->version_inf_list.at(i)->version.toInt();
break;
}
}
if(new_version == -1) {
logger()->warn("未找到此组ID: " + group_id);
return;
}
/*already in the down list so jump version check
for(int i=0; i<file_clinet_list.size(); i++){
if(file_clinet_list.at(i)->down_info->contact_var_id == client_t->var_id){
return;
}
}
*/
if((!client_ver.isEmpty()) && client_ver.toInt() != 0){
if((new_version > client_ver.toInt())){
//TODO add auto update
/*
QString msg_str;
msg_str.sprintf("<version_info id=\"%x\" now_version=\"%d\"></version_info>", dwConnID, new_version);
QByteArray ba = msg_str.toLatin1();
sendMessage(dwConnID, ba, ENCRYPT_YES);
logger()->info("had new version send cmd to :" + fix_id);
*/
}
}
}
void hpsocket_s::lus_do_cmd(QByteArray cmd, CONNID dwConnID, uint8_t encrypt_c)
{
QDomDocument xml;
xml.setContent(cmd);
struct m_client * client = id_2_client(dwConnID);
CHECK_PTR_VOID(client);
struct _down_info *down_info = &client->down_info;
QDomElement rootnode = xml.documentElement();
if(rootnode.tagName() == "lus_cmd"){
if(rootnode.attributeNode("body").isNull()){
log_printf("error! no body world", LG_ERROR);
return;
}
/*更新client心跳*/
if(rootnode.attributeNode("body").value() == "heart"){
uint16_t heart_time = 0;
heart_time = rootnode.attributeNode("paral").value().toInt();
logger()->debug(QString("get once herat : %1 fix id: %2").arg(QString::number(heart_time), client->fix_id));
client->heart = heart_time;
return;
}
if(rootnode.attributeNode("body").value() == "requst_members"){
QString msg = "<user_msg type=\"members_id\" body=\"";
for(int i=0; i<hp_listener->msg_clinet_list.size(); i++){
//msg+=msg_clinet_list.at(i)->fix_id;
msg+=",";
}
msg += "\" />";
logger()->info(QString("%1 requst members: %2").arg(client->fix_id).arg(msg));
return;
}
if(rootnode.attributeNode("body").value() == "licence"){
QString key_md5;
key_md5 = rootnode.attributeNode("paral").value();
logger()->info("key md5: " + key_md5);
for(int i=0; i<licence_list.size(); i++){
if(key_md5.toLatin1() == licence_list.at(i)->key){
if(client->licence.indexOf(licence_list.at(i)->licence_str) == -1){
client->licence += licence_list.at(i)->licence_str;
client->licence +="#";
logger()->info("add lience: " + client->licence);
}
return;
}
}
return;
}
}
if(rootnode.tagName() == "bd_info"){ //板级状态信息
prase_bd_info(rootnode, dwConnID);
return;
}
//wait for test
if(rootnode.tagName() == "lus_requst"){ //升级请求
if(rootnode.attributeNode("type").isEntity()){
log_printf("error! no type world", LG_ERROR);
return;
}
if(rootnode.attributeNode("type").value() == "id_info"){
QString fix_id = rootnode.attributeNode("fix_id").value();
logger()->debug()<<"got client: "<<fix_id;
}
if(rootnode.attributeNode("type").value() == "file_down"){
QString index = rootnode.attributeNode("index").value()+"/";
QString label = rootnode.attributeNode("label").value()+"/";
QString file_name = file_pool + index+label+rootnode.attributeNode("file_name").value();
QFileInfo f_info(file_name);
if(!f_info.exists()){
logger()->error()<<"no such file: "<<file_name;
return;
}
logger()->info(client->fix_id + "requst "+file_name);
down_info->file_path = file_name;
down_info->type = ST_FILE;
down_info->status = DOWN_WAITE;
QString cmd = "<lus_cmd body=\"send_file\" type=\"requst_file\" md5=\"xxxx\" />";
QString file_md5 = get_file_md5(file_name);
cmd.replace("xxxx", file_md5);
sendMessage(dwConnID, cmd.toLatin1(), ENCRYPT_YES);
}
//change kernel_down to exec_pack
if(rootnode.attributeNode("type").value() == "exec_pack"){
down_info->type = ST_PACK;
//TODO find file in file pool
for(int i=0; i<xml_conf-> server_conf->version_inf_list.size(); i++){
if(xml_conf->server_conf->version_inf_list.at(i)->group_id == client->group_id){
QString path = xml_conf-> server_conf->version_inf_list.at(i)->file_path;
if((!path.isEmpty()) && (path.size()>4)){
down_info->file_path = path;
logger()->info(client->fix_id + ": update kernel " + down_info->file_path);
down_info->status = DOWN_WAITE;
QString cmd = "<lus_cmd body=\"send_file\" type=\"kernel\" md5=\"xxxx\" />";
QString file_md5 = get_file_md5(down_info->file_path);
cmd.replace("xxxx", file_md5);
sendMessage(dwConnID, cmd.toLatin1(), ENCRYPT_YES);
}else{
logger()->warn()<<"kernel_down error, file path is null";
}
}
}
}
return;
}
if(rootnode.tagName() == "term_cmd_bak"){ //term返回信息
QString str = rootnode.attributeNode("body").value();
QByteArray bak_txt;
bak_txt = bak_txt.fromBase64(str.toLatin1());
if(!rootnode.attributeNode("exit_code").isEntity()){
bak_txt += "\n";
bak_txt += ">>exit code:"+rootnode.attributeNode("exit_code").value();
bak_txt += "<<";
}
logger()->debug()<<client->fix_id <<":terminal bak "<< bak_txt;
emit terminal_bak(bak_txt);
return;
}
logger()->error()<<client->fix_id << ":not found cmd :" + cmd;
}
/*扫描等待下载列表,并发起下载*/
void hpsocket_s::auto_scanf_down(void)
{
/*没有等待下载的client*/
if(file_clinet_list.size() == 0)return;
logger()->debug()<<"auto scan file client list";
if(downing_count > xml_conf->server_conf->max_down){
logger()->warn()<<"got max downing limit: "<<xml_conf->server_conf->max_down;
return;
}
for(int i=0; i<file_clinet_list.size(); i++){
m_client *client = file_clinet_list.at(i);
//no down info
if(client->fix_id == nullptr || client->down_info.status == DOWN_DISABLE){
client->heart --;
if(client->heart == 0){
logger()->info()<<client->fix_id<<" "<<"file client got fix id timeout";
QTcpSocket * sk;
sk = (QTcpSocket *)client->socket;
if(sk != nullptr){
sk->close();
}
}
continue;
}
logger()->debug()<<"scan "<<client->fix_id<<": file_inf.down_status: "<<client->down_info.status;
if(client->down_info.status == DOWN_WAITE){
logger()->info()<<"send file to " <<client->fix_id <<" " <<client->down_info.file_path;
client->down_info.status = DOWN_ING;
downing_count++;
sendfile_launch(client);
}else if(client->down_info.status == DOWN_OK){
logger()->debug()<<"clear down client: "<<client->fix_id;
downing_count--;
//free(client->tcp_msg_inf.cache);
file_clinet_list.removeAt(i);
//((QTcpSocket *)client->socket)->close();
//TODO check mem
}
}
}
void hpsocket_s::clr_file_client()
{
struct m_client * p_clinet;
QTcpSocket * clientConnection = qobject_cast<QTcpSocket *>(sender());
/*查找、私有化操作的client*/
for(int i=0; i<file_clinet_list.size(); i++){
if(file_clinet_list.at(i)->socket == clientConnection){
p_clinet=file_clinet_list.at(i);
}
}
free(p_clinet->tcp_msg_inf.cache);
file_clinet_list.removeOne(p_clinet);
}
void hpsocket_s::send_init_file()
{
struct m_client * p_clinet = new struct m_client;
p_clinet->file_inf.bytesToWrite = 0;
p_clinet->file_inf.bytesWritten = 0;
p_clinet->file_inf.totalBytes = 0;
p_clinet->tcp_msg_inf.cache =(unsigned char *) malloc(sizeof(unsigned char) * FILE_MSG_CACHE);
QTcpSocket *clientConnection = tcp_file_server->nextPendingConnection();
if(clientConnection == 0){
logger()->error()<<"got bad file client!";
return;
}
p_clinet->socket = clientConnection;
connect(clientConnection,SIGNAL(readyRead()),this,SLOT(readsocket_data()));
connect(clientConnection,SIGNAL(disconnected()), this,SLOT(clr_file_client()));
connect(clientConnection,SIGNAL(bytesWritten(qint64)),this,SLOT(sendFileBody(qint64)));
/*a new device online*/
if( clientConnection != NULL){
p_clinet->down_info.status = DOWN_DISABLE;
p_clinet->fix_id.clear();
p_clinet->down_info.file_path.clear();
p_clinet->down_info.type = 0xff;
p_clinet->heart = DEF_FILE_CLIENT_HEART_TIME;
file_clinet_list.append(p_clinet);
}else{
logger()->error()<<"alloc file client error!";
}
}
void hpsocket_s::readsocket_data()
{
QTcpSocket * socket = qobject_cast<QTcpSocket *>(sender());
struct m_client * client = nullptr;
QDataStream in(socket);
//设置数据流版本,这里要和服务器端相同
in.setVersion(QDataStream::Qt_5_6);
in.setByteOrder(QDataStream::LittleEndian);
for(int i=0; i<file_clinet_list.size(); i++){
if(file_clinet_list.at(i)->socket == socket){
client = file_clinet_list.at(i);
break;
}
}
if(client == nullptr)
return;
if( client->tcp_msg_inf.blocksize ==0) //如果是刚开始接收数据
{
//判断接收的数据是否有两字节,也就是文件的大小信息
//如果有则保存到blockSize变量中,没有则返回,继续接收数据
if(socket->bytesAvailable() < (int)(sizeof(quint32) +sizeof(quint8))) {
return;
}
in >> client->tcp_msg_inf.blocksize;
in >> client->tcp_msg_inf.load_size;
in >> client->tcp_msg_inf.encrypt_flag;
qDebug() << "file client block size "<<client->tcp_msg_inf.blocksize;
qDebug() << "file client encrypt flag" << client->tcp_msg_inf.encrypt_flag;
}
if(socket->bytesAvailable() < (client->tcp_msg_inf.blocksize-sizeof(quint32)*2-sizeof (quint8))) return;
//如果没有得到全部的数据,则返回,继续接收数据
int real_data_len = client->tcp_msg_inf.blocksize -sizeof(quint32)*2-sizeof (quint8);
//qDebug()<<real_data_len;
if(real_data_len > FILE_MSG_CACHE){
logger()->error()<<"msg too big for FILE_MSG_CACHE:"<<FILE_MSG_CACHE;
return;
}
in.readRawData((char *)client->tcp_msg_inf.cache, real_data_len); //原始读取!
QByteArray byte_data;
QDataStream b_in(&byte_data, QIODevice::WriteOnly);
if(client->tcp_msg_inf.encrypt_flag == ENCRYPT_YES && hp_listener->lus_rsa != nullptr){
char rsa_cache[1024 * 1024] = {0};
int un_size = 0;
//解密
un_size = RSA_private_decrypt(real_data_len, client->tcp_msg_inf.cache, (unsigned char *)rsa_cache, hp_listener->lus_rsa, RSA_PKCS1_OAEP_PADDING);
if(un_size > CRYPT_CACHE_SIZE){
logger()->error()<<un_size <<" too long to jiemi arrary!";
b_in.writeRawData((const char *)client->tcp_msg_inf.cache, client->tcp_msg_inf.load_size);
//return -1;
}
b_in.writeRawData(rsa_cache, client->tcp_msg_inf.load_size);
}else{
b_in.writeRawData((const char *)client->tcp_msg_inf.cache, real_data_len);
}
client->tcp_msg_inf.blocksize = 0;
#if DEBUG_SOCKET
qDebug()<<"f socket: "<< byte_data;
#endif
if(byte_data.startsWith('<') && byte_data.endsWith('>')){
byte_data = byte_data.remove(0, 1);
byte_data = byte_data.remove(byte_data.size()-1, 1);
//qDebug()<<byte_data;
QByteArrayList list = byte_data.split(',');
if(list.at(0) == "id"){
for(int i=0; i<hp_listener->msg_clinet_list.size(); i++){
if(hp_listener->msg_clinet_list.at(i)->fix_id == list.at(1)){
m_client *msg_client = hp_listener->msg_clinet_list.at(i);
if(msg_client->down_info.file_path.isEmpty()){
logger()->error()<<"down_info file path is empty!";
}else{
logger()->info()<<"client: "<<hp_listener->msg_clinet_list.at(i)->fix_id<<" "<<"add to down list";
client->down_info = msg_client->down_info;
client->fix_id = msg_client->fix_id;
client->rsa = msg_client->rsa;
client->var_id = msg_client->var_id;
client->down_info.status = DOWN_WAITE;
}
}
}
}else{
logger()->error()<<"bad file client msg format";
}
}
}
void hpsocket_s::sendfile_launch(struct m_client * p_clinet) //实现文件大小等信息的发送
{
QString path = p_clinet->down_info.file_path;
if(path.isEmpty()){
logger()->warn()<<"file path is null";
return;
}
p_clinet->file_inf.localFile = new QFile(path);
QTcpSocket *clientConnection =(QTcpSocket *) p_clinet->socket;
QFile * file = p_clinet->file_inf.localFile;
if(! file->open(QFile::ReadOnly))
{
logger()->error() << "open file error!";
return;
}
//文件总大小
p_clinet->file_inf.totalBytes = file->size();
//qDebug()<< "file size :" << p_clinet->file_inf.totalBytes;
QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
sendOut.setVersion(QDataStream::Qt_4_6);
QString currentFileName;
if(path.indexOf('/') != -1){
currentFileName = path.right(path.size()- path.lastIndexOf('/')-1);
}else if(path.indexOf('\\') != -1){
qDebug() << "lastIndexOf" << path.lastIndexOf('\\');
currentFileName = path.right(path.size()- path.lastIndexOf('\\')-1);
}
qDebug() << "currentFileName " << currentFileName;
//依次写入文件类型、总大小信息空间、文件名大小信息空间、文件名
sendOut << qint64(0)<<qint64(0) << qint64(0) << currentFileName;
//这里的总大小是文件名大小等信息和实际文件大小的总和
p_clinet->file_inf.totalBytes += outBlock.size();
sendOut.device()->seek(0);
//返回outBolock的开始,用实际的大小信息代替3个qint64(0)空间
sendOut<<p_clinet->down_info.type <<p_clinet->file_inf.totalBytes <<qint64((outBlock.size() - sizeof(qint64)*3));
qDebug() << "file info: "<< p_clinet->down_info.type <<" "<<p_clinet->file_inf.totalBytes << qint64((outBlock.size() - sizeof(qint64)*3));
//发送完头数据后剩余数据的大小
p_clinet->file_inf.bytesToWrite = p_clinet->file_inf.totalBytes - clientConnection->write(outBlock);
outBlock.resize(0);
}
void hpsocket_s::lus_send_file(CONNID id, QString fileName)
{
struct m_client * p_client = id_2_client(id);
CHECK_PTR_VOID(p_client);
if(p_client->down_info.status == DOWN_ING){
qDebug()<<"client busy!";
return;
}
p_client->down_info.status = DOWN_WAITE;
p_client->down_info.file_path = fileName;
}
void hpsocket_s::sendFileBody(qint64 numBytes)
{
struct m_client * p_clinet;
QTcpSocket * clientConnection = qobject_cast<QTcpSocket *>(sender());
/*查找、私有化操作的client*/
for(int i=0; i<file_clinet_list.size(); i++){
if(file_clinet_list.at(i)->socket == clientConnection){
p_clinet=file_clinet_list.at(i);
logger()->debug() << "send body found clinet " << p_clinet->fix_id;
}
}
//已经发送数据的大小
p_clinet->file_inf.bytesWritten += (int)numBytes;
logger()->debug() << "bytesWritten="<< p_clinet->file_inf.bytesWritten;
logger()->debug() << "to bytesWritten="<< p_clinet->file_inf.bytesToWrite;
if(p_clinet->file_inf.bytesToWrite > 0) //如果已经发送了数据
{
//每次发送loadSize大小的数据,这里设置为4KB,如果剩余的数据不足4KB,
//就发送剩余数据的大小
outBlock =p_clinet->file_inf.localFile->read(qMin(p_clinet->file_inf.bytesToWrite,loadSize));
//发送完一次数据后还剩余数据的大小
p_clinet->file_inf.bytesToWrite -= (int)clientConnection->write(outBlock);
//清空发送缓冲区
outBlock.resize(0);
} else {
logger()->debug()<<"close file connect no data to send";
p_clinet->file_inf.localFile->close(); //如果没有发送任何数据,则关闭文件
p_clinet->down_info.status = DOWN_OK;
return;
}
if(p_clinet->file_inf.bytesWritten == p_clinet->file_inf.totalBytes) //发送完毕
{
p_clinet->file_inf.localFile->close();
logger()->debug() << "file send ok";
p_clinet->down_info.status = DOWN_OK;
return ;
}
}
quint64 hpsocket_s::lus_client_msg_count(void)
{
return hp_listener->msg_clinet_list.size();
}
quint64 hpsocket_s::lus_client_down_count(void)
{
return file_clinet_list.size();
}
void CListenerImpl::email_data(QByteArray data, QString addr, uint8_t encrypt_c, int port)
{
/*广播消息*/
if(addr == "BROADCAST_ADDR"){
log_printf("broadcast!", LG_DEBUG);
if(msg_clinet_list.size() <2)return;
for(int i=0; i<msg_clinet_list.size(); i++){
lus_send((ITcpServer*)msg_clinet_list.at(i)->socket, msg_clinet_list.at(i)->var_id,data, encrypt_c);
}
}else if(addr == "TANK_ADDR"){
if(msg_clinet_list.size() <2)return;
for(int i=0; i<msg_clinet_list.size(); i++){
/*
if(msg_clinet_list.at(i)->licence.indexOf(TANK_LICENCE) != -1){
lus_send((ITcpServer*)msg_clinet_list.at(i)->socket, msg_clinet_list.at(i)->var_id,data, encrypt_c);
}
*/
}
}else if(addr == "TANK_IMAGE_ADDR"){
}else if(addr == "TANK_CMD_ADDR"){
}else{
/*发送给指定clinet*/
for(int i=0; i<msg_clinet_list.size(); i++){
if(msg_clinet_list.at(i)->fix_id == addr){
lus_send((ITcpServer*)msg_clinet_list.at(i)->socket, msg_clinet_list.at(i)->var_id,data, encrypt_c);
log_printf("sendto " + msg_clinet_list.at(i)->fix_id, LG_DEBUG);
}
}
}
}
EnHandleResult CListenerImpl:: OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
{
struct m_client * p_clinet = new struct m_client;
TCHAR szAddress[50];
int iAddressLen = sizeof(szAddress) / sizeof(TCHAR);
USHORT usPort;
p_clinet->file_inf.bytesToWrite = 0;
p_clinet->file_inf.bytesWritten = 0;
p_clinet->file_inf.totalBytes = 0;
p_clinet->tcp_msg_inf.cache = (unsigned char *)malloc(sizeof(char)*1024*1024); //TODO cfg
p_clinet->tcp_msg_inf.blocksize = 0;
p_clinet->msg_count = 0;
p_clinet->heart = DEF_HEART_TIME;
p_clinet->down_info.status = DOWN_DISABLE;
p_clinet->socket = pSender;
p_clinet->up_time = QDateTime::currentDateTime();
p_clinet->rsa = nullptr;
//QString time_str = time.toString("M-d hh:m:s");
/*a new device online*/
QString msg_str;
p_clinet->var_id = dwConnID;
msg_str.clear();
/*获取client的IP地址*/
pSender->GetRemoteAddress(dwConnID, szAddress, iAddressLen, usPort);
p_clinet->clinet_ip = QString(szAddress);
logger()->info() <<"client connected: " <<p_clinet->clinet_ip;
// qDebug()<<"port num :"<<usPort;
msg_clinet_list.append(p_clinet);
client_map.insert(dwConnID, p_clinet);
/*发送动态ID到client*/
msg_str = QString("<lus_init_msg id=\"%1\" key_pub=\"%2\" now_version=\"\" />").arg(QString::number(dwConnID), QString(local_pub_rsa));
QByteArray ba = msg_str.toLatin1();
lus_send(pSender, dwConnID, ba, ENCRYPT_NO);
return HR_OK;
}
EnHandleResult CListenerImpl::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
QDateTime end_time = QDateTime::currentDateTime();
struct m_client * client = client_map.find(dwConnID).value();
client->down_time = end_time;
logger()->info()<<client->fix_id<< " <offcline> ";
/**free**/
free(client->tcp_msg_inf.cache);
RSA_free((RSA *)client->rsa);
/**end free**/
int index = msg_clinet_list.indexOf(client);
if(likely(index != -1)){
if(offline_list.size()>100){
offline_list.removeFirst();
}
offline_list.append(msg_clinet_list.takeAt(index));
}
client_map.remove(dwConnID);
}
EnHandleResult CListenerImpl::OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength)
{
ITcpPullServer* pServer = ITcpPullServer::FromS(pSender);
struct m_client * client = client_map.find(dwConnID).value();
int remain = iLength;
while(remain > 0){
if( client->tcp_msg_inf.blocksize ==0){
if(iLength < LUS_PACK_HEAH_SZ) {
return HR_IGNORE;
}
/*读取包头信息*/
pServer->Fetch(dwConnID, (BYTE *)(&client->tcp_msg_inf.blocksize),sizeof (quint32));
pServer->Fetch(dwConnID, (BYTE *)(&client->tcp_msg_inf.load_size),sizeof (quint32));
pServer->Fetch(dwConnID, (BYTE *)(&client->tcp_msg_inf.encrypt_flag),sizeof (quint8));
remain -= LUS_PACK_HEAH_SZ;
//qDebug()<<client->tcp_msg_inf.blocksize << " " <<client->tcp_msg_inf.load_size<<" "<<client->tcp_msg_inf.encrypt_flag;
}
//如果没有得到全部的数据,则返回,继续接收数据
if(iLength < (client->tcp_msg_inf.blocksize-LUS_PACK_HEAH_SZ)) return HR_IGNORE;
int real_data_len = client->tcp_msg_inf.blocksize -LUS_PACK_HEAH_SZ;
pServer->Fetch(dwConnID, (BYTE *)client->tcp_msg_inf.cache, real_data_len);
remain -= real_data_len;
QByteArray byte_data;
QDataStream b_in(&byte_data, QIODevice::WriteOnly);
if(client->tcp_msg_inf.encrypt_flag == ENCRYPT_YES){
//将接收到的数据存放到变量中
int un_size = 0;
//解密
un_size = RSA_private_decrypt(real_data_len, client->tcp_msg_inf.cache, (unsigned char *)rsa_cache, lus_rsa, RSA_PKCS1_OAEP_PADDING);
if(un_size > CRYPT_CACHE_SIZE){
logger()->error()<<un_size <<" too long to jiemi arrary!";
b_in.writeRawData((const char *)client->tcp_msg_inf.cache, client->tcp_msg_inf.load_size);
//return -1;
}
b_in.writeRawData(rsa_cache, client->tcp_msg_inf.load_size);
do_cmd(byte_data, dwConnID, ENCRYPT_YES);
}else{
b_in.writeRawData((const char *)client->tcp_msg_inf.cache, real_data_len);
do_cmd(byte_data, dwConnID, ENCRYPT_NO);
}
client->msg_count++;
client->tcp_msg_inf.blocksize = 0;
}
}
EnHandleResult CListenerImpl::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
ITcpPullServer* pServer = ITcpPullServer::FromS(pSender);
if(pServer ==hp_file_server){
}
return HR_IGNORE;
}
void CListenerImpl::lus_send(ITcpServer* pSender, CONNID dwConnID, QByteArray b_data, quint8 encrypt_c)
{
struct m_client *client_t;
if(client_map.contains(dwConnID)){
client_t = client_map.find(dwConnID).value();
}else{
qDebug()<<"find not this client";
return;
}
RSA * rsa = (RSA *)client_t->rsa;
logger()->debug()<<"got client: "<< client_t->fix_id << " rsa" << rsa;
//qDebug()<<"send "<<b_data;
//用于暂存我们要发送的数据
QByteArray block;
//使用数据流写入数据
QDataStream out(&block,QIODevice::WriteOnly);
//设置数据流的版本,客户端和服务器端使用的版本要相同
out.setVersion(QDataStream::Qt_5_6);
out.setByteOrder(QDataStream::LittleEndian);
if(b_data.size() > CRYPT_CACHE_SIZE)
encrypt_c == ENCRYPT_NO;
out<<(quint32) 0;
out<<(quint32) b_data.size();
if(encrypt_c == ENCRYPT_YES && rsa != nullptr){
quint32 en_len = 0;
//qDebug()<<"en_len: " <<en_len << " "<<RSA_size(rsa);
en_len = RSA_public_encrypt(b_data.size(), (const unsigned char *)b_data.data(), (unsigned char *)rsa_cache, rsa, RSA_PKCS1_OAEP_PADDING);
//qDebug()<<"en_len: " <<en_len;
out<<(quint8) ENCRYPT_YES;
out.writeRawData(rsa_cache, sizeof(char)*en_len); //原始写!!
out.device()->seek(0);
out<<(quint32) ((en_len + sizeof(quint32)*2+sizeof(quint8)));
}else{
out<<(quint8) ENCRYPT_NO;
out.writeRawData(b_data, b_data.size()); //原始写!!
out.device()->seek(0);
out<<(quint32) (b_data.size() + sizeof(quint32)*2+sizeof(quint8));
}
pSender->Send(dwConnID, (BYTE *)block.data(), block.size());
}
void hpsocket_s::lus_init_conf(QString path)
{
logger()->info("读取配置文件");
if(path.isEmpty())
path ="./lus_server_conf.xml" ;
#ifdef Q_OS_WIN32
xml_conf->read_conf(path);
logger()->info("windows system");
#endif
#ifdef Q_OS_LINUX
xml_conf->read_conf(path);
logger()->info("linux system");
#endif
logger()->info("max_down " +xml_conf->server_conf->max_down);
hp_msg_server->Start("0.0.0.0", 9527);
logger()->info("strat msg server\n");
}
hpsocket_s::hpsocket_s()
{
logger()->info("start hp socket");
downing_count = 0;
loadSize = 4*1024;
qRegisterMetaType<CONNID>("CONNID");
qRegisterMetaType<uint8_t>("uint8_t");
/*文件传输socket初始化*/
tcp_file_server = new QTcpServer;
if(!tcp_file_server->listen(QHostAddress::Any,9528))
{ //**本地主机的6666端口,如果出错就输出错误信息,并关闭
logger()->error("file connect listen error: " + tcp_file_server->errorString());
}
connect(tcp_file_server,SIGNAL(newConnection()),this,SLOT(send_init_file()));
/*下载列表扫描定时器*/
timer_down = new QTimer;
connect( timer_down, SIGNAL(timeout() ), this, SLOT( auto_scanf_down() ) );
timer_down->start(5000); //TODO cfg
logger()->info("start down scan");
hp_listener = new CListenerImpl;
hp_listener->init_listener();
hp_msg_server = HP_Create_TcpPullServer(hp_listener);
hp_file_server = HP_Create_TcpPullServer(hp_listener);
hp_listener->hp_msg_server = hp_msg_server;
hp_listener->hp_file_server = hp_file_server;
connect(hp_listener, SIGNAL(lus_msg(QByteArray,CONNID,uint8_t)), this, SLOT(lus_do_cmd(QByteArray,CONNID,uint8_t)));
}
void hpsocket_s::sendMessage(CONNID dwConnID, QByteArray b_data ,quint8 encrypt_c)
{
hp_listener->lus_send(ITcpPullServer::ToS(hp_msg_server), dwConnID, b_data, encrypt_c);
}
lus_client_listp hpsocket_s::lus_get_down_list(void)
{
return &file_clinet_list;
}
lus_client_listp hpsocket_s::lus_get_offline_client_list(void)
{
return &hp_listener->offline_list;
}
lus_client_listp hpsocket_s::lus_get_client_list(void)
{
return &hp_listener->msg_clinet_list;
}
lus_client_st* hpsocket_s:: id_2_client(CONNID id)
{
if(hp_listener->client_map.contains(id)){
return hp_listener->client_map.find(id).value();
}
return nullptr;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化