diff --git a/.gitignore b/.gitignore index c69e786..d20d992 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ ui_*.h /server/VarifyServer/.idea /server/ChatServer/*.log /client/llfcchat/llfcchat.pro.user.92bdd7d +client/llfcchat/release/ +bin/static/* + diff --git a/README.md b/README.md index c086174..e922157 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,44 @@ C++ 聊天项目实战案例,涵盖grpc,并发线程,网络编程,qt开 [day29-好友认证和聊天](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day29-%E5%A5%BD%E5%8F%8B%E8%AE%A4%E8%AF%81%E5%92%8C%E8%81%8A%E5%A4%A9%E9%80%9A%E4%BF%A1.md) +[day30-项目难点和面试技巧](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day30-%E9%A1%B9%E7%9B%AE%E9%9A%BE%E7%82%B9%E5%92%8C%E9%9D%A2%E8%AF%95%E6%8A%80%E5%B7%A7.md) + +[day31-好友认证和聊天](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day31-%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93.md) + +**第二季** + +代码需要切换到Season_2分支,可查看第二季逻辑 + +[day32-分布式锁设计思路](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day32%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF.md) + +[day33-单服务器踢人逻辑](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day33%E5%8D%95%E6%9C%8D%E7%A8%8B%E8%B8%A2%E4%BA%BA%E9%80%BB%E8%BE%91.md) + +[day34-多服务器踢人逻辑](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day34%E5%A4%9A%E6%9C%8D%E7%A8%8B%E8%B8%A2%E4%BA%BA%E9%80%BB%E8%BE%91.md) + +[day35-心跳逻辑](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day35%E5%BF%83%E8%B7%B3%E9%80%BB%E8%BE%91.md) + +[day36-实现头像编辑框](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day36-%E5%AE%9E%E7%8E%B0%E5%A4%B4%E5%83%8F%E7%BC%96%E8%BE%91%E6%A1%86.md) + +[day37-聊天信息存储方案](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day37-%E8%81%8A%E5%A4%A9%E4%BF%A1%E6%81%AF%E5%AD%98%E5%82%A8%E6%96%B9%E6%A1%88.md) + +[day38-断点续传](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day38-%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0.md) + +[day39-多媒体信息传输](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day39-%E5%A4%9A%E5%AA%92%E4%BD%93%E4%BF%A1%E6%81%AF%E4%BC%A0%E8%BE%93.md) + +[day40-聊天图片资源续传和进度显示](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day40-%E8%81%8A%E5%A4%A9%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E7%BB%AD%E4%BC%A0%E5%92%8C%E8%BF%9B%E5%BA%A6%E6%98%BE%E7%A4%BA.md) + +[day41-分布式事务死锁解决方案](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day41-%E5%88%86%E5%B8%83%E5%BC%8F%E6%AD%BB%E9%94%81%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88.md) + +[day42-Qt粘包引发的血案](https://gitee.com/secondtonone1/llfcchat/blob/master/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day42-Qt%E7%B2%98%E5%8C%85%E5%BC%95%E5%8F%91%E7%9A%84%E8%A1%80%E6%A1%88.md) + +[day43-Grpc通知客户端聊天资源下载](https://gitee.com/secondtonone1/llfcchat/blob/Season_2/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day41-%E9%80%9A%E7%9F%A5%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%BC%82%E6%AD%A5%E4%B8%8B%E8%BD%BD%E8%81%8A%E5%A4%A9%E5%9B%BE%E7%89%87.md) + +[day43-用户登录加载聊天资源](https://gitee.com/secondtonone1/llfcchat/blob/Season_2/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day42-%E7%94%A8%E6%88%B7%E5%8A%A0%E8%BD%BD%E8%81%8A%E5%A4%A9%E8%B5%84%E6%BA%90.md) + +[day44-webrtc的coturn服务器搭建](https://gitee.com/secondtonone1/llfcchat/blob/Season_2/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day43-webrtc%E7%9A%84coturn%E6%9C%8D%E5%8A%A1%E6%90%AD%E5%BB%BA.md) + +[day45-信令服务器实现视频通信](https://gitee.com/secondtonone1/llfcchat/blob/Season_2/%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3/day44-webrtc%E4%BF%A1%E4%BB%A4%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0.md) + #### 赞赏 您的赞赏是我更新的动力,谢谢支持! diff --git a/client/llfcchat/ChatItemBase.cpp b/client/llfcchat/ChatItemBase.cpp index 20fcf3a..5945276 100644 --- a/client/llfcchat/ChatItemBase.cpp +++ b/client/llfcchat/ChatItemBase.cpp @@ -88,3 +88,12 @@ void ChatItemBase::setStatus(int status) return ; } } + + +QLabel* ChatItemBase::getIconLabel() { + return m_pIconLabel; +} + +QWidget* ChatItemBase::getBubble() { + return m_pBubble; +} \ No newline at end of file diff --git a/client/llfcchat/ChatItemBase.h b/client/llfcchat/ChatItemBase.h index b912151..6abd3e3 100644 --- a/client/llfcchat/ChatItemBase.h +++ b/client/llfcchat/ChatItemBase.h @@ -16,6 +16,8 @@ class ChatItemBase : public QWidget void setUserIcon(const QPixmap &icon); void setWidget(QWidget *w); void setStatus(int status); + QLabel* getIconLabel(); + QWidget* getBubble(); private: ChatRole m_role; QLabel *m_pNameLabel; diff --git a/client/llfcchat/ClickableLabel.cpp b/client/llfcchat/ClickableLabel.cpp new file mode 100644 index 0000000..d12e6f5 --- /dev/null +++ b/client/llfcchat/ClickableLabel.cpp @@ -0,0 +1,74 @@ +#include "ClickableLabel.h" +#include +#include +// ClickableLabel.cpp +ClickableLabel::ClickableLabel(QWidget* parent) + : QLabel(parent) + , m_showOverlay(false) + , m_hovered(false) +{ + setCursor(Qt::PointingHandCursor); + setMouseTracking(true); +} + +void ClickableLabel::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) { + emit clicked(); + } + QLabel::mousePressEvent(event); +} + +void ClickableLabel::enterEvent(QEvent* event) +{ + m_hovered = true; + update(); + QLabel::enterEvent(event); +} + +void ClickableLabel::leaveEvent(QEvent* event) +{ + m_hovered = false; + update(); + QLabel::leaveEvent(event); +} + +void ClickableLabel::paintEvent(QPaintEvent* event) +{ + QLabel::paintEvent(event); + + if (m_showOverlay && !m_overlayIcon.isNull()) { + QPainter painter(this); + + // ư͸ + if (m_hovered) { + painter.fillRect(rect(), QColor(0, 0, 0, 100)); + } + else { + painter.fillRect(rect(), QColor(0, 0, 0, 60)); + } + + // ͼ + int iconSize = qMin(width(), height()) / 3; // ͼСΪͼƬ1/3 + QRect iconRect( + (width() - iconSize) / 2, + (height() - iconSize) / 2, + iconSize, + iconSize + ); + + m_overlayIcon.paint(&painter, iconRect); + } +} + +void ClickableLabel::setIconOverlay(const QIcon& icon) +{ + m_overlayIcon = icon; + update(); +} + +void ClickableLabel::showIconOverlay(bool show) +{ + m_showOverlay = show; + update(); +} \ No newline at end of file diff --git a/client/llfcchat/ClickableLabel.h b/client/llfcchat/ClickableLabel.h new file mode 100644 index 0000000..97eb440 --- /dev/null +++ b/client/llfcchat/ClickableLabel.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +class ClickableLabel : + public QLabel +{ + Q_OBJECT +public: + explicit ClickableLabel(QWidget* parent = nullptr); + void setIconOverlay(const QIcon& icon); //ͼ + void showIconOverlay(bool show); //ʾ/ͼ +protected: + void mousePressEvent(QMouseEvent* event) override; + void enterEvent(QEvent* event) override; + void leaveEvent(QEvent* event) override; + void paintEvent(QPaintEvent* event) override; + +signals: + void clicked(); + +private: + QIcon m_overlayIcon; + bool m_showOverlay; + bool m_hovered; +}; + diff --git a/client/llfcchat/MessageTextEdit.cpp b/client/llfcchat/MessageTextEdit.cpp index 9fb06ae..0148705 100644 --- a/client/llfcchat/MessageTextEdit.cpp +++ b/client/llfcchat/MessageTextEdit.cpp @@ -1,7 +1,7 @@ #include "MessageTextEdit.h" #include #include - +#include "global.h" MessageTextEdit::MessageTextEdit(QWidget *parent) : QTextEdit(parent) @@ -19,15 +19,14 @@ MessageTextEdit::~MessageTextEdit() } -QVector MessageTextEdit::getMsgList() +QVector> MessageTextEdit::getMsgList() { - mGetMsgList.clear(); - + _total_msg_list.clear(); QString doc = this->document()->toPlainText(); QString text="";//存储文本信息 int indexUrl = 0; //这个是存储的富文本信息,包括图片的url以及文件的url - int count = mMsgList.size(); + int count = _img_or_file_list.size(); for(int index=0; index MessageTextEdit::getMsgList() { if(!text.isEmpty()) { - QPixmap pix; - insertMsgList(mGetMsgList,"text",text,pix); + insertMsgList(_total_msg_list, MsgType::TEXT_MSG, text, QPixmap(),"",0,""); text.clear(); } while(indexUrldocument()->toHtml().contains(msg.content,Qt::CaseSensitive)) + std::shared_ptr msg = _img_or_file_list[indexUrl]; + if(this->document()->toHtml().contains(msg->_text_or_url,Qt::CaseSensitive)) { indexUrl++; - mGetMsgList.append(msg); + _total_msg_list.append(msg); break; } indexUrl++; @@ -60,13 +58,12 @@ QVector MessageTextEdit::getMsgList() } if(!text.isEmpty()) { - QPixmap pix; - insertMsgList(mGetMsgList,"text",text,pix); + insertMsgList(_total_msg_list, MsgType::TEXT_MSG, text, QPixmap(), "", 0, ""); text.clear(); } - mMsgList.clear(); + _img_or_file_list.clear(); this->clear(); - return mGetMsgList; + return _total_msg_list; } void MessageTextEdit::dragEnterEvent(QDragEnterEvent *event) @@ -102,12 +99,40 @@ void MessageTextEdit::insertFileFromUrl(const QStringList &urls) if(isImage(url)) insertImages(url); else - insertTextFile(url); + insertFiles(url); } } void MessageTextEdit::insertImages(const QString &url) { + //文件信息 + QFileInfo fileInfo(url); + if (fileInfo.isDir()) + { + QMessageBox::information(this, "提示", "只允许拖拽单个文件!"); + return; + } + + auto total_size = fileInfo.size(); + + qint64 max_size = qint64(2) * 1024 * 1024 * 1024; + + if (total_size > max_size) + { + QMessageBox::information(this, "提示", "发送的文件大小不能大于2G"); + return; + } + + // 计算文件MD5 + QString fileMd5 = calculateFileHash(url); + + if (fileMd5.isEmpty()) + { + QMessageBox::warning(this, "错误", "无法计算文件MD5"); + return; + } + + QImage image(url); //按比例缩放图片 if(image.width()>120||image.height()>80) @@ -123,31 +148,51 @@ void MessageTextEdit::insertImages(const QString &url) // QTextDocument *document = this->document(); // document->addResource(QTextDocument::ImageResource, QUrl(url), QVariant(image)); cursor.insertImage(image,url); - - insertMsgList(mMsgList,"image",url,QPixmap::fromImage(image)); + QString origin_name = fileInfo.fileName(); + QString unique_name = generateUniqueFileName(origin_name); + insertMsgList(_img_or_file_list, MsgType::IMG_MSG, url, QPixmap::fromImage(image), unique_name, + total_size, fileMd5); } -void MessageTextEdit::insertTextFile(const QString &url) -{ +void MessageTextEdit::insertFiles(const QString& url) { QFileInfo fileInfo(url); - if(fileInfo.isDir()) + if (fileInfo.isDir()) { - QMessageBox::information(this,"提示","只允许拖拽单个文件!"); + QMessageBox::information(this, "提示", "只允许拖拽单个文件!"); return; } - if(fileInfo.size()>100*1024*1024) + auto total_size = fileInfo.size(); + + qint64 max_size = qint64(2) * 1024 * 1024 * 1024; + + if (total_size > max_size) + { + QMessageBox::information(this, "提示", "发送的文件大小不能大于100M"); + return; + } + + // 计算文件MD5 + QString fileMd5 = calculateFileHash(url); + + if (fileMd5.isEmpty()) { - QMessageBox::information(this,"提示","发送的文件大小不能大于100M"); + QMessageBox::warning(this, "错误", "无法计算文件MD5"); return; } QPixmap pix = getFileIconPixmap(url); QTextCursor cursor = this->textCursor(); - cursor.insertImage(pix.toImage(),url); - insertMsgList(mMsgList,"file",url,pix); + cursor.insertImage(pix.toImage(), url); + + QString origin_name = fileInfo.fileName(); + QString unique_name = generateUniqueFileName(origin_name); + insertMsgList(_img_or_file_list, MsgType::FILE_MSG, url, pix, unique_name, + total_size, fileMd5); } + + bool MessageTextEdit::canInsertFromMimeData(const QMimeData *source) const { return QTextEdit::canInsertFromMimeData(source); @@ -165,7 +210,7 @@ void MessageTextEdit::insertFromMimeData(const QMimeData *source) if(isImage(url)) insertImages(url); else - insertTextFile(url); + insertFiles(url); } } @@ -181,15 +226,17 @@ bool MessageTextEdit::isImage(QString url) return false; } -void MessageTextEdit::insertMsgList(QVector &list, QString flag, QString text, QPixmap pix) -{ - MsgInfo msg; - msg.msgFlag=flag; - msg.content = text; - msg.pixmap = pix; - list.append(msg); +void MessageTextEdit::insertMsgList(QVector> &list, MsgType msgtype, + QString text_or_url, QPixmap preview_pix, + QString unique_name, uint64_t total_size, QString md5) { + + auto msg_info = std::make_shared(msgtype, text_or_url, preview_pix, unique_name, total_size, md5); + list.append(msg_info); + } + + QStringList MessageTextEdit::getUrl(QString text) { QStringList urls; diff --git a/client/llfcchat/MessageTextEdit.h b/client/llfcchat/MessageTextEdit.h index 86bca36..5ef4f70 100644 --- a/client/llfcchat/MessageTextEdit.h +++ b/client/llfcchat/MessageTextEdit.h @@ -23,7 +23,7 @@ class MessageTextEdit : public QTextEdit ~MessageTextEdit(); - QVector getMsgList(); + QVector> getMsgList(); void insertFileFromUrl(const QStringList &urls); signals: @@ -36,14 +36,16 @@ class MessageTextEdit : public QTextEdit private: void insertImages(const QString &url); - void insertTextFile(const QString &url); + void insertFiles(const QString &url); bool canInsertFromMimeData(const QMimeData *source) const; void insertFromMimeData(const QMimeData *source); private: bool isImage(QString url);//判断文件是否为图片 - void insertMsgList(QVector &list,QString flag, QString text, QPixmap pix); - + void insertMsgList(QVector>& list, MsgType msgtype, + QString text_or_url, QPixmap preview_pix, + QString unique_name, uint64_t total_size, QString md5); + QStringList getUrl(QString text); QPixmap getFileIconPixmap(const QString &url);//获取文件图标及大小信息,并转化成图片 QString getFileSize(qint64 size);//获取文件大小 @@ -52,8 +54,8 @@ private slots: void textEditChanged(); private: - QVector mMsgList; - QVector mGetMsgList; + QVector> _img_or_file_list; + QVector> _total_msg_list; }; #endif // MESSAGETEXTEDIT_H diff --git a/client/llfcchat/PictureBubble.cpp b/client/llfcchat/PictureBubble.cpp index 5d4bf35..77401f2 100644 --- a/client/llfcchat/PictureBubble.cpp +++ b/client/llfcchat/PictureBubble.cpp @@ -1,21 +1,242 @@ #include "PictureBubble.h" #include - +#include #define PIC_MAX_WIDTH 160 #define PIC_MAX_HEIGHT 90 -PictureBubble::PictureBubble(const QPixmap &picture, ChatRole role, QWidget *parent) - :BubbleFrame(role, parent) +PictureBubble::PictureBubble(const QPixmap &picture, ChatRole role, int total, QWidget *parent) + :BubbleFrame(role, parent), m_state(TransferState::None), m_total_size(total) { - QLabel *lb = new QLabel(); - lb->setScaledContents(true); - QPixmap pix = picture.scaled(QSize(PIC_MAX_WIDTH, PIC_MAX_HEIGHT), Qt::KeepAspectRatio); - lb->setPixmap(pix); - this->setWidget(lb); + // 加载图标(使用Qt内置图标或自定义图标) + m_pauseIcon = style()->standardIcon(QStyle::SP_MediaPause); + m_playIcon = style()->standardIcon(QStyle::SP_MediaPlay); + m_downloadIcon = style()->standardIcon(QStyle::SP_ArrowDown); + + // 创建容器 + QWidget* container = new QWidget(); + m_vLayout = new QVBoxLayout(container); + m_vLayout->setContentsMargins(0, 0, 0, 0); + m_vLayout->setSpacing(5); + + + // 创建可点击的图片标签 + m_picLabel = new ClickableLabel(); + m_picLabel->setScaledContents(true); + QPixmap pix = picture.scaled(QSize(PIC_MAX_WIDTH, PIC_MAX_HEIGHT), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + m_pixmapSize = pix.size(); + m_picLabel->setPixmap(pix); + m_picLabel->setFixedSize(pix.size()); + + connect(m_picLabel, &ClickableLabel::clicked, + this, &PictureBubble::onPictureClicked); + + // 创建进度条 + m_progressBar = new QProgressBar(); + m_progressBar->setFixedWidth(pix.width()); + m_progressBar->setFixedHeight(10); + m_progressBar->setRange(0, 100); + m_progressBar->setValue(0); + m_progressBar->setTextVisible(true); + setState(TransferState::None); + // 样式美化 + m_progressBar->setStyleSheet( + "QProgressBar {" + " border: 1px solid #ccc;" + " border-radius: 3px;" + " text-align: center;" + " background-color: #f0f0f0;" + " font-size: 10px;" + "}" + "QProgressBar::chunk {" + " background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, " + " stop:0 #4CAF50, stop:1 #45a049);" + " border-radius: 2px;" + "}" + ); + + m_vLayout->addWidget(m_picLabel); + m_vLayout->addWidget(m_progressBar); + this->setWidget(container); + adjustSize(); +} + +void PictureBubble::adjustSize() +{ int left_margin = this->layout()->contentsMargins().left(); int right_margin = this->layout()->contentsMargins().right(); int v_margin = this->layout()->contentsMargins().bottom(); - setFixedSize(pix.width()+left_margin + right_margin, pix.height() + v_margin *2); + + int width = m_pixmapSize.width() + left_margin + right_margin; + int height = m_pixmapSize.height() + v_margin * 2; + + if (m_progressBar->isHidden() == false) { + height += m_progressBar->height() + m_vLayout->spacing(); + } + + setFixedSize(width, height); +} + +void PictureBubble::setProgress(int value, int total_value) +{ + if (m_total_size != total_value) { + m_total_size = total_value; + } + float percent = (value / (m_total_size*1.0))*100; + m_progressBar->setValue(percent); + if (percent >= 100) { + setState(TransferState::Completed); + } +} + +void PictureBubble::showProgress(bool show) +{ + if (show) { + m_progressBar->show(); + } + else { + m_progressBar->hide(); + } + + adjustSize(); +} + +void PictureBubble::resumeState() { + if (_msg_info->_transfer_type == TransferType::Download) { + _msg_info->_transfer_state = TransferState::Downloading; + m_state = TransferState::Downloading; + updateIconOverlay(); + return; + } + + if (_msg_info->_transfer_type == TransferType::Upload) { + _msg_info->_transfer_state = TransferState::Uploading; + m_state = TransferState::Uploading; + updateIconOverlay(); + return; + } +} + +void PictureBubble::setState(TransferState state) +{ + m_state = state; + if (_msg_info) { + _msg_info->_transfer_state = state; + } + + // 根据状态显示/隐藏进度条 + switch (state) { + case TransferState::Downloading: + case TransferState::Uploading: + case TransferState::Paused: + showProgress(true); + break; + case TransferState::Completed: + // 完成后延迟隐藏进度条 + QTimer::singleShot(1000, this, [this]() { + showProgress(false); + }); + break; + case TransferState::None: + case TransferState::Failed: + showProgress(false); + break; + } + + updateIconOverlay(); +} + +void PictureBubble::setMsgInfo(std::shared_ptr msg) +{ + _msg_info = msg; + setProgress(_msg_info->_current_size, _msg_info->_total_size); + if (_msg_info->_transfer_state == TransferState::Uploading) { + setState(TransferState::Uploading); + return; + } + + if (_msg_info->_transfer_state == TransferState::Downloading) { + setState(TransferState::Downloading); + return; + } + //解决切换bug + if (_msg_info->_transfer_state == TransferState::Completed) { + setState(TransferState::Completed); + return; + } + + if (_msg_info->_transfer_state == TransferState::Paused) { + setState(TransferState::Paused); + return; + } +} + +void PictureBubble::setDownloadFinish(std::shared_ptr msg,QString file_path) { + m_progressBar->setValue(100); + setState(TransferState::Completed); + auto picture = QPixmap(file_path); + QPixmap pix = picture.scaled(QSize(PIC_MAX_WIDTH, PIC_MAX_HEIGHT), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + m_pixmapSize = pix.size(); + m_picLabel->setPixmap(pix); + m_picLabel->setFixedSize(pix.size()); + adjustSize(); + updateIconOverlay(); +} + +void PictureBubble::onPictureClicked() +{ + if (_msg_info == nullptr) { + return; + } + switch (m_state) { + case TransferState::Downloading: + case TransferState::Uploading: + // 暂停 + setState(TransferState::Paused); + emit pauseRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Paused: + // 继续 + resumeState(); // + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Failed: + // 重试 + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + default: + // 其他状态可以实现查看大图等功能 + break; + } +} + +void PictureBubble::updateIconOverlay() +{ + switch (m_state) { + case TransferState::Downloading: + case TransferState::Uploading: + m_picLabel->setIconOverlay(m_pauseIcon); + m_picLabel->showIconOverlay(true); + break; + + case TransferState::Paused: + m_picLabel->setIconOverlay(m_playIcon); + m_picLabel->showIconOverlay(true); + break; + + case TransferState::Failed: + m_picLabel->setIconOverlay(m_downloadIcon); // 或重试图标 + m_picLabel->showIconOverlay(true); + break; + + default: + m_picLabel->showIconOverlay(false); + break; + } } diff --git a/client/llfcchat/PictureBubble.h b/client/llfcchat/PictureBubble.h index 960afd5..9d6ffdb 100644 --- a/client/llfcchat/PictureBubble.h +++ b/client/llfcchat/PictureBubble.h @@ -4,11 +4,49 @@ #include "BubbleFrame.h" #include #include +#include "ClickableLabel.h" +#include +#include "global.h" class PictureBubble : public BubbleFrame { Q_OBJECT public: - PictureBubble(const QPixmap &picture, ChatRole role, QWidget *parent = nullptr); + + + PictureBubble(const QPixmap& picture, ChatRole role,int total, QWidget* parent = nullptr); + + void setProgress(int value, int total_value); + void showProgress(bool show); + void setState(TransferState state); + void resumeState(); + void setMsgInfo(std::shared_ptr msg); + TransferState state() const { return m_state; } + void setDownloadFinish(std::shared_ptr msg, QString file_path); + +signals: + void pauseRequested(QString unique_name, TransferType transfer_type); // 请求暂停 + void resumeRequested(QString unique_name, TransferType transfer_type); // 请求继续 + void cancelRequested(QString unique_name, TransferType transfer_type); // 请求取消 + +private slots: + void onPictureClicked(); + +private: + void updateIconOverlay(); + void adjustSize(); + +private: + ClickableLabel* m_picLabel; + QProgressBar* m_progressBar; + TransferState m_state; + + QIcon m_pauseIcon; + QIcon m_playIcon; + QIcon m_downloadIcon; + QSize m_pixmapSize; + QVBoxLayout* m_vLayout; + int m_total_size; + std::shared_ptr _msg_info; }; #endif // PICTUREBUBBLE_H diff --git a/client/llfcchat/applyfriend.h b/client/llfcchat/applyfriend.h index 79010da..2712220 100644 --- a/client/llfcchat/applyfriend.h +++ b/client/llfcchat/applyfriend.h @@ -1,4 +1,4 @@ -#ifndef APPLYFRIEND_H +#ifndef APPLYFRIEND_H #define APPLYFRIEND_H #include @@ -23,11 +23,11 @@ class ApplyFriend : public QDialog private: void resetLabels(); Ui::ApplyFriend *ui; - //Ѿõıǩ + //已经创建好的标签 QMap _add_labels; std::vector _add_label_keys; QPoint _label_point; - //ʾºѵıǩ + //用来在输入框显示添加新好友的标签 QMap _friend_labels; std::vector _friend_label_keys; void addLabel(QString name); @@ -35,23 +35,23 @@ class ApplyFriend : public QDialog QPoint _tip_cur_point; std::shared_ptr _si; public slots: - //ʾlabelǩ + //显示更多label标签 void ShowMoreLabel(); - //label»سǩչʾ + //输入label按下回车触发将标签加入展示栏 void SlotLabelEnter(); - //رգƳչʾѱǩ + //点击关闭,移除展示栏好友便签 void SlotRemoveFriendLabel(QString); - //ͨtipʵӺͼٺѱǩ + //通过点击tip实现增加和减少好友便签 void SlotChangeFriendLabelByTip(QString, ClickLbState); - //ı仯ʾͬʾ + //输入框文本变化显示不同提示 void SlotLabelTextChange(const QString& text); - // + //输入框输入完成 void SlotLabelEditFinished(); - //ǩʾʾ򣬵ʾݺӺѱǩ + //输入标签显示提示框,点击提示框内容后添加好友便签 void SlotAddFirendLabelByClickTip(QString text); - //ȷϻص + //处理确认回调 void SlotApplySure(); - //ȡص + //处理取消回调 void SlotApplyCancel(); }; diff --git a/client/llfcchat/chatdialog.cpp b/client/llfcchat/chatdialog.cpp index 582951a..1822047 100644 --- a/client/llfcchat/chatdialog.cpp +++ b/client/llfcchat/chatdialog.cpp @@ -19,7 +19,8 @@ #include "tcpmgr.h" #include "usermgr.h" #include - +#include +#include "FileTcpMgr.h" ChatDialog::ChatDialog(QWidget* parent) : QDialog(parent), @@ -68,13 +69,10 @@ ChatDialog::ChatDialog(QWidget* parent) : //连接加载信号和槽 connect(ui->chat_user_list, &ChatUserList::sig_loading_chat_user, this, &ChatDialog::slot_loading_chat_user); - //模拟加载自己头像 - QString head_icon = UserMgr::GetInstance()->GetIcon(); - QPixmap pixmap(head_icon); // 加载图片 - QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 - ui->side_head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 - ui->side_head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 - + //刷新头像信号和槽函数 + connect(ui->user_info_page, &UserInfoPage::sig_reset_head, this, &ChatDialog::slot_reset_head); + + slot_reset_head(); ui->side_chat_lb->setProperty("state", "normal"); ui->side_chat_lb->SetState("normal", "hover", "pressed", "selected_normal", "selected_hover", "selected_pressed"); @@ -152,6 +150,9 @@ ChatDialog::ChatDialog(QWidget* parent) : connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_text_chat_msg, this, &ChatDialog::slot_text_chat_msg); + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_img_chat_msg, + this, &ChatDialog::slot_img_chat_msg); + _timer = new QTimer(this); connect(_timer, &QTimer::timeout, this, [this]() { auto user_info = UserMgr::GetInstance()->GetUserInfo(); @@ -176,6 +177,21 @@ ChatDialog::ChatDialog(QWidget* parent) : this, &ChatDialog::slot_load_chat_msg); connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_chat_msg_rsp, this, &ChatDialog::slot_add_chat_msg); + + //连接tcp返回的图片聊天信息回复 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_chat_img_rsp, this, &ChatDialog::slot_add_img_msg); + //重置label icon + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_reset_label_icon, this, &ChatDialog::slot_reset_icon); + //接收tcp返回的上传进度信息 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_update_upload_progress, + this, &ChatDialog::slot_update_upload_progress); + //接收tcp返回的下载进度信息 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_update_download_progress, + this, &ChatDialog::slot_update_download_progress); + + //接收tcp返回的下载完成信息 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_download_finish, + this, &ChatDialog::slot_download_finish); } ChatDialog::~ChatDialog() @@ -282,6 +298,18 @@ void ChatDialog::slot_text_chat_msg(std::vector> m } +void ChatDialog::slot_img_chat_msg(std::shared_ptr imgchat) { + //更新数据 + auto thread_id = imgchat->GetThreadId(); + auto thread_data = UserMgr::GetInstance()->GetChatThreadByThreadId(thread_id); + thread_data->AddMsg(imgchat); + if (_cur_chat_thread_id != thread_id) { + return; + } + + ui->chat_page->AppendOtherMsg(imgchat); +} + bool ChatDialog::eventFilter(QObject* watched, QEvent* event) { @@ -406,7 +434,8 @@ void ChatDialog::slot_create_private_chat(int uid, int other_id, int thread_id) return; } -void ChatDialog::slot_load_chat_msg(int thread_id, int msg_id, bool load_more, std::vector> msglists) +void ChatDialog::slot_load_chat_msg(int thread_id, int msg_id, bool load_more, + std::vector> msglists) { _cur_load_chat->SetLastMsgId(msg_id); //加载聊天信息 @@ -470,9 +499,29 @@ void ChatDialog::slot_add_chat_msg(int thread_id, std::vectorchat_page->UpdateChatStatus(msg->GetUniqueId(),msg->GetStatus()); + ui->chat_page->UpdateChatStatus(msg); + } +} + + +void ChatDialog::slot_add_img_msg(int thread_id, std::shared_ptr img_msg) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(thread_id); + if (chat_data == nullptr) { + return; + } + + chat_data->MoveMsg(img_msg); + + if (_cur_chat_thread_id != thread_id) { + return; } - + + //更新聊天界面信息 + ui->chat_page->UpdateImgChatStatus(img_msg); +} + +void ChatDialog::slot_reset_icon(QString path) { + UserMgr::GetInstance()->ResetLabelIcon(path); } void ChatDialog::showLoadingDlg(bool show) @@ -1025,3 +1074,134 @@ void ChatDialog::slot_jump_chat_item_from_infopage(std::shared_ptr use emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_CREATE_PRIVATE_CHAT_REQ, jsonData); } + +void ChatDialog::slot_update_upload_progress(std::shared_ptr msg_info) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(msg_info->_thread_id); + if (chat_data == nullptr) { + return; + } + + //更新消息,其实不用更新,都是共享msg_info的一块内存,这里为了安全还是再次更新下 + + chat_data->UpdateProgress(msg_info); + + if (_cur_chat_thread_id != msg_info->_thread_id) { + return; + } + + + //更新聊天界面信息 + ui->chat_page->UpdateFileProgress(msg_info); +} + + +void ChatDialog::slot_update_download_progress(std::shared_ptr msg_info) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(msg_info->_thread_id); + if (chat_data == nullptr) { + return; + } + + //更新消息,其实不用更新,都是共享msg_info的一块内存,这里为了安全还是再次更新下 + + chat_data->UpdateProgress(msg_info); + + if (_cur_chat_thread_id != msg_info->_thread_id) { + return; + } + + + //更新聊天界面信息 + ui->chat_page->UpdateFileProgress(msg_info); +} +void ChatDialog::slot_download_finish(std::shared_ptr msg_info, QString file_path) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(msg_info->_thread_id); + if (chat_data == nullptr) { + return; + } + + //更新消息,其实不用更新,都是共享msg_info的一块内存,这里为了安全还是再次更新下 + + chat_data->UpdateProgress(msg_info); + + if (_cur_chat_thread_id != msg_info->_thread_id) { + return; + } + + + //更新聊天界面信息 + ui->chat_page->DownloadFileFinished(msg_info, file_path); +} + +void ChatDialog::slot_reset_head() +{ + //模拟加载自己头像 + QString head_icon = UserMgr::GetInstance()->GetIcon(); + //使用正则表达式检查是否使用默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(head_icon); + if (match.hasMatch()) { + // 如果是默认头像(:/res/head_X.jpg 格式) + QPixmap pixmap(head_icon); // 加载默认头像图片 + QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->side_head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->side_head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(uid) + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + auto file_name = QFileInfo(head_icon).fileName(); + QString avatarPath = avatarsDir.filePath(file_name); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->side_head_lb->setPixmap(scaledPixmap); + ui->side_head_lb->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + LoadHeadIcon(avatarPath, ui->side_head_lb, file_name,"self_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + QString avatarPath = avatarsDir.filePath(QFileInfo(head_icon).fileName()); + avatarsDir.mkpath("."); + LoadHeadIcon(avatarPath, ui->side_head_lb, head_icon,"self_icon"); + } + } +} + + +void ChatDialog::LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name,QString req_type) { + UserMgr::GetInstance()->AddLabelToReset(avatarPath, icon_label); + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(icon_label->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + icon_label->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + icon_label->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + } + else { + //发送请求获取资源 + auto download_info = std::make_shared(); + download_info->_name = file_name; + download_info->_current_size = 0; + download_info->_seq = 1; + download_info->_total_size = 0; + download_info->_client_path = avatarPath; + //添加文件到管理者 + UserMgr::GetInstance()->AddDownloadFile(file_name, download_info); + //发送消息 + FileTcpMgr::GetInstance()->SendDownloadInfo(download_info, req_type); + } +} \ No newline at end of file diff --git a/client/llfcchat/chatdialog.h b/client/llfcchat/chatdialog.h index 6085789..3395d02 100644 --- a/client/llfcchat/chatdialog.h +++ b/client/llfcchat/chatdialog.h @@ -1,4 +1,4 @@ -#ifndef CHATDIALOG_H +#ifndef CHATDIALOG_H #define CHATDIALOG_H #include @@ -30,7 +30,7 @@ class ChatDialog : public QDialog void handleGlobalMousePress(QMouseEvent *event) ; void CloseFindDlg(); void UpdateChatMsg(std::vector> msgdata); - + void LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type); private: void showLoadingDlg(bool show = true); void AddLBGroup(StateWidget* lb); @@ -48,7 +48,7 @@ class ChatDialog : public QDialog QWidget* _last_widget; //todo... //QMap _chat_items_added; - //chat_thred_idͶӦitemӳϵ + //chat_thred_id和对应的item的映射关系。 QMap _chat_thread_items; int _cur_chat_thread_id; QTimer * _timer; @@ -73,17 +73,23 @@ public slots: void slot_jump_chat_item_from_infopage(std::shared_ptr ui); void slot_item_clicked(QListWidgetItem *item); void slot_text_chat_msg(std::vector> msglists); + void slot_img_chat_msg(std::shared_ptr imgchat); void slot_load_chat_thread(bool load_more, int last_thread_id, std::vector> chat_threads); void slot_create_private_chat(int uid, int other_id, int thread_id); void slot_load_chat_msg(int thread_id, int msg_id, bool load_more, - std::vector> msglists); + std::vector> msglists); void slot_add_chat_msg(int thread_id, std::vector> msglists); + void slot_add_img_msg(int thread_id, std::shared_ptr img_msg); + void slot_reset_icon(QString path); + void slot_update_upload_progress(std::shared_ptr msg_info); + void slot_update_download_progress(std::shared_ptr msg_info); + void slot_download_finish(std::shared_ptr msg_info, QString file_path); private slots: - + void slot_reset_head(); }; diff --git a/client/llfcchat/chatpage.cpp b/client/llfcchat/chatpage.cpp index ced1e29..0f7eed1 100644 --- a/client/llfcchat/chatpage.cpp +++ b/client/llfcchat/chatpage.cpp @@ -11,6 +11,9 @@ #include #include "tcpmgr.h" #include +#include +#include "filetcpmgr.h" +#include ChatPage::ChatPage(QWidget *parent) : QWidget(parent), @@ -50,16 +53,17 @@ void ChatPage::SetChatData(std::shared_ptr chat_data) { ui->title_lb->setText(friend_info->_name); ui->chat_data_list->removeAllItem(); _unrsp_item_map.clear(); + _base_item_map.clear(); for(auto & msg : chat_data->GetMsgMapRef()){ AppendChatMsg(msg); } for (auto& msg : chat_data->GetMsgUnRspRef()) { - AppendChatMsg(msg); + AppendChatMsg(msg,false); } } -void ChatPage::AppendChatMsg(std::shared_ptr msg) +void ChatPage::AppendChatMsg(std::shared_ptr msg, bool rsp) { auto self_info = UserMgr::GetInstance()->GetUserInfo(); ChatRole role; @@ -68,19 +72,34 @@ void ChatPage::AppendChatMsg(std::shared_ptr msg) ChatItemBase* pChatItem = new ChatItemBase(role); pChatItem->setUserName(self_info->_name); - pChatItem->setUserIcon(QPixmap(self_info->_icon)); + SetSelfIcon(pChatItem, self_info->_icon); QWidget* pBubble = nullptr; if (msg->GetMsgType() == ChatMsgType::TEXT) { pBubble = new TextBubble(role, msg->GetMsgContent()); + }else if (msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); } pChatItem->setWidget(pBubble); auto status = msg->GetStatus(); pChatItem->setStatus(status); ui->chat_data_list->appendChatItem(pChatItem); - if (status == 0) { + if (rsp) { + _base_item_map[msg->GetMsgId()] = pChatItem; + } + else { _unrsp_item_map[msg->GetUniqueId()] = pChatItem; } + } else { role = ChatRole::Other; @@ -89,43 +108,312 @@ void ChatPage::AppendChatMsg(std::shared_ptr msg) if (friend_info == nullptr) { return; } + pChatItem->setUserName(friend_info->_name); - pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(friend_info->_icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(msg->GetSendUid()) + "/avatars"); + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(friend_info->_icon); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + auto icon_label = pChatItem->getIconLabel(); + LoadHeadIcon(avatarPath, icon_label, friend_info->_icon,"other_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + //创建目录 + avatarsDir.mkpath("."); + auto icon_label = pChatItem->getIconLabel(); + QString avatarPath = avatarsDir.filePath(friend_info->_icon); + LoadHeadIcon(avatarPath, icon_label, friend_info->_icon, "other_icon"); + } + } + QWidget* pBubble = nullptr; if (msg->GetMsgType() == ChatMsgType::TEXT) { pBubble = new TextBubble(role, msg->GetMsgContent()); } + else if(msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } pChatItem->setWidget(pBubble); auto status = msg->GetStatus(); pChatItem->setStatus(status); ui->chat_data_list->appendChatItem(pChatItem); - if (status == 0) { + if (rsp) { + _base_item_map[msg->GetMsgId()] = pChatItem; + } + else { _unrsp_item_map[msg->GetUniqueId()] = pChatItem; } } +} + +void ChatPage::AppendOtherMsg(std::shared_ptr msg) { + auto self_info = UserMgr::GetInstance()->GetUserInfo(); + ChatRole role; + if (msg->GetSendUid() == self_info->_uid) { + role = ChatRole::Self; + ChatItemBase* pChatItem = new ChatItemBase(role); + + pChatItem->setUserName(self_info->_name); + SetSelfIcon(pChatItem, self_info->_icon); + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + else if (msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } + + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + _base_item_map[msg->GetMsgId()] = pChatItem; + } + else { + role = ChatRole::Other; + ChatItemBase* pChatItem = new ChatItemBase(role); + auto friend_info = UserMgr::GetInstance()->GetFriendById(msg->GetSendUid()); + if (friend_info == nullptr) { + return; + } + pChatItem->setUserName(friend_info->_name); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(friend_info->_icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(uid) + "/avatars"); + auto file_name = QFileInfo(self_info->_icon).fileName(); + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(file_name); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + auto icon_label = pChatItem->getIconLabel(); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + //创建目录 + avatarsDir.mkpath("."); + auto icon_label = pChatItem->getIconLabel(); + QString avatarPath = avatarsDir.filePath(file_name); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } + } + + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + else if (msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + _base_item_map[msg->GetMsgId()] = pChatItem; + } +} + +void ChatPage::LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type) { + UserMgr::GetInstance()->AddLabelToReset(avatarPath, icon_label); + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(icon_label->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + icon_label->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + icon_label->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + } + else { + //发送请求获取资源 + auto download_info = std::make_shared(); + download_info->_name = file_name; + download_info->_current_size = 0; + download_info->_seq = 1; + download_info->_total_size = 0; + download_info->_client_path = avatarPath; + //添加文件到管理者 + UserMgr::GetInstance()->AddDownloadFile(file_name, download_info); + //发送消息 + FileTcpMgr::GetInstance()->SendDownloadInfo(download_info, req_type); + } +} + +void ChatPage::UpdateChatStatus(std::shared_ptr msg) +{ + auto iter = _unrsp_item_map.find(msg->GetUniqueId()); + //没找到则直接返回 + if (iter == _unrsp_item_map.end()) { + return; + } + + iter.value()->setStatus(msg->GetStatus()); + _base_item_map[msg->GetMsgId()] = iter.value(); + _unrsp_item_map.erase(iter); +} + +void ChatPage::UpdateImgChatStatus(std::shared_ptr msg) { + auto iter = _unrsp_item_map.find(msg->GetUniqueId()); + //没找到则直接返回 + if (iter == _unrsp_item_map.end()) { + return; + } + + iter.value()->setStatus(msg->GetStatus()); + _base_item_map[msg->GetMsgId()] = iter.value(); + _unrsp_item_map.erase(iter); + + auto bubble = _base_item_map[msg->GetMsgId()]->getBubble(); + PictureBubble* pic_bubble = dynamic_cast(bubble); + pic_bubble->setMsgInfo(msg->_msg_info); +} + +void ChatPage::UpdateFileProgress(std::shared_ptr msg_info) { + auto iter = _base_item_map.find(msg_info->_msg_id); + if (iter == _base_item_map.end()) { + return; + } + + if (msg_info->_msg_type == MsgType::IMG_MSG) { + auto bubble = iter.value()->getBubble(); + PictureBubble* pic_bubble = dynamic_cast(bubble); + pic_bubble->setProgress(msg_info->_rsp_size, msg_info->_total_size); + } + +} + +void ChatPage::DownloadFileFinished(std::shared_ptr msg_info, QString file_path) { + auto iter = _base_item_map.find(msg_info->_msg_id); + if (iter == _base_item_map.end()) { + return; + } + if (msg_info->_msg_type == MsgType::IMG_MSG) { + auto bubble = iter.value()->getBubble(); + PictureBubble* pic_bubble = dynamic_cast(bubble); + pic_bubble->setDownloadFinish(msg_info, file_path); + auto chat_data_base = _chat_data->GetChatDataBase(msg_info->_msg_id); + if (chat_data_base == nullptr) { + return; + } + auto img_data = dynamic_pointer_cast(chat_data_base); + img_data->_msg_info->_preview_pix = QPixmap(file_path); + img_data->_msg_info->_transfer_state = TransferState::Completed; + img_data->_msg_info->_current_size = img_data->_msg_info->_total_size; + } } -void ChatPage::UpdateChatStatus(QString unique_id, int status) +void ChatPage::SetSelfIcon(ChatItemBase* pChatItem, QString icon) { - auto iter = _unrsp_item_map.find(unique_id); - if (iter != _unrsp_item_map.end()) { - iter.value()->setStatus(status); - _unrsp_item_map.erase(iter); + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(uid) + "/avatars"); + auto file_name = QFileInfo(icon).fileName(); + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(file_name); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + auto icon_label = pChatItem->getIconLabel(); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + //创建目录 + avatarsDir.mkpath("."); + auto icon_label = pChatItem->getIconLabel(); + QString avatarPath = avatarsDir.filePath(file_name); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } } } void ChatPage::paintEvent(QPaintEvent *event) { + Q_UNUSED(event); QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } -void ChatPage::on_send_btn_clicked() -{ +void ChatPage::on_send_btn_clicked() { if (_chat_data == nullptr) { qDebug() << "friend_info is empty"; return; @@ -137,31 +425,31 @@ void ChatPage::on_send_btn_clicked() QString userName = user_info->_name; QString userIcon = user_info->_icon; - const QVector& msgList = pTextEdit->getMsgList(); + const QVector>& msgList = pTextEdit->getMsgList(); QJsonObject textObj; QJsonArray textArray; int txt_size = 0; auto thread_id = _chat_data->GetThreadId(); - for(int i=0; i 1024){ + if (msgList[i]->_text_or_url.length() > 1024) { continue; } - QString type = msgList[i].msgFlag; - ChatItemBase *pChatItem = new ChatItemBase(role); + MsgType type = msgList[i]->_msg_type; + ChatItemBase* pChatItem = new ChatItemBase(role); pChatItem->setUserName(userName); - pChatItem->setUserIcon(QPixmap(userIcon)); - QWidget *pBubble = nullptr; + SetSelfIcon(pChatItem, user_info->_icon); + QWidget* pBubble = nullptr; //生成唯一id QUuid uuid = QUuid::createUuid(); //转为字符串 QString uuidString = uuid.toString(); - if(type == "text") - { - pBubble = new TextBubble(role, msgList[i].content); - if(txt_size + msgList[i].content.length()> 1024){ + if (type == MsgType::TEXT_MSG) + { + pBubble = new TextBubble(role, msgList[i]->_text_or_url); + if (txt_size + msgList[i]->_text_or_url.length() > 1024) { textObj["fromuid"] = user_info->_uid; textObj["touid"] = _chat_data->GetOtherId(); textObj["thread_id"] = thread_id; @@ -178,29 +466,72 @@ void ChatPage::on_send_btn_clicked() //将bubble和uid绑定,以后可以等网络返回消息后设置是否送达 //_bubble_map[uuidString] = pBubble; - txt_size += msgList[i].content.length(); + txt_size += msgList[i]->_text_or_url.length(); QJsonObject obj; - QByteArray utf8Message = msgList[i].content.toUtf8(); + QByteArray utf8Message = msgList[i]->_text_or_url.toUtf8(); auto content = QString::fromUtf8(utf8Message); obj["content"] = content; obj["unique_id"] = uuidString; textArray.append(obj); - //todo... 注意,此处先按私聊处理 - auto txt_msg = std::make_shared(uuidString, thread_id, ChatFormType::PRIVATE, + //注意,此处先按私聊处理 + auto txt_msg = std::make_shared(uuidString, thread_id, ChatFormType::PRIVATE, ChatMsgType::TEXT, content, user_info->_uid, 0); //将未回复的消息加入到未回复列表中,以便后续处理 - _chat_data->AppendUnRspMsg(uuidString,txt_msg); + _chat_data->AppendUnRspMsg(uuidString, txt_msg); } - else if(type == "image") + else if (type == MsgType::IMG_MSG) { - pBubble = new PictureBubble(QPixmap(msgList[i].content) , role); + //将之前缓存的文本发送过去 + if (txt_size) { + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + pBubble = new PictureBubble(QPixmap(msgList[i]->_text_or_url), role, msgList[i]->_total_size); + //需要组织成文件发送,具体参考头像上传 + auto img_msg = std::make_shared(msgList[i],uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString, img_msg); + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["md5"] = msgList[i]->_md5; + textObj["name"] = msgList[i]->_unique_name; + textObj["token"] = UserMgr::GetInstance()->GetToken(); + textObj["unique_id"] = uuidString; + textObj["text_or_url"] = msgList[i]->_text_or_url; + + //文件信息加入管理 + UserMgr::GetInstance()->AddTransFile(msgList[i]->_unique_name, msgList[i]); + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_IMG_CHAT_MSG_REQ, jsonData); + //链接暂停信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + //链接恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } - else if(type == "file") + else if (type == MsgType::FILE_MSG) { } //发送消息 - if(pBubble != nullptr) + if (pBubble != nullptr) { pChatItem->setWidget(pBubble); pChatItem->setStatus(0); @@ -210,22 +541,25 @@ void ChatPage::on_send_btn_clicked() } - qDebug() << "textArray is " << textArray ; - //发送给服务器 - textObj["text_array"] = textArray; - textObj["fromuid"] = user_info->_uid; - textObj["touid"] = _chat_data->GetOtherId(); - textObj["thread_id"] = thread_id; - QJsonDocument doc(textObj); - QByteArray jsonData = doc.toJson(QJsonDocument::Compact); - //发送并清空之前累计的文本列表 - txt_size = 0; - textArray = QJsonArray(); - textObj = QJsonObject(); - //发送tcp请求给chat server - emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + if (txt_size > 0) { + qDebug() << "textArray is " << textArray; + //发送给服务器 + textObj["text_array"] = textArray; + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } } + void ChatPage::on_receive_btn_clicked() { auto pTextEdit = ui->chatEdit; @@ -234,23 +568,23 @@ void ChatPage::on_receive_btn_clicked() QString userName = friend_info->_name; QString userIcon = friend_info->_icon; - const QVector& msgList = pTextEdit->getMsgList(); + const QVector>& msgList = pTextEdit->getMsgList(); for(int i=0; i_msg_type; ChatItemBase *pChatItem = new ChatItemBase(role); pChatItem->setUserName(userName); pChatItem->setUserIcon(QPixmap(userIcon)); QWidget *pBubble = nullptr; - if(type == "text") + if(type == MsgType::TEXT_MSG) { - pBubble = new TextBubble(role, msgList[i].content); + pBubble = new TextBubble(role, msgList[i]->_text_or_url); } - else if(type == "image") + else if(type == MsgType::IMG_MSG) { - pBubble = new PictureBubble(QPixmap(msgList[i].content) , role); + pBubble = new PictureBubble(QPixmap(msgList[i]->_text_or_url) , role, msgList[i]->_total_size); } - else if(type == "file") + else if(type == MsgType::FILE_MSG) { } @@ -263,7 +597,29 @@ void ChatPage::on_receive_btn_clicked() } } +void ChatPage::on_clicked_paused(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->PauseTransFileByName(unique_name); +} + +void ChatPage::on_clicked_resume(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->ResumeTransFileByName(unique_name); + //继续发送或者下载 + if (transfer_type == TransferType::Upload) { + FileTcpMgr::GetInstance()->ContinueUploadFile(unique_name); + return; + } + + if (transfer_type == TransferType::Download) { + FileTcpMgr::GetInstance()->ContinueDownloadFile(unique_name); + return; + } +} + void ChatPage::clearItems() { ui->chat_data_list->removeAllItem(); + _unrsp_item_map.clear(); + _base_item_map.clear(); } diff --git a/client/llfcchat/chatpage.h b/client/llfcchat/chatpage.h index ffd4fe5..9493b32 100644 --- a/client/llfcchat/chatpage.h +++ b/client/llfcchat/chatpage.h @@ -17,21 +17,36 @@ class ChatPage : public QWidget explicit ChatPage(QWidget *parent = nullptr); ~ChatPage(); void SetChatData(std::shared_ptr chat_data); - void AppendChatMsg(std::shared_ptr msg); - void UpdateChatStatus(QString unique_id, int status); + void AppendChatMsg(std::shared_ptr msg, bool rsp=true); + void UpdateChatStatus(std::shared_ptr msg); + void UpdateImgChatStatus(std::shared_ptr img_msg); + void SetSelfIcon(ChatItemBase* pChatItem, QString icon); + void UpdateFileProgress(std::shared_ptr msg_info); + void LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type); + void AppendOtherMsg(std::shared_ptr msg); + void DownloadFileFinished(std::shared_ptr msg_info, QString file_path); protected: void paintEvent(QPaintEvent *event); + private slots: void on_send_btn_clicked(); void on_receive_btn_clicked(); + //PictureBubbleͣź + void on_clicked_paused(QString unique_name, TransferType transfer_type); + //PictureBubbleļź + void on_clicked_resume(QString unique_name, TransferType transfer_type); + private: void clearItems(); Ui::ChatPage *ui; std::shared_ptr _chat_data; QMap _bubble_map; + //δظϢ QHash _unrsp_item_map; + //ѾظϢ + QHash _base_item_map; }; #endif // CHATPAGE_H diff --git a/client/llfcchat/chatuserwid.cpp b/client/llfcchat/chatuserwid.cpp index a1d1a64..7a177ff 100644 --- a/client/llfcchat/chatuserwid.cpp +++ b/client/llfcchat/chatuserwid.cpp @@ -1,6 +1,9 @@ #include "chatuserwid.h" #include "ui_chatuserwid.h" #include "usermgr.h" +#include +#include +#include "filetcpmgr.h" ChatUserWid::ChatUserWid(QWidget *parent) : ListItemBase(parent), @@ -27,16 +30,80 @@ void ChatUserWid::SetChatData(std::shared_ptr chat_data) { auto other_id = _chat_data->GetOtherId(); auto other_info = UserMgr::GetInstance()->GetFriendById(other_id); // 加载图片 - QPixmap pixmap(other_info->_icon); - // 设置图片自动缩放 - ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); - ui->icon_lb->setScaledContents(true); + QString head_icon = UserMgr::GetInstance()->GetIcon(); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(other_info->_icon); + + if (match.hasMatch()) { + // 如果是默认头像(:/res/head_X.jpg 格式) + QPixmap pixmap(other_info->_icon); // 加载默认头像图片 + QPixmap scaledPixmap = pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->icon_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->icon_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto other_uid = other_info->_uid; + QDir avatarsDir(storageDir + "/user/" + QString::number(other_uid) + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(other_info->_icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->icon_lb->setPixmap(scaledPixmap); + ui->icon_lb->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + LoadHeadIcon(avatarPath, ui->icon_lb, other_info->_icon,"other_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + QString avatarPath = avatarsDir.filePath(QFileInfo(other_info->_icon).fileName()); + avatarsDir.mkpath("."); + LoadHeadIcon(avatarPath, ui->icon_lb, other_info->_icon, "other_icon"); + } + } ui->user_name_lb->setText(other_info->_name); ui->user_chat_lb->setText(chat_data->GetLastMsg()); +} + +void ChatUserWid::LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name,QString req_type) { + UserMgr::GetInstance()->AddLabelToReset(avatarPath, icon_label); + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(icon_label->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + icon_label->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + icon_label->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + } + else { + //发送请求获取资源 + auto download_info = std::make_shared(); + download_info->_name = file_name; + download_info->_current_size = 0; + download_info->_seq = 1; + download_info->_total_size = 0; + download_info->_client_path = avatarPath; + //添加文件到管理者 + UserMgr::GetInstance()->AddDownloadFile(file_name, download_info); + //发送消息 + FileTcpMgr::GetInstance()->SendDownloadInfo(download_info, req_type); + } } std::shared_ptr ChatUserWid::GetChatData() diff --git a/client/llfcchat/chatuserwid.h b/client/llfcchat/chatuserwid.h index b736579..e29b5f0 100644 --- a/client/llfcchat/chatuserwid.h +++ b/client/llfcchat/chatuserwid.h @@ -4,6 +4,7 @@ #include #include "listitembase.h" #include "userdata.h" +#include namespace Ui { class ChatUserWid; } @@ -20,6 +21,7 @@ class ChatUserWid : public ListItemBase std::shared_ptr GetChatData(); void ShowRedPoint(bool bshow); void updateLastMsg(std::vector> msgs); + void LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type); private: Ui::ChatUserWid *ui; std::shared_ptr _chat_data; diff --git a/client/llfcchat/filetcpmgr.cpp b/client/llfcchat/filetcpmgr.cpp new file mode 100644 index 0000000..d06c26d --- /dev/null +++ b/client/llfcchat/filetcpmgr.cpp @@ -0,0 +1,1139 @@ +#include "filetcpmgr.h" +#include "usermgr.h" +#include +#include +FileTcpMgr::FileTcpMgr(QObject* parent) : QObject(parent), +_host(""), _port(0), _b_recv_pending(false), _message_id(0), _message_len(0), +_bytes_sent(0), _pending(false), _cwnd_size(0) +{ + registerMetaType(); + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { + qDebug() << "Connected to server!"; + emit sig_con_success(true); + }); + + + QObject::connect(&_socket, &QTcpSocket::readyRead, this, [&]() { + // 当有数据可读时,读取所有数据 + // 读取所有数据并追加到缓冲区 + _buffer.append(_socket.readAll()); + + forever{ + //先解析头部 + if (!_b_recv_pending) { + // 检查缓冲区中的数据是否足够解析出一个消息头(消息ID + 消息长度) + if (_buffer.size() < FILE_UPLOAD_HEAD_LEN) { + return; // 数据不够,等待更多数据 + } + + // ✅ 每次都重新创建stream + QDataStream stream(_buffer); + stream.setVersion(QDataStream::Qt_5_0); + stream >> _message_id >> _message_len; + + _buffer.remove(0, FILE_UPLOAD_HEAD_LEN); // 使用remove代替mid赋值 + + qDebug() << "Message ID:" << _message_id << ", Length:" << _message_len; + + } + + //buffer剩余长读是否满足消息体长度,不满足则退出继续等待接受 + if (_buffer.size() < _message_len) { + _b_recv_pending = true; + return; + } + + _b_recv_pending = false; + // 读取消息体 + QByteArray messageBody = _buffer.mid(0, _message_len); + qDebug() << "receive body msg is " << messageBody; + + _buffer = _buffer.mid(_message_len); + handleMsg(ReqId(_message_id),_message_len, messageBody); + } + + }); + + + //5.15 之后版本 +// QObject::connect(&_socket, QOverload::of(&QTcpSocket::errorOccurred), [&](QAbstractSocket::SocketError socketError) { +// Q_UNUSED(socketError) +// qDebug() << "Error:" << _socket.errorString(); +// }); + + // 处理错误(适用于Qt 5.15之前的版本) + QObject::connect(&_socket, static_cast(&QTcpSocket::error), + this, + [&](QTcpSocket::SocketError socketError) { + qDebug() << "Error:" << _socket.errorString(); + //todo... 根据错误类型做不同的处理 + switch (socketError) { + case QTcpSocket::ConnectionRefusedError: + qDebug() << "Connection Refused!"; + emit sig_con_success(false); + break; + case QTcpSocket::RemoteHostClosedError: + qDebug() << "Remote Host Closed Connection!"; + break; + case QTcpSocket::HostNotFoundError: + qDebug() << "Host Not Found!"; + emit sig_con_success(false); + break; + case QTcpSocket::SocketTimeoutError: + qDebug() << "Connection Timeout!"; + emit sig_con_success(false); + break; + case QTcpSocket::NetworkError: + //qDebug() << "Network Error!"; + break; + default: + //qDebug() << "Other Error!"; + break; + } + }); + + // 处理连接断开 + QObject::connect(&_socket, &QTcpSocket::disconnected, this, [&]() { + qDebug() << "Disconnected from server."; + emit sig_connection_closed(); + }); + + + //连接发送信号用来发送数据 + QObject::connect(this, &FileTcpMgr::sig_send_data, this, &FileTcpMgr::slot_send_data); + + //连接发送信号 + QObject::connect(&_socket, &QTcpSocket::bytesWritten, this, [this](qint64 bytes) { + //更新发送数据 + _bytes_sent += bytes; + //未发送完整 + if (_bytes_sent < _current_block.size()) { + //继续发送 + auto data_to_send = _current_block.mid(_bytes_sent); + _socket.write(data_to_send); + return; + } + + //发送完全,则查看队列是否为空 + if (_send_queue.isEmpty()) { + //队列为空,说明已经将所有数据发送完成,将pending设置为false,这样后续要发送数据时可以继续发送 + _current_block.clear(); + _pending = false; + _bytes_sent = 0; + return; + } + + //队列不为空,则取出队首元素 + _current_block = _send_queue.dequeue(); + _bytes_sent = 0; + _pending = true; + qint64 w2 = _socket.write(_current_block); + qDebug() << "[TcpMgr] Dequeued and write() returned" << w2; + }); + + //连接 + QObject::connect(this, &FileTcpMgr::sig_close, this, &FileTcpMgr::slot_tcp_close); + + //链接续传信号 + QObject::connect(this, &FileTcpMgr::sig_continue_upload_file, this, &FileTcpMgr::slot_continue_upload_file); + QObject::connect(this, &FileTcpMgr::sig_continue_download_file, this, &FileTcpMgr::slot_continue_download_file); + //注册消息 + initHandlers(); + +} + +void FileTcpMgr::registerMetaType() +{ + // 注册所有自定义类型 + qRegisterMetaType("ServerInfo"); + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("SearchInfo"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AddFriendApply"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("ApplyInfo"); + + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AuthRsp"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("UserInfo"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("ReqId"); + qRegisterMetaType("MsgInfo"); + qRegisterMetaType>("std::shared_ptr"); +} + +void FileTcpMgr::handleMsg(ReqId id, int len, QByteArray data) +{ + auto find_iter = _handlers.find(id); + if (find_iter == _handlers.end()) { + qDebug() << "not found id [" << id << "] to handle"; + return; + } + + find_iter.value()(id, len, data); +} + +void FileTcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes) +{ + uint16_t id = reqId; + + // 计算长度(使用网络字节序转换) + quint32 len = static_cast(dataBytes.length()); + + // 创建一个QByteArray用于存储要发送的所有数据 + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + + // 设置数据流使用网络字节序 + out.setByteOrder(QDataStream::BigEndian); + + // 写入ID和长度 + out << id << len; + + // 添加字符串数据 + block.append(dataBytes); + + //判断是否正在发送 + if (_pending) { + //放入队列直接返回,因为目前有数据正在发送 + _send_queue.enqueue(block); + return; + } + + // 没有正在发送,把这包设为“当前块”,重置计数,并写出去 + _current_block = block; // ← 保存当前正在发送的 block + _bytes_sent = 0; // ← 归零 + _pending = true; // ← 标记正在发送 + + qint64 written = _socket.write(_current_block); + /* qDebug() << "tcp mgr send byte data is" << _current_block + << ", write() returned" << written;*/ +} + +void FileTcpMgr::slot_tcp_connect(std::shared_ptr si) +{ + qDebug() << "receive tcp connect signal"; + // 尝试连接到服务器 + qDebug() << "Connecting to server..."; + _host = si->_res_host; + _port = static_cast(si->_res_port.toUInt()); + _socket.connectToHost(_host, _port); +} + + +FileTcpMgr::~FileTcpMgr() { + +} + +void FileTcpMgr::SendData(ReqId reqId, QByteArray data) +{ + emit sig_send_data(reqId, data); +} + +void FileTcpMgr::initHandlers() +{ + // 接收上传用户头像回复 + _handlers.insert(ID_UPLOAD_HEAD_ICON_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto md5 = recvObj["md5"].toString(); + auto seq = recvObj["seq"].toInt(); + auto trans_size = recvObj["trans_size"].toInt(); + auto uid = recvObj["uid"].toInt(); + auto total_size = recvObj["total_size"].toInt(); + auto name = recvObj["name"].toString(); + + qDebug() << "recv : " << name << "file trans_size is " << trans_size; + //判断trans_size和total_size相等 + if (total_size == trans_size) { + UserMgr::GetInstance()->RmvUploadFile(name); + return; + } + + auto file_info = UserMgr::GetInstance()->GetUploadInfoByName(name); + if (!file_info) { + return; + } + + //再次组织数据发送 + QFile file(file_info->filePath()); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(trans_size); + QByteArray buffer; + seq++; + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = md5; + sendObj["name"] = name; + sendObj["seq"] = seq; + sendObj["trans_size"] = buffer.size() + (seq - 1) * MAX_FILE_LEN; + sendObj["total_size"] = total_size; + + if (buffer.size() + (seq - 1) * MAX_FILE_LEN >= total_size) { + sendObj["last"] = 1; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = recvObj["last_seq"].toInt(); + sendObj["uid"] = uid; + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + SendData(ID_UPLOAD_HEAD_ICON_REQ, send_data); + + file.close(); + }); + + _handlers.insert(ID_DOWN_LOAD_FILE_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive download file info rsp success"; + + QString base64Data = jsonObj["data"].toString(); + QString clientPath = jsonObj["client_path"].toString(); + int seq = jsonObj["seq"].toInt(); + bool is_last = jsonObj["is_last"].toBool(); + QString total_size_str = jsonObj["total_size"].toString(); + qint64 total_size = total_size_str.toLongLong(nullptr); + QString current_size_str = jsonObj["current_size"].toString(); + qint64 current_size = current_size_str.toLongLong(nullptr); + QString name = jsonObj["name"].toString(); + QString req_type = jsonObj["req_type"].toString(); + + auto file_info = UserMgr::GetInstance()->GetDownloadInfo(name); + if (file_info == nullptr) { + qDebug() << "file: " << name << " not found"; + return; + } + + file_info->_current_size = current_size; + file_info->_total_size = total_size; + + //Base64解码 + QByteArray decodedData = QByteArray::fromBase64(base64Data.toUtf8()); + QFile file(clientPath); + + // 根据 seq 决定打开模式 + QIODevice::OpenMode mode; + if (seq == 1) { + // 第一个包,覆盖写入 + mode = QIODevice::WriteOnly; + } + else { + // 后续包,追加写入 + mode = QIODevice::WriteOnly | QIODevice::Append; + } + + if (!file.open(mode)) { + qDebug() << "Failed to open file for writing:" << clientPath; + qDebug() << "Error:" << file.errorString(); + return; + } + + + qint64 bytesWritten = file.write(decodedData); + if (bytesWritten != decodedData.size()) { + qDebug() << "Failed to write all data. Written:" << bytesWritten + << "Expected:" << decodedData.size(); + } + + file.close(); + + qDebug() << "Successfully wrote" << bytesWritten << "bytes to file"; + qDebug() << "Progress:" << current_size << "/" << total_size + << "(" << (current_size * 100 / total_size) << "%)"; + + if (is_last) { + qDebug() << "File download completed:" << clientPath; + UserMgr::GetInstance()->RmvDownloadFile(name); + if (req_type == "self_icon") { + //发送信号通知主界面重新加载label + emit sig_reset_label_icon(clientPath); + } + else if (req_type == "other_icon") { + //发送信号通知主界面刷新其他人头像,此处先不做,后期可以添加,目前不添加不影响使用,只是别人换头像,自己看到为空,但是会后台请求。 + //考虑这种建议是先使用该人之前的头像,点击切换界面后自动刷新加载为新的。 + } + } + else { + //继续请求 + file_info->_seq = seq + 1; + FileTcpMgr::GetInstance()->SendDownloadInfo(file_info, req_type); + } + }); + + _handlers.insert(ID_FILE_INFO_SYNC_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败,将来可能断点重传等 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + //为了简单起见,先处理网络正常情况 + auto seq = recvObj["seq"].toInt(); + auto name = recvObj["name"].toString(); + auto receiver = recvObj["receiver"].toInt(); + auto sender = recvObj["sender"].toInt(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //将文件移动到用户自己的资源目录 + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(file_info->_sender); + auto destPath = img_path_str + '/' + file_info->_unique_name; + + CopyFile(file_info->_text_or_url,destPath, img_path_str); + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file,sender,receiver); + return; + } + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + //通知界面显示 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info, sender, receiver); + }); + + _handlers.insert(ID_IMG_CHAT_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + + auto receiver = recvObj["receiver"].toInt(); + auto sender = recvObj["sender"].toInt(); + + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(file_info->_sender); + auto destPath = img_path_str + '/' + file_info->_unique_name; + + CopyFile(file_info->_text_or_url, destPath, img_path_str); + + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file,sender,receiver); + return; + } + + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + + //发送信号,更新图片上传进度 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info,sender,receiver); }); + + _handlers.insert(ID_IMG_CHAT_CONTINUE_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(file_info->_sender); + auto destPath = img_path_str + '/' + file_info->_unique_name; + + CopyFile(file_info->_text_or_url, destPath, img_path_str); + + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file, file_info->_sender, file_info->_receiver); + return; + } + + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + + //发送信号,更新图片上传进度 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info, file_info->_sender, file_info->_receiver); }); + + _handlers.insert(ID_IMG_CHAT_DOWN_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive download file info rsp success"; + + QString base64Data = jsonObj["data"].toString(); + int seq = jsonObj["seq"].toInt(); + bool is_last = jsonObj["is_last"].toBool(); + QString total_size_str = jsonObj["total_size"].toString(); + qint64 total_size = total_size_str.toLongLong(nullptr); + QString current_size_str = jsonObj["current_size"].toString(); + qint64 current_size = current_size_str.toLongLong(nullptr); + QString name = jsonObj["name"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (file_info == nullptr) { + qDebug() << "file: " << name << " not found"; + return; + } + + file_info->_current_size = current_size; + file_info->_rsp_size = current_size; + file_info->_total_size = total_size; + auto clientPath = file_info->_text_or_url; + + //Base64解码 + QByteArray decodedData = QByteArray::fromBase64(base64Data.toUtf8()); + auto file_path = clientPath + "/" + name; + QFile file(file_path); + + // 根据 seq 决定打开模式 + QIODevice::OpenMode mode; + if (seq == 1) { + // 第一个包,覆盖写入 + mode = QIODevice::WriteOnly; + } + else { + // 后续包,追加写入 + mode = QIODevice::WriteOnly | QIODevice::Append; + } + + if (!file.open(mode)) { + qDebug() << "Failed to open file for writing:" << clientPath; + qDebug() << "Error:" << file.errorString(); + return; + } + + + qint64 bytesWritten = file.write(decodedData); + if (bytesWritten != decodedData.size()) { + qDebug() << "Failed to write all data. Written:" << bytesWritten + << "Expected:" << decodedData.size(); + } + + file.close(); + + qDebug() << "Successfully wrote" << bytesWritten << "bytes to file"; + qDebug() << "Progress:" << current_size << "/" << total_size + << "(" << (current_size * 100 / total_size) << "%)"; + + if (is_last) { + qDebug() << "File download completed:" << clientPath; + UserMgr::GetInstance()->RmvTransFileByName(name); + //通知界面下载完成 + emit sig_download_finish(file_info, file_path); + } + else { + //继续请求 + file_info->_seq = seq + 1; + file_info->_last_confirmed_seq = seq; + if (file_info->_transfer_state == TransferState::Paused) { + //暂停状态,则直接返回 + return; + } + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = QString::number(file_info->_current_size); + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = file_info->_sender; + jsonObj_send["receiver_id"] = file_info->_receiver; + jsonObj_send["message_id"] = file_info->_msg_id; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj_send["uid"] = uid; + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + //todo...通知界面更新进度 + emit sig_update_download_progress(file_info); + } + }); + + _handlers.insert(ID_IMG_CHAT_DOWN_INFO_SYNC_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive download file info rsp success"; + + int message_id = jsonObj["message_id"].toInt(); + int thread_id = jsonObj["thread_id"].toInt(); + int sender_id = jsonObj["sender_id"].toInt(); + int recv_id = jsonObj["recv_id"].toInt(); + QString name = jsonObj["name"].toString(); + int msg_type = jsonObj["msg_type"].toInt(); + int status = jsonObj["status"].toInt(); + QString total_size_str = jsonObj["total_size"].toString(); + int64_t total_size = total_size_str.toLongLong(); // 64位整数 + auto uid = UserMgr::GetInstance()->GetUid(); + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(sender_id); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + //如果未找到则初始化一下 + if (!file_info) { + //预览图先默认空白,md5为空 + file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, CreateLoadingPlaceholder(200, 200), name, total_size, ""); + file_info->_msg_id = message_id; + file_info->_sender = sender_id; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::Uploading; + UserMgr::GetInstance()->AddTransFile(name, file_info); + } + + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = "0"; + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = sender_id; + jsonObj_send["receiver_id"] = recv_id; + jsonObj_send["message_id"] = message_id; + jsonObj_send["uid"] = uid; + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QDir chatimgDir(img_path_str); + jsonObj["client_path"] = img_path_str; + if (!chatimgDir.exists()) { + chatimgDir.mkpath("."); // 创建当前路径 + } + //通知界面更新进度 + emit sig_update_download_progress(file_info); + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + + }); + +} + +void FileTcpMgr::CopyFile(QString src_path, QString dst_path, QString dst_dir) { + //将文件移动到用户自己的资源目录 + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + + QDir chatimgDir(dst_dir); + if (!chatimgDir.exists()) { + chatimgDir.mkpath("."); // 创建当前路径 + } + + if (QFile::copy(src_path, dst_path)) { + qDebug() << "文件拷贝成功"; + + } + else { + qDebug() << "文件拷贝失败"; + + } +} + +void FileTcpMgr::ContinueUploadFile(QString unique_name) { + emit sig_continue_upload_file(unique_name); +} + +void FileTcpMgr::ContinueDownloadFile(QString unique_name) { + emit sig_continue_download_file(unique_name); +} + +void FileTcpMgr::BatchSend(std::shared_ptr msg_info, int sender, int receiver) { + if (msg_info == nullptr) { + return; + } + + if ((msg_info->_seq) * MAX_FILE_LEN >= msg_info->_total_size) { + qDebug() << "file has sent finished"; + return; + } + + if (MAX_CWND_SIZE - _cwnd_size == 0) { + return; + } + + //打开 + QFile file(msg_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(msg_info->_seq * MAX_FILE_LEN); + + bool b_last = false; + //再次组织数据发送 + for (; MAX_CWND_SIZE - _cwnd_size > 0; ) { + + QByteArray buffer; + msg_info->_seq++; + //放入发送未回包集合 + msg_info->_flighting_seqs.insert(msg_info->_seq); + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = msg_info->_md5; + sendObj["name"] = msg_info->_unique_name; + sendObj["seq"] = msg_info->_seq; + msg_info->_current_size = buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN; + sendObj["trans_size"] = QString::number(msg_info->_current_size); + sendObj["total_size"] = QString::number(msg_info->_total_size); + + b_last = false; + if (buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN >= msg_info->_total_size) { + sendObj["last"] = 1; + b_last = true; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = msg_info->_max_seq; + sendObj["uid"] = UserMgr::GetInstance()->GetUid(); + sendObj["message_id"] = msg_info->_msg_id; + sendObj["sender"] = sender; + sendObj["receiver"] = receiver; + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + //直接发送,其实是放入tcpmgr发送队列 + SendData(ID_IMG_CHAT_UPLOAD_REQ, send_data); + _cwnd_size++; + //如果 + if (b_last) { + break; + } + } + + file.close(); +} + +void FileTcpMgr::slot_tcp_close() { + _socket.close(); +} + +void FileTcpMgr::slot_continue_upload_file(QString unique_name) { + auto msg_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + if (msg_info == nullptr) { + return; + } + //将待发送序列号更新为已经确认接收的序列号,然后基于此序列号再递增。 + msg_info->_seq = msg_info->_last_confirmed_seq; + + if ((msg_info->_seq) * MAX_FILE_LEN >= msg_info->_total_size) { + qDebug() << "file has sent finished"; + return; + } + + if (MAX_CWND_SIZE - _cwnd_size == 0) { + return; + } + + //打开 + QFile file(msg_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(msg_info->_seq * MAX_FILE_LEN); + + bool b_last = false; + //再次组织数据发送 + for (; MAX_CWND_SIZE - _cwnd_size > 0; ) { + + QByteArray buffer; + msg_info->_seq++; + //放入发送未回包集合 + msg_info->_flighting_seqs.insert(msg_info->_seq); + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = msg_info->_md5; + sendObj["name"] = msg_info->_unique_name; + sendObj["seq"] = msg_info->_seq; + msg_info->_current_size = buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN; + sendObj["trans_size"] = msg_info->_current_size; + sendObj["total_size"] = msg_info->_total_size; + sendObj["sender"] = msg_info->_sender; + sendObj["receiver"] = msg_info->_receiver; + sendObj["message_id"] = msg_info->_msg_id; + + b_last = false; + if (buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN >= msg_info->_total_size) { + sendObj["last"] = 1; + b_last = true; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = msg_info->_max_seq; + sendObj["uid"] = UserMgr::GetInstance()->GetUid(); + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + //直接发送,其实是放入tcpmgr发送队列 + SendData(ID_IMG_CHAT_CONTINUE_UPLOAD_REQ, send_data); + _cwnd_size++; + //如果 + if (b_last) { + break; + } + } + + file.close(); +} + +void FileTcpMgr::slot_continue_download_file(QString unique_name) { + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + if (file_info == nullptr) { + return; + } + + if (file_info->_current_size >= file_info->_total_size) { + qDebug() << "file has received finished"; + return; + } + + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = unique_name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = QString::number(file_info->_current_size); + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = file_info->_sender; + jsonObj_send["receiver_id"] = file_info->_receiver; + jsonObj_send["message_id"] = file_info->_msg_id; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj_send["uid"] = uid; + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + +} + +void FileTcpMgr::CloseConnection() { + emit sig_close(); +} + +void FileTcpMgr::SendDownloadInfo(std::shared_ptr download, QString req_type) { + QJsonObject jsonObj; + jsonObj["name"] = download->_name; + jsonObj["seq"] = download->_seq; + jsonObj["trans_size"] = 0; + jsonObj["total_size"] = 0; + jsonObj["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj["uid"] = UserMgr::GetInstance()->GetUid(); + jsonObj["client_path"] = download->_client_path; + jsonObj["req_type"] = req_type; + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + + SendData(ID_DOWN_LOAD_FILE_REQ, send_data); +} + + +FileTcpThread::FileTcpThread() +{ + _file_tcp_thread = new QThread(); + FileTcpMgr::GetInstance()->moveToThread(_file_tcp_thread); + QObject::connect(_file_tcp_thread, &QThread::finished, _file_tcp_thread, &QObject::deleteLater); + _file_tcp_thread->start(); +} + +FileTcpThread::~FileTcpThread() +{ + _file_tcp_thread->quit(); +} diff --git a/client/llfcchat/filetcpmgr.h b/client/llfcchat/filetcpmgr.h new file mode 100644 index 0000000..92fc531 --- /dev/null +++ b/client/llfcchat/filetcpmgr.h @@ -0,0 +1,84 @@ +#ifndef FILETCPMGR_H +#define FILETCPMGR_H + +#include +#include "singleton.h" +#include "global.h" +#include +#include +#include "userdata.h" +#include +#include +#include +#include +#include +#include "global.h" + +class FileTcpThread: public std::enable_shared_from_this{ +public: + FileTcpThread(); + ~FileTcpThread(); +private: + QThread * _file_tcp_thread; + +}; + +class FileTcpMgr : public QObject, public Singleton, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + friend class Singleton; + ~FileTcpMgr(); + void SendData(ReqId reqId, QByteArray data); + void CloseConnection(); + void SendDownloadInfo(std::shared_ptr download,QString req_type); + void BatchSend(std::shared_ptr msg_info, int sender, int receiver); + void ContinueUploadFile(QString unique_name); + void ContinueDownloadFile(QString unique_name); + void CopyFile(QString src_path, QString dst_path, QString dst_dir); +private: + void initHandlers(); + explicit FileTcpMgr(QObject *parent = nullptr); + + void registerMetaType(); + void handleMsg(ReqId id, int len, QByteArray data); + + QTcpSocket _socket; + QString _host; + uint16_t _port; + QByteArray _buffer; + bool _b_recv_pending; + quint16 _message_id; + quint32 _message_len; + QMap> _handlers; + //发送队列 + QQueue _send_queue; + //正在发送的包 + QByteArray _current_block; + //当前已发送的字节数 + qint64 _bytes_sent; + //是否正在发送 + bool _pending; + //发送的拥塞窗口,控制发送数量 + int _cwnd_size; +signals: + void sig_close(); + void sig_send_data(ReqId reqId, QByteArray data); + void sig_con_success(bool bsuccess); + void sig_connection_closed(); + void sig_reset_label_icon(QString path); + void sig_update_upload_progress(std::shared_ptr); + void sig_continue_upload_file(QString unique_name); + void sig_continue_download_file(QString unique_name); + void sig_update_download_progress(std::shared_ptr); + void sig_download_finish(std::shared_ptr,QString file_path); +public slots: + void slot_send_data(ReqId reqId, QByteArray data); + void slot_tcp_connect(std::shared_ptr si); + void slot_tcp_close(); + void slot_continue_upload_file(QString unique_name); + void slot_continue_download_file(QString unique_name); +}; + +#endif // FILETCPMGR_H diff --git a/client/llfcchat/global.cpp b/client/llfcchat/global.cpp index 1a3eab6..29fc232 100644 --- a/client/llfcchat/global.cpp +++ b/client/llfcchat/global.cpp @@ -1,6 +1,8 @@ #include "global.h" #include #include +#include +#include std::function repolish =[](QWidget *w){ w->style()->unpolish(w); @@ -26,4 +28,64 @@ void delay_run(int msecs) { // singleShot 到时后会触发 loop.quit(),从而退出事件循环 QTimer::singleShot(msecs, &loop, &QEventLoop::quit); loop.exec(); +} + +QString generateUniqueFileName(const QString& originalName){ + + QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); + QFileInfo fileInfo(originalName); + QString extension = fileInfo.suffix(); + return uuid + (extension.isEmpty() ? "" : "." + extension); +} + +QString generateUniqueIconName(){ + QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); + return uuid + ".png"; +} + +QString calculateFileHash(const QString& filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) + return QString(); + + QCryptographicHash hash(QCryptographicHash::Md5); + + // 分块计算哈希,避免大文件占用过多内存 + const qint64 chunkSize = 1024 * 1024; // 1MB + while (!file.atEnd()) + { + hash.addData(file.read(chunkSize)); + } + file.close(); + + return hash.result().toHex(); +} + +QPixmap CreateLoadingPlaceholder(int width, int height ) { + QPixmap placeholder(width, height); + placeholder.fill(QColor(240, 240, 240)); // 浅灰色背景 + + QPainter painter(&placeholder); + painter.setRenderHint(QPainter::Antialiasing); + + // 绘制边框 + painter.setPen(QPen(QColor(200, 200, 200), 2)); + painter.drawRect(1, 1, width - 2, height - 2); + + // 绘制加载图标(简单的旋转圆圈或文字) + QFont font; + font.setPointSize(12); + painter.setFont(font); + painter.setPen(QColor(150, 150, 150)); + painter.drawText(placeholder.rect(), Qt::AlignCenter, "加载中..."); + + // 可选:添加图片图标 + painter.setPen(QColor(180, 180, 180)); + QRect iconRect(width / 2 - 20, height / 2 - 40, 40, 30); + painter.drawRect(iconRect); + painter.drawLine(iconRect.topLeft(), iconRect.bottomRight()); + painter.drawLine(iconRect.topRight(), iconRect.bottomLeft()); + + return placeholder; } \ No newline at end of file diff --git a/client/llfcchat/global.h b/client/llfcchat/global.h index 70c3489..c411251 100644 --- a/client/llfcchat/global.h +++ b/client/llfcchat/global.h @@ -9,6 +9,21 @@ #include #include #include +#include +#include + +//TCP文件上传包头长度 +#define FILE_UPLOAD_HEAD_LEN 6 +//TCP ID长度 +#define FILE_UPLOAD_ID_LEN 2 +//TCP 长度字段的长度 +#define FILE_UPLOAD_LEN_LEN 4 +//最大文件长度 +#define MAX_FILE_LEN (1024*32) +//定义最大拥塞窗口的大小 +#define MAX_CWND_SIZE 5 + + /** * @brief repolish用来根据属性刷新qss */ @@ -52,7 +67,26 @@ enum ReqId{ ID_CREATE_PRIVATE_CHAT_RSP = 1028, //创建私聊回复 ID_LOAD_CHAT_MSG_REQ = 1029, //加载聊天消息 ID_LOAD_CHAT_MSG_RSP = 1030, //加载聊天消息 + ID_UPLOAD_HEAD_ICON_REQ = 1031, //上传头像请求 + ID_UPLOAD_HEAD_ICON_RSP = 1032, //上传头像回复 + ID_DOWN_LOAD_FILE_REQ = 1033, //下载文件请求 + ID_DOWN_LOAD_FILE_RSP = 1034, //下载文件回复 + ID_IMG_CHAT_MSG_REQ = 1035, //图片聊天消息请求 + ID_IMG_CHAT_MSG_RSP = 1036, //图片聊天信息回复 + ID_IMG_CHAT_UPLOAD_REQ = 1037, //上传聊天图片资源 + ID_IMG_CHAT_UPLOAD_RSP = 1038, //上传聊天图片资源回复 + + ID_NOTIFY_IMG_CHAT_MSG_REQ = 1039, //通知用户图片聊天信息 + ID_FILE_INFO_SYNC_REQ = 1041, //文件信息同步请求 + ID_FILE_INFO_SYNC_RSP = 1042, //文件信息同步回复 + ID_IMG_CHAT_CONTINUE_UPLOAD_REQ = 1043, //续传聊天图片资源请求 + ID_IMG_CHAT_CONTINUE_UPLOAD_RSP = 1044, //续传聊天图片资源回复 + ID_IMG_CHAT_DOWN_INFO_SYNC_REQ = 1045, //获取图片下载信息同步请求 + ID_IMG_CHAT_DOWN_INFO_SYNC_RSP = 1046, //获取图片下载信息同步回复 + ID_IMG_CHAT_DOWN_REQ = 1047, //聊天图片下载请求 + ID_IMG_CHAT_DOWN_RSP = 1048 //聊天图片下载回复 }; +Q_DECLARE_METATYPE(ReqId) enum ErrorCodes{ SUCCESS = 0, @@ -86,12 +120,21 @@ extern QString gate_url_prefix; struct ServerInfo{ - QString Host; - QString Port; - QString Token; - int Uid; +public: + ServerInfo() = default; + ServerInfo(const ServerInfo& other):_chat_host(other._chat_host),_chat_port(other._chat_port), + _token(other._token),_uid(other._uid){} + QString _chat_host; + QString _chat_port; + QString _res_host; + QString _res_port; + QString _token; + int _uid; }; +Q_DECLARE_METATYPE(ServerInfo) +Q_DECLARE_METATYPE(std::shared_ptr) + enum class ChatRole { @@ -99,11 +142,62 @@ enum class ChatRole Other }; +enum class MsgType { + TEXT_MSG = 0, //文本消息 + IMG_MSG = 1, //图片消息 + VIDEO_MSG = 2, //视频消息 + FILE_MSG = 3//文件消息, +}; + +enum class TransferType { + None, + Download, //下载 + Upload //上传 +}; + +enum class TransferState { + None, // 无传输 + Downloading, // 下载中 + Uploading, // 上传中 + Paused, // 暂停 + Completed, // 完成 + Failed // 失败 +}; + struct MsgInfo{ - QString msgFlag;//"text,image,file" - QString content;//表示文件和图像的url,文本信息 - QPixmap pixmap;//文件和图片的缩略图 + MsgInfo() = default; + MsgInfo(MsgType msgtype, QString text_or_url, QPixmap pixmap, QString unique_name, qint64 total_size, QString md5) + :_msg_type(msgtype), _text_or_url(text_or_url), _preview_pix(pixmap),_unique_name(unique_name),_total_size(total_size), + _current_size(0),_seq(1),_md5(md5), _last_confirmed_seq(0),_rsp_size(0), _transfer_state(TransferState::None), + _transfer_type(TransferType::None) + { + _max_seq = ((total_size + MAX_FILE_LEN - 1) / MAX_FILE_LEN); + } + + MsgType _msg_type; //消息类型, 文本,图片,视频,文件 + QString _text_or_url;//表示文件和图像的url,文本信息 + QPixmap _preview_pix;//文件和图片的缩略图 + QString _unique_name; //文件唯一名字 + qint64 _total_size; //文件总大小 + qint64 _current_size; //传输大小 + qint64 _seq; //传输序号 + QString _md5; //文件md5 + std::set _rsp_seqs; //已经接受的回传序列集合 + std::set _flighting_seqs; //正在发送,但是未收到服务器回复,将来用来做超时重传 + qint64 _last_confirmed_seq; //最后确认序列 + qint64 _max_seq; //最大序列号 + qint64 _msg_id; //关联的消息id + qint64 _rsp_size; //服务器返回实际上传或者下载的大小 + qint64 _thread_id; // 会话id + TransferState _transfer_state; //上传或者下载, 暂停,传输完成 + TransferType _transfer_type; //文件类型, 上传或者下载 + int _sender; //发送者 + int _receiver; //接收者 + }; +//声明为元对象类型 +Q_DECLARE_METATYPE(MsgInfo) +Q_DECLARE_METATYPE(std::shared_ptr) //聊天界面几种模式 enum ChatUIMode{ @@ -163,7 +257,8 @@ const int CHAT_COUNT_PER_PAGE = 13; enum MsgStatus{ UN_READ = 0, //对方未读 SEND_FAILED = 1, //发送失败 - READED = 2 //对方已读 + READED = 2, //对方已读 + UN_UPLOAD = 3 //未上传完成 }; //聊天形式,私聊和群聊 @@ -176,7 +271,25 @@ enum class ChatFormType { enum class ChatMsgType { TEXT = 0, PIC = 1, - FILE = 2 + VIDEO = 2, + FILE = 3 }; + + +extern QString generateUniqueFileName(const QString& originalName); + +extern QString generateUniqueIconName(); + +struct DownloadInfo { + QString _name; + int _total_size; + int _current_size; + int _seq; + QString _client_path; +}; + +extern QString calculateFileHash(const QString& filePath); +extern QPixmap CreateLoadingPlaceholder(int width = 200, int height = 200); + #endif // GLOBAL_H diff --git a/client/llfcchat/llfcchat.pro b/client/llfcchat/llfcchat.pro index 62ebe94..0043e74 100644 --- a/client/llfcchat/llfcchat.pro +++ b/client/llfcchat/llfcchat.pro @@ -29,6 +29,7 @@ SOURCES += \ BubbleFrame.cpp \ ChatItemBase.cpp \ ChatView.cpp \ + ClickableLabel.cpp \ MessageTextEdit.cpp \ PictureBubble.cpp \ TextBubble.cpp \ @@ -49,6 +50,7 @@ SOURCES += \ conuseritem.cpp \ customizeedit.cpp \ customizetextedit.cpp \ + filetcpmgr.cpp \ findfaildlg.cpp \ findsuccessdlg.cpp \ friendinfopage.cpp \ @@ -79,6 +81,7 @@ HEADERS += \ BubbleFrame.h \ ChatItemBase.h \ ChatView.h \ + ClickableLabel.h \ MessageTextEdit.h \ PictureBubble.h \ TextBubble.h \ @@ -99,6 +102,7 @@ HEADERS += \ conuseritem.h \ customizeedit.h \ customizetextedit.h \ + filetcpmgr.h \ findfaildlg.h \ findsuccessdlg.h \ friendinfopage.h \ diff --git a/client/llfcchat/logindialog.cpp b/client/llfcchat/logindialog.cpp index ad19730..dfcfe24 100644 --- a/client/llfcchat/logindialog.cpp +++ b/client/llfcchat/logindialog.cpp @@ -6,6 +6,7 @@ #include #include #include +#include "filetcpmgr.h" LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), @@ -20,7 +21,6 @@ LoginDialog::LoginDialog(QWidget *parent) : //连接登录回包信号 connect(HttpMgr::GetInstance().get(), &HttpMgr::sig_login_mod_finish, this, &LoginDialog::slot_login_mod_finish); - //连接tcp连接请求的信号和槽函数 connect(this, &LoginDialog::sig_connect_tcp, TcpMgr::GetInstance().get(), &TcpMgr::slot_tcp_connect); //连接tcp管理者发出的连接成功信号 @@ -28,6 +28,12 @@ LoginDialog::LoginDialog(QWidget *parent) : //连接tcp管理者发出的登陆失败信号 connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_login_failed, this, &LoginDialog::slot_login_failed); + //连接tcp连接资源服务器请求的信号和槽函数 + connect(this, &LoginDialog::sig_connect_res_server, + FileTcpMgr::GetInstance().get(), &FileTcpMgr::slot_tcp_connect); + + //连接资源管理tcp发出的连接成功信号 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_con_success, this, &LoginDialog::slot_res_con_finish); initHead(); } @@ -80,17 +86,25 @@ void LoginDialog::initHttpHandlers() auto email = jsonObj["email"].toString(); //发送信号通知tcpMgr发送长链接 - ServerInfo si; - si.Uid = jsonObj["uid"].toInt(); - si.Host = jsonObj["host"].toString(); - si.Port = jsonObj["port"].toString(); - si.Token = jsonObj["token"].toString(); - - _uid = si.Uid; - _token = si.Token; - qDebug()<< "email is " << email << " uid is " << si.Uid <<" host is " - << si.Host << " Port is " << si.Port << " Token is " << si.Token; - emit sig_connect_tcp(si); + _si = std::make_shared(); + + _si->_uid = jsonObj["uid"].toInt(); + _si->_chat_host = jsonObj["chathost"].toString(); + _si->_chat_port = jsonObj["chatport"].toString(); + _si->_token = jsonObj["token"].toString(); + + _si->_res_host = jsonObj["reshost"].toString(); + _si->_res_port = jsonObj["resport"].toString(); + + + qDebug()<< "email is " << email << " uid is " << _si->_uid <<" chat host is " + << _si->_chat_host << " chat port is " + << _si->_chat_port << " token is " << _si->_token + << " res host is " << _si->_res_host + << " res port is " << _si->_res_port; + emit sig_connect_tcp(_si); + // qDebug() << "send thread is " << QThread::currentThread(); + // emit sig_test(); }); } @@ -209,24 +223,12 @@ void LoginDialog::slot_login_mod_finish(ReqId id, QString res, ErrorCodes err) void LoginDialog::slot_tcp_con_finish(bool bsuccess) { - - if(bsuccess){ - showTip(tr("聊天服务连接成功,正在登录..."),true); - QJsonObject jsonObj; - jsonObj["uid"] = _uid; - jsonObj["token"] = _token; - - QJsonDocument doc(jsonObj); - QByteArray jsonData = doc.toJson(QJsonDocument::Indented); - - //发送tcp请求给chat server - emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_CHAT_LOGIN, jsonData); - - }else{ - showTip(tr("网络异常"),false); - enableBtn(true); - } - + if(bsuccess){ + showTip(tr("聊天服务连接成功,正在连接资源服务器..."),true); + emit sig_connect_res_server(_si); + }else{ + showTip(tr("网络异常"), false); + } } void LoginDialog::slot_login_failed(int err) @@ -237,6 +239,27 @@ void LoginDialog::slot_login_failed(int err) enableBtn(true); } +void LoginDialog::slot_res_con_finish(bool bsuccess) +{ + if(bsuccess){ + showTip(tr("聊天服务连接成功,正在登录..."),true); + QJsonObject jsonObj; + jsonObj["uid"] = _si->_uid; + jsonObj["token"] = _si->_token; + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Indented); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_CHAT_LOGIN, jsonData); + + }else{ + showTip(tr("网络异常"),false); + enableBtn(true); + } + +} + void LoginDialog::AddTipErr(TipErr te,QString tips){ _tip_errs[te] = tips; showTip(tips, false); diff --git a/client/llfcchat/logindialog.h b/client/llfcchat/logindialog.h index 39e2c6b..5307d48 100644 --- a/client/llfcchat/logindialog.h +++ b/client/llfcchat/logindialog.h @@ -27,18 +27,20 @@ class LoginDialog : public QDialog QMap _tip_errs; void AddTipErr(TipErr te,QString tips); void DelTipErr(TipErr te); - int _uid; - QString _token; + std::shared_ptr _si; private slots: void slot_forget_pwd(); void on_login_btn_clicked(); void slot_login_mod_finish(ReqId id, QString res, ErrorCodes err); void slot_tcp_con_finish(bool bsuccess); void slot_login_failed(int); + void slot_res_con_finish(bool bsuccess); signals: void switchRegister(); void switchReset(); - void sig_connect_tcp(ServerInfo); + void sig_connect_tcp(std::shared_ptr); + void sig_connect_res_server(std::shared_ptr); + void sig_test(); }; #endif // LOGINDIALOG_H diff --git a/client/llfcchat/main.cpp b/client/llfcchat/main.cpp index 4acdaf3..b08ba52 100644 --- a/client/llfcchat/main.cpp +++ b/client/llfcchat/main.cpp @@ -2,7 +2,8 @@ #include #include #include "global.h" - +#include "tcpmgr.h" +#include "filetcpmgr.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); @@ -32,6 +33,10 @@ int main(int argc, char *argv[]) QString gate_port = settings.value("GateServer/port").toString(); gate_url_prefix = "http://"+gate_host+":"+gate_port; + //启动tcp线程 + TcpThread tcpthread; + //启动资源网络线程 + FileTcpThread file_tcp_thread; MainWindow w; w.show(); return a.exec(); diff --git a/client/llfcchat/mainwindow.cpp b/client/llfcchat/mainwindow.cpp index 82479bf..a0698eb 100644 --- a/client/llfcchat/mainwindow.cpp +++ b/client/llfcchat/mainwindow.cpp @@ -4,6 +4,7 @@ #include "tcpmgr.h" #include #include +#include "filetcpmgr.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -27,9 +28,9 @@ MainWindow::MainWindow(QWidget *parent) : connect(TcpMgr::GetInstance().get(),&TcpMgr::sig_notify_offline, this, &MainWindow::SlotOffline); //连接服务器断开心跳超时或异常连接信息 connect(TcpMgr::GetInstance().get(),&TcpMgr::sig_connection_closed, this, &MainWindow::SlotExcepConOffline); - //测试用 - //emit TcpMgr::GetInstance()->sig_swich_chatdlg(); - + //连接资源服务器断开 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_connection_closed, + this, &MainWindow::SlotResServerConOffline); } MainWindow::~MainWindow() @@ -125,10 +126,19 @@ void MainWindow::SlotExcepConOffline() // 使用静态方法直接弹出一个信息框 QMessageBox::information(this, "下线提示", "心跳超时或临界异常,该终端下线!"); TcpMgr::GetInstance()->CloseConnection(); + FileTcpMgr::GetInstance()->CloseConnection(); offlineLogin(); } +void MainWindow::SlotResServerConOffline(){ + // 使用静态方法直接弹出一个信息框 + QMessageBox::information(this, "下线提示", "与资源服务器断开连接!"); + TcpMgr::GetInstance()->CloseConnection(); + FileTcpMgr::GetInstance()->CloseConnection(); + offlineLogin(); +} + void MainWindow::offlineLogin(){ if(_ui_status == LOGIN_UI){ return; diff --git a/client/llfcchat/mainwindow.h b/client/llfcchat/mainwindow.h index e2597fc..520660c 100644 --- a/client/llfcchat/mainwindow.h +++ b/client/llfcchat/mainwindow.h @@ -41,6 +41,7 @@ public slots: void SlotSwitchChat(); void SlotOffline(); void SlotExcepConOffline(); + void SlotResServerConOffline(); private: void offlineLogin(); diff --git a/client/llfcchat/tcpmgr.cpp b/client/llfcchat/tcpmgr.cpp index f110078..5e68c25 100644 --- a/client/llfcchat/tcpmgr.cpp +++ b/client/llfcchat/tcpmgr.cpp @@ -1,23 +1,25 @@ #include "tcpmgr.h" #include #include "usermgr.h" +#include +#include +#include +#include -TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_message_len(0) +TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_message_len(0),_bytes_sent(0),_pending(false) { - QObject::connect(&_socket, &QTcpSocket::connected, [&]() { + registerMetaType(); + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { qDebug() << "Connected to server!"; // 连接建立后发送消息 emit sig_con_success(true); }); - QObject::connect(&_socket, &QTcpSocket::readyRead, [&]() { + QObject::connect(&_socket, &QTcpSocket::readyRead, this, [&]() { // 当有数据可读时,读取所有数据 // 读取所有数据并追加到缓冲区 _buffer.append(_socket.readAll()); - QDataStream stream(&_buffer, QIODevice::ReadOnly); - stream.setVersion(QDataStream::Qt_5_0); - forever { //先解析头部 if(!_b_recv_pending){ @@ -26,13 +28,11 @@ TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_messa return; // 数据不够,等待更多数据 } - // 预读取消息ID和消息长度,但不从缓冲区中移除 + // ✅ 每次都重新创建stream + QDataStream stream(_buffer); + stream.setVersion(QDataStream::Qt_5_0); stream >> _message_id >> _message_len; - - //将buffer 中的前四个字节移除 - _buffer = _buffer.mid(sizeof(quint16) * 2); - - // 输出读取的数据 + _buffer.remove(0, sizeof(quint16) * 2); // 使用remove代替mid赋值 qDebug() << "Message ID:" << _message_id << ", Length:" << _message_len; } @@ -62,6 +62,7 @@ TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_messa // 处理错误(适用于Qt 5.15之前的版本) QObject::connect(&_socket, static_cast(&QTcpSocket::error), + this, [&](QTcpSocket::SocketError socketError) { qDebug() << "Error:" << _socket.errorString() ; switch (socketError) { @@ -90,24 +91,94 @@ TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_messa }); // 处理连接断开 - QObject::connect(&_socket, &QTcpSocket::disconnected, [&]() { + QObject::connect(&_socket, &QTcpSocket::disconnected, this,[&]() { qDebug() << "Disconnected from server."; //并且发送通知到界面 emit sig_connection_closed(); }); //连接发送信号用来发送数据 QObject::connect(this, &TcpMgr::sig_send_data, this, &TcpMgr::slot_send_data); + + //连接发送信号 + QObject::connect(&_socket, &QTcpSocket::bytesWritten, this, [this](qint64 bytes) { + //更新发送数据 + _bytes_sent += bytes; + //未发送完整 + if (_bytes_sent < _current_block.size()) { + //继续发送 + auto data_to_send = _current_block.mid(_bytes_sent); + _socket.write(data_to_send); + return; + } + + //发送完全,则查看队列是否为空 + if (_send_queue.isEmpty()) { + //队列为空,说明已经将所有数据发送完成,将pending设置为false,这样后续要发送数据时可以继续发送 + _current_block.clear(); + _pending = false; + _bytes_sent = 0; + return; + } + + //队列不为空,则取出队首元素 + _current_block = _send_queue.dequeue(); + _bytes_sent = 0; + _pending = true; + qint64 w2 = _socket.write(_current_block); + qDebug() << "[TcpMgr] Dequeued and write() returned" << w2; + }); + + + //关闭socket + connect(this, &TcpMgr::sig_close, this, &TcpMgr::slot_tcp_close); //注册消息 initHandlers(); + +} + +void TcpMgr::registerMetaType() { + // 注册所有自定义类型 + qRegisterMetaType("ServerInfo"); + qRegisterMetaType("SearchInfo"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AddFriendApply"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("ApplyInfo"); + + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AuthRsp"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("UserInfo"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("ReqId"); + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType>>("std::vector>"); } void TcpMgr::CloseConnection(){ - _socket.close(); + emit sig_close(); } +void TcpMgr::SendData(ReqId reqId, QByteArray data) +{ + emit sig_send_data(reqId, data); +} + + + TcpMgr::~TcpMgr(){ } + void TcpMgr::initHandlers() { //auto self = shared_from_this(); @@ -251,6 +322,7 @@ void TcpMgr::initHandlers() if (jsonDoc.isNull()) { qDebug() << "Failed to create QJsonDocument."; return; + } QJsonObject jsonObj = jsonDoc.object(); @@ -656,7 +728,7 @@ void TcpMgr::initHandlers() int last_msg_id = jsonObj["last_message_id"].toInt(); bool load_more = jsonObj["load_more"].toBool(); - std::vector> chat_datas; + std::vector> chat_datas; for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { auto send_uid = data["sender"].toInt(); auto msg_id = data["msg_id"].toInt(); @@ -665,14 +737,283 @@ void TcpMgr::initHandlers() auto msg_content = data["msg_content"].toString(); QString chat_time = data["chat_time"].toString(); int status = data["status"].toInt(); - auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, - ChatMsgType::TEXT, msg_content, send_uid, status,chat_time); - chat_datas.push_back(chat_data); + int msg_type = data["msg_type"].toInt(); + int recv_id = data["receiver"].toInt(); + if (msg_type == int(ChatMsgType::TEXT)) { + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + + if (msg_type == int(ChatMsgType::PIC)) { + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(send_uid); + QString img_path = img_path_str + "/" + msg_content; + //文件不存在,则创建空白图片占位,同时组织数据准备发送 + if (QFile::exists(img_path) == false) { + + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + //如果文件存在 + //如果文件存在则直接构建MsgInfo + // 获取文件大小 + QFileInfo fileInfo(img_path); + qint64 file_size = fileInfo.size(); + //从文件路径加载QPixmap + QPixmap pixmap(img_path); + //如果图片加载失败,也是创建占位符,然后组织发送 + if (pixmap.isNull()) { + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + + //说明图片加载正确,构建真实图片 + auto file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, + pixmap, msg_content, file_size, ""); + file_info->_msg_id = msg_id; + file_info->_sender = send_uid; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::None; + //放入chat_datas列表 + auto chat_data = std::make_shared(file_info,"", thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } } //发送信号通知界面 emit sig_load_chat_msg(thread_id, last_msg_id, load_more, chat_datas); }); + + _handlers.insert(ID_IMG_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto unique_id = jsonObj["unique_id"].toString(); + auto unique_name = jsonObj["unique_name"].toString(); + + auto sender = jsonObj["fromuid"].toInt(); + auto msg_id = jsonObj["message_id"].toInt(); + QString chat_time = jsonObj["chat_time"].toString(); + int status = jsonObj["status"].toInt(); + auto text_or_url = jsonObj["text_or_url"].toString(); + auto receiver = jsonObj["touid"].toInt(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + //如果未找到文件对应的信息则返回 + if (!file_info) { + return; + } + //设置消息id和会话id + file_info->_msg_id = msg_id; + file_info->_thread_id = thread_id; + //设置发送者和接收者 + file_info->_sender = sender; + file_info->_receiver = receiver; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Upload; + //设置文件传输状态 + file_info->_transfer_state = TransferState::Uploading; + + auto chat_data = std::make_shared(file_info, unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, sender, status, chat_time); + + //更新msg_id,因为最开始构造的chat_dat中ImgChatData的msg_id为空 + chat_data->SetMsgId(msg_id); + + //发送信号通知界面 + emit sig_chat_img_rsp(thread_id, chat_data); + + //管理消息,添加序列号到正在发送集合 + file_info->_flighting_seqs.insert(file_info->_seq); + + //发送消息 + QFile file(file_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + file.seek(file_info->_current_size); + auto buffer = file.read(MAX_FILE_LEN); + qDebug() << "buffer is " << buffer; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + QJsonObject file_obj; + file_obj["name"] = file_info->_unique_name; + file_obj["unique_id"] = unique_id; + file_obj["seq"] = file_info->_seq; + file_info->_current_size = buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN; + file_obj["trans_size"] = QString::number(file_info->_current_size); + file_obj["total_size"] = QString::number(file_info->_total_size); + file_obj["token"] = UserMgr::GetInstance()->GetToken(); + file_obj["md5"] = file_info->_md5; + file_obj["uid"] = UserMgr::GetInstance()->GetUid(); + file_obj["data"] = base64Data; + file_obj["message_id"] = msg_id; + file_obj["receiver"] = receiver; + file_obj["sender"] = sender; + + if (buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN >= file_info->_total_size) { + file_obj["last"] = 1; + } + else { + file_obj["last"] = 0; + } + + //发送文件 todo 留作以后收到服务器返回消息后再发送 + QJsonDocument doc_file(file_obj); + QByteArray fileData = doc_file.toJson(QJsonDocument::Compact); + + //发送消息给ResourceServer + FileTcpMgr::GetInstance()->SendData(ReqId::ID_FILE_INFO_SYNC_REQ, fileData); + + }); + + + _handlers.insert(ID_NOTIFY_IMG_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + qDebug() << "receive notify img chat msg req success" ; + + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto sender_id = jsonObj["sender_id"].toInt(); + auto message_id = jsonObj["message_id"].toInt(); + auto receiver_id = jsonObj["receiver_id"].toInt(); + auto img_name = jsonObj["img_name"].toString(); + auto total_size_str = jsonObj["total_size"].toString(); + auto total_size = total_size_str.toLongLong(); + auto uid = UserMgr::GetInstance()->GetUid(); + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir +"/user/"+ QString::number(uid)+ "/chatimg/" + QString::number(sender_id); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(img_name); + //正常情况是找不到的,所以这里初始化一个文件信息放入UserMgr中管理 + if (!file_info) { + //预览图先默认空白,md5为空 + file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, CreateLoadingPlaceholder(200, 200), img_name, total_size, ""); + UserMgr::GetInstance()->AddTransFile(img_name, file_info); + } + + file_info->_msg_id = message_id; + file_info->_sender = sender_id; + file_info->_receiver = receiver_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::Downloading; + + auto img_chat_data_ptr = std::make_shared(file_info, "", + thread_id, ChatFormType::PRIVATE, ChatMsgType::PIC, + sender_id, MsgStatus::READED); + + //发送给界面显示 + emit sig_img_chat_msg(img_chat_data_ptr); + + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = img_name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = "0"; + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = sender_id; + jsonObj_send["receiver_id"] = receiver_id; + jsonObj_send["message_id"] = message_id; + jsonObj_send["uid"] = uid; + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QDir chatimgDir(img_path_str); + jsonObj["client_path"] = img_path_str; + if (!chatimgDir.exists()) { + chatimgDir.mkpath("."); // 创建当前路径 + } + + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + }); + +} + +void TcpMgr::CreatePlaceholderImgMsgL(QString img_path_str, QString msg_content, + int msg_id, int thread_id, int send_uid, int recv_id, int status, QString chat_time, + std::vector> &chat_datas) { + //如果加载失败,则使用占位符使图片变为空白,并且md5为空 + auto file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, + CreateLoadingPlaceholder(200, 200), msg_content, 0, ""); + file_info->_msg_id = msg_id; + file_info->_sender = send_uid; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::Downloading; + file_info->_rsp_size = file_info->_current_size; + //放入chat_datas列表 + auto chat_data = std::make_shared(file_info, "", thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + //加入下载列表,并且发送下载请求 + UserMgr::GetInstance()->AddTransFile(msg_content, file_info); + + QJsonObject jsonObj_send; + jsonObj_send["message_id"] = file_info->_msg_id; + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + // 从服务器获取文件大小,然后请求下载 + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_INFO_SYNC_REQ, send_data); } void TcpMgr::handleMsg(ReqId id, int len, QByteArray data) @@ -686,14 +1027,18 @@ void TcpMgr::handleMsg(ReqId id, int len, QByteArray data) find_iter.value()(id,len,data); } -void TcpMgr::slot_tcp_connect(ServerInfo si) +void TcpMgr::slot_tcp_close() { + _socket.close(); +} + +void TcpMgr::slot_tcp_connect(std::shared_ptr si) { qDebug()<< "receive tcp connect signal"; // 尝试连接到服务器 - qDebug() << "Connecting to server..."; - _host = si.Host; - _port = static_cast(si.Port.toUInt()); - _socket.connectToHost(si.Host, _port); + qDebug() << "Connecting to chat server..."; + _host = si->_chat_host; + _port = static_cast(si->_chat_port.toUInt()); + _socket.connectToHost(_host, _port); } void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes) @@ -716,9 +1061,33 @@ void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes) // 添加字符串数据 block.append(dataBytes); - // 发送数据 - _socket.write(block); - qDebug() << "tcp mgr send byte data is " << block ; + //判断是否正在发送 + if (_pending) { + //放入队列直接返回,因为目前有数据正在发送 + _send_queue.enqueue(block); + return; + } + + // 没有正在发送,把这包设为“当前块”,重置计数,并写出去 + _current_block = block; // ← 保存当前正在发送的 block + _bytes_sent = 0; // ← 归零 + _pending = true; // ← 标记正在发送 + + qint64 written = _socket.write(_current_block); + /* qDebug() << "tcp mgr send byte data is" << _current_block + << ", write() returned" << written;*/ } +TcpThread::TcpThread() +{ + _tcp_thread = new QThread(); + TcpMgr::GetInstance()->moveToThread(_tcp_thread); + QObject::connect(_tcp_thread, &QThread::finished, _tcp_thread, &QObject::deleteLater); + + _tcp_thread->start(); +} +TcpThread::~TcpThread() +{ + _tcp_thread->quit(); +} diff --git a/client/llfcchat/tcpmgr.h b/client/llfcchat/tcpmgr.h index 4e909b5..28c2a10 100644 --- a/client/llfcchat/tcpmgr.h +++ b/client/llfcchat/tcpmgr.h @@ -1,4 +1,4 @@ -#ifndef TCPMGR_H +#ifndef TCPMGR_H #define TCPMGR_H #include #include "singleton.h" @@ -8,6 +8,16 @@ #include "userdata.h" #include #include +#include +#include + +class TcpThread:public std::enable_shared_from_this { +public: + TcpThread(); + ~TcpThread(); +private: + QThread* _tcp_thread; +}; class TcpMgr:public QObject, public Singleton, public std::enable_shared_from_this @@ -16,11 +26,17 @@ class TcpMgr:public QObject, public Singleton, public: ~ TcpMgr(); void CloseConnection(); + void SendData(ReqId reqId, QByteArray data); + private: friend class Singleton; TcpMgr(); + void registerMetaType(); void initHandlers(); void handleMsg(ReqId id, int len, QByteArray data); + void CreatePlaceholderImgMsgL(QString img_path_str, QString msg_content, + int msg_id, int thread_id, int send_uid, int recv_id, int status, QString chat_time, + std::vector>& chat_datas); QTcpSocket _socket; QString _host; uint16_t _port; @@ -29,10 +45,24 @@ class TcpMgr:public QObject, public Singleton, quint16 _message_id; quint16 _message_len; QMap> _handlers; + //发送队列 + QQueue _send_queue; + //正在发送的包 + QByteArray _current_block; + //当前已发送的字节数 + qint64 _bytes_sent; + //是否正在发送 + bool _pending; public slots: - void slot_tcp_connect(ServerInfo); + void slot_tcp_close(); + void slot_tcp_connect(std::shared_ptr si); void slot_send_data(ReqId reqId, QByteArray data); + void slot_test() { + qDebug() << "receve thread is " << QThread::currentThread(); + qDebug() << "slot test......"; + } signals: + void sig_close(); void sig_con_success(bool bsuccess); void sig_send_data(ReqId reqId, QByteArray data); void sig_swich_chatdlg(); @@ -49,9 +79,11 @@ public slots: std::vector> chat_list); void sig_create_private_chat(int uid, int other_id, int thread_id); void sig_load_chat_msg(int thread_id, int message_id, bool load_more, - std::vector> msg_list); + std::vector> msg_list); void sig_chat_msg_rsp(int thread_id, std::vector> msg_list); + void sig_chat_img_rsp(int thread_id, std::shared_ptr msg_list); + void sig_img_chat_msg(std::shared_ptr msg_list); }; #endif // TCPMGR_H diff --git a/client/llfcchat/userdata.cpp b/client/llfcchat/userdata.cpp index dc42d1c..61c5e7d 100644 --- a/client/llfcchat/userdata.cpp +++ b/client/llfcchat/userdata.cpp @@ -1,4 +1,6 @@ -#include "userdata.h" +#include "userdata.h" +#include + SearchInfo::SearchInfo(int uid, QString name, QString nick, QString desc, int sex, QString icon):_uid(uid) ,_name(name), _nick(nick),_desc(desc),_sex(sex),_icon(icon){ @@ -60,11 +62,25 @@ void ChatThreadData::MoveMsg(std::shared_ptr msg) { } iter.value()->SetMsgId(msg->GetMsgId()); - iter.value()->SetStatus(2); + iter.value()->SetStatus(msg->GetStatus()); AddMsg(iter.value()); _msg_unrsp_map.erase(iter); } +void ChatThreadData::UpdateProgress(std::shared_ptr msg) { + auto iter = _msg_map.find(msg->_msg_id); + if (iter == _msg_map.end()) { + return; + } + + //更新进度信息,根据消息类型转化为具体类型 + if (msg->_msg_type == MsgType::IMG_MSG) { + auto img_chat_data = std::dynamic_pointer_cast(iter.value()); + img_chat_data->_msg_info->_rsp_size = msg->_rsp_size; + img_chat_data->_msg_info->_current_size = msg->_current_size; + } +} + void ChatThreadData::SetLastMsgId(int msg_id) { _last_msg_id = msg_id; @@ -134,4 +150,13 @@ void AuthInfo::SetChatDatas(std::vector> chat_data void AuthRsp::SetChatDatas(std::vector> chat_datas) { _chat_datas = chat_datas; _thread_id = _chat_datas[0]->GetThreadId(); +} + +std::shared_ptr ChatThreadData::GetChatDataBase(int msg_id) { + auto iter = _msg_map.find(msg_id); + if (iter == _msg_map.end()) { + return nullptr; + } + + return iter.value(); } \ No newline at end of file diff --git a/client/llfcchat/userdata.h b/client/llfcchat/userdata.h index b9434a5..482db45 100644 --- a/client/llfcchat/userdata.h +++ b/client/llfcchat/userdata.h @@ -1,4 +1,4 @@ -#ifndef USERDATA_H +#ifndef USERDATA_H #define USERDATA_H #include #include @@ -11,6 +11,7 @@ class SearchInfo { public: SearchInfo(int uid, QString name, QString nick, QString desc, int sex, QString icon); + SearchInfo() = default; int _uid; QString _name; QString _nick; @@ -19,10 +20,14 @@ class SearchInfo { QString _icon; }; +Q_DECLARE_METATYPE(SearchInfo) +Q_DECLARE_METATYPE(std::shared_ptr) + class AddFriendApply { public: AddFriendApply(int from_uid, QString name, QString desc, QString icon, QString nick, int sex); + AddFriendApply() = default; int _from_uid; QString _name; QString _desc; @@ -31,7 +36,10 @@ class AddFriendApply { int _sex; }; +Q_DECLARE_METATYPE(std::shared_ptr) + struct ApplyInfo { + ApplyInfo() = default; ApplyInfo(int uid, QString name, QString desc, QString icon, QString nick, int sex, int status) :_uid(uid),_name(name),_desc(desc), @@ -61,7 +69,7 @@ struct AuthInfo { QString nick, QString icon, int sex): _uid(uid), _name(name), _nick(nick), _icon(icon), _sex(sex), _thread_id(0){} - + AuthInfo() = default; void SetChatDatas(std::vector> _chat_datas); int _uid; QString _name; @@ -72,7 +80,10 @@ struct AuthInfo { std::vector> _chat_datas; }; +Q_DECLARE_METATYPE(std::shared_ptr) + struct AuthRsp { + AuthRsp() = default; AuthRsp(int peer_uid, QString peer_name, QString peer_nick, QString peer_icon, int peer_sex) :_uid(peer_uid),_name(peer_name),_nick(peer_nick), @@ -92,6 +103,8 @@ struct AuthRsp { std::vector> _chat_datas; }; +Q_DECLARE_METATYPE(std::shared_ptr) + struct UserInfo { UserInfo(int uid, QString name, QString nick, QString icon, int sex, QString last_msg = "", QString desc=""): _uid(uid),_name(name),_nick(nick),_icon(icon),_sex(sex),_desc(desc){} @@ -116,6 +129,8 @@ struct UserInfo { } + UserInfo() = default; + int _uid; QString _name; QString _nick; @@ -124,8 +139,11 @@ struct UserInfo { QString _desc; }; +Q_DECLARE_METATYPE(std::shared_ptr) + class ChatDataBase { public: + ChatDataBase() = default; ChatDataBase(int msg_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, QString content,int _send_uid, int status, QString chat_time ); ChatDataBase(QString unique_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, @@ -144,26 +162,29 @@ class ChatDataBase { int GetStatus() { return _status; } void SetMsgId(int msg_id) { _msg_id = msg_id; } void SetStatus(int status) { _status = status; } -private: - //ͻ˱Ψһʶ + virtual ~ChatDataBase() {} // 添加虚析构函数 +protected: + //客户端本地唯一标识 QString _unique_id; - //Ϣid + //消息id int _msg_id; - //Ựid + //会话id int _thread_id; - //ȺĻ˽ + //群聊还是私聊 ChatFormType _form_type; - //ıϢΪ0ͼƬΪ1ļΪ2 + //文本信息为0,图片为1,文件为2 ChatMsgType _msg_type; QString _content; - //id + //发送者id int _send_uid; - //״̬ + //状态 int _status; - //ʱ + //聊天时间 QString _chat_time; }; +Q_DECLARE_METATYPE(std::vector>) + class TextChatData : public ChatDataBase { public: @@ -183,28 +204,55 @@ class TextChatData : public ChatDataBase { TextChatData(int msg_id, QString unique_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, QString content, int send_uid, int status, QString chat_time = "") : - ChatDataBase(unique_id, thread_id, form_type, msg_type, content, send_uid, status, chat_time) + ChatDataBase(msg_id, unique_id, thread_id, form_type, msg_type, content, send_uid, status, chat_time) { } + TextChatData() = default; + + ~TextChatData() override{} }; -//߳Ϣ +Q_DECLARE_METATYPE(std::vector>) + +class ImgChatData : public ChatDataBase { +public: + ImgChatData(std::shared_ptr msg_info, QString unique_id, + int thread_id, ChatFormType form_type, ChatMsgType msg_type, + int send_uid, int status, QString chat_time = ""): + ChatDataBase(unique_id,thread_id, form_type, msg_type, msg_info->_text_or_url, + send_uid, status, chat_time), _msg_info(msg_info){ + _msg_id = _msg_info->_msg_id; + } + + ~ImgChatData() override {} + + std::shared_ptr _msg_info; +}; + +Q_DECLARE_METATYPE(std::shared_ptr) + +//聊天线程信息 struct ChatThreadInfo { int _thread_id; QString _type; // "private" or "group" - int _user1_id; // ˽ʱӦ private_chat.user1_idȺʱΪ 0 - int _user2_id; // ˽ʱӦ private_chat.user2_idȺʱΪ 0 + int _user1_id; // 私聊时对应 private_chat.user1_id;群聊时设为 0 + int _user2_id; // 私聊时对应 private_chat.user2_id;群聊时设为 0 + ChatThreadInfo() = default; }; -//ͻ˱ش洢߳ݽṹ +Q_DECLARE_METATYPE(std::vector>) + +//客户端本地存储的聊天线程数据结构 class ChatThreadData { public: + ChatThreadData() = default; ChatThreadData(int other_id, int thread_id, int last_msg_id): _other_id(other_id), _thread_id(thread_id), _last_msg_id(last_msg_id){} void AddMsg(std::shared_ptr msg); void MoveMsg(std::shared_ptr msg); + void UpdateProgress(std::shared_ptr msg); void SetLastMsgId(int msg_id); void SetOtherId(int other_id); int GetOtherId(); @@ -217,20 +265,21 @@ class ChatThreadData { int GetLastMsgId(); QMap>& GetMsgUnRspRef(); void AppendUnRspMsg(QString unique_id, std::shared_ptr base_msg); + std::shared_ptr GetChatDataBase(int msg_id); private: - //˽ģΪԷidȺģΪ0 + //如果是私聊,则为对方的id;如果是群聊,则为0 int _other_id; int _last_msg_id; int _thread_id; QString _last_msg; - //ȺϢ,Աб + //群聊信息,成员列表 std::vector _group_members; - //Ⱥ + //群聊名称 QString _group_name; - //ϢmapΪ࣬ΪͼƬϢ + //缓存消息map,抽象为基类,因为会有图片等其他类型消息 QMap> _msg_map; - //δظϢ - //ѷ͵ϢδյӦġ + //缓存未回复的消息 + //已发送的消息,还未收到回应的。 QMap> _msg_unrsp_map; }; diff --git a/client/llfcchat/userinfopage.cpp b/client/llfcchat/userinfopage.cpp index e7ba80c..7f8ab77 100644 --- a/client/llfcchat/userinfopage.cpp +++ b/client/llfcchat/userinfopage.cpp @@ -8,6 +8,11 @@ #include #include #include +#include "usermgr.h" +#include "tcpmgr.h" +#include "filetcpmgr.h" +#include "global.h" +#include UserInfoPage::UserInfoPage(QWidget *parent) : QWidget(parent), @@ -16,10 +21,60 @@ UserInfoPage::UserInfoPage(QWidget *parent) : ui->setupUi(this); auto icon = UserMgr::GetInstance()->GetIcon(); qDebug() << "icon is " << icon ; - QPixmap pixmap(icon); - QPixmap scaledPixmap = pixmap.scaled( ui->head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 - ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 - ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + //使用正则表达式检查是否使用默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(icon); + if (match.hasMatch()) { + QPixmap pixmap(icon); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(uid) + "/avatars"); + // 确保目录存在 + if (avatarsDir.exists()) { + auto file_name = QFileInfo(icon).fileName(); + QString avatarPath = avatarsDir.filePath(QFileInfo(icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + } + else { + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + LoadHeadIcon(avatarPath, ui->head_lb, file_name,"self_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + + //获取nick auto nick = UserMgr::GetInstance()->GetNick(); //获取name @@ -29,6 +84,8 @@ UserInfoPage::UserInfoPage(QWidget *parent) : ui->nick_ed->setText(nick); ui->name_ed->setText(name); ui->desc_ed->setText(desc); + //连接上 + connect(ui->up_btn, &QPushButton::clicked, this, &UserInfoPage::slot_up_load); } UserInfoPage::~UserInfoPage() @@ -36,8 +93,38 @@ UserInfoPage::~UserInfoPage() delete ui; } +void UserInfoPage::LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type) { + UserMgr::GetInstance()->AddLabelToReset(avatarPath, ui->head_lb); + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + } + else { + //发送请求获取资源 + auto download_info = std::make_shared(); + download_info->_name = file_name; + download_info->_current_size = 0; + download_info->_seq = 1; + download_info->_total_size = 0; + download_info->_client_path = avatarPath; + //添加文件到管理者 + UserMgr::GetInstance()->AddDownloadFile(file_name, download_info); + //发送消息 + FileTcpMgr::GetInstance()->SendDownloadInfo(download_info, req_type); + } + +} + //上传头像 -void UserInfoPage::on_up_btn_clicked() +void UserInfoPage::slot_up_load() { // 1. 让对话框也能选 *.webp QString filename = QFileDialog::getOpenFileName( @@ -71,6 +158,8 @@ void UserInfoPage::on_up_btn_clicked() QString storageDir = QStandardPaths::writableLocation( QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + storageDir = storageDir + "/" + QString::number(uid); // 2. 在其下再建一个 avatars 子目录 QDir dir(storageDir); if (!dir.exists("avatars")) { @@ -85,7 +174,9 @@ void UserInfoPage::on_up_btn_clicked() } } // 3. 拼接最终的文件名 head.png - QString filePath = dir.filePath("avatars/head.png"); + QString file_name = generateUniqueIconName(); + QString filePath = dir.filePath("avatars" + + QString(QDir::separator()) + file_name); // 4. 保存 scaledPixmap 为 PNG(无损、最高质量) if (!scaledPixmap.save(filePath, "PNG")) { @@ -98,4 +189,88 @@ void UserInfoPage::on_up_btn_clicked() qDebug() << "头像已保存到:" << filePath; // 以后读取直接用同一路径:storageDir/avatars/head.png } + + //实现头像上传 + QFile file(filePath); + if(!file.open(QIODevice::ReadOnly)){ + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + //保存当前文件位置指针 + qint64 originalPos = file.pos(); + + QCryptographicHash hash(QCryptographicHash::Md5); + if (!hash.addData(&file)) { + qWarning() << "Failed to read data from file:" << filePath; + return ; + } + + // 5. 转化为16进制字符串 + QString file_md5 = hash.result().toHex(); // 返回十六进制字符串 + + //读取文件内容并发送 + QByteArray buffer; + int seq = 0; + + //创建QFileInfo 对象 + auto fileInfo = std::make_shared(filePath); + //获取文件名 + QString fileName = fileInfo->fileName(); + //文件名 + qDebug() << "文件名是: " << fileName; + + //获取文件大小 + int total_size = fileInfo->size(); + //最后一个发送序列 + int last_seq = 0; + //获取最后一个发送序列 + if(total_size % MAX_FILE_LEN){ + last_seq = (total_size / MAX_FILE_LEN) +1; + }else{ + last_seq = total_size / MAX_FILE_LEN; + } + + // 恢复文件指针到原来的位置 + file.seek(originalPos); + + //每次读取MAX_FILE_LEN字节并发送 + buffer = file.read(MAX_FILE_LEN); + + QJsonObject jsonObj; + //将文件内容转化为Base64 编码(可选) + QString base64Data = buffer.toBase64(); + ++seq; + jsonObj["md5"] = file_md5; + jsonObj["name"] = file_name; + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq - 1) * MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + jsonObj["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj["uid"] = UserMgr::GetInstance()->GetUid(); + + if (buffer.size() + (seq - 1) * MAX_FILE_LEN == total_size) { + jsonObj["last"] = 1; + } else { + jsonObj["last"] = 0; + } + + jsonObj["data"] = base64Data; + jsonObj["last_seq"] = last_seq; + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + //设置Icon + UserMgr::GetInstance()->SetIcon(file_name); + //将md5信息和文件信息关联存储 + UserMgr::GetInstance()->AddUploadFile(file_name, fileInfo); + //发送消息 + FileTcpMgr::GetInstance()->SendData(ID_UPLOAD_HEAD_ICON_REQ, send_data); + file.close(); + emit sig_reset_head(); } + + + + + + diff --git a/client/llfcchat/userinfopage.h b/client/llfcchat/userinfopage.h index 75e8d87..adc7b1d 100644 --- a/client/llfcchat/userinfopage.h +++ b/client/llfcchat/userinfopage.h @@ -2,6 +2,7 @@ #define USERINFOPAGE_H #include +#include namespace Ui { class UserInfoPage; @@ -14,12 +15,16 @@ class UserInfoPage : public QWidget public: explicit UserInfoPage(QWidget *parent = nullptr); ~UserInfoPage(); - + void LoadHeadIcon(QString avatarPath, QLabel* icon_label, QString file_name, QString req_type); +protected: private slots: - void on_up_btn_clicked(); + void slot_up_load(); private: Ui::UserInfoPage *ui; + +signals: + void sig_reset_head(); }; #endif // USERINFOPAGE_H diff --git a/client/llfcchat/usermgr.cpp b/client/llfcchat/usermgr.cpp index eecc61a..330696b 100644 --- a/client/llfcchat/usermgr.cpp +++ b/client/llfcchat/usermgr.cpp @@ -8,41 +8,59 @@ UserMgr::~UserMgr() } void UserMgr::SetUserInfo(std::shared_ptr user_info) { + std::lock_guard lock(_mtx); _user_info = user_info; } void UserMgr::SetToken(QString token) { + std::lock_guard lock(_mtx); _token = token; } +QString UserMgr::GetToken(){ + std::lock_guard lock(_mtx); + return _token; +} + int UserMgr::GetUid() { + std::lock_guard lock(_mtx); return _user_info->_uid; } QString UserMgr::GetName() { + std::lock_guard lock(_mtx); return _user_info->_name; } QString UserMgr::GetNick() { + std::lock_guard lock(_mtx); return _user_info->_nick; } QString UserMgr::GetIcon() { + std::lock_guard lock(_mtx); return _user_info->_icon; } +void UserMgr::SetIcon(QString name) { + std::lock_guard lock(_mtx); + _user_info->_icon = name; +} + QString UserMgr::GetDesc() { + std::lock_guard lock(_mtx); return _user_info->_desc; } std::shared_ptr UserMgr::GetUserInfo() { + std::lock_guard lock(_mtx); return _user_info; } @@ -59,6 +77,7 @@ void UserMgr::AppendApplyList(QJsonArray array) auto status = value["status"].toInt(); auto info = std::make_shared(uid, name, desc, icon, nick, sex, status); + std::lock_guard lock(_mtx); _apply_list.push_back(info); } } @@ -76,6 +95,7 @@ void UserMgr::AppendFriendList(QJsonArray array) { auto info = std::make_shared(uid, name, nick, icon, sex, desc, back); + std::lock_guard lock(_mtx); _friend_list.push_back(info); _friend_map.insert(uid, info); } @@ -83,16 +103,19 @@ void UserMgr::AppendFriendList(QJsonArray array) { std::vector > UserMgr::GetApplyList() { + std::lock_guard lock(_mtx); return _apply_list; } void UserMgr::AddApplyList(std::shared_ptr app) { + std::lock_guard lock(_mtx); _apply_list.push_back(app); } bool UserMgr::AlreadyApply(int uid) { + std::lock_guard lock(_mtx); for(auto& apply: _apply_list){ if(apply->_uid == uid){ return true; @@ -103,7 +126,7 @@ bool UserMgr::AlreadyApply(int uid) } std::vector> UserMgr::GetChatListPerPage() { - + std::lock_guard lock(_mtx); std::vector> friend_list; int begin = _chat_loaded; int end = begin + CHAT_COUNT_PER_PAGE; @@ -124,6 +147,7 @@ std::vector> UserMgr::GetChatListPerPage() { std::vector> UserMgr::GetConListPerPage() { + std::lock_guard lock(_mtx); std::vector> friend_list; int begin = _contact_loaded; int end = begin + CHAT_COUNT_PER_PAGE; @@ -159,6 +183,7 @@ void UserMgr::SlotAddFriendAuth(std::shared_ptr auth) } bool UserMgr::IsLoadChatFin() { + std::lock_guard lock(_mtx); if (_chat_loaded >= _friend_list.size()) { return true; } @@ -167,6 +192,7 @@ bool UserMgr::IsLoadChatFin() { } void UserMgr::UpdateChatLoadedCount() { + std::lock_guard lock(_mtx); int begin = _chat_loaded; int end = begin + CHAT_COUNT_PER_PAGE; @@ -183,6 +209,7 @@ void UserMgr::UpdateChatLoadedCount() { } void UserMgr::UpdateContactLoadedCount() { + std::lock_guard lock(_mtx); int begin = _contact_loaded; int end = begin + CHAT_COUNT_PER_PAGE; @@ -200,6 +227,7 @@ void UserMgr::UpdateContactLoadedCount() { bool UserMgr::IsLoadConFin() { + std::lock_guard lock(_mtx); if (_contact_loaded >= _friend_list.size()) { return true; } @@ -209,6 +237,7 @@ bool UserMgr::IsLoadConFin() bool UserMgr::CheckFriendById(int uid) { + std::lock_guard lock(_mtx); auto iter = _friend_map.find(uid); if(iter == _friend_map.end()){ return false; @@ -219,18 +248,21 @@ bool UserMgr::CheckFriendById(int uid) void UserMgr::AddFriend(std::shared_ptr auth_rsp) { + std::lock_guard lock(_mtx); auto friend_info = std::make_shared(auth_rsp); _friend_map[friend_info->_uid] = friend_info; } void UserMgr::AddFriend(std::shared_ptr auth_info) { + std::lock_guard lock(_mtx); auto friend_info = std::make_shared(auth_info); _friend_map[friend_info->_uid] = friend_info; } std::shared_ptr UserMgr::GetFriendById(int uid) { + std::lock_guard lock(_mtx); auto find_it = _friend_map.find(uid); if(find_it == _friend_map.end()){ return nullptr; @@ -243,16 +275,19 @@ std::shared_ptr UserMgr::GetFriendById(int uid) int UserMgr::GetLastChatThreadId() { + std::lock_guard lock(_mtx); return _last_chat_thread_id; } void UserMgr::SetLastChatThreadId(int id) { + std::lock_guard lock(_mtx); _last_chat_thread_id = id; } void UserMgr::AddChatThreadData(std::shared_ptr chat_thread_data, int other_uid) { + std::lock_guard lock(_mtx); //建立会话id到数据的映射关系 _chat_map[chat_thread_data->GetThreadId()] = chat_thread_data; //存储会话列表 @@ -265,6 +300,7 @@ void UserMgr::AddChatThreadData(std::shared_ptr chat_thread_data int UserMgr::GetThreadIdByUid(int uid) { + std::lock_guard lock(_mtx); auto iter = _uid_to_thread_id.find(uid); if (iter == _uid_to_thread_id.end()){ return -1; @@ -275,6 +311,7 @@ int UserMgr::GetThreadIdByUid(int uid) std::shared_ptr UserMgr::GetChatThreadByThreadId(int thread_id) { + std::lock_guard lock(_mtx); auto find_iter = _chat_map.find(thread_id); if (find_iter != _chat_map.end()) { return find_iter.value(); @@ -283,6 +320,7 @@ std::shared_ptr UserMgr::GetChatThreadByThreadId(int thread_id) } std::shared_ptr UserMgr::GetChatThreadByUid(int uid) { + std::lock_guard lock(_mtx); auto iter = _uid_to_thread_id.find(uid); if (iter == _uid_to_thread_id.end()) { return nullptr; @@ -300,6 +338,7 @@ std::shared_ptr UserMgr::GetChatThreadByUid(int uid) { std::shared_ptr UserMgr::GetCurLoadData() { + std::lock_guard lock(_mtx); if (_cur_load_chat_index >= _chat_thread_ids.size()) { return nullptr; } @@ -313,6 +352,7 @@ std::shared_ptr UserMgr::GetCurLoadData() } std::shared_ptr UserMgr::GetNextLoadData() { + std::lock_guard lock(_mtx); _cur_load_chat_index++; if (_cur_load_chat_index >= _chat_thread_ids.size()) { return nullptr; @@ -326,5 +366,200 @@ std::shared_ptr UserMgr::GetNextLoadData() { return iter.value(); } +void UserMgr::AddUploadFile(QString name, std::shared_ptr file_info) +{ + std::lock_guard lock(_mtx); + _name_to_upload_info.insert(name, file_info); +} + +void UserMgr::RmvUploadFile(QString name) +{ + std::lock_guard lock(_mtx); + _name_to_upload_info.remove(name); +} + +std::shared_ptr UserMgr::GetUploadInfoByName(QString name) +{ + std::lock_guard lock(_mtx); + auto iter = _name_to_upload_info.find(name); + if(iter == _name_to_upload_info.end()){ + return nullptr; + } + + return iter.value(); +} + + +bool UserMgr::IsDownLoading(QString name) { + std::lock_guard lock(_down_load_mtx); + auto iter = _name_to_download_info.find(name); + if (iter == _name_to_download_info.end()) { + return false; + } + + return true; +} + +void UserMgr::AddDownloadFile(QString name, + std::shared_ptr file_info) { + std::lock_guard lock(_down_load_mtx); + _name_to_download_info[name] = file_info; +} + +void UserMgr::RmvDownloadFile(QString name) { + std::lock_guard lock(_down_load_mtx); + _name_to_download_info.remove(name); +} + +std::shared_ptr UserMgr::GetDownloadInfo(QString name) +{ + std::lock_guard lock(_down_load_mtx); + auto iter = _name_to_download_info.find(name); + if (iter == _name_to_download_info.end()) { + return nullptr; + } + + return iter.value(); +} + + +void UserMgr::AddLabelToReset(QString path, QLabel* label) +{ + auto iter = _path_to_reset_labels.find(path); + if (iter == _path_to_reset_labels.end()) { + QList list; + list.append(label); + _path_to_reset_labels.insert(path, list); + return; + } + + iter->append(label); +} + +void UserMgr::ResetLabelIcon(QString path) +{ + auto iter = _path_to_reset_labels.find(path); + if (iter == _path_to_reset_labels.end()) { + return; + } + + for (auto ele_iter = iter.value().begin(); ele_iter != iter.value().end(); ele_iter++) { + QPixmap pixmap(path); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled((*ele_iter)->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + (*ele_iter)->setPixmap(scaledPixmap); + (*ele_iter)->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << path; + } + } + + _path_to_reset_labels.erase(iter); +} + +void UserMgr::AddTransFile(QString name, std::shared_ptr msg_info) +{ + std::lock_guard mtx(_trans_mtx); + _name_to_msg_info[name] = msg_info; +} + +std::shared_ptr UserMgr::GetTransFileByName(QString name) { + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return nullptr; + } + + return *iter; +} + +void UserMgr::RmvTransFileByName(QString name) { + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return ; + } + + _name_to_msg_info.erase(iter); +} + +void UserMgr::PauseTransFileByName(QString name) { + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return; + } + + iter.value()->_transfer_state = TransferState::Paused; +} + +void UserMgr::ResumeTransFileByName(QString name) +{ + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return; + } + + if (iter.value()->_transfer_type == TransferType::Download) { + iter.value()->_transfer_state = TransferState::Downloading; + return; + } + + if (iter.value()->_transfer_type == TransferType::Upload) { + iter.value()->_transfer_state = TransferState::Uploading; + return; + } +} +bool UserMgr::TransFileIsUploading(QString name) { + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return false; + } + + if (iter.value()->_transfer_state == TransferState::Uploading) { + return true; + } + + return false; +} + +std::shared_ptr UserMgr::GetFreeUploadFile() { + std::lock_guard mtx(_trans_mtx); + if (_name_to_msg_info.isEmpty()) { + return nullptr; + } + + for (auto iter = _name_to_msg_info.begin(); iter != _name_to_msg_info.end(); iter++) { + //只要传输状态不是暂停则返回一个可用的待传输文件 + if ((iter.value()->_transfer_state != TransferState::Paused) && + (iter.value()->_transfer_type == TransferType::Upload)) { + return iter.value(); + } + } + + //没有找到等待传输的文件则返回空 + return nullptr; +} + +std::shared_ptr UserMgr::GetFreeDownloadFile() { + std::lock_guard mtx(_trans_mtx); + if (_name_to_msg_info.isEmpty()) { + return nullptr; + } + + for (auto iter = _name_to_msg_info.begin(); iter != _name_to_msg_info.end(); iter++) { + //只要传输状态不是暂停则返回一个可用的待传输文件 + if ((iter.value()->_transfer_state != TransferState::Paused) && + (iter.value()->_transfer_type == TransferType::Download)) { + return iter.value(); + } + } + + //没有找到等待传输的文件则返回空 + return nullptr; +} diff --git a/client/llfcchat/usermgr.h b/client/llfcchat/usermgr.h index 2fef121..92fa38a 100644 --- a/client/llfcchat/usermgr.h +++ b/client/llfcchat/usermgr.h @@ -1,10 +1,14 @@ -#ifndef USERMGR_H +#ifndef USERMGR_H #define USERMGR_H #include #include #include #include "userdata.h" #include +#include +#include +#include "global.h" + class UserMgr:public QObject,public Singleton, public std::enable_shared_from_this { @@ -14,11 +18,13 @@ class UserMgr:public QObject,public Singleton, ~ UserMgr(); void SetUserInfo(std::shared_ptr user_info); void SetToken(QString token); + QString GetToken(); int GetUid(); QString GetName(); QString GetNick(); QString GetIcon(); QString GetDesc(); + void SetIcon(QString name); std::shared_ptr GetUserInfo(); void AppendApplyList(QJsonArray array); void AppendFriendList(QJsonArray array); @@ -42,9 +48,32 @@ class UserMgr:public QObject,public Singleton, std::shared_ptr GetChatThreadByThreadId(int thread_id); std::shared_ptr GetChatThreadByUid(int uid); - //ȡǰڼصݡ + //获取当前正在加载的聊天数据。 std::shared_ptr GetCurLoadData(); std::shared_ptr GetNextLoadData(); + + //将md5和文件信息关联起来 + void AddUploadFile(QString name, std::shared_ptr file_info); + //移除上传的文件信息 + void RmvUploadFile(QString name); + //获取上传信息 + std::shared_ptr GetUploadInfoByName(QString name); + bool IsDownLoading(QString name); + void AddDownloadFile(QString name, std::shared_ptr file_info); + void RmvDownloadFile(QString name); + std::shared_ptr GetDownloadInfo(QString name); + //添加资源路径到将要重置的Label集合 + void AddLabelToReset(QString path, QLabel* label); + void ResetLabelIcon(QString path); + void AddTransFile(QString name, std::shared_ptr msg_info); + std::shared_ptr GetTransFileByName(QString name); + void RmvTransFileByName(QString name); + std::shared_ptr GetFreeUploadFile(); + std::shared_ptr GetFreeDownloadFile(); + void PauseTransFileByName(QString name); + void ResumeTransFileByName(QString name); + bool TransFileIsUploading(QString name); + private: UserMgr(); std::shared_ptr _user_info; @@ -54,17 +83,30 @@ class UserMgr:public QObject,public Singleton, QString _token; int _chat_loaded; int _contact_loaded; - //Ựidݵӳϵ + //建立会话id到数据的映射关系 QMap> _chat_map; - //Ựidб + //聊天会话id列表 std::vector _chat_thread_ids; - //¼ѾбĻỰ + //记录已经加载聊天列表的会话索引 int _cur_load_chat_index; - //ϴλỰid + //上次会话的id int _last_chat_thread_id; - //ûuidthread_idӳϵ + //缓存其他用户uid和聊天的thread_id的映射关系。 QMap _uid_to_thread_id; + std::mutex _mtx; + + //上传文件md5和文件信息关联 映射 + QMap > _name_to_upload_info; + std::mutex _down_load_mtx; + //名字关联下载信息 + QMap > _name_to_download_info; + QHash> _path_to_reset_labels; + //聊天传输文件映射 + QHash > _name_to_msg_info; + //传输文件用的锁 + std::mutex _trans_mtx; + public slots: void SlotAddFriendRsp(std::shared_ptr rsp); void SlotAddFriendAuth(std::shared_ptr auth); diff --git a/server/ChatServer/CSession.cpp b/server/ChatServer/CSession.cpp index 67edff9..1fcc0d0 100644 --- a/server/ChatServer/CSession.cpp +++ b/server/ChatServer/CSession.cpp @@ -8,6 +8,7 @@ #include "LogicSystem.h" #include "RedisMgr.h" #include "ConfigMgr.h" +#include "MysqlMgr.h" CSession::CSession(boost::asio::io_context& io_context, CServer* server): _socket(io_context), _server(server), _b_close(false),_b_head_parse(false), _user_uid(0){ @@ -262,6 +263,22 @@ void CSession::NotifyOffline(int uid) { return; } +void CSession::NotifyChatImgRecv(const ::message::NotifyChatImgReq* request) { + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["message_id"] = request->message_id(); + rtvalue["sender_id"] = request->from_uid(); + rtvalue["receiver_id"] = request->to_uid(); + rtvalue["img_name"] = request->file_name(); + rtvalue["total_size"] = std::to_string(request->total_size()); + rtvalue["thread_id"] = request->thread_id(); + + std::string return_str = rtvalue.toStyledString(); + //֪ͨͼƬϢ + Send(return_str, ID_NOTIFY_IMG_CHAT_MSG_REQ); + return; +} + LogicNode::LogicNode(shared_ptr session, shared_ptr recvnode):_session(session),_recvnode(recvnode) { @@ -313,5 +330,8 @@ void CSession::DealExceptionSession() RedisMgr::GetInstance()->Del(USER_SESSION_PREFIX + uid_str); //û¼Ϣ RedisMgr::GetInstance()->Del(USERIPPREFIX + uid_str); + //ûtokenϢ + std::string token_key = USERTOKENPREFIX + uid_str; + RedisMgr::GetInstance()->Del(token_key); } diff --git a/server/ChatServer/CSession.h b/server/ChatServer/CSession.h index c013215..da988c9 100644 --- a/server/ChatServer/CSession.h +++ b/server/ChatServer/CSession.h @@ -10,6 +10,9 @@ #include #include "const.h" #include "MsgNode.h" +#include "message.grpc.pb.h" +#include "message.pb.h" +#include using namespace std; @@ -17,7 +20,7 @@ namespace beast = boost::beast; // from namespace http = beast::http; // from namespace net = boost::asio; // from using tcp = boost::asio::ip::tcp; // from - +using message::NotifyChatImgReq; class CServer; class LogicSystem; @@ -39,6 +42,7 @@ class CSession: public std::enable_shared_from_this void AsyncReadBody(int length); void AsyncReadHead(int total_len); void NotifyOffline(int uid); + void NotifyChatImgRecv(const ::message::NotifyChatImgReq* request); //жǷ bool IsHeartbeatExpired(std::time_t& now); // diff --git a/server/ChatServer/ChatServiceImpl.cpp b/server/ChatServer/ChatServiceImpl.cpp index 4cd064c..ce18207 100644 --- a/server/ChatServer/ChatServiceImpl.cpp +++ b/server/ChatServer/ChatServiceImpl.cpp @@ -215,3 +215,27 @@ void ChatServiceImpl::RegisterServer(std::shared_ptr pServer) { _p_server = pServer; } + +Status ChatServiceImpl::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) +{ + //ûǷڱ + auto uid = request->to_uid(); + auto session = UserMgr::GetInstance()->GetSession(uid); + + Defer defer([request, response]() { + //þĻذϢ + response->set_error(ErrorCodes::Success); + response->set_message_id(request->message_id()); + }); + + //ûڴֱӷ + if (session == nullptr) { + //ֻǷ1״̬ + return Status::OK; + } + + //ڴֱӷ֪ͨԷ + session->NotifyChatImgRecv(request); + //ֻǷ1״̬ + return Status::OK; +} diff --git a/server/ChatServer/ChatServiceImpl.h b/server/ChatServer/ChatServiceImpl.h index 000a745..7aa15e0 100644 --- a/server/ChatServer/ChatServiceImpl.h +++ b/server/ChatServer/ChatServiceImpl.h @@ -23,6 +23,7 @@ using message::TextChatMsgRsp; using message::TextChatData; using message::KickUserReq; using message::KickUserRsp; +using message::NotifyChatImgReq; class ChatServiceImpl final: public ChatService::Service @@ -45,6 +46,8 @@ class ChatServiceImpl final: public ChatService::Service const KickUserReq* request, KickUserRsp* response) override; void RegisterServer(std::shared_ptr pServer); + //Resource˷͵ͼƬ֪ͨ + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) override; private: std::shared_ptr _p_server; }; diff --git a/server/ChatServer/LogicSystem.cpp b/server/ChatServer/LogicSystem.cpp index 6eb0d11..0d9ec8c 100644 --- a/server/ChatServer/LogicSystem.cpp +++ b/server/ChatServer/LogicSystem.cpp @@ -107,6 +107,10 @@ void LogicSystem::RegisterCallBacks() { _fun_callbacks[ID_LOAD_CHAT_MSG_REQ] = std::bind(&LogicSystem::LoadChatMsg, this, placeholders::_1, placeholders::_2, placeholders::_3); + + _fun_callbacks[ID_IMG_CHAT_MSG_REQ] = std::bind(&LogicSystem::DealChatImgMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); + } void LogicSystem::LoginHandler(shared_ptr session, const short &msg_id, const string &msg_data) { @@ -158,6 +162,7 @@ void LogicSystem::LoginHandler(shared_ptr session, const short &msg_id rtvalue["desc"] = user_info->desc; rtvalue["sex"] = user_info->sex; rtvalue["icon"] = user_info->icon; + rtvalue["token"] = token; //ݿȡб std::vector> apply_list; @@ -504,6 +509,7 @@ void LogicSystem::DealChatTextMsg(std::shared_ptr session, const short chat_msg->thread_id = thread_id; chat_msg->content = content; chat_msg->status = 2; + chat_msg->msg_type = int(ChatMsgType::TEXT); chat_datas.push_back(chat_msg); } @@ -904,7 +910,61 @@ void LogicSystem::LoadChatMsg(std::shared_ptr session, chat_data["msg_content"] = chat.content; chat_data["chat_time"] = chat.chat_time; chat_data["status"] = chat.status; + chat_data["msg_type"] = chat.msg_type; + chat_data["receiver"] = chat.recv_id; rtvalue["chat_datas"].append(chat_data); } } + +void LogicSystem::DealChatImgMsg(std::shared_ptr session, + const short& msg_id, const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto uid = root["fromuid"].asInt(); + auto touid = root["touid"].asInt(); + + auto md5 = root["md5"].asString(); + auto unique_name = root["name"].asString(); + auto token = root["token"].asString(); + auto unique_id = root["unique_id"].asString(); + auto chat_time = root["chat_time"].asString(); + auto status = root["status"].asInt(); + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + + rtvalue["fromuid"] = uid; + rtvalue["touid"] = touid; + auto thread_id = root["thread_id"].asInt(); + rtvalue["thread_id"] = thread_id; + rtvalue["md5"] = md5; + rtvalue["unique_name"] = unique_name; + rtvalue["unique_id"] = unique_id; + rtvalue["chat_time"] = chat_time; + rtvalue["status"] = MsgStatus::UN_UPLOAD; + + auto timestamp = getCurrentTimestamp(); + auto chat_msg = std::make_shared(); + chat_msg->chat_time = timestamp; + chat_msg->sender_id = uid; + chat_msg->recv_id = touid; + chat_msg->unique_id = unique_id; + chat_msg->thread_id = thread_id; + chat_msg->content = unique_name; + chat_msg->status = MsgStatus::UN_UPLOAD; + chat_msg->msg_type = int(ChatMsgType::PIC); + + //ݿ + MysqlMgr::GetInstance()->AddChatMsg(chat_msg); + + rtvalue["message_id"] = chat_msg->message_id; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_MSG_RSP); + }); + +} + diff --git a/server/ChatServer/LogicSystem.h b/server/ChatServer/LogicSystem.h index fd96a77..cc62683 100644 --- a/server/ChatServer/LogicSystem.h +++ b/server/ChatServer/LogicSystem.h @@ -47,6 +47,8 @@ class LogicSystem:public Singleton int& nextLastId); void CreatePrivateChat(std::shared_ptr session, const short& msg_id, const string& msg_data); void LoadChatMsg(std::shared_ptr session, const short& msg_id, const string& msg_data); + void DealChatImgMsg(std::shared_ptr session, const short& msg_id, const string& msg_data); + std::thread _worker_thread; std::queue> _msg_que; std::mutex _mutex; diff --git a/server/ChatServer/MysqlDao.cpp b/server/ChatServer/MysqlDao.cpp index c47033e..2fc1dd1 100644 --- a/server/ChatServer/MysqlDao.cpp +++ b/server/ChatServer/MysqlDao.cpp @@ -243,6 +243,7 @@ bool MysqlDao::AuthFriendApply(const int& from, const int& to) { return true; } + bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, std::vector>& chat_datas) { auto con = pool_->getConnection(); @@ -255,8 +256,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, }); try { - - //ʼ + // ʼ con->_con->setAutoCommit(false); std::string reverse_back; std::string apply_desc; @@ -284,7 +284,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, return false; } } - + { // 2. ִĸ std::unique_ptr updStmt(con->_con->prepareStatement( @@ -292,7 +292,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, "SET status = 1 " "WHERE from_uid = ? AND to_uid = ?" )); - + updStmt->setInt(1, to); updStmt->setInt(2, from); @@ -302,32 +302,53 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, return false; } } - + { - // 3. ׼һSQL, ֤ - std::unique_ptr pstmt(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " - "VALUES (?, ?, ?) " + // 3. ѹϵ - ؼĽչ̶˳ + // ȷ˳ʼհ uid С˳ + int smaller_uid = std::min(from, to); + int larger_uid = std::max(from, to); + + // һβ룺С uid Ϊ self_id + std::unique_ptr pstmt(con->_con->prepareStatement( + "INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?)" )); - //ʱfrom֤ʱto - pstmt->setInt(1, from); // from id - pstmt->setInt(2, to); - pstmt->setString(3, back_name); - // ִи + + if (from == smaller_uid) { + pstmt->setInt(1, from); + pstmt->setInt(2, to); + pstmt->setString(3, back_name); + } + else { + pstmt->setInt(1, to); + pstmt->setInt(2, from); + pstmt->setString(3, reverse_back); + } + int rowAffected = pstmt->executeUpdate(); if (rowAffected < 0) { con->_con->rollback(); return false; } - //׼ڶSQL䣬뷽 - std::unique_ptr pstmt2(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " - "VALUES (?, ?, ?) " + // ڶβ룺ϴ uid Ϊ self_id + std::unique_ptr pstmt2(con->_con->prepareStatement( + "INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?)" )); - //ʱfrom֤ʱto - pstmt2->setInt(1, to); // from id - pstmt2->setInt(2, from); - pstmt2->setString(3, reverse_back); - // ִи + + if (from == larger_uid) { + pstmt2->setInt(1, from); + pstmt2->setInt(2, to); + pstmt2->setString(3, back_name); + } + else { + pstmt2->setInt(1, to); + pstmt2->setInt(2, from); + pstmt2->setString(3, reverse_back); + } + int rowAffected2 = pstmt2->executeUpdate(); if (rowAffected2 < 0) { con->_con->rollback(); @@ -335,15 +356,13 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, } } - - // 4. chat_thread long long threadId = 0; { std::unique_ptr threadStmt(con->_con->prepareStatement( - "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());" + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW())" )); - + threadStmt->executeUpdate(); std::unique_ptr stmt(con->_con->createStatement()); @@ -355,6 +374,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, threadId = rs->getInt64(1); } else { + con->_con->rollback(); return false; } } @@ -368,27 +388,37 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, pcStmt->setInt64(1, threadId); pcStmt->setInt(2, from); pcStmt->setInt(3, to); - if (pcStmt->executeUpdate() < 0) return false; + + if (pcStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } } - // 6. ѡʼϢ chat_message - if (apply_desc.empty() == false) + // 6. ʼϢ + if (!apply_desc.empty()) { std::unique_ptr msgStmt(con->_con->prepareStatement( - "INSERT INTO chat_message(thread_id, sender_id, recv_id, content,created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, NOW(), NOW(), ?)" )); - + msgStmt->setInt64(1, threadId); msgStmt->setInt(2, to); msgStmt->setInt(3, from); msgStmt->setString(4, apply_desc); msgStmt->setInt(5, 2); - if (msgStmt->executeUpdate() < 0) { return false; } + + if (msgStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } std::unique_ptr stmt(con->_con->createStatement()); std::unique_ptr rs( stmt->executeQuery("SELECT LAST_INSERT_ID()") ); + if (rs->next()) { auto messageId = rs->getInt64(1); auto tx_data = std::make_shared(); @@ -402,28 +432,34 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, chat_datas.push_back(tx_data); } else { + con->_con->rollback(); return false; } } + // 7. ΪѵϢ { std::unique_ptr msgStmt(con->_con->prepareStatement( - "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, NOW(), NOW(), ?)" )); - + msgStmt->setInt64(1, threadId); msgStmt->setInt(2, from); msgStmt->setInt(3, to); msgStmt->setString(4, "We are friends now!"); - msgStmt->setInt(5, 2); - if (msgStmt->executeUpdate() < 0) { return false; } + if (msgStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } std::unique_ptr stmt(con->_con->createStatement()); std::unique_ptr rs( stmt->executeQuery("SELECT LAST_INSERT_ID()") ); + if (rs->next()) { auto messageId = rs->getInt64(1); auto tx_data = std::make_shared(); @@ -436,6 +472,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, chat_datas.push_back(tx_data); } else { + con->_con->rollback(); return false; } } @@ -454,13 +491,20 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, std::cerr << "SQLException: " << e.what(); std::cerr << " (MySQL error code: " << e.getErrorCode(); std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + + // 1213Կ + if (e.getErrorCode() == 1213) { + std::cerr << "Deadlock detected, consider retry" << std::endl; + } + return false; } - return true; } + + std::shared_ptr MysqlDao::GetUser(int uid) { auto con = pool_->getConnection(); @@ -731,20 +775,21 @@ bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) if (!con) { return false; } + Defer defer([this, &con]() { pool_->returnConnection(std::move(con)); }); + auto& conn = con->_con; + int uid1 = std::min(user1_id, user2_id); + int uid2 = std::max(user1_id, user2_id); try { // conn->setAutoCommit(false); - // 1. ѯǷѴ˽IJм - int uid1 = std::min(user1_id, user2_id); - int uid2 = std::max(user1_id, user2_id); + // 1. ȳԲѯѴڵļ¼() std::string check_sql = "SELECT thread_id FROM private_chat " - "WHERE (user1_id = ? AND user2_id = ?) " - "FOR UPDATE;"; + "WHERE user1_id = ? AND user2_id = ?;"; std::unique_ptr pstmt(conn->prepareStatement(check_sql)); pstmt->setInt64(1, uid1); @@ -790,8 +835,34 @@ bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) return true; } catch (sql::SQLException& e) { - std::cerr << "SQLException: " << e.what() << std::endl; conn->rollback(); + + // ǷΨһͻ (MySQL error code 1062) + if (e.getErrorCode() == 1062) { + // ²ѯѴڵļ¼ + try { + conn->setAutoCommit(true); + std::string retry_sql = + "SELECT thread_id FROM private_chat " + "WHERE user1_id = ? AND user2_id = ?;"; + std::unique_ptr pstmt_retry( + conn->prepareStatement(retry_sql)); + pstmt_retry->setInt64(1, uid1); + pstmt_retry->setInt64(2, uid2); + std::unique_ptr res_retry(pstmt_retry->executeQuery()); + + if (res_retry->next()) { + thread_id = res_retry->getInt("thread_id"); + return true; + } + } + catch (...) { + return false; + } + } + + std::cerr << "SQLException: " << e.what() + << " (Code: " << e.getErrorCode() << ")" << std::endl; return false; } return false; @@ -812,12 +883,10 @@ std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_messag try { auto page_res = std::make_shared(); page_res->load_more = false; - page_res->next_cursor = last_message_id; - // SQLȡһжǷи const std::string sql = R"( SELECT message_id, thread_id, sender_id, recv_id, content, - created_at, updated_at, status + created_at, updated_at, status,msg_type FROM chat_message WHERE thread_id = ? AND message_id > ? @@ -845,8 +914,15 @@ std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_messag msg.content = rs->getString("content"); msg.chat_time = rs->getString("created_at"); msg.status = rs->getInt("status"); + msg.msg_type = rs->getInt("msg_type"); page_res->messages.push_back(std::move(msg)); } + if (page_res->messages.size() > page_size) { + page_res->messages.pop_back(); + page_res->load_more = true; + } + + page_res->next_cursor = page_res->messages.back().message_id; return page_res; } @@ -877,8 +953,8 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) auto pstmt = std::unique_ptr( conn->prepareStatement( "INSERT INTO chat_message " - "(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " - "VALUES (?, ?, ?, ?, ?, ?, ?)" + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status,msg_type) " + "VALUES (?, ?, ?, ?, ?, ?, ?,?)" ) ); @@ -893,6 +969,7 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) pstmt->setString(6, msg->chat_time); // updated_at pstmt->setInt(7, msg->status); + pstmt->setInt(8, msg->msg_type); pstmt->executeUpdate(); // 2. ȡ LAST_INSERT_ID() @@ -921,3 +998,106 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) return true; } + +bool MysqlDao::AddChatMsg(std::shared_ptr chat_data) { + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + try { + //رԶύֶ + conn->setAutoCommit(false); + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "INSERT INTO chat_message " + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status,msg_type) " + "VALUES (?, ?, ?, ?, ?, ?, ?,?)" + ) + ); + + // 󶨲 + pstmt->setUInt64(1, chat_data->thread_id); + pstmt->setUInt64(2, chat_data->sender_id); + pstmt->setUInt64(3, chat_data->recv_id); + pstmt->setString(4, chat_data->content); + pstmt->setString(5, chat_data->chat_time); // created_at + pstmt->setString(6, chat_data->chat_time); // updated_at + pstmt->setInt(7, chat_data->status); + pstmt->setInt(8, chat_data->msg_type); + + pstmt->executeUpdate(); + + // ȡ + std::unique_ptr keyStmt( + conn->createStatement() + ); + std::unique_ptr rs( + keyStmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + chat_data->message_id = rs->getUInt64(1); + } + + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } +} + +std::shared_ptr MysqlDao::GetChatMsg(int message_id) +{ + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + + try { + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "SELECT message_id, thread_id, sender_id, recv_id, " + "content, created_at, updated_at, status , msg_type" + "FROM chat_message WHERE message_id = ?" + ) + ); + + pstmt->setUInt64(1, message_id); + auto rs = std::unique_ptr(pstmt->executeQuery()); + + if (rs->next()) { + auto msg = std::make_shared(); + msg->message_id = rs->getUInt64("message_id"); + msg->thread_id = rs->getUInt64("thread_id"); + msg->sender_id = rs->getUInt64("sender_id"); + msg->recv_id = rs->getUInt64("recv_id"); + msg->content = rs->getString("content"); + msg->chat_time = rs->getString("created_at"); + msg->status = rs->getInt("status"); + msg->msg_type = rs->getInt("msg_type"); + + return msg; + } + + return nullptr; + + } + catch (sql::SQLException& e) { + std::cerr << "GetChatMessageById SQLException: " << e.what() << std::endl; + return nullptr; + } +} + diff --git a/server/ChatServer/MysqlDao.h b/server/ChatServer/MysqlDao.h index a6441f3..4bf0535 100644 --- a/server/ChatServer/MysqlDao.h +++ b/server/ChatServer/MysqlDao.h @@ -245,6 +245,7 @@ class MysqlDao bool AddFriendApply(const int& from, const int& to, const std::string& desc, const std::string& back_name); bool AuthFriendApply(const int& from, const int& to); bool AddFriend(const int& from, const int& to, std::string back_name, std::vector> &chat_datas); + std::shared_ptr GetUser(int uid); std::shared_ptr GetUser(std::string name); bool GetApplyList(int touid, std::vector>& applyList, int offset, int limit ); @@ -259,6 +260,8 @@ class MysqlDao bool CreatePrivateChat(int user1_id, int user2_id, int& thread_id); std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); bool AddChatMsg(std::vector>& chat_datas); + bool AddChatMsg(std::shared_ptr chat_data); + std::shared_ptr GetChatMsg(int message_id); private: std::unique_ptr pool_; }; diff --git a/server/ChatServer/MysqlMgr.cpp b/server/ChatServer/MysqlMgr.cpp index 951e57a..45c75c0 100644 --- a/server/ChatServer/MysqlMgr.cpp +++ b/server/ChatServer/MysqlMgr.cpp @@ -83,3 +83,12 @@ bool MysqlMgr::AddChatMsg(std::vector>& chat_datas) return _dao.AddChatMsg(chat_datas); } +bool MysqlMgr::AddChatMsg(std::shared_ptr chat_data) { + return _dao.AddChatMsg(chat_data); +} + +std::shared_ptr MysqlMgr::GetChatMsg(int message_id) +{ + return _dao.GetChatMsg(message_id); +} + diff --git a/server/ChatServer/MysqlMgr.h b/server/ChatServer/MysqlMgr.h index f6a71b3..8321724 100644 --- a/server/ChatServer/MysqlMgr.h +++ b/server/ChatServer/MysqlMgr.h @@ -31,6 +31,8 @@ class MysqlMgr: public Singleton bool CreatePrivateChat(int user1_id, int user2_id, int &thread_id); std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); bool AddChatMsg(std::vector>& chat_datas); + bool AddChatMsg(std::shared_ptr chat_data); + std::shared_ptr GetChatMsg(int message_id); private: MysqlMgr(); MysqlDao _dao; diff --git a/server/ChatServer/const.h b/server/ChatServer/const.h index b15b23f..85b54ad 100644 --- a/server/ChatServer/const.h +++ b/server/ChatServer/const.h @@ -70,6 +70,12 @@ enum MSG_IDS { ID_LOAD_CHAT_MSG_REQ = 1029, //Ϣ ID_LOAD_CHAT_MSG_RSP = 1030, //Ϣ + + ID_IMG_CHAT_MSG_REQ = 1035, //ͼƬϢ + ID_IMG_CHAT_MSG_RSP = 1036, //ͼƬϢظ + ID_NOTIFY_IMG_CHAT_MSG_REQ = 1039, //֪ͨûͼƬϢ + ID_FILE_INFO_SYNC_REQ = 1041, //ļϢͬ + ID_FILE_INFO_SYNC_RSP = 1042 //ļϢͬظ }; #define USERIPPREFIX "uip_" @@ -87,4 +93,11 @@ enum MSG_IDS { //ֲʽʱ #define ACQUIRE_TIME_OUT 5 +enum MsgStatus { + UN_READ = 0, //Էδ + SEND_FAILED = 1, //ʧ + READED = 2, //ԷѶ + UN_UPLOAD = 3 //δϴ +}; + diff --git a/server/ChatServer/data.h b/server/ChatServer/data.h index 1901079..2a08a37 100644 --- a/server/ChatServer/data.h +++ b/server/ChatServer/data.h @@ -47,6 +47,7 @@ struct ChatMessage { std::string content; std::string chat_time; int status; + int msg_type; }; // ѯṹnext_cursorֶ @@ -55,3 +56,10 @@ struct PageResult { bool load_more; int next_cursor; // ҳһmessage_id´βѯ }; + +enum class ChatMsgType { + TEXT = 0, + PIC = 1, + VIDEO = 2, + FILE = 3 +}; \ No newline at end of file diff --git a/server/ChatServer/libssl-3-x64.dll b/server/ChatServer/libssl-3-x64.dll new file mode 100644 index 0000000..a1ee2e9 Binary files /dev/null and b/server/ChatServer/libssl-3-x64.dll differ diff --git a/server/ChatServer/message.grpc.pb.cc b/server/ChatServer/message.grpc.pb.cc index 1e98fcd..6014ed6 100644 --- a/server/ChatServer/message.grpc.pb.cc +++ b/server/ChatServer/message.grpc.pb.cc @@ -192,6 +192,7 @@ static const char* ChatService_method_names[] = { "/message.ChatService/NotifyAuthFriend", "/message.ChatService/NotifyTextChatMsg", "/message.ChatService/NotifyKickUser", + "/message.ChatService/NotifyChatImgMsg", }; std::unique_ptr< ChatService::Stub> ChatService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { @@ -207,6 +208,7 @@ ChatService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channe , rpcmethod_NotifyAuthFriend_(ChatService_method_names[3], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_NotifyTextChatMsg_(ChatService_method_names[4], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_NotifyKickUser_(ChatService_method_names[5], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyChatImgMsg_(ChatService_method_names[6], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) {} ::grpc::Status ChatService::Stub::NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::message::AddFriendRsp* response) { @@ -347,6 +349,29 @@ ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* ChatService::Stub::A return result; } +::grpc::Status ChatService::Stub::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyChatImgMsg_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::NotifyChatImgRsp, ::message::NotifyChatImgReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyChatImgMsg_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyChatImgMsgRaw(context, request, cq); + result->StartCall(); + return result; +} + ChatService::Service::Service() { AddMethod(new ::grpc::internal::RpcServiceMethod( ChatService_method_names[0], @@ -408,6 +433,16 @@ ChatService::Service::Service() { ::message::KickUserRsp* resp) { return service->NotifyKickUser(ctx, req, resp); }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[6], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::NotifyChatImgReq* req, + ::message::NotifyChatImgRsp* resp) { + return service->NotifyChatImgMsg(ctx, req, resp); + }, this))); } ChatService::Service::~Service() { @@ -455,6 +490,13 @@ ::grpc::Status ChatService::Service::NotifyKickUser(::grpc::ServerContext* conte return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } +::grpc::Status ChatService::Service::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + } // namespace message diff --git a/server/ChatServer/message.grpc.pb.h b/server/ChatServer/message.grpc.pb.h index a27d500..bd0efca 100644 --- a/server/ChatServer/message.grpc.pb.h +++ b/server/ChatServer/message.grpc.pb.h @@ -795,6 +795,13 @@ class ChatService final { std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); } + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } class experimental_async_interface { public: virtual ~experimental_async_interface() {} @@ -834,6 +841,12 @@ class ChatService final { #else virtual void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; #endif + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif }; #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL typedef class experimental_async_interface async_interface; @@ -855,6 +868,8 @@ class ChatService final { virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; }; class Stub final : public StubInterface { public: @@ -901,6 +916,13 @@ class ChatService final { std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); } + ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } class experimental_async final : public StubInterface::experimental_async_interface { public: @@ -940,6 +962,12 @@ class ChatService final { #else void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; #endif + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif private: friend class Stub; explicit experimental_async(Stub* stub): stub_(stub) { } @@ -963,12 +991,15 @@ class ChatService final { ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; const ::grpc::internal::RpcMethod rpcmethod_NotifyAddFriend_; const ::grpc::internal::RpcMethod rpcmethod_RplyAddFriend_; const ::grpc::internal::RpcMethod rpcmethod_SendChatMsg_; const ::grpc::internal::RpcMethod rpcmethod_NotifyAuthFriend_; const ::grpc::internal::RpcMethod rpcmethod_NotifyTextChatMsg_; const ::grpc::internal::RpcMethod rpcmethod_NotifyKickUser_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyChatImgMsg_; }; static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); @@ -982,6 +1013,7 @@ class ChatService final { virtual ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response); virtual ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response); virtual ::grpc::Status NotifyKickUser(::grpc::ServerContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response); + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response); }; template class WithAsyncMethod_NotifyAddFriend : public BaseClass { @@ -1103,7 +1135,27 @@ class ChatService final { ::grpc::Service::RequestAsyncUnary(5, context, request, response, new_call_cq, notification_cq, tag); } }; - typedef WithAsyncMethod_NotifyAddFriend > > > > > AsyncService; + template + class WithAsyncMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodAsync(6); + } + ~WithAsyncMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::message::NotifyChatImgReq* request, ::grpc::ServerAsyncResponseWriter< ::message::NotifyChatImgRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_NotifyAddFriend > > > > > > AsyncService; template class ExperimentalWithCallbackMethod_NotifyAddFriend : public BaseClass { private: @@ -1386,11 +1438,58 @@ class ChatService final { #endif { return nullptr; } }; + template + class ExperimentalWithCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { return this->NotifyChatImgMsg(context, request, response); }));} + void SetMessageAllocatorFor_NotifyChatImgMsg( + ::grpc::experimental::MessageAllocator< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(6); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(6); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #endif + { return nullptr; } + }; #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL - typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > CallbackService; + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > CallbackService; #endif - typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > ExperimentalCallbackService; + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > ExperimentalCallbackService; template class WithGenericMethod_NotifyAddFriend : public BaseClass { private: @@ -1494,6 +1593,23 @@ class ChatService final { } }; template + class WithGenericMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodGeneric(6); + } + ~WithGenericMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template class WithRawMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -1614,6 +1730,26 @@ class ChatService final { } }; template + class WithRawMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodRaw(6); + } + ~WithRawMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template class ExperimentalWithRawCallbackMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -1842,6 +1978,44 @@ class ChatService final { { return nullptr; } }; template + class ExperimentalWithRawCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyChatImgMsg(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template class WithStreamedUnaryMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -2003,9 +2177,36 @@ class ChatService final { // replace default version of method with streamed unary virtual ::grpc::Status StreamedNotifyKickUser(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::KickUserReq,::message::KickUserRsp>* server_unary_streamer) = 0; }; - typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > StreamedUnaryService; + template + class WithStreamedUnaryMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodStreamed(6, + new ::grpc::internal::StreamedUnaryHandler< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* streamer) { + return this->StreamedNotifyChatImgMsg(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::NotifyChatImgReq,::message::NotifyChatImgRsp>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedUnaryService; typedef Service SplitStreamedService; - typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > StreamedService; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedService; }; } // namespace message diff --git a/server/ChatServer/message.pb.cc b/server/ChatServer/message.pb.cc index 5fea1ff..1cc6cc6 100644 --- a/server/ChatServer/message.pb.cc +++ b/server/ChatServer/message.pb.cc @@ -97,6 +97,14 @@ class KickUserRspDefaultTypeInternal { public: ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; } _KickUserRsp_default_instance_; +class NotifyChatImgReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgReq_default_instance_; +class NotifyChatImgRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgRsp_default_instance_; } // namespace message static void InitDefaultsscc_info_AddFriendMsg_message_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -281,6 +289,34 @@ static void InitDefaultsscc_info_LoginRsp_message_2eproto() { ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_LoginRsp_message_2eproto = {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_LoginRsp_message_2eproto}, {}}; +static void InitDefaultsscc_info_NotifyChatImgReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgReq_default_instance_; + new (ptr) ::message::NotifyChatImgReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgRsp_default_instance_; + new (ptr) ::message::NotifyChatImgRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto}, {}}; + static void InitDefaultsscc_info_RplyFriendReq_message_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -381,7 +417,7 @@ ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_TextChatMsgRsp_message_2e {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_TextChatMsgRsp_message_2eproto}, { &scc_info_TextChatData_message_2eproto.base,}}; -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_message_2eproto[20]; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_message_2eproto[22]; static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_message_2eproto = nullptr; static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_message_2eproto = nullptr; @@ -550,6 +586,29 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_message_2eproto::offsets[] PRO ~0u, // no _weak_field_map_ PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, error_), PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, uid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, thread_id_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, thread_id_), }; static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { { 0, -1, sizeof(::message::GetVarifyReq)}, @@ -572,6 +631,8 @@ static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOB { 141, -1, sizeof(::message::TextChatMsgRsp)}, { 151, -1, sizeof(::message::KickUserReq)}, { 157, -1, sizeof(::message::KickUserRsp)}, + { 164, -1, sizeof(::message::NotifyChatImgReq)}, + { 175, -1, sizeof(::message::NotifyChatImgRsp)}, }; static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { @@ -595,6 +656,8 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = reinterpret_cast(&::message::_TextChatMsgRsp_default_instance_), reinterpret_cast(&::message::_KickUserReq_default_instance_), reinterpret_cast(&::message::_KickUserRsp_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgReq_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgRsp_default_instance_), }; const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = @@ -633,28 +696,37 @@ const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE "romuid\030\002 \001(\005\022\r\n\005touid\030\003 \001(\005\022\021\n\tthread_id" "\030\004 \001(\005\022\'\n\010textmsgs\030\005 \003(\0132\025.message.TextC" "hatData\"\032\n\013KickUserReq\022\013\n\003uid\030\001 \001(\005\")\n\013K" - "ickUserRsp\022\r\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\0052P" - "\n\rVarifyService\022\?\n\rGetVarifyCode\022\025.messa" - "ge.GetVarifyReq\032\025.message.GetVarifyRsp\"\000" - "2\207\001\n\rStatusService\022G\n\rGetChatServer\022\031.me" - "ssage.GetChatServerReq\032\031.message.GetChat" - "ServerRsp\"\000\022-\n\005Login\022\021.message.LoginReq\032" - "\021.message.LoginRsp2\245\003\n\013ChatService\022A\n\017No" - "tifyAddFriend\022\025.message.AddFriendReq\032\025.m" - "essage.AddFriendRsp\"\000\022A\n\rRplyAddFriend\022\026" - ".message.RplyFriendReq\032\026.message.RplyFri" - "endRsp\"\000\022A\n\013SendChatMsg\022\027.message.SendCh" - "atMsgReq\032\027.message.SendChatMsgRsp\"\000\022D\n\020N" - "otifyAuthFriend\022\026.message.AuthFriendReq\032" - "\026.message.AuthFriendRsp\"\000\022G\n\021NotifyTextC" - "hatMsg\022\027.message.TextChatMsgReq\032\027.messag" - "e.TextChatMsgRsp\"\000\022>\n\016NotifyKickUser\022\024.m" - "essage.KickUserReq\032\024.message.KickUserRsp" - "\"\000b\006proto3" + "ickUserRsp\022\r\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\005\"\202" + "\001\n\020NotifyChatImgReq\022\020\n\010from_uid\030\001 \001(\005\022\016\n" + "\006to_uid\030\002 \001(\005\022\022\n\nmessage_id\030\003 \001(\005\022\021\n\tfil" + "e_name\030\004 \001(\t\022\022\n\ntotal_size\030\005 \001(\003\022\021\n\tthre" + "ad_id\030\006 \001(\005\"\221\001\n\020NotifyChatImgRsp\022\r\n\005erro" + "r\030\001 \001(\005\022\020\n\010from_uid\030\002 \001(\005\022\016\n\006to_uid\030\003 \001(" + "\005\022\022\n\nmessage_id\030\004 \001(\005\022\021\n\tfile_name\030\005 \001(\t" + "\022\022\n\ntotal_size\030\006 \001(\003\022\021\n\tthread_id\030\007 \001(\0052" + "P\n\rVarifyService\022\?\n\rGetVarifyCode\022\025.mess" + "age.GetVarifyReq\032\025.message.GetVarifyRsp\"" + "\0002\207\001\n\rStatusService\022G\n\rGetChatServer\022\031.m" + "essage.GetChatServerReq\032\031.message.GetCha" + "tServerRsp\"\000\022-\n\005Login\022\021.message.LoginReq" + "\032\021.message.LoginRsp2\361\003\n\013ChatService\022A\n\017N" + "otifyAddFriend\022\025.message.AddFriendReq\032\025." + "message.AddFriendRsp\"\000\022A\n\rRplyAddFriend\022" + "\026.message.RplyFriendReq\032\026.message.RplyFr" + "iendRsp\"\000\022A\n\013SendChatMsg\022\027.message.SendC" + "hatMsgReq\032\027.message.SendChatMsgRsp\"\000\022D\n\020" + "NotifyAuthFriend\022\026.message.AuthFriendReq" + "\032\026.message.AuthFriendRsp\"\000\022G\n\021NotifyText" + "ChatMsg\022\027.message.TextChatMsgReq\032\027.messa" + "ge.TextChatMsgRsp\"\000\022>\n\016NotifyKickUser\022\024." + "message.KickUserReq\032\024.message.KickUserRs" + "p\"\000\022J\n\020NotifyChatImgMsg\022\031.message.Notify" + "ChatImgReq\032\031.message.NotifyChatImgRsp\"\000b" + "\006proto3" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_message_2eproto_deps[1] = { }; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_message_2eproto_sccs[20] = { +static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_message_2eproto_sccs[22] = { &scc_info_AddFriendMsg_message_2eproto.base, &scc_info_AddFriendReq_message_2eproto.base, &scc_info_AddFriendRsp_message_2eproto.base, @@ -668,6 +740,8 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_mes &scc_info_KickUserRsp_message_2eproto.base, &scc_info_LoginReq_message_2eproto.base, &scc_info_LoginRsp_message_2eproto.base, + &scc_info_NotifyChatImgReq_message_2eproto.base, + &scc_info_NotifyChatImgRsp_message_2eproto.base, &scc_info_RplyFriendReq_message_2eproto.base, &scc_info_RplyFriendRsp_message_2eproto.base, &scc_info_SendChatMsgReq_message_2eproto.base, @@ -678,10 +752,10 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_mes }; static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_message_2eproto_once; const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_message_2eproto = { - false, false, descriptor_table_protodef_message_2eproto, "message.proto", 2090, - &descriptor_table_message_2eproto_once, descriptor_table_message_2eproto_sccs, descriptor_table_message_2eproto_deps, 20, 0, + false, false, descriptor_table_protodef_message_2eproto, "message.proto", 2447, + &descriptor_table_message_2eproto_once, descriptor_table_message_2eproto_sccs, descriptor_table_message_2eproto_deps, 22, 0, schemas, file_default_instances, TableStruct_message_2eproto::offsets, - file_level_metadata_message_2eproto, 20, file_level_enum_descriptors_message_2eproto, file_level_service_descriptors_message_2eproto, + file_level_metadata_message_2eproto, 22, file_level_enum_descriptors_message_2eproto, file_level_service_descriptors_message_2eproto, }; // Force running AddDescriptors() at dynamic initialization time. @@ -6086,6 +6160,707 @@ ::PROTOBUF_NAMESPACE_ID::Metadata KickUserRsp::GetMetadata() const { } +// =================================================================== + +void NotifyChatImgReq::InitAsDefaultInstance() { +} +class NotifyChatImgReq::_Internal { + public: +}; + +NotifyChatImgReq::NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgReq) +} +NotifyChatImgReq::NotifyChatImgReq(const NotifyChatImgReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&from_uid_, &from.from_uid_, + static_cast(reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgReq) +} + +void NotifyChatImgReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgReq_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); +} + +NotifyChatImgReq::~NotifyChatImgReq() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgReq::ArenaDtor(void* object) { + NotifyChatImgReq* _this = reinterpret_cast< NotifyChatImgReq* >(object); + (void)_this; +} +void NotifyChatImgReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgReq& NotifyChatImgReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 from_uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgReq.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_from_uid(), target); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_to_uid(), target); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_message_id(), target); + } + + // string file_name = 4; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgReq.file_name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_file_name(), target); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(5, this->_internal_total_size(), target); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(6, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgReq) + return target; +} + +size_t NotifyChatImgReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 4; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgReq) + MergeFrom(*source); + } +} + +void NotifyChatImgReq::MergeFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } +} + +void NotifyChatImgReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgReq::CopyFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgReq::IsInitialized() const { + return true; +} + +void NotifyChatImgReq::InternalSwap(NotifyChatImgReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, total_size_) + + sizeof(NotifyChatImgReq::total_size_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, from_uid_)>( + reinterpret_cast(&from_uid_), + reinterpret_cast(&other->from_uid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void NotifyChatImgRsp::InitAsDefaultInstance() { +} +class NotifyChatImgRsp::_Internal { + public: +}; + +NotifyChatImgRsp::NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgRsp) +} +NotifyChatImgRsp::NotifyChatImgRsp(const NotifyChatImgRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgRsp) +} + +void NotifyChatImgRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgRsp_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); +} + +NotifyChatImgRsp::~NotifyChatImgRsp() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgRsp::ArenaDtor(void* object) { + NotifyChatImgRsp* _this = reinterpret_cast< NotifyChatImgRsp* >(object); + (void)_this; +} +void NotifyChatImgRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgRsp& NotifyChatImgRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 from_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgRsp.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_from_uid(), target); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_to_uid(), target); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_message_id(), target); + } + + // string file_name = 5; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgRsp.file_name"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_file_name(), target); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(6, this->_internal_total_size(), target); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(7, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgRsp) + return target; +} + +size_t NotifyChatImgRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 5; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgRsp) + MergeFrom(*source); + } +} + +void NotifyChatImgRsp::MergeFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } +} + +void NotifyChatImgRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgRsp::CopyFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgRsp::IsInitialized() const { + return true; +} + +void NotifyChatImgRsp::InternalSwap(NotifyChatImgRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, thread_id_) + + sizeof(NotifyChatImgRsp::thread_id_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + // @@protoc_insertion_point(namespace_scope) } // namespace message PROTOBUF_NAMESPACE_OPEN @@ -6149,6 +6924,12 @@ template<> PROTOBUF_NOINLINE ::message::KickUserReq* Arena::CreateMaybeMessage< template<> PROTOBUF_NOINLINE ::message::KickUserRsp* Arena::CreateMaybeMessage< ::message::KickUserRsp >(Arena* arena) { return Arena::CreateMessageInternal< ::message::KickUserRsp >(arena); } +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgReq* Arena::CreateMaybeMessage< ::message::NotifyChatImgReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage< ::message::NotifyChatImgRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgRsp >(arena); +} PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) diff --git a/server/ChatServer/message.pb.h b/server/ChatServer/message.pb.h index 804f4de..426e615 100644 --- a/server/ChatServer/message.pb.h +++ b/server/ChatServer/message.pb.h @@ -47,7 +47,7 @@ struct TableStruct_message_2eproto { PROTOBUF_SECTION_VARIABLE(protodesc_cold); static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[20] + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[22] PROTOBUF_SECTION_VARIABLE(protodesc_cold); static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; @@ -94,6 +94,12 @@ extern LoginReqDefaultTypeInternal _LoginReq_default_instance_; class LoginRsp; class LoginRspDefaultTypeInternal; extern LoginRspDefaultTypeInternal _LoginRsp_default_instance_; +class NotifyChatImgReq; +class NotifyChatImgReqDefaultTypeInternal; +extern NotifyChatImgReqDefaultTypeInternal _NotifyChatImgReq_default_instance_; +class NotifyChatImgRsp; +class NotifyChatImgRspDefaultTypeInternal; +extern NotifyChatImgRspDefaultTypeInternal _NotifyChatImgRsp_default_instance_; class RplyFriendReq; class RplyFriendReqDefaultTypeInternal; extern RplyFriendReqDefaultTypeInternal _RplyFriendReq_default_instance_; @@ -130,6 +136,8 @@ template<> ::message::KickUserReq* Arena::CreateMaybeMessage<::message::KickUser template<> ::message::KickUserRsp* Arena::CreateMaybeMessage<::message::KickUserRsp>(Arena*); template<> ::message::LoginReq* Arena::CreateMaybeMessage<::message::LoginReq>(Arena*); template<> ::message::LoginRsp* Arena::CreateMaybeMessage<::message::LoginRsp>(Arena*); +template<> ::message::NotifyChatImgReq* Arena::CreateMaybeMessage<::message::NotifyChatImgReq>(Arena*); +template<> ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage<::message::NotifyChatImgRsp>(Arena*); template<> ::message::RplyFriendReq* Arena::CreateMaybeMessage<::message::RplyFriendReq>(Arena*); template<> ::message::RplyFriendRsp* Arena::CreateMaybeMessage<::message::RplyFriendRsp>(Arena*); template<> ::message::SendChatMsgReq* Arena::CreateMaybeMessage<::message::SendChatMsgReq>(Arena*); @@ -3517,6 +3525,415 @@ class KickUserRsp PROTOBUF_FINAL : mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; friend struct ::TableStruct_message_2eproto; }; +// ------------------------------------------------------------------- + +class NotifyChatImgReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgReq) */ { + public: + inline NotifyChatImgReq() : NotifyChatImgReq(nullptr) {} + virtual ~NotifyChatImgReq(); + + NotifyChatImgReq(const NotifyChatImgReq& from); + NotifyChatImgReq(NotifyChatImgReq&& from) noexcept + : NotifyChatImgReq() { + *this = ::std::move(from); + } + + inline NotifyChatImgReq& operator=(const NotifyChatImgReq& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgReq& operator=(NotifyChatImgReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgReq* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 20; + + friend void swap(NotifyChatImgReq& a, NotifyChatImgReq& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgReq& from); + void MergeFrom(const NotifyChatImgReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgReq"; + } + protected: + explicit NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 4, + kFromUidFieldNumber = 1, + kToUidFieldNumber = 2, + kMessageIdFieldNumber = 3, + kThreadIdFieldNumber = 6, + kTotalSizeFieldNumber = 5, + }; + // string file_name = 4; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 from_uid = 1; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 2; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 3; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 6; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 5; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class NotifyChatImgRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgRsp) */ { + public: + inline NotifyChatImgRsp() : NotifyChatImgRsp(nullptr) {} + virtual ~NotifyChatImgRsp(); + + NotifyChatImgRsp(const NotifyChatImgRsp& from); + NotifyChatImgRsp(NotifyChatImgRsp&& from) noexcept + : NotifyChatImgRsp() { + *this = ::std::move(from); + } + + inline NotifyChatImgRsp& operator=(const NotifyChatImgRsp& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgRsp& operator=(NotifyChatImgRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgRsp* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 21; + + friend void swap(NotifyChatImgRsp& a, NotifyChatImgRsp& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgRsp& from); + void MergeFrom(const NotifyChatImgRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgRsp"; + } + protected: + explicit NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 5, + kErrorFieldNumber = 1, + kFromUidFieldNumber = 2, + kToUidFieldNumber = 3, + kMessageIdFieldNumber = 4, + kTotalSizeFieldNumber = 6, + kThreadIdFieldNumber = 7, + }; + // string file_name = 5; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 from_uid = 2; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 3; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 4; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 6; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // int32 thread_id = 7; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; // =================================================================== @@ -5697,6 +6114,358 @@ inline void KickUserRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { // @@protoc_insertion_point(field_set:message.KickUserRsp.uid) } +// ------------------------------------------------------------------- + +// NotifyChatImgReq + +// int32 from_uid = 1; +inline void NotifyChatImgReq::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgReq::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgReq::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.from_uid) +} + +// int32 to_uid = 2; +inline void NotifyChatImgReq::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgReq::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgReq::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.to_uid) +} + +// int32 message_id = 3; +inline void NotifyChatImgReq::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgReq::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgReq::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.message_id) +} + +// string file_name = 4; +inline void NotifyChatImgReq::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgReq::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgReq::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgReq.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgReq::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgReq::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgReq::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgReq::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgReq.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgReq::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgReq.file_name) +} + +// int64 total_size = 5; +inline void NotifyChatImgReq::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgReq::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgReq::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.total_size) +} + +// int32 thread_id = 6; +inline void NotifyChatImgReq::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgReq::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgReq::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.thread_id) +} + +// ------------------------------------------------------------------- + +// NotifyChatImgRsp + +// int32 error = 1; +inline void NotifyChatImgRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::error() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.error) + return _internal_error(); +} +inline void NotifyChatImgRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void NotifyChatImgRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.error) +} + +// int32 from_uid = 2; +inline void NotifyChatImgRsp::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgRsp::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgRsp::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.from_uid) +} + +// int32 to_uid = 3; +inline void NotifyChatImgRsp::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgRsp::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgRsp::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.to_uid) +} + +// int32 message_id = 4; +inline void NotifyChatImgRsp::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgRsp::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgRsp::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.message_id) +} + +// string file_name = 5; +inline void NotifyChatImgRsp::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgRsp::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgRsp::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgRsp.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgRsp::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgRsp::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgRsp::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgRsp::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgRsp.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgRsp::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgRsp.file_name) +} + +// int64 total_size = 6; +inline void NotifyChatImgRsp::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgRsp::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgRsp::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.total_size) +} + +// int32 thread_id = 7; +inline void NotifyChatImgRsp::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgRsp::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgRsp::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.thread_id) +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ @@ -5738,6 +6507,10 @@ inline void KickUserRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/server/ChatServer/message.proto b/server/ChatServer/message.proto index 2cd23c2..2cef837 100644 --- a/server/ChatServer/message.proto +++ b/server/ChatServer/message.proto @@ -135,6 +135,26 @@ message KickUserRsp{ int32 uid = 2; } + +message NotifyChatImgReq{ + int32 from_uid = 1; + int32 to_uid = 2; + int32 message_id = 3; + string file_name = 4; + int64 total_size = 5; + int32 thread_id =6; +} + +message NotifyChatImgRsp{ + int32 error = 1; + int32 from_uid = 2; + int32 to_uid = 3; + int32 message_id = 4; + string file_name = 5; + int64 total_size = 6; + int32 thread_id =7; +} + service ChatService { rpc NotifyAddFriend(AddFriendReq) returns (AddFriendRsp) {} rpc RplyAddFriend(RplyFriendReq) returns (RplyFriendRsp) {} @@ -142,4 +162,5 @@ service ChatService { rpc NotifyAuthFriend(AuthFriendReq) returns (AuthFriendRsp) {} rpc NotifyTextChatMsg(TextChatMsgReq) returns (TextChatMsgRsp){} rpc NotifyKickUser(KickUserReq) returns (KickUserRsp){} + rpc NotifyChatImgMsg(NotifyChatImgReq) returns (NotifyChatImgRsp){} } diff --git a/server/ChatServer2/CSession.cpp b/server/ChatServer2/CSession.cpp index 67edff9..1fcc0d0 100644 --- a/server/ChatServer2/CSession.cpp +++ b/server/ChatServer2/CSession.cpp @@ -8,6 +8,7 @@ #include "LogicSystem.h" #include "RedisMgr.h" #include "ConfigMgr.h" +#include "MysqlMgr.h" CSession::CSession(boost::asio::io_context& io_context, CServer* server): _socket(io_context), _server(server), _b_close(false),_b_head_parse(false), _user_uid(0){ @@ -262,6 +263,22 @@ void CSession::NotifyOffline(int uid) { return; } +void CSession::NotifyChatImgRecv(const ::message::NotifyChatImgReq* request) { + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["message_id"] = request->message_id(); + rtvalue["sender_id"] = request->from_uid(); + rtvalue["receiver_id"] = request->to_uid(); + rtvalue["img_name"] = request->file_name(); + rtvalue["total_size"] = std::to_string(request->total_size()); + rtvalue["thread_id"] = request->thread_id(); + + std::string return_str = rtvalue.toStyledString(); + //֪ͨͼƬϢ + Send(return_str, ID_NOTIFY_IMG_CHAT_MSG_REQ); + return; +} + LogicNode::LogicNode(shared_ptr session, shared_ptr recvnode):_session(session),_recvnode(recvnode) { @@ -313,5 +330,8 @@ void CSession::DealExceptionSession() RedisMgr::GetInstance()->Del(USER_SESSION_PREFIX + uid_str); //û¼Ϣ RedisMgr::GetInstance()->Del(USERIPPREFIX + uid_str); + //ûtokenϢ + std::string token_key = USERTOKENPREFIX + uid_str; + RedisMgr::GetInstance()->Del(token_key); } diff --git a/server/ChatServer2/CSession.h b/server/ChatServer2/CSession.h index c013215..da988c9 100644 --- a/server/ChatServer2/CSession.h +++ b/server/ChatServer2/CSession.h @@ -10,6 +10,9 @@ #include #include "const.h" #include "MsgNode.h" +#include "message.grpc.pb.h" +#include "message.pb.h" +#include using namespace std; @@ -17,7 +20,7 @@ namespace beast = boost::beast; // from namespace http = beast::http; // from namespace net = boost::asio; // from using tcp = boost::asio::ip::tcp; // from - +using message::NotifyChatImgReq; class CServer; class LogicSystem; @@ -39,6 +42,7 @@ class CSession: public std::enable_shared_from_this void AsyncReadBody(int length); void AsyncReadHead(int total_len); void NotifyOffline(int uid); + void NotifyChatImgRecv(const ::message::NotifyChatImgReq* request); //жǷ bool IsHeartbeatExpired(std::time_t& now); // diff --git a/server/ChatServer2/ChatServiceImpl.cpp b/server/ChatServer2/ChatServiceImpl.cpp index 4cd064c..ce18207 100644 --- a/server/ChatServer2/ChatServiceImpl.cpp +++ b/server/ChatServer2/ChatServiceImpl.cpp @@ -215,3 +215,27 @@ void ChatServiceImpl::RegisterServer(std::shared_ptr pServer) { _p_server = pServer; } + +Status ChatServiceImpl::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) +{ + //ûǷڱ + auto uid = request->to_uid(); + auto session = UserMgr::GetInstance()->GetSession(uid); + + Defer defer([request, response]() { + //þĻذϢ + response->set_error(ErrorCodes::Success); + response->set_message_id(request->message_id()); + }); + + //ûڴֱӷ + if (session == nullptr) { + //ֻǷ1״̬ + return Status::OK; + } + + //ڴֱӷ֪ͨԷ + session->NotifyChatImgRecv(request); + //ֻǷ1״̬ + return Status::OK; +} diff --git a/server/ChatServer2/ChatServiceImpl.h b/server/ChatServer2/ChatServiceImpl.h index 000a745..ad3ee0b 100644 --- a/server/ChatServer2/ChatServiceImpl.h +++ b/server/ChatServer2/ChatServiceImpl.h @@ -23,6 +23,7 @@ using message::TextChatMsgRsp; using message::TextChatData; using message::KickUserReq; using message::KickUserRsp; +using message::NotifyChatImgReq; class ChatServiceImpl final: public ChatService::Service @@ -45,6 +46,8 @@ class ChatServiceImpl final: public ChatService::Service const KickUserReq* request, KickUserRsp* response) override; void RegisterServer(std::shared_ptr pServer); + //տͻ˷͵ͼƬ֪ͨ + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) override; private: std::shared_ptr _p_server; }; diff --git a/server/ChatServer2/LogicSystem.cpp b/server/ChatServer2/LogicSystem.cpp index 6eb0d11..0d9ec8c 100644 --- a/server/ChatServer2/LogicSystem.cpp +++ b/server/ChatServer2/LogicSystem.cpp @@ -107,6 +107,10 @@ void LogicSystem::RegisterCallBacks() { _fun_callbacks[ID_LOAD_CHAT_MSG_REQ] = std::bind(&LogicSystem::LoadChatMsg, this, placeholders::_1, placeholders::_2, placeholders::_3); + + _fun_callbacks[ID_IMG_CHAT_MSG_REQ] = std::bind(&LogicSystem::DealChatImgMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); + } void LogicSystem::LoginHandler(shared_ptr session, const short &msg_id, const string &msg_data) { @@ -158,6 +162,7 @@ void LogicSystem::LoginHandler(shared_ptr session, const short &msg_id rtvalue["desc"] = user_info->desc; rtvalue["sex"] = user_info->sex; rtvalue["icon"] = user_info->icon; + rtvalue["token"] = token; //ݿȡб std::vector> apply_list; @@ -504,6 +509,7 @@ void LogicSystem::DealChatTextMsg(std::shared_ptr session, const short chat_msg->thread_id = thread_id; chat_msg->content = content; chat_msg->status = 2; + chat_msg->msg_type = int(ChatMsgType::TEXT); chat_datas.push_back(chat_msg); } @@ -904,7 +910,61 @@ void LogicSystem::LoadChatMsg(std::shared_ptr session, chat_data["msg_content"] = chat.content; chat_data["chat_time"] = chat.chat_time; chat_data["status"] = chat.status; + chat_data["msg_type"] = chat.msg_type; + chat_data["receiver"] = chat.recv_id; rtvalue["chat_datas"].append(chat_data); } } + +void LogicSystem::DealChatImgMsg(std::shared_ptr session, + const short& msg_id, const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto uid = root["fromuid"].asInt(); + auto touid = root["touid"].asInt(); + + auto md5 = root["md5"].asString(); + auto unique_name = root["name"].asString(); + auto token = root["token"].asString(); + auto unique_id = root["unique_id"].asString(); + auto chat_time = root["chat_time"].asString(); + auto status = root["status"].asInt(); + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + + rtvalue["fromuid"] = uid; + rtvalue["touid"] = touid; + auto thread_id = root["thread_id"].asInt(); + rtvalue["thread_id"] = thread_id; + rtvalue["md5"] = md5; + rtvalue["unique_name"] = unique_name; + rtvalue["unique_id"] = unique_id; + rtvalue["chat_time"] = chat_time; + rtvalue["status"] = MsgStatus::UN_UPLOAD; + + auto timestamp = getCurrentTimestamp(); + auto chat_msg = std::make_shared(); + chat_msg->chat_time = timestamp; + chat_msg->sender_id = uid; + chat_msg->recv_id = touid; + chat_msg->unique_id = unique_id; + chat_msg->thread_id = thread_id; + chat_msg->content = unique_name; + chat_msg->status = MsgStatus::UN_UPLOAD; + chat_msg->msg_type = int(ChatMsgType::PIC); + + //ݿ + MysqlMgr::GetInstance()->AddChatMsg(chat_msg); + + rtvalue["message_id"] = chat_msg->message_id; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_MSG_RSP); + }); + +} + diff --git a/server/ChatServer2/LogicSystem.h b/server/ChatServer2/LogicSystem.h index fd96a77..cc62683 100644 --- a/server/ChatServer2/LogicSystem.h +++ b/server/ChatServer2/LogicSystem.h @@ -47,6 +47,8 @@ class LogicSystem:public Singleton int& nextLastId); void CreatePrivateChat(std::shared_ptr session, const short& msg_id, const string& msg_data); void LoadChatMsg(std::shared_ptr session, const short& msg_id, const string& msg_data); + void DealChatImgMsg(std::shared_ptr session, const short& msg_id, const string& msg_data); + std::thread _worker_thread; std::queue> _msg_que; std::mutex _mutex; diff --git a/server/ChatServer2/MysqlDao.cpp b/server/ChatServer2/MysqlDao.cpp index c47033e..2fc1dd1 100644 --- a/server/ChatServer2/MysqlDao.cpp +++ b/server/ChatServer2/MysqlDao.cpp @@ -243,6 +243,7 @@ bool MysqlDao::AuthFriendApply(const int& from, const int& to) { return true; } + bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, std::vector>& chat_datas) { auto con = pool_->getConnection(); @@ -255,8 +256,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, }); try { - - //ʼ + // ʼ con->_con->setAutoCommit(false); std::string reverse_back; std::string apply_desc; @@ -284,7 +284,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, return false; } } - + { // 2. ִĸ std::unique_ptr updStmt(con->_con->prepareStatement( @@ -292,7 +292,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, "SET status = 1 " "WHERE from_uid = ? AND to_uid = ?" )); - + updStmt->setInt(1, to); updStmt->setInt(2, from); @@ -302,32 +302,53 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, return false; } } - + { - // 3. ׼һSQL, ֤ - std::unique_ptr pstmt(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " - "VALUES (?, ?, ?) " + // 3. ѹϵ - ؼĽչ̶˳ + // ȷ˳ʼհ uid С˳ + int smaller_uid = std::min(from, to); + int larger_uid = std::max(from, to); + + // һβ룺С uid Ϊ self_id + std::unique_ptr pstmt(con->_con->prepareStatement( + "INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?)" )); - //ʱfrom֤ʱto - pstmt->setInt(1, from); // from id - pstmt->setInt(2, to); - pstmt->setString(3, back_name); - // ִи + + if (from == smaller_uid) { + pstmt->setInt(1, from); + pstmt->setInt(2, to); + pstmt->setString(3, back_name); + } + else { + pstmt->setInt(1, to); + pstmt->setInt(2, from); + pstmt->setString(3, reverse_back); + } + int rowAffected = pstmt->executeUpdate(); if (rowAffected < 0) { con->_con->rollback(); return false; } - //׼ڶSQL䣬뷽 - std::unique_ptr pstmt2(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " - "VALUES (?, ?, ?) " + // ڶβ룺ϴ uid Ϊ self_id + std::unique_ptr pstmt2(con->_con->prepareStatement( + "INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?)" )); - //ʱfrom֤ʱto - pstmt2->setInt(1, to); // from id - pstmt2->setInt(2, from); - pstmt2->setString(3, reverse_back); - // ִи + + if (from == larger_uid) { + pstmt2->setInt(1, from); + pstmt2->setInt(2, to); + pstmt2->setString(3, back_name); + } + else { + pstmt2->setInt(1, to); + pstmt2->setInt(2, from); + pstmt2->setString(3, reverse_back); + } + int rowAffected2 = pstmt2->executeUpdate(); if (rowAffected2 < 0) { con->_con->rollback(); @@ -335,15 +356,13 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, } } - - // 4. chat_thread long long threadId = 0; { std::unique_ptr threadStmt(con->_con->prepareStatement( - "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());" + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW())" )); - + threadStmt->executeUpdate(); std::unique_ptr stmt(con->_con->createStatement()); @@ -355,6 +374,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, threadId = rs->getInt64(1); } else { + con->_con->rollback(); return false; } } @@ -368,27 +388,37 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, pcStmt->setInt64(1, threadId); pcStmt->setInt(2, from); pcStmt->setInt(3, to); - if (pcStmt->executeUpdate() < 0) return false; + + if (pcStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } } - // 6. ѡʼϢ chat_message - if (apply_desc.empty() == false) + // 6. ʼϢ + if (!apply_desc.empty()) { std::unique_ptr msgStmt(con->_con->prepareStatement( - "INSERT INTO chat_message(thread_id, sender_id, recv_id, content,created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, NOW(), NOW(), ?)" )); - + msgStmt->setInt64(1, threadId); msgStmt->setInt(2, to); msgStmt->setInt(3, from); msgStmt->setString(4, apply_desc); msgStmt->setInt(5, 2); - if (msgStmt->executeUpdate() < 0) { return false; } + + if (msgStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } std::unique_ptr stmt(con->_con->createStatement()); std::unique_ptr rs( stmt->executeQuery("SELECT LAST_INSERT_ID()") ); + if (rs->next()) { auto messageId = rs->getInt64(1); auto tx_data = std::make_shared(); @@ -402,28 +432,34 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, chat_datas.push_back(tx_data); } else { + con->_con->rollback(); return false; } } + // 7. ΪѵϢ { std::unique_ptr msgStmt(con->_con->prepareStatement( - "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, NOW(), NOW(), ?)" )); - + msgStmt->setInt64(1, threadId); msgStmt->setInt(2, from); msgStmt->setInt(3, to); msgStmt->setString(4, "We are friends now!"); - msgStmt->setInt(5, 2); - if (msgStmt->executeUpdate() < 0) { return false; } + if (msgStmt->executeUpdate() < 0) { + con->_con->rollback(); + return false; + } std::unique_ptr stmt(con->_con->createStatement()); std::unique_ptr rs( stmt->executeQuery("SELECT LAST_INSERT_ID()") ); + if (rs->next()) { auto messageId = rs->getInt64(1); auto tx_data = std::make_shared(); @@ -436,6 +472,7 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, chat_datas.push_back(tx_data); } else { + con->_con->rollback(); return false; } } @@ -454,13 +491,20 @@ bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, std::cerr << "SQLException: " << e.what(); std::cerr << " (MySQL error code: " << e.getErrorCode(); std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + + // 1213Կ + if (e.getErrorCode() == 1213) { + std::cerr << "Deadlock detected, consider retry" << std::endl; + } + return false; } - return true; } + + std::shared_ptr MysqlDao::GetUser(int uid) { auto con = pool_->getConnection(); @@ -731,20 +775,21 @@ bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) if (!con) { return false; } + Defer defer([this, &con]() { pool_->returnConnection(std::move(con)); }); + auto& conn = con->_con; + int uid1 = std::min(user1_id, user2_id); + int uid2 = std::max(user1_id, user2_id); try { // conn->setAutoCommit(false); - // 1. ѯǷѴ˽IJм - int uid1 = std::min(user1_id, user2_id); - int uid2 = std::max(user1_id, user2_id); + // 1. ȳԲѯѴڵļ¼() std::string check_sql = "SELECT thread_id FROM private_chat " - "WHERE (user1_id = ? AND user2_id = ?) " - "FOR UPDATE;"; + "WHERE user1_id = ? AND user2_id = ?;"; std::unique_ptr pstmt(conn->prepareStatement(check_sql)); pstmt->setInt64(1, uid1); @@ -790,8 +835,34 @@ bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) return true; } catch (sql::SQLException& e) { - std::cerr << "SQLException: " << e.what() << std::endl; conn->rollback(); + + // ǷΨһͻ (MySQL error code 1062) + if (e.getErrorCode() == 1062) { + // ²ѯѴڵļ¼ + try { + conn->setAutoCommit(true); + std::string retry_sql = + "SELECT thread_id FROM private_chat " + "WHERE user1_id = ? AND user2_id = ?;"; + std::unique_ptr pstmt_retry( + conn->prepareStatement(retry_sql)); + pstmt_retry->setInt64(1, uid1); + pstmt_retry->setInt64(2, uid2); + std::unique_ptr res_retry(pstmt_retry->executeQuery()); + + if (res_retry->next()) { + thread_id = res_retry->getInt("thread_id"); + return true; + } + } + catch (...) { + return false; + } + } + + std::cerr << "SQLException: " << e.what() + << " (Code: " << e.getErrorCode() << ")" << std::endl; return false; } return false; @@ -812,12 +883,10 @@ std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_messag try { auto page_res = std::make_shared(); page_res->load_more = false; - page_res->next_cursor = last_message_id; - // SQLȡһжǷи const std::string sql = R"( SELECT message_id, thread_id, sender_id, recv_id, content, - created_at, updated_at, status + created_at, updated_at, status,msg_type FROM chat_message WHERE thread_id = ? AND message_id > ? @@ -845,8 +914,15 @@ std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_messag msg.content = rs->getString("content"); msg.chat_time = rs->getString("created_at"); msg.status = rs->getInt("status"); + msg.msg_type = rs->getInt("msg_type"); page_res->messages.push_back(std::move(msg)); } + if (page_res->messages.size() > page_size) { + page_res->messages.pop_back(); + page_res->load_more = true; + } + + page_res->next_cursor = page_res->messages.back().message_id; return page_res; } @@ -877,8 +953,8 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) auto pstmt = std::unique_ptr( conn->prepareStatement( "INSERT INTO chat_message " - "(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " - "VALUES (?, ?, ?, ?, ?, ?, ?)" + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status,msg_type) " + "VALUES (?, ?, ?, ?, ?, ?, ?,?)" ) ); @@ -893,6 +969,7 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) pstmt->setString(6, msg->chat_time); // updated_at pstmt->setInt(7, msg->status); + pstmt->setInt(8, msg->msg_type); pstmt->executeUpdate(); // 2. ȡ LAST_INSERT_ID() @@ -921,3 +998,106 @@ bool MysqlDao::AddChatMsg(std::vector>& chat_datas) return true; } + +bool MysqlDao::AddChatMsg(std::shared_ptr chat_data) { + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + try { + //رԶύֶ + conn->setAutoCommit(false); + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "INSERT INTO chat_message " + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status,msg_type) " + "VALUES (?, ?, ?, ?, ?, ?, ?,?)" + ) + ); + + // 󶨲 + pstmt->setUInt64(1, chat_data->thread_id); + pstmt->setUInt64(2, chat_data->sender_id); + pstmt->setUInt64(3, chat_data->recv_id); + pstmt->setString(4, chat_data->content); + pstmt->setString(5, chat_data->chat_time); // created_at + pstmt->setString(6, chat_data->chat_time); // updated_at + pstmt->setInt(7, chat_data->status); + pstmt->setInt(8, chat_data->msg_type); + + pstmt->executeUpdate(); + + // ȡ + std::unique_ptr keyStmt( + conn->createStatement() + ); + std::unique_ptr rs( + keyStmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + chat_data->message_id = rs->getUInt64(1); + } + + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } +} + +std::shared_ptr MysqlDao::GetChatMsg(int message_id) +{ + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + + try { + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "SELECT message_id, thread_id, sender_id, recv_id, " + "content, created_at, updated_at, status , msg_type" + "FROM chat_message WHERE message_id = ?" + ) + ); + + pstmt->setUInt64(1, message_id); + auto rs = std::unique_ptr(pstmt->executeQuery()); + + if (rs->next()) { + auto msg = std::make_shared(); + msg->message_id = rs->getUInt64("message_id"); + msg->thread_id = rs->getUInt64("thread_id"); + msg->sender_id = rs->getUInt64("sender_id"); + msg->recv_id = rs->getUInt64("recv_id"); + msg->content = rs->getString("content"); + msg->chat_time = rs->getString("created_at"); + msg->status = rs->getInt("status"); + msg->msg_type = rs->getInt("msg_type"); + + return msg; + } + + return nullptr; + + } + catch (sql::SQLException& e) { + std::cerr << "GetChatMessageById SQLException: " << e.what() << std::endl; + return nullptr; + } +} + diff --git a/server/ChatServer2/MysqlDao.h b/server/ChatServer2/MysqlDao.h index a6441f3..4bf0535 100644 --- a/server/ChatServer2/MysqlDao.h +++ b/server/ChatServer2/MysqlDao.h @@ -245,6 +245,7 @@ class MysqlDao bool AddFriendApply(const int& from, const int& to, const std::string& desc, const std::string& back_name); bool AuthFriendApply(const int& from, const int& to); bool AddFriend(const int& from, const int& to, std::string back_name, std::vector> &chat_datas); + std::shared_ptr GetUser(int uid); std::shared_ptr GetUser(std::string name); bool GetApplyList(int touid, std::vector>& applyList, int offset, int limit ); @@ -259,6 +260,8 @@ class MysqlDao bool CreatePrivateChat(int user1_id, int user2_id, int& thread_id); std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); bool AddChatMsg(std::vector>& chat_datas); + bool AddChatMsg(std::shared_ptr chat_data); + std::shared_ptr GetChatMsg(int message_id); private: std::unique_ptr pool_; }; diff --git a/server/ChatServer2/MysqlMgr.cpp b/server/ChatServer2/MysqlMgr.cpp index 951e57a..45c75c0 100644 --- a/server/ChatServer2/MysqlMgr.cpp +++ b/server/ChatServer2/MysqlMgr.cpp @@ -83,3 +83,12 @@ bool MysqlMgr::AddChatMsg(std::vector>& chat_datas) return _dao.AddChatMsg(chat_datas); } +bool MysqlMgr::AddChatMsg(std::shared_ptr chat_data) { + return _dao.AddChatMsg(chat_data); +} + +std::shared_ptr MysqlMgr::GetChatMsg(int message_id) +{ + return _dao.GetChatMsg(message_id); +} + diff --git a/server/ChatServer2/MysqlMgr.h b/server/ChatServer2/MysqlMgr.h index f6a71b3..8321724 100644 --- a/server/ChatServer2/MysqlMgr.h +++ b/server/ChatServer2/MysqlMgr.h @@ -31,6 +31,8 @@ class MysqlMgr: public Singleton bool CreatePrivateChat(int user1_id, int user2_id, int &thread_id); std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); bool AddChatMsg(std::vector>& chat_datas); + bool AddChatMsg(std::shared_ptr chat_data); + std::shared_ptr GetChatMsg(int message_id); private: MysqlMgr(); MysqlDao _dao; diff --git a/server/ChatServer2/const.h b/server/ChatServer2/const.h index b15b23f..85b54ad 100644 --- a/server/ChatServer2/const.h +++ b/server/ChatServer2/const.h @@ -70,6 +70,12 @@ enum MSG_IDS { ID_LOAD_CHAT_MSG_REQ = 1029, //Ϣ ID_LOAD_CHAT_MSG_RSP = 1030, //Ϣ + + ID_IMG_CHAT_MSG_REQ = 1035, //ͼƬϢ + ID_IMG_CHAT_MSG_RSP = 1036, //ͼƬϢظ + ID_NOTIFY_IMG_CHAT_MSG_REQ = 1039, //֪ͨûͼƬϢ + ID_FILE_INFO_SYNC_REQ = 1041, //ļϢͬ + ID_FILE_INFO_SYNC_RSP = 1042 //ļϢͬظ }; #define USERIPPREFIX "uip_" @@ -87,4 +93,11 @@ enum MSG_IDS { //ֲʽʱ #define ACQUIRE_TIME_OUT 5 +enum MsgStatus { + UN_READ = 0, //Էδ + SEND_FAILED = 1, //ʧ + READED = 2, //ԷѶ + UN_UPLOAD = 3 //δϴ +}; + diff --git a/server/ChatServer2/data.h b/server/ChatServer2/data.h index 1901079..2a08a37 100644 --- a/server/ChatServer2/data.h +++ b/server/ChatServer2/data.h @@ -47,6 +47,7 @@ struct ChatMessage { std::string content; std::string chat_time; int status; + int msg_type; }; // ѯṹnext_cursorֶ @@ -55,3 +56,10 @@ struct PageResult { bool load_more; int next_cursor; // ҳһmessage_id´βѯ }; + +enum class ChatMsgType { + TEXT = 0, + PIC = 1, + VIDEO = 2, + FILE = 3 +}; \ No newline at end of file diff --git a/server/ChatServer2/message.grpc.pb.cc b/server/ChatServer2/message.grpc.pb.cc index 1e98fcd..6014ed6 100644 --- a/server/ChatServer2/message.grpc.pb.cc +++ b/server/ChatServer2/message.grpc.pb.cc @@ -192,6 +192,7 @@ static const char* ChatService_method_names[] = { "/message.ChatService/NotifyAuthFriend", "/message.ChatService/NotifyTextChatMsg", "/message.ChatService/NotifyKickUser", + "/message.ChatService/NotifyChatImgMsg", }; std::unique_ptr< ChatService::Stub> ChatService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { @@ -207,6 +208,7 @@ ChatService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channe , rpcmethod_NotifyAuthFriend_(ChatService_method_names[3], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_NotifyTextChatMsg_(ChatService_method_names[4], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_NotifyKickUser_(ChatService_method_names[5], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyChatImgMsg_(ChatService_method_names[6], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) {} ::grpc::Status ChatService::Stub::NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::message::AddFriendRsp* response) { @@ -347,6 +349,29 @@ ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* ChatService::Stub::A return result; } +::grpc::Status ChatService::Stub::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyChatImgMsg_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::NotifyChatImgRsp, ::message::NotifyChatImgReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyChatImgMsg_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyChatImgMsgRaw(context, request, cq); + result->StartCall(); + return result; +} + ChatService::Service::Service() { AddMethod(new ::grpc::internal::RpcServiceMethod( ChatService_method_names[0], @@ -408,6 +433,16 @@ ChatService::Service::Service() { ::message::KickUserRsp* resp) { return service->NotifyKickUser(ctx, req, resp); }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[6], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::NotifyChatImgReq* req, + ::message::NotifyChatImgRsp* resp) { + return service->NotifyChatImgMsg(ctx, req, resp); + }, this))); } ChatService::Service::~Service() { @@ -455,6 +490,13 @@ ::grpc::Status ChatService::Service::NotifyKickUser(::grpc::ServerContext* conte return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } +::grpc::Status ChatService::Service::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + } // namespace message diff --git a/server/ChatServer2/message.grpc.pb.h b/server/ChatServer2/message.grpc.pb.h index a27d500..bd0efca 100644 --- a/server/ChatServer2/message.grpc.pb.h +++ b/server/ChatServer2/message.grpc.pb.h @@ -795,6 +795,13 @@ class ChatService final { std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); } + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } class experimental_async_interface { public: virtual ~experimental_async_interface() {} @@ -834,6 +841,12 @@ class ChatService final { #else virtual void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; #endif + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif }; #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL typedef class experimental_async_interface async_interface; @@ -855,6 +868,8 @@ class ChatService final { virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; }; class Stub final : public StubInterface { public: @@ -901,6 +916,13 @@ class ChatService final { std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); } + ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } class experimental_async final : public StubInterface::experimental_async_interface { public: @@ -940,6 +962,12 @@ class ChatService final { #else void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; #endif + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif private: friend class Stub; explicit experimental_async(Stub* stub): stub_(stub) { } @@ -963,12 +991,15 @@ class ChatService final { ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; const ::grpc::internal::RpcMethod rpcmethod_NotifyAddFriend_; const ::grpc::internal::RpcMethod rpcmethod_RplyAddFriend_; const ::grpc::internal::RpcMethod rpcmethod_SendChatMsg_; const ::grpc::internal::RpcMethod rpcmethod_NotifyAuthFriend_; const ::grpc::internal::RpcMethod rpcmethod_NotifyTextChatMsg_; const ::grpc::internal::RpcMethod rpcmethod_NotifyKickUser_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyChatImgMsg_; }; static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); @@ -982,6 +1013,7 @@ class ChatService final { virtual ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response); virtual ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response); virtual ::grpc::Status NotifyKickUser(::grpc::ServerContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response); + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response); }; template class WithAsyncMethod_NotifyAddFriend : public BaseClass { @@ -1103,7 +1135,27 @@ class ChatService final { ::grpc::Service::RequestAsyncUnary(5, context, request, response, new_call_cq, notification_cq, tag); } }; - typedef WithAsyncMethod_NotifyAddFriend > > > > > AsyncService; + template + class WithAsyncMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodAsync(6); + } + ~WithAsyncMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::message::NotifyChatImgReq* request, ::grpc::ServerAsyncResponseWriter< ::message::NotifyChatImgRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_NotifyAddFriend > > > > > > AsyncService; template class ExperimentalWithCallbackMethod_NotifyAddFriend : public BaseClass { private: @@ -1386,11 +1438,58 @@ class ChatService final { #endif { return nullptr; } }; + template + class ExperimentalWithCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { return this->NotifyChatImgMsg(context, request, response); }));} + void SetMessageAllocatorFor_NotifyChatImgMsg( + ::grpc::experimental::MessageAllocator< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(6); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(6); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #endif + { return nullptr; } + }; #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL - typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > CallbackService; + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > CallbackService; #endif - typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > ExperimentalCallbackService; + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > ExperimentalCallbackService; template class WithGenericMethod_NotifyAddFriend : public BaseClass { private: @@ -1494,6 +1593,23 @@ class ChatService final { } }; template + class WithGenericMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodGeneric(6); + } + ~WithGenericMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template class WithRawMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -1614,6 +1730,26 @@ class ChatService final { } }; template + class WithRawMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodRaw(6); + } + ~WithRawMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template class ExperimentalWithRawCallbackMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -1842,6 +1978,44 @@ class ChatService final { { return nullptr; } }; template + class ExperimentalWithRawCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyChatImgMsg(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template class WithStreamedUnaryMethod_NotifyAddFriend : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} @@ -2003,9 +2177,36 @@ class ChatService final { // replace default version of method with streamed unary virtual ::grpc::Status StreamedNotifyKickUser(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::KickUserReq,::message::KickUserRsp>* server_unary_streamer) = 0; }; - typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > StreamedUnaryService; + template + class WithStreamedUnaryMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodStreamed(6, + new ::grpc::internal::StreamedUnaryHandler< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* streamer) { + return this->StreamedNotifyChatImgMsg(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::NotifyChatImgReq,::message::NotifyChatImgRsp>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedUnaryService; typedef Service SplitStreamedService; - typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > StreamedService; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedService; }; } // namespace message diff --git a/server/ChatServer2/message.pb.cc b/server/ChatServer2/message.pb.cc index 5fea1ff..1cc6cc6 100644 --- a/server/ChatServer2/message.pb.cc +++ b/server/ChatServer2/message.pb.cc @@ -97,6 +97,14 @@ class KickUserRspDefaultTypeInternal { public: ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; } _KickUserRsp_default_instance_; +class NotifyChatImgReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgReq_default_instance_; +class NotifyChatImgRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgRsp_default_instance_; } // namespace message static void InitDefaultsscc_info_AddFriendMsg_message_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -281,6 +289,34 @@ static void InitDefaultsscc_info_LoginRsp_message_2eproto() { ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_LoginRsp_message_2eproto = {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_LoginRsp_message_2eproto}, {}}; +static void InitDefaultsscc_info_NotifyChatImgReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgReq_default_instance_; + new (ptr) ::message::NotifyChatImgReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgRsp_default_instance_; + new (ptr) ::message::NotifyChatImgRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto}, {}}; + static void InitDefaultsscc_info_RplyFriendReq_message_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -381,7 +417,7 @@ ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_TextChatMsgRsp_message_2e {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_TextChatMsgRsp_message_2eproto}, { &scc_info_TextChatData_message_2eproto.base,}}; -static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_message_2eproto[20]; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_message_2eproto[22]; static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_message_2eproto = nullptr; static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_message_2eproto = nullptr; @@ -550,6 +586,29 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_message_2eproto::offsets[] PRO ~0u, // no _weak_field_map_ PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, error_), PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, uid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, thread_id_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, thread_id_), }; static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { { 0, -1, sizeof(::message::GetVarifyReq)}, @@ -572,6 +631,8 @@ static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOB { 141, -1, sizeof(::message::TextChatMsgRsp)}, { 151, -1, sizeof(::message::KickUserReq)}, { 157, -1, sizeof(::message::KickUserRsp)}, + { 164, -1, sizeof(::message::NotifyChatImgReq)}, + { 175, -1, sizeof(::message::NotifyChatImgRsp)}, }; static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { @@ -595,6 +656,8 @@ static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = reinterpret_cast(&::message::_TextChatMsgRsp_default_instance_), reinterpret_cast(&::message::_KickUserReq_default_instance_), reinterpret_cast(&::message::_KickUserRsp_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgReq_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgRsp_default_instance_), }; const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = @@ -633,28 +696,37 @@ const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE "romuid\030\002 \001(\005\022\r\n\005touid\030\003 \001(\005\022\021\n\tthread_id" "\030\004 \001(\005\022\'\n\010textmsgs\030\005 \003(\0132\025.message.TextC" "hatData\"\032\n\013KickUserReq\022\013\n\003uid\030\001 \001(\005\")\n\013K" - "ickUserRsp\022\r\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\0052P" - "\n\rVarifyService\022\?\n\rGetVarifyCode\022\025.messa" - "ge.GetVarifyReq\032\025.message.GetVarifyRsp\"\000" - "2\207\001\n\rStatusService\022G\n\rGetChatServer\022\031.me" - "ssage.GetChatServerReq\032\031.message.GetChat" - "ServerRsp\"\000\022-\n\005Login\022\021.message.LoginReq\032" - "\021.message.LoginRsp2\245\003\n\013ChatService\022A\n\017No" - "tifyAddFriend\022\025.message.AddFriendReq\032\025.m" - "essage.AddFriendRsp\"\000\022A\n\rRplyAddFriend\022\026" - ".message.RplyFriendReq\032\026.message.RplyFri" - "endRsp\"\000\022A\n\013SendChatMsg\022\027.message.SendCh" - "atMsgReq\032\027.message.SendChatMsgRsp\"\000\022D\n\020N" - "otifyAuthFriend\022\026.message.AuthFriendReq\032" - "\026.message.AuthFriendRsp\"\000\022G\n\021NotifyTextC" - "hatMsg\022\027.message.TextChatMsgReq\032\027.messag" - "e.TextChatMsgRsp\"\000\022>\n\016NotifyKickUser\022\024.m" - "essage.KickUserReq\032\024.message.KickUserRsp" - "\"\000b\006proto3" + "ickUserRsp\022\r\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\005\"\202" + "\001\n\020NotifyChatImgReq\022\020\n\010from_uid\030\001 \001(\005\022\016\n" + "\006to_uid\030\002 \001(\005\022\022\n\nmessage_id\030\003 \001(\005\022\021\n\tfil" + "e_name\030\004 \001(\t\022\022\n\ntotal_size\030\005 \001(\003\022\021\n\tthre" + "ad_id\030\006 \001(\005\"\221\001\n\020NotifyChatImgRsp\022\r\n\005erro" + "r\030\001 \001(\005\022\020\n\010from_uid\030\002 \001(\005\022\016\n\006to_uid\030\003 \001(" + "\005\022\022\n\nmessage_id\030\004 \001(\005\022\021\n\tfile_name\030\005 \001(\t" + "\022\022\n\ntotal_size\030\006 \001(\003\022\021\n\tthread_id\030\007 \001(\0052" + "P\n\rVarifyService\022\?\n\rGetVarifyCode\022\025.mess" + "age.GetVarifyReq\032\025.message.GetVarifyRsp\"" + "\0002\207\001\n\rStatusService\022G\n\rGetChatServer\022\031.m" + "essage.GetChatServerReq\032\031.message.GetCha" + "tServerRsp\"\000\022-\n\005Login\022\021.message.LoginReq" + "\032\021.message.LoginRsp2\361\003\n\013ChatService\022A\n\017N" + "otifyAddFriend\022\025.message.AddFriendReq\032\025." + "message.AddFriendRsp\"\000\022A\n\rRplyAddFriend\022" + "\026.message.RplyFriendReq\032\026.message.RplyFr" + "iendRsp\"\000\022A\n\013SendChatMsg\022\027.message.SendC" + "hatMsgReq\032\027.message.SendChatMsgRsp\"\000\022D\n\020" + "NotifyAuthFriend\022\026.message.AuthFriendReq" + "\032\026.message.AuthFriendRsp\"\000\022G\n\021NotifyText" + "ChatMsg\022\027.message.TextChatMsgReq\032\027.messa" + "ge.TextChatMsgRsp\"\000\022>\n\016NotifyKickUser\022\024." + "message.KickUserReq\032\024.message.KickUserRs" + "p\"\000\022J\n\020NotifyChatImgMsg\022\031.message.Notify" + "ChatImgReq\032\031.message.NotifyChatImgRsp\"\000b" + "\006proto3" ; static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_message_2eproto_deps[1] = { }; -static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_message_2eproto_sccs[20] = { +static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_message_2eproto_sccs[22] = { &scc_info_AddFriendMsg_message_2eproto.base, &scc_info_AddFriendReq_message_2eproto.base, &scc_info_AddFriendRsp_message_2eproto.base, @@ -668,6 +740,8 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_mes &scc_info_KickUserRsp_message_2eproto.base, &scc_info_LoginReq_message_2eproto.base, &scc_info_LoginRsp_message_2eproto.base, + &scc_info_NotifyChatImgReq_message_2eproto.base, + &scc_info_NotifyChatImgRsp_message_2eproto.base, &scc_info_RplyFriendReq_message_2eproto.base, &scc_info_RplyFriendRsp_message_2eproto.base, &scc_info_SendChatMsgReq_message_2eproto.base, @@ -678,10 +752,10 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_mes }; static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_message_2eproto_once; const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_message_2eproto = { - false, false, descriptor_table_protodef_message_2eproto, "message.proto", 2090, - &descriptor_table_message_2eproto_once, descriptor_table_message_2eproto_sccs, descriptor_table_message_2eproto_deps, 20, 0, + false, false, descriptor_table_protodef_message_2eproto, "message.proto", 2447, + &descriptor_table_message_2eproto_once, descriptor_table_message_2eproto_sccs, descriptor_table_message_2eproto_deps, 22, 0, schemas, file_default_instances, TableStruct_message_2eproto::offsets, - file_level_metadata_message_2eproto, 20, file_level_enum_descriptors_message_2eproto, file_level_service_descriptors_message_2eproto, + file_level_metadata_message_2eproto, 22, file_level_enum_descriptors_message_2eproto, file_level_service_descriptors_message_2eproto, }; // Force running AddDescriptors() at dynamic initialization time. @@ -6086,6 +6160,707 @@ ::PROTOBUF_NAMESPACE_ID::Metadata KickUserRsp::GetMetadata() const { } +// =================================================================== + +void NotifyChatImgReq::InitAsDefaultInstance() { +} +class NotifyChatImgReq::_Internal { + public: +}; + +NotifyChatImgReq::NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgReq) +} +NotifyChatImgReq::NotifyChatImgReq(const NotifyChatImgReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&from_uid_, &from.from_uid_, + static_cast(reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgReq) +} + +void NotifyChatImgReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgReq_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); +} + +NotifyChatImgReq::~NotifyChatImgReq() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgReq::ArenaDtor(void* object) { + NotifyChatImgReq* _this = reinterpret_cast< NotifyChatImgReq* >(object); + (void)_this; +} +void NotifyChatImgReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgReq& NotifyChatImgReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 from_uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgReq.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_from_uid(), target); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_to_uid(), target); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_message_id(), target); + } + + // string file_name = 4; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgReq.file_name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_file_name(), target); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(5, this->_internal_total_size(), target); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(6, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgReq) + return target; +} + +size_t NotifyChatImgReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 4; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgReq) + MergeFrom(*source); + } +} + +void NotifyChatImgReq::MergeFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } +} + +void NotifyChatImgReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgReq::CopyFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgReq::IsInitialized() const { + return true; +} + +void NotifyChatImgReq::InternalSwap(NotifyChatImgReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, total_size_) + + sizeof(NotifyChatImgReq::total_size_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, from_uid_)>( + reinterpret_cast(&from_uid_), + reinterpret_cast(&other->from_uid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void NotifyChatImgRsp::InitAsDefaultInstance() { +} +class NotifyChatImgRsp::_Internal { + public: +}; + +NotifyChatImgRsp::NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgRsp) +} +NotifyChatImgRsp::NotifyChatImgRsp(const NotifyChatImgRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgRsp) +} + +void NotifyChatImgRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgRsp_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); +} + +NotifyChatImgRsp::~NotifyChatImgRsp() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgRsp::ArenaDtor(void* object) { + NotifyChatImgRsp* _this = reinterpret_cast< NotifyChatImgRsp* >(object); + (void)_this; +} +void NotifyChatImgRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgRsp& NotifyChatImgRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 from_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgRsp.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_from_uid(), target); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_to_uid(), target); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_message_id(), target); + } + + // string file_name = 5; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgRsp.file_name"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_file_name(), target); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(6, this->_internal_total_size(), target); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(7, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgRsp) + return target; +} + +size_t NotifyChatImgRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 5; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgRsp) + MergeFrom(*source); + } +} + +void NotifyChatImgRsp::MergeFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } +} + +void NotifyChatImgRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgRsp::CopyFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgRsp::IsInitialized() const { + return true; +} + +void NotifyChatImgRsp::InternalSwap(NotifyChatImgRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, thread_id_) + + sizeof(NotifyChatImgRsp::thread_id_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + // @@protoc_insertion_point(namespace_scope) } // namespace message PROTOBUF_NAMESPACE_OPEN @@ -6149,6 +6924,12 @@ template<> PROTOBUF_NOINLINE ::message::KickUserReq* Arena::CreateMaybeMessage< template<> PROTOBUF_NOINLINE ::message::KickUserRsp* Arena::CreateMaybeMessage< ::message::KickUserRsp >(Arena* arena) { return Arena::CreateMessageInternal< ::message::KickUserRsp >(arena); } +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgReq* Arena::CreateMaybeMessage< ::message::NotifyChatImgReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage< ::message::NotifyChatImgRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgRsp >(arena); +} PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) diff --git a/server/ChatServer2/message.pb.h b/server/ChatServer2/message.pb.h index 804f4de..426e615 100644 --- a/server/ChatServer2/message.pb.h +++ b/server/ChatServer2/message.pb.h @@ -47,7 +47,7 @@ struct TableStruct_message_2eproto { PROTOBUF_SECTION_VARIABLE(protodesc_cold); static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] PROTOBUF_SECTION_VARIABLE(protodesc_cold); - static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[20] + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[22] PROTOBUF_SECTION_VARIABLE(protodesc_cold); static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; @@ -94,6 +94,12 @@ extern LoginReqDefaultTypeInternal _LoginReq_default_instance_; class LoginRsp; class LoginRspDefaultTypeInternal; extern LoginRspDefaultTypeInternal _LoginRsp_default_instance_; +class NotifyChatImgReq; +class NotifyChatImgReqDefaultTypeInternal; +extern NotifyChatImgReqDefaultTypeInternal _NotifyChatImgReq_default_instance_; +class NotifyChatImgRsp; +class NotifyChatImgRspDefaultTypeInternal; +extern NotifyChatImgRspDefaultTypeInternal _NotifyChatImgRsp_default_instance_; class RplyFriendReq; class RplyFriendReqDefaultTypeInternal; extern RplyFriendReqDefaultTypeInternal _RplyFriendReq_default_instance_; @@ -130,6 +136,8 @@ template<> ::message::KickUserReq* Arena::CreateMaybeMessage<::message::KickUser template<> ::message::KickUserRsp* Arena::CreateMaybeMessage<::message::KickUserRsp>(Arena*); template<> ::message::LoginReq* Arena::CreateMaybeMessage<::message::LoginReq>(Arena*); template<> ::message::LoginRsp* Arena::CreateMaybeMessage<::message::LoginRsp>(Arena*); +template<> ::message::NotifyChatImgReq* Arena::CreateMaybeMessage<::message::NotifyChatImgReq>(Arena*); +template<> ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage<::message::NotifyChatImgRsp>(Arena*); template<> ::message::RplyFriendReq* Arena::CreateMaybeMessage<::message::RplyFriendReq>(Arena*); template<> ::message::RplyFriendRsp* Arena::CreateMaybeMessage<::message::RplyFriendRsp>(Arena*); template<> ::message::SendChatMsgReq* Arena::CreateMaybeMessage<::message::SendChatMsgReq>(Arena*); @@ -3517,6 +3525,415 @@ class KickUserRsp PROTOBUF_FINAL : mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; friend struct ::TableStruct_message_2eproto; }; +// ------------------------------------------------------------------- + +class NotifyChatImgReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgReq) */ { + public: + inline NotifyChatImgReq() : NotifyChatImgReq(nullptr) {} + virtual ~NotifyChatImgReq(); + + NotifyChatImgReq(const NotifyChatImgReq& from); + NotifyChatImgReq(NotifyChatImgReq&& from) noexcept + : NotifyChatImgReq() { + *this = ::std::move(from); + } + + inline NotifyChatImgReq& operator=(const NotifyChatImgReq& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgReq& operator=(NotifyChatImgReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgReq* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 20; + + friend void swap(NotifyChatImgReq& a, NotifyChatImgReq& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgReq& from); + void MergeFrom(const NotifyChatImgReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgReq"; + } + protected: + explicit NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 4, + kFromUidFieldNumber = 1, + kToUidFieldNumber = 2, + kMessageIdFieldNumber = 3, + kThreadIdFieldNumber = 6, + kTotalSizeFieldNumber = 5, + }; + // string file_name = 4; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 from_uid = 1; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 2; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 3; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 6; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 5; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class NotifyChatImgRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgRsp) */ { + public: + inline NotifyChatImgRsp() : NotifyChatImgRsp(nullptr) {} + virtual ~NotifyChatImgRsp(); + + NotifyChatImgRsp(const NotifyChatImgRsp& from); + NotifyChatImgRsp(NotifyChatImgRsp&& from) noexcept + : NotifyChatImgRsp() { + *this = ::std::move(from); + } + + inline NotifyChatImgRsp& operator=(const NotifyChatImgRsp& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgRsp& operator=(NotifyChatImgRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgRsp* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 21; + + friend void swap(NotifyChatImgRsp& a, NotifyChatImgRsp& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgRsp& from); + void MergeFrom(const NotifyChatImgRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgRsp"; + } + protected: + explicit NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 5, + kErrorFieldNumber = 1, + kFromUidFieldNumber = 2, + kToUidFieldNumber = 3, + kMessageIdFieldNumber = 4, + kTotalSizeFieldNumber = 6, + kThreadIdFieldNumber = 7, + }; + // string file_name = 5; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 from_uid = 2; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 3; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 4; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 6; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // int32 thread_id = 7; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; // =================================================================== @@ -5697,6 +6114,358 @@ inline void KickUserRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { // @@protoc_insertion_point(field_set:message.KickUserRsp.uid) } +// ------------------------------------------------------------------- + +// NotifyChatImgReq + +// int32 from_uid = 1; +inline void NotifyChatImgReq::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgReq::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgReq::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.from_uid) +} + +// int32 to_uid = 2; +inline void NotifyChatImgReq::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgReq::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgReq::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.to_uid) +} + +// int32 message_id = 3; +inline void NotifyChatImgReq::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgReq::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgReq::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.message_id) +} + +// string file_name = 4; +inline void NotifyChatImgReq::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgReq::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgReq::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgReq.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgReq::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgReq::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgReq::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgReq::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgReq.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgReq::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgReq.file_name) +} + +// int64 total_size = 5; +inline void NotifyChatImgReq::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgReq::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgReq::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.total_size) +} + +// int32 thread_id = 6; +inline void NotifyChatImgReq::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgReq::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgReq::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.thread_id) +} + +// ------------------------------------------------------------------- + +// NotifyChatImgRsp + +// int32 error = 1; +inline void NotifyChatImgRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::error() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.error) + return _internal_error(); +} +inline void NotifyChatImgRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void NotifyChatImgRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.error) +} + +// int32 from_uid = 2; +inline void NotifyChatImgRsp::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgRsp::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgRsp::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.from_uid) +} + +// int32 to_uid = 3; +inline void NotifyChatImgRsp::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgRsp::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgRsp::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.to_uid) +} + +// int32 message_id = 4; +inline void NotifyChatImgRsp::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgRsp::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgRsp::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.message_id) +} + +// string file_name = 5; +inline void NotifyChatImgRsp::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgRsp::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgRsp::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgRsp.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgRsp::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgRsp::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgRsp::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgRsp::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgRsp.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgRsp::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgRsp.file_name) +} + +// int64 total_size = 6; +inline void NotifyChatImgRsp::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgRsp::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgRsp::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.total_size) +} + +// int32 thread_id = 7; +inline void NotifyChatImgRsp::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgRsp::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgRsp::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.thread_id) +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ @@ -5738,6 +6507,10 @@ inline void KickUserRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/server/ChatServer2/message.proto b/server/ChatServer2/message.proto index 2cd23c2..2cef837 100644 --- a/server/ChatServer2/message.proto +++ b/server/ChatServer2/message.proto @@ -135,6 +135,26 @@ message KickUserRsp{ int32 uid = 2; } + +message NotifyChatImgReq{ + int32 from_uid = 1; + int32 to_uid = 2; + int32 message_id = 3; + string file_name = 4; + int64 total_size = 5; + int32 thread_id =6; +} + +message NotifyChatImgRsp{ + int32 error = 1; + int32 from_uid = 2; + int32 to_uid = 3; + int32 message_id = 4; + string file_name = 5; + int64 total_size = 6; + int32 thread_id =7; +} + service ChatService { rpc NotifyAddFriend(AddFriendReq) returns (AddFriendRsp) {} rpc RplyAddFriend(RplyFriendReq) returns (RplyFriendRsp) {} @@ -142,4 +162,5 @@ service ChatService { rpc NotifyAuthFriend(AuthFriendReq) returns (AuthFriendRsp) {} rpc NotifyTextChatMsg(TextChatMsgReq) returns (TextChatMsgRsp){} rpc NotifyKickUser(KickUserReq) returns (KickUserRsp){} + rpc NotifyChatImgMsg(NotifyChatImgReq) returns (NotifyChatImgRsp){} } diff --git a/server/GateServer/LogicSystem.cpp b/server/GateServer/LogicSystem.cpp index 1f9667a..7890ed1 100644 --- a/server/GateServer/LogicSystem.cpp +++ b/server/GateServer/LogicSystem.cpp @@ -277,8 +277,14 @@ LogicSystem::LogicSystem() { root["email"] = email; root["uid"] = userInfo.uid; root["token"] = reply.token(); - root["host"] = reply.host(); - root["port"] = reply.port(); + root["chathost"] = reply.host(); + root["chatport"] = reply.port(); + auto& gCfgMgr = ConfigMgr::Inst(); + std::string res_port = gCfgMgr["ResServer"]["Port"]; + std::string res_host = gCfgMgr["ResServer"]["Host"]; + root["reshost"] = res_host; + root["resport"] = res_port; + std::string jsonstr = root.toStyledString(); beast::ostream(connection->_response.body()) << jsonstr; return true; diff --git a/server/GateServer/config.ini b/server/GateServer/config.ini index 1e163e0..7efa97f 100644 --- a/server/GateServer/config.ini +++ b/server/GateServer/config.ini @@ -16,3 +16,9 @@ Schema = llfc Host = 81.68.86.146 Port = 6380 Passwd = 123456 +[ResServer] +Name = reserver +Host = 127.0.0.1 +Port = 9090 +RPCPort = 51055 + diff --git a/server/ResourceServer/AsioIOServicePool.cpp b/server/ResourceServer/AsioIOServicePool.cpp new file mode 100644 index 0000000..4c5c748 --- /dev/null +++ b/server/ResourceServer/AsioIOServicePool.cpp @@ -0,0 +1,42 @@ +#include "AsioIOServicePool.h" +#include +using namespace std; +AsioIOServicePool::AsioIOServicePool(std::size_t size):_ioServices(size), +_works(size), _nextIOService(0){ + for (std::size_t i = 0; i < size; ++i) { + _works[i] = std::unique_ptr(new Work(_ioServices[i])); + } + + //遍历多个ioservice,创建多个线程,每个线程内部启动ioservice + for (std::size_t i = 0; i < _ioServices.size(); ++i) { + _threads.emplace_back([this, i]() { + _ioServices[i].run(); + }); + } +} + +AsioIOServicePool::~AsioIOServicePool() { + std::cout << "AsioIOServicePool destruct" << endl; +} + +boost::asio::io_context& AsioIOServicePool::GetIOService() { + auto& service = _ioServices[_nextIOService++]; + if (_nextIOService == _ioServices.size()) { + _nextIOService = 0; + } + return service; +} + +void AsioIOServicePool::Stop(){ + //因为仅仅执行work.reset并不能让iocontext从run的状态中退出 + //当iocontext已经绑定了读或写的监听事件后,还需要手动stop该服务。 + for (auto& work : _works) { + //把服务先停止 + work->get_io_context().stop(); + work.reset(); + } + + for (auto& t : _threads) { + t.join(); + } +} diff --git a/server/ResourceServer/AsioIOServicePool.h b/server/ResourceServer/AsioIOServicePool.h new file mode 100644 index 0000000..423d657 --- /dev/null +++ b/server/ResourceServer/AsioIOServicePool.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include "Singleton.h" +class AsioIOServicePool:public Singleton +{ + friend Singleton; +public: + using IOService = boost::asio::io_context; + using Work = boost::asio::io_context::work; + using WorkPtr = std::unique_ptr; + ~AsioIOServicePool(); + AsioIOServicePool(const AsioIOServicePool&) = delete; + AsioIOServicePool& operator=(const AsioIOServicePool&) = delete; + // ʹ round-robin ķʽһ io_service + boost::asio::io_context& GetIOService(); + void Stop(); +private: + AsioIOServicePool(std::size_t size = std::thread::hardware_concurrency()); + std::vector _ioServices; + std::vector _works; + std::vector _threads; + std::size_t _nextIOService; +}; + diff --git a/server/ResourceServer/CServer.cpp b/server/ResourceServer/CServer.cpp new file mode 100644 index 0000000..457809e --- /dev/null +++ b/server/ResourceServer/CServer.cpp @@ -0,0 +1,48 @@ +#include "CServer.h" +#include +#include "AsioIOServicePool.h" +#include "UserMgr.h" + +CServer::CServer(boost::asio::io_context& io_context, short port):_io_context(io_context), _port(port), +_acceptor(io_context, tcp::endpoint(tcp::v4(),port)) +{ + cout << "Server start success, listen on port : " << _port << endl; + StartAccept(); +} + +CServer::~CServer() { + cout << "Server destruct listen on port : " << _port << endl; +} + +void CServer::HandleAccept(shared_ptr new_session, const boost::system::error_code& error){ + if (!error) { + new_session->Start(); + lock_guard lock(_mutex); + _sessions.insert(make_pair(new_session->GetSessionId(), new_session)); + } + else { + cout << "session accept failed, error is " << error.what() << endl; + } + + StartAccept(); +} + +void CServer::StartAccept() { + auto &io_context = AsioIOServicePool::GetInstance()->GetIOService(); + shared_ptr new_session = make_shared(io_context, this); + _acceptor.async_accept(new_session->GetSocket(), std::bind(&CServer::HandleAccept, this, new_session, placeholders::_1)); +} + +void CServer::ClearSession(std::string uuid) { + + if (_sessions.find(uuid) != _sessions.end()) { + //ƳûsessionĹ + UserMgr::GetInstance()->RmvUserSession(_sessions[uuid]->GetUserId()); + } + + { + lock_guard lock(_mutex); + _sessions.erase(uuid); + } + +} diff --git a/server/ResourceServer/CServer.h b/server/ResourceServer/CServer.h new file mode 100644 index 0000000..a1146ef --- /dev/null +++ b/server/ResourceServer/CServer.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include "CSession.h" +#include +#include +#include +using namespace std; +using boost::asio::ip::tcp; +class CServer +{ +public: + CServer(boost::asio::io_context& io_context, short port); + ~CServer(); + void ClearSession(std::string); +private: + void HandleAccept(shared_ptr, const boost::system::error_code & error); + void StartAccept(); + boost::asio::io_context &_io_context; + short _port; + tcp::acceptor _acceptor; + std::map> _sessions; + std::mutex _mutex; +}; + diff --git a/server/ResourceServer/CSession.cpp b/server/ResourceServer/CSession.cpp new file mode 100644 index 0000000..37731e1 --- /dev/null +++ b/server/ResourceServer/CSession.cpp @@ -0,0 +1,243 @@ +#include "CSession.h" +#include "CServer.h" +#include +#include +#include +#include +#include +#include "LogicSystem.h" + + +CSession::CSession(boost::asio::io_context& io_context, CServer* server): + _socket(io_context), _server(server), _b_close(false),_b_head_parse(false), _user_uid(0){ + boost::uuids::uuid a_uuid = boost::uuids::random_generator()(); + _session_id = boost::uuids::to_string(a_uuid); + _recv_head_node = make_shared(HEAD_TOTAL_LEN); +} +CSession::~CSession() { + std::cout << "~CSession destruct" << endl; +} + +tcp::socket& CSession::GetSocket() { + return _socket; +} + +std::string& CSession::GetSessionId() { + return _session_id; +} + +void CSession::SetUserId(int uid) +{ + _user_uid = uid; +} + +int CSession::GetUserId() +{ + return _user_uid; +} + +void CSession::Start(){ + std::cout << "session : " << _session_id << " started to read" << std::endl; + AsyncReadHead(HEAD_TOTAL_LEN); +} + +void CSession::Send(std::string msg, short msgid) { + std::lock_guard lock(_send_lock); + int send_que_size = _send_que.size(); + if (send_que_size > MAX_SENDQUE) { + std::cout << "session: " << _session_id << " send que fulled, size is " << MAX_SENDQUE << endl; + return; + } + + _send_que.push(make_shared(msg.c_str(), msg.length(), msgid)); + if (send_que_size > 0) { + return; + } + auto& msgnode = _send_que.front(); + boost::asio::async_write(_socket, boost::asio::buffer(msgnode->_data, msgnode->_total_len), + std::bind(&CSession::HandleWrite, this, std::placeholders::_1, SharedSelf())); +} + +void CSession::Send(char* msg, short max_length, short msgid) { + std::lock_guard lock(_send_lock); + int send_que_size = _send_que.size(); + if (send_que_size > MAX_SENDQUE) { + std::cout << "session: " << _session_id << " send que fulled, size is " << MAX_SENDQUE << endl; + return; + } + + _send_que.push(make_shared(msg, max_length, msgid)); + if (send_que_size>0) { + return; + } + auto& msgnode = _send_que.front(); + boost::asio::async_write(_socket, boost::asio::buffer(msgnode->_data, msgnode->_total_len), + std::bind(&CSession::HandleWrite, this, std::placeholders::_1, SharedSelf())); +} + +void CSession::Close() { + _socket.close(); + _b_close = true; +} + +std::shared_ptrCSession::SharedSelf() { + return shared_from_this(); +} + +void CSession::AsyncReadBody(int total_len) +{ + auto self = shared_from_this(); + asyncReadFull(total_len, [self, this, total_len](const boost::system::error_code& ec, std::size_t bytes_transfered) { + try { + if (ec) { + std::cout << "handle read failed, error is " << ec.what() << endl; + Close(); + _server->ClearSession(_session_id); + return; + } + + if (bytes_transfered < total_len) { + std::cout << "read length not match, read [" << bytes_transfered << "] , total [" + << total_len<<"]" << endl; + Close(); + _server->ClearSession(_session_id); + return; + } + + memcpy(_recv_msg_node->_data , _data , bytes_transfered); + _recv_msg_node->_cur_len += bytes_transfered; + _recv_msg_node->_data[_recv_msg_node->_total_len] = '\0'; + //cout << "receive data is " << _recv_msg_node->_data << endl; + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(_session_id); // ɹϣֵ + int index = hash_value % LOGIC_WORKER_COUNT; + //std::cout << "Hash value: " << hash_value << std::endl; + //˴ϢͶݵ߼ + LogicSystem::GetInstance()->PostMsgToQue(make_shared(shared_from_this(), _recv_msg_node), index); + //ͷ¼ + AsyncReadHead(HEAD_TOTAL_LEN); + } + catch (std::exception& e) { + std::cout << "Exception code is " << e.what() << endl; + } + }); +} + +void CSession::AsyncReadHead(int total_len) +{ + auto self = shared_from_this(); + asyncReadFull(HEAD_TOTAL_LEN, [self, this](const boost::system::error_code& ec, std::size_t bytes_transfered) { + try { + if (ec) { + std::cout << "handle read failed, error is " << ec.what() << endl; + Close(); + _server->ClearSession(_session_id); + return; + } + + if (bytes_transfered < HEAD_TOTAL_LEN) { + std::cout << "read length not match, read [" << bytes_transfered << "] , total [" + << HEAD_TOTAL_LEN << "]" << endl; + Close(); + _server->ClearSession(_session_id); + return; + } + + _recv_head_node->Clear(); + memcpy(_recv_head_node->_data, _data, bytes_transfered); + + //ȡͷMSGID + short msg_id = 0; + memcpy(&msg_id, _recv_head_node->_data, HEAD_ID_LEN); + //ֽתΪֽ + msg_id = boost::asio::detail::socket_ops::network_to_host_short(msg_id); + std::cout << "msg_id is " << msg_id << endl; + //idǷ + if (msg_id > MAX_LENGTH) { + std::cout << "invalid msg_id is " << msg_id << endl; + _server->ClearSession(_session_id); + return; + } + int msg_len = 0; + memcpy(&msg_len, _recv_head_node->_data + HEAD_ID_LEN, HEAD_DATA_LEN); + //ֽתΪֽ + msg_len = boost::asio::detail::socket_ops::network_to_host_long(msg_len); + std::cout << "msg_len is " << msg_len << endl; + + //idǷ + if (msg_len > MAX_LENGTH) { + std::cout << "invalid data length is " << msg_len << endl; + _server->ClearSession(_session_id); + return; + } + + _recv_msg_node = make_shared(msg_len, msg_id); + AsyncReadBody(msg_len); + } + catch (std::exception& e) { + std::cout << "Exception code is " << e.what() << endl; + } + }); +} + +void CSession::HandleWrite(const boost::system::error_code& error, std::shared_ptr shared_self) { + //쳣 + try { + if (!error) { + std::lock_guard lock(_send_lock); + //cout << "send data " << _send_que.front()->_data+HEAD_LENGTH << endl; + _send_que.pop(); + if (!_send_que.empty()) { + auto& msgnode = _send_que.front(); + boost::asio::async_write(_socket, boost::asio::buffer(msgnode->_data, msgnode->_total_len), + std::bind(&CSession::HandleWrite, this, std::placeholders::_1, shared_self)); + } + } + else { + std::cout << "handle write failed, error is " << error.what() << endl; + Close(); + _server->ClearSession(_session_id); + } + } + catch (std::exception& e) { + std::cerr << "Exception code : " << e.what() << endl; + } + +} + +//ȡ +void CSession::asyncReadFull(std::size_t maxLength, std::function handler ) +{ + ::memset(_data, 0, MAX_LENGTH); + asyncReadLen(0, maxLength, handler); +} + +//ȡָֽ +void CSession::asyncReadLen(std::size_t read_len, std::size_t total_len, + std::function handler) +{ + auto self = shared_from_this(); + _socket.async_read_some(boost::asio::buffer(_data + read_len, total_len-read_len), + [read_len, total_len, handler, self](const boost::system::error_code& ec, std::size_t bytesTransfered) { + if (ec) { + // ִ󣬵ûص + handler(ec, read_len + bytesTransfered); + return; + } + + if (read_len + bytesTransfered >= total_len) { + //ȹ˾͵ûص + handler(ec, read_len + bytesTransfered); + return; + } + + // ûдҳȲȡ + self->asyncReadLen(read_len + bytesTransfered, total_len, handler); + }); +} + +LogicNode::LogicNode(shared_ptr session, + shared_ptr recvnode):_session(session),_recvnode(recvnode) { + +} diff --git a/server/ResourceServer/CSession.h b/server/ResourceServer/CSession.h new file mode 100644 index 0000000..7eac74e --- /dev/null +++ b/server/ResourceServer/CSession.h @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "const.h" +#include "MsgNode.h" +using namespace std; + + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace net = boost::asio; // from +using tcp = boost::asio::ip::tcp; // from + + +class CServer; +class LogicSystem; + +class CSession: public std::enable_shared_from_this +{ +public: + CSession(boost::asio::io_context& io_context, CServer* server); + ~CSession(); + tcp::socket& GetSocket(); + std::string& GetSessionId(); + void SetUserId(int uid); + int GetUserId(); + void Start(); + void Send(char* msg, short max_length, short msgid); + void Send(std::string msg, short msgid); + void Close(); + std::shared_ptr SharedSelf(); + void AsyncReadBody(int length); + void AsyncReadHead(int total_len); +private: + void asyncReadFull(std::size_t maxLength, std::function handler); + void asyncReadLen(std::size_t read_len, std::size_t total_len, + std::function handler); + + + void HandleWrite(const boost::system::error_code& error, std::shared_ptr shared_self); + tcp::socket _socket; + std::string _session_id; + char _data[MAX_LENGTH]; + CServer* _server; + bool _b_close; + std::queue > _send_que; + std::mutex _send_lock; + //յϢṹ + std::shared_ptr _recv_msg_node; + bool _b_head_parse; + //յͷṹ + std::shared_ptr _recv_head_node; + int _user_uid; +}; + + diff --git a/server/ResourceServer/ChatServerGrpcClient.cpp b/server/ResourceServer/ChatServerGrpcClient.cpp new file mode 100644 index 0000000..8002a1d --- /dev/null +++ b/server/ResourceServer/ChatServerGrpcClient.cpp @@ -0,0 +1,52 @@ +#include "ChatServerGrpcClient.h" +#include "MysqlMgr.h" + +NotifyChatImgRsp ChatServerGrpcClient::NotifyChatImgMsg(int message_id,std::string chatserver) +{ + ClientContext context; + NotifyChatImgRsp reply; + NotifyChatImgReq request; + request.set_message_id(message_id); + if (_hash_pools.find(chatserver) == _hash_pools.end()) { + reply.set_error(ErrorCodes::ServerIpErr); + return reply; + } + auto chat_msg = MysqlMgr::GetInstance()->GetChatMsgById(message_id); + request.set_file_name(chat_msg->content); + request.set_from_uid(chat_msg->sender_id); + request.set_to_uid(chat_msg->recv_id); + request.set_thread_id(chat_msg->thread_id); + // Դļ· + auto file_dir = ConfigMgr::Inst().GetFileOutPath(); + //Ϣǽշͻ˷͹,Դ洢ڷͷļ + auto uid_str = std::to_string(chat_msg->sender_id); + auto file_path = (file_dir / uid_str / chat_msg->content); + boost::uintmax_t file_size = boost::filesystem::file_size(file_path); + request.set_total_size(file_size); + + auto &pool_ = _hash_pools[chatserver]; + auto stub = pool_->getConnection(); + Status status = stub->NotifyChatImgMsg(&context, request, &reply); + Defer defer([&stub, &pool_, this]() { + pool_->returnConnection(std::move(stub)); + }); + if (status.ok()) { + return reply; + } + else { + reply.set_error(ErrorCodes::RPCFailed); + return reply; + } +} + +ChatServerGrpcClient::ChatServerGrpcClient() +{ + auto& gCfgMgr = ConfigMgr::Inst(); + std::string host1 = gCfgMgr["chatserver1"]["Host"]; + std::string port1 = gCfgMgr["chatserver1"]["Port"]; + _hash_pools["chatserver1"] = std::make_unique(5, host1, port1); + + std::string host2 = gCfgMgr["chatserver2"]["Host"]; + std::string port2 = gCfgMgr["chatserver2"]["Port"]; + _hash_pools["chatserver2"] = std::make_unique(5, host2, port2); +} diff --git a/server/ResourceServer/ChatServerGrpcClient.h b/server/ResourceServer/ChatServerGrpcClient.h new file mode 100644 index 0000000..d8a57d4 --- /dev/null +++ b/server/ResourceServer/ChatServerGrpcClient.h @@ -0,0 +1,93 @@ +#pragma once +#include "const.h" +#include "Singleton.h" +#include "ConfigMgr.h" +#include "message.grpc.pb.h" +#include "message.pb.h" +#include +#include +#include +using grpc::Channel; +using grpc::Status; +using grpc::ClientContext; + + +using message::ChatService; +using message::NotifyChatImgReq; +using message::NotifyChatImgRsp; + +class ChatServerConPool { +public: + ChatServerConPool(size_t poolSize, std::string host, std::string port) + : poolSize_(poolSize), host_(host), port_(port), b_stop_(false) { + for (size_t i = 0; i < poolSize_; ++i) { + + std::shared_ptr channel = grpc::CreateChannel(host + ":" + port, + grpc::InsecureChannelCredentials()); + + connections_.push(ChatService::NewStub(channel)); + } + } + + ~ChatServerConPool() { + std::lock_guard lock(mutex_); + Close(); + while (!connections_.empty()) { + connections_.pop(); + } + } + + std::unique_ptr getConnection() { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { + if (b_stop_) { + return true; + } + return !connections_.empty(); + }); + //ֱֹͣӷؿָ + if (b_stop_) { + return nullptr; + } + auto context = std::move(connections_.front()); + connections_.pop(); + return context; + } + + void returnConnection(std::unique_ptr context) { + std::lock_guard lock(mutex_); + if (b_stop_) { + return; + } + connections_.push(std::move(context)); + cond_.notify_one(); + } + + void Close() { + b_stop_ = true; + cond_.notify_all(); + } + +private: + atomic b_stop_; + size_t poolSize_; + std::string host_; + std::string port_; + std::queue> connections_; + std::mutex mutex_; + std::condition_variable cond_; +}; + +class ChatServerGrpcClient :public Singleton +{ + friend class Singleton; +public: + ~ChatServerGrpcClient() { + + } + NotifyChatImgRsp NotifyChatImgMsg(int message_id, std::string chatserver); +private: + ChatServerGrpcClient(); + //sever_ipӳصӳ, > + std::unordered_map> _hash_pools; +}; \ No newline at end of file diff --git a/server/ResourceServer/ConfigMgr.cpp b/server/ResourceServer/ConfigMgr.cpp new file mode 100644 index 0000000..d9e5b2f --- /dev/null +++ b/server/ResourceServer/ConfigMgr.cpp @@ -0,0 +1,82 @@ +#include "ConfigMgr.h" +ConfigMgr::ConfigMgr(){ + // ȡǰĿ¼ + boost::filesystem::path current_path = boost::filesystem::current_path(); + // config.iniļ· + boost::filesystem::path config_path = current_path / "config.ini"; + std::cout << "Config path: " << config_path << std::endl; + + // ʹBoost.PropertyTreeȡINIļ + boost::property_tree::ptree pt; + boost::property_tree::read_ini(config_path.string(), pt); + + + // INIļеsection + for (const auto& section_pair : pt) { + const std::string& section_name = section_pair.first; + const boost::property_tree::ptree& section_tree = section_pair.second; + + // ÿsectionеkey-value + std::map section_config; + for (const auto& key_value_pair : section_tree) { + const std::string& key = key_value_pair.first; + const std::string& value = key_value_pair.second.get_value(); + section_config[key] = value; + } + SectionInfo sectionInfo; + sectionInfo._section_datas = section_config; + // sectionkey-valueԱ浽config_map + _config_map[section_name] = sectionInfo; + } + + // еsectionkey-value + for (const auto& section_entry : _config_map) { + const std::string& section_name = section_entry.first; + SectionInfo section_config = section_entry.second; + std::cout << "[" << section_name << "]" << std::endl; + for (const auto& key_value_pair : section_config._section_datas) { + std::cout << key_value_pair.first << "=" << key_value_pair.second << std::endl; + } + } + + + InitPath(); +} + +std::string ConfigMgr::GetValue(const std::string& section, const std::string& key) { + if (_config_map.find(section) == _config_map.end()) { + return ""; + } + + return _config_map[section].GetValue(key); +} + +boost::filesystem::path ConfigMgr::GetFileOutPath() +{ + return _static_path; +} + +void ConfigMgr::InitPath() +{ + // ȡǰĿ¼ + boost::filesystem::path current_path = boost::filesystem::current_path(); + std::string bindir = _config_map["Output"].GetValue("Path"); + std::string staticdir = _config_map["Static"].GetValue("Path"); + _static_path = current_path / bindir / staticdir; + _bin_path = current_path / bindir; + + + // ·Ƿ + if (!boost::filesystem::exists(_static_path)) { + // ·ڣ + if (boost::filesystem::create_directories(_static_path)) { + std::cout << "·ѳɹ: " << _static_path.string() << std::endl; + } + else { + std::cerr << "·ʧ: " << _static_path.string() << std::endl; + } + } + else { + std::cout << "·Ѵ: " << _static_path.string() << std::endl; + } +} diff --git a/server/ResourceServer/ConfigMgr.h b/server/ResourceServer/ConfigMgr.h new file mode 100644 index 0000000..2521937 --- /dev/null +++ b/server/ResourceServer/ConfigMgr.h @@ -0,0 +1,89 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +struct SectionInfo { + SectionInfo(){} + ~SectionInfo(){ + _section_datas.clear(); + } + + SectionInfo(const SectionInfo& src) { + _section_datas = src._section_datas; + } + + SectionInfo& operator = (const SectionInfo& src) { + if (&src == this) { + return *this; + } + + this->_section_datas = src._section_datas; + return *this; + } + + std::map _section_datas; + std::string operator[](const std::string &key) { + if (_section_datas.find(key) == _section_datas.end()) { + return ""; + } + // һЩ߽ + return _section_datas[key]; + } + + std::string GetValue(const std::string & key) { + if (_section_datas.find(key) == _section_datas.end()) { + return ""; + } + // һЩ߽ + return _section_datas[key]; + } +}; + +class ConfigMgr +{ +public: + ~ConfigMgr() { + _config_map.clear(); + } + SectionInfo operator[](const std::string& section) { + if (_config_map.find(section) == _config_map.end()) { + return SectionInfo(); + } + return _config_map[section]; + } + + + ConfigMgr& operator=(const ConfigMgr& src) { + if (&src == this) { + return *this; + } + + this->_config_map = src._config_map; + }; + + ConfigMgr(const ConfigMgr& src) { + this->_config_map = src._config_map; + } + + static ConfigMgr& Inst() { + static ConfigMgr cfg_mgr; + return cfg_mgr; + } + + std::string GetValue(const std::string& section, const std::string & key); + boost::filesystem::path GetFileOutPath(); + void InitPath(); +private: + ConfigMgr(); + // 洢sectionkey-valueԵmap + std::map _config_map; + //staticĿ¼ + boost::filesystem::path _static_path; + //binĿ¼ + boost::filesystem::path _bin_path; +}; + diff --git a/server/ResourceServer/DistLock.cpp b/server/ResourceServer/DistLock.cpp new file mode 100644 index 0000000..617d23f --- /dev/null +++ b/server/ResourceServer/DistLock.cpp @@ -0,0 +1,73 @@ +#include "DistLock.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//嵥ģʽ +DistLock& DistLock::Inst() { + static DistLock lock; + return lock; +} + +// ʹ Boost UUID ȫΨһʶUUID +static std::string generateUUID() { + boost::uuids::uuid uuid = boost::uuids::random_generator()(); + return to_string(uuid); +} + +// ԻȡΨһʶUUIDȡʧ򷵻ؿַ +std::string DistLock::acquireLock(redisContext* context, const std::string& lockName, + int lockTimeout, int acquireTimeout) { + std::string identifier = generateUUID(); + std::string lockKey = "lock:" + lockName; + auto endTime = std::chrono::steady_clock::now() + std::chrono::seconds(acquireTimeout); + + while (std::chrono::steady_clock::now() < endTime) { + // ʹ SET ԼSET lockKey identifier NX EX lockTimeout + redisReply* reply = (redisReply*)redisCommand(context, "SET %s %s NX EX %d", + lockKey.c_str(), identifier.c_str(), lockTimeout); + if (reply != nullptr) { + // жϷؽǷΪ OK + if (reply->type == REDIS_REPLY_STATUS && std::string(reply->str) == "OK") { + freeReplyObject(reply); + return identifier; + } + freeReplyObject(reply); + } + // ͣ 1 ԣֹæȴ + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + return ""; +} + +// ͷֻij߲ͷţǷɹ +bool DistLock::releaseLock(redisContext* context, const std::string& lockName, + const std::string& identifier) { + std::string lockKey = "lock:" + lockName; + // Lua űжʶǷƥ䣬ƥɾ + const char* luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then \ + return redis.call('del', KEYS[1]) \ + else \ + return 0 \ + end"; + // EVAL ִ Lua űһΪűΪ key key ԼӦIJ + redisReply* reply = (redisReply*)redisCommand(context, "EVAL %s 1 %s %s", + luaScript, lockKey.c_str(), identifier.c_str()); + bool success = false; + if (reply != nullptr) { + // ֵΪ 1 ʱʾɹɾ + if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 1) { + success = true; + } + freeReplyObject(reply); + } + return success; +} \ No newline at end of file diff --git a/server/ResourceServer/DistLock.h b/server/ResourceServer/DistLock.h new file mode 100644 index 0000000..61b2c78 --- /dev/null +++ b/server/ResourceServer/DistLock.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include +class DistLock +{ +public: + static DistLock& Inst(); + ~DistLock() = default; + std::string acquireLock(redisContext* context, const std::string& lockName, + int lockTimeout, int acquireTimeout); + + bool releaseLock(redisContext* context, const std::string& lockName, + const std::string& identifier); +private: + DistLock() = default; +}; + diff --git a/server/ResourceServer/FileInfo.cpp b/server/ResourceServer/FileInfo.cpp new file mode 100644 index 0000000..ef3869d --- /dev/null +++ b/server/ResourceServer/FileInfo.cpp @@ -0,0 +1 @@ +#include "FileInfo.h" diff --git a/server/ResourceServer/FileInfo.h b/server/ResourceServer/FileInfo.h new file mode 100644 index 0000000..81c8f83 --- /dev/null +++ b/server/ResourceServer/FileInfo.h @@ -0,0 +1,25 @@ +#pragma once +#include + +class FileInfo { +public: + FileInfo(int seq = 0, std::string name = "", int64_t total_size = 0, + int64_t trans_size = 0, std::string file_path_str = "") + :_seq(seq), _name(name), _total_size(total_size), + _trans_size(trans_size), _file_path_str(file_path_str) {} + int _seq; + std::string _name; + int64_t _total_size; + int64_t _trans_size; + std::string _file_path_str; +}; + +class ChatImgInfo { +public: + ChatImgInfo(int sender_id, int receiver_id, int message_id, std::string img_name) + :_sender_id(sender_id),_receiver_id(receiver_id),_message_id(message_id),_img_name(img_name){} + int _sender_id; + int _receiver_id; + int _message_id; + std::string _img_name; +}; diff --git a/server/ResourceServer/FileSystem.cpp b/server/ResourceServer/FileSystem.cpp new file mode 100644 index 0000000..28706af --- /dev/null +++ b/server/ResourceServer/FileSystem.cpp @@ -0,0 +1,28 @@ +#include "FileSystem.h" +#include "const.h" + +FileSystem::~FileSystem() +{ + +} + +void FileSystem::PostMsgToQue(shared_ptr msg, int index) +{ + _file_workers[index]->PostTask(msg); +} + +void FileSystem::PostDownloadTaskToQue(std::shared_ptr msg, int index) +{ + _down_load_worker[index]->PostTask(msg); +} + +FileSystem::FileSystem() +{ + for (int i = 0; i < FILE_WORKER_COUNT; i++) { + _file_workers.push_back(std::make_shared()); + } + + for (int i = 0; i < DOWN_LOAD_WORKER_COUNT; i++) { + _down_load_worker.push_back(std::make_shared()); + } +} diff --git a/server/ResourceServer/FileSystem.h b/server/ResourceServer/FileSystem.h new file mode 100644 index 0000000..24f1990 --- /dev/null +++ b/server/ResourceServer/FileSystem.h @@ -0,0 +1,20 @@ +#pragma once +#include "Singleton.h" +#include "FileWorker.h" +#include +#include + +class FileSystem :public Singleton +{ + friend class Singleton; +public: + ~FileSystem(); + void PostMsgToQue(shared_ptr msg, int index); + void PostDownloadTaskToQue(std::shared_ptr msg, int index); +private: + FileSystem(); + std::vector> _file_workers; + std::vector> _down_load_worker; +}; + + diff --git a/server/ResourceServer/FileWorker.cpp b/server/ResourceServer/FileWorker.cpp new file mode 100644 index 0000000..6926294 --- /dev/null +++ b/server/ResourceServer/FileWorker.cpp @@ -0,0 +1,662 @@ +#include "FileWorker.h" +#include "CSession.h" +#include +#include +#include +#include "base64.h" +#include "ConfigMgr.h" +#include "MysqlMgr.h" +#include "RedisMgr.h" +#include "ChatServerGrpcClient.h" + +FileWorker::FileWorker() :_b_stop(false) +{ + RegisterHandlers(); + _work_thread = std::thread([this]() { + while (!_b_stop) { + std::unique_lock lock(_mtx); + _cv.wait(lock, [this]() { + if (_b_stop) { + return true; + } + + if (_task_que.empty()) { + return false; + } + + return true; + }); + + if (_b_stop) { + break; + } + + auto task_call = _task_que.front(); + _task_que.pop(); + task_call(); + } + + }); +} + +FileWorker::~FileWorker() +{ + _b_stop = true; + _cv.notify_one(); + _work_thread.join(); +} + +void FileWorker::RegisterHandlers() +{ + _handlers[ID_UPLOAD_FILE_REQ] = [this](std::shared_ptr task) { + // + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // ȡļչ + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //һ + if (task->_seq == 1) { + // ļգ򴴽 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // Ϊļ + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "޷ļд롣" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "дļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "ļѳɹΪ: " << task->_name << std::endl; + } + + if (task->_callback) { + task->_callback(result); + } + }; + + //ͷϴ + _handlers[ID_UPLOAD_HEAD_ICON_REQ] = [this](std::shared_ptr task) { + // + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // ȡļչ + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //һ + if (task->_seq == 1) { + // ļգ򴴽 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // Ϊļ + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "޷ļд롣" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "дļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "ļѳɹΪ: " << task->_name << std::endl; + //ͷ + MysqlMgr::GetInstance()->UpdateUserIcon(task->_uid, filename); + //ȡûϢ + auto user_info = MysqlMgr::GetInstance()->GetUser(task->_uid); + if (user_info == nullptr) { + return; + } + + //ݿдredis + Json::Value redis_root; + redis_root["uid"] = task->_uid; + redis_root["pwd"] = user_info->pwd; + redis_root["name"] = user_info->name; + redis_root["email"] = user_info->email; + redis_root["nick"] = user_info->nick; + redis_root["desc"] = user_info->desc; + redis_root["sex"] = user_info->sex; + redis_root["icon"] = user_info->icon; + std::string base_key = USER_BASE_INFO + std::to_string(task->_uid); + RedisMgr::GetInstance()->Set(base_key, redis_root.toStyledString()); + } + + if (task->_callback) { + task->_callback(result); + } + }; + + //ͼƬϴ + _handlers[ID_IMG_CHAT_UPLOAD_REQ] = [this](std::shared_ptr task) { + // + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // ȡļչ + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //һ + if (task->_seq == 1) { + // ļգ򴴽 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // Ϊļ + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "޷ļд롣" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "дļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "ļѳɹΪ: " << task->_name << std::endl; + //ݿͼϴ״̬ + MysqlMgr::GetInstance()->UpdateUploadStatus(task->_chat_msg_id); + + std::string uid_ip_value = ""; + auto receiver_str = std::to_string(task->_receiver); + auto uid_ip_key = USERIPPREFIX + receiver_str; + bool b_ip = RedisMgr::GetInstance()->Get(uid_ip_key, uid_ip_value); + //δ¼ֱӷ + if (!b_ip) { + if (task->_callback) { + task->_callback(result); + } + + return; + } + + if (task->_callback) { + task->_callback(result); + } + + //ͨgrpc֪ͨChatServer + ChatServerGrpcClient::GetInstance()->NotifyChatImgMsg(task->_chat_msg_id, uid_ip_value); + return; + } + + if (task->_callback) { + task->_callback(result); + } + }; + + //ļϢͬ + _handlers[ID_FILE_INFO_SYNC_REQ] = [this](std::shared_ptr task) { + // + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // ȡļչ + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //һ + if (task->_seq == 1) { + // ļգ򴴽 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // Ϊļ + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "޷ļд롣" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "дļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "ļѳɹΪ: " << task->_name << std::endl; + //todo...ݿͼϴ״̬ + MysqlMgr::GetInstance()->UpdateUploadStatus(task->_chat_msg_id); + std::string uid_ip_value = ""; + auto receiver_str = std::to_string(task->_receiver); + auto uid_ip_key = USERIPPREFIX + receiver_str; + bool b_ip = RedisMgr::GetInstance()->Get(uid_ip_key, uid_ip_value); + //δ¼ֱӷ + if (!b_ip) { + if (task->_callback) { + task->_callback(result); + } + + return; + } + + if (task->_callback) { + task->_callback(result); + } + + //ͨgrpc֪ͨChatServer + ChatServerGrpcClient::GetInstance()->NotifyChatImgMsg(task->_chat_msg_id, uid_ip_value); + return; + } + + if (task->_callback) { + task->_callback(result); + } + }; + + //ͼƬ + _handlers[ID_IMG_CHAT_CONTINUE_UPLOAD_REQ] = [this](std::shared_ptr task) { + // + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // ȡļչ + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //һ + if (task->_seq == 1) { + // ļգ򴴽 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // Ϊļ + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "޷ļд롣" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "дļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "ļѳɹΪ: " << task->_name << std::endl; + //ݿͼϴ״̬ + MysqlMgr::GetInstance()->UpdateUploadStatus(task->_chat_msg_id); + + std::string uid_ip_value = ""; + auto receiver_str = std::to_string(task->_receiver); + auto uid_ip_key = USERIPPREFIX + receiver_str; + bool b_ip = RedisMgr::GetInstance()->Get(uid_ip_key, uid_ip_value); + //δ¼ֱӷ + if (!b_ip) { + if (task->_callback) { + task->_callback(result); + } + + return; + } + + //ͨgrpc֪ͨChatServer + ChatServerGrpcClient::GetInstance()->NotifyChatImgMsg(task->_chat_msg_id, uid_ip_value); + if (task->_callback) { + task->_callback(result); + } + + return; + } + + if (task->_callback) { + task->_callback(result); + } + }; + +} + +void FileWorker::PostTask(std::shared_ptr task) +{ + { + std::lock_guard lock(_mtx); + //pythonԶ˼룬αհӵ + _task_que.push([task, this]() { + task_callback(task); + }); + } + + _cv.notify_one(); +} + +void FileWorker::task_callback(std::shared_ptr task) +{ + auto iter = _handlers.find(task->_msg_id); + if (iter == _handlers.end()) { + return; + } + + iter->second(task); +} + +DownloadWorker::DownloadWorker() :_b_stop(false) +{ + _work_thread = std::thread([this]() { + while (!_b_stop) { + std::unique_lock lock(_mtx); + _cv.wait(lock, [this]() { + if (_b_stop) { + return true; + } + + if (_task_que.empty()) { + return false; + } + + return true; + }); + + if (_b_stop) { + break; + } + + auto task = _task_que.front(); + _task_que.pop(); + task_callback(task); + } + }); +} + +DownloadWorker::~DownloadWorker() +{ + _b_stop = true; + _cv.notify_one(); + _work_thread.join(); +} + +void DownloadWorker::PostTask(std::shared_ptr task) +{ + { + std::lock_guard lock(_mtx); + _task_que.push(task); + } + + _cv.notify_one(); +} + +void DownloadWorker::task_callback(std::shared_ptr task) +{ + // + auto file_path_str = task->_file_path; + + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + + Json::Value result; + result["error"] = ErrorCodes::Success; + + if (!boost::filesystem::exists(file_path)) { + std::cerr << "ļ: " << file_path_str << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + + std::ifstream infile(file_path_str, std::ios::binary); + if (!infile) { + std::cerr << "޷ļжȡ" << std::endl; + result["error"] = ErrorCodes::FileReadPermissionFailed; + task->_callback(result); + return; + } + + std::shared_ptr file_info = nullptr; + + if (task->_seq == 1) { + // ȡļС + infile.seekg(0, std::ios::end); + std::streamsize file_size = infile.tellg(); + infile.seekg(0, std::ios::beg); + //Ϊգ򴴽FileInfo ݴ洢 + file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = task->_name; + file_info->_seq = 1; + + file_info->_total_size = file_size; + file_info->_trans_size = 0; + // 浽 RedisǾݣùʱ + RedisMgr::GetInstance()->SetDownLoadInfo(task->_name, file_info); + std::cout << "[] ļ: " << task->_name + << ", С: " << file_size << " ֽ" << std::endl; + } + else { + //ϵ Redis ȡʷϢ + file_info = RedisMgr::GetInstance()->GetDownloadInfo(task->_name); + if (file_info == nullptr) { + // Redis ûϢܹˣ + std::cerr << "ϵʧܣRedis Ϣ: " << task->_name << std::endl; + result["error"] = ErrorCodes::RedisReadErr; + task->_callback(result); + infile.close(); + return; + } + // ֤кǷƥ + if (task->_seq != file_info->_seq) { + std::cerr << "кŲƥ䣬: " << file_info->_seq + << ", ʵ: " << task->_seq << std::endl; + result["error"] = ErrorCodes::FileSeqInvalid; + task->_callback(result); + infile.close(); + return; + } + + std::cout << "[] ļ: " << task->_name + << ", seq: " << task->_seq + << ", : " << file_info->_trans_size + << "/" << file_info->_total_size << std::endl; + } + + // 㵱ǰƫ + std::streamsize offset = ((std::streamsize)task->_seq - 1) * MAX_FILE_LEN; + if (offset >= file_info->_total_size) { + std::cerr << "ƫļС" << std::endl; + result["error"] = ErrorCodes::FileOffsetInvalid; + task->_callback(result); + infile.close(); + return; + } + + // λָƫ + infile.seekg(offset); + + // ȡMAX_FILE_LENֽ + char buffer[MAX_FILE_LEN]; + infile.read(buffer, MAX_FILE_LEN); + //ȡreadʵʶȡֽ + std::streamsize bytes_read = infile.gcount(); + + if (bytes_read <= 0) { + std::cerr << "ȡļʧܡ" << std::endl; + result["error"] = ErrorCodes::FileReadFailed; + task->_callback(result); + infile.close(); + return; + } + + // ȡݽbase64 + std::string data_to_encode(buffer, bytes_read); + std::string encoded_data = base64_encode(data_to_encode); + + // Ƿһ + std::streamsize current_pos = offset + bytes_read; + bool is_last = (current_pos >= file_info->_total_size); + + // ÷ؽ + result["data"] = encoded_data; + result["seq"] = task->_seq; + result["total_size"] = std::to_string(file_info->_total_size); + result["current_size"] = std::to_string(current_pos); + result["is_last"] = is_last; + + infile.close(); + + if (is_last) { + std::cout << "ļȡ: " << file_path_str << std::endl; + RedisMgr::GetInstance()->DelDownLoadInfo(task->_name); + } + else { + //Ϣ + file_info->_seq++; + file_info->_trans_size = offset + bytes_read; + //redis + RedisMgr::GetInstance()->SetDownLoadInfo(task->_name, file_info); + } + + if (task->_callback) { + task->_callback(result); + } + +} diff --git a/server/ResourceServer/FileWorker.h b/server/ResourceServer/FileWorker.h new file mode 100644 index 0000000..33937c1 --- /dev/null +++ b/server/ResourceServer/FileWorker.h @@ -0,0 +1,89 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "const.h" +#include +#include "const.h" +#include + +class CSession; +struct FileTask { + FileTask(std::shared_ptr session, MSG_IDS msg_id, int uid, std::string path, std::string name, + int seq, int total_size, int trans_size, int last, + std::string file_data, + std::function callback,int chat_msg_id=0, + int sender = 0, int receiver = 0) :_session(session), _msg_id(msg_id),_uid(uid), + _seq(seq), _path(path), _name(name), _total_size(total_size), + _trans_size(trans_size), _last(last), _file_data(file_data), _callback(callback), _chat_msg_id(chat_msg_id), + _sender(sender), _receiver(receiver) + {} + ~FileTask(){} + std::shared_ptr _session; + MSG_IDS _msg_id; + int _uid; + int _seq ; + std::string _path; + std::string _name ; + int _total_size ; + int _trans_size ; + int _last ; + std::string _file_data; + std::function _callback; //ӻص + int _chat_msg_id; + int _sender; + int _receiver; + int _thread_id; +}; + + +struct DownloadTask { + DownloadTask(std::shared_ptr session, int uid, std::string name, + int seq, std::string file_path, + std::function callback) :_session(session), _uid(uid), + _seq(seq), _name(name), _file_path(file_path), _callback(callback) + {} + ~DownloadTask() {} + std::shared_ptr _session; + int _uid; + int _seq; + std::string _name; + std::string _file_path; + std::function _callback; //ӻص +}; + +class FileWorker +{ +public: + FileWorker(); + ~FileWorker(); + void RegisterHandlers(); + void PostTask(std::shared_ptr task); +private: + void task_callback(std::shared_ptr); + std::unordered_map)> > _handlers; + std::thread _work_thread; + std::queue> _task_que; + std::atomic _b_stop; + std::mutex _mtx; + std::condition_variable _cv; +}; + + +class DownloadWorker { +public: + DownloadWorker(); + ~DownloadWorker(); + void PostTask(std::shared_ptr task); +private: + void task_callback(std::shared_ptr); + std::thread _work_thread; + std::queue> _task_que; + std::atomic _b_stop; + std::mutex _mtx; + std::condition_variable _cv; +}; + diff --git a/server/ResourceServer/LogicSystem.cpp b/server/ResourceServer/LogicSystem.cpp new file mode 100644 index 0000000..9cfd1f5 --- /dev/null +++ b/server/ResourceServer/LogicSystem.cpp @@ -0,0 +1,45 @@ +#include "LogicSystem.h" +#include "const.h" +#include "base64.h" +#include +#include +#include "ConfigMgr.h" +#include "FileSystem.h" + +using namespace std; + +LogicSystem::LogicSystem(){ + for (int i = 0; i < LOGIC_WORKER_COUNT; i++) { + _workers.push_back(std::make_shared()); + } +} + +LogicSystem::~LogicSystem(){ + +} + +void LogicSystem::PostMsgToQue(shared_ptr < LogicNode> msg, int index) { + _workers[index]->PostTask(msg); +} + + +void LogicSystem::AddMD5File(std::string md5, std::shared_ptr fileinfo) { + std::lock_guard lock(_file_mtx); + _map_md5_files[md5] = fileinfo; +} + +std::shared_ptr LogicSystem::GetFileInfo(std::string md5) { + std::lock_guard lock(_file_mtx); + auto iter = _map_md5_files.find(md5); + if (iter == _map_md5_files.end()) { + return nullptr; + } + + return iter->second; +} + + + + + + diff --git a/server/ResourceServer/LogicSystem.h b/server/ResourceServer/LogicSystem.h new file mode 100644 index 0000000..e628ffa --- /dev/null +++ b/server/ResourceServer/LogicSystem.h @@ -0,0 +1,33 @@ +#pragma once +#include "Singleton.h" +#include +#include +#include "CSession.h" +#include +#include +#include +#include "const.h" +#include +#include +#include +#include +#include "LogicWorker.h" +#include "FileInfo.h" + + +typedef function, const short &msg_id, const string &msg_data)> FunCallBack; +class LogicSystem:public Singleton +{ + friend class Singleton; +public: + ~LogicSystem(); + void PostMsgToQue(shared_ptr < LogicNode> msg, int index); + void AddMD5File(std::string md5, std::shared_ptr fileinfo); + std::shared_ptr GetFileInfo(std::string md5); +private: + LogicSystem(); + std::vector > _workers; + std::mutex _file_mtx; + std::unordered_map> _map_md5_files; +}; + diff --git a/server/ResourceServer/LogicWorker.cpp b/server/ResourceServer/LogicWorker.cpp new file mode 100644 index 0000000..d88a7b0 --- /dev/null +++ b/server/ResourceServer/LogicWorker.cpp @@ -0,0 +1,764 @@ +#include "LogicWorker.h" +#include +#include +#include +#include "FileSystem.h" +#include "CSession.h" +#include "LogicSystem.h" +#include "ConfigMgr.h" +#include "RedisMgr.h" +#include "MysqlMgr.h" + +LogicWorker::LogicWorker():_b_stop(false) +{ + RegisterCallBacks(); + + _work_thread = std::thread([this]() { + while (!_b_stop) { + std::unique_lock lock(_mtx); + _cv.wait(lock, [this]() { + if(_b_stop) { + return true; + } + + if (_task_que.empty()) { + return false; + } + + return true; + + }); + + if (_b_stop) { + return; + } + + auto task = _task_que.front(); + task_callback(task); + _task_que.pop(); + } + }); + +} + +LogicWorker::~LogicWorker() +{ + _b_stop = true; + _cv.notify_one(); + _work_thread.join(); +} + +void LogicWorker::PostTask(std::shared_ptr task) +{ + std::lock_guard lock(_mtx); + _task_que.push(task); + _cv.notify_one(); +} + +void LogicWorker::RegisterCallBacks() +{ + _fun_callbacks[ID_TEST_MSG_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto data = root["data"].asString(); + std::cout << "recv test data is " << data << std::endl; + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_TEST_MSG_RSP); + }); + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["data"] = data; + }; + + _fun_callbacks[ID_UPLOAD_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + //תΪַ + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str/ name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_FILE_RSP); + }; + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //һ + if (seq == 1) { + //ݴ洢 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + //todo... ڸΪredis,Լmysql ־û洢 + bool success = RedisMgr::GetInstance()->SetFileInfo(md5, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(md5); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_FILE_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(md5, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_FILE_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_UPLOAD_FILE_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + }; + + + + _fun_callbacks[ID_SYNC_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_SYNC_FILE_RSP); + }); + + auto md5 = root["md5"].asString(); + + auto file = LogicSystem::GetInstance()->GetFileInfo(md5); + if (file == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = std::to_string(file->_total_size); + rtvalue["seq"] = file->_seq; + rtvalue["name"] = file->_name; + rtvalue["trans_size"] = std::to_string(file->_trans_size); + rtvalue["md5"] = md5; + + }; + + + _fun_callbacks[ID_UPLOAD_HEAD_ICON_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto uid = root["uid"].asInt(); + auto token = root["token"].asString(); + auto last_seq = root["last_seq"].asInt(); + //תΪַ + auto uid_str = std::to_string(uid); + + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["last_seq"] = last_seq; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + }; + + //һУһtokenǷ + if (seq == 1) { + //redisȡûtokenǷȷ + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //һ + if (seq == 1) { + //ݴ洢 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + //LogicSystem::GetInstance()->AddMD5File(md5, file_info); + //Ϊredis洢 + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + else { + //auto file_info = LogicSystem::GetInstance()->GetFileInfo(md5); + //Ϊredisм + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_UPLOAD_HEAD_ICON_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + + }; + + _fun_callbacks[ID_DOWN_LOAD_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto uid = root["uid"].asInt(); + auto token = root["token"].asString(); + auto client_path = root["client_path"].asString(); + auto req_type = root["req_type"].asString(); + //תΪַ + auto uid_str = std::to_string(uid); + + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["client_path"] = client_path; + rtvalue["name"] = name; + rtvalue["req_type"] = req_type; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_DOWN_LOAD_FILE_RSP); + }; + + //һУһtokenǷ + if (seq == 1) { + //redisȡûtokenǷȷ + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_DOWN_LOAD_FILE_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_DOWN_LOAD_FILE_RSP); + return; + } + } + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + FileSystem::GetInstance()->PostDownloadTaskToQue( + std::make_shared(session, uid, name, seq, file_path_str, callback), + index + ); + + }; + + _fun_callbacks[ID_IMG_CHAT_UPLOAD_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size_str = root["total_size"].asString(); + auto trans_size_str = root["trans_size"].asString(); + int64_t total_size = std::stoll(total_size_str); + int64_t trans_size = std::stoll(trans_size_str); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + auto sender = root["sender"].asInt(); + auto receiver = root["receiver"].asInt(); + auto message_id = root["message_id"].asInt(); + //תΪַ + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = std::to_string(total_size); + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = std::to_string(trans_size); + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["sender"] = sender; + rtvalue["receiver"] = receiver; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_UPLOAD_RSP); + }; + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //һ + if (seq == 1) { + //ݴ洢 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_UPLOAD_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_UPLOAD_RSP); + return; + } + file_info->_seq++; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_UPLOAD_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_IMG_CHAT_UPLOAD_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback, message_id,sender,receiver), + index + ); + }; + + + _fun_callbacks[ID_FILE_INFO_SYNC_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size_str = root["total_size"].asString(); + auto trans_size_str = root["trans_size"].asString(); + auto total_size = std::stoll(total_size_str); + auto trans_size = std::stoll(trans_size_str); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + auto message_id = root["message_id"].asInt(); + auto sender = root["sender"].asInt(); + auto receiver = root["receiver"].asInt(); + //תΪַ + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["sender"] = sender; + rtvalue["receiver"] = receiver; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + }; + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //һ + if (seq == 1) { + //ݴ洢 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_FILE_INFO_SYNC_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback, message_id,sender,receiver), + index + ); + }; + + + + _fun_callbacks[ID_IMG_CHAT_CONTINUE_UPLOAD_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + auto message_id = root["message_id"].asInt(); + auto sender = root["sender"].asInt(); + auto receiver = root["receiver"].asInt(); + //תΪַ + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["sender"] = sender; + rtvalue["receiver"] = receiver; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + }; + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //һ + if (seq == 1) { + //ݴ洢 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_IMG_CHAT_CONTINUE_UPLOAD_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback, message_id,sender,receiver), + index + ); + }; + + _fun_callbacks[ID_IMG_CHAT_DOWN_INFO_SYNC_REQ] = [this](std::shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto message_id = root["message_id"].asInt(); + auto chat_msg = MysqlMgr::GetInstance()->GetChatMsgById(message_id); + if (chat_msg == nullptr) { + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::MsgIdErr; + return; + } + + // Դļ· + auto file_dir = ConfigMgr::Inst().GetFileOutPath(); + //Ϣǽշͻ˷͹,Դ洢ڷͷļ + auto uid_str = std::to_string(chat_msg->sender_id); + auto file_path = (file_dir / uid_str / chat_msg->content); + boost::uintmax_t file_size = boost::filesystem::file_size(file_path); + + // 첽ɺ + Json::Value rtvalue ; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["message_id"] = chat_msg->message_id; + rtvalue["thread_id"] = chat_msg->thread_id; + rtvalue["sender_id"] = chat_msg->sender_id; + rtvalue["recv_id"] = chat_msg->recv_id; + rtvalue["name"] = chat_msg->content; + rtvalue["msg_type"] = chat_msg->msg_type; + rtvalue["status"] = chat_msg->status; + rtvalue["total_size"] = std::to_string(file_size); + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_INFO_SYNC_RSP); + }; + + _fun_callbacks[ID_IMG_CHAT_DOWN_REQ] = [this](std::shared_ptr session, const short& msg_req_id, + const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size_str = root["total_size"].asString(); + auto trans_size_str = root["trans_size"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto message_id = root["message_id"].asInt(); + auto sender = root["sender_id"].asInt(); + auto receiver = root["receiver_id"].asInt(); + auto token = root["token"].asString(); + auto uid = root["uid"].asInt(); + + auto callback = [=](const Json::Value& result) { + // 첽ɺ + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["name"] = name; + rtvalue["sender_id"] = sender; + rtvalue["receiver_id"] = receiver; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + }; + + // ʹ std::hash ַйϣ + std::hash hash_fn; + size_t hash_value = hash_fn(name); // ɹϣֵ + int index = hash_value % DOWN_LOAD_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + + //һУһtokenǷ + if (seq == 1) { + //redisȡûtokenǷȷ + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + Json::Value rtvalue; + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + return; + } + } + + auto sender_str = std::to_string(sender); + //תΪַ + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / sender_str / name).string(); + + auto down_load_task = std::make_shared(session, uid, name, seq, file_path_str, callback); + + FileSystem::GetInstance()->PostDownloadTaskToQue(down_load_task,index); + }; + +} + +void LogicWorker::task_callback(std::shared_ptr task) +{ + cout << "recv_msg id is " << task->_recvnode->_msg_id << endl; + auto call_back_iter = _fun_callbacks.find(task->_recvnode->_msg_id); + if (call_back_iter == _fun_callbacks.end()) { + return; + } + call_back_iter->second(task->_session, task->_recvnode->_msg_id, + std::string(task->_recvnode->_data, task->_recvnode->_cur_len)); +} diff --git a/server/ResourceServer/LogicWorker.h b/server/ResourceServer/LogicWorker.h new file mode 100644 index 0000000..9765b86 --- /dev/null +++ b/server/ResourceServer/LogicWorker.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include +#include +#include +#include +#include "MsgNode.h" +#include + +class CSession; +class LogicNode { +public: + LogicNode(std::shared_ptr, std::shared_ptr); + shared_ptr _session; + shared_ptr _recvnode; +}; + +typedef function, + const short& msg_id, const string& msg_data)> FunCallBack; + +class LogicWorker +{ +public: + LogicWorker(); + ~LogicWorker(); + void PostTask(std::shared_ptr task); + void RegisterCallBacks(); +private: + void task_callback(std::shared_ptr); + std::thread _work_thread; + std::queue> _task_que; + std::atomic _b_stop; + std::mutex _mtx; + std::condition_variable _cv; + std::unordered_map _fun_callbacks; +}; + diff --git a/server/ResourceServer/MsgNode.cpp b/server/ResourceServer/MsgNode.cpp new file mode 100644 index 0000000..e0330a5 --- /dev/null +++ b/server/ResourceServer/MsgNode.cpp @@ -0,0 +1,17 @@ +#include "MsgNode.h" +RecvNode::RecvNode(int max_len, short msg_id):MsgNode(max_len), +_msg_id(msg_id){ + +} + + +SendNode::SendNode(const char* msg, int max_len, short msg_id):MsgNode(max_len + HEAD_TOTAL_LEN) +, _msg_id(msg_id){ + //ȷid, תΪֽ + short msg_id_host = boost::asio::detail::socket_ops::host_to_network_short(msg_id); + memcpy(_data, &msg_id_host, HEAD_ID_LEN); + //תΪֽ + int max_len_host = boost::asio::detail::socket_ops::host_to_network_long(max_len); + memcpy(_data + HEAD_ID_LEN, &max_len_host, HEAD_DATA_LEN); + memcpy(_data + HEAD_ID_LEN + HEAD_DATA_LEN, msg, max_len); +} diff --git a/server/ResourceServer/MsgNode.h b/server/ResourceServer/MsgNode.h new file mode 100644 index 0000000..5784c9b --- /dev/null +++ b/server/ResourceServer/MsgNode.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include "const.h" +#include +#include +using namespace std; +using boost::asio::ip::tcp; +class LogicSystem; +class MsgNode +{ +public: + MsgNode(int max_len) :_total_len(max_len), _cur_len(0) { + _data = new char[_total_len + 1](); + _data[_total_len] = '\0'; + } + + ~MsgNode() { + std::cout << "destruct MsgNode" << endl; + delete[] _data; + } + + void Clear() { + ::memset(_data, 0, _total_len); + _cur_len = 0; + } + + int _cur_len; + int _total_len; + char* _data; +}; + +class RecvNode :public MsgNode { +public: + RecvNode(int max_len, short msg_id); + short _msg_id; +}; + +class SendNode:public MsgNode { +public: + SendNode(const char* msg,int max_len, short msg_id); + short _msg_id; +}; + diff --git a/server/ResourceServer/MysqlDao.cpp b/server/ResourceServer/MysqlDao.cpp new file mode 100644 index 0000000..0e33564 --- /dev/null +++ b/server/ResourceServer/MysqlDao.cpp @@ -0,0 +1,1083 @@ +#include "MysqlDao.h" +#include "ConfigMgr.h" +#include "const.h" + +MysqlDao::MysqlDao() +{ + auto& cfg = ConfigMgr::Inst(); + const auto& host = cfg["Mysql"]["Host"]; + const auto& port = cfg["Mysql"]["Port"]; + const auto& pwd = cfg["Mysql"]["Passwd"]; + const auto& schema = cfg["Mysql"]["Schema"]; + const auto& user = cfg["Mysql"]["User"]; + pool_.reset(new MySqlPool(host + ":" + port, user, pwd, schema, 5)); +} + +MysqlDao::~MysqlDao() { + pool_->Close(); +} + +int MysqlDao::RegUser(const std::string& name, const std::string& email, const std::string& pwd) +{ + auto con = pool_->getConnection(); + try { + if (con == nullptr) { + return false; + } + // ׼ô洢 + std::unique_ptr < sql::PreparedStatement > stmt(con->_con->prepareStatement("CALL reg_user(?,?,?,@result)")); + // + stmt->setString(1, name); + stmt->setString(2, email); + stmt->setString(3, pwd); + + // PreparedStatementֱ֧עҪʹûỰȡֵ + + // ִд洢 + stmt->execute(); + // 洢˻ỰʽȡִֵSELECTѯȡ + // 磬洢һỰ@result洢ȡ + std::unique_ptr stmtResult(con->_con->createStatement()); + std::unique_ptr res(stmtResult->executeQuery("SELECT @result AS result")); + if (res->next()) { + int result = res->getInt("result"); + std::cout << "Result: " << result << std::endl; + pool_->returnConnection(std::move(con)); + return result; + } + pool_->returnConnection(std::move(con)); + return -1; + } + catch (sql::SQLException& e) { + pool_->returnConnection(std::move(con)); + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return -1; + } +} + +bool MysqlDao::CheckEmail(const std::string& name, const std::string& email) { + auto con = pool_->getConnection(); + try { + if (con == nullptr) { + return false; + } + + // ׼ѯ + std::unique_ptr pstmt(con->_con->prepareStatement("SELECT email FROM user WHERE name = ?")); + + // 󶨲 + pstmt->setString(1, name); + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + + // + while (res->next()) { + std::cout << "Check Email: " << res->getString("email") << std::endl; + if (email != res->getString("email")) { + pool_->returnConnection(std::move(con)); + return false; + } + pool_->returnConnection(std::move(con)); + return true; + } + return true; + } + catch (sql::SQLException& e) { + pool_->returnConnection(std::move(con)); + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } +} + +bool MysqlDao::UpdatePwd(const std::string& name, const std::string& newpwd) { + auto con = pool_->getConnection(); + try { + if (con == nullptr) { + return false; + } + + // ׼ѯ + std::unique_ptr pstmt(con->_con->prepareStatement("UPDATE user SET pwd = ? WHERE name = ?")); + + // 󶨲 + pstmt->setString(2, name); + pstmt->setString(1, newpwd); + + // ִи + int updateCount = pstmt->executeUpdate(); + + std::cout << "Updated rows: " << updateCount << std::endl; + pool_->returnConnection(std::move(con)); + return true; + } + catch (sql::SQLException& e) { + pool_->returnConnection(std::move(con)); + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } +} + +bool MysqlDao::CheckPwd(const std::string& name, const std::string& pwd, UserInfo& userInfo) { + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + // ׼SQL + std::unique_ptr pstmt(con->_con->prepareStatement("SELECT * FROM user WHERE name = ?")); + pstmt->setString(1, name); // username滻ΪҪѯû + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + std::string origin_pwd = ""; + // + while (res->next()) { + origin_pwd = res->getString("pwd"); + // ѯ + std::cout << "Password: " << origin_pwd << std::endl; + break; + } + + if (pwd != origin_pwd) { + return false; + } + userInfo.name = name; + userInfo.email = res->getString("email"); + userInfo.uid = res->getInt("uid"); + userInfo.pwd = origin_pwd; + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } +} + +bool MysqlDao::AddFriendApply(const int& from, const int& to, + const std::string& desc, const std::string& back_name) +{ + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + // ׼SQL + std::unique_ptr pstmt( + con->_con->prepareStatement("INSERT INTO friend_apply (from_uid, to_uid, descs, back_name) " + "values (?,?,?,?) " + "ON DUPLICATE KEY UPDATE from_uid = from_uid, to_uid = to_uid, descs = ?, back_name = ?")); + pstmt->setInt(1, from); // from id + pstmt->setInt(2, to); + pstmt->setString(3, desc); + pstmt->setString(4, back_name); + pstmt->setString(5, desc); + pstmt->setString(6, back_name); + // ִи + int rowAffected = pstmt->executeUpdate(); + if (rowAffected < 0) { + return false; + } + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } + + + return true; +} + +bool MysqlDao::AuthFriendApply(const int& from, const int& to) { + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + // ׼SQL + std::unique_ptr pstmt(con->_con->prepareStatement("UPDATE friend_apply SET status = 1 " + "WHERE from_uid = ? AND to_uid = ?")); + //ʱfrom֤ʱto + pstmt->setInt(1, to); // from id + pstmt->setInt(2, from); + // ִи + int rowAffected = pstmt->executeUpdate(); + if (rowAffected < 0) { + return false; + } + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } + + + return true; +} + +bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, + std::vector>& chat_datas) { + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + + //ʼ + con->_con->setAutoCommit(false); + std::string reverse_back; + std::string apply_desc; + + { + // 1. ȡ + std::unique_ptr selStmt(con->_con->prepareStatement( + "SELECT back_name, descs " + "FROM friend_apply " + "WHERE from_uid = ? AND to_uid = ? " + "FOR UPDATE" + )); + selStmt->setInt(1, to); + selStmt->setInt(2, from); + + std::unique_ptr rsSel(selStmt->executeQuery()); + + if (rsSel->next()) { + reverse_back = rsSel->getString("back_name"); + apply_desc = rsSel->getString("descs"); + } + else { + // ûжӦ¼ֱ rollback ʧ + con->_con->rollback(); + return false; + } + } + + { + // 2. ִĸ + std::unique_ptr updStmt(con->_con->prepareStatement( + "UPDATE friend_apply " + "SET status = 1 " + "WHERE from_uid = ? AND to_uid = ?" + )); + + updStmt->setInt(1, to); + updStmt->setInt(2, from); + + if (updStmt->executeUpdate() != 1) { + // ԣع + con->_con->rollback(); + return false; + } + } + + { + // 3. ׼һSQL, ֤ + std::unique_ptr pstmt(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?) " + )); + //ʱfrom֤ʱto + pstmt->setInt(1, from); // from id + pstmt->setInt(2, to); + pstmt->setString(3, back_name); + // ִи + int rowAffected = pstmt->executeUpdate(); + if (rowAffected < 0) { + con->_con->rollback(); + return false; + } + + //׼ڶSQL䣬뷽 + std::unique_ptr pstmt2(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?) " + )); + //ʱfrom֤ʱto + pstmt2->setInt(1, to); // from id + pstmt2->setInt(2, from); + pstmt2->setString(3, reverse_back); + // ִи + int rowAffected2 = pstmt2->executeUpdate(); + if (rowAffected2 < 0) { + con->_con->rollback(); + return false; + } + } + + + + // 4. chat_thread + long long threadId = 0; + { + std::unique_ptr threadStmt(con->_con->prepareStatement( + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());" + )); + + threadStmt->executeUpdate(); + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + + if (rs->next()) { + threadId = rs->getInt64(1); + } + else { + return false; + } + } + + // 5. private_chat + { + std::unique_ptr pcStmt(con->_con->prepareStatement( + "INSERT INTO private_chat(thread_id, user1_id, user2_id) VALUES (?, ?, ?)" + )); + + pcStmt->setInt64(1, threadId); + pcStmt->setInt(2, from); + pcStmt->setInt(3, to); + if (pcStmt->executeUpdate() < 0) return false; + } + + // 6. ѡʼϢ chat_message + if (apply_desc.empty() == false) + { + std::unique_ptr msgStmt(con->_con->prepareStatement( + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content,created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + )); + + msgStmt->setInt64(1, threadId); + msgStmt->setInt(2, to); + msgStmt->setInt(3, from); + msgStmt->setString(4, apply_desc); + msgStmt->setInt(5, 2); + if (msgStmt->executeUpdate() < 0) { return false; } + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + auto messageId = rs->getInt64(1); + auto tx_data = std::make_shared(); + tx_data->set_sender_id(to); + tx_data->set_msg_id(messageId); + tx_data->set_msgcontent(apply_desc); + tx_data->set_thread_id(threadId); + tx_data->set_unique_id(""); + tx_data->set_status(2); + std::cout << "addfriend insert message success" << std::endl; + chat_datas.push_back(tx_data); + } + else { + return false; + } + } + + { + std::unique_ptr msgStmt(con->_con->prepareStatement( + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + )); + + msgStmt->setInt64(1, threadId); + msgStmt->setInt(2, from); + msgStmt->setInt(3, to); + msgStmt->setString(4, "We are friends now!"); + + msgStmt->setInt(5, 2); + + if (msgStmt->executeUpdate() < 0) { return false; } + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + auto messageId = rs->getInt64(1); + auto tx_data = std::make_shared(); + tx_data->set_sender_id(from); + tx_data->set_msg_id(messageId); + tx_data->set_msgcontent("We are friends now!"); + tx_data->set_thread_id(threadId); + tx_data->set_unique_id(""); + tx_data->set_status(2); + chat_datas.push_back(tx_data); + } + else { + return false; + } + } + + // ύ + con->_con->commit(); + std::cout << "addfriend insert friends success" << std::endl; + + return true; + } + catch (sql::SQLException& e) { + // 󣬻ع + if (con) { + con->_con->rollback(); + } + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } + + + return true; +} + +std::shared_ptr MysqlDao::GetUser(int uid) +{ + auto con = pool_->getConnection(); + if (con == nullptr) { + return nullptr; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + // ׼SQL + std::unique_ptr pstmt(con->_con->prepareStatement("SELECT * FROM user WHERE uid = ?")); + pstmt->setInt(1, uid); // uid滻ΪҪѯuid + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + std::shared_ptr user_ptr = nullptr; + // + while (res->next()) { + user_ptr.reset(new UserInfo); + user_ptr->pwd = res->getString("pwd"); + user_ptr->email = res->getString("email"); + user_ptr->name = res->getString("name"); + user_ptr->nick = res->getString("nick"); + user_ptr->desc = res->getString("desc"); + user_ptr->sex = res->getInt("sex"); + user_ptr->icon = res->getString("icon"); + user_ptr->uid = uid; + break; + } + return user_ptr; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return nullptr; + } +} + +std::shared_ptr MysqlDao::GetUser(std::string name) +{ + auto con = pool_->getConnection(); + if (con == nullptr) { + return nullptr; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + // ׼SQL + std::unique_ptr pstmt(con->_con->prepareStatement("SELECT * FROM user WHERE name = ?")); + pstmt->setString(1, name); // uid滻ΪҪѯuid + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + std::shared_ptr user_ptr = nullptr; + // + while (res->next()) { + user_ptr.reset(new UserInfo); + user_ptr->pwd = res->getString("pwd"); + user_ptr->email = res->getString("email"); + user_ptr->name = res->getString("name"); + user_ptr->nick = res->getString("nick"); + user_ptr->desc = res->getString("desc"); + user_ptr->sex = res->getInt("sex"); + user_ptr->uid = res->getInt("uid"); + user_ptr->icon = res->getString("icon"); + break; + } + return user_ptr; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return nullptr; + } +} + + +bool MysqlDao::GetApplyList(int touid, std::vector>& applyList, int begin, int limit) { + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + + try { + // ׼SQL, ʼidб + std::unique_ptr pstmt(con->_con->prepareStatement("select apply.from_uid, apply.status, user.name, " + "user.nick, user.sex from friend_apply as apply join user on apply.from_uid = user.uid where apply.to_uid = ? " + "and apply.id > ? order by apply.id ASC LIMIT ? ")); + + pstmt->setInt(1, touid); // uid滻ΪҪѯuid + pstmt->setInt(2, begin); // ʼid + pstmt->setInt(3, limit); //ƫ + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + // + while (res->next()) { + auto name = res->getString("name"); + auto uid = res->getInt("from_uid"); + auto status = res->getInt("status"); + auto nick = res->getString("nick"); + auto sex = res->getInt("sex"); + auto apply_ptr = std::make_shared(uid, name, "", "", nick, sex, status); + applyList.push_back(apply_ptr); + } + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } +} + +bool MysqlDao::GetFriendList(int self_id, std::vector >& user_info_list) { + + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + + try { + // ׼SQL, ʼidб + std::unique_ptr pstmt(con->_con->prepareStatement("select * from friend where self_id = ? ")); + + pstmt->setInt(1, self_id); // uid滻ΪҪѯuid + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + // + while (res->next()) { + auto friend_id = res->getInt("friend_id"); + auto back = res->getString("back"); + //һβѯfriend_idӦϢ + auto user_info = GetUser(friend_id); + if (user_info == nullptr) { + continue; + } + + user_info->back = user_info->name; + user_info_list.push_back(user_info); + } + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } + + return true; +} + +// loadMore, nextLastId +bool MysqlDao::GetUserThreads( + int64_t userId, + int64_t lastId, + int pageSize, + std::vector>& threads, + bool& loadMore, + int& nextLastId) +{ + // ʼ״̬ + loadMore = false; + nextLastId = lastId; + threads.clear(); + + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + try { + // ׼ҳѯCTE + UNION ALL + ORDER + LIMIT N+1 + std::string sql = + "WITH all_threads AS ( " + " SELECT thread_id, 'private' AS type, user1_id, user2_id " + " FROM private_chat " + " WHERE (user1_id = ? OR user2_id = ?) " + " AND thread_id > ? " + " UNION ALL " + " SELECT thread_id, 'group' AS type, 0 AS user1_id, 0 AS user2_id " + " FROM group_chat_member " + " WHERE user_id = ? " + " AND thread_id > ? " + ") " + "SELECT thread_id, type, user1_id, user2_id " + " FROM all_threads " + " ORDER BY thread_id " + " LIMIT ?;"; + + std::unique_ptr pstmt( + conn->prepareStatement(sql)); + + // 󶨲? Ӧ (userId, userId, lastId, userId, lastId, pageSize+1) + int idx = 1; + pstmt->setInt64(idx++, userId); // private.user1_id + pstmt->setInt64(idx++, userId); // private.user2_id + pstmt->setInt64(idx++, lastId); // private.thread_id > lastId + pstmt->setInt64(idx++, userId); // group.user_id + pstmt->setInt64(idx++, lastId); // group.thread_id > lastId + pstmt->setInt(idx++, pageSize + 1); // LIMIT pageSize+1 + + // ִ + std::unique_ptr res(pstmt->executeQuery()); + + // Ȱжʱ + std::vector> tmp; + while (res->next()) { + auto cti = std::make_shared(); + cti->_thread_id = res->getInt64("thread_id"); + cti->_type = res->getString("type"); + cti->_user1_id = res->getInt64("user1_id"); + cti->_user2_id = res->getInt64("user2_id"); + tmp.push_back(cti); + } + + // жǷȡһ + if ((int)tmp.size() > pageSize) { + loadMore = true; + tmp.pop_back(); // pageSize+1 + } + + // ݣ nextLastId Ϊһ thread_id + if (!tmp.empty()) { + nextLastId = tmp.back()->_thread_id; + } + + // + threads = std::move(tmp); + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() + << " (MySQL error code: " << e.getErrorCode() + << ", SQLState: " << e.getSQLState() << ")\n"; + return false; + } + + return true; +} + +bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) +{ + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + try { + // + conn->setAutoCommit(false); + // 1. ѯǷѴ˽IJм + int uid1 = std::min(user1_id, user2_id); + int uid2 = std::max(user1_id, user2_id); + std::string check_sql = + "SELECT thread_id FROM private_chat " + "WHERE (user1_id = ? AND user2_id = ?) " + "FOR UPDATE;"; + + std::unique_ptr pstmt(conn->prepareStatement(check_sql)); + pstmt->setInt64(1, uid1); + pstmt->setInt64(2, uid2); + std::unique_ptr res(pstmt->executeQuery()); + + if (res->next()) { + // Ѵڣظ thread_id + thread_id = res->getInt("thread_id"); + conn->commit(); // ύ + return true; + } + + // 2. δҵµ chat_thread private_chat ¼ + // chat_thread ¼¼ + std::string insert_chat_thread_sql = + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());"; + + std::unique_ptr pstmt_insert_thread(conn->prepareStatement(insert_chat_thread_sql)); + pstmt_insert_thread->executeUpdate(); + + // ȡ² thread_id + std::string get_last_insert_id_sql = "SELECT LAST_INSERT_ID();"; + std::unique_ptr pstmt_last_insert_id(conn->prepareStatement(get_last_insert_id_sql)); + std::unique_ptr res_last_id(pstmt_last_insert_id->executeQuery()); + res_last_id->next(); + thread_id = res_last_id->getInt(1); + + // 3. private_chat ¼¼ + std::string insert_private_chat_sql = + "INSERT INTO private_chat (thread_id, user1_id, user2_id, created_at) " + "VALUES (?, ?, ?, NOW());"; + + + std::unique_ptr pstmt_insert_private(conn->prepareStatement(insert_private_chat_sql)); + pstmt_insert_private->setInt64(1, thread_id); + pstmt_insert_private->setInt64(2, uid1); + pstmt_insert_private->setInt64(3, uid2); + pstmt_insert_private->executeUpdate(); + + // ύ + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } + return false; +} + +std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_message_id, int page_size) +{ + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + + try { + auto page_res = std::make_shared(); + page_res->load_more = false; + page_res->next_cursor = last_message_id; + + // SQLȡһжǷи + const std::string sql = R"( + SELECT message_id, thread_id, sender_id, recv_id, content, + created_at, updated_at, status + FROM chat_message + WHERE thread_id = ? + AND message_id > ? + ORDER BY message_id ASC + LIMIT ? + )"; + + uint32_t fetch_limit = page_size + 1; + auto pstmt = std::unique_ptr( + conn->prepareStatement(sql) + ); + pstmt->setInt(1, thread_id); + pstmt->setInt(2, last_message_id); + pstmt->setInt(3, fetch_limit); + + auto rs = std::unique_ptr(pstmt->executeQuery()); + + // ȡ fetch_limit ¼ + while (rs->next()) { + ChatMessage msg; + msg.message_id = rs->getUInt64("message_id"); + msg.thread_id = rs->getUInt64("thread_id"); + msg.sender_id = rs->getUInt64("sender_id"); + msg.recv_id = rs->getUInt64("recv_id"); + msg.content = rs->getString("content"); + msg.chat_time = rs->getString("created_at"); + msg.status = rs->getInt("status"); + page_res->messages.push_back(std::move(msg)); + } + + return page_res; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return nullptr; + } + return nullptr; + +} + + +bool MysqlDao::AddChatMsg(std::vector>& chat_datas) { + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + + try { + //رԶύֶ + conn->setAutoCommit(false); + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "INSERT INTO chat_message " + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, ?, ?, ?)" + ) + ); + + for (auto& msg : chat_datas) { + // ֶͨ + pstmt->setUInt64(1, msg->thread_id); + pstmt->setUInt64(2, msg->sender_id); + pstmt->setUInt64(3, msg->recv_id); + pstmt->setString(4, msg->content); + + pstmt->setString(5, msg->chat_time); // created_at + pstmt->setString(6, msg->chat_time); // updated_at + + pstmt->setInt(7, msg->status); + pstmt->executeUpdate(); + + // 2. ȡ LAST_INSERT_ID() + std::unique_ptr keyStmt( + conn->createStatement() + ); + std::unique_ptr rs( + keyStmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + msg->message_id = rs->getUInt64(1); + } + else { + continue; + } + } + + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } + return true; + +} + + +bool MysqlDao::UpdateHeadInfo(int uid, const std::string& icon) +{ + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + try { + std::string update_sql = + "UPDATE user SET icon = ? WHERE uid = ?;"; + + std::unique_ptr pstmt(conn->prepareStatement(update_sql)); + pstmt->setString(1, icon); + pstmt->setInt64(2, uid); + + int affected_rows = pstmt->executeUpdate(); + + // Ƿб£ѡ + if (affected_rows == 0) { + std::cerr << "No user found with uid: " << uid << std::endl; + return false; + } + + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException in UpdateHeadInfo: " << e.what() << std::endl; + return false; + } + return false; +} + +bool MysqlDao::UpdateUploadStatus(int chat_message_id) +{ + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + try { + std::string update_sql = + "UPDATE chat_message SET status = ? WHERE message_id = ?;"; + + std::unique_ptr pstmt(conn->prepareStatement(update_sql)); + pstmt->setInt(1, MsgStatus::READED); + pstmt->setInt64(2, chat_message_id); + + int affected_rows = pstmt->executeUpdate(); + + // Ƿб£ѡ + if (affected_rows == 0) { + std::cerr << "No chat message found with chat_message_id: " << chat_message_id << std::endl; + return false; + } + + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException in UpdateUploadStatus: " << e.what() << std::endl; + return false; + } + return false; +} + +std::shared_ptr MysqlDao::GetImgInfoByMsgId(int message_id) { + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + try { + std::string update_sql = + "select message_id, sender_id, recv_id, content from WHERE message_id = ?;"; + + // ׼ѯ + std::unique_ptr pstmt(con->_con->prepareStatement(update_sql)); + + // 󶨲 + pstmt->setInt(1, message_id); + + // ִвѯ + std::unique_ptr res(pstmt->executeQuery()); + // + while (res->next()) { + auto message_id = res->getInt64("message_id"); + auto sender_id = res->getInt64("sender_id"); + auto recv_id = res->getInt64("recv_id"); + auto img_name = res->getString("content"); + auto img_info = std::make_shared(sender_id, recv_id, message_id, img_name); + return img_info; + } + return nullptr; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException in UpdateUploadStatus: " << e.what() << std::endl; + return nullptr; + } + return nullptr; +} + +std::shared_ptr MysqlDao::GetChatMsgById(int message_id) { + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + + try { + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "SELECT message_id, thread_id, sender_id, recv_id, " + "content, created_at, updated_at, status , msg_type " + "FROM chat_message WHERE message_id = ?" + ) + ); + + pstmt->setUInt64(1, message_id); + auto rs = std::unique_ptr(pstmt->executeQuery()); + + if (rs->next()) { + auto msg = std::make_shared(); + msg->message_id = rs->getUInt64("message_id"); + msg->thread_id = rs->getUInt64("thread_id"); + msg->sender_id = rs->getUInt64("sender_id"); + msg->recv_id = rs->getUInt64("recv_id"); + msg->content = rs->getString("content"); + msg->chat_time = rs->getString("created_at"); + msg->status = rs->getInt("status"); + msg->msg_type = rs->getInt("msg_type"); + return msg; + } + + return nullptr; + + } + catch (sql::SQLException& e) { + std::cerr << "GetChatMessageById SQLException: " << e.what() << std::endl; + return nullptr; + } +} diff --git a/server/ResourceServer/MysqlDao.h b/server/ResourceServer/MysqlDao.h new file mode 100644 index 0000000..6836f0f --- /dev/null +++ b/server/ResourceServer/MysqlDao.h @@ -0,0 +1,272 @@ +#pragma once +#include "const.h" +#include +#include +#include +#include +#include +#include +#include +#include "data.h" +#include +#include +#include +#include "message.pb.h" +#include "FileInfo.h" +using message::AddFriendMsg; +using message::TextChatData; + +class SqlConnection { +public: + SqlConnection(sql::Connection* con, int64_t lasttime):_con(con), _last_oper_time(lasttime){} + std::unique_ptr _con; + int64_t _last_oper_time; +}; + +class MySqlPool { +public: + MySqlPool(const std::string& url, const std::string& user, const std::string& pass, const std::string& schema, int poolSize) + : url_(url), user_(user), pass_(pass), schema_(schema), poolSize_(poolSize), b_stop_(false), _fail_count(0){ + try { + for (int i = 0; i < poolSize_; ++i) { + sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance(); + auto* con = driver->connect(url_, user_, pass_); + con->setSchema(schema_); + // ȡǰʱ + auto currentTime = std::chrono::system_clock::now().time_since_epoch(); + // ʱתΪ + long long timestamp = std::chrono::duration_cast(currentTime).count(); + pool_.push(std::make_unique(con, timestamp)); + std::cout << "mysql connection init success" << std::endl; + } + + _check_thread = std::thread([this]() { + int count = 0; + while (!b_stop_) { + if (count >= 60) { + count = 0; + checkConnectionPro(); + } + std::this_thread::sleep_for(std::chrono::seconds(1)); + count++; + } + }); + + _check_thread.detach(); + } + catch (sql::SQLException& e) { + // 쳣 + std::cout << "mysql pool init failed, error is " << e.what()<< std::endl; + } + } + + void checkConnectionPro() { + // 1)ȶȡĿ괦 + size_t targetCount; + { + std::lock_guard guard(mutex_); + targetCount = pool_.size(); + } + + //2 ǰѾ + size_t processed = 0; + + //3 ʱ + auto now = std::chrono::system_clock::now().time_since_epoch(); + long long timestamp = std::chrono::duration_cast(now).count(); + + while (processed < targetCount) { + std::unique_ptr con; + { + std::lock_guard guard(mutex_); + if (pool_.empty()) { + break; + } + con = std::move(pool_.front()); + pool_.pop(); + } + + bool healthy = true; + ///߼ + if (timestamp - con->_last_oper_time >= 5) { + try { + std::unique_ptr stmt(con->_con->createStatement()); + stmt->executeQuery("SELECT 1"); + con->_last_oper_time = timestamp; + } + catch (sql::SQLException& e) { + std::cout << "Error keeping connection alive: " << e.what() << std::endl; + healthy = false; + _fail_count++; + } + + } + + if (healthy) + { + std::lock_guard guard(mutex_); + pool_.push(std::move(con)); + cond_.notify_one(); + } + + ++processed; + } + + while (_fail_count > 0) { + auto b_res = reconnect(timestamp); + if (b_res) { + _fail_count--; + } + else { + break; + } + } + } + + bool reconnect(long long timestamp) { + try { + + sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance(); + auto* con = driver->connect(url_, user_, pass_); + con->setSchema(schema_); + + auto newCon = std::make_unique(con, timestamp); + { + std::lock_guard guard(mutex_); + pool_.push(std::move(newCon)); + } + std::cout << "mysql connection reconnect success" << std::endl; + return true; + + } + catch (sql::SQLException& e) { + std::cout << "Reconnect failed, error is " << e.what() << std::endl; + return false; + } + } + + + void checkConnection() { + std::lock_guard guard(mutex_); + int poolsize = pool_.size(); + // ȡǰʱ + auto currentTime = std::chrono::system_clock::now().time_since_epoch(); + // ʱתΪ + long long timestamp = std::chrono::duration_cast(currentTime).count(); + for (int i = 0; i < poolsize; i++) { + auto con = std::move(pool_.front()); + pool_.pop(); + Defer defer([this, &con]() { + pool_.push(std::move(con)); + }); + + if (timestamp - con->_last_oper_time < 5) { + continue; + } + + try { + std::unique_ptr stmt(con->_con->createStatement()); + stmt->executeQuery("SELECT 1"); + con->_last_oper_time = timestamp; + //std::cout << "execute timer alive query , cur is " << timestamp << std::endl; + } + catch (sql::SQLException& e) { + std::cout << "Error keeping connection alive: " << e.what() << std::endl; + // ´Ӳ滻ɵ + sql::mysql::MySQL_Driver* driver = sql::mysql::get_mysql_driver_instance(); + auto* newcon = driver->connect(url_, user_, pass_); + newcon->setSchema(schema_); + con->_con.reset(newcon); + con->_last_oper_time = timestamp; + } + } + } + + std::unique_ptr getConnection() { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { + if (b_stop_) { + return true; + } + return !pool_.empty(); }); + if (b_stop_) { + return nullptr; + } + std::unique_ptr con(std::move(pool_.front())); + pool_.pop(); + return con; + } + + void returnConnection(std::unique_ptr con) { + std::unique_lock lock(mutex_); + if (b_stop_) { + return; + } + pool_.push(std::move(con)); + cond_.notify_one(); + } + + void Close() { + b_stop_ = true; + cond_.notify_all(); + } + + ~MySqlPool() { + std::unique_lock lock(mutex_); + while (!pool_.empty()) { + pool_.pop(); + } + } + +private: + std::string url_; + std::string user_; + std::string pass_; + std::string schema_; + int poolSize_; + std::queue> pool_; + std::mutex mutex_; + std::condition_variable cond_; + std::atomic b_stop_; + std::thread _check_thread; + std::atomic _fail_count; +}; + + + +class MysqlDao +{ +public: + MysqlDao(); + ~MysqlDao(); + int RegUser(const std::string& name, const std::string& email, const std::string& pwd); + bool CheckEmail(const std::string& name, const std::string & email); + bool UpdatePwd(const std::string& name, const std::string& newpwd); + bool CheckPwd(const std::string& name, const std::string& pwd, UserInfo& userInfo); + bool AddFriendApply(const int& from, const int& to, const std::string& desc, const std::string& back_name); + bool AuthFriendApply(const int& from, const int& to); + bool AddFriend(const int& from, const int& to, std::string back_name, std::vector> &chat_datas); + std::shared_ptr GetUser(int uid); + std::shared_ptr GetUser(std::string name); + bool GetApplyList(int touid, std::vector>& applyList, int offset, int limit ); + bool GetFriendList(int self_id, std::vector >& user_info); + bool GetUserThreads( + int64_t userId, + int64_t lastId, + int pageSize, + std::vector>& threads, + bool& loadMore, + int& nextLastId); + bool CreatePrivateChat(int user1_id, int user2_id, int& thread_id); + std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); + bool AddChatMsg(std::vector>& chat_datas); + bool UpdateHeadInfo(int uid, const std::string& icon); + bool UpdateUploadStatus(int chat_message_id); + std::shared_ptr GetImgInfoByMsgId(int message_id); + std::shared_ptr GetChatMsgById(int message_id); + +private: + std::unique_ptr pool_; +}; + + diff --git a/server/ResourceServer/MysqlMgr.cpp b/server/ResourceServer/MysqlMgr.cpp new file mode 100644 index 0000000..87d6f93 --- /dev/null +++ b/server/ResourceServer/MysqlMgr.cpp @@ -0,0 +1,104 @@ +#include "MysqlMgr.h" + + +MysqlMgr::~MysqlMgr() { + +} + +int MysqlMgr::RegUser(const std::string& name, const std::string& email, const std::string& pwd) +{ + return _dao.RegUser(name, email, pwd); +} + +bool MysqlMgr::CheckEmail(const std::string& name, const std::string& email) { + return _dao.CheckEmail(name, email); +} + +bool MysqlMgr::UpdatePwd(const std::string& name, const std::string& pwd) { + return _dao.UpdatePwd(name, pwd); +} + +MysqlMgr::MysqlMgr() { +} + +bool MysqlMgr::CheckPwd(const std::string& name, const std::string& pwd, UserInfo& userInfo) { + return _dao.CheckPwd(name, pwd, userInfo); +} + +bool MysqlMgr::AddFriendApply(const int& from, const int& to, const std::string& desc, const std::string& back_name) +{ + return _dao.AddFriendApply(from, to, desc, back_name); +} + +bool MysqlMgr::AuthFriendApply(const int& from, const int& to) { + return _dao.AuthFriendApply(from, to); +} + +bool MysqlMgr::AddFriend(const int& from, const int& to, std::string back_name, + std::vector>& msg_list) { + return _dao.AddFriend(from, to, back_name, msg_list); +} + +std::shared_ptr MysqlMgr::GetUser(int uid) +{ + return _dao.GetUser(uid); +} + +std::shared_ptr MysqlMgr::GetUser(std::string name) +{ + return _dao.GetUser(name); +} + +bool MysqlMgr::GetApplyList(int touid, + std::vector>& applyList, int begin, int limit) { + + return _dao.GetApplyList(touid, applyList, begin, limit); +} + +bool MysqlMgr::GetFriendList(int self_id, std::vector >& user_info) { + return _dao.GetFriendList(self_id, user_info); +} + +bool MysqlMgr::GetUserThreads(int64_t userId, + int64_t lastId, + int pageSize, + std::vector>& threads, + bool& loadMore, + int& nextLastId) +{ + return _dao.GetUserThreads(userId, lastId, pageSize, threads, loadMore, nextLastId); +} + +bool MysqlMgr::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) +{ + return _dao.CreatePrivateChat(user1_id, user2_id, thread_id); +} + +std::shared_ptr MysqlMgr::LoadChatMsg(int threadId, int lastId, int pageSize) +{ + return _dao.LoadChatMsg(threadId, lastId, pageSize); +} + +bool MysqlMgr::AddChatMsg(std::vector>& chat_datas) { + return _dao.AddChatMsg(chat_datas); +} + +bool MysqlMgr::UpdateUserIcon(int uid, const std::string& icon) { + return _dao.UpdateHeadInfo(uid, icon); +} + +bool MysqlMgr::UpdateUploadStatus(int chat_messag_id) +{ + return _dao.UpdateUploadStatus(chat_messag_id); +} + +std::shared_ptr MysqlMgr::GetImgInfoByMsgId(int msg_id) +{ + //ѯݿȡͼƬϢ + return _dao.GetImgInfoByMsgId(msg_id); +} + +std::shared_ptr MysqlMgr::GetChatMsgById(int message_id) +{ + return _dao.GetChatMsgById(message_id); +} \ No newline at end of file diff --git a/server/ResourceServer/MysqlMgr.h b/server/ResourceServer/MysqlMgr.h new file mode 100644 index 0000000..e3fe4a9 --- /dev/null +++ b/server/ResourceServer/MysqlMgr.h @@ -0,0 +1,43 @@ +#pragma once +#include "const.h" +#include "MysqlDao.h" +#include "Singleton.h" +#include +#include "message.pb.h" +#include "FileInfo.h" + +class MysqlMgr: public Singleton +{ + friend class Singleton; +public: + ~MysqlMgr(); + int RegUser(const std::string& name, const std::string& email, const std::string& pwd); + bool CheckEmail(const std::string& name, const std::string & email); + bool UpdatePwd(const std::string& name, const std::string& email); + bool CheckPwd(const std::string& name, const std::string& pwd, UserInfo& userInfo); + bool AddFriendApply(const int& from, const int& to, const std::string& desc, const std::string& back_name); + bool AuthFriendApply(const int& from, const int& to); + bool AddFriend(const int& from, const int& to, std::string back_name, std::vector>& msg_list); + std::shared_ptr GetUser(int uid); + std::shared_ptr GetUser(std::string name); + bool GetApplyList(int touid, std::vector>& applyList, int begin, int limit=10); + bool GetFriendList(int self_id, std::vector >& user_info); + bool GetUserThreads(int64_t userId, + int64_t lastId, + int pageSize, + std::vector>& threads, + bool& loadMore, + int& nextLastId); + + bool CreatePrivateChat(int user1_id, int user2_id, int &thread_id); + std::shared_ptr LoadChatMsg(int threadId, int lastId, int pageSize); + bool AddChatMsg(std::vector>& chat_datas); + bool UpdateUserIcon(int uid, const std::string& icon); + bool UpdateUploadStatus(int chat_messag_id); + std::shared_ptr GetImgInfoByMsgId(int msg_id); + std::shared_ptr GetChatMsgById(int message_id); +private: + MysqlMgr(); + MysqlDao _dao; +}; + diff --git a/server/ResourceServer/PropertySheet.props b/server/ResourceServer/PropertySheet.props new file mode 100644 index 0000000..07876aa --- /dev/null +++ b/server/ResourceServer/PropertySheet.props @@ -0,0 +1,23 @@ + + + + + + D:\cppsoft\redis\deps\hiredis;D:\cppsoft\boost_1_81_0;D:\cppsoft\libjson\include;D:\cppsoft\mysql_connector\include;$(IncludePath) + D:\cppsoft\redis\lib;D:\cppsoft\libjson\lib;D:\cppsoft\boost_1_81_0\stage\lib;D:\cppsoft\mysql_connector\lib64\vs14;$(LibraryPath) + + + + json_vc71_libmtd.lib;libprotobufd.lib;gpr.lib;grpc.lib;grpc++.lib;grpc++_reflection.lib;address_sorting.lib;ws2_32.lib;cares.lib;zlibstaticd.lib;upb.lib;ssl.lib;crypto.lib;absl_bad_any_cast_impl.lib;absl_bad_optional_access.lib;absl_bad_variant_access.lib;absl_base.lib;absl_city.lib;absl_civil_time.lib;absl_cord.lib;absl_debugging_internal.lib;absl_demangle_internal.lib;absl_examine_stack.lib;absl_exponential_biased.lib;absl_failure_signal_handler.lib;absl_flags.lib;absl_flags_config.lib;absl_flags_internal.lib;absl_flags_marshalling.lib;absl_flags_parse.lib;absl_flags_program_name.lib;absl_flags_usage.lib;absl_flags_usage_internal.lib;absl_graphcycles_internal.lib;absl_hash.lib;absl_hashtablez_sampler.lib;absl_int128.lib;absl_leak_check.lib;absl_leak_check_disable.lib;absl_log_severity.lib;absl_malloc_internal.lib;absl_periodic_sampler.lib;absl_random_distributions.lib;absl_random_internal_distribution_test_util.lib;absl_random_internal_pool_urbg.lib;absl_random_internal_randen.lib;absl_random_internal_randen_hwaes.lib;absl_random_internal_randen_hwaes_impl.lib;absl_random_internal_randen_slow.lib;absl_random_internal_seed_material.lib;absl_random_seed_gen_exception.lib;absl_random_seed_sequences.lib;absl_raw_hash_set.lib;absl_raw_logging_internal.lib;absl_scoped_set_env.lib;absl_spinlock_wait.lib;absl_stacktrace.lib;absl_status.lib;absl_strings.lib;absl_strings_internal.lib;absl_str_format_internal.lib;absl_symbolize.lib;absl_synchronization.lib;absl_throw_delegate.lib;absl_time.lib;absl_time_zone.lib;absl_statusor.lib;re2.lib;Win32_Interop.lib;hiredis.lib;libssl.lib;libcrypto.lib;debug\mysqlcppconn.lib;debug\mysqlcppconn8.lib;%(AdditionalDependencies) + D:\cppsoft\grpc\visualpro\third_party\re2\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\types\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\synchronization\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\status\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\random\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\flags\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\debugging\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\container\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\hash\Debug;D:\cppsoft\grpc\visualpro\third_party\boringssl-with-bazel\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\numeric\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\time\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\base\Debug;D:\cppsoft\grpc\visualpro\third_party\abseil-cpp\absl\strings\Debug;D:\cppsoft\grpc\visualpro\third_party\protobuf\Debug;D:\cppsoft\grpc\visualpro\third_party\zlib\Debug;D:\cppsoft\grpc\visualpro\Debug;D:\cppsoft\grpc\visualpro\third_party\cares\cares\lib\Debug;%(AdditionalLibraryDirectories) + + + D:\cppsoft\grpc\third_party\re2;D:\cppsoft\grpc\third_party\address_sorting\include;D:\cppsoft\grpc\third_party\abseil-cpp;D:\cppsoft\grpc\third_party\protobuf\src;D:\cppsoft\grpc\include;%(AdditionalIncludeDirectories) + + + xcopy $(ProjectDir)config.ini $(SolutionDir)$(Platform)\$(Configuration)\ /y + xcopy $(ProjectDir)*.dll $(SolutionDir)$(Platform)\$(Configuration)\ /y + + + + \ No newline at end of file diff --git a/server/ResourceServer/RedisMgr.cpp b/server/ResourceServer/RedisMgr.cpp new file mode 100644 index 0000000..80fee27 --- /dev/null +++ b/server/ResourceServer/RedisMgr.cpp @@ -0,0 +1,602 @@ +#include "RedisMgr.h" +#include "const.h" +#include "ConfigMgr.h" +#include "DistLock.h" +#include +#include +#include +RedisMgr::RedisMgr() { + auto& gCfgMgr = ConfigMgr::Inst(); + auto host = gCfgMgr["Redis"]["Host"]; + auto port = gCfgMgr["Redis"]["Port"]; + auto pwd = gCfgMgr["Redis"]["Passwd"]; + _con_pool.reset(new RedisConPool(10, host.c_str(), atoi(port.c_str()), pwd.c_str())); +} + +RedisMgr::~RedisMgr() { + +} + + + +bool RedisMgr::Get(const std::string& key, std::string& value) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "GET %s", key.c_str()); + if (reply == NULL) { + std::cout << "[ GET " << key << " ] failed" << std::endl; + // freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_STRING) { + std::cout << "[ GET " << key << " ] failed" << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + value = reply->str; + freeReplyObject(reply); + + std::cout << "Succeed to execute command [ GET " << key << " ]" << std::endl; + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::Set(const std::string &key, const std::string &value){ + //ִredis + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "SET %s %s", key.c_str(), value.c_str()); + + //NULL˵ִʧ + if (NULL == reply) + { + std::cout << "Execut command [ SET " << key << " "<< value << " ] failure ! " << std::endl; + //freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + //ִʧͷ + if (!(reply->type == REDIS_REPLY_STATUS && (strcmp(reply->str, "OK") == 0 || strcmp(reply->str, "ok") == 0))) + { + std::cout << "Execut command [ SET " << key << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + std::cout << "Execut command [ SET " << key << " " << value << " ] success ! " << std::endl; + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::SetExp(const std::string& key, const std::string& value, int expire_seconds) { + //ִredis + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "SETEX %s %d %s", key.c_str(), + expire_seconds, + value.c_str()); + + if (NULL == reply) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (!(reply->type == REDIS_REPLY_STATUS && + (strcmp(reply->str, "OK") == 0 || strcmp(reply->str, "ok") == 0))) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + freeReplyObject(reply); + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] success ! " << std::endl; + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::LPush(const std::string &key, const std::string &value) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "LPUSH %s %s", key.c_str(), value.c_str()); + if (NULL == reply) + { + std::cout << "Execut command [ LPUSH " << key << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_INTEGER || reply->integer <= 0) { + std::cout << "Execut command [ LPUSH " << key << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + std::cout << "Execut command [ LPUSH " << key << " " << value << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::LPop(const std::string &key, std::string& value){ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "LPOP %s ", key.c_str()); + if (reply == nullptr ) { + std::cout << "Execut command [ LPOP " << key<< " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type == REDIS_REPLY_NIL) { + std::cout << "Execut command [ LPOP " << key << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + value = reply->str; + std::cout << "Execut command [ LPOP " << key << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::RPush(const std::string& key, const std::string& value) { + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "RPUSH %s %s", key.c_str(), value.c_str()); + if (NULL == reply) + { + std::cout << "Execut command [ RPUSH " << key << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_INTEGER || reply->integer <= 0) { + std::cout << "Execut command [ RPUSH " << key << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + std::cout << "Execut command [ RPUSH " << key << " " << value << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} +bool RedisMgr::RPop(const std::string& key, std::string& value) { + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "RPOP %s ", key.c_str()); + if (reply == nullptr ) { + std::cout << "Execut command [ RPOP " << key << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type == REDIS_REPLY_NIL) { + std::cout << "Execut command [ RPOP " << key << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + value = reply->str; + std::cout << "Execut command [ RPOP " << key << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::HSet(const std::string &key, const std::string &hkey, const std::string &value) { + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "HSET %s %s %s", key.c_str(), hkey.c_str(), value.c_str()); + if (reply == nullptr ) { + std::cout << "Execut command [ HSet " << key << " " << hkey <<" " << value << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_INTEGER) { + std::cout << "Execut command [ HSet " << key << " " << hkey << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + std::cout << "Execut command [ HSet " << key << " " << hkey << " " << value << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::HSet(const char* key, const char* hkey, const char* hvalue, size_t hvaluelen) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + const char* argv[4]; + size_t argvlen[4]; + argv[0] = "HSET"; + argvlen[0] = 4; + argv[1] = key; + argvlen[1] = strlen(key); + argv[2] = hkey; + argvlen[2] = strlen(hkey); + argv[3] = hvalue; + argvlen[3] = hvaluelen; + + auto reply = (redisReply*)redisCommandArgv(connect, 4, argv, argvlen); + if (reply == nullptr ) { + std::cout << "Execut command [ HSet " << key << " " << hkey << " " << hvalue << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_INTEGER) { + std::cout << "Execut command [ HSet " << key << " " << hkey << " " << hvalue << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + std::cout << "Execut command [ HSet " << key << " " << hkey << " " << hvalue << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +std::string RedisMgr::HGet(const std::string &key, const std::string &hkey) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return ""; + } + const char* argv[3]; + size_t argvlen[3]; + argv[0] = "HGET"; + argvlen[0] = 4; + argv[1] = key.c_str(); + argvlen[1] = key.length(); + argv[2] = hkey.c_str(); + argvlen[2] = hkey.length(); + + auto reply = (redisReply*)redisCommandArgv(connect, 3, argv, argvlen); + if (reply == nullptr ) { + std::cout << "Execut command [ HGet " << key << " "<< hkey <<" ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return ""; + } + + if ( reply->type == REDIS_REPLY_NIL) { + freeReplyObject(reply); + std::cout << "Execut command [ HGet " << key << " " << hkey << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return ""; + } + + std::string value = reply->str; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + std::cout << "Execut command [ HGet " << key << " " << hkey << " ] success ! " << std::endl; + return value; +} + +bool RedisMgr::HDel(const std::string& key, const std::string& field) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + + Defer defer([&connect, this]() { + _con_pool->returnConnection(connect); + }); + + redisReply* reply = (redisReply*)redisCommand(connect, "HDEL %s %s", key.c_str(), field.c_str()); + if (reply == nullptr) { + std::cerr << "HDEL command failed" << std::endl; + return false; + } + + bool success = false; + if (reply->type == REDIS_REPLY_INTEGER) { + success = reply->integer > 0; + } + + freeReplyObject(reply); + return success; +} + +bool RedisMgr::Del(const std::string &key) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "DEL %s", key.c_str()); + if (reply == nullptr ) { + std::cout << "Execut command [ Del " << key << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if ( reply->type != REDIS_REPLY_INTEGER) { + std::cout << "Execut command [ Del " << key << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + std::cout << "Execut command [ Del " << key << " ] success ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + +bool RedisMgr::ExistsKey(const std::string &key) +{ + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + + auto reply = (redisReply*)redisCommand(connect, "exists %s", key.c_str()); + if (reply == nullptr ) { + std::cout << "Not Found [ Key " << key << " ] ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (reply->type != REDIS_REPLY_INTEGER || reply->integer == 0) { + std::cout << "Not Found [ Key " << key << " ] ! " << std::endl; + _con_pool->returnConnection(connect); + freeReplyObject(reply); + return false; + } + std::cout << " Found [ Key " << key << " ] exists ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return true; +} + + +std::string RedisMgr::acquireLock(const std::string& lockName, + int lockTimeout, int acquireTimeout) { + + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return ""; + } + + Defer defer([&connect, this]() { + _con_pool->returnConnection(connect); + }); + + return DistLock::Inst().acquireLock(connect, lockName, lockTimeout, acquireTimeout); +} + +bool RedisMgr::releaseLock(const std::string& lockName, + const std::string& identifier) { + if (identifier.empty()) { + return true; + } + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + + + Defer defer([&connect, this]() { + _con_pool->returnConnection(connect); + }); + + return DistLock::Inst().releaseLock(connect, lockName, identifier); +} + +void RedisMgr::IncreaseCount(std::string server_name) +{ + auto lock_key = LOCK_COUNT; + auto identifier = RedisMgr::GetInstance()->acquireLock(lock_key, LOCK_TIME_OUT, ACQUIRE_TIME_OUT); + //defer + Defer defer2([this, identifier, lock_key]() { + RedisMgr::GetInstance()->releaseLock(lock_key, identifier); + }); + + //¼ + auto rd_res = RedisMgr::GetInstance()->HGet(LOGIN_COUNT, server_name); + int count = 0; + if (!rd_res.empty()) { + count = std::stoi(rd_res); + } + + count++; + auto count_str = std::to_string(count); + RedisMgr::GetInstance()->HSet(LOGIN_COUNT, server_name, count_str); +} + +void RedisMgr::DecreaseCount(std::string server_name) +{ + auto lock_key = LOCK_COUNT; + auto identifier = RedisMgr::GetInstance()->acquireLock(lock_key, LOCK_TIME_OUT, ACQUIRE_TIME_OUT); + //defer + Defer defer2([this, identifier, lock_key]() { + RedisMgr::GetInstance()->releaseLock(lock_key, identifier); + }); + + //¼ + auto rd_res = RedisMgr::GetInstance()->HGet(LOGIN_COUNT, server_name); + int count = 0; + if (!rd_res.empty()) { + count = std::stoi(rd_res); + if (count > 0) { + count--; + } + + } + + auto count_str = std::to_string(count); + RedisMgr::GetInstance()->HSet(LOGIN_COUNT, server_name, count_str); +} + + +void RedisMgr::InitCount(std::string server_name) { + auto lock_key = LOCK_COUNT; + auto identifier = RedisMgr::GetInstance()->acquireLock(lock_key, LOCK_TIME_OUT, ACQUIRE_TIME_OUT); + //defer + Defer defer2([this, identifier, lock_key]() { + RedisMgr::GetInstance()->releaseLock(lock_key, identifier); + }); + + RedisMgr::GetInstance()->HSet(LOGIN_COUNT, server_name, "0"); +} + +void RedisMgr::DelCount(std::string server_name) { + auto lock_key = LOCK_COUNT; + auto identifier = RedisMgr::GetInstance()->acquireLock(lock_key, LOCK_TIME_OUT, ACQUIRE_TIME_OUT); + //defer + Defer defer2([this, identifier, lock_key]() { + RedisMgr::GetInstance()->releaseLock(lock_key, identifier); + }); + + RedisMgr::GetInstance()->HDel(LOGIN_COUNT, server_name); +} + +bool RedisMgr::SetFileInfo(const std::string& name, std::shared_ptr file_info) +{ + Json::Reader reader; + Json::Value root; + root["file_path_str"] = file_info->_file_path_str; + root["name"] = file_info->_name; + root["seq"] = file_info->_seq; + root["total_size"] = std::to_string(file_info->_total_size); + root["trans_size"] = std::to_string(file_info->_trans_size); + auto file_info_str = root.toStyledString(); + auto redis_key = "file_upload_" + name; + bool success = SetExp(redis_key, file_info_str, 3600); + return success; +} + +bool RedisMgr::SetDownLoadInfo(const std::string& name, std::shared_ptr file_info) { + Json::Reader reader; + Json::Value root; + root["file_path_str"] = file_info->_file_path_str; + root["name"] = file_info->_name; + root["seq"] = file_info->_seq; + root["total_size"] = std::to_string(file_info->_total_size); + root["trans_size"] = std::to_string(file_info->_trans_size); + auto file_info_str = root.toStyledString(); + auto redis_key = "file_download_" + name; + bool success = SetExp(redis_key, file_info_str, 3600); + return success; +} + +bool RedisMgr::DelDownLoadInfo(const std::string& name) { + auto redis_key = "file_download_" + name; + return Del(redis_key); +} + +std::shared_ptr RedisMgr::GetFileInfo(const std::string& name) { + auto redis_key = "file_upload_" + name; + std::string file_info_str = ""; + + // Redis ȡ + bool success = Get(redis_key, file_info_str); + if (!success || file_info_str.empty()) { + return nullptr; + } + + // JSON + Json::Reader reader; + Json::Value root; + if (!reader.parse(file_info_str, root)) { + std::cout << "Failed to parse file info JSON for name: " << name << std::endl; + return nullptr; + } + + // FileInfo + auto file_info = std::make_shared(); + try { + file_info->_file_path_str = root["file_path_str"].asString(); + file_info->_name = root["name"].asString(); + file_info->_seq = root["seq"].asInt(); + file_info->_total_size = std::stoll(root["total_size"].asString()); + file_info->_trans_size = std::stoll(root["trans_size"].asString()); + } + catch (const std::exception& e) { + std::cout << "Error parsing file info fields for name " << name << ": " << e.what() << std::endl; + return nullptr; + } + + return file_info; +} + + +std::shared_ptr RedisMgr::GetDownloadInfo(const std::string& name) { + auto redis_key = "file_download_" + name; + std::string file_info_str = ""; + + // Redis ȡ + bool success = Get(redis_key, file_info_str); + if (!success || file_info_str.empty()) { + return nullptr; + } + + // JSON + Json::Reader reader; + Json::Value root; + if (!reader.parse(file_info_str, root)) { + std::cout << "Failed to parse file info JSON for name: " << name << std::endl; + return nullptr; + } + + // FileInfo + auto file_info = std::make_shared(); + try { + file_info->_file_path_str = root["file_path_str"].asString(); + file_info->_name = root["name"].asString(); + file_info->_seq = root["seq"].asInt(); + file_info->_total_size = std::stoll(root["total_size"].asString()); + file_info->_trans_size = std::stoll(root["trans_size"].asString()); + } + catch (const std::exception& e) { + std::cout << "Error parsing file info fields for name " << name << ": " << e.what() << std::endl; + return nullptr; + } + + return file_info; +} \ No newline at end of file diff --git a/server/ResourceServer/RedisMgr.h b/server/ResourceServer/RedisMgr.h new file mode 100644 index 0000000..4f6cc32 --- /dev/null +++ b/server/ResourceServer/RedisMgr.h @@ -0,0 +1,312 @@ +#pragma once +#include "const.h" +#include "hiredis.h" +#include +#include +#include +#include "Singleton.h" +#include +#include "FileInfo.h" + +class RedisConPool { +public: + RedisConPool(size_t poolSize, const char* host, int port, const char* pwd) + : poolSize_(poolSize), host_(host), port_(port), b_stop_(false), pwd_(pwd), counter_(0), fail_count_(0){ + for (size_t i = 0; i < poolSize_; ++i) { + auto* context = redisConnect(host, port); + if (context == nullptr || context->err != 0) { + if (context != nullptr) { + redisFree(context); + } + continue; + } + + auto reply = (redisReply*)redisCommand(context, "AUTH %s", pwd); + if (reply->type == REDIS_REPLY_ERROR) { + std::cout << "֤ʧ" << std::endl; + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + continue; + } + + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + std::cout << "֤ɹ" << std::endl; + connections_.push(context); + } + + check_thread_ = std::thread([this]() { + while (!b_stop_) { + counter_++; + if (counter_ >= 60) { + checkThreadPro(); + counter_ = 0; + } + + std::this_thread::sleep_for(std::chrono::seconds(1)); // ÿ 30 뷢һ PING + } + }); + + } + + ~RedisConPool() { + + } + + void ClearConnections() { + std::lock_guard lock(mutex_); + while (!connections_.empty()) { + auto* context = connections_.front(); + redisFree(context); + connections_.pop(); + } + } + + redisContext* getConnection() { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { + if (b_stop_) { + return true; + } + return !connections_.empty(); + }); + //ֱֹͣӷؿָ + if (b_stop_) { + return nullptr; + } + auto* context = connections_.front(); + connections_.pop(); + return context; + } + + redisContext* getConNonBlock() { + std::unique_lock lock(mutex_); + if (b_stop_) { + return nullptr; + } + + if (connections_.empty()) { + return nullptr; + } + + auto* context = connections_.front(); + connections_.pop(); + return context; + } + + void returnConnection(redisContext* context) { + std::lock_guard lock(mutex_); + if (b_stop_) { + return; + } + connections_.push(context); + cond_.notify_one(); + } + + void Close() { + b_stop_ = true; + cond_.notify_all(); + check_thread_.join(); + } + +private: + + bool reconnect() { + auto context = redisConnect(host_, port_); + if (context == nullptr || context->err != 0) { + if (context != nullptr) { + redisFree(context); + } + return false; + } + + auto reply = (redisReply*)redisCommand(context, "AUTH %s", pwd_); + if (reply->type == REDIS_REPLY_ERROR) { + std::cout << "֤ʧ" << std::endl; + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + redisFree(context); + return false; + } + + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + std::cout << "֤ɹ" << std::endl; + returnConnection(context); + return true; + } + + void checkThreadPro() { + size_t pool_size; + { + // õǰ + std::lock_guard lock(mutex_); + pool_size = connections_.size(); + } + + + for (int i = 0; i < pool_size && !b_stop_; ++i) { + redisContext* ctx = nullptr; + // 1) ȡһ() + bool bsuccess = false; + auto * context = getConNonBlock(); + if (context == nullptr) { + break; + } + + redisReply* reply = nullptr; + try { + reply = (redisReply*)redisCommand(context, "PING"); + // 2. ȿײ I/OЭûд + if (context->err) { + std::cout << "Connection error: " << context->err << std::endl; + if (reply) { + freeReplyObject(reply); + } + redisFree(context); + fail_count_++; + continue; + } + + // 3. ٿ Redis صDz ERROR + if (!reply || reply->type == REDIS_REPLY_ERROR) { + std::cout << "reply is null, redis ping failed: " << std::endl; + if (reply) { + freeReplyObject(reply); + } + redisFree(context); + fail_count_++; + continue; + } + // 4. û⣬򻹻ȥ + //std::cout << "connection alive" << std::endl; + freeReplyObject(reply); + returnConnection(context); + } + catch (std::exception& exp) { + if (reply) { + freeReplyObject(reply); + } + + redisFree(context); + fail_count_++; + } + + } + + //ִ + while (fail_count_ > 0) { + auto res = reconnect(); + if(res){ + fail_count_--; + } + else { + //´ + break; + } + } + } + + + void checkThread() { + std::lock_guard lock(mutex_); + if (b_stop_) { + return; + } + auto pool_size = connections_.size(); + for (int i = 0; i < pool_size && !b_stop_; i++) { + auto* context = connections_.front(); + connections_.pop(); + try { + auto reply = (redisReply*)redisCommand(context, "PING"); + if (!reply) { + std::cout << "reply is null, redis ping failed: " << std::endl; + connections_.push(context); + continue; + } + freeReplyObject(reply); + connections_.push(context); + } + catch(std::exception& exp){ + std::cout << "Error keeping connection alive: " << exp.what() << std::endl; + redisFree(context); + context = redisConnect(host_, port_); + if (context == nullptr || context->err != 0) { + if (context != nullptr) { + redisFree(context); + } + continue; + } + + auto reply = (redisReply*)redisCommand(context, "AUTH %s", pwd_); + if (reply->type == REDIS_REPLY_ERROR) { + std::cout << "֤ʧ" << std::endl; + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + continue; + } + + //ִгɹ ͷredisCommandִк󷵻صredisReplyռõڴ + freeReplyObject(reply); + std::cout << "֤ɹ" << std::endl; + connections_.push(context); + } + } + } + std::atomic b_stop_; + size_t poolSize_; + const char* host_; + const char* pwd_; + int port_; + std::queue connections_; + std::atomic fail_count_; + std::mutex mutex_; + std::condition_variable cond_; + std::thread check_thread_; + int counter_; +}; + +class RedisMgr: public Singleton, + public std::enable_shared_from_this +{ + friend class Singleton; +public: + ~RedisMgr(); + bool Get(const std::string &key, std::string& value); + bool Set(const std::string &key, const std::string &value); + bool SetExp(const std::string& key, const std::string& value, int expire_seconds); + bool LPush(const std::string &key, const std::string &value); + bool LPop(const std::string &key, std::string& value); + bool RPush(const std::string& key, const std::string& value); + bool RPop(const std::string& key, std::string& value); + bool HSet(const std::string &key, const std::string &hkey, const std::string &value); + bool HSet(const char* key, const char* hkey, const char* hvalue, size_t hvaluelen); + std::string HGet(const std::string &key, const std::string &hkey); + bool HDel(const std::string& key, const std::string& field); + bool Del(const std::string &key); + bool ExistsKey(const std::string &key); + void Close() { + _con_pool->Close(); + _con_pool->ClearConnections(); + } + + std::string acquireLock(const std::string& lockName, + int lockTimeout, int acquireTimeout); + + bool releaseLock(const std::string& lockName, + const std::string& identifier); + + void IncreaseCount(std::string server_name); + void DecreaseCount(std::string server_name); + void InitCount(std::string server_name); + void DelCount(std::string server_name); + bool SetFileInfo(const std::string& name, std::shared_ptr); + std::shared_ptr GetFileInfo(const std::string& name); + std::shared_ptr GetDownloadInfo(const std::string& name); + bool SetDownLoadInfo(const std::string& name, std::shared_ptr); + bool DelDownLoadInfo(const std::string& name); +private: + RedisMgr(); + unique_ptr _con_pool; +}; + diff --git a/server/ResourceServer/ResourceServer.cpp b/server/ResourceServer/ResourceServer.cpp new file mode 100644 index 0000000..4f6c166 --- /dev/null +++ b/server/ResourceServer/ResourceServer.cpp @@ -0,0 +1,41 @@ +#include "LogicSystem.h" +#include +#include +#include +#include "AsioIOServicePool.h" +#include "CServer.h" +#include "ConfigMgr.h" +#include + +using namespace std; +bool bstop = false; +std::condition_variable cond_quit; +std::mutex mutex_quit; + +int main() +{ + auto& cfg = ConfigMgr::Inst(); + auto server_name = cfg["SelfServer"]["Name"]; + + std::shared_ptr pool = nullptr; + try { + pool = AsioIOServicePool::GetInstance(); + + boost::asio::io_context io_context; + boost::asio::signal_set signals(io_context, SIGINT, SIGTERM); + signals.async_wait([&io_context, pool](auto, auto) { + io_context.stop(); + pool->Stop(); + }); + auto port_str = cfg["SelfServer"]["Port"]; + CServer s(io_context, atoi(port_str.c_str())); + io_context.run(); + } + catch (std::exception& e) { + if (pool) { + pool->Stop(); + } + std::cerr << "Exception: " << e.what() << endl; + } + +} diff --git a/server/ResourceServer/ResourceServer.sln b/server/ResourceServer/ResourceServer.sln new file mode 100644 index 0000000..209e145 --- /dev/null +++ b/server/ResourceServer/ResourceServer.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.34114.132 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ResourceServer", "ResourceServer.vcxproj", "{175729EC-A4DC-44FC-96E7-6B8B467E70AF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Debug|x64.ActiveCfg = Debug|x64 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Debug|x64.Build.0 = Debug|x64 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Debug|x86.ActiveCfg = Debug|Win32 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Debug|x86.Build.0 = Debug|Win32 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Release|x64.ActiveCfg = Release|x64 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Release|x64.Build.0 = Release|x64 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Release|x86.ActiveCfg = Release|Win32 + {175729EC-A4DC-44FC-96E7-6B8B467E70AF}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3F05EFA0-3045-4AC5-9369-D7EDC0DCD231} + EndGlobalSection +EndGlobal diff --git a/server/ResourceServer/ResourceServer.vcxproj b/server/ResourceServer/ResourceServer.vcxproj new file mode 100644 index 0000000..14f4e97 --- /dev/null +++ b/server/ResourceServer/ResourceServer.vcxproj @@ -0,0 +1,195 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {175729ec-a4dc-44fc-96e7-6b8b467e70af} + ResourceServer + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/ResourceServer/ResourceServer.vcxproj.filters b/server/ResourceServer/ResourceServer.vcxproj.filters new file mode 100644 index 0000000..dd520b0 --- /dev/null +++ b/server/ResourceServer/ResourceServer.vcxproj.filters @@ -0,0 +1,151 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + + + \ No newline at end of file diff --git a/server/ResourceServer/ResourceServer.vcxproj.user b/server/ResourceServer/ResourceServer.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/server/ResourceServer/ResourceServer.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/server/ResourceServer/Singleton.h b/server/ResourceServer/Singleton.h new file mode 100644 index 0000000..281fd18 --- /dev/null +++ b/server/ResourceServer/Singleton.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +using namespace std; +template +class Singleton { +protected: + Singleton() = default; + Singleton(const Singleton&) = delete; + Singleton& operator=(const Singleton& st) = delete; + + static std::shared_ptr _instance; +public: + static std::shared_ptr GetInstance() { + static std::once_flag s_flag; + std::call_once(s_flag, [&]() { + _instance = shared_ptr(new T); + }); + + return _instance; + } + void PrintAddress() { + std::cout << _instance.get() << endl; + } + ~Singleton() { + std::cout << "this is singleton destruct" << std::endl; + } +}; + +template +std::shared_ptr Singleton::_instance = nullptr; diff --git a/server/ResourceServer/UserMgr.cpp b/server/ResourceServer/UserMgr.cpp new file mode 100644 index 0000000..2224bc0 --- /dev/null +++ b/server/ResourceServer/UserMgr.cpp @@ -0,0 +1,45 @@ +#include "UserMgr.h" +#include "CSession.h" + + +UserMgr:: ~ UserMgr(){ + _uid_to_session.clear(); +} + + +std::shared_ptr UserMgr::GetSession(int uid) +{ + std::lock_guard lock(_session_mtx); + auto iter = _uid_to_session.find(uid); + if (iter == _uid_to_session.end()) { + return nullptr; + } + + return iter->second; +} + +void UserMgr::SetUserSession(int uid, std::shared_ptr session) +{ + std::lock_guard lock(_session_mtx); + _uid_to_session[uid] = session; +} + +void UserMgr::RmvUserSession(int uid) +{ + auto uid_str = std::to_string(uid); + //Ϊٴε¼Իɱɾkeyעkey + // п¼ɾkeyҲkey + + //RedisMgr::GetInstance()->Del(USERIPPREFIX + uid_str); + + { + std::lock_guard lock(_session_mtx); + _uid_to_session.erase(uid); + } + +} + +UserMgr::UserMgr() +{ + +} diff --git a/server/ResourceServer/UserMgr.h b/server/ResourceServer/UserMgr.h new file mode 100644 index 0000000..1fd8a1f --- /dev/null +++ b/server/ResourceServer/UserMgr.h @@ -0,0 +1,21 @@ +#pragma once +#include "Singleton.h" +#include +#include +#include + +class CSession; +class UserMgr: public Singleton +{ + friend class Singleton; +public: + ~UserMgr(); + std::shared_ptr GetSession(int uid); + void SetUserSession(int uid, std::shared_ptr session); + void RmvUserSession(int uid); +private: + UserMgr(); + std::mutex _session_mtx; + std::unordered_map> _uid_to_session; +}; + diff --git a/server/ResourceServer/base64.cpp b/server/ResourceServer/base64.cpp new file mode 100644 index 0000000..843719e --- /dev/null +++ b/server/ResourceServer/base64.cpp @@ -0,0 +1,282 @@ +/* + base64.cpp and base64.h + + base64 encoding and decoding with C++. + More information at + https://renenyffenegger.ch/notes/development/Base64/Encoding-and-decoding-base-64-with-cpp + + Version: 2.rc.09 (release candidate) + + Copyright (C) 2004-2017, 2020-2022 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +#include "base64.h" + +#include +#include + + // + // Depending on the url parameter in base64_chars, one of + // two sets of base64 characters needs to be chosen. + // They differ in their last two characters. + // +static const char* base64_chars[2] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "+/", + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" + "-_"}; + +static unsigned int pos_of_char(const unsigned char chr) { + // + // Return the position of chr within base64_encode() + // + + if (chr >= 'A' && chr <= 'Z') return chr - 'A'; + else if (chr >= 'a' && chr <= 'z') return chr - 'a' + ('Z' - 'A') + 1; + else if (chr >= '0' && chr <= '9') return chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2; + else if (chr == '+' || chr == '-') return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( + else if (chr == '/' || chr == '_') return 63; // Ditto for '/' and '_' + else + // + // 2020-10-23: Throw std::exception rather than const char* + //(Pablo Martin-Gomez, https://github.com/Bouska) + // + throw std::runtime_error("Input is not valid base64-encoded data."); +} + +static std::string insert_linebreaks(std::string str, size_t distance) { + // + // Provided by https://github.com/JomaCorpFX, adapted by me. + // + if (!str.length()) { + return ""; + } + + size_t pos = distance; + + while (pos < str.size()) { + str.insert(pos, "\n"); + pos += distance + 1; + } + + return str; +} + +template +static std::string encode_with_line_breaks(String s) { + return insert_linebreaks(base64_encode(s, false), line_length); +} + +template +static std::string encode_pem(String s) { + return encode_with_line_breaks(s); +} + +template +static std::string encode_mime(String s) { + return encode_with_line_breaks(s); +} + +template +static std::string encode(String s, bool url) { + return base64_encode(reinterpret_cast(s.data()), s.length(), url); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, size_t in_len, bool url) { + + size_t len_encoded = (in_len +2) / 3 * 4; + + unsigned char trailing_char = url ? '.' : '='; + + // + // Choose set of base64 characters. They differ + // for the last two positions, depending on the url + // parameter. + // A bool (as is the parameter url) is guaranteed + // to evaluate to either 0 or 1 in C++ therefore, + // the correct character set is chosen by subscripting + // base64_chars with url. + // + const char* base64_chars_ = base64_chars[url]; + + std::string ret; + ret.reserve(len_encoded); + + unsigned int pos = 0; + + while (pos < in_len) { + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0xfc) >> 2]); + + if (pos+1 < in_len) { + ret.push_back(base64_chars_[((bytes_to_encode[pos + 0] & 0x03) << 4) + ((bytes_to_encode[pos + 1] & 0xf0) >> 4)]); + + if (pos+2 < in_len) { + ret.push_back(base64_chars_[((bytes_to_encode[pos + 1] & 0x0f) << 2) + ((bytes_to_encode[pos + 2] & 0xc0) >> 6)]); + ret.push_back(base64_chars_[ bytes_to_encode[pos + 2] & 0x3f]); + } + else { + ret.push_back(base64_chars_[(bytes_to_encode[pos + 1] & 0x0f) << 2]); + ret.push_back(trailing_char); + } + } + else { + + ret.push_back(base64_chars_[(bytes_to_encode[pos + 0] & 0x03) << 4]); + ret.push_back(trailing_char); + ret.push_back(trailing_char); + } + + pos += 3; + } + + + return ret; +} + +template +static std::string decode(String const& encoded_string, bool remove_linebreaks) { + // + // decode(…) is templated so that it can be used with String = const std::string& + // or std::string_view (requires at least C++17) + // + + if (encoded_string.empty()) return std::string(); + + if (remove_linebreaks) { + + std::string copy(encoded_string); + + copy.erase(std::remove(copy.begin(), copy.end(), '\n'), copy.end()); + + return base64_decode(copy, false); + } + + size_t length_of_string = encoded_string.length(); + size_t pos = 0; + + // + // The approximate length (bytes) of the decoded string might be one or + // two bytes smaller, depending on the amount of trailing equal signs + // in the encoded string. This approximation is needed to reserve + // enough space in the string to be returned. + // + size_t approx_length_of_decoded_string = length_of_string / 4 * 3; + std::string ret; + ret.reserve(approx_length_of_decoded_string); + + while (pos < length_of_string) { + // + // Iterate over encoded input string in chunks. The size of all + // chunks except the last one is 4 bytes. + // + // The last chunk might be padded with equal signs or dots + // in order to make it 4 bytes in size as well, but this + // is not required as per RFC 2045. + // + // All chunks except the last one produce three output bytes. + // + // The last chunk produces at least one and up to three bytes. + // + + size_t pos_of_char_1 = pos_of_char(encoded_string.at(pos+1) ); + + // + // Emit the first output byte that is produced in each chunk: + // + ret.push_back(static_cast( ( (pos_of_char(encoded_string.at(pos+0)) ) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4))); + + if ( ( pos + 2 < length_of_string ) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045) + encoded_string.at(pos+2) != '=' && + encoded_string.at(pos+2) != '.' // accept URL-safe base 64 strings, too, so check for '.' also. + ) + { + // + // Emit a chunk's second byte (which might not be produced in the last chunk). + // + unsigned int pos_of_char_2 = pos_of_char(encoded_string.at(pos+2) ); + ret.push_back(static_cast( (( pos_of_char_1 & 0x0f) << 4) + (( pos_of_char_2 & 0x3c) >> 2))); + + if ( ( pos + 3 < length_of_string ) && + encoded_string.at(pos+3) != '=' && + encoded_string.at(pos+3) != '.' + ) + { + // + // Emit a chunk's third byte (which might not be produced in the last chunk). + // + ret.push_back(static_cast( ( (pos_of_char_2 & 0x03 ) << 6 ) + pos_of_char(encoded_string.at(pos+3)) )); + } + } + + pos += 4; + } + + return ret; +} + +std::string base64_decode(std::string const& s, bool remove_linebreaks) { + return decode(s, remove_linebreaks); +} + +std::string base64_encode(std::string const& s, bool url) { + return encode(s, url); +} + +std::string base64_encode_pem (std::string const& s) { + return encode_pem(s); +} + +std::string base64_encode_mime(std::string const& s) { + return encode_mime(s); +} + +#if __cplusplus >= 201703L +// +// Interface with std::string_view rather than const std::string& +// Requires C++17 +// Provided by Yannic Bonenberger (https://github.com/Yannic) +// + +std::string base64_encode(std::string_view s, bool url) { + return encode(s, url); +} + +std::string base64_encode_pem(std::string_view s) { + return encode_pem(s); +} + +std::string base64_encode_mime(std::string_view s) { + return encode_mime(s); +} + +std::string base64_decode(std::string_view s, bool remove_linebreaks) { + return decode(s, remove_linebreaks); +} + +#endif // __cplusplus >= 201703L diff --git a/server/ResourceServer/base64.h b/server/ResourceServer/base64.h new file mode 100644 index 0000000..4860d63 --- /dev/null +++ b/server/ResourceServer/base64.h @@ -0,0 +1,35 @@ +// +// base64 encoding and decoding with C++. +// Version: 2.rc.09 (release candidate) +// + +#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A +#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A + +#include + +#if __cplusplus >= 201703L +#include +#endif // __cplusplus >= 201703L + +std::string base64_encode (std::string const& s, bool url = false); +std::string base64_encode_pem (std::string const& s); +std::string base64_encode_mime(std::string const& s); + +std::string base64_decode(std::string const& s, bool remove_linebreaks = false); +std::string base64_encode(unsigned char const*, size_t len, bool url = false); + +#if __cplusplus >= 201703L +// +// Interface with std::string_view rather than const std::string& +// Requires C++17 +// Provided by Yannic Bonenberger (https://github.com/Yannic) +// +std::string base64_encode (std::string_view s, bool url = false); +std::string base64_encode_pem (std::string_view s); +std::string base64_encode_mime(std::string_view s); + +std::string base64_decode(std::string_view s, bool remove_linebreaks = false); +#endif // __cplusplus >= 201703L + +#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ diff --git a/server/ResourceServer/const.h b/server/ResourceServer/const.h new file mode 100644 index 0000000..e681b19 --- /dev/null +++ b/server/ResourceServer/const.h @@ -0,0 +1,116 @@ +#pragma once +#include + + +enum ErrorCodes { + Success = 0, + Error_Json = 1001, //Json + RPCFailed = 1002, //RPC + VarifyExpired = 1003, //֤ + VarifyCodeErr = 1004, //֤ + UserExist = 1005, //ûѾ + PasswdErr = 1006, // + EmailNotMatch = 1007, //䲻ƥ + PasswdUpFailed = 1008, //ʧ + PasswdInvalid = 1009, //ʧ + TokenInvalid = 1010, //TokenʧЧ + UidInvalid = 1011, //uidЧ + FileNotExists = 1012, //ļ + FileSaveRedisFailed = 1013, //ļ洢redisʧ + CreateFilePathFailed = 1014, //ļ·ʧ + FileWritePermissionFailed = 1015, //ļдȨ޲ + FileReadPermissionFailed = 1016, //ļȨ޲ + FileSeqInvalid = 1017, //ļ + FileOffsetInvalid = 1018, //ļƫ + FileReadFailed = 1019, //ļȡʧ + RedisReadErr = 1020, //redisȡʧ + ServerIpErr = 1021, //server ip + MsgIdErr = 1022, //Ϣid +}; + +enum MsgStatus { + UN_READ = 0, //Էδ + SEND_FAILED = 1, //ʧ + READED = 2, //ԷѶ + UN_UPLOAD = 3 //δϴ +}; + +// Defer +class Defer { +public: + // һlambdaʽߺָ + Defer(std::function func) : func_(func) {} + + // ִдĺ + ~Defer() { + func_(); + } + +private: + std::function func_; +}; + +#define MAX_LENGTH 1024*50 +//ͷܳ +#define HEAD_TOTAL_LEN 6 +//ͷid +#define HEAD_ID_LEN 2 +//ͷݳ +#define HEAD_DATA_LEN 4 +#define MAX_RECVQUE 2000000 +#define MAX_SENDQUE 2000000 + +//4߼ +#define LOGIC_WORKER_COUNT 4 +//4ļ +#define FILE_WORKER_COUNT 4 + +//4ع +#define DOWN_LOAD_WORKER_COUNT 4 + + +enum MSG_IDS { + ID_TEST_MSG_REQ = 1001, //Ϣ + ID_TEST_MSG_RSP = 1002, //Ϣذ + ID_UPLOAD_FILE_REQ = 1003, //ļ + ID_UPLOAD_FILE_RSP = 1004, //ļظ + ID_SYNC_FILE_REQ = 1005, //ͬļϢ + ID_SYNC_FILE_RSP = 1006, //ͬļظظ + ID_UPLOAD_HEAD_ICON_REQ = 1031, //ϴͷ + ID_UPLOAD_HEAD_ICON_RSP = 1032, //ϴͷظ + ID_DOWN_LOAD_FILE_REQ = 1033, //ļ + ID_DOWN_LOAD_FILE_RSP = 1034, //ļظ + + ID_IMG_CHAT_UPLOAD_REQ = 1037, //ϴͼƬԴ + ID_IMG_CHAT_UPLOAD_RSP = 1038, //ϴͼƬԴظ + ID_NOTIFY_IMG_CHAT_MSG_REQ = 1039, //֪ͨûͼƬϢ + ID_FILE_INFO_SYNC_REQ = 1041, //ļϢͬ + ID_FILE_INFO_SYNC_RSP = 1042, //ļϢͬظ + ID_IMG_CHAT_CONTINUE_UPLOAD_REQ = 1043, //ͼƬԴ + ID_IMG_CHAT_CONTINUE_UPLOAD_RSP = 1044, //ͼƬԴظ + ID_IMG_CHAT_DOWN_INFO_SYNC_REQ = 1045, //ȡͼƬصͬϢ + ID_IMG_CHAT_DOWN_INFO_SYNC_RSP = 1046, //ȡͼƬصͬϢذ + ID_IMG_CHAT_DOWN_REQ = 1047, //ͼƬ + ID_IMG_CHAT_DOWN_RSP = 1048 //ͼƬػظ +}; + +#define USERIPPREFIX "uip_" +#define USERTOKENPREFIX "utoken_" +#define IPCOUNTPREFIX "ipcount_" +#define USER_BASE_INFO "ubaseinfo_" +#define LOGIN_COUNT "logincount" +#define NAME_INFO "nameinfo_" + +#define LOCK_PREFIX "lock_" +#define USER_SESSION_PREFIX "usession_" +#define LOCK_COUNT "lockcount" + +//ֲʽijʱ +#define LOCK_TIME_OUT 10 +//ֲʽʱ +#define ACQUIRE_TIME_OUT 5 + +//ļĴС +#define MAX_FILE_LEN 1024*32 + + diff --git a/server/ResourceServer/data.h b/server/ResourceServer/data.h new file mode 100644 index 0000000..97246df --- /dev/null +++ b/server/ResourceServer/data.h @@ -0,0 +1,59 @@ +#pragma once +#include +#include +struct UserInfo { + UserInfo():name(""), pwd(""),uid(0),email(""),nick(""),desc(""),sex(0), icon(""), back("") {} + std::string name; + std::string pwd; + int uid; + std::string email; + std::string nick; + std::string desc; + int sex; + std::string icon; + std::string back; +}; + +struct ApplyInfo { + ApplyInfo(int uid, std::string name, std::string desc, + std::string icon, std::string nick, int sex, int status) + :_uid(uid),_name(name),_desc(desc), + _icon(icon),_nick(nick),_sex(sex),_status(status){} + + int _uid; + std::string _name; + std::string _desc; + std::string _icon; + std::string _nick; + int _sex; + int _status; +}; + +//߳Ϣ +struct ChatThreadInfo { + int _thread_id; + std::string _type; // "private" or "group" + int _user1_id; // ˽ʱӦ private_chat.user1_idȺʱΪ 0 + int _user2_id; // ˽ʱӦ private_chat.user2_idȺʱΪ 0 +}; + +//ϢϢ +struct ChatMessage { + int message_id; + int thread_id; + int sender_id; + int recv_id; + std::string unique_id; + std::string content; + std::string chat_time; + int status; + int msg_type; +}; + +// ѯṹnext_cursorֶ +struct PageResult { + std::vector messages; + bool load_more; + int next_cursor; // ҳһmessage_id´βѯ +}; + diff --git a/server/ResourceServer/message.grpc.pb.cc b/server/ResourceServer/message.grpc.pb.cc new file mode 100644 index 0000000..6014ed6 --- /dev/null +++ b/server/ResourceServer/message.grpc.pb.cc @@ -0,0 +1,502 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: message.proto + +#include "message.pb.h" +#include "message.grpc.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +namespace message { + +static const char* VarifyService_method_names[] = { + "/message.VarifyService/GetVarifyCode", +}; + +std::unique_ptr< VarifyService::Stub> VarifyService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< VarifyService::Stub> stub(new VarifyService::Stub(channel)); + return stub; +} + +VarifyService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel), rpcmethod_GetVarifyCode_(VarifyService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status VarifyService::Stub::GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::message::GetVarifyRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::GetVarifyReq, ::message::GetVarifyRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetVarifyCode_, context, request, response); +} + +void VarifyService::Stub::experimental_async::GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::GetVarifyReq, ::message::GetVarifyRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetVarifyCode_, context, request, response, std::move(f)); +} + +void VarifyService::Stub::experimental_async::GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetVarifyCode_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>* VarifyService::Stub::PrepareAsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::GetVarifyRsp, ::message::GetVarifyReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetVarifyCode_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>* VarifyService::Stub::AsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncGetVarifyCodeRaw(context, request, cq); + result->StartCall(); + return result; +} + +VarifyService::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + VarifyService_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< VarifyService::Service, ::message::GetVarifyReq, ::message::GetVarifyRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](VarifyService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::GetVarifyReq* req, + ::message::GetVarifyRsp* resp) { + return service->GetVarifyCode(ctx, req, resp); + }, this))); +} + +VarifyService::Service::~Service() { +} + +::grpc::Status VarifyService::Service::GetVarifyCode(::grpc::ServerContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +static const char* StatusService_method_names[] = { + "/message.StatusService/GetChatServer", + "/message.StatusService/Login", +}; + +std::unique_ptr< StatusService::Stub> StatusService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< StatusService::Stub> stub(new StatusService::Stub(channel)); + return stub; +} + +StatusService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel), rpcmethod_GetChatServer_(StatusService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login_(StatusService_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status StatusService::Stub::GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::message::GetChatServerRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::GetChatServerReq, ::message::GetChatServerRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetChatServer_, context, request, response); +} + +void StatusService::Stub::experimental_async::GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::GetChatServerReq, ::message::GetChatServerRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetChatServer_, context, request, response, std::move(f)); +} + +void StatusService::Stub::experimental_async::GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetChatServer_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>* StatusService::Stub::PrepareAsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::GetChatServerRsp, ::message::GetChatServerReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetChatServer_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>* StatusService::Stub::AsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncGetChatServerRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status StatusService::Stub::Login(::grpc::ClientContext* context, const ::message::LoginReq& request, ::message::LoginRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::LoginReq, ::message::LoginRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Login_, context, request, response); +} + +void StatusService::Stub::experimental_async::Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::LoginReq, ::message::LoginRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Login_, context, request, response, std::move(f)); +} + +void StatusService::Stub::experimental_async::Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Login_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::LoginRsp>* StatusService::Stub::PrepareAsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::LoginRsp, ::message::LoginReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Login_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::LoginRsp>* StatusService::Stub::AsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncLoginRaw(context, request, cq); + result->StartCall(); + return result; +} + +StatusService::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + StatusService_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< StatusService::Service, ::message::GetChatServerReq, ::message::GetChatServerRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](StatusService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::GetChatServerReq* req, + ::message::GetChatServerRsp* resp) { + return service->GetChatServer(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + StatusService_method_names[1], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< StatusService::Service, ::message::LoginReq, ::message::LoginRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](StatusService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::LoginReq* req, + ::message::LoginRsp* resp) { + return service->Login(ctx, req, resp); + }, this))); +} + +StatusService::Service::~Service() { +} + +::grpc::Status StatusService::Service::GetChatServer(::grpc::ServerContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status StatusService::Service::Login(::grpc::ServerContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +static const char* ChatService_method_names[] = { + "/message.ChatService/NotifyAddFriend", + "/message.ChatService/RplyAddFriend", + "/message.ChatService/SendChatMsg", + "/message.ChatService/NotifyAuthFriend", + "/message.ChatService/NotifyTextChatMsg", + "/message.ChatService/NotifyKickUser", + "/message.ChatService/NotifyChatImgMsg", +}; + +std::unique_ptr< ChatService::Stub> ChatService::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + (void)options; + std::unique_ptr< ChatService::Stub> stub(new ChatService::Stub(channel)); + return stub; +} + +ChatService::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel), rpcmethod_NotifyAddFriend_(ChatService_method_names[0], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_RplyAddFriend_(ChatService_method_names[1], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SendChatMsg_(ChatService_method_names[2], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyAuthFriend_(ChatService_method_names[3], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyTextChatMsg_(ChatService_method_names[4], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyKickUser_(ChatService_method_names[5], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_NotifyChatImgMsg_(ChatService_method_names[6], ::grpc::internal::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status ChatService::Stub::NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::message::AddFriendRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::AddFriendReq, ::message::AddFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyAddFriend_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::AddFriendReq, ::message::AddFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyAddFriend_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyAddFriend_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>* ChatService::Stub::PrepareAsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::AddFriendRsp, ::message::AddFriendReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyAddFriend_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>* ChatService::Stub::AsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyAddFriendRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::message::RplyFriendRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::RplyFriendReq, ::message::RplyFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_RplyAddFriend_, context, request, response); +} + +void ChatService::Stub::experimental_async::RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::RplyFriendReq, ::message::RplyFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_RplyAddFriend_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_RplyAddFriend_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>* ChatService::Stub::PrepareAsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::RplyFriendRsp, ::message::RplyFriendReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_RplyAddFriend_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>* ChatService::Stub::AsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncRplyAddFriendRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::message::SendChatMsgRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::SendChatMsgReq, ::message::SendChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_SendChatMsg_, context, request, response); +} + +void ChatService::Stub::experimental_async::SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::SendChatMsgReq, ::message::SendChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SendChatMsg_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_SendChatMsg_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>* ChatService::Stub::PrepareAsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::SendChatMsgRsp, ::message::SendChatMsgReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_SendChatMsg_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>* ChatService::Stub::AsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncSendChatMsgRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::message::AuthFriendRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::AuthFriendReq, ::message::AuthFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyAuthFriend_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::AuthFriendReq, ::message::AuthFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyAuthFriend_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyAuthFriend_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>* ChatService::Stub::PrepareAsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::AuthFriendRsp, ::message::AuthFriendReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyAuthFriend_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>* ChatService::Stub::AsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyAuthFriendRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::message::TextChatMsgRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::TextChatMsgReq, ::message::TextChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyTextChatMsg_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::TextChatMsgReq, ::message::TextChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyTextChatMsg_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyTextChatMsg_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* ChatService::Stub::PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::TextChatMsgRsp, ::message::TextChatMsgReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyTextChatMsg_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* ChatService::Stub::AsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyTextChatMsgRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::message::KickUserRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::KickUserReq, ::message::KickUserRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyKickUser_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::KickUserReq, ::message::KickUserRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyKickUser_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyKickUser_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* ChatService::Stub::PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::KickUserRsp, ::message::KickUserReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyKickUser_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* ChatService::Stub::AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyKickUserRaw(context, request, cq); + result->StartCall(); + return result; +} + +::grpc::Status ChatService::Stub::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) { + return ::grpc::internal::BlockingUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_NotifyChatImgMsg_, context, request, response); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, std::move(f)); +} + +void ChatService::Stub::experimental_async::NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_NotifyChatImgMsg_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::message::NotifyChatImgRsp, ::message::NotifyChatImgReq, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_NotifyChatImgMsg_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* ChatService::Stub::AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncNotifyChatImgMsgRaw(context, request, cq); + result->StartCall(); + return result; +} + +ChatService::Service::Service() { + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[0], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::AddFriendReq, ::message::AddFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::AddFriendReq* req, + ::message::AddFriendRsp* resp) { + return service->NotifyAddFriend(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[1], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::RplyFriendReq, ::message::RplyFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::RplyFriendReq* req, + ::message::RplyFriendRsp* resp) { + return service->RplyAddFriend(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[2], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::SendChatMsgReq, ::message::SendChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::SendChatMsgReq* req, + ::message::SendChatMsgRsp* resp) { + return service->SendChatMsg(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[3], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::AuthFriendReq, ::message::AuthFriendRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::AuthFriendReq* req, + ::message::AuthFriendRsp* resp) { + return service->NotifyAuthFriend(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[4], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::TextChatMsgReq, ::message::TextChatMsgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::TextChatMsgReq* req, + ::message::TextChatMsgRsp* resp) { + return service->NotifyTextChatMsg(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[5], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::KickUserReq, ::message::KickUserRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::KickUserReq* req, + ::message::KickUserRsp* resp) { + return service->NotifyKickUser(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + ChatService_method_names[6], + ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< ChatService::Service, ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](ChatService::Service* service, + ::grpc::ServerContext* ctx, + const ::message::NotifyChatImgReq* req, + ::message::NotifyChatImgRsp* resp) { + return service->NotifyChatImgMsg(ctx, req, resp); + }, this))); +} + +ChatService::Service::~Service() { +} + +::grpc::Status ChatService::Service::NotifyAddFriend(::grpc::ServerContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::RplyAddFriend(::grpc::ServerContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::SendChatMsg(::grpc::ServerContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::NotifyAuthFriend(::grpc::ServerContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::NotifyTextChatMsg(::grpc::ServerContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::NotifyKickUser(::grpc::ServerContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status ChatService::Service::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace message + diff --git a/server/ResourceServer/message.grpc.pb.h b/server/ResourceServer/message.grpc.pb.h new file mode 100644 index 0000000..bd0efca --- /dev/null +++ b/server/ResourceServer/message.grpc.pb.h @@ -0,0 +1,2215 @@ +// Generated by the gRPC C++ plugin. +// If you make any local change, they will be lost. +// source: message.proto +#ifndef GRPC_message_2eproto__INCLUDED +#define GRPC_message_2eproto__INCLUDED + +#include "message.pb.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace message { + +class VarifyService final { + public: + static constexpr char const* service_full_name() { + return "message.VarifyService"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::message::GetVarifyRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>> AsyncGetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>>(AsyncGetVarifyCodeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>> PrepareAsyncGetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>>(PrepareAsyncGetVarifyCodeRaw(context, request, cq)); + } + class experimental_async_interface { + public: + virtual ~experimental_async_interface() {} + virtual void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef class experimental_async_interface async_interface; + #endif + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + async_interface* async() { return experimental_async(); } + #endif + virtual class experimental_async_interface* experimental_async() { return nullptr; } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>* AsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::GetVarifyRsp>* PrepareAsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::message::GetVarifyRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>> AsyncGetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>>(AsyncGetVarifyCodeRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>> PrepareAsyncGetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>>(PrepareAsyncGetVarifyCodeRaw(context, request, cq)); + } + class experimental_async final : + public StubInterface::experimental_async_interface { + public: + void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void GetVarifyCode(::grpc::ClientContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + private: + friend class Stub; + explicit experimental_async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class experimental_async_interface* experimental_async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class experimental_async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>* AsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::GetVarifyRsp>* PrepareAsyncGetVarifyCodeRaw(::grpc::ClientContext* context, const ::message::GetVarifyReq& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_GetVarifyCode_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status GetVarifyCode(::grpc::ServerContext* context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response); + }; + template + class WithAsyncMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_GetVarifyCode() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetVarifyCode(::grpc::ServerContext* context, ::message::GetVarifyReq* request, ::grpc::ServerAsyncResponseWriter< ::message::GetVarifyRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_GetVarifyCode AsyncService; + template + class ExperimentalWithCallbackMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_GetVarifyCode() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::message::GetVarifyReq, ::message::GetVarifyRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::GetVarifyReq* request, ::message::GetVarifyRsp* response) { return this->GetVarifyCode(context, request, response); }));} + void SetMessageAllocatorFor_GetVarifyCode( + ::grpc::experimental::MessageAllocator< ::message::GetVarifyReq, ::message::GetVarifyRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(0); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::GetVarifyReq, ::message::GetVarifyRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* GetVarifyCode( + ::grpc::CallbackServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* GetVarifyCode( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) + #endif + { return nullptr; } + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef ExperimentalWithCallbackMethod_GetVarifyCode CallbackService; + #endif + + typedef ExperimentalWithCallbackMethod_GetVarifyCode ExperimentalCallbackService; + template + class WithGenericMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_GetVarifyCode() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_GetVarifyCode() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetVarifyCode(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class ExperimentalWithRawCallbackMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_GetVarifyCode() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetVarifyCode(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* GetVarifyCode( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* GetVarifyCode( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class WithStreamedUnaryMethod_GetVarifyCode : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_GetVarifyCode() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::message::GetVarifyReq, ::message::GetVarifyRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::GetVarifyReq, ::message::GetVarifyRsp>* streamer) { + return this->StreamedGetVarifyCode(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_GetVarifyCode() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status GetVarifyCode(::grpc::ServerContext* /*context*/, const ::message::GetVarifyReq* /*request*/, ::message::GetVarifyRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedGetVarifyCode(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::GetVarifyReq,::message::GetVarifyRsp>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_GetVarifyCode StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_GetVarifyCode StreamedService; +}; + +class StatusService final { + public: + static constexpr char const* service_full_name() { + return "message.StatusService"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::message::GetChatServerRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>> AsyncGetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>>(AsyncGetChatServerRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>> PrepareAsyncGetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>>(PrepareAsyncGetChatServerRaw(context, request, cq)); + } + virtual ::grpc::Status Login(::grpc::ClientContext* context, const ::message::LoginReq& request, ::message::LoginRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>> AsyncLogin(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>>(AsyncLoginRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>> PrepareAsyncLogin(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>>(PrepareAsyncLoginRaw(context, request, cq)); + } + class experimental_async_interface { + public: + virtual ~experimental_async_interface() {} + virtual void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef class experimental_async_interface async_interface; + #endif + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + async_interface* async() { return experimental_async(); } + #endif + virtual class experimental_async_interface* experimental_async() { return nullptr; } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>* AsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::GetChatServerRsp>* PrepareAsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>* AsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::LoginRsp>* PrepareAsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::message::GetChatServerRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>> AsyncGetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>>(AsyncGetChatServerRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>> PrepareAsyncGetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>>(PrepareAsyncGetChatServerRaw(context, request, cq)); + } + ::grpc::Status Login(::grpc::ClientContext* context, const ::message::LoginReq& request, ::message::LoginRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>> AsyncLogin(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>>(AsyncLoginRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>> PrepareAsyncLogin(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>>(PrepareAsyncLoginRaw(context, request, cq)); + } + class experimental_async final : + public StubInterface::experimental_async_interface { + public: + void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void GetChatServer(::grpc::ClientContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void Login(::grpc::ClientContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + private: + friend class Stub; + explicit experimental_async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class experimental_async_interface* experimental_async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class experimental_async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>* AsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::GetChatServerRsp>* PrepareAsyncGetChatServerRaw(::grpc::ClientContext* context, const ::message::GetChatServerReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>* AsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::LoginRsp>* PrepareAsyncLoginRaw(::grpc::ClientContext* context, const ::message::LoginReq& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_GetChatServer_; + const ::grpc::internal::RpcMethod rpcmethod_Login_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status GetChatServer(::grpc::ServerContext* context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response); + virtual ::grpc::Status Login(::grpc::ServerContext* context, const ::message::LoginReq* request, ::message::LoginRsp* response); + }; + template + class WithAsyncMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_GetChatServer() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetChatServer(::grpc::ServerContext* context, ::message::GetChatServerReq* request, ::grpc::ServerAsyncResponseWriter< ::message::GetChatServerRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_Login() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestLogin(::grpc::ServerContext* context, ::message::LoginReq* request, ::grpc::ServerAsyncResponseWriter< ::message::LoginRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_GetChatServer > AsyncService; + template + class ExperimentalWithCallbackMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_GetChatServer() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::message::GetChatServerReq, ::message::GetChatServerRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::GetChatServerReq* request, ::message::GetChatServerRsp* response) { return this->GetChatServer(context, request, response); }));} + void SetMessageAllocatorFor_GetChatServer( + ::grpc::experimental::MessageAllocator< ::message::GetChatServerReq, ::message::GetChatServerRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(0); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::GetChatServerReq, ::message::GetChatServerRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* GetChatServer( + ::grpc::CallbackServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* GetChatServer( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_Login() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::message::LoginReq, ::message::LoginRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::LoginReq* request, ::message::LoginRsp* response) { return this->Login(context, request, response); }));} + void SetMessageAllocatorFor_Login( + ::grpc::experimental::MessageAllocator< ::message::LoginReq, ::message::LoginRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(1); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::LoginReq, ::message::LoginRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* Login( + ::grpc::CallbackServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* Login( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) + #endif + { return nullptr; } + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef ExperimentalWithCallbackMethod_GetChatServer > CallbackService; + #endif + + typedef ExperimentalWithCallbackMethod_GetChatServer > ExperimentalCallbackService; + template + class WithGenericMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_GetChatServer() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_Login() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_GetChatServer() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGetChatServer(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_Login() { + ::grpc::Service::MarkMethodRaw(1); + } + ~WithRawMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestLogin(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class ExperimentalWithRawCallbackMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_GetChatServer() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetChatServer(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* GetChatServer( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* GetChatServer( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_Login() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* Login( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* Login( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class WithStreamedUnaryMethod_GetChatServer : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_GetChatServer() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::message::GetChatServerReq, ::message::GetChatServerRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::GetChatServerReq, ::message::GetChatServerRsp>* streamer) { + return this->StreamedGetChatServer(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_GetChatServer() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status GetChatServer(::grpc::ServerContext* /*context*/, const ::message::GetChatServerReq* /*request*/, ::message::GetChatServerRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedGetChatServer(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::GetChatServerReq,::message::GetChatServerRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_Login : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_Login() { + ::grpc::Service::MarkMethodStreamed(1, + new ::grpc::internal::StreamedUnaryHandler< + ::message::LoginReq, ::message::LoginRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::LoginReq, ::message::LoginRsp>* streamer) { + return this->StreamedLogin(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_Login() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status Login(::grpc::ServerContext* /*context*/, const ::message::LoginReq* /*request*/, ::message::LoginRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedLogin(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::LoginReq,::message::LoginRsp>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_GetChatServer > StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_GetChatServer > StreamedService; +}; + +class ChatService final { + public: + static constexpr char const* service_full_name() { + return "message.ChatService"; + } + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::message::AddFriendRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>> AsyncNotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>>(AsyncNotifyAddFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>> PrepareAsyncNotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>>(PrepareAsyncNotifyAddFriendRaw(context, request, cq)); + } + virtual ::grpc::Status RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::message::RplyFriendRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>> AsyncRplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>>(AsyncRplyAddFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>> PrepareAsyncRplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>>(PrepareAsyncRplyAddFriendRaw(context, request, cq)); + } + virtual ::grpc::Status SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::message::SendChatMsgRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>> AsyncSendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>>(AsyncSendChatMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>> PrepareAsyncSendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>>(PrepareAsyncSendChatMsgRaw(context, request, cq)); + } + virtual ::grpc::Status NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::message::AuthFriendRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>> AsyncNotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>>(AsyncNotifyAuthFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>> PrepareAsyncNotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>>(PrepareAsyncNotifyAuthFriendRaw(context, request, cq)); + } + virtual ::grpc::Status NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::message::TextChatMsgRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>> AsyncNotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>>(AsyncNotifyTextChatMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>> PrepareAsyncNotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>>(PrepareAsyncNotifyTextChatMsgRaw(context, request, cq)); + } + virtual ::grpc::Status NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::message::KickUserRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>> AsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>>(AsyncNotifyKickUserRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); + } + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } + class experimental_async_interface { + public: + virtual ~experimental_async_interface() {} + virtual void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) = 0; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) = 0; + #else + virtual void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) = 0; + #endif + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef class experimental_async_interface async_interface; + #endif + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + async_interface* async() { return experimental_async(); } + #endif + virtual class experimental_async_interface* experimental_async() { return nullptr; } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>* AsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::AddFriendRsp>* PrepareAsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>* AsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::RplyFriendRsp>* PrepareAsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>* AsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::SendChatMsgRsp>* PrepareAsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>* AsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::AuthFriendRsp>* PrepareAsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>* AsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub final : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::message::AddFriendRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>> AsyncNotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>>(AsyncNotifyAddFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>> PrepareAsyncNotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>>(PrepareAsyncNotifyAddFriendRaw(context, request, cq)); + } + ::grpc::Status RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::message::RplyFriendRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>> AsyncRplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>>(AsyncRplyAddFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>> PrepareAsyncRplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>>(PrepareAsyncRplyAddFriendRaw(context, request, cq)); + } + ::grpc::Status SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::message::SendChatMsgRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>> AsyncSendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>>(AsyncSendChatMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>> PrepareAsyncSendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>>(PrepareAsyncSendChatMsgRaw(context, request, cq)); + } + ::grpc::Status NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::message::AuthFriendRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>> AsyncNotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>>(AsyncNotifyAuthFriendRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>> PrepareAsyncNotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>>(PrepareAsyncNotifyAuthFriendRaw(context, request, cq)); + } + ::grpc::Status NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::message::TextChatMsgRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>> AsyncNotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>>(AsyncNotifyTextChatMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>> PrepareAsyncNotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>>(PrepareAsyncNotifyTextChatMsgRaw(context, request, cq)); + } + ::grpc::Status NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::message::KickUserRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>> AsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>>(AsyncNotifyKickUserRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>> PrepareAsyncNotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>>(PrepareAsyncNotifyKickUserRaw(context, request, cq)); + } + ::grpc::Status NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::message::NotifyChatImgRsp* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> AsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(AsyncNotifyChatImgMsgRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>> PrepareAsyncNotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>>(PrepareAsyncNotifyChatImgMsgRaw(context, request, cq)); + } + class experimental_async final : + public StubInterface::experimental_async_interface { + public: + void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyAddFriend(::grpc::ClientContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void RplyAddFriend(::grpc::ClientContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void SendChatMsg(::grpc::ClientContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyAuthFriend(::grpc::ClientContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyTextChatMsg(::grpc::ClientContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyKickUser(::grpc::ClientContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, std::function) override; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::ClientUnaryReactor* reactor) override; + #else + void NotifyChatImgMsg(::grpc::ClientContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response, ::grpc::experimental::ClientUnaryReactor* reactor) override; + #endif + private: + friend class Stub; + explicit experimental_async(Stub* stub): stub_(stub) { } + Stub* stub() { return stub_; } + Stub* stub_; + }; + class experimental_async_interface* experimental_async() override { return &async_stub_; } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + class experimental_async async_stub_{this}; + ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>* AsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::AddFriendRsp>* PrepareAsyncNotifyAddFriendRaw(::grpc::ClientContext* context, const ::message::AddFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>* AsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::RplyFriendRsp>* PrepareAsyncRplyAddFriendRaw(::grpc::ClientContext* context, const ::message::RplyFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>* AsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::SendChatMsgRsp>* PrepareAsyncSendChatMsgRaw(::grpc::ClientContext* context, const ::message::SendChatMsgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>* AsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::AuthFriendRsp>* PrepareAsyncNotifyAuthFriendRaw(::grpc::ClientContext* context, const ::message::AuthFriendReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* AsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::TextChatMsgRsp>* PrepareAsyncNotifyTextChatMsgRaw(::grpc::ClientContext* context, const ::message::TextChatMsgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* AsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::KickUserRsp>* PrepareAsyncNotifyKickUserRaw(::grpc::ClientContext* context, const ::message::KickUserReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* AsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::message::NotifyChatImgRsp>* PrepareAsyncNotifyChatImgMsgRaw(::grpc::ClientContext* context, const ::message::NotifyChatImgReq& request, ::grpc::CompletionQueue* cq) override; + const ::grpc::internal::RpcMethod rpcmethod_NotifyAddFriend_; + const ::grpc::internal::RpcMethod rpcmethod_RplyAddFriend_; + const ::grpc::internal::RpcMethod rpcmethod_SendChatMsg_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyAuthFriend_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyTextChatMsg_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyKickUser_; + const ::grpc::internal::RpcMethod rpcmethod_NotifyChatImgMsg_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status NotifyAddFriend(::grpc::ServerContext* context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response); + virtual ::grpc::Status RplyAddFriend(::grpc::ServerContext* context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response); + virtual ::grpc::Status SendChatMsg(::grpc::ServerContext* context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response); + virtual ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response); + virtual ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response); + virtual ::grpc::Status NotifyKickUser(::grpc::ServerContext* context, const ::message::KickUserReq* request, ::message::KickUserRsp* response); + virtual ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response); + }; + template + class WithAsyncMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyAddFriend() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyAddFriend(::grpc::ServerContext* context, ::message::AddFriendReq* request, ::grpc::ServerAsyncResponseWriter< ::message::AddFriendRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_RplyAddFriend() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestRplyAddFriend(::grpc::ServerContext* context, ::message::RplyFriendReq* request, ::grpc::ServerAsyncResponseWriter< ::message::RplyFriendRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_SendChatMsg() { + ::grpc::Service::MarkMethodAsync(2); + } + ~WithAsyncMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestSendChatMsg(::grpc::ServerContext* context, ::message::SendChatMsgReq* request, ::grpc::ServerAsyncResponseWriter< ::message::SendChatMsgRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyAuthFriend() { + ::grpc::Service::MarkMethodAsync(3); + } + ~WithAsyncMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyAuthFriend(::grpc::ServerContext* context, ::message::AuthFriendReq* request, ::grpc::ServerAsyncResponseWriter< ::message::AuthFriendRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(3, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyTextChatMsg() { + ::grpc::Service::MarkMethodAsync(4); + } + ~WithAsyncMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyTextChatMsg(::grpc::ServerContext* context, ::message::TextChatMsgReq* request, ::grpc::ServerAsyncResponseWriter< ::message::TextChatMsgRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(4, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyKickUser() { + ::grpc::Service::MarkMethodAsync(5); + } + ~WithAsyncMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyKickUser(::grpc::ServerContext* context, ::message::KickUserReq* request, ::grpc::ServerAsyncResponseWriter< ::message::KickUserRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(5, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodAsync(6); + } + ~WithAsyncMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::message::NotifyChatImgReq* request, ::grpc::ServerAsyncResponseWriter< ::message::NotifyChatImgRsp>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_NotifyAddFriend > > > > > > AsyncService; + template + class ExperimentalWithCallbackMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyAddFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::message::AddFriendReq, ::message::AddFriendRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::AddFriendReq* request, ::message::AddFriendRsp* response) { return this->NotifyAddFriend(context, request, response); }));} + void SetMessageAllocatorFor_NotifyAddFriend( + ::grpc::experimental::MessageAllocator< ::message::AddFriendReq, ::message::AddFriendRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(0); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(0); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::AddFriendReq, ::message::AddFriendRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyAddFriend( + ::grpc::CallbackServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyAddFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_RplyAddFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::message::RplyFriendReq, ::message::RplyFriendRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::RplyFriendReq* request, ::message::RplyFriendRsp* response) { return this->RplyAddFriend(context, request, response); }));} + void SetMessageAllocatorFor_RplyAddFriend( + ::grpc::experimental::MessageAllocator< ::message::RplyFriendReq, ::message::RplyFriendRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(1); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(1); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::RplyFriendReq, ::message::RplyFriendRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* RplyAddFriend( + ::grpc::CallbackServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* RplyAddFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_SendChatMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(2, + new ::grpc::internal::CallbackUnaryHandler< ::message::SendChatMsgReq, ::message::SendChatMsgRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::SendChatMsgReq* request, ::message::SendChatMsgRsp* response) { return this->SendChatMsg(context, request, response); }));} + void SetMessageAllocatorFor_SendChatMsg( + ::grpc::experimental::MessageAllocator< ::message::SendChatMsgReq, ::message::SendChatMsgRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(2); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(2); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::SendChatMsgReq, ::message::SendChatMsgRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* SendChatMsg( + ::grpc::CallbackServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* SendChatMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyAuthFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(3, + new ::grpc::internal::CallbackUnaryHandler< ::message::AuthFriendReq, ::message::AuthFriendRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::AuthFriendReq* request, ::message::AuthFriendRsp* response) { return this->NotifyAuthFriend(context, request, response); }));} + void SetMessageAllocatorFor_NotifyAuthFriend( + ::grpc::experimental::MessageAllocator< ::message::AuthFriendReq, ::message::AuthFriendRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(3); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(3); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::AuthFriendReq, ::message::AuthFriendRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyAuthFriend( + ::grpc::CallbackServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyAuthFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyTextChatMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(4, + new ::grpc::internal::CallbackUnaryHandler< ::message::TextChatMsgReq, ::message::TextChatMsgRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::TextChatMsgReq* request, ::message::TextChatMsgRsp* response) { return this->NotifyTextChatMsg(context, request, response); }));} + void SetMessageAllocatorFor_NotifyTextChatMsg( + ::grpc::experimental::MessageAllocator< ::message::TextChatMsgReq, ::message::TextChatMsgRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(4); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(4); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::TextChatMsgReq, ::message::TextChatMsgRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyTextChatMsg( + ::grpc::CallbackServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyTextChatMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyKickUser() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(5, + new ::grpc::internal::CallbackUnaryHandler< ::message::KickUserReq, ::message::KickUserRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::KickUserReq* request, ::message::KickUserRsp* response) { return this->NotifyKickUser(context, request, response); }));} + void SetMessageAllocatorFor_NotifyKickUser( + ::grpc::experimental::MessageAllocator< ::message::KickUserReq, ::message::KickUserRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(5); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(5); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::KickUserReq, ::message::KickUserRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyKickUser( + ::grpc::CallbackServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyKickUser( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) { return this->NotifyChatImgMsg(context, request, response); }));} + void SetMessageAllocatorFor_NotifyChatImgMsg( + ::grpc::experimental::MessageAllocator< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* allocator) { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(6); + #else + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::experimental().GetHandler(6); + #endif + static_cast<::grpc::internal::CallbackUnaryHandler< ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>*>(handler) + ->SetMessageAllocator(allocator); + } + ~ExperimentalWithCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) + #endif + { return nullptr; } + }; + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > CallbackService; + #endif + + typedef ExperimentalWithCallbackMethod_NotifyAddFriend > > > > > > ExperimentalCallbackService; + template + class WithGenericMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyAddFriend() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_RplyAddFriend() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_SendChatMsg() { + ::grpc::Service::MarkMethodGeneric(2); + } + ~WithGenericMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyAuthFriend() { + ::grpc::Service::MarkMethodGeneric(3); + } + ~WithGenericMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyTextChatMsg() { + ::grpc::Service::MarkMethodGeneric(4); + } + ~WithGenericMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyKickUser() { + ::grpc::Service::MarkMethodGeneric(5); + } + ~WithGenericMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodGeneric(6); + } + ~WithGenericMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithRawMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyAddFriend() { + ::grpc::Service::MarkMethodRaw(0); + } + ~WithRawMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyAddFriend(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_RplyAddFriend() { + ::grpc::Service::MarkMethodRaw(1); + } + ~WithRawMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestRplyAddFriend(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_SendChatMsg() { + ::grpc::Service::MarkMethodRaw(2); + } + ~WithRawMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestSendChatMsg(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyAuthFriend() { + ::grpc::Service::MarkMethodRaw(3); + } + ~WithRawMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyAuthFriend(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(3, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyTextChatMsg() { + ::grpc::Service::MarkMethodRaw(4); + } + ~WithRawMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyTextChatMsg(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(4, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyKickUser() { + ::grpc::Service::MarkMethodRaw(5); + } + ~WithRawMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyKickUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(5, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithRawMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodRaw(6); + } + ~WithRawMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(6, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class ExperimentalWithRawCallbackMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyAddFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(0, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyAddFriend(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyAddFriend( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyAddFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_RplyAddFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(1, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->RplyAddFriend(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* RplyAddFriend( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* RplyAddFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_SendChatMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(2, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SendChatMsg(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* SendChatMsg( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* SendChatMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyAuthFriend() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(3, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyAuthFriend(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyAuthFriend( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyAuthFriend( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyTextChatMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(4, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyTextChatMsg(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyTextChatMsg( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyTextChatMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyKickUser() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(5, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyKickUser(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyKickUser( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyKickUser( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class ExperimentalWithRawCallbackMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() { + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::Service:: + #else + ::grpc::Service::experimental(). + #endif + MarkMethodRawCallback(6, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + ::grpc::CallbackServerContext* + #else + ::grpc::experimental::CallbackServerContext* + #endif + context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->NotifyChatImgMsg(context, request, response); })); + } + ~ExperimentalWithRawCallbackMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + virtual ::grpc::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #else + virtual ::grpc::experimental::ServerUnaryReactor* NotifyChatImgMsg( + ::grpc::experimental::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) + #endif + { return nullptr; } + }; + template + class WithStreamedUnaryMethod_NotifyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyAddFriend() { + ::grpc::Service::MarkMethodStreamed(0, + new ::grpc::internal::StreamedUnaryHandler< + ::message::AddFriendReq, ::message::AddFriendRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::AddFriendReq, ::message::AddFriendRsp>* streamer) { + return this->StreamedNotifyAddFriend(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyAddFriend(::grpc::ServerContext* /*context*/, const ::message::AddFriendReq* /*request*/, ::message::AddFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyAddFriend(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::AddFriendReq,::message::AddFriendRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_RplyAddFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_RplyAddFriend() { + ::grpc::Service::MarkMethodStreamed(1, + new ::grpc::internal::StreamedUnaryHandler< + ::message::RplyFriendReq, ::message::RplyFriendRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::RplyFriendReq, ::message::RplyFriendRsp>* streamer) { + return this->StreamedRplyAddFriend(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_RplyAddFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status RplyAddFriend(::grpc::ServerContext* /*context*/, const ::message::RplyFriendReq* /*request*/, ::message::RplyFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedRplyAddFriend(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::RplyFriendReq,::message::RplyFriendRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_SendChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_SendChatMsg() { + ::grpc::Service::MarkMethodStreamed(2, + new ::grpc::internal::StreamedUnaryHandler< + ::message::SendChatMsgReq, ::message::SendChatMsgRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::SendChatMsgReq, ::message::SendChatMsgRsp>* streamer) { + return this->StreamedSendChatMsg(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_SendChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status SendChatMsg(::grpc::ServerContext* /*context*/, const ::message::SendChatMsgReq* /*request*/, ::message::SendChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedSendChatMsg(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::SendChatMsgReq,::message::SendChatMsgRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_NotifyAuthFriend : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyAuthFriend() { + ::grpc::Service::MarkMethodStreamed(3, + new ::grpc::internal::StreamedUnaryHandler< + ::message::AuthFriendReq, ::message::AuthFriendRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::AuthFriendReq, ::message::AuthFriendRsp>* streamer) { + return this->StreamedNotifyAuthFriend(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyAuthFriend() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyAuthFriend(::grpc::ServerContext* /*context*/, const ::message::AuthFriendReq* /*request*/, ::message::AuthFriendRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyAuthFriend(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::AuthFriendReq,::message::AuthFriendRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_NotifyTextChatMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyTextChatMsg() { + ::grpc::Service::MarkMethodStreamed(4, + new ::grpc::internal::StreamedUnaryHandler< + ::message::TextChatMsgReq, ::message::TextChatMsgRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::TextChatMsgReq, ::message::TextChatMsgRsp>* streamer) { + return this->StreamedNotifyTextChatMsg(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyTextChatMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyTextChatMsg(::grpc::ServerContext* /*context*/, const ::message::TextChatMsgReq* /*request*/, ::message::TextChatMsgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyTextChatMsg(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::TextChatMsgReq,::message::TextChatMsgRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_NotifyKickUser : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyKickUser() { + ::grpc::Service::MarkMethodStreamed(5, + new ::grpc::internal::StreamedUnaryHandler< + ::message::KickUserReq, ::message::KickUserRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::KickUserReq, ::message::KickUserRsp>* streamer) { + return this->StreamedNotifyKickUser(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyKickUser() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyKickUser(::grpc::ServerContext* /*context*/, const ::message::KickUserReq* /*request*/, ::message::KickUserRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyKickUser(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::KickUserReq,::message::KickUserRsp>* server_unary_streamer) = 0; + }; + template + class WithStreamedUnaryMethod_NotifyChatImgMsg : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_NotifyChatImgMsg() { + ::grpc::Service::MarkMethodStreamed(6, + new ::grpc::internal::StreamedUnaryHandler< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::message::NotifyChatImgReq, ::message::NotifyChatImgRsp>* streamer) { + return this->StreamedNotifyChatImgMsg(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_NotifyChatImgMsg() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status NotifyChatImgMsg(::grpc::ServerContext* /*context*/, const ::message::NotifyChatImgReq* /*request*/, ::message::NotifyChatImgRsp* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedNotifyChatImgMsg(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::message::NotifyChatImgReq,::message::NotifyChatImgRsp>* server_unary_streamer) = 0; + }; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedUnaryService; + typedef Service SplitStreamedService; + typedef WithStreamedUnaryMethod_NotifyAddFriend > > > > > > StreamedService; +}; + +} // namespace message + + +#endif // GRPC_message_2eproto__INCLUDED diff --git a/server/ResourceServer/message.pb.cc b/server/ResourceServer/message.pb.cc new file mode 100644 index 0000000..1cc6cc6 --- /dev/null +++ b/server/ResourceServer/message.pb.cc @@ -0,0 +1,6936 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: message.proto + +#include "message.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include +extern PROTOBUF_INTERNAL_EXPORT_message_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_AddFriendMsg_message_2eproto; +extern PROTOBUF_INTERNAL_EXPORT_message_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_TextChatData_message_2eproto; +namespace message { +class GetVarifyReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _GetVarifyReq_default_instance_; +class GetVarifyRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _GetVarifyRsp_default_instance_; +class GetChatServerReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _GetChatServerReq_default_instance_; +class GetChatServerRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _GetChatServerRsp_default_instance_; +class LoginReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _LoginReq_default_instance_; +class LoginRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _LoginRsp_default_instance_; +class AddFriendReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _AddFriendReq_default_instance_; +class AddFriendRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _AddFriendRsp_default_instance_; +class RplyFriendReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _RplyFriendReq_default_instance_; +class RplyFriendRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _RplyFriendRsp_default_instance_; +class SendChatMsgReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _SendChatMsgReq_default_instance_; +class SendChatMsgRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _SendChatMsgRsp_default_instance_; +class AddFriendMsgDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _AddFriendMsg_default_instance_; +class AuthFriendReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _AuthFriendReq_default_instance_; +class AuthFriendRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _AuthFriendRsp_default_instance_; +class TextChatMsgReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _TextChatMsgReq_default_instance_; +class TextChatDataDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _TextChatData_default_instance_; +class TextChatMsgRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _TextChatMsgRsp_default_instance_; +class KickUserReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _KickUserReq_default_instance_; +class KickUserRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _KickUserRsp_default_instance_; +class NotifyChatImgReqDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgReq_default_instance_; +class NotifyChatImgRspDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _NotifyChatImgRsp_default_instance_; +} // namespace message +static void InitDefaultsscc_info_AddFriendMsg_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_AddFriendMsg_default_instance_; + new (ptr) ::message::AddFriendMsg(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::AddFriendMsg::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_AddFriendMsg_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_AddFriendMsg_message_2eproto}, {}}; + +static void InitDefaultsscc_info_AddFriendReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_AddFriendReq_default_instance_; + new (ptr) ::message::AddFriendReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::AddFriendReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_AddFriendReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_AddFriendReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_AddFriendRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_AddFriendRsp_default_instance_; + new (ptr) ::message::AddFriendRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::AddFriendRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_AddFriendRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_AddFriendRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_AuthFriendReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_AuthFriendReq_default_instance_; + new (ptr) ::message::AuthFriendReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::AuthFriendReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_AuthFriendReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_AuthFriendReq_message_2eproto}, { + &scc_info_AddFriendMsg_message_2eproto.base,}}; + +static void InitDefaultsscc_info_AuthFriendRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_AuthFriendRsp_default_instance_; + new (ptr) ::message::AuthFriendRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::AuthFriendRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_AuthFriendRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_AuthFriendRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_GetChatServerReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_GetChatServerReq_default_instance_; + new (ptr) ::message::GetChatServerReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::GetChatServerReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GetChatServerReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GetChatServerReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_GetChatServerRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_GetChatServerRsp_default_instance_; + new (ptr) ::message::GetChatServerRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::GetChatServerRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GetChatServerRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GetChatServerRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_GetVarifyReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_GetVarifyReq_default_instance_; + new (ptr) ::message::GetVarifyReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::GetVarifyReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GetVarifyReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GetVarifyReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_GetVarifyRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_GetVarifyRsp_default_instance_; + new (ptr) ::message::GetVarifyRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::GetVarifyRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GetVarifyRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_GetVarifyRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_KickUserReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_KickUserReq_default_instance_; + new (ptr) ::message::KickUserReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::KickUserReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_KickUserReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_KickUserReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_KickUserRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_KickUserRsp_default_instance_; + new (ptr) ::message::KickUserRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::KickUserRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_KickUserRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_KickUserRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_LoginReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_LoginReq_default_instance_; + new (ptr) ::message::LoginReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::LoginReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_LoginReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_LoginReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_LoginRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_LoginRsp_default_instance_; + new (ptr) ::message::LoginRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::LoginRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_LoginRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_LoginRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_NotifyChatImgReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgReq_default_instance_; + new (ptr) ::message::NotifyChatImgReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_NotifyChatImgRsp_default_instance_; + new (ptr) ::message::NotifyChatImgRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::NotifyChatImgRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_NotifyChatImgRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_NotifyChatImgRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_RplyFriendReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_RplyFriendReq_default_instance_; + new (ptr) ::message::RplyFriendReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::RplyFriendReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_RplyFriendReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_RplyFriendReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_RplyFriendRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_RplyFriendRsp_default_instance_; + new (ptr) ::message::RplyFriendRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::RplyFriendRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_RplyFriendRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_RplyFriendRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_SendChatMsgReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_SendChatMsgReq_default_instance_; + new (ptr) ::message::SendChatMsgReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::SendChatMsgReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SendChatMsgReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SendChatMsgReq_message_2eproto}, {}}; + +static void InitDefaultsscc_info_SendChatMsgRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_SendChatMsgRsp_default_instance_; + new (ptr) ::message::SendChatMsgRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::SendChatMsgRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_SendChatMsgRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_SendChatMsgRsp_message_2eproto}, {}}; + +static void InitDefaultsscc_info_TextChatData_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_TextChatData_default_instance_; + new (ptr) ::message::TextChatData(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::TextChatData::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_TextChatData_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_TextChatData_message_2eproto}, {}}; + +static void InitDefaultsscc_info_TextChatMsgReq_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_TextChatMsgReq_default_instance_; + new (ptr) ::message::TextChatMsgReq(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::TextChatMsgReq::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_TextChatMsgReq_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_TextChatMsgReq_message_2eproto}, { + &scc_info_TextChatData_message_2eproto.base,}}; + +static void InitDefaultsscc_info_TextChatMsgRsp_message_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::message::_TextChatMsgRsp_default_instance_; + new (ptr) ::message::TextChatMsgRsp(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::message::TextChatMsgRsp::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_TextChatMsgRsp_message_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_TextChatMsgRsp_message_2eproto}, { + &scc_info_TextChatData_message_2eproto.base,}}; + +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_message_2eproto[22]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_message_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_message_2eproto = nullptr; + +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_message_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::GetVarifyReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::GetVarifyReq, email_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::GetVarifyRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::GetVarifyRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::GetVarifyRsp, email_), + PROTOBUF_FIELD_OFFSET(::message::GetVarifyRsp, code_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::GetChatServerReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::GetChatServerReq, uid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::GetChatServerRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::GetChatServerRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::GetChatServerRsp, host_), + PROTOBUF_FIELD_OFFSET(::message::GetChatServerRsp, port_), + PROTOBUF_FIELD_OFFSET(::message::GetChatServerRsp, token_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::LoginReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::LoginReq, uid_), + PROTOBUF_FIELD_OFFSET(::message::LoginReq, token_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::LoginRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::LoginRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::LoginRsp, uid_), + PROTOBUF_FIELD_OFFSET(::message::LoginRsp, token_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, applyuid_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, name_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, desc_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, icon_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, nick_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, sex_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendReq, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendRsp, applyuid_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendRsp, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::RplyFriendReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::RplyFriendReq, rplyuid_), + PROTOBUF_FIELD_OFFSET(::message::RplyFriendReq, agree_), + PROTOBUF_FIELD_OFFSET(::message::RplyFriendReq, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::RplyFriendRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::RplyFriendRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::RplyFriendRsp, rplyuid_), + PROTOBUF_FIELD_OFFSET(::message::RplyFriendRsp, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgReq, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgReq, touid_), + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgReq, message_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgRsp, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::SendChatMsgRsp, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, sender_id_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, unique_id_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, msg_id_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, thread_id_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, msgcontent_), + PROTOBUF_FIELD_OFFSET(::message::AddFriendMsg, status_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::AuthFriendReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::AuthFriendReq, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::AuthFriendReq, touid_), + PROTOBUF_FIELD_OFFSET(::message::AuthFriendReq, textmsgs_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::AuthFriendRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::AuthFriendRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::AuthFriendRsp, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::AuthFriendRsp, touid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgReq, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgReq, touid_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgReq, thread_id_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgReq, textmsgs_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::TextChatData, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::TextChatData, unique_id_), + PROTOBUF_FIELD_OFFSET(::message::TextChatData, msg_id_), + PROTOBUF_FIELD_OFFSET(::message::TextChatData, msgcontent_), + PROTOBUF_FIELD_OFFSET(::message::TextChatData, chat_time_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, fromuid_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, touid_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, thread_id_), + PROTOBUF_FIELD_OFFSET(::message::TextChatMsgRsp, textmsgs_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::KickUserReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::KickUserReq, uid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::KickUserRsp, uid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgReq, thread_id_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, error_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, from_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, to_uid_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, message_id_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, file_name_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, total_size_), + PROTOBUF_FIELD_OFFSET(::message::NotifyChatImgRsp, thread_id_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::message::GetVarifyReq)}, + { 6, -1, sizeof(::message::GetVarifyRsp)}, + { 14, -1, sizeof(::message::GetChatServerReq)}, + { 20, -1, sizeof(::message::GetChatServerRsp)}, + { 29, -1, sizeof(::message::LoginReq)}, + { 36, -1, sizeof(::message::LoginRsp)}, + { 44, -1, sizeof(::message::AddFriendReq)}, + { 56, -1, sizeof(::message::AddFriendRsp)}, + { 64, -1, sizeof(::message::RplyFriendReq)}, + { 72, -1, sizeof(::message::RplyFriendRsp)}, + { 80, -1, sizeof(::message::SendChatMsgReq)}, + { 88, -1, sizeof(::message::SendChatMsgRsp)}, + { 96, -1, sizeof(::message::AddFriendMsg)}, + { 107, -1, sizeof(::message::AuthFriendReq)}, + { 115, -1, sizeof(::message::AuthFriendRsp)}, + { 123, -1, sizeof(::message::TextChatMsgReq)}, + { 132, -1, sizeof(::message::TextChatData)}, + { 141, -1, sizeof(::message::TextChatMsgRsp)}, + { 151, -1, sizeof(::message::KickUserReq)}, + { 157, -1, sizeof(::message::KickUserRsp)}, + { 164, -1, sizeof(::message::NotifyChatImgReq)}, + { 175, -1, sizeof(::message::NotifyChatImgRsp)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::message::_GetVarifyReq_default_instance_), + reinterpret_cast(&::message::_GetVarifyRsp_default_instance_), + reinterpret_cast(&::message::_GetChatServerReq_default_instance_), + reinterpret_cast(&::message::_GetChatServerRsp_default_instance_), + reinterpret_cast(&::message::_LoginReq_default_instance_), + reinterpret_cast(&::message::_LoginRsp_default_instance_), + reinterpret_cast(&::message::_AddFriendReq_default_instance_), + reinterpret_cast(&::message::_AddFriendRsp_default_instance_), + reinterpret_cast(&::message::_RplyFriendReq_default_instance_), + reinterpret_cast(&::message::_RplyFriendRsp_default_instance_), + reinterpret_cast(&::message::_SendChatMsgReq_default_instance_), + reinterpret_cast(&::message::_SendChatMsgRsp_default_instance_), + reinterpret_cast(&::message::_AddFriendMsg_default_instance_), + reinterpret_cast(&::message::_AuthFriendReq_default_instance_), + reinterpret_cast(&::message::_AuthFriendRsp_default_instance_), + reinterpret_cast(&::message::_TextChatMsgReq_default_instance_), + reinterpret_cast(&::message::_TextChatData_default_instance_), + reinterpret_cast(&::message::_TextChatMsgRsp_default_instance_), + reinterpret_cast(&::message::_KickUserReq_default_instance_), + reinterpret_cast(&::message::_KickUserRsp_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgReq_default_instance_), + reinterpret_cast(&::message::_NotifyChatImgRsp_default_instance_), +}; + +const char descriptor_table_protodef_message_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\rmessage.proto\022\007message\"\035\n\014GetVarifyReq" + "\022\r\n\005email\030\001 \001(\t\":\n\014GetVarifyRsp\022\r\n\005error" + "\030\001 \001(\005\022\r\n\005email\030\002 \001(\t\022\014\n\004code\030\003 \001(\t\"\037\n\020G" + "etChatServerReq\022\013\n\003uid\030\001 \001(\005\"L\n\020GetChatS" + "erverRsp\022\r\n\005error\030\001 \001(\005\022\014\n\004host\030\002 \001(\t\022\014\n" + "\004port\030\003 \001(\t\022\r\n\005token\030\004 \001(\t\"&\n\010LoginReq\022\013" + "\n\003uid\030\001 \001(\005\022\r\n\005token\030\002 \001(\t\"5\n\010LoginRsp\022\r" + "\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\005\022\r\n\005token\030\003 \001(" + "\t\"t\n\014AddFriendReq\022\020\n\010applyuid\030\001 \001(\005\022\014\n\004n" + "ame\030\002 \001(\t\022\014\n\004desc\030\003 \001(\t\022\014\n\004icon\030\004 \001(\t\022\014\n" + "\004nick\030\005 \001(\t\022\013\n\003sex\030\006 \001(\005\022\r\n\005touid\030\007 \001(\005\"" + ">\n\014AddFriendRsp\022\r\n\005error\030\001 \001(\005\022\020\n\010applyu" + "id\030\002 \001(\005\022\r\n\005touid\030\003 \001(\005\">\n\rRplyFriendReq" + "\022\017\n\007rplyuid\030\001 \001(\005\022\r\n\005agree\030\002 \001(\010\022\r\n\005toui" + "d\030\003 \001(\005\">\n\rRplyFriendRsp\022\r\n\005error\030\001 \001(\005\022" + "\017\n\007rplyuid\030\002 \001(\005\022\r\n\005touid\030\003 \001(\005\"A\n\016SendC" + "hatMsgReq\022\017\n\007fromuid\030\001 \001(\005\022\r\n\005touid\030\002 \001(" + "\005\022\017\n\007message\030\003 \001(\t\"\?\n\016SendChatMsgRsp\022\r\n\005" + "error\030\001 \001(\005\022\017\n\007fromuid\030\002 \001(\005\022\r\n\005touid\030\003 " + "\001(\005\"{\n\014AddFriendMsg\022\021\n\tsender_id\030\001 \001(\005\022\021" + "\n\tunique_id\030\002 \001(\t\022\016\n\006msg_id\030\003 \001(\005\022\021\n\tthr" + "ead_id\030\004 \001(\005\022\022\n\nmsgcontent\030\005 \001(\t\022\016\n\006stat" + "us\030\006 \001(\005\"X\n\rAuthFriendReq\022\017\n\007fromuid\030\001 \001" + "(\005\022\r\n\005touid\030\002 \001(\005\022\'\n\010textmsgs\030\003 \003(\0132\025.me" + "ssage.AddFriendMsg\">\n\rAuthFriendRsp\022\r\n\005e" + "rror\030\001 \001(\005\022\017\n\007fromuid\030\002 \001(\005\022\r\n\005touid\030\003 \001" + "(\005\"l\n\016TextChatMsgReq\022\017\n\007fromuid\030\001 \001(\005\022\r\n" + "\005touid\030\002 \001(\005\022\021\n\tthread_id\030\003 \001(\005\022\'\n\010textm" + "sgs\030\004 \003(\0132\025.message.TextChatData\"X\n\014Text" + "ChatData\022\021\n\tunique_id\030\001 \001(\t\022\016\n\006msg_id\030\002 " + "\001(\005\022\022\n\nmsgcontent\030\003 \001(\t\022\021\n\tchat_time\030\004 \001" + "(\t\"{\n\016TextChatMsgRsp\022\r\n\005error\030\001 \001(\005\022\017\n\007f" + "romuid\030\002 \001(\005\022\r\n\005touid\030\003 \001(\005\022\021\n\tthread_id" + "\030\004 \001(\005\022\'\n\010textmsgs\030\005 \003(\0132\025.message.TextC" + "hatData\"\032\n\013KickUserReq\022\013\n\003uid\030\001 \001(\005\")\n\013K" + "ickUserRsp\022\r\n\005error\030\001 \001(\005\022\013\n\003uid\030\002 \001(\005\"\202" + "\001\n\020NotifyChatImgReq\022\020\n\010from_uid\030\001 \001(\005\022\016\n" + "\006to_uid\030\002 \001(\005\022\022\n\nmessage_id\030\003 \001(\005\022\021\n\tfil" + "e_name\030\004 \001(\t\022\022\n\ntotal_size\030\005 \001(\003\022\021\n\tthre" + "ad_id\030\006 \001(\005\"\221\001\n\020NotifyChatImgRsp\022\r\n\005erro" + "r\030\001 \001(\005\022\020\n\010from_uid\030\002 \001(\005\022\016\n\006to_uid\030\003 \001(" + "\005\022\022\n\nmessage_id\030\004 \001(\005\022\021\n\tfile_name\030\005 \001(\t" + "\022\022\n\ntotal_size\030\006 \001(\003\022\021\n\tthread_id\030\007 \001(\0052" + "P\n\rVarifyService\022\?\n\rGetVarifyCode\022\025.mess" + "age.GetVarifyReq\032\025.message.GetVarifyRsp\"" + "\0002\207\001\n\rStatusService\022G\n\rGetChatServer\022\031.m" + "essage.GetChatServerReq\032\031.message.GetCha" + "tServerRsp\"\000\022-\n\005Login\022\021.message.LoginReq" + "\032\021.message.LoginRsp2\361\003\n\013ChatService\022A\n\017N" + "otifyAddFriend\022\025.message.AddFriendReq\032\025." + "message.AddFriendRsp\"\000\022A\n\rRplyAddFriend\022" + "\026.message.RplyFriendReq\032\026.message.RplyFr" + "iendRsp\"\000\022A\n\013SendChatMsg\022\027.message.SendC" + "hatMsgReq\032\027.message.SendChatMsgRsp\"\000\022D\n\020" + "NotifyAuthFriend\022\026.message.AuthFriendReq" + "\032\026.message.AuthFriendRsp\"\000\022G\n\021NotifyText" + "ChatMsg\022\027.message.TextChatMsgReq\032\027.messa" + "ge.TextChatMsgRsp\"\000\022>\n\016NotifyKickUser\022\024." + "message.KickUserReq\032\024.message.KickUserRs" + "p\"\000\022J\n\020NotifyChatImgMsg\022\031.message.Notify" + "ChatImgReq\032\031.message.NotifyChatImgRsp\"\000b" + "\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_message_2eproto_deps[1] = { +}; +static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_message_2eproto_sccs[22] = { + &scc_info_AddFriendMsg_message_2eproto.base, + &scc_info_AddFriendReq_message_2eproto.base, + &scc_info_AddFriendRsp_message_2eproto.base, + &scc_info_AuthFriendReq_message_2eproto.base, + &scc_info_AuthFriendRsp_message_2eproto.base, + &scc_info_GetChatServerReq_message_2eproto.base, + &scc_info_GetChatServerRsp_message_2eproto.base, + &scc_info_GetVarifyReq_message_2eproto.base, + &scc_info_GetVarifyRsp_message_2eproto.base, + &scc_info_KickUserReq_message_2eproto.base, + &scc_info_KickUserRsp_message_2eproto.base, + &scc_info_LoginReq_message_2eproto.base, + &scc_info_LoginRsp_message_2eproto.base, + &scc_info_NotifyChatImgReq_message_2eproto.base, + &scc_info_NotifyChatImgRsp_message_2eproto.base, + &scc_info_RplyFriendReq_message_2eproto.base, + &scc_info_RplyFriendRsp_message_2eproto.base, + &scc_info_SendChatMsgReq_message_2eproto.base, + &scc_info_SendChatMsgRsp_message_2eproto.base, + &scc_info_TextChatData_message_2eproto.base, + &scc_info_TextChatMsgReq_message_2eproto.base, + &scc_info_TextChatMsgRsp_message_2eproto.base, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_message_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_message_2eproto = { + false, false, descriptor_table_protodef_message_2eproto, "message.proto", 2447, + &descriptor_table_message_2eproto_once, descriptor_table_message_2eproto_sccs, descriptor_table_message_2eproto_deps, 22, 0, + schemas, file_default_instances, TableStruct_message_2eproto::offsets, + file_level_metadata_message_2eproto, 22, file_level_enum_descriptors_message_2eproto, file_level_service_descriptors_message_2eproto, +}; + +// Force running AddDescriptors() at dynamic initialization time. +static bool dynamic_init_dummy_message_2eproto = (static_cast(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_message_2eproto)), true); +namespace message { + +// =================================================================== + +void GetVarifyReq::InitAsDefaultInstance() { +} +class GetVarifyReq::_Internal { + public: +}; + +GetVarifyReq::GetVarifyReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.GetVarifyReq) +} +GetVarifyReq::GetVarifyReq(const GetVarifyReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_email().empty()) { + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_email(), + GetArena()); + } + // @@protoc_insertion_point(copy_constructor:message.GetVarifyReq) +} + +void GetVarifyReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GetVarifyReq_message_2eproto.base); + email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +GetVarifyReq::~GetVarifyReq() { + // @@protoc_insertion_point(destructor:message.GetVarifyReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void GetVarifyReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + email_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void GetVarifyReq::ArenaDtor(void* object) { + GetVarifyReq* _this = reinterpret_cast< GetVarifyReq* >(object); + (void)_this; +} +void GetVarifyReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void GetVarifyReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const GetVarifyReq& GetVarifyReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GetVarifyReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void GetVarifyReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.GetVarifyReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + email_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GetVarifyReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string email = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_email(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetVarifyReq.email")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* GetVarifyReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.GetVarifyReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string email = 1; + if (this->email().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_email().data(), static_cast(this->_internal_email().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetVarifyReq.email"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_email(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.GetVarifyReq) + return target; +} + +size_t GetVarifyReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.GetVarifyReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string email = 1; + if (this->email().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_email()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void GetVarifyReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.GetVarifyReq) + GOOGLE_DCHECK_NE(&from, this); + const GetVarifyReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.GetVarifyReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.GetVarifyReq) + MergeFrom(*source); + } +} + +void GetVarifyReq::MergeFrom(const GetVarifyReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.GetVarifyReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.email().size() > 0) { + _internal_set_email(from._internal_email()); + } +} + +void GetVarifyReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.GetVarifyReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GetVarifyReq::CopyFrom(const GetVarifyReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.GetVarifyReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GetVarifyReq::IsInitialized() const { + return true; +} + +void GetVarifyReq::InternalSwap(GetVarifyReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + email_.Swap(&other->email_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GetVarifyReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void GetVarifyRsp::InitAsDefaultInstance() { +} +class GetVarifyRsp::_Internal { + public: +}; + +GetVarifyRsp::GetVarifyRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.GetVarifyRsp) +} +GetVarifyRsp::GetVarifyRsp(const GetVarifyRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_email().empty()) { + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_email(), + GetArena()); + } + code_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_code().empty()) { + code_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_code(), + GetArena()); + } + error_ = from.error_; + // @@protoc_insertion_point(copy_constructor:message.GetVarifyRsp) +} + +void GetVarifyRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GetVarifyRsp_message_2eproto.base); + email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + code_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + error_ = 0; +} + +GetVarifyRsp::~GetVarifyRsp() { + // @@protoc_insertion_point(destructor:message.GetVarifyRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void GetVarifyRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + email_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + code_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void GetVarifyRsp::ArenaDtor(void* object) { + GetVarifyRsp* _this = reinterpret_cast< GetVarifyRsp* >(object); + (void)_this; +} +void GetVarifyRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void GetVarifyRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const GetVarifyRsp& GetVarifyRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GetVarifyRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void GetVarifyRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.GetVarifyRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + email_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + code_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + error_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GetVarifyRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string email = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_email(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetVarifyRsp.email")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string code = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_code(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetVarifyRsp.code")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* GetVarifyRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.GetVarifyRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // string email = 2; + if (this->email().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_email().data(), static_cast(this->_internal_email().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetVarifyRsp.email"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_email(), target); + } + + // string code = 3; + if (this->code().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_code().data(), static_cast(this->_internal_code().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetVarifyRsp.code"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_code(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.GetVarifyRsp) + return target; +} + +size_t GetVarifyRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.GetVarifyRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string email = 2; + if (this->email().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_email()); + } + + // string code = 3; + if (this->code().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_code()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void GetVarifyRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.GetVarifyRsp) + GOOGLE_DCHECK_NE(&from, this); + const GetVarifyRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.GetVarifyRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.GetVarifyRsp) + MergeFrom(*source); + } +} + +void GetVarifyRsp::MergeFrom(const GetVarifyRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.GetVarifyRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.email().size() > 0) { + _internal_set_email(from._internal_email()); + } + if (from.code().size() > 0) { + _internal_set_code(from._internal_code()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } +} + +void GetVarifyRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.GetVarifyRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GetVarifyRsp::CopyFrom(const GetVarifyRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.GetVarifyRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GetVarifyRsp::IsInitialized() const { + return true; +} + +void GetVarifyRsp::InternalSwap(GetVarifyRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + email_.Swap(&other->email_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + code_.Swap(&other->code_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(error_, other->error_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GetVarifyRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void GetChatServerReq::InitAsDefaultInstance() { +} +class GetChatServerReq::_Internal { + public: +}; + +GetChatServerReq::GetChatServerReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.GetChatServerReq) +} +GetChatServerReq::GetChatServerReq(const GetChatServerReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + uid_ = from.uid_; + // @@protoc_insertion_point(copy_constructor:message.GetChatServerReq) +} + +void GetChatServerReq::SharedCtor() { + uid_ = 0; +} + +GetChatServerReq::~GetChatServerReq() { + // @@protoc_insertion_point(destructor:message.GetChatServerReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void GetChatServerReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void GetChatServerReq::ArenaDtor(void* object) { + GetChatServerReq* _this = reinterpret_cast< GetChatServerReq* >(object); + (void)_this; +} +void GetChatServerReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void GetChatServerReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const GetChatServerReq& GetChatServerReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GetChatServerReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void GetChatServerReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.GetChatServerReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + uid_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GetChatServerReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* GetChatServerReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.GetChatServerReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 uid = 1; + if (this->uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_uid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.GetChatServerReq) + return target; +} + +size_t GetChatServerReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.GetChatServerReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 uid = 1; + if (this->uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_uid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void GetChatServerReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.GetChatServerReq) + GOOGLE_DCHECK_NE(&from, this); + const GetChatServerReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.GetChatServerReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.GetChatServerReq) + MergeFrom(*source); + } +} + +void GetChatServerReq::MergeFrom(const GetChatServerReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.GetChatServerReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.uid() != 0) { + _internal_set_uid(from._internal_uid()); + } +} + +void GetChatServerReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.GetChatServerReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GetChatServerReq::CopyFrom(const GetChatServerReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.GetChatServerReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GetChatServerReq::IsInitialized() const { + return true; +} + +void GetChatServerReq::InternalSwap(GetChatServerReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(uid_, other->uid_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GetChatServerReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void GetChatServerRsp::InitAsDefaultInstance() { +} +class GetChatServerRsp::_Internal { + public: +}; + +GetChatServerRsp::GetChatServerRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.GetChatServerRsp) +} +GetChatServerRsp::GetChatServerRsp(const GetChatServerRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + host_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_host().empty()) { + host_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_host(), + GetArena()); + } + port_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_port().empty()) { + port_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_port(), + GetArena()); + } + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_token().empty()) { + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_token(), + GetArena()); + } + error_ = from.error_; + // @@protoc_insertion_point(copy_constructor:message.GetChatServerRsp) +} + +void GetChatServerRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_GetChatServerRsp_message_2eproto.base); + host_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + port_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + error_ = 0; +} + +GetChatServerRsp::~GetChatServerRsp() { + // @@protoc_insertion_point(destructor:message.GetChatServerRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void GetChatServerRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + host_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + port_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + token_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void GetChatServerRsp::ArenaDtor(void* object) { + GetChatServerRsp* _this = reinterpret_cast< GetChatServerRsp* >(object); + (void)_this; +} +void GetChatServerRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void GetChatServerRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const GetChatServerRsp& GetChatServerRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_GetChatServerRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void GetChatServerRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.GetChatServerRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + host_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + port_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + error_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* GetChatServerRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string host = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_host(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetChatServerRsp.host")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string port = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_port(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetChatServerRsp.port")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string token = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_token(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.GetChatServerRsp.token")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* GetChatServerRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.GetChatServerRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // string host = 2; + if (this->host().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_host().data(), static_cast(this->_internal_host().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetChatServerRsp.host"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_host(), target); + } + + // string port = 3; + if (this->port().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_port().data(), static_cast(this->_internal_port().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetChatServerRsp.port"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_port(), target); + } + + // string token = 4; + if (this->token().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_token().data(), static_cast(this->_internal_token().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.GetChatServerRsp.token"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_token(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.GetChatServerRsp) + return target; +} + +size_t GetChatServerRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.GetChatServerRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string host = 2; + if (this->host().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_host()); + } + + // string port = 3; + if (this->port().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_port()); + } + + // string token = 4; + if (this->token().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_token()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void GetChatServerRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.GetChatServerRsp) + GOOGLE_DCHECK_NE(&from, this); + const GetChatServerRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.GetChatServerRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.GetChatServerRsp) + MergeFrom(*source); + } +} + +void GetChatServerRsp::MergeFrom(const GetChatServerRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.GetChatServerRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.host().size() > 0) { + _internal_set_host(from._internal_host()); + } + if (from.port().size() > 0) { + _internal_set_port(from._internal_port()); + } + if (from.token().size() > 0) { + _internal_set_token(from._internal_token()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } +} + +void GetChatServerRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.GetChatServerRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void GetChatServerRsp::CopyFrom(const GetChatServerRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.GetChatServerRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool GetChatServerRsp::IsInitialized() const { + return true; +} + +void GetChatServerRsp::InternalSwap(GetChatServerRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + host_.Swap(&other->host_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + port_.Swap(&other->port_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + token_.Swap(&other->token_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(error_, other->error_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata GetChatServerRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void LoginReq::InitAsDefaultInstance() { +} +class LoginReq::_Internal { + public: +}; + +LoginReq::LoginReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.LoginReq) +} +LoginReq::LoginReq(const LoginReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_token().empty()) { + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_token(), + GetArena()); + } + uid_ = from.uid_; + // @@protoc_insertion_point(copy_constructor:message.LoginReq) +} + +void LoginReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_LoginReq_message_2eproto.base); + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + uid_ = 0; +} + +LoginReq::~LoginReq() { + // @@protoc_insertion_point(destructor:message.LoginReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void LoginReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + token_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void LoginReq::ArenaDtor(void* object) { + LoginReq* _this = reinterpret_cast< LoginReq* >(object); + (void)_this; +} +void LoginReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void LoginReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const LoginReq& LoginReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_LoginReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void LoginReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.LoginReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + uid_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* LoginReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string token = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_token(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.LoginReq.token")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* LoginReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.LoginReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 uid = 1; + if (this->uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_uid(), target); + } + + // string token = 2; + if (this->token().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_token().data(), static_cast(this->_internal_token().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.LoginReq.token"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_token(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.LoginReq) + return target; +} + +size_t LoginReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.LoginReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string token = 2; + if (this->token().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_token()); + } + + // int32 uid = 1; + if (this->uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_uid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void LoginReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.LoginReq) + GOOGLE_DCHECK_NE(&from, this); + const LoginReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.LoginReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.LoginReq) + MergeFrom(*source); + } +} + +void LoginReq::MergeFrom(const LoginReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.LoginReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.token().size() > 0) { + _internal_set_token(from._internal_token()); + } + if (from.uid() != 0) { + _internal_set_uid(from._internal_uid()); + } +} + +void LoginReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.LoginReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void LoginReq::CopyFrom(const LoginReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.LoginReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool LoginReq::IsInitialized() const { + return true; +} + +void LoginReq::InternalSwap(LoginReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + token_.Swap(&other->token_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(uid_, other->uid_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata LoginReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void LoginRsp::InitAsDefaultInstance() { +} +class LoginRsp::_Internal { + public: +}; + +LoginRsp::LoginRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.LoginRsp) +} +LoginRsp::LoginRsp(const LoginRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_token().empty()) { + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_token(), + GetArena()); + } + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); + // @@protoc_insertion_point(copy_constructor:message.LoginRsp) +} + +void LoginRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_LoginRsp_message_2eproto.base); + token_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); +} + +LoginRsp::~LoginRsp() { + // @@protoc_insertion_point(destructor:message.LoginRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void LoginRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + token_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void LoginRsp::ArenaDtor(void* object) { + LoginRsp* _this = reinterpret_cast< LoginRsp* >(object); + (void)_this; +} +void LoginRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void LoginRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const LoginRsp& LoginRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_LoginRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void LoginRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.LoginRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* LoginRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string token = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_token(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.LoginRsp.token")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* LoginRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.LoginRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 uid = 2; + if (this->uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_uid(), target); + } + + // string token = 3; + if (this->token().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_token().data(), static_cast(this->_internal_token().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.LoginRsp.token"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_token(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.LoginRsp) + return target; +} + +size_t LoginRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.LoginRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string token = 3; + if (this->token().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_token()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 uid = 2; + if (this->uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_uid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void LoginRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.LoginRsp) + GOOGLE_DCHECK_NE(&from, this); + const LoginRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.LoginRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.LoginRsp) + MergeFrom(*source); + } +} + +void LoginRsp::MergeFrom(const LoginRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.LoginRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.token().size() > 0) { + _internal_set_token(from._internal_token()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.uid() != 0) { + _internal_set_uid(from._internal_uid()); + } +} + +void LoginRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.LoginRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void LoginRsp::CopyFrom(const LoginRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.LoginRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool LoginRsp::IsInitialized() const { + return true; +} + +void LoginRsp::InternalSwap(LoginRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + token_.Swap(&other->token_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(LoginRsp, uid_) + + sizeof(LoginRsp::uid_) + - PROTOBUF_FIELD_OFFSET(LoginRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata LoginRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void AddFriendReq::InitAsDefaultInstance() { +} +class AddFriendReq::_Internal { + public: +}; + +AddFriendReq::AddFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.AddFriendReq) +} +AddFriendReq::AddFriendReq(const AddFriendReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_name().empty()) { + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_name(), + GetArena()); + } + desc_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_desc().empty()) { + desc_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_desc(), + GetArena()); + } + icon_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_icon().empty()) { + icon_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_icon(), + GetArena()); + } + nick_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_nick().empty()) { + nick_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_nick(), + GetArena()); + } + ::memcpy(&applyuid_, &from.applyuid_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&applyuid_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.AddFriendReq) +} + +void AddFriendReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_AddFriendReq_message_2eproto.base); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + desc_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + icon_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + nick_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&applyuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&applyuid_)) + sizeof(touid_)); +} + +AddFriendReq::~AddFriendReq() { + // @@protoc_insertion_point(destructor:message.AddFriendReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void AddFriendReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + desc_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + icon_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + nick_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void AddFriendReq::ArenaDtor(void* object) { + AddFriendReq* _this = reinterpret_cast< AddFriendReq* >(object); + (void)_this; +} +void AddFriendReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void AddFriendReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const AddFriendReq& AddFriendReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_AddFriendReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void AddFriendReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.AddFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + desc_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + icon_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + nick_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&applyuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&applyuid_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* AddFriendReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 applyuid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + applyuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string name = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendReq.name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string desc = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_desc(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendReq.desc")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string icon = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_icon(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendReq.icon")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string nick = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_nick(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendReq.nick")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 sex = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + sex_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* AddFriendReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.AddFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 applyuid = 1; + if (this->applyuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_applyuid(), target); + } + + // string name = 2; + if (this->name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendReq.name"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_name(), target); + } + + // string desc = 3; + if (this->desc().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_desc().data(), static_cast(this->_internal_desc().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendReq.desc"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_desc(), target); + } + + // string icon = 4; + if (this->icon().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_icon().data(), static_cast(this->_internal_icon().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendReq.icon"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_icon(), target); + } + + // string nick = 5; + if (this->nick().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_nick().data(), static_cast(this->_internal_nick().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendReq.nick"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_nick(), target); + } + + // int32 sex = 6; + if (this->sex() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(6, this->_internal_sex(), target); + } + + // int32 touid = 7; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(7, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.AddFriendReq) + return target; +} + +size_t AddFriendReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.AddFriendReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 2; + if (this->name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string desc = 3; + if (this->desc().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_desc()); + } + + // string icon = 4; + if (this->icon().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_icon()); + } + + // string nick = 5; + if (this->nick().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_nick()); + } + + // int32 applyuid = 1; + if (this->applyuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_applyuid()); + } + + // int32 sex = 6; + if (this->sex() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_sex()); + } + + // int32 touid = 7; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void AddFriendReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.AddFriendReq) + GOOGLE_DCHECK_NE(&from, this); + const AddFriendReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.AddFriendReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.AddFriendReq) + MergeFrom(*source); + } +} + +void AddFriendReq::MergeFrom(const AddFriendReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.AddFriendReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.name().size() > 0) { + _internal_set_name(from._internal_name()); + } + if (from.desc().size() > 0) { + _internal_set_desc(from._internal_desc()); + } + if (from.icon().size() > 0) { + _internal_set_icon(from._internal_icon()); + } + if (from.nick().size() > 0) { + _internal_set_nick(from._internal_nick()); + } + if (from.applyuid() != 0) { + _internal_set_applyuid(from._internal_applyuid()); + } + if (from.sex() != 0) { + _internal_set_sex(from._internal_sex()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void AddFriendReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.AddFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void AddFriendReq::CopyFrom(const AddFriendReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.AddFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool AddFriendReq::IsInitialized() const { + return true; +} + +void AddFriendReq::InternalSwap(AddFriendReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + name_.Swap(&other->name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + desc_.Swap(&other->desc_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + icon_.Swap(&other->icon_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + nick_.Swap(&other->nick_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(AddFriendReq, touid_) + + sizeof(AddFriendReq::touid_) + - PROTOBUF_FIELD_OFFSET(AddFriendReq, applyuid_)>( + reinterpret_cast(&applyuid_), + reinterpret_cast(&other->applyuid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata AddFriendReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void AddFriendRsp::InitAsDefaultInstance() { +} +class AddFriendRsp::_Internal { + public: +}; + +AddFriendRsp::AddFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.AddFriendRsp) +} +AddFriendRsp::AddFriendRsp(const AddFriendRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.AddFriendRsp) +} + +void AddFriendRsp::SharedCtor() { + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); +} + +AddFriendRsp::~AddFriendRsp() { + // @@protoc_insertion_point(destructor:message.AddFriendRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void AddFriendRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void AddFriendRsp::ArenaDtor(void* object) { + AddFriendRsp* _this = reinterpret_cast< AddFriendRsp* >(object); + (void)_this; +} +void AddFriendRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void AddFriendRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const AddFriendRsp& AddFriendRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_AddFriendRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void AddFriendRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.AddFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* AddFriendRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 applyuid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + applyuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* AddFriendRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.AddFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 applyuid = 2; + if (this->applyuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_applyuid(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.AddFriendRsp) + return target; +} + +size_t AddFriendRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.AddFriendRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 applyuid = 2; + if (this->applyuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_applyuid()); + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void AddFriendRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.AddFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + const AddFriendRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.AddFriendRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.AddFriendRsp) + MergeFrom(*source); + } +} + +void AddFriendRsp::MergeFrom(const AddFriendRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.AddFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.applyuid() != 0) { + _internal_set_applyuid(from._internal_applyuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void AddFriendRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.AddFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void AddFriendRsp::CopyFrom(const AddFriendRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.AddFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool AddFriendRsp::IsInitialized() const { + return true; +} + +void AddFriendRsp::InternalSwap(AddFriendRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(AddFriendRsp, touid_) + + sizeof(AddFriendRsp::touid_) + - PROTOBUF_FIELD_OFFSET(AddFriendRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata AddFriendRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void RplyFriendReq::InitAsDefaultInstance() { +} +class RplyFriendReq::_Internal { + public: +}; + +RplyFriendReq::RplyFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.RplyFriendReq) +} +RplyFriendReq::RplyFriendReq(const RplyFriendReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&rplyuid_, &from.rplyuid_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&rplyuid_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.RplyFriendReq) +} + +void RplyFriendReq::SharedCtor() { + ::memset(&rplyuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&rplyuid_)) + sizeof(touid_)); +} + +RplyFriendReq::~RplyFriendReq() { + // @@protoc_insertion_point(destructor:message.RplyFriendReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void RplyFriendReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void RplyFriendReq::ArenaDtor(void* object) { + RplyFriendReq* _this = reinterpret_cast< RplyFriendReq* >(object); + (void)_this; +} +void RplyFriendReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void RplyFriendReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const RplyFriendReq& RplyFriendReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_RplyFriendReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void RplyFriendReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.RplyFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&rplyuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&rplyuid_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* RplyFriendReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 rplyuid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + rplyuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // bool agree = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + agree_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* RplyFriendReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.RplyFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 rplyuid = 1; + if (this->rplyuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_rplyuid(), target); + } + + // bool agree = 2; + if (this->agree() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(2, this->_internal_agree(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.RplyFriendReq) + return target; +} + +size_t RplyFriendReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.RplyFriendReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 rplyuid = 1; + if (this->rplyuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_rplyuid()); + } + + // bool agree = 2; + if (this->agree() != 0) { + total_size += 1 + 1; + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void RplyFriendReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.RplyFriendReq) + GOOGLE_DCHECK_NE(&from, this); + const RplyFriendReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.RplyFriendReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.RplyFriendReq) + MergeFrom(*source); + } +} + +void RplyFriendReq::MergeFrom(const RplyFriendReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.RplyFriendReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.rplyuid() != 0) { + _internal_set_rplyuid(from._internal_rplyuid()); + } + if (from.agree() != 0) { + _internal_set_agree(from._internal_agree()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void RplyFriendReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.RplyFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RplyFriendReq::CopyFrom(const RplyFriendReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.RplyFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RplyFriendReq::IsInitialized() const { + return true; +} + +void RplyFriendReq::InternalSwap(RplyFriendReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(RplyFriendReq, touid_) + + sizeof(RplyFriendReq::touid_) + - PROTOBUF_FIELD_OFFSET(RplyFriendReq, rplyuid_)>( + reinterpret_cast(&rplyuid_), + reinterpret_cast(&other->rplyuid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata RplyFriendReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void RplyFriendRsp::InitAsDefaultInstance() { +} +class RplyFriendRsp::_Internal { + public: +}; + +RplyFriendRsp::RplyFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.RplyFriendRsp) +} +RplyFriendRsp::RplyFriendRsp(const RplyFriendRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.RplyFriendRsp) +} + +void RplyFriendRsp::SharedCtor() { + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); +} + +RplyFriendRsp::~RplyFriendRsp() { + // @@protoc_insertion_point(destructor:message.RplyFriendRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void RplyFriendRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void RplyFriendRsp::ArenaDtor(void* object) { + RplyFriendRsp* _this = reinterpret_cast< RplyFriendRsp* >(object); + (void)_this; +} +void RplyFriendRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void RplyFriendRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const RplyFriendRsp& RplyFriendRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_RplyFriendRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void RplyFriendRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.RplyFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* RplyFriendRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 rplyuid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + rplyuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* RplyFriendRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.RplyFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 rplyuid = 2; + if (this->rplyuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_rplyuid(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.RplyFriendRsp) + return target; +} + +size_t RplyFriendRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.RplyFriendRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 rplyuid = 2; + if (this->rplyuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_rplyuid()); + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void RplyFriendRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.RplyFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + const RplyFriendRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.RplyFriendRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.RplyFriendRsp) + MergeFrom(*source); + } +} + +void RplyFriendRsp::MergeFrom(const RplyFriendRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.RplyFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.rplyuid() != 0) { + _internal_set_rplyuid(from._internal_rplyuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void RplyFriendRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.RplyFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void RplyFriendRsp::CopyFrom(const RplyFriendRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.RplyFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool RplyFriendRsp::IsInitialized() const { + return true; +} + +void RplyFriendRsp::InternalSwap(RplyFriendRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(RplyFriendRsp, touid_) + + sizeof(RplyFriendRsp::touid_) + - PROTOBUF_FIELD_OFFSET(RplyFriendRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata RplyFriendRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void SendChatMsgReq::InitAsDefaultInstance() { +} +class SendChatMsgReq::_Internal { + public: +}; + +SendChatMsgReq::SendChatMsgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.SendChatMsgReq) +} +SendChatMsgReq::SendChatMsgReq(const SendChatMsgReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + message_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_message().empty()) { + message_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_message(), + GetArena()); + } + ::memcpy(&fromuid_, &from.fromuid_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.SendChatMsgReq) +} + +void SendChatMsgReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_SendChatMsgReq_message_2eproto.base); + message_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); +} + +SendChatMsgReq::~SendChatMsgReq() { + // @@protoc_insertion_point(destructor:message.SendChatMsgReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void SendChatMsgReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + message_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void SendChatMsgReq::ArenaDtor(void* object) { + SendChatMsgReq* _this = reinterpret_cast< SendChatMsgReq* >(object); + (void)_this; +} +void SendChatMsgReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void SendChatMsgReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const SendChatMsgReq& SendChatMsgReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SendChatMsgReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void SendChatMsgReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.SendChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + message_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SendChatMsgReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 fromuid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string message = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_message(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.SendChatMsgReq.message")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* SendChatMsgReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.SendChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_fromuid(), target); + } + + // int32 touid = 2; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_touid(), target); + } + + // string message = 3; + if (this->message().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_message().data(), static_cast(this->_internal_message().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.SendChatMsgReq.message"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_message(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.SendChatMsgReq) + return target; +} + +size_t SendChatMsgReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.SendChatMsgReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string message = 3; + if (this->message().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_message()); + } + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 2; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void SendChatMsgReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.SendChatMsgReq) + GOOGLE_DCHECK_NE(&from, this); + const SendChatMsgReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.SendChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.SendChatMsgReq) + MergeFrom(*source); + } +} + +void SendChatMsgReq::MergeFrom(const SendChatMsgReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.SendChatMsgReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.message().size() > 0) { + _internal_set_message(from._internal_message()); + } + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void SendChatMsgReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.SendChatMsgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SendChatMsgReq::CopyFrom(const SendChatMsgReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.SendChatMsgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SendChatMsgReq::IsInitialized() const { + return true; +} + +void SendChatMsgReq::InternalSwap(SendChatMsgReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + message_.Swap(&other->message_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(SendChatMsgReq, touid_) + + sizeof(SendChatMsgReq::touid_) + - PROTOBUF_FIELD_OFFSET(SendChatMsgReq, fromuid_)>( + reinterpret_cast(&fromuid_), + reinterpret_cast(&other->fromuid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SendChatMsgReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void SendChatMsgRsp::InitAsDefaultInstance() { +} +class SendChatMsgRsp::_Internal { + public: +}; + +SendChatMsgRsp::SendChatMsgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.SendChatMsgRsp) +} +SendChatMsgRsp::SendChatMsgRsp(const SendChatMsgRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.SendChatMsgRsp) +} + +void SendChatMsgRsp::SharedCtor() { + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); +} + +SendChatMsgRsp::~SendChatMsgRsp() { + // @@protoc_insertion_point(destructor:message.SendChatMsgRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void SendChatMsgRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void SendChatMsgRsp::ArenaDtor(void* object) { + SendChatMsgRsp* _this = reinterpret_cast< SendChatMsgRsp* >(object); + (void)_this; +} +void SendChatMsgRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void SendChatMsgRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const SendChatMsgRsp& SendChatMsgRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_SendChatMsgRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void SendChatMsgRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.SendChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SendChatMsgRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 fromuid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* SendChatMsgRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.SendChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_fromuid(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.SendChatMsgRsp) + return target; +} + +size_t SendChatMsgRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.SendChatMsgRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void SendChatMsgRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.SendChatMsgRsp) + GOOGLE_DCHECK_NE(&from, this); + const SendChatMsgRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.SendChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.SendChatMsgRsp) + MergeFrom(*source); + } +} + +void SendChatMsgRsp::MergeFrom(const SendChatMsgRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.SendChatMsgRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void SendChatMsgRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.SendChatMsgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SendChatMsgRsp::CopyFrom(const SendChatMsgRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.SendChatMsgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SendChatMsgRsp::IsInitialized() const { + return true; +} + +void SendChatMsgRsp::InternalSwap(SendChatMsgRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(SendChatMsgRsp, touid_) + + sizeof(SendChatMsgRsp::touid_) + - PROTOBUF_FIELD_OFFSET(SendChatMsgRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SendChatMsgRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void AddFriendMsg::InitAsDefaultInstance() { +} +class AddFriendMsg::_Internal { + public: +}; + +AddFriendMsg::AddFriendMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.AddFriendMsg) +} +AddFriendMsg::AddFriendMsg(const AddFriendMsg& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + unique_id_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_unique_id().empty()) { + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_unique_id(), + GetArena()); + } + msgcontent_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_msgcontent().empty()) { + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_msgcontent(), + GetArena()); + } + ::memcpy(&sender_id_, &from.sender_id_, + static_cast(reinterpret_cast(&status_) - + reinterpret_cast(&sender_id_)) + sizeof(status_)); + // @@protoc_insertion_point(copy_constructor:message.AddFriendMsg) +} + +void AddFriendMsg::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_AddFriendMsg_message_2eproto.base); + unique_id_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + msgcontent_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&sender_id_, 0, static_cast( + reinterpret_cast(&status_) - + reinterpret_cast(&sender_id_)) + sizeof(status_)); +} + +AddFriendMsg::~AddFriendMsg() { + // @@protoc_insertion_point(destructor:message.AddFriendMsg) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void AddFriendMsg::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + unique_id_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + msgcontent_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void AddFriendMsg::ArenaDtor(void* object) { + AddFriendMsg* _this = reinterpret_cast< AddFriendMsg* >(object); + (void)_this; +} +void AddFriendMsg::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void AddFriendMsg::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const AddFriendMsg& AddFriendMsg::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_AddFriendMsg_message_2eproto.base); + return *internal_default_instance(); +} + + +void AddFriendMsg::Clear() { +// @@protoc_insertion_point(message_clear_start:message.AddFriendMsg) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + unique_id_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + msgcontent_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&sender_id_, 0, static_cast( + reinterpret_cast(&status_) - + reinterpret_cast(&sender_id_)) + sizeof(status_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* AddFriendMsg::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 sender_id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + sender_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string unique_id = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + auto str = _internal_mutable_unique_id(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendMsg.unique_id")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 msg_id = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + msg_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string msgcontent = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_msgcontent(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.AddFriendMsg.msgcontent")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 status = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + status_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* AddFriendMsg::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.AddFriendMsg) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 sender_id = 1; + if (this->sender_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_sender_id(), target); + } + + // string unique_id = 2; + if (this->unique_id().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_unique_id().data(), static_cast(this->_internal_unique_id().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendMsg.unique_id"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_unique_id(), target); + } + + // int32 msg_id = 3; + if (this->msg_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_msg_id(), target); + } + + // int32 thread_id = 4; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_thread_id(), target); + } + + // string msgcontent = 5; + if (this->msgcontent().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_msgcontent().data(), static_cast(this->_internal_msgcontent().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.AddFriendMsg.msgcontent"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_msgcontent(), target); + } + + // int32 status = 6; + if (this->status() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(6, this->_internal_status(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.AddFriendMsg) + return target; +} + +size_t AddFriendMsg::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.AddFriendMsg) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string unique_id = 2; + if (this->unique_id().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_unique_id()); + } + + // string msgcontent = 5; + if (this->msgcontent().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_msgcontent()); + } + + // int32 sender_id = 1; + if (this->sender_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_sender_id()); + } + + // int32 msg_id = 3; + if (this->msg_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_msg_id()); + } + + // int32 thread_id = 4; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + // int32 status = 6; + if (this->status() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_status()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void AddFriendMsg::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.AddFriendMsg) + GOOGLE_DCHECK_NE(&from, this); + const AddFriendMsg* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.AddFriendMsg) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.AddFriendMsg) + MergeFrom(*source); + } +} + +void AddFriendMsg::MergeFrom(const AddFriendMsg& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.AddFriendMsg) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.unique_id().size() > 0) { + _internal_set_unique_id(from._internal_unique_id()); + } + if (from.msgcontent().size() > 0) { + _internal_set_msgcontent(from._internal_msgcontent()); + } + if (from.sender_id() != 0) { + _internal_set_sender_id(from._internal_sender_id()); + } + if (from.msg_id() != 0) { + _internal_set_msg_id(from._internal_msg_id()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } + if (from.status() != 0) { + _internal_set_status(from._internal_status()); + } +} + +void AddFriendMsg::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.AddFriendMsg) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void AddFriendMsg::CopyFrom(const AddFriendMsg& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.AddFriendMsg) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool AddFriendMsg::IsInitialized() const { + return true; +} + +void AddFriendMsg::InternalSwap(AddFriendMsg* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + unique_id_.Swap(&other->unique_id_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + msgcontent_.Swap(&other->msgcontent_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(AddFriendMsg, status_) + + sizeof(AddFriendMsg::status_) + - PROTOBUF_FIELD_OFFSET(AddFriendMsg, sender_id_)>( + reinterpret_cast(&sender_id_), + reinterpret_cast(&other->sender_id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata AddFriendMsg::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void AuthFriendReq::InitAsDefaultInstance() { +} +class AuthFriendReq::_Internal { + public: +}; + +AuthFriendReq::AuthFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + textmsgs_(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.AuthFriendReq) +} +AuthFriendReq::AuthFriendReq(const AuthFriendReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + textmsgs_(from.textmsgs_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&fromuid_, &from.fromuid_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.AuthFriendReq) +} + +void AuthFriendReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_AuthFriendReq_message_2eproto.base); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); +} + +AuthFriendReq::~AuthFriendReq() { + // @@protoc_insertion_point(destructor:message.AuthFriendReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void AuthFriendReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void AuthFriendReq::ArenaDtor(void* object) { + AuthFriendReq* _this = reinterpret_cast< AuthFriendReq* >(object); + (void)_this; +} +void AuthFriendReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void AuthFriendReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const AuthFriendReq& AuthFriendReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_AuthFriendReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void AuthFriendReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.AuthFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + textmsgs_.Clear(); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&fromuid_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* AuthFriendReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 fromuid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // repeated .message.AddFriendMsg textmsgs = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_textmsgs(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr)); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* AuthFriendReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.AuthFriendReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_fromuid(), target); + } + + // int32 touid = 2; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_touid(), target); + } + + // repeated .message.AddFriendMsg textmsgs = 3; + for (unsigned int i = 0, + n = static_cast(this->_internal_textmsgs_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(3, this->_internal_textmsgs(i), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.AuthFriendReq) + return target; +} + +size_t AuthFriendReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.AuthFriendReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .message.AddFriendMsg textmsgs = 3; + total_size += 1UL * this->_internal_textmsgs_size(); + for (const auto& msg : this->textmsgs_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 2; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void AuthFriendReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.AuthFriendReq) + GOOGLE_DCHECK_NE(&from, this); + const AuthFriendReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.AuthFriendReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.AuthFriendReq) + MergeFrom(*source); + } +} + +void AuthFriendReq::MergeFrom(const AuthFriendReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.AuthFriendReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + textmsgs_.MergeFrom(from.textmsgs_); + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void AuthFriendReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.AuthFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void AuthFriendReq::CopyFrom(const AuthFriendReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.AuthFriendReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool AuthFriendReq::IsInitialized() const { + return true; +} + +void AuthFriendReq::InternalSwap(AuthFriendReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + textmsgs_.InternalSwap(&other->textmsgs_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(AuthFriendReq, touid_) + + sizeof(AuthFriendReq::touid_) + - PROTOBUF_FIELD_OFFSET(AuthFriendReq, fromuid_)>( + reinterpret_cast(&fromuid_), + reinterpret_cast(&other->fromuid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata AuthFriendReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void AuthFriendRsp::InitAsDefaultInstance() { +} +class AuthFriendRsp::_Internal { + public: +}; + +AuthFriendRsp::AuthFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.AuthFriendRsp) +} +AuthFriendRsp::AuthFriendRsp(const AuthFriendRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + // @@protoc_insertion_point(copy_constructor:message.AuthFriendRsp) +} + +void AuthFriendRsp::SharedCtor() { + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); +} + +AuthFriendRsp::~AuthFriendRsp() { + // @@protoc_insertion_point(destructor:message.AuthFriendRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void AuthFriendRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void AuthFriendRsp::ArenaDtor(void* object) { + AuthFriendRsp* _this = reinterpret_cast< AuthFriendRsp* >(object); + (void)_this; +} +void AuthFriendRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void AuthFriendRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const AuthFriendRsp& AuthFriendRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_AuthFriendRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void AuthFriendRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.AuthFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&error_, 0, static_cast( + reinterpret_cast(&touid_) - + reinterpret_cast(&error_)) + sizeof(touid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* AuthFriendRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 fromuid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* AuthFriendRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.AuthFriendRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_fromuid(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.AuthFriendRsp) + return target; +} + +size_t AuthFriendRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.AuthFriendRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void AuthFriendRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.AuthFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + const AuthFriendRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.AuthFriendRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.AuthFriendRsp) + MergeFrom(*source); + } +} + +void AuthFriendRsp::MergeFrom(const AuthFriendRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.AuthFriendRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } +} + +void AuthFriendRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.AuthFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void AuthFriendRsp::CopyFrom(const AuthFriendRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.AuthFriendRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool AuthFriendRsp::IsInitialized() const { + return true; +} + +void AuthFriendRsp::InternalSwap(AuthFriendRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(AuthFriendRsp, touid_) + + sizeof(AuthFriendRsp::touid_) + - PROTOBUF_FIELD_OFFSET(AuthFriendRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata AuthFriendRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void TextChatMsgReq::InitAsDefaultInstance() { +} +class TextChatMsgReq::_Internal { + public: +}; + +TextChatMsgReq::TextChatMsgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + textmsgs_(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.TextChatMsgReq) +} +TextChatMsgReq::TextChatMsgReq(const TextChatMsgReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + textmsgs_(from.textmsgs_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&fromuid_, &from.fromuid_, + static_cast(reinterpret_cast(&thread_id_) - + reinterpret_cast(&fromuid_)) + sizeof(thread_id_)); + // @@protoc_insertion_point(copy_constructor:message.TextChatMsgReq) +} + +void TextChatMsgReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_TextChatMsgReq_message_2eproto.base); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&fromuid_)) + sizeof(thread_id_)); +} + +TextChatMsgReq::~TextChatMsgReq() { + // @@protoc_insertion_point(destructor:message.TextChatMsgReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void TextChatMsgReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void TextChatMsgReq::ArenaDtor(void* object) { + TextChatMsgReq* _this = reinterpret_cast< TextChatMsgReq* >(object); + (void)_this; +} +void TextChatMsgReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void TextChatMsgReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const TextChatMsgReq& TextChatMsgReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_TextChatMsgReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void TextChatMsgReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.TextChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + textmsgs_.Clear(); + ::memset(&fromuid_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&fromuid_)) + sizeof(thread_id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* TextChatMsgReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 fromuid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // repeated .message.TextChatData textmsgs = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_textmsgs(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr)); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* TextChatMsgReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.TextChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_fromuid(), target); + } + + // int32 touid = 2; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_touid(), target); + } + + // int32 thread_id = 3; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_thread_id(), target); + } + + // repeated .message.TextChatData textmsgs = 4; + for (unsigned int i = 0, + n = static_cast(this->_internal_textmsgs_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(4, this->_internal_textmsgs(i), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.TextChatMsgReq) + return target; +} + +size_t TextChatMsgReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.TextChatMsgReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .message.TextChatData textmsgs = 4; + total_size += 1UL * this->_internal_textmsgs_size(); + for (const auto& msg : this->textmsgs_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // int32 fromuid = 1; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 2; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + // int32 thread_id = 3; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void TextChatMsgReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.TextChatMsgReq) + GOOGLE_DCHECK_NE(&from, this); + const TextChatMsgReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.TextChatMsgReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.TextChatMsgReq) + MergeFrom(*source); + } +} + +void TextChatMsgReq::MergeFrom(const TextChatMsgReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.TextChatMsgReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + textmsgs_.MergeFrom(from.textmsgs_); + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } +} + +void TextChatMsgReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.TextChatMsgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void TextChatMsgReq::CopyFrom(const TextChatMsgReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.TextChatMsgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool TextChatMsgReq::IsInitialized() const { + return true; +} + +void TextChatMsgReq::InternalSwap(TextChatMsgReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + textmsgs_.InternalSwap(&other->textmsgs_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(TextChatMsgReq, thread_id_) + + sizeof(TextChatMsgReq::thread_id_) + - PROTOBUF_FIELD_OFFSET(TextChatMsgReq, fromuid_)>( + reinterpret_cast(&fromuid_), + reinterpret_cast(&other->fromuid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata TextChatMsgReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void TextChatData::InitAsDefaultInstance() { +} +class TextChatData::_Internal { + public: +}; + +TextChatData::TextChatData(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.TextChatData) +} +TextChatData::TextChatData(const TextChatData& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + unique_id_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_unique_id().empty()) { + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_unique_id(), + GetArena()); + } + msgcontent_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_msgcontent().empty()) { + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_msgcontent(), + GetArena()); + } + chat_time_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_chat_time().empty()) { + chat_time_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_chat_time(), + GetArena()); + } + msg_id_ = from.msg_id_; + // @@protoc_insertion_point(copy_constructor:message.TextChatData) +} + +void TextChatData::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_TextChatData_message_2eproto.base); + unique_id_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + msgcontent_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + chat_time_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + msg_id_ = 0; +} + +TextChatData::~TextChatData() { + // @@protoc_insertion_point(destructor:message.TextChatData) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void TextChatData::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + unique_id_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + msgcontent_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + chat_time_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void TextChatData::ArenaDtor(void* object) { + TextChatData* _this = reinterpret_cast< TextChatData* >(object); + (void)_this; +} +void TextChatData::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void TextChatData::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const TextChatData& TextChatData::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_TextChatData_message_2eproto.base); + return *internal_default_instance(); +} + + +void TextChatData::Clear() { +// @@protoc_insertion_point(message_clear_start:message.TextChatData) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + unique_id_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + msgcontent_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + chat_time_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + msg_id_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* TextChatData::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string unique_id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + auto str = _internal_mutable_unique_id(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.TextChatData.unique_id")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 msg_id = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + msg_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string msgcontent = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + auto str = _internal_mutable_msgcontent(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.TextChatData.msgcontent")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string chat_time = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_chat_time(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.TextChatData.chat_time")); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* TextChatData::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.TextChatData) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string unique_id = 1; + if (this->unique_id().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_unique_id().data(), static_cast(this->_internal_unique_id().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.TextChatData.unique_id"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_unique_id(), target); + } + + // int32 msg_id = 2; + if (this->msg_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_msg_id(), target); + } + + // string msgcontent = 3; + if (this->msgcontent().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_msgcontent().data(), static_cast(this->_internal_msgcontent().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.TextChatData.msgcontent"); + target = stream->WriteStringMaybeAliased( + 3, this->_internal_msgcontent(), target); + } + + // string chat_time = 4; + if (this->chat_time().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_chat_time().data(), static_cast(this->_internal_chat_time().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.TextChatData.chat_time"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_chat_time(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.TextChatData) + return target; +} + +size_t TextChatData::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.TextChatData) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string unique_id = 1; + if (this->unique_id().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_unique_id()); + } + + // string msgcontent = 3; + if (this->msgcontent().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_msgcontent()); + } + + // string chat_time = 4; + if (this->chat_time().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_chat_time()); + } + + // int32 msg_id = 2; + if (this->msg_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_msg_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void TextChatData::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.TextChatData) + GOOGLE_DCHECK_NE(&from, this); + const TextChatData* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.TextChatData) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.TextChatData) + MergeFrom(*source); + } +} + +void TextChatData::MergeFrom(const TextChatData& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.TextChatData) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.unique_id().size() > 0) { + _internal_set_unique_id(from._internal_unique_id()); + } + if (from.msgcontent().size() > 0) { + _internal_set_msgcontent(from._internal_msgcontent()); + } + if (from.chat_time().size() > 0) { + _internal_set_chat_time(from._internal_chat_time()); + } + if (from.msg_id() != 0) { + _internal_set_msg_id(from._internal_msg_id()); + } +} + +void TextChatData::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.TextChatData) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void TextChatData::CopyFrom(const TextChatData& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.TextChatData) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool TextChatData::IsInitialized() const { + return true; +} + +void TextChatData::InternalSwap(TextChatData* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + unique_id_.Swap(&other->unique_id_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + msgcontent_.Swap(&other->msgcontent_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + chat_time_.Swap(&other->chat_time_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + swap(msg_id_, other->msg_id_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata TextChatData::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void TextChatMsgRsp::InitAsDefaultInstance() { +} +class TextChatMsgRsp::_Internal { + public: +}; + +TextChatMsgRsp::TextChatMsgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena), + textmsgs_(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.TextChatMsgRsp) +} +TextChatMsgRsp::TextChatMsgRsp(const TextChatMsgRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + textmsgs_(from.textmsgs_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + // @@protoc_insertion_point(copy_constructor:message.TextChatMsgRsp) +} + +void TextChatMsgRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_TextChatMsgRsp_message_2eproto.base); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); +} + +TextChatMsgRsp::~TextChatMsgRsp() { + // @@protoc_insertion_point(destructor:message.TextChatMsgRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void TextChatMsgRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void TextChatMsgRsp::ArenaDtor(void* object) { + TextChatMsgRsp* _this = reinterpret_cast< TextChatMsgRsp* >(object); + (void)_this; +} +void TextChatMsgRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void TextChatMsgRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const TextChatMsgRsp& TextChatMsgRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_TextChatMsgRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void TextChatMsgRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.TextChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + textmsgs_.Clear(); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* TextChatMsgRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 fromuid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + fromuid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 touid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + touid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // repeated .message.TextChatData textmsgs = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_textmsgs(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr)); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* TextChatMsgRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.TextChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_fromuid(), target); + } + + // int32 touid = 3; + if (this->touid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_touid(), target); + } + + // int32 thread_id = 4; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_thread_id(), target); + } + + // repeated .message.TextChatData textmsgs = 5; + for (unsigned int i = 0, + n = static_cast(this->_internal_textmsgs_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, this->_internal_textmsgs(i), target, stream); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.TextChatMsgRsp) + return target; +} + +size_t TextChatMsgRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.TextChatMsgRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .message.TextChatData textmsgs = 5; + total_size += 1UL * this->_internal_textmsgs_size(); + for (const auto& msg : this->textmsgs_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 fromuid = 2; + if (this->fromuid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_fromuid()); + } + + // int32 touid = 3; + if (this->touid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_touid()); + } + + // int32 thread_id = 4; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void TextChatMsgRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.TextChatMsgRsp) + GOOGLE_DCHECK_NE(&from, this); + const TextChatMsgRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.TextChatMsgRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.TextChatMsgRsp) + MergeFrom(*source); + } +} + +void TextChatMsgRsp::MergeFrom(const TextChatMsgRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.TextChatMsgRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + textmsgs_.MergeFrom(from.textmsgs_); + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.fromuid() != 0) { + _internal_set_fromuid(from._internal_fromuid()); + } + if (from.touid() != 0) { + _internal_set_touid(from._internal_touid()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } +} + +void TextChatMsgRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.TextChatMsgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void TextChatMsgRsp::CopyFrom(const TextChatMsgRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.TextChatMsgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool TextChatMsgRsp::IsInitialized() const { + return true; +} + +void TextChatMsgRsp::InternalSwap(TextChatMsgRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + textmsgs_.InternalSwap(&other->textmsgs_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(TextChatMsgRsp, thread_id_) + + sizeof(TextChatMsgRsp::thread_id_) + - PROTOBUF_FIELD_OFFSET(TextChatMsgRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata TextChatMsgRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void KickUserReq::InitAsDefaultInstance() { +} +class KickUserReq::_Internal { + public: +}; + +KickUserReq::KickUserReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.KickUserReq) +} +KickUserReq::KickUserReq(const KickUserReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + uid_ = from.uid_; + // @@protoc_insertion_point(copy_constructor:message.KickUserReq) +} + +void KickUserReq::SharedCtor() { + uid_ = 0; +} + +KickUserReq::~KickUserReq() { + // @@protoc_insertion_point(destructor:message.KickUserReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void KickUserReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void KickUserReq::ArenaDtor(void* object) { + KickUserReq* _this = reinterpret_cast< KickUserReq* >(object); + (void)_this; +} +void KickUserReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void KickUserReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const KickUserReq& KickUserReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_KickUserReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void KickUserReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.KickUserReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + uid_ = 0; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* KickUserReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* KickUserReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.KickUserReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 uid = 1; + if (this->uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_uid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.KickUserReq) + return target; +} + +size_t KickUserReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.KickUserReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 uid = 1; + if (this->uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_uid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void KickUserReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.KickUserReq) + GOOGLE_DCHECK_NE(&from, this); + const KickUserReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.KickUserReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.KickUserReq) + MergeFrom(*source); + } +} + +void KickUserReq::MergeFrom(const KickUserReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.KickUserReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.uid() != 0) { + _internal_set_uid(from._internal_uid()); + } +} + +void KickUserReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.KickUserReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void KickUserReq::CopyFrom(const KickUserReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.KickUserReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool KickUserReq::IsInitialized() const { + return true; +} + +void KickUserReq::InternalSwap(KickUserReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + swap(uid_, other->uid_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata KickUserReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void KickUserRsp::InitAsDefaultInstance() { +} +class KickUserRsp::_Internal { + public: +}; + +KickUserRsp::KickUserRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.KickUserRsp) +} +KickUserRsp::KickUserRsp(const KickUserRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); + // @@protoc_insertion_point(copy_constructor:message.KickUserRsp) +} + +void KickUserRsp::SharedCtor() { + ::memset(&error_, 0, static_cast( + reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); +} + +KickUserRsp::~KickUserRsp() { + // @@protoc_insertion_point(destructor:message.KickUserRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void KickUserRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); +} + +void KickUserRsp::ArenaDtor(void* object) { + KickUserRsp* _this = reinterpret_cast< KickUserRsp* >(object); + (void)_this; +} +void KickUserRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void KickUserRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const KickUserRsp& KickUserRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_KickUserRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void KickUserRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.KickUserRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&error_, 0, static_cast( + reinterpret_cast(&uid_) - + reinterpret_cast(&error_)) + sizeof(uid_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* KickUserRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* KickUserRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.KickUserRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 uid = 2; + if (this->uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_uid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.KickUserRsp) + return target; +} + +size_t KickUserRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.KickUserRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 uid = 2; + if (this->uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_uid()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void KickUserRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.KickUserRsp) + GOOGLE_DCHECK_NE(&from, this); + const KickUserRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.KickUserRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.KickUserRsp) + MergeFrom(*source); + } +} + +void KickUserRsp::MergeFrom(const KickUserRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.KickUserRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.uid() != 0) { + _internal_set_uid(from._internal_uid()); + } +} + +void KickUserRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.KickUserRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void KickUserRsp::CopyFrom(const KickUserRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.KickUserRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool KickUserRsp::IsInitialized() const { + return true; +} + +void KickUserRsp::InternalSwap(KickUserRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(KickUserRsp, uid_) + + sizeof(KickUserRsp::uid_) + - PROTOBUF_FIELD_OFFSET(KickUserRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata KickUserRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void NotifyChatImgReq::InitAsDefaultInstance() { +} +class NotifyChatImgReq::_Internal { + public: +}; + +NotifyChatImgReq::NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgReq) +} +NotifyChatImgReq::NotifyChatImgReq(const NotifyChatImgReq& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&from_uid_, &from.from_uid_, + static_cast(reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgReq) +} + +void NotifyChatImgReq::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgReq_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); +} + +NotifyChatImgReq::~NotifyChatImgReq() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgReq) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgReq::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgReq::ArenaDtor(void* object) { + NotifyChatImgReq* _this = reinterpret_cast< NotifyChatImgReq* >(object); + (void)_this; +} +void NotifyChatImgReq::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgReq::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgReq& NotifyChatImgReq::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgReq_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgReq::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&from_uid_, 0, static_cast( + reinterpret_cast(&total_size_) - + reinterpret_cast(&from_uid_)) + sizeof(total_size_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgReq::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 from_uid = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgReq.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgReq::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_from_uid(), target); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_to_uid(), target); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_message_id(), target); + } + + // string file_name = 4; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgReq.file_name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_file_name(), target); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(5, this->_internal_total_size(), target); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(6, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgReq) + return target; +} + +size_t NotifyChatImgReq::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgReq) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 4; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 from_uid = 1; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 2; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 3; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int32 thread_id = 6; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + // int64 total_size = 5; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgReq::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgReq* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgReq) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgReq) + MergeFrom(*source); + } +} + +void NotifyChatImgReq::MergeFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgReq) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } +} + +void NotifyChatImgReq::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgReq::CopyFrom(const NotifyChatImgReq& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgReq) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgReq::IsInitialized() const { + return true; +} + +void NotifyChatImgReq::InternalSwap(NotifyChatImgReq* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, total_size_) + + sizeof(NotifyChatImgReq::total_size_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgReq, from_uid_)>( + reinterpret_cast(&from_uid_), + reinterpret_cast(&other->from_uid_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgReq::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void NotifyChatImgRsp::InitAsDefaultInstance() { +} +class NotifyChatImgRsp::_Internal { + public: +}; + +NotifyChatImgRsp::NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:message.NotifyChatImgRsp) +} +NotifyChatImgRsp::NotifyChatImgRsp(const NotifyChatImgRsp& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from._internal_file_name().empty()) { + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from._internal_file_name(), + GetArena()); + } + ::memcpy(&error_, &from.error_, + static_cast(reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + // @@protoc_insertion_point(copy_constructor:message.NotifyChatImgRsp) +} + +void NotifyChatImgRsp::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_NotifyChatImgRsp_message_2eproto.base); + file_name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); +} + +NotifyChatImgRsp::~NotifyChatImgRsp() { + // @@protoc_insertion_point(destructor:message.NotifyChatImgRsp) + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +void NotifyChatImgRsp::SharedDtor() { + GOOGLE_DCHECK(GetArena() == nullptr); + file_name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void NotifyChatImgRsp::ArenaDtor(void* object) { + NotifyChatImgRsp* _this = reinterpret_cast< NotifyChatImgRsp* >(object); + (void)_this; +} +void NotifyChatImgRsp::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void NotifyChatImgRsp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const NotifyChatImgRsp& NotifyChatImgRsp::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_NotifyChatImgRsp_message_2eproto.base); + return *internal_default_instance(); +} + + +void NotifyChatImgRsp::Clear() { +// @@protoc_insertion_point(message_clear_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::memset(&error_, 0, static_cast( + reinterpret_cast(&thread_id_) - + reinterpret_cast(&error_)) + sizeof(thread_id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* NotifyChatImgRsp::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + ::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena(); (void)arena; + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // int32 error = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + error_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 from_uid = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + from_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 to_uid = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + to_uid_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 message_id = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 32)) { + message_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string file_name = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 42)) { + auto str = _internal_mutable_file_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "message.NotifyChatImgRsp.file_name")); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int64 total_size = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 48)) { + total_size_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // int32 thread_id = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 56)) { + thread_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} + +::PROTOBUF_NAMESPACE_ID::uint8* NotifyChatImgRsp::_InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int32 error = 1; + if (this->error() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(1, this->_internal_error(), target); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(2, this->_internal_from_uid(), target); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(3, this->_internal_to_uid(), target); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(4, this->_internal_message_id(), target); + } + + // string file_name = 5; + if (this->file_name().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_file_name().data(), static_cast(this->_internal_file_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "message.NotifyChatImgRsp.file_name"); + target = stream->WriteStringMaybeAliased( + 5, this->_internal_file_name(), target); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt64ToArray(6, this->_internal_total_size(), target); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteInt32ToArray(7, this->_internal_thread_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:message.NotifyChatImgRsp) + return target; +} + +size_t NotifyChatImgRsp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:message.NotifyChatImgRsp) + size_t total_size = 0; + + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string file_name = 5; + if (this->file_name().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_file_name()); + } + + // int32 error = 1; + if (this->error() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_error()); + } + + // int32 from_uid = 2; + if (this->from_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_from_uid()); + } + + // int32 to_uid = 3; + if (this->to_uid() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_to_uid()); + } + + // int32 message_id = 4; + if (this->message_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_message_id()); + } + + // int64 total_size = 6; + if (this->total_size() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int64Size( + this->_internal_total_size()); + } + + // int32 thread_id = 7; + if (this->thread_id() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + this->_internal_thread_id()); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize( + _internal_metadata_, total_size, &_cached_size_); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void NotifyChatImgRsp::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + const NotifyChatImgRsp* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:message.NotifyChatImgRsp) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:message.NotifyChatImgRsp) + MergeFrom(*source); + } +} + +void NotifyChatImgRsp::MergeFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:message.NotifyChatImgRsp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + _internal_set_file_name(from._internal_file_name()); + } + if (from.error() != 0) { + _internal_set_error(from._internal_error()); + } + if (from.from_uid() != 0) { + _internal_set_from_uid(from._internal_from_uid()); + } + if (from.to_uid() != 0) { + _internal_set_to_uid(from._internal_to_uid()); + } + if (from.message_id() != 0) { + _internal_set_message_id(from._internal_message_id()); + } + if (from.total_size() != 0) { + _internal_set_total_size(from._internal_total_size()); + } + if (from.thread_id() != 0) { + _internal_set_thread_id(from._internal_thread_id()); + } +} + +void NotifyChatImgRsp::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void NotifyChatImgRsp::CopyFrom(const NotifyChatImgRsp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:message.NotifyChatImgRsp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool NotifyChatImgRsp::IsInitialized() const { + return true; +} + +void NotifyChatImgRsp::InternalSwap(NotifyChatImgRsp* other) { + using std::swap; + _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_); + file_name_.Swap(&other->file_name_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, thread_id_) + + sizeof(NotifyChatImgRsp::thread_id_) + - PROTOBUF_FIELD_OFFSET(NotifyChatImgRsp, error_)>( + reinterpret_cast(&error_), + reinterpret_cast(&other->error_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata NotifyChatImgRsp::GetMetadata() const { + return GetMetadataStatic(); +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace message +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::message::GetVarifyReq* Arena::CreateMaybeMessage< ::message::GetVarifyReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::GetVarifyReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::GetVarifyRsp* Arena::CreateMaybeMessage< ::message::GetVarifyRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::GetVarifyRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::GetChatServerReq* Arena::CreateMaybeMessage< ::message::GetChatServerReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::GetChatServerReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::GetChatServerRsp* Arena::CreateMaybeMessage< ::message::GetChatServerRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::GetChatServerRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::LoginReq* Arena::CreateMaybeMessage< ::message::LoginReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::LoginReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::LoginRsp* Arena::CreateMaybeMessage< ::message::LoginRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::LoginRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::AddFriendReq* Arena::CreateMaybeMessage< ::message::AddFriendReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::AddFriendReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::AddFriendRsp* Arena::CreateMaybeMessage< ::message::AddFriendRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::AddFriendRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::RplyFriendReq* Arena::CreateMaybeMessage< ::message::RplyFriendReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::RplyFriendReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::RplyFriendRsp* Arena::CreateMaybeMessage< ::message::RplyFriendRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::RplyFriendRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::SendChatMsgReq* Arena::CreateMaybeMessage< ::message::SendChatMsgReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::SendChatMsgReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::SendChatMsgRsp* Arena::CreateMaybeMessage< ::message::SendChatMsgRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::SendChatMsgRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::AddFriendMsg* Arena::CreateMaybeMessage< ::message::AddFriendMsg >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::AddFriendMsg >(arena); +} +template<> PROTOBUF_NOINLINE ::message::AuthFriendReq* Arena::CreateMaybeMessage< ::message::AuthFriendReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::AuthFriendReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::AuthFriendRsp* Arena::CreateMaybeMessage< ::message::AuthFriendRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::AuthFriendRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::TextChatMsgReq* Arena::CreateMaybeMessage< ::message::TextChatMsgReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::TextChatMsgReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::TextChatData* Arena::CreateMaybeMessage< ::message::TextChatData >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::TextChatData >(arena); +} +template<> PROTOBUF_NOINLINE ::message::TextChatMsgRsp* Arena::CreateMaybeMessage< ::message::TextChatMsgRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::TextChatMsgRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::KickUserReq* Arena::CreateMaybeMessage< ::message::KickUserReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::KickUserReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::KickUserRsp* Arena::CreateMaybeMessage< ::message::KickUserRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::KickUserRsp >(arena); +} +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgReq* Arena::CreateMaybeMessage< ::message::NotifyChatImgReq >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgReq >(arena); +} +template<> PROTOBUF_NOINLINE ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage< ::message::NotifyChatImgRsp >(Arena* arena) { + return Arena::CreateMessageInternal< ::message::NotifyChatImgRsp >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/server/ResourceServer/message.pb.h b/server/ResourceServer/message.pb.h new file mode 100644 index 0000000..426e615 --- /dev/null +++ b/server/ResourceServer/message.pb.h @@ -0,0 +1,6522 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: message.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_message_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_message_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3013000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3013000 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_message_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_message_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[22] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_message_2eproto; +namespace message { +class AddFriendMsg; +class AddFriendMsgDefaultTypeInternal; +extern AddFriendMsgDefaultTypeInternal _AddFriendMsg_default_instance_; +class AddFriendReq; +class AddFriendReqDefaultTypeInternal; +extern AddFriendReqDefaultTypeInternal _AddFriendReq_default_instance_; +class AddFriendRsp; +class AddFriendRspDefaultTypeInternal; +extern AddFriendRspDefaultTypeInternal _AddFriendRsp_default_instance_; +class AuthFriendReq; +class AuthFriendReqDefaultTypeInternal; +extern AuthFriendReqDefaultTypeInternal _AuthFriendReq_default_instance_; +class AuthFriendRsp; +class AuthFriendRspDefaultTypeInternal; +extern AuthFriendRspDefaultTypeInternal _AuthFriendRsp_default_instance_; +class GetChatServerReq; +class GetChatServerReqDefaultTypeInternal; +extern GetChatServerReqDefaultTypeInternal _GetChatServerReq_default_instance_; +class GetChatServerRsp; +class GetChatServerRspDefaultTypeInternal; +extern GetChatServerRspDefaultTypeInternal _GetChatServerRsp_default_instance_; +class GetVarifyReq; +class GetVarifyReqDefaultTypeInternal; +extern GetVarifyReqDefaultTypeInternal _GetVarifyReq_default_instance_; +class GetVarifyRsp; +class GetVarifyRspDefaultTypeInternal; +extern GetVarifyRspDefaultTypeInternal _GetVarifyRsp_default_instance_; +class KickUserReq; +class KickUserReqDefaultTypeInternal; +extern KickUserReqDefaultTypeInternal _KickUserReq_default_instance_; +class KickUserRsp; +class KickUserRspDefaultTypeInternal; +extern KickUserRspDefaultTypeInternal _KickUserRsp_default_instance_; +class LoginReq; +class LoginReqDefaultTypeInternal; +extern LoginReqDefaultTypeInternal _LoginReq_default_instance_; +class LoginRsp; +class LoginRspDefaultTypeInternal; +extern LoginRspDefaultTypeInternal _LoginRsp_default_instance_; +class NotifyChatImgReq; +class NotifyChatImgReqDefaultTypeInternal; +extern NotifyChatImgReqDefaultTypeInternal _NotifyChatImgReq_default_instance_; +class NotifyChatImgRsp; +class NotifyChatImgRspDefaultTypeInternal; +extern NotifyChatImgRspDefaultTypeInternal _NotifyChatImgRsp_default_instance_; +class RplyFriendReq; +class RplyFriendReqDefaultTypeInternal; +extern RplyFriendReqDefaultTypeInternal _RplyFriendReq_default_instance_; +class RplyFriendRsp; +class RplyFriendRspDefaultTypeInternal; +extern RplyFriendRspDefaultTypeInternal _RplyFriendRsp_default_instance_; +class SendChatMsgReq; +class SendChatMsgReqDefaultTypeInternal; +extern SendChatMsgReqDefaultTypeInternal _SendChatMsgReq_default_instance_; +class SendChatMsgRsp; +class SendChatMsgRspDefaultTypeInternal; +extern SendChatMsgRspDefaultTypeInternal _SendChatMsgRsp_default_instance_; +class TextChatData; +class TextChatDataDefaultTypeInternal; +extern TextChatDataDefaultTypeInternal _TextChatData_default_instance_; +class TextChatMsgReq; +class TextChatMsgReqDefaultTypeInternal; +extern TextChatMsgReqDefaultTypeInternal _TextChatMsgReq_default_instance_; +class TextChatMsgRsp; +class TextChatMsgRspDefaultTypeInternal; +extern TextChatMsgRspDefaultTypeInternal _TextChatMsgRsp_default_instance_; +} // namespace message +PROTOBUF_NAMESPACE_OPEN +template<> ::message::AddFriendMsg* Arena::CreateMaybeMessage<::message::AddFriendMsg>(Arena*); +template<> ::message::AddFriendReq* Arena::CreateMaybeMessage<::message::AddFriendReq>(Arena*); +template<> ::message::AddFriendRsp* Arena::CreateMaybeMessage<::message::AddFriendRsp>(Arena*); +template<> ::message::AuthFriendReq* Arena::CreateMaybeMessage<::message::AuthFriendReq>(Arena*); +template<> ::message::AuthFriendRsp* Arena::CreateMaybeMessage<::message::AuthFriendRsp>(Arena*); +template<> ::message::GetChatServerReq* Arena::CreateMaybeMessage<::message::GetChatServerReq>(Arena*); +template<> ::message::GetChatServerRsp* Arena::CreateMaybeMessage<::message::GetChatServerRsp>(Arena*); +template<> ::message::GetVarifyReq* Arena::CreateMaybeMessage<::message::GetVarifyReq>(Arena*); +template<> ::message::GetVarifyRsp* Arena::CreateMaybeMessage<::message::GetVarifyRsp>(Arena*); +template<> ::message::KickUserReq* Arena::CreateMaybeMessage<::message::KickUserReq>(Arena*); +template<> ::message::KickUserRsp* Arena::CreateMaybeMessage<::message::KickUserRsp>(Arena*); +template<> ::message::LoginReq* Arena::CreateMaybeMessage<::message::LoginReq>(Arena*); +template<> ::message::LoginRsp* Arena::CreateMaybeMessage<::message::LoginRsp>(Arena*); +template<> ::message::NotifyChatImgReq* Arena::CreateMaybeMessage<::message::NotifyChatImgReq>(Arena*); +template<> ::message::NotifyChatImgRsp* Arena::CreateMaybeMessage<::message::NotifyChatImgRsp>(Arena*); +template<> ::message::RplyFriendReq* Arena::CreateMaybeMessage<::message::RplyFriendReq>(Arena*); +template<> ::message::RplyFriendRsp* Arena::CreateMaybeMessage<::message::RplyFriendRsp>(Arena*); +template<> ::message::SendChatMsgReq* Arena::CreateMaybeMessage<::message::SendChatMsgReq>(Arena*); +template<> ::message::SendChatMsgRsp* Arena::CreateMaybeMessage<::message::SendChatMsgRsp>(Arena*); +template<> ::message::TextChatData* Arena::CreateMaybeMessage<::message::TextChatData>(Arena*); +template<> ::message::TextChatMsgReq* Arena::CreateMaybeMessage<::message::TextChatMsgReq>(Arena*); +template<> ::message::TextChatMsgRsp* Arena::CreateMaybeMessage<::message::TextChatMsgRsp>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +namespace message { + +// =================================================================== + +class GetVarifyReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.GetVarifyReq) */ { + public: + inline GetVarifyReq() : GetVarifyReq(nullptr) {} + virtual ~GetVarifyReq(); + + GetVarifyReq(const GetVarifyReq& from); + GetVarifyReq(GetVarifyReq&& from) noexcept + : GetVarifyReq() { + *this = ::std::move(from); + } + + inline GetVarifyReq& operator=(const GetVarifyReq& from) { + CopyFrom(from); + return *this; + } + inline GetVarifyReq& operator=(GetVarifyReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GetVarifyReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const GetVarifyReq* internal_default_instance() { + return reinterpret_cast( + &_GetVarifyReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(GetVarifyReq& a, GetVarifyReq& b) { + a.Swap(&b); + } + inline void Swap(GetVarifyReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetVarifyReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline GetVarifyReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + GetVarifyReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const GetVarifyReq& from); + void MergeFrom(const GetVarifyReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GetVarifyReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.GetVarifyReq"; + } + protected: + explicit GetVarifyReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kEmailFieldNumber = 1, + }; + // string email = 1; + void clear_email(); + const std::string& email() const; + void set_email(const std::string& value); + void set_email(std::string&& value); + void set_email(const char* value); + void set_email(const char* value, size_t size); + std::string* mutable_email(); + std::string* release_email(); + void set_allocated_email(std::string* email); + private: + const std::string& _internal_email() const; + void _internal_set_email(const std::string& value); + std::string* _internal_mutable_email(); + public: + + // @@protoc_insertion_point(class_scope:message.GetVarifyReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr email_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class GetVarifyRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.GetVarifyRsp) */ { + public: + inline GetVarifyRsp() : GetVarifyRsp(nullptr) {} + virtual ~GetVarifyRsp(); + + GetVarifyRsp(const GetVarifyRsp& from); + GetVarifyRsp(GetVarifyRsp&& from) noexcept + : GetVarifyRsp() { + *this = ::std::move(from); + } + + inline GetVarifyRsp& operator=(const GetVarifyRsp& from) { + CopyFrom(from); + return *this; + } + inline GetVarifyRsp& operator=(GetVarifyRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GetVarifyRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const GetVarifyRsp* internal_default_instance() { + return reinterpret_cast( + &_GetVarifyRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(GetVarifyRsp& a, GetVarifyRsp& b) { + a.Swap(&b); + } + inline void Swap(GetVarifyRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetVarifyRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline GetVarifyRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + GetVarifyRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const GetVarifyRsp& from); + void MergeFrom(const GetVarifyRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GetVarifyRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.GetVarifyRsp"; + } + protected: + explicit GetVarifyRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kEmailFieldNumber = 2, + kCodeFieldNumber = 3, + kErrorFieldNumber = 1, + }; + // string email = 2; + void clear_email(); + const std::string& email() const; + void set_email(const std::string& value); + void set_email(std::string&& value); + void set_email(const char* value); + void set_email(const char* value, size_t size); + std::string* mutable_email(); + std::string* release_email(); + void set_allocated_email(std::string* email); + private: + const std::string& _internal_email() const; + void _internal_set_email(const std::string& value); + std::string* _internal_mutable_email(); + public: + + // string code = 3; + void clear_code(); + const std::string& code() const; + void set_code(const std::string& value); + void set_code(std::string&& value); + void set_code(const char* value); + void set_code(const char* value, size_t size); + std::string* mutable_code(); + std::string* release_code(); + void set_allocated_code(std::string* code); + private: + const std::string& _internal_code() const; + void _internal_set_code(const std::string& value); + std::string* _internal_mutable_code(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.GetVarifyRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr email_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr code_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class GetChatServerReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.GetChatServerReq) */ { + public: + inline GetChatServerReq() : GetChatServerReq(nullptr) {} + virtual ~GetChatServerReq(); + + GetChatServerReq(const GetChatServerReq& from); + GetChatServerReq(GetChatServerReq&& from) noexcept + : GetChatServerReq() { + *this = ::std::move(from); + } + + inline GetChatServerReq& operator=(const GetChatServerReq& from) { + CopyFrom(from); + return *this; + } + inline GetChatServerReq& operator=(GetChatServerReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GetChatServerReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const GetChatServerReq* internal_default_instance() { + return reinterpret_cast( + &_GetChatServerReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(GetChatServerReq& a, GetChatServerReq& b) { + a.Swap(&b); + } + inline void Swap(GetChatServerReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetChatServerReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline GetChatServerReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + GetChatServerReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const GetChatServerReq& from); + void MergeFrom(const GetChatServerReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GetChatServerReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.GetChatServerReq"; + } + protected: + explicit GetChatServerReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUidFieldNumber = 1, + }; + // int32 uid = 1; + void clear_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 uid() const; + void set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_uid() const; + void _internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.GetChatServerReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 uid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class GetChatServerRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.GetChatServerRsp) */ { + public: + inline GetChatServerRsp() : GetChatServerRsp(nullptr) {} + virtual ~GetChatServerRsp(); + + GetChatServerRsp(const GetChatServerRsp& from); + GetChatServerRsp(GetChatServerRsp&& from) noexcept + : GetChatServerRsp() { + *this = ::std::move(from); + } + + inline GetChatServerRsp& operator=(const GetChatServerRsp& from) { + CopyFrom(from); + return *this; + } + inline GetChatServerRsp& operator=(GetChatServerRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const GetChatServerRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const GetChatServerRsp* internal_default_instance() { + return reinterpret_cast( + &_GetChatServerRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(GetChatServerRsp& a, GetChatServerRsp& b) { + a.Swap(&b); + } + inline void Swap(GetChatServerRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(GetChatServerRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline GetChatServerRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + GetChatServerRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const GetChatServerRsp& from); + void MergeFrom(const GetChatServerRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(GetChatServerRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.GetChatServerRsp"; + } + protected: + explicit GetChatServerRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kHostFieldNumber = 2, + kPortFieldNumber = 3, + kTokenFieldNumber = 4, + kErrorFieldNumber = 1, + }; + // string host = 2; + void clear_host(); + const std::string& host() const; + void set_host(const std::string& value); + void set_host(std::string&& value); + void set_host(const char* value); + void set_host(const char* value, size_t size); + std::string* mutable_host(); + std::string* release_host(); + void set_allocated_host(std::string* host); + private: + const std::string& _internal_host() const; + void _internal_set_host(const std::string& value); + std::string* _internal_mutable_host(); + public: + + // string port = 3; + void clear_port(); + const std::string& port() const; + void set_port(const std::string& value); + void set_port(std::string&& value); + void set_port(const char* value); + void set_port(const char* value, size_t size); + std::string* mutable_port(); + std::string* release_port(); + void set_allocated_port(std::string* port); + private: + const std::string& _internal_port() const; + void _internal_set_port(const std::string& value); + std::string* _internal_mutable_port(); + public: + + // string token = 4; + void clear_token(); + const std::string& token() const; + void set_token(const std::string& value); + void set_token(std::string&& value); + void set_token(const char* value); + void set_token(const char* value, size_t size); + std::string* mutable_token(); + std::string* release_token(); + void set_allocated_token(std::string* token); + private: + const std::string& _internal_token() const; + void _internal_set_token(const std::string& value); + std::string* _internal_mutable_token(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.GetChatServerRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr host_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr port_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr token_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class LoginReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.LoginReq) */ { + public: + inline LoginReq() : LoginReq(nullptr) {} + virtual ~LoginReq(); + + LoginReq(const LoginReq& from); + LoginReq(LoginReq&& from) noexcept + : LoginReq() { + *this = ::std::move(from); + } + + inline LoginReq& operator=(const LoginReq& from) { + CopyFrom(from); + return *this; + } + inline LoginReq& operator=(LoginReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const LoginReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const LoginReq* internal_default_instance() { + return reinterpret_cast( + &_LoginReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 4; + + friend void swap(LoginReq& a, LoginReq& b) { + a.Swap(&b); + } + inline void Swap(LoginReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(LoginReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline LoginReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + LoginReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const LoginReq& from); + void MergeFrom(const LoginReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(LoginReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.LoginReq"; + } + protected: + explicit LoginReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTokenFieldNumber = 2, + kUidFieldNumber = 1, + }; + // string token = 2; + void clear_token(); + const std::string& token() const; + void set_token(const std::string& value); + void set_token(std::string&& value); + void set_token(const char* value); + void set_token(const char* value, size_t size); + std::string* mutable_token(); + std::string* release_token(); + void set_allocated_token(std::string* token); + private: + const std::string& _internal_token() const; + void _internal_set_token(const std::string& value); + std::string* _internal_mutable_token(); + public: + + // int32 uid = 1; + void clear_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 uid() const; + void set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_uid() const; + void _internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.LoginReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr token_; + ::PROTOBUF_NAMESPACE_ID::int32 uid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class LoginRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.LoginRsp) */ { + public: + inline LoginRsp() : LoginRsp(nullptr) {} + virtual ~LoginRsp(); + + LoginRsp(const LoginRsp& from); + LoginRsp(LoginRsp&& from) noexcept + : LoginRsp() { + *this = ::std::move(from); + } + + inline LoginRsp& operator=(const LoginRsp& from) { + CopyFrom(from); + return *this; + } + inline LoginRsp& operator=(LoginRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const LoginRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const LoginRsp* internal_default_instance() { + return reinterpret_cast( + &_LoginRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 5; + + friend void swap(LoginRsp& a, LoginRsp& b) { + a.Swap(&b); + } + inline void Swap(LoginRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(LoginRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline LoginRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + LoginRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const LoginRsp& from); + void MergeFrom(const LoginRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(LoginRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.LoginRsp"; + } + protected: + explicit LoginRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTokenFieldNumber = 3, + kErrorFieldNumber = 1, + kUidFieldNumber = 2, + }; + // string token = 3; + void clear_token(); + const std::string& token() const; + void set_token(const std::string& value); + void set_token(std::string&& value); + void set_token(const char* value); + void set_token(const char* value, size_t size); + std::string* mutable_token(); + std::string* release_token(); + void set_allocated_token(std::string* token); + private: + const std::string& _internal_token() const; + void _internal_set_token(const std::string& value); + std::string* _internal_mutable_token(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 uid = 2; + void clear_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 uid() const; + void set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_uid() const; + void _internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.LoginRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr token_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 uid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class AddFriendReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.AddFriendReq) */ { + public: + inline AddFriendReq() : AddFriendReq(nullptr) {} + virtual ~AddFriendReq(); + + AddFriendReq(const AddFriendReq& from); + AddFriendReq(AddFriendReq&& from) noexcept + : AddFriendReq() { + *this = ::std::move(from); + } + + inline AddFriendReq& operator=(const AddFriendReq& from) { + CopyFrom(from); + return *this; + } + inline AddFriendReq& operator=(AddFriendReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const AddFriendReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const AddFriendReq* internal_default_instance() { + return reinterpret_cast( + &_AddFriendReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 6; + + friend void swap(AddFriendReq& a, AddFriendReq& b) { + a.Swap(&b); + } + inline void Swap(AddFriendReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AddFriendReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline AddFriendReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + AddFriendReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const AddFriendReq& from); + void MergeFrom(const AddFriendReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(AddFriendReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.AddFriendReq"; + } + protected: + explicit AddFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 2, + kDescFieldNumber = 3, + kIconFieldNumber = 4, + kNickFieldNumber = 5, + kApplyuidFieldNumber = 1, + kSexFieldNumber = 6, + kTouidFieldNumber = 7, + }; + // string name = 2; + void clear_name(); + const std::string& name() const; + void set_name(const std::string& value); + void set_name(std::string&& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + std::string* mutable_name(); + std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string desc = 3; + void clear_desc(); + const std::string& desc() const; + void set_desc(const std::string& value); + void set_desc(std::string&& value); + void set_desc(const char* value); + void set_desc(const char* value, size_t size); + std::string* mutable_desc(); + std::string* release_desc(); + void set_allocated_desc(std::string* desc); + private: + const std::string& _internal_desc() const; + void _internal_set_desc(const std::string& value); + std::string* _internal_mutable_desc(); + public: + + // string icon = 4; + void clear_icon(); + const std::string& icon() const; + void set_icon(const std::string& value); + void set_icon(std::string&& value); + void set_icon(const char* value); + void set_icon(const char* value, size_t size); + std::string* mutable_icon(); + std::string* release_icon(); + void set_allocated_icon(std::string* icon); + private: + const std::string& _internal_icon() const; + void _internal_set_icon(const std::string& value); + std::string* _internal_mutable_icon(); + public: + + // string nick = 5; + void clear_nick(); + const std::string& nick() const; + void set_nick(const std::string& value); + void set_nick(std::string&& value); + void set_nick(const char* value); + void set_nick(const char* value, size_t size); + std::string* mutable_nick(); + std::string* release_nick(); + void set_allocated_nick(std::string* nick); + private: + const std::string& _internal_nick() const; + void _internal_set_nick(const std::string& value); + std::string* _internal_mutable_nick(); + public: + + // int32 applyuid = 1; + void clear_applyuid(); + ::PROTOBUF_NAMESPACE_ID::int32 applyuid() const; + void set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_applyuid() const; + void _internal_set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 sex = 6; + void clear_sex(); + ::PROTOBUF_NAMESPACE_ID::int32 sex() const; + void set_sex(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_sex() const; + void _internal_set_sex(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 7; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.AddFriendReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr desc_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr icon_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr nick_; + ::PROTOBUF_NAMESPACE_ID::int32 applyuid_; + ::PROTOBUF_NAMESPACE_ID::int32 sex_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class AddFriendRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.AddFriendRsp) */ { + public: + inline AddFriendRsp() : AddFriendRsp(nullptr) {} + virtual ~AddFriendRsp(); + + AddFriendRsp(const AddFriendRsp& from); + AddFriendRsp(AddFriendRsp&& from) noexcept + : AddFriendRsp() { + *this = ::std::move(from); + } + + inline AddFriendRsp& operator=(const AddFriendRsp& from) { + CopyFrom(from); + return *this; + } + inline AddFriendRsp& operator=(AddFriendRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const AddFriendRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const AddFriendRsp* internal_default_instance() { + return reinterpret_cast( + &_AddFriendRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 7; + + friend void swap(AddFriendRsp& a, AddFriendRsp& b) { + a.Swap(&b); + } + inline void Swap(AddFriendRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AddFriendRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline AddFriendRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + AddFriendRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const AddFriendRsp& from); + void MergeFrom(const AddFriendRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(AddFriendRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.AddFriendRsp"; + } + protected: + explicit AddFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kErrorFieldNumber = 1, + kApplyuidFieldNumber = 2, + kTouidFieldNumber = 3, + }; + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 applyuid = 2; + void clear_applyuid(); + ::PROTOBUF_NAMESPACE_ID::int32 applyuid() const; + void set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_applyuid() const; + void _internal_set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.AddFriendRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 applyuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class RplyFriendReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.RplyFriendReq) */ { + public: + inline RplyFriendReq() : RplyFriendReq(nullptr) {} + virtual ~RplyFriendReq(); + + RplyFriendReq(const RplyFriendReq& from); + RplyFriendReq(RplyFriendReq&& from) noexcept + : RplyFriendReq() { + *this = ::std::move(from); + } + + inline RplyFriendReq& operator=(const RplyFriendReq& from) { + CopyFrom(from); + return *this; + } + inline RplyFriendReq& operator=(RplyFriendReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const RplyFriendReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const RplyFriendReq* internal_default_instance() { + return reinterpret_cast( + &_RplyFriendReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 8; + + friend void swap(RplyFriendReq& a, RplyFriendReq& b) { + a.Swap(&b); + } + inline void Swap(RplyFriendReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RplyFriendReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline RplyFriendReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + RplyFriendReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const RplyFriendReq& from); + void MergeFrom(const RplyFriendReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(RplyFriendReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.RplyFriendReq"; + } + protected: + explicit RplyFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kRplyuidFieldNumber = 1, + kAgreeFieldNumber = 2, + kTouidFieldNumber = 3, + }; + // int32 rplyuid = 1; + void clear_rplyuid(); + ::PROTOBUF_NAMESPACE_ID::int32 rplyuid() const; + void set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_rplyuid() const; + void _internal_set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // bool agree = 2; + void clear_agree(); + bool agree() const; + void set_agree(bool value); + private: + bool _internal_agree() const; + void _internal_set_agree(bool value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.RplyFriendReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 rplyuid_; + bool agree_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class RplyFriendRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.RplyFriendRsp) */ { + public: + inline RplyFriendRsp() : RplyFriendRsp(nullptr) {} + virtual ~RplyFriendRsp(); + + RplyFriendRsp(const RplyFriendRsp& from); + RplyFriendRsp(RplyFriendRsp&& from) noexcept + : RplyFriendRsp() { + *this = ::std::move(from); + } + + inline RplyFriendRsp& operator=(const RplyFriendRsp& from) { + CopyFrom(from); + return *this; + } + inline RplyFriendRsp& operator=(RplyFriendRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const RplyFriendRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const RplyFriendRsp* internal_default_instance() { + return reinterpret_cast( + &_RplyFriendRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 9; + + friend void swap(RplyFriendRsp& a, RplyFriendRsp& b) { + a.Swap(&b); + } + inline void Swap(RplyFriendRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(RplyFriendRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline RplyFriendRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + RplyFriendRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const RplyFriendRsp& from); + void MergeFrom(const RplyFriendRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(RplyFriendRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.RplyFriendRsp"; + } + protected: + explicit RplyFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kErrorFieldNumber = 1, + kRplyuidFieldNumber = 2, + kTouidFieldNumber = 3, + }; + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 rplyuid = 2; + void clear_rplyuid(); + ::PROTOBUF_NAMESPACE_ID::int32 rplyuid() const; + void set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_rplyuid() const; + void _internal_set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.RplyFriendRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 rplyuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class SendChatMsgReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.SendChatMsgReq) */ { + public: + inline SendChatMsgReq() : SendChatMsgReq(nullptr) {} + virtual ~SendChatMsgReq(); + + SendChatMsgReq(const SendChatMsgReq& from); + SendChatMsgReq(SendChatMsgReq&& from) noexcept + : SendChatMsgReq() { + *this = ::std::move(from); + } + + inline SendChatMsgReq& operator=(const SendChatMsgReq& from) { + CopyFrom(from); + return *this; + } + inline SendChatMsgReq& operator=(SendChatMsgReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const SendChatMsgReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const SendChatMsgReq* internal_default_instance() { + return reinterpret_cast( + &_SendChatMsgReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 10; + + friend void swap(SendChatMsgReq& a, SendChatMsgReq& b) { + a.Swap(&b); + } + inline void Swap(SendChatMsgReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SendChatMsgReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline SendChatMsgReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + SendChatMsgReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const SendChatMsgReq& from); + void MergeFrom(const SendChatMsgReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SendChatMsgReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.SendChatMsgReq"; + } + protected: + explicit SendChatMsgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kMessageFieldNumber = 3, + kFromuidFieldNumber = 1, + kTouidFieldNumber = 2, + }; + // string message = 3; + void clear_message(); + const std::string& message() const; + void set_message(const std::string& value); + void set_message(std::string&& value); + void set_message(const char* value); + void set_message(const char* value, size_t size); + std::string* mutable_message(); + std::string* release_message(); + void set_allocated_message(std::string* message); + private: + const std::string& _internal_message() const; + void _internal_set_message(const std::string& value); + std::string* _internal_mutable_message(); + public: + + // int32 fromuid = 1; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 2; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.SendChatMsgReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr message_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class SendChatMsgRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.SendChatMsgRsp) */ { + public: + inline SendChatMsgRsp() : SendChatMsgRsp(nullptr) {} + virtual ~SendChatMsgRsp(); + + SendChatMsgRsp(const SendChatMsgRsp& from); + SendChatMsgRsp(SendChatMsgRsp&& from) noexcept + : SendChatMsgRsp() { + *this = ::std::move(from); + } + + inline SendChatMsgRsp& operator=(const SendChatMsgRsp& from) { + CopyFrom(from); + return *this; + } + inline SendChatMsgRsp& operator=(SendChatMsgRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const SendChatMsgRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const SendChatMsgRsp* internal_default_instance() { + return reinterpret_cast( + &_SendChatMsgRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 11; + + friend void swap(SendChatMsgRsp& a, SendChatMsgRsp& b) { + a.Swap(&b); + } + inline void Swap(SendChatMsgRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SendChatMsgRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline SendChatMsgRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + SendChatMsgRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const SendChatMsgRsp& from); + void MergeFrom(const SendChatMsgRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SendChatMsgRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.SendChatMsgRsp"; + } + protected: + explicit SendChatMsgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kErrorFieldNumber = 1, + kFromuidFieldNumber = 2, + kTouidFieldNumber = 3, + }; + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 fromuid = 2; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.SendChatMsgRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class AddFriendMsg PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.AddFriendMsg) */ { + public: + inline AddFriendMsg() : AddFriendMsg(nullptr) {} + virtual ~AddFriendMsg(); + + AddFriendMsg(const AddFriendMsg& from); + AddFriendMsg(AddFriendMsg&& from) noexcept + : AddFriendMsg() { + *this = ::std::move(from); + } + + inline AddFriendMsg& operator=(const AddFriendMsg& from) { + CopyFrom(from); + return *this; + } + inline AddFriendMsg& operator=(AddFriendMsg&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const AddFriendMsg& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const AddFriendMsg* internal_default_instance() { + return reinterpret_cast( + &_AddFriendMsg_default_instance_); + } + static constexpr int kIndexInFileMessages = + 12; + + friend void swap(AddFriendMsg& a, AddFriendMsg& b) { + a.Swap(&b); + } + inline void Swap(AddFriendMsg* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AddFriendMsg* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline AddFriendMsg* New() const final { + return CreateMaybeMessage(nullptr); + } + + AddFriendMsg* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const AddFriendMsg& from); + void MergeFrom(const AddFriendMsg& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(AddFriendMsg* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.AddFriendMsg"; + } + protected: + explicit AddFriendMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUniqueIdFieldNumber = 2, + kMsgcontentFieldNumber = 5, + kSenderIdFieldNumber = 1, + kMsgIdFieldNumber = 3, + kThreadIdFieldNumber = 4, + kStatusFieldNumber = 6, + }; + // string unique_id = 2; + void clear_unique_id(); + const std::string& unique_id() const; + void set_unique_id(const std::string& value); + void set_unique_id(std::string&& value); + void set_unique_id(const char* value); + void set_unique_id(const char* value, size_t size); + std::string* mutable_unique_id(); + std::string* release_unique_id(); + void set_allocated_unique_id(std::string* unique_id); + private: + const std::string& _internal_unique_id() const; + void _internal_set_unique_id(const std::string& value); + std::string* _internal_mutable_unique_id(); + public: + + // string msgcontent = 5; + void clear_msgcontent(); + const std::string& msgcontent() const; + void set_msgcontent(const std::string& value); + void set_msgcontent(std::string&& value); + void set_msgcontent(const char* value); + void set_msgcontent(const char* value, size_t size); + std::string* mutable_msgcontent(); + std::string* release_msgcontent(); + void set_allocated_msgcontent(std::string* msgcontent); + private: + const std::string& _internal_msgcontent() const; + void _internal_set_msgcontent(const std::string& value); + std::string* _internal_mutable_msgcontent(); + public: + + // int32 sender_id = 1; + void clear_sender_id(); + ::PROTOBUF_NAMESPACE_ID::int32 sender_id() const; + void set_sender_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_sender_id() const; + void _internal_set_sender_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 msg_id = 3; + void clear_msg_id(); + ::PROTOBUF_NAMESPACE_ID::int32 msg_id() const; + void set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_msg_id() const; + void _internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 4; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 status = 6; + void clear_status(); + ::PROTOBUF_NAMESPACE_ID::int32 status() const; + void set_status(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_status() const; + void _internal_set_status(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.AddFriendMsg) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr unique_id_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr msgcontent_; + ::PROTOBUF_NAMESPACE_ID::int32 sender_id_; + ::PROTOBUF_NAMESPACE_ID::int32 msg_id_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + ::PROTOBUF_NAMESPACE_ID::int32 status_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class AuthFriendReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.AuthFriendReq) */ { + public: + inline AuthFriendReq() : AuthFriendReq(nullptr) {} + virtual ~AuthFriendReq(); + + AuthFriendReq(const AuthFriendReq& from); + AuthFriendReq(AuthFriendReq&& from) noexcept + : AuthFriendReq() { + *this = ::std::move(from); + } + + inline AuthFriendReq& operator=(const AuthFriendReq& from) { + CopyFrom(from); + return *this; + } + inline AuthFriendReq& operator=(AuthFriendReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const AuthFriendReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const AuthFriendReq* internal_default_instance() { + return reinterpret_cast( + &_AuthFriendReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 13; + + friend void swap(AuthFriendReq& a, AuthFriendReq& b) { + a.Swap(&b); + } + inline void Swap(AuthFriendReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AuthFriendReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline AuthFriendReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + AuthFriendReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const AuthFriendReq& from); + void MergeFrom(const AuthFriendReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(AuthFriendReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.AuthFriendReq"; + } + protected: + explicit AuthFriendReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTextmsgsFieldNumber = 3, + kFromuidFieldNumber = 1, + kTouidFieldNumber = 2, + }; + // repeated .message.AddFriendMsg textmsgs = 3; + int textmsgs_size() const; + private: + int _internal_textmsgs_size() const; + public: + void clear_textmsgs(); + ::message::AddFriendMsg* mutable_textmsgs(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::AddFriendMsg >* + mutable_textmsgs(); + private: + const ::message::AddFriendMsg& _internal_textmsgs(int index) const; + ::message::AddFriendMsg* _internal_add_textmsgs(); + public: + const ::message::AddFriendMsg& textmsgs(int index) const; + ::message::AddFriendMsg* add_textmsgs(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::AddFriendMsg >& + textmsgs() const; + + // int32 fromuid = 1; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 2; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.AuthFriendReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::AddFriendMsg > textmsgs_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class AuthFriendRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.AuthFriendRsp) */ { + public: + inline AuthFriendRsp() : AuthFriendRsp(nullptr) {} + virtual ~AuthFriendRsp(); + + AuthFriendRsp(const AuthFriendRsp& from); + AuthFriendRsp(AuthFriendRsp&& from) noexcept + : AuthFriendRsp() { + *this = ::std::move(from); + } + + inline AuthFriendRsp& operator=(const AuthFriendRsp& from) { + CopyFrom(from); + return *this; + } + inline AuthFriendRsp& operator=(AuthFriendRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const AuthFriendRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const AuthFriendRsp* internal_default_instance() { + return reinterpret_cast( + &_AuthFriendRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 14; + + friend void swap(AuthFriendRsp& a, AuthFriendRsp& b) { + a.Swap(&b); + } + inline void Swap(AuthFriendRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(AuthFriendRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline AuthFriendRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + AuthFriendRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const AuthFriendRsp& from); + void MergeFrom(const AuthFriendRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(AuthFriendRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.AuthFriendRsp"; + } + protected: + explicit AuthFriendRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kErrorFieldNumber = 1, + kFromuidFieldNumber = 2, + kTouidFieldNumber = 3, + }; + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 fromuid = 2; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.AuthFriendRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class TextChatMsgReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.TextChatMsgReq) */ { + public: + inline TextChatMsgReq() : TextChatMsgReq(nullptr) {} + virtual ~TextChatMsgReq(); + + TextChatMsgReq(const TextChatMsgReq& from); + TextChatMsgReq(TextChatMsgReq&& from) noexcept + : TextChatMsgReq() { + *this = ::std::move(from); + } + + inline TextChatMsgReq& operator=(const TextChatMsgReq& from) { + CopyFrom(from); + return *this; + } + inline TextChatMsgReq& operator=(TextChatMsgReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const TextChatMsgReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const TextChatMsgReq* internal_default_instance() { + return reinterpret_cast( + &_TextChatMsgReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 15; + + friend void swap(TextChatMsgReq& a, TextChatMsgReq& b) { + a.Swap(&b); + } + inline void Swap(TextChatMsgReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TextChatMsgReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline TextChatMsgReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + TextChatMsgReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const TextChatMsgReq& from); + void MergeFrom(const TextChatMsgReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(TextChatMsgReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.TextChatMsgReq"; + } + protected: + explicit TextChatMsgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTextmsgsFieldNumber = 4, + kFromuidFieldNumber = 1, + kTouidFieldNumber = 2, + kThreadIdFieldNumber = 3, + }; + // repeated .message.TextChatData textmsgs = 4; + int textmsgs_size() const; + private: + int _internal_textmsgs_size() const; + public: + void clear_textmsgs(); + ::message::TextChatData* mutable_textmsgs(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >* + mutable_textmsgs(); + private: + const ::message::TextChatData& _internal_textmsgs(int index) const; + ::message::TextChatData* _internal_add_textmsgs(); + public: + const ::message::TextChatData& textmsgs(int index) const; + ::message::TextChatData* add_textmsgs(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >& + textmsgs() const; + + // int32 fromuid = 1; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 2; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 3; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.TextChatMsgReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData > textmsgs_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class TextChatData PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.TextChatData) */ { + public: + inline TextChatData() : TextChatData(nullptr) {} + virtual ~TextChatData(); + + TextChatData(const TextChatData& from); + TextChatData(TextChatData&& from) noexcept + : TextChatData() { + *this = ::std::move(from); + } + + inline TextChatData& operator=(const TextChatData& from) { + CopyFrom(from); + return *this; + } + inline TextChatData& operator=(TextChatData&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const TextChatData& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const TextChatData* internal_default_instance() { + return reinterpret_cast( + &_TextChatData_default_instance_); + } + static constexpr int kIndexInFileMessages = + 16; + + friend void swap(TextChatData& a, TextChatData& b) { + a.Swap(&b); + } + inline void Swap(TextChatData* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TextChatData* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline TextChatData* New() const final { + return CreateMaybeMessage(nullptr); + } + + TextChatData* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const TextChatData& from); + void MergeFrom(const TextChatData& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(TextChatData* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.TextChatData"; + } + protected: + explicit TextChatData(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUniqueIdFieldNumber = 1, + kMsgcontentFieldNumber = 3, + kChatTimeFieldNumber = 4, + kMsgIdFieldNumber = 2, + }; + // string unique_id = 1; + void clear_unique_id(); + const std::string& unique_id() const; + void set_unique_id(const std::string& value); + void set_unique_id(std::string&& value); + void set_unique_id(const char* value); + void set_unique_id(const char* value, size_t size); + std::string* mutable_unique_id(); + std::string* release_unique_id(); + void set_allocated_unique_id(std::string* unique_id); + private: + const std::string& _internal_unique_id() const; + void _internal_set_unique_id(const std::string& value); + std::string* _internal_mutable_unique_id(); + public: + + // string msgcontent = 3; + void clear_msgcontent(); + const std::string& msgcontent() const; + void set_msgcontent(const std::string& value); + void set_msgcontent(std::string&& value); + void set_msgcontent(const char* value); + void set_msgcontent(const char* value, size_t size); + std::string* mutable_msgcontent(); + std::string* release_msgcontent(); + void set_allocated_msgcontent(std::string* msgcontent); + private: + const std::string& _internal_msgcontent() const; + void _internal_set_msgcontent(const std::string& value); + std::string* _internal_mutable_msgcontent(); + public: + + // string chat_time = 4; + void clear_chat_time(); + const std::string& chat_time() const; + void set_chat_time(const std::string& value); + void set_chat_time(std::string&& value); + void set_chat_time(const char* value); + void set_chat_time(const char* value, size_t size); + std::string* mutable_chat_time(); + std::string* release_chat_time(); + void set_allocated_chat_time(std::string* chat_time); + private: + const std::string& _internal_chat_time() const; + void _internal_set_chat_time(const std::string& value); + std::string* _internal_mutable_chat_time(); + public: + + // int32 msg_id = 2; + void clear_msg_id(); + ::PROTOBUF_NAMESPACE_ID::int32 msg_id() const; + void set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_msg_id() const; + void _internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.TextChatData) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr unique_id_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr msgcontent_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr chat_time_; + ::PROTOBUF_NAMESPACE_ID::int32 msg_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class TextChatMsgRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.TextChatMsgRsp) */ { + public: + inline TextChatMsgRsp() : TextChatMsgRsp(nullptr) {} + virtual ~TextChatMsgRsp(); + + TextChatMsgRsp(const TextChatMsgRsp& from); + TextChatMsgRsp(TextChatMsgRsp&& from) noexcept + : TextChatMsgRsp() { + *this = ::std::move(from); + } + + inline TextChatMsgRsp& operator=(const TextChatMsgRsp& from) { + CopyFrom(from); + return *this; + } + inline TextChatMsgRsp& operator=(TextChatMsgRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const TextChatMsgRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const TextChatMsgRsp* internal_default_instance() { + return reinterpret_cast( + &_TextChatMsgRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 17; + + friend void swap(TextChatMsgRsp& a, TextChatMsgRsp& b) { + a.Swap(&b); + } + inline void Swap(TextChatMsgRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(TextChatMsgRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline TextChatMsgRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + TextChatMsgRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const TextChatMsgRsp& from); + void MergeFrom(const TextChatMsgRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(TextChatMsgRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.TextChatMsgRsp"; + } + protected: + explicit TextChatMsgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTextmsgsFieldNumber = 5, + kErrorFieldNumber = 1, + kFromuidFieldNumber = 2, + kTouidFieldNumber = 3, + kThreadIdFieldNumber = 4, + }; + // repeated .message.TextChatData textmsgs = 5; + int textmsgs_size() const; + private: + int _internal_textmsgs_size() const; + public: + void clear_textmsgs(); + ::message::TextChatData* mutable_textmsgs(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >* + mutable_textmsgs(); + private: + const ::message::TextChatData& _internal_textmsgs(int index) const; + ::message::TextChatData* _internal_add_textmsgs(); + public: + const ::message::TextChatData& textmsgs(int index) const; + ::message::TextChatData* add_textmsgs(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >& + textmsgs() const; + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 fromuid = 2; + void clear_fromuid(); + ::PROTOBUF_NAMESPACE_ID::int32 fromuid() const; + void set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_fromuid() const; + void _internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 touid = 3; + void clear_touid(); + ::PROTOBUF_NAMESPACE_ID::int32 touid() const; + void set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_touid() const; + void _internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 4; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.TextChatMsgRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData > textmsgs_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 fromuid_; + ::PROTOBUF_NAMESPACE_ID::int32 touid_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class KickUserReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.KickUserReq) */ { + public: + inline KickUserReq() : KickUserReq(nullptr) {} + virtual ~KickUserReq(); + + KickUserReq(const KickUserReq& from); + KickUserReq(KickUserReq&& from) noexcept + : KickUserReq() { + *this = ::std::move(from); + } + + inline KickUserReq& operator=(const KickUserReq& from) { + CopyFrom(from); + return *this; + } + inline KickUserReq& operator=(KickUserReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const KickUserReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const KickUserReq* internal_default_instance() { + return reinterpret_cast( + &_KickUserReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 18; + + friend void swap(KickUserReq& a, KickUserReq& b) { + a.Swap(&b); + } + inline void Swap(KickUserReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(KickUserReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline KickUserReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + KickUserReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const KickUserReq& from); + void MergeFrom(const KickUserReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(KickUserReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.KickUserReq"; + } + protected: + explicit KickUserReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUidFieldNumber = 1, + }; + // int32 uid = 1; + void clear_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 uid() const; + void set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_uid() const; + void _internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.KickUserReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 uid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class KickUserRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.KickUserRsp) */ { + public: + inline KickUserRsp() : KickUserRsp(nullptr) {} + virtual ~KickUserRsp(); + + KickUserRsp(const KickUserRsp& from); + KickUserRsp(KickUserRsp&& from) noexcept + : KickUserRsp() { + *this = ::std::move(from); + } + + inline KickUserRsp& operator=(const KickUserRsp& from) { + CopyFrom(from); + return *this; + } + inline KickUserRsp& operator=(KickUserRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const KickUserRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const KickUserRsp* internal_default_instance() { + return reinterpret_cast( + &_KickUserRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 19; + + friend void swap(KickUserRsp& a, KickUserRsp& b) { + a.Swap(&b); + } + inline void Swap(KickUserRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(KickUserRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline KickUserRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + KickUserRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const KickUserRsp& from); + void MergeFrom(const KickUserRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(KickUserRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.KickUserRsp"; + } + protected: + explicit KickUserRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kErrorFieldNumber = 1, + kUidFieldNumber = 2, + }; + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 uid = 2; + void clear_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 uid() const; + void set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_uid() const; + void _internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.KickUserRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 uid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class NotifyChatImgReq PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgReq) */ { + public: + inline NotifyChatImgReq() : NotifyChatImgReq(nullptr) {} + virtual ~NotifyChatImgReq(); + + NotifyChatImgReq(const NotifyChatImgReq& from); + NotifyChatImgReq(NotifyChatImgReq&& from) noexcept + : NotifyChatImgReq() { + *this = ::std::move(from); + } + + inline NotifyChatImgReq& operator=(const NotifyChatImgReq& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgReq& operator=(NotifyChatImgReq&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgReq& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgReq* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgReq_default_instance_); + } + static constexpr int kIndexInFileMessages = + 20; + + friend void swap(NotifyChatImgReq& a, NotifyChatImgReq& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgReq* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgReq* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgReq* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgReq* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgReq& from); + void MergeFrom(const NotifyChatImgReq& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgReq* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgReq"; + } + protected: + explicit NotifyChatImgReq(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 4, + kFromUidFieldNumber = 1, + kToUidFieldNumber = 2, + kMessageIdFieldNumber = 3, + kThreadIdFieldNumber = 6, + kTotalSizeFieldNumber = 5, + }; + // string file_name = 4; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 from_uid = 1; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 2; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 3; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 thread_id = 6; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 5; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgReq) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// ------------------------------------------------------------------- + +class NotifyChatImgRsp PROTOBUF_FINAL : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:message.NotifyChatImgRsp) */ { + public: + inline NotifyChatImgRsp() : NotifyChatImgRsp(nullptr) {} + virtual ~NotifyChatImgRsp(); + + NotifyChatImgRsp(const NotifyChatImgRsp& from); + NotifyChatImgRsp(NotifyChatImgRsp&& from) noexcept + : NotifyChatImgRsp() { + *this = ::std::move(from); + } + + inline NotifyChatImgRsp& operator=(const NotifyChatImgRsp& from) { + CopyFrom(from); + return *this; + } + inline NotifyChatImgRsp& operator=(NotifyChatImgRsp&& from) noexcept { + if (GetArena() == from.GetArena()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const NotifyChatImgRsp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const NotifyChatImgRsp* internal_default_instance() { + return reinterpret_cast( + &_NotifyChatImgRsp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 21; + + friend void swap(NotifyChatImgRsp& a, NotifyChatImgRsp& b) { + a.Swap(&b); + } + inline void Swap(NotifyChatImgRsp* other) { + if (other == this) return; + if (GetArena() == other->GetArena()) { + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(NotifyChatImgRsp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArena() == other->GetArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline NotifyChatImgRsp* New() const final { + return CreateMaybeMessage(nullptr); + } + + NotifyChatImgRsp* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const NotifyChatImgRsp& from); + void MergeFrom(const NotifyChatImgRsp& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize( + ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(NotifyChatImgRsp* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "message.NotifyChatImgRsp"; + } + protected: + explicit NotifyChatImgRsp(::PROTOBUF_NAMESPACE_ID::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_message_2eproto); + return ::descriptor_table_message_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFileNameFieldNumber = 5, + kErrorFieldNumber = 1, + kFromUidFieldNumber = 2, + kToUidFieldNumber = 3, + kMessageIdFieldNumber = 4, + kTotalSizeFieldNumber = 6, + kThreadIdFieldNumber = 7, + }; + // string file_name = 5; + void clear_file_name(); + const std::string& file_name() const; + void set_file_name(const std::string& value); + void set_file_name(std::string&& value); + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + std::string* mutable_file_name(); + std::string* release_file_name(); + void set_allocated_file_name(std::string* file_name); + private: + const std::string& _internal_file_name() const; + void _internal_set_file_name(const std::string& value); + std::string* _internal_mutable_file_name(); + public: + + // int32 error = 1; + void clear_error(); + ::PROTOBUF_NAMESPACE_ID::int32 error() const; + void set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_error() const; + void _internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 from_uid = 2; + void clear_from_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 from_uid() const; + void set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_from_uid() const; + void _internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 to_uid = 3; + void clear_to_uid(); + ::PROTOBUF_NAMESPACE_ID::int32 to_uid() const; + void set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_to_uid() const; + void _internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int32 message_id = 4; + void clear_message_id(); + ::PROTOBUF_NAMESPACE_ID::int32 message_id() const; + void set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_message_id() const; + void _internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // int64 total_size = 6; + void clear_total_size(); + ::PROTOBUF_NAMESPACE_ID::int64 total_size() const; + void set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + private: + ::PROTOBUF_NAMESPACE_ID::int64 _internal_total_size() const; + void _internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value); + public: + + // int32 thread_id = 7; + void clear_thread_id(); + ::PROTOBUF_NAMESPACE_ID::int32 thread_id() const; + void set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + private: + ::PROTOBUF_NAMESPACE_ID::int32 _internal_thread_id() const; + void _internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value); + public: + + // @@protoc_insertion_point(class_scope:message.NotifyChatImgRsp) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr file_name_; + ::PROTOBUF_NAMESPACE_ID::int32 error_; + ::PROTOBUF_NAMESPACE_ID::int32 from_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 to_uid_; + ::PROTOBUF_NAMESPACE_ID::int32 message_id_; + ::PROTOBUF_NAMESPACE_ID::int64 total_size_; + ::PROTOBUF_NAMESPACE_ID::int32 thread_id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_message_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// GetVarifyReq + +// string email = 1; +inline void GetVarifyReq::clear_email() { + email_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetVarifyReq::email() const { + // @@protoc_insertion_point(field_get:message.GetVarifyReq.email) + return _internal_email(); +} +inline void GetVarifyReq::set_email(const std::string& value) { + _internal_set_email(value); + // @@protoc_insertion_point(field_set:message.GetVarifyReq.email) +} +inline std::string* GetVarifyReq::mutable_email() { + // @@protoc_insertion_point(field_mutable:message.GetVarifyReq.email) + return _internal_mutable_email(); +} +inline const std::string& GetVarifyReq::_internal_email() const { + return email_.Get(); +} +inline void GetVarifyReq::_internal_set_email(const std::string& value) { + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetVarifyReq::set_email(std::string&& value) { + + email_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetVarifyReq.email) +} +inline void GetVarifyReq::set_email(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetVarifyReq.email) +} +inline void GetVarifyReq::set_email(const char* value, + size_t size) { + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetVarifyReq.email) +} +inline std::string* GetVarifyReq::_internal_mutable_email() { + + return email_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetVarifyReq::release_email() { + // @@protoc_insertion_point(field_release:message.GetVarifyReq.email) + return email_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetVarifyReq::set_allocated_email(std::string* email) { + if (email != nullptr) { + + } else { + + } + email_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), email, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetVarifyReq.email) +} + +// ------------------------------------------------------------------- + +// GetVarifyRsp + +// int32 error = 1; +inline void GetVarifyRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetVarifyRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetVarifyRsp::error() const { + // @@protoc_insertion_point(field_get:message.GetVarifyRsp.error) + return _internal_error(); +} +inline void GetVarifyRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void GetVarifyRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.GetVarifyRsp.error) +} + +// string email = 2; +inline void GetVarifyRsp::clear_email() { + email_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetVarifyRsp::email() const { + // @@protoc_insertion_point(field_get:message.GetVarifyRsp.email) + return _internal_email(); +} +inline void GetVarifyRsp::set_email(const std::string& value) { + _internal_set_email(value); + // @@protoc_insertion_point(field_set:message.GetVarifyRsp.email) +} +inline std::string* GetVarifyRsp::mutable_email() { + // @@protoc_insertion_point(field_mutable:message.GetVarifyRsp.email) + return _internal_mutable_email(); +} +inline const std::string& GetVarifyRsp::_internal_email() const { + return email_.Get(); +} +inline void GetVarifyRsp::_internal_set_email(const std::string& value) { + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetVarifyRsp::set_email(std::string&& value) { + + email_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetVarifyRsp.email) +} +inline void GetVarifyRsp::set_email(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetVarifyRsp.email) +} +inline void GetVarifyRsp::set_email(const char* value, + size_t size) { + + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetVarifyRsp.email) +} +inline std::string* GetVarifyRsp::_internal_mutable_email() { + + return email_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetVarifyRsp::release_email() { + // @@protoc_insertion_point(field_release:message.GetVarifyRsp.email) + return email_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetVarifyRsp::set_allocated_email(std::string* email) { + if (email != nullptr) { + + } else { + + } + email_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), email, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetVarifyRsp.email) +} + +// string code = 3; +inline void GetVarifyRsp::clear_code() { + code_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetVarifyRsp::code() const { + // @@protoc_insertion_point(field_get:message.GetVarifyRsp.code) + return _internal_code(); +} +inline void GetVarifyRsp::set_code(const std::string& value) { + _internal_set_code(value); + // @@protoc_insertion_point(field_set:message.GetVarifyRsp.code) +} +inline std::string* GetVarifyRsp::mutable_code() { + // @@protoc_insertion_point(field_mutable:message.GetVarifyRsp.code) + return _internal_mutable_code(); +} +inline const std::string& GetVarifyRsp::_internal_code() const { + return code_.Get(); +} +inline void GetVarifyRsp::_internal_set_code(const std::string& value) { + + code_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetVarifyRsp::set_code(std::string&& value) { + + code_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetVarifyRsp.code) +} +inline void GetVarifyRsp::set_code(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + code_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetVarifyRsp.code) +} +inline void GetVarifyRsp::set_code(const char* value, + size_t size) { + + code_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetVarifyRsp.code) +} +inline std::string* GetVarifyRsp::_internal_mutable_code() { + + return code_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetVarifyRsp::release_code() { + // @@protoc_insertion_point(field_release:message.GetVarifyRsp.code) + return code_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetVarifyRsp::set_allocated_code(std::string* code) { + if (code != nullptr) { + + } else { + + } + code_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), code, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetVarifyRsp.code) +} + +// ------------------------------------------------------------------- + +// GetChatServerReq + +// int32 uid = 1; +inline void GetChatServerReq::clear_uid() { + uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetChatServerReq::_internal_uid() const { + return uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetChatServerReq::uid() const { + // @@protoc_insertion_point(field_get:message.GetChatServerReq.uid) + return _internal_uid(); +} +inline void GetChatServerReq::_internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + uid_ = value; +} +inline void GetChatServerReq::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_uid(value); + // @@protoc_insertion_point(field_set:message.GetChatServerReq.uid) +} + +// ------------------------------------------------------------------- + +// GetChatServerRsp + +// int32 error = 1; +inline void GetChatServerRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetChatServerRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 GetChatServerRsp::error() const { + // @@protoc_insertion_point(field_get:message.GetChatServerRsp.error) + return _internal_error(); +} +inline void GetChatServerRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void GetChatServerRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.GetChatServerRsp.error) +} + +// string host = 2; +inline void GetChatServerRsp::clear_host() { + host_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetChatServerRsp::host() const { + // @@protoc_insertion_point(field_get:message.GetChatServerRsp.host) + return _internal_host(); +} +inline void GetChatServerRsp::set_host(const std::string& value) { + _internal_set_host(value); + // @@protoc_insertion_point(field_set:message.GetChatServerRsp.host) +} +inline std::string* GetChatServerRsp::mutable_host() { + // @@protoc_insertion_point(field_mutable:message.GetChatServerRsp.host) + return _internal_mutable_host(); +} +inline const std::string& GetChatServerRsp::_internal_host() const { + return host_.Get(); +} +inline void GetChatServerRsp::_internal_set_host(const std::string& value) { + + host_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetChatServerRsp::set_host(std::string&& value) { + + host_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetChatServerRsp.host) +} +inline void GetChatServerRsp::set_host(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + host_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetChatServerRsp.host) +} +inline void GetChatServerRsp::set_host(const char* value, + size_t size) { + + host_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetChatServerRsp.host) +} +inline std::string* GetChatServerRsp::_internal_mutable_host() { + + return host_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetChatServerRsp::release_host() { + // @@protoc_insertion_point(field_release:message.GetChatServerRsp.host) + return host_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetChatServerRsp::set_allocated_host(std::string* host) { + if (host != nullptr) { + + } else { + + } + host_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), host, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetChatServerRsp.host) +} + +// string port = 3; +inline void GetChatServerRsp::clear_port() { + port_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetChatServerRsp::port() const { + // @@protoc_insertion_point(field_get:message.GetChatServerRsp.port) + return _internal_port(); +} +inline void GetChatServerRsp::set_port(const std::string& value) { + _internal_set_port(value); + // @@protoc_insertion_point(field_set:message.GetChatServerRsp.port) +} +inline std::string* GetChatServerRsp::mutable_port() { + // @@protoc_insertion_point(field_mutable:message.GetChatServerRsp.port) + return _internal_mutable_port(); +} +inline const std::string& GetChatServerRsp::_internal_port() const { + return port_.Get(); +} +inline void GetChatServerRsp::_internal_set_port(const std::string& value) { + + port_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetChatServerRsp::set_port(std::string&& value) { + + port_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetChatServerRsp.port) +} +inline void GetChatServerRsp::set_port(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + port_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetChatServerRsp.port) +} +inline void GetChatServerRsp::set_port(const char* value, + size_t size) { + + port_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetChatServerRsp.port) +} +inline std::string* GetChatServerRsp::_internal_mutable_port() { + + return port_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetChatServerRsp::release_port() { + // @@protoc_insertion_point(field_release:message.GetChatServerRsp.port) + return port_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetChatServerRsp::set_allocated_port(std::string* port) { + if (port != nullptr) { + + } else { + + } + port_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), port, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetChatServerRsp.port) +} + +// string token = 4; +inline void GetChatServerRsp::clear_token() { + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& GetChatServerRsp::token() const { + // @@protoc_insertion_point(field_get:message.GetChatServerRsp.token) + return _internal_token(); +} +inline void GetChatServerRsp::set_token(const std::string& value) { + _internal_set_token(value); + // @@protoc_insertion_point(field_set:message.GetChatServerRsp.token) +} +inline std::string* GetChatServerRsp::mutable_token() { + // @@protoc_insertion_point(field_mutable:message.GetChatServerRsp.token) + return _internal_mutable_token(); +} +inline const std::string& GetChatServerRsp::_internal_token() const { + return token_.Get(); +} +inline void GetChatServerRsp::_internal_set_token(const std::string& value) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void GetChatServerRsp::set_token(std::string&& value) { + + token_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.GetChatServerRsp.token) +} +inline void GetChatServerRsp::set_token(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.GetChatServerRsp.token) +} +inline void GetChatServerRsp::set_token(const char* value, + size_t size) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.GetChatServerRsp.token) +} +inline std::string* GetChatServerRsp::_internal_mutable_token() { + + return token_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* GetChatServerRsp::release_token() { + // @@protoc_insertion_point(field_release:message.GetChatServerRsp.token) + return token_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void GetChatServerRsp::set_allocated_token(std::string* token) { + if (token != nullptr) { + + } else { + + } + token_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), token, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.GetChatServerRsp.token) +} + +// ------------------------------------------------------------------- + +// LoginReq + +// int32 uid = 1; +inline void LoginReq::clear_uid() { + uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginReq::_internal_uid() const { + return uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginReq::uid() const { + // @@protoc_insertion_point(field_get:message.LoginReq.uid) + return _internal_uid(); +} +inline void LoginReq::_internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + uid_ = value; +} +inline void LoginReq::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_uid(value); + // @@protoc_insertion_point(field_set:message.LoginReq.uid) +} + +// string token = 2; +inline void LoginReq::clear_token() { + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& LoginReq::token() const { + // @@protoc_insertion_point(field_get:message.LoginReq.token) + return _internal_token(); +} +inline void LoginReq::set_token(const std::string& value) { + _internal_set_token(value); + // @@protoc_insertion_point(field_set:message.LoginReq.token) +} +inline std::string* LoginReq::mutable_token() { + // @@protoc_insertion_point(field_mutable:message.LoginReq.token) + return _internal_mutable_token(); +} +inline const std::string& LoginReq::_internal_token() const { + return token_.Get(); +} +inline void LoginReq::_internal_set_token(const std::string& value) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void LoginReq::set_token(std::string&& value) { + + token_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.LoginReq.token) +} +inline void LoginReq::set_token(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.LoginReq.token) +} +inline void LoginReq::set_token(const char* value, + size_t size) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.LoginReq.token) +} +inline std::string* LoginReq::_internal_mutable_token() { + + return token_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* LoginReq::release_token() { + // @@protoc_insertion_point(field_release:message.LoginReq.token) + return token_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void LoginReq::set_allocated_token(std::string* token) { + if (token != nullptr) { + + } else { + + } + token_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), token, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.LoginReq.token) +} + +// ------------------------------------------------------------------- + +// LoginRsp + +// int32 error = 1; +inline void LoginRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginRsp::error() const { + // @@protoc_insertion_point(field_get:message.LoginRsp.error) + return _internal_error(); +} +inline void LoginRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void LoginRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.LoginRsp.error) +} + +// int32 uid = 2; +inline void LoginRsp::clear_uid() { + uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginRsp::_internal_uid() const { + return uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 LoginRsp::uid() const { + // @@protoc_insertion_point(field_get:message.LoginRsp.uid) + return _internal_uid(); +} +inline void LoginRsp::_internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + uid_ = value; +} +inline void LoginRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_uid(value); + // @@protoc_insertion_point(field_set:message.LoginRsp.uid) +} + +// string token = 3; +inline void LoginRsp::clear_token() { + token_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& LoginRsp::token() const { + // @@protoc_insertion_point(field_get:message.LoginRsp.token) + return _internal_token(); +} +inline void LoginRsp::set_token(const std::string& value) { + _internal_set_token(value); + // @@protoc_insertion_point(field_set:message.LoginRsp.token) +} +inline std::string* LoginRsp::mutable_token() { + // @@protoc_insertion_point(field_mutable:message.LoginRsp.token) + return _internal_mutable_token(); +} +inline const std::string& LoginRsp::_internal_token() const { + return token_.Get(); +} +inline void LoginRsp::_internal_set_token(const std::string& value) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void LoginRsp::set_token(std::string&& value) { + + token_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.LoginRsp.token) +} +inline void LoginRsp::set_token(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.LoginRsp.token) +} +inline void LoginRsp::set_token(const char* value, + size_t size) { + + token_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.LoginRsp.token) +} +inline std::string* LoginRsp::_internal_mutable_token() { + + return token_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* LoginRsp::release_token() { + // @@protoc_insertion_point(field_release:message.LoginRsp.token) + return token_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void LoginRsp::set_allocated_token(std::string* token) { + if (token != nullptr) { + + } else { + + } + token_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), token, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.LoginRsp.token) +} + +// ------------------------------------------------------------------- + +// AddFriendReq + +// int32 applyuid = 1; +inline void AddFriendReq::clear_applyuid() { + applyuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::_internal_applyuid() const { + return applyuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::applyuid() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.applyuid) + return _internal_applyuid(); +} +inline void AddFriendReq::_internal_set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + applyuid_ = value; +} +inline void AddFriendReq::set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_applyuid(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.applyuid) +} + +// string name = 2; +inline void AddFriendReq::clear_name() { + name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendReq::name() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.name) + return _internal_name(); +} +inline void AddFriendReq::set_name(const std::string& value) { + _internal_set_name(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.name) +} +inline std::string* AddFriendReq::mutable_name() { + // @@protoc_insertion_point(field_mutable:message.AddFriendReq.name) + return _internal_mutable_name(); +} +inline const std::string& AddFriendReq::_internal_name() const { + return name_.Get(); +} +inline void AddFriendReq::_internal_set_name(const std::string& value) { + + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendReq::set_name(std::string&& value) { + + name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendReq.name) +} +inline void AddFriendReq::set_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendReq.name) +} +inline void AddFriendReq::set_name(const char* value, + size_t size) { + + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendReq.name) +} +inline std::string* AddFriendReq::_internal_mutable_name() { + + return name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendReq::release_name() { + // @@protoc_insertion_point(field_release:message.AddFriendReq.name) + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendReq::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendReq.name) +} + +// string desc = 3; +inline void AddFriendReq::clear_desc() { + desc_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendReq::desc() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.desc) + return _internal_desc(); +} +inline void AddFriendReq::set_desc(const std::string& value) { + _internal_set_desc(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.desc) +} +inline std::string* AddFriendReq::mutable_desc() { + // @@protoc_insertion_point(field_mutable:message.AddFriendReq.desc) + return _internal_mutable_desc(); +} +inline const std::string& AddFriendReq::_internal_desc() const { + return desc_.Get(); +} +inline void AddFriendReq::_internal_set_desc(const std::string& value) { + + desc_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendReq::set_desc(std::string&& value) { + + desc_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendReq.desc) +} +inline void AddFriendReq::set_desc(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + desc_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendReq.desc) +} +inline void AddFriendReq::set_desc(const char* value, + size_t size) { + + desc_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendReq.desc) +} +inline std::string* AddFriendReq::_internal_mutable_desc() { + + return desc_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendReq::release_desc() { + // @@protoc_insertion_point(field_release:message.AddFriendReq.desc) + return desc_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendReq::set_allocated_desc(std::string* desc) { + if (desc != nullptr) { + + } else { + + } + desc_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), desc, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendReq.desc) +} + +// string icon = 4; +inline void AddFriendReq::clear_icon() { + icon_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendReq::icon() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.icon) + return _internal_icon(); +} +inline void AddFriendReq::set_icon(const std::string& value) { + _internal_set_icon(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.icon) +} +inline std::string* AddFriendReq::mutable_icon() { + // @@protoc_insertion_point(field_mutable:message.AddFriendReq.icon) + return _internal_mutable_icon(); +} +inline const std::string& AddFriendReq::_internal_icon() const { + return icon_.Get(); +} +inline void AddFriendReq::_internal_set_icon(const std::string& value) { + + icon_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendReq::set_icon(std::string&& value) { + + icon_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendReq.icon) +} +inline void AddFriendReq::set_icon(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + icon_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendReq.icon) +} +inline void AddFriendReq::set_icon(const char* value, + size_t size) { + + icon_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendReq.icon) +} +inline std::string* AddFriendReq::_internal_mutable_icon() { + + return icon_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendReq::release_icon() { + // @@protoc_insertion_point(field_release:message.AddFriendReq.icon) + return icon_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendReq::set_allocated_icon(std::string* icon) { + if (icon != nullptr) { + + } else { + + } + icon_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), icon, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendReq.icon) +} + +// string nick = 5; +inline void AddFriendReq::clear_nick() { + nick_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendReq::nick() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.nick) + return _internal_nick(); +} +inline void AddFriendReq::set_nick(const std::string& value) { + _internal_set_nick(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.nick) +} +inline std::string* AddFriendReq::mutable_nick() { + // @@protoc_insertion_point(field_mutable:message.AddFriendReq.nick) + return _internal_mutable_nick(); +} +inline const std::string& AddFriendReq::_internal_nick() const { + return nick_.Get(); +} +inline void AddFriendReq::_internal_set_nick(const std::string& value) { + + nick_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendReq::set_nick(std::string&& value) { + + nick_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendReq.nick) +} +inline void AddFriendReq::set_nick(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + nick_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendReq.nick) +} +inline void AddFriendReq::set_nick(const char* value, + size_t size) { + + nick_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendReq.nick) +} +inline std::string* AddFriendReq::_internal_mutable_nick() { + + return nick_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendReq::release_nick() { + // @@protoc_insertion_point(field_release:message.AddFriendReq.nick) + return nick_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendReq::set_allocated_nick(std::string* nick) { + if (nick != nullptr) { + + } else { + + } + nick_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), nick, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendReq.nick) +} + +// int32 sex = 6; +inline void AddFriendReq::clear_sex() { + sex_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::_internal_sex() const { + return sex_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::sex() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.sex) + return _internal_sex(); +} +inline void AddFriendReq::_internal_set_sex(::PROTOBUF_NAMESPACE_ID::int32 value) { + + sex_ = value; +} +inline void AddFriendReq::set_sex(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_sex(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.sex) +} + +// int32 touid = 7; +inline void AddFriendReq::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendReq::touid() const { + // @@protoc_insertion_point(field_get:message.AddFriendReq.touid) + return _internal_touid(); +} +inline void AddFriendReq::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void AddFriendReq::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.AddFriendReq.touid) +} + +// ------------------------------------------------------------------- + +// AddFriendRsp + +// int32 error = 1; +inline void AddFriendRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::error() const { + // @@protoc_insertion_point(field_get:message.AddFriendRsp.error) + return _internal_error(); +} +inline void AddFriendRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void AddFriendRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.AddFriendRsp.error) +} + +// int32 applyuid = 2; +inline void AddFriendRsp::clear_applyuid() { + applyuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::_internal_applyuid() const { + return applyuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::applyuid() const { + // @@protoc_insertion_point(field_get:message.AddFriendRsp.applyuid) + return _internal_applyuid(); +} +inline void AddFriendRsp::_internal_set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + applyuid_ = value; +} +inline void AddFriendRsp::set_applyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_applyuid(value); + // @@protoc_insertion_point(field_set:message.AddFriendRsp.applyuid) +} + +// int32 touid = 3; +inline void AddFriendRsp::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendRsp::touid() const { + // @@protoc_insertion_point(field_get:message.AddFriendRsp.touid) + return _internal_touid(); +} +inline void AddFriendRsp::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void AddFriendRsp::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.AddFriendRsp.touid) +} + +// ------------------------------------------------------------------- + +// RplyFriendReq + +// int32 rplyuid = 1; +inline void RplyFriendReq::clear_rplyuid() { + rplyuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendReq::_internal_rplyuid() const { + return rplyuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendReq::rplyuid() const { + // @@protoc_insertion_point(field_get:message.RplyFriendReq.rplyuid) + return _internal_rplyuid(); +} +inline void RplyFriendReq::_internal_set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + rplyuid_ = value; +} +inline void RplyFriendReq::set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_rplyuid(value); + // @@protoc_insertion_point(field_set:message.RplyFriendReq.rplyuid) +} + +// bool agree = 2; +inline void RplyFriendReq::clear_agree() { + agree_ = false; +} +inline bool RplyFriendReq::_internal_agree() const { + return agree_; +} +inline bool RplyFriendReq::agree() const { + // @@protoc_insertion_point(field_get:message.RplyFriendReq.agree) + return _internal_agree(); +} +inline void RplyFriendReq::_internal_set_agree(bool value) { + + agree_ = value; +} +inline void RplyFriendReq::set_agree(bool value) { + _internal_set_agree(value); + // @@protoc_insertion_point(field_set:message.RplyFriendReq.agree) +} + +// int32 touid = 3; +inline void RplyFriendReq::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendReq::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendReq::touid() const { + // @@protoc_insertion_point(field_get:message.RplyFriendReq.touid) + return _internal_touid(); +} +inline void RplyFriendReq::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void RplyFriendReq::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.RplyFriendReq.touid) +} + +// ------------------------------------------------------------------- + +// RplyFriendRsp + +// int32 error = 1; +inline void RplyFriendRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::error() const { + // @@protoc_insertion_point(field_get:message.RplyFriendRsp.error) + return _internal_error(); +} +inline void RplyFriendRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void RplyFriendRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.RplyFriendRsp.error) +} + +// int32 rplyuid = 2; +inline void RplyFriendRsp::clear_rplyuid() { + rplyuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::_internal_rplyuid() const { + return rplyuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::rplyuid() const { + // @@protoc_insertion_point(field_get:message.RplyFriendRsp.rplyuid) + return _internal_rplyuid(); +} +inline void RplyFriendRsp::_internal_set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + rplyuid_ = value; +} +inline void RplyFriendRsp::set_rplyuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_rplyuid(value); + // @@protoc_insertion_point(field_set:message.RplyFriendRsp.rplyuid) +} + +// int32 touid = 3; +inline void RplyFriendRsp::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 RplyFriendRsp::touid() const { + // @@protoc_insertion_point(field_get:message.RplyFriendRsp.touid) + return _internal_touid(); +} +inline void RplyFriendRsp::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void RplyFriendRsp::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.RplyFriendRsp.touid) +} + +// ------------------------------------------------------------------- + +// SendChatMsgReq + +// int32 fromuid = 1; +inline void SendChatMsgReq::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgReq::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgReq::fromuid() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgReq.fromuid) + return _internal_fromuid(); +} +inline void SendChatMsgReq::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void SendChatMsgReq::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgReq.fromuid) +} + +// int32 touid = 2; +inline void SendChatMsgReq::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgReq::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgReq::touid() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgReq.touid) + return _internal_touid(); +} +inline void SendChatMsgReq::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void SendChatMsgReq::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgReq.touid) +} + +// string message = 3; +inline void SendChatMsgReq::clear_message() { + message_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& SendChatMsgReq::message() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgReq.message) + return _internal_message(); +} +inline void SendChatMsgReq::set_message(const std::string& value) { + _internal_set_message(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgReq.message) +} +inline std::string* SendChatMsgReq::mutable_message() { + // @@protoc_insertion_point(field_mutable:message.SendChatMsgReq.message) + return _internal_mutable_message(); +} +inline const std::string& SendChatMsgReq::_internal_message() const { + return message_.Get(); +} +inline void SendChatMsgReq::_internal_set_message(const std::string& value) { + + message_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void SendChatMsgReq::set_message(std::string&& value) { + + message_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.SendChatMsgReq.message) +} +inline void SendChatMsgReq::set_message(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + message_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.SendChatMsgReq.message) +} +inline void SendChatMsgReq::set_message(const char* value, + size_t size) { + + message_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.SendChatMsgReq.message) +} +inline std::string* SendChatMsgReq::_internal_mutable_message() { + + return message_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* SendChatMsgReq::release_message() { + // @@protoc_insertion_point(field_release:message.SendChatMsgReq.message) + return message_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void SendChatMsgReq::set_allocated_message(std::string* message) { + if (message != nullptr) { + + } else { + + } + message_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), message, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.SendChatMsgReq.message) +} + +// ------------------------------------------------------------------- + +// SendChatMsgRsp + +// int32 error = 1; +inline void SendChatMsgRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::error() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgRsp.error) + return _internal_error(); +} +inline void SendChatMsgRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void SendChatMsgRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgRsp.error) +} + +// int32 fromuid = 2; +inline void SendChatMsgRsp::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::fromuid() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgRsp.fromuid) + return _internal_fromuid(); +} +inline void SendChatMsgRsp::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void SendChatMsgRsp::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgRsp.fromuid) +} + +// int32 touid = 3; +inline void SendChatMsgRsp::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 SendChatMsgRsp::touid() const { + // @@protoc_insertion_point(field_get:message.SendChatMsgRsp.touid) + return _internal_touid(); +} +inline void SendChatMsgRsp::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void SendChatMsgRsp::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.SendChatMsgRsp.touid) +} + +// ------------------------------------------------------------------- + +// AddFriendMsg + +// int32 sender_id = 1; +inline void AddFriendMsg::clear_sender_id() { + sender_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::_internal_sender_id() const { + return sender_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::sender_id() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.sender_id) + return _internal_sender_id(); +} +inline void AddFriendMsg::_internal_set_sender_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + sender_id_ = value; +} +inline void AddFriendMsg::set_sender_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_sender_id(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.sender_id) +} + +// string unique_id = 2; +inline void AddFriendMsg::clear_unique_id() { + unique_id_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendMsg::unique_id() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.unique_id) + return _internal_unique_id(); +} +inline void AddFriendMsg::set_unique_id(const std::string& value) { + _internal_set_unique_id(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.unique_id) +} +inline std::string* AddFriendMsg::mutable_unique_id() { + // @@protoc_insertion_point(field_mutable:message.AddFriendMsg.unique_id) + return _internal_mutable_unique_id(); +} +inline const std::string& AddFriendMsg::_internal_unique_id() const { + return unique_id_.Get(); +} +inline void AddFriendMsg::_internal_set_unique_id(const std::string& value) { + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendMsg::set_unique_id(std::string&& value) { + + unique_id_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendMsg.unique_id) +} +inline void AddFriendMsg::set_unique_id(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendMsg.unique_id) +} +inline void AddFriendMsg::set_unique_id(const char* value, + size_t size) { + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendMsg.unique_id) +} +inline std::string* AddFriendMsg::_internal_mutable_unique_id() { + + return unique_id_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendMsg::release_unique_id() { + // @@protoc_insertion_point(field_release:message.AddFriendMsg.unique_id) + return unique_id_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendMsg::set_allocated_unique_id(std::string* unique_id) { + if (unique_id != nullptr) { + + } else { + + } + unique_id_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), unique_id, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendMsg.unique_id) +} + +// int32 msg_id = 3; +inline void AddFriendMsg::clear_msg_id() { + msg_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::_internal_msg_id() const { + return msg_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::msg_id() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.msg_id) + return _internal_msg_id(); +} +inline void AddFriendMsg::_internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + msg_id_ = value; +} +inline void AddFriendMsg::set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_msg_id(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.msg_id) +} + +// int32 thread_id = 4; +inline void AddFriendMsg::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::thread_id() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.thread_id) + return _internal_thread_id(); +} +inline void AddFriendMsg::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void AddFriendMsg::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.thread_id) +} + +// string msgcontent = 5; +inline void AddFriendMsg::clear_msgcontent() { + msgcontent_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& AddFriendMsg::msgcontent() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.msgcontent) + return _internal_msgcontent(); +} +inline void AddFriendMsg::set_msgcontent(const std::string& value) { + _internal_set_msgcontent(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.msgcontent) +} +inline std::string* AddFriendMsg::mutable_msgcontent() { + // @@protoc_insertion_point(field_mutable:message.AddFriendMsg.msgcontent) + return _internal_mutable_msgcontent(); +} +inline const std::string& AddFriendMsg::_internal_msgcontent() const { + return msgcontent_.Get(); +} +inline void AddFriendMsg::_internal_set_msgcontent(const std::string& value) { + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void AddFriendMsg::set_msgcontent(std::string&& value) { + + msgcontent_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.AddFriendMsg.msgcontent) +} +inline void AddFriendMsg::set_msgcontent(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.AddFriendMsg.msgcontent) +} +inline void AddFriendMsg::set_msgcontent(const char* value, + size_t size) { + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.AddFriendMsg.msgcontent) +} +inline std::string* AddFriendMsg::_internal_mutable_msgcontent() { + + return msgcontent_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* AddFriendMsg::release_msgcontent() { + // @@protoc_insertion_point(field_release:message.AddFriendMsg.msgcontent) + return msgcontent_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void AddFriendMsg::set_allocated_msgcontent(std::string* msgcontent) { + if (msgcontent != nullptr) { + + } else { + + } + msgcontent_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), msgcontent, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.AddFriendMsg.msgcontent) +} + +// int32 status = 6; +inline void AddFriendMsg::clear_status() { + status_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::_internal_status() const { + return status_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AddFriendMsg::status() const { + // @@protoc_insertion_point(field_get:message.AddFriendMsg.status) + return _internal_status(); +} +inline void AddFriendMsg::_internal_set_status(::PROTOBUF_NAMESPACE_ID::int32 value) { + + status_ = value; +} +inline void AddFriendMsg::set_status(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_status(value); + // @@protoc_insertion_point(field_set:message.AddFriendMsg.status) +} + +// ------------------------------------------------------------------- + +// AuthFriendReq + +// int32 fromuid = 1; +inline void AuthFriendReq::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendReq::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendReq::fromuid() const { + // @@protoc_insertion_point(field_get:message.AuthFriendReq.fromuid) + return _internal_fromuid(); +} +inline void AuthFriendReq::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void AuthFriendReq::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.AuthFriendReq.fromuid) +} + +// int32 touid = 2; +inline void AuthFriendReq::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendReq::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendReq::touid() const { + // @@protoc_insertion_point(field_get:message.AuthFriendReq.touid) + return _internal_touid(); +} +inline void AuthFriendReq::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void AuthFriendReq::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.AuthFriendReq.touid) +} + +// repeated .message.AddFriendMsg textmsgs = 3; +inline int AuthFriendReq::_internal_textmsgs_size() const { + return textmsgs_.size(); +} +inline int AuthFriendReq::textmsgs_size() const { + return _internal_textmsgs_size(); +} +inline void AuthFriendReq::clear_textmsgs() { + textmsgs_.Clear(); +} +inline ::message::AddFriendMsg* AuthFriendReq::mutable_textmsgs(int index) { + // @@protoc_insertion_point(field_mutable:message.AuthFriendReq.textmsgs) + return textmsgs_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::AddFriendMsg >* +AuthFriendReq::mutable_textmsgs() { + // @@protoc_insertion_point(field_mutable_list:message.AuthFriendReq.textmsgs) + return &textmsgs_; +} +inline const ::message::AddFriendMsg& AuthFriendReq::_internal_textmsgs(int index) const { + return textmsgs_.Get(index); +} +inline const ::message::AddFriendMsg& AuthFriendReq::textmsgs(int index) const { + // @@protoc_insertion_point(field_get:message.AuthFriendReq.textmsgs) + return _internal_textmsgs(index); +} +inline ::message::AddFriendMsg* AuthFriendReq::_internal_add_textmsgs() { + return textmsgs_.Add(); +} +inline ::message::AddFriendMsg* AuthFriendReq::add_textmsgs() { + // @@protoc_insertion_point(field_add:message.AuthFriendReq.textmsgs) + return _internal_add_textmsgs(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::AddFriendMsg >& +AuthFriendReq::textmsgs() const { + // @@protoc_insertion_point(field_list:message.AuthFriendReq.textmsgs) + return textmsgs_; +} + +// ------------------------------------------------------------------- + +// AuthFriendRsp + +// int32 error = 1; +inline void AuthFriendRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::error() const { + // @@protoc_insertion_point(field_get:message.AuthFriendRsp.error) + return _internal_error(); +} +inline void AuthFriendRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void AuthFriendRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.AuthFriendRsp.error) +} + +// int32 fromuid = 2; +inline void AuthFriendRsp::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::fromuid() const { + // @@protoc_insertion_point(field_get:message.AuthFriendRsp.fromuid) + return _internal_fromuid(); +} +inline void AuthFriendRsp::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void AuthFriendRsp::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.AuthFriendRsp.fromuid) +} + +// int32 touid = 3; +inline void AuthFriendRsp::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 AuthFriendRsp::touid() const { + // @@protoc_insertion_point(field_get:message.AuthFriendRsp.touid) + return _internal_touid(); +} +inline void AuthFriendRsp::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void AuthFriendRsp::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.AuthFriendRsp.touid) +} + +// ------------------------------------------------------------------- + +// TextChatMsgReq + +// int32 fromuid = 1; +inline void TextChatMsgReq::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::fromuid() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgReq.fromuid) + return _internal_fromuid(); +} +inline void TextChatMsgReq::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void TextChatMsgReq::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgReq.fromuid) +} + +// int32 touid = 2; +inline void TextChatMsgReq::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::touid() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgReq.touid) + return _internal_touid(); +} +inline void TextChatMsgReq::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void TextChatMsgReq::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgReq.touid) +} + +// int32 thread_id = 3; +inline void TextChatMsgReq::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgReq::thread_id() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgReq.thread_id) + return _internal_thread_id(); +} +inline void TextChatMsgReq::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void TextChatMsgReq::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgReq.thread_id) +} + +// repeated .message.TextChatData textmsgs = 4; +inline int TextChatMsgReq::_internal_textmsgs_size() const { + return textmsgs_.size(); +} +inline int TextChatMsgReq::textmsgs_size() const { + return _internal_textmsgs_size(); +} +inline void TextChatMsgReq::clear_textmsgs() { + textmsgs_.Clear(); +} +inline ::message::TextChatData* TextChatMsgReq::mutable_textmsgs(int index) { + // @@protoc_insertion_point(field_mutable:message.TextChatMsgReq.textmsgs) + return textmsgs_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >* +TextChatMsgReq::mutable_textmsgs() { + // @@protoc_insertion_point(field_mutable_list:message.TextChatMsgReq.textmsgs) + return &textmsgs_; +} +inline const ::message::TextChatData& TextChatMsgReq::_internal_textmsgs(int index) const { + return textmsgs_.Get(index); +} +inline const ::message::TextChatData& TextChatMsgReq::textmsgs(int index) const { + // @@protoc_insertion_point(field_get:message.TextChatMsgReq.textmsgs) + return _internal_textmsgs(index); +} +inline ::message::TextChatData* TextChatMsgReq::_internal_add_textmsgs() { + return textmsgs_.Add(); +} +inline ::message::TextChatData* TextChatMsgReq::add_textmsgs() { + // @@protoc_insertion_point(field_add:message.TextChatMsgReq.textmsgs) + return _internal_add_textmsgs(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >& +TextChatMsgReq::textmsgs() const { + // @@protoc_insertion_point(field_list:message.TextChatMsgReq.textmsgs) + return textmsgs_; +} + +// ------------------------------------------------------------------- + +// TextChatData + +// string unique_id = 1; +inline void TextChatData::clear_unique_id() { + unique_id_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& TextChatData::unique_id() const { + // @@protoc_insertion_point(field_get:message.TextChatData.unique_id) + return _internal_unique_id(); +} +inline void TextChatData::set_unique_id(const std::string& value) { + _internal_set_unique_id(value); + // @@protoc_insertion_point(field_set:message.TextChatData.unique_id) +} +inline std::string* TextChatData::mutable_unique_id() { + // @@protoc_insertion_point(field_mutable:message.TextChatData.unique_id) + return _internal_mutable_unique_id(); +} +inline const std::string& TextChatData::_internal_unique_id() const { + return unique_id_.Get(); +} +inline void TextChatData::_internal_set_unique_id(const std::string& value) { + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void TextChatData::set_unique_id(std::string&& value) { + + unique_id_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.TextChatData.unique_id) +} +inline void TextChatData::set_unique_id(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.TextChatData.unique_id) +} +inline void TextChatData::set_unique_id(const char* value, + size_t size) { + + unique_id_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.TextChatData.unique_id) +} +inline std::string* TextChatData::_internal_mutable_unique_id() { + + return unique_id_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* TextChatData::release_unique_id() { + // @@protoc_insertion_point(field_release:message.TextChatData.unique_id) + return unique_id_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void TextChatData::set_allocated_unique_id(std::string* unique_id) { + if (unique_id != nullptr) { + + } else { + + } + unique_id_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), unique_id, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.TextChatData.unique_id) +} + +// int32 msg_id = 2; +inline void TextChatData::clear_msg_id() { + msg_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatData::_internal_msg_id() const { + return msg_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatData::msg_id() const { + // @@protoc_insertion_point(field_get:message.TextChatData.msg_id) + return _internal_msg_id(); +} +inline void TextChatData::_internal_set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + msg_id_ = value; +} +inline void TextChatData::set_msg_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_msg_id(value); + // @@protoc_insertion_point(field_set:message.TextChatData.msg_id) +} + +// string msgcontent = 3; +inline void TextChatData::clear_msgcontent() { + msgcontent_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& TextChatData::msgcontent() const { + // @@protoc_insertion_point(field_get:message.TextChatData.msgcontent) + return _internal_msgcontent(); +} +inline void TextChatData::set_msgcontent(const std::string& value) { + _internal_set_msgcontent(value); + // @@protoc_insertion_point(field_set:message.TextChatData.msgcontent) +} +inline std::string* TextChatData::mutable_msgcontent() { + // @@protoc_insertion_point(field_mutable:message.TextChatData.msgcontent) + return _internal_mutable_msgcontent(); +} +inline const std::string& TextChatData::_internal_msgcontent() const { + return msgcontent_.Get(); +} +inline void TextChatData::_internal_set_msgcontent(const std::string& value) { + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void TextChatData::set_msgcontent(std::string&& value) { + + msgcontent_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.TextChatData.msgcontent) +} +inline void TextChatData::set_msgcontent(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.TextChatData.msgcontent) +} +inline void TextChatData::set_msgcontent(const char* value, + size_t size) { + + msgcontent_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.TextChatData.msgcontent) +} +inline std::string* TextChatData::_internal_mutable_msgcontent() { + + return msgcontent_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* TextChatData::release_msgcontent() { + // @@protoc_insertion_point(field_release:message.TextChatData.msgcontent) + return msgcontent_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void TextChatData::set_allocated_msgcontent(std::string* msgcontent) { + if (msgcontent != nullptr) { + + } else { + + } + msgcontent_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), msgcontent, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.TextChatData.msgcontent) +} + +// string chat_time = 4; +inline void TextChatData::clear_chat_time() { + chat_time_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& TextChatData::chat_time() const { + // @@protoc_insertion_point(field_get:message.TextChatData.chat_time) + return _internal_chat_time(); +} +inline void TextChatData::set_chat_time(const std::string& value) { + _internal_set_chat_time(value); + // @@protoc_insertion_point(field_set:message.TextChatData.chat_time) +} +inline std::string* TextChatData::mutable_chat_time() { + // @@protoc_insertion_point(field_mutable:message.TextChatData.chat_time) + return _internal_mutable_chat_time(); +} +inline const std::string& TextChatData::_internal_chat_time() const { + return chat_time_.Get(); +} +inline void TextChatData::_internal_set_chat_time(const std::string& value) { + + chat_time_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void TextChatData::set_chat_time(std::string&& value) { + + chat_time_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.TextChatData.chat_time) +} +inline void TextChatData::set_chat_time(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + chat_time_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.TextChatData.chat_time) +} +inline void TextChatData::set_chat_time(const char* value, + size_t size) { + + chat_time_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.TextChatData.chat_time) +} +inline std::string* TextChatData::_internal_mutable_chat_time() { + + return chat_time_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* TextChatData::release_chat_time() { + // @@protoc_insertion_point(field_release:message.TextChatData.chat_time) + return chat_time_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void TextChatData::set_allocated_chat_time(std::string* chat_time) { + if (chat_time != nullptr) { + + } else { + + } + chat_time_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), chat_time, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.TextChatData.chat_time) +} + +// ------------------------------------------------------------------- + +// TextChatMsgRsp + +// int32 error = 1; +inline void TextChatMsgRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::error() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgRsp.error) + return _internal_error(); +} +inline void TextChatMsgRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void TextChatMsgRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgRsp.error) +} + +// int32 fromuid = 2; +inline void TextChatMsgRsp::clear_fromuid() { + fromuid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::_internal_fromuid() const { + return fromuid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::fromuid() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgRsp.fromuid) + return _internal_fromuid(); +} +inline void TextChatMsgRsp::_internal_set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + fromuid_ = value; +} +inline void TextChatMsgRsp::set_fromuid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_fromuid(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgRsp.fromuid) +} + +// int32 touid = 3; +inline void TextChatMsgRsp::clear_touid() { + touid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::_internal_touid() const { + return touid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::touid() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgRsp.touid) + return _internal_touid(); +} +inline void TextChatMsgRsp::_internal_set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + touid_ = value; +} +inline void TextChatMsgRsp::set_touid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_touid(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgRsp.touid) +} + +// int32 thread_id = 4; +inline void TextChatMsgRsp::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 TextChatMsgRsp::thread_id() const { + // @@protoc_insertion_point(field_get:message.TextChatMsgRsp.thread_id) + return _internal_thread_id(); +} +inline void TextChatMsgRsp::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void TextChatMsgRsp::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.TextChatMsgRsp.thread_id) +} + +// repeated .message.TextChatData textmsgs = 5; +inline int TextChatMsgRsp::_internal_textmsgs_size() const { + return textmsgs_.size(); +} +inline int TextChatMsgRsp::textmsgs_size() const { + return _internal_textmsgs_size(); +} +inline void TextChatMsgRsp::clear_textmsgs() { + textmsgs_.Clear(); +} +inline ::message::TextChatData* TextChatMsgRsp::mutable_textmsgs(int index) { + // @@protoc_insertion_point(field_mutable:message.TextChatMsgRsp.textmsgs) + return textmsgs_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >* +TextChatMsgRsp::mutable_textmsgs() { + // @@protoc_insertion_point(field_mutable_list:message.TextChatMsgRsp.textmsgs) + return &textmsgs_; +} +inline const ::message::TextChatData& TextChatMsgRsp::_internal_textmsgs(int index) const { + return textmsgs_.Get(index); +} +inline const ::message::TextChatData& TextChatMsgRsp::textmsgs(int index) const { + // @@protoc_insertion_point(field_get:message.TextChatMsgRsp.textmsgs) + return _internal_textmsgs(index); +} +inline ::message::TextChatData* TextChatMsgRsp::_internal_add_textmsgs() { + return textmsgs_.Add(); +} +inline ::message::TextChatData* TextChatMsgRsp::add_textmsgs() { + // @@protoc_insertion_point(field_add:message.TextChatMsgRsp.textmsgs) + return _internal_add_textmsgs(); +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::message::TextChatData >& +TextChatMsgRsp::textmsgs() const { + // @@protoc_insertion_point(field_list:message.TextChatMsgRsp.textmsgs) + return textmsgs_; +} + +// ------------------------------------------------------------------- + +// KickUserReq + +// int32 uid = 1; +inline void KickUserReq::clear_uid() { + uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserReq::_internal_uid() const { + return uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserReq::uid() const { + // @@protoc_insertion_point(field_get:message.KickUserReq.uid) + return _internal_uid(); +} +inline void KickUserReq::_internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + uid_ = value; +} +inline void KickUserReq::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_uid(value); + // @@protoc_insertion_point(field_set:message.KickUserReq.uid) +} + +// ------------------------------------------------------------------- + +// KickUserRsp + +// int32 error = 1; +inline void KickUserRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserRsp::error() const { + // @@protoc_insertion_point(field_get:message.KickUserRsp.error) + return _internal_error(); +} +inline void KickUserRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void KickUserRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.KickUserRsp.error) +} + +// int32 uid = 2; +inline void KickUserRsp::clear_uid() { + uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserRsp::_internal_uid() const { + return uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 KickUserRsp::uid() const { + // @@protoc_insertion_point(field_get:message.KickUserRsp.uid) + return _internal_uid(); +} +inline void KickUserRsp::_internal_set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + uid_ = value; +} +inline void KickUserRsp::set_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_uid(value); + // @@protoc_insertion_point(field_set:message.KickUserRsp.uid) +} + +// ------------------------------------------------------------------- + +// NotifyChatImgReq + +// int32 from_uid = 1; +inline void NotifyChatImgReq::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgReq::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgReq::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.from_uid) +} + +// int32 to_uid = 2; +inline void NotifyChatImgReq::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgReq::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgReq::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.to_uid) +} + +// int32 message_id = 3; +inline void NotifyChatImgReq::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgReq::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgReq::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.message_id) +} + +// string file_name = 4; +inline void NotifyChatImgReq::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgReq::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgReq::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgReq.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgReq::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgReq::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgReq::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgReq.file_name) +} +inline void NotifyChatImgReq::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgReq.file_name) +} +inline std::string* NotifyChatImgReq::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgReq::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgReq.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgReq::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgReq.file_name) +} + +// int64 total_size = 5; +inline void NotifyChatImgReq::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgReq::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgReq::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgReq::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.total_size) +} + +// int32 thread_id = 6; +inline void NotifyChatImgReq::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgReq::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgReq.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgReq::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgReq::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgReq.thread_id) +} + +// ------------------------------------------------------------------- + +// NotifyChatImgRsp + +// int32 error = 1; +inline void NotifyChatImgRsp::clear_error() { + error_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_error() const { + return error_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::error() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.error) + return _internal_error(); +} +inline void NotifyChatImgRsp::_internal_set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + + error_ = value; +} +inline void NotifyChatImgRsp::set_error(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_error(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.error) +} + +// int32 from_uid = 2; +inline void NotifyChatImgRsp::clear_from_uid() { + from_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_from_uid() const { + return from_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::from_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.from_uid) + return _internal_from_uid(); +} +inline void NotifyChatImgRsp::_internal_set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + from_uid_ = value; +} +inline void NotifyChatImgRsp::set_from_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_from_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.from_uid) +} + +// int32 to_uid = 3; +inline void NotifyChatImgRsp::clear_to_uid() { + to_uid_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_to_uid() const { + return to_uid_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::to_uid() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.to_uid) + return _internal_to_uid(); +} +inline void NotifyChatImgRsp::_internal_set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + + to_uid_ = value; +} +inline void NotifyChatImgRsp::set_to_uid(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_to_uid(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.to_uid) +} + +// int32 message_id = 4; +inline void NotifyChatImgRsp::clear_message_id() { + message_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_message_id() const { + return message_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::message_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.message_id) + return _internal_message_id(); +} +inline void NotifyChatImgRsp::_internal_set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + message_id_ = value; +} +inline void NotifyChatImgRsp::set_message_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_message_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.message_id) +} + +// string file_name = 5; +inline void NotifyChatImgRsp::clear_file_name() { + file_name_.ClearToEmpty(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline const std::string& NotifyChatImgRsp::file_name() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.file_name) + return _internal_file_name(); +} +inline void NotifyChatImgRsp::set_file_name(const std::string& value) { + _internal_set_file_name(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::mutable_file_name() { + // @@protoc_insertion_point(field_mutable:message.NotifyChatImgRsp.file_name) + return _internal_mutable_file_name(); +} +inline const std::string& NotifyChatImgRsp::_internal_file_name() const { + return file_name_.Get(); +} +inline void NotifyChatImgRsp::_internal_set_file_name(const std::string& value) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value, GetArena()); +} +inline void NotifyChatImgRsp::set_file_name(std::string&& value) { + + file_name_.Set( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArena()); + // @@protoc_insertion_point(field_set_rvalue:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value), + GetArena()); + // @@protoc_insertion_point(field_set_char:message.NotifyChatImgRsp.file_name) +} +inline void NotifyChatImgRsp::set_file_name(const char* value, + size_t size) { + + file_name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), GetArena()); + // @@protoc_insertion_point(field_set_pointer:message.NotifyChatImgRsp.file_name) +} +inline std::string* NotifyChatImgRsp::_internal_mutable_file_name() { + + return file_name_.Mutable(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline std::string* NotifyChatImgRsp::release_file_name() { + // @@protoc_insertion_point(field_release:message.NotifyChatImgRsp.file_name) + return file_name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena()); +} +inline void NotifyChatImgRsp::set_allocated_file_name(std::string* file_name) { + if (file_name != nullptr) { + + } else { + + } + file_name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), file_name, + GetArena()); + // @@protoc_insertion_point(field_set_allocated:message.NotifyChatImgRsp.file_name) +} + +// int64 total_size = 6; +inline void NotifyChatImgRsp::clear_total_size() { + total_size_ = PROTOBUF_LONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::_internal_total_size() const { + return total_size_; +} +inline ::PROTOBUF_NAMESPACE_ID::int64 NotifyChatImgRsp::total_size() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.total_size) + return _internal_total_size(); +} +inline void NotifyChatImgRsp::_internal_set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + + total_size_ = value; +} +inline void NotifyChatImgRsp::set_total_size(::PROTOBUF_NAMESPACE_ID::int64 value) { + _internal_set_total_size(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.total_size) +} + +// int32 thread_id = 7; +inline void NotifyChatImgRsp::clear_thread_id() { + thread_id_ = 0; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::_internal_thread_id() const { + return thread_id_; +} +inline ::PROTOBUF_NAMESPACE_ID::int32 NotifyChatImgRsp::thread_id() const { + // @@protoc_insertion_point(field_get:message.NotifyChatImgRsp.thread_id) + return _internal_thread_id(); +} +inline void NotifyChatImgRsp::_internal_set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + + thread_id_ = value; +} +inline void NotifyChatImgRsp::set_thread_id(::PROTOBUF_NAMESPACE_ID::int32 value) { + _internal_set_thread_id(value); + // @@protoc_insertion_point(field_set:message.NotifyChatImgRsp.thread_id) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace message + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_message_2eproto diff --git a/server/ResourceServer/message.proto b/server/ResourceServer/message.proto new file mode 100644 index 0000000..7177b02 --- /dev/null +++ b/server/ResourceServer/message.proto @@ -0,0 +1,168 @@ +syntax = "proto3"; + +package message; + +service VarifyService { + rpc GetVarifyCode (GetVarifyReq) returns (GetVarifyRsp) {} +} + +message GetVarifyReq { + string email = 1; +} + +message GetVarifyRsp { + int32 error = 1; + string email = 2; + string code = 3; +} + +message GetChatServerReq { + int32 uid = 1; +} + +message GetChatServerRsp { + int32 error = 1; + string host = 2; + string port = 3; + string token = 4; +} + +message LoginReq{ + int32 uid = 1; + string token= 2; +} + +message LoginRsp { + int32 error = 1; + int32 uid = 2; + string token = 3; +} + +service StatusService { + rpc GetChatServer (GetChatServerReq) returns (GetChatServerRsp) {} + rpc Login(LoginReq) returns(LoginRsp); +} + +message AddFriendReq { + int32 applyuid = 1; + string name = 2; + string desc = 3; + string icon = 4; + string nick = 5; + int32 sex = 6; + int32 touid = 7; +} + +message AddFriendRsp { + int32 error = 1; + int32 applyuid = 2; + int32 touid = 3; +} + +message RplyFriendReq { + int32 rplyuid = 1; + bool agree = 2; + int32 touid = 3; +} + +message RplyFriendRsp { + int32 error = 1; + int32 rplyuid = 2; + int32 touid = 3; +} + +message SendChatMsgReq{ + int32 fromuid = 1; + int32 touid = 2; + string message = 3; +} + +message SendChatMsgRsp{ + int32 error = 1; + int32 fromuid = 2; + int32 touid = 3; +} + +message AddFriendMsg{ + int32 sender_id = 1; + string unique_id = 2; + int32 msg_id = 3; + int32 thread_id = 4; + string msgcontent = 5; + int32 status = 6; +} + +message AuthFriendReq{ + int32 fromuid = 1; + int32 touid = 2; + repeated AddFriendMsg textmsgs = 3; +} + +message AuthFriendRsp{ + int32 error = 1; + int32 fromuid = 2; + int32 touid = 3; +} + +message TextChatMsgReq { + int32 fromuid = 1; + int32 touid = 2; + int32 thread_id = 3; + repeated TextChatData textmsgs = 4; +} + +message TextChatData{ + string unique_id = 1; + int32 msg_id = 2; + string msgcontent = 3; + string chat_time = 4; +} + +message TextChatMsgRsp { + int32 error = 1; + int32 fromuid = 2; + int32 touid = 3; + int32 thread_id = 4; + repeated TextChatData textmsgs = 5; +} + +message KickUserReq{ + int32 uid = 1; +} + +message KickUserRsp{ + int32 error = 1; + int32 uid = 2; +} + +message NotifyChatImgReq{ + int32 from_uid = 1; + int32 to_uid = 2; + int32 message_id = 3; + string file_name = 4; + int64 total_size = 5; + int32 thread_id =6; +} + +message NotifyChatImgRsp{ + int32 error = 1; + int32 from_uid = 2; + int32 to_uid = 3; + int32 message_id = 4; + string file_name = 5; + int64 total_size = 6; + int32 thread_id =7; +} + +service ChatService { + rpc NotifyAddFriend(AddFriendReq) returns (AddFriendRsp) {} + rpc RplyAddFriend(RplyFriendReq) returns (RplyFriendRsp) {} + rpc SendChatMsg(SendChatMsgReq) returns (SendChatMsgRsp) {} + rpc NotifyAuthFriend(AuthFriendReq) returns (AuthFriendRsp) {} + rpc NotifyTextChatMsg(TextChatMsgReq) returns (TextChatMsgRsp){} + rpc NotifyKickUser(KickUserReq) returns (KickUserRsp){} + rpc NotifyChatImgMsg(NotifyChatImgReq) returns (NotifyChatImgRsp){} +} + + + diff --git a/server/ResourceServer/mysqlcppconn-9-vs14.dll b/server/ResourceServer/mysqlcppconn-9-vs14.dll new file mode 100644 index 0000000..93ad27e Binary files /dev/null and b/server/ResourceServer/mysqlcppconn-9-vs14.dll differ diff --git a/server/ResourceServer/mysqlcppconn8-2-vs14.dll b/server/ResourceServer/mysqlcppconn8-2-vs14.dll new file mode 100644 index 0000000..8952a2e Binary files /dev/null and b/server/ResourceServer/mysqlcppconn8-2-vs14.dll differ diff --git a/server/ResourceServer/start.bat b/server/ResourceServer/start.bat new file mode 100644 index 0000000..93a65ba --- /dev/null +++ b/server/ResourceServer/start.bat @@ -0,0 +1,12 @@ +@echo off +set PROTOC_PATH=D:\cppsoft\grpc\visualpro\third_party\protobuf\Debug\protoc.exe +set GRPC_PLUGIN_PATH=D:\cppsoft\grpc\visualpro\Debug\grpc_cpp_plugin.exe +set PROTO_FILE=message.proto + +echo Generating gRPC code... +%PROTOC_PATH% -I="." --grpc_out="." --plugin=protoc-gen-grpc="%GRPC_PLUGIN_PATH%" "%PROTO_FILE%" + +echo Generating C++ code... +%PROTOC_PATH% --cpp_out=. "%PROTO_FILE%" + +echo Done. \ No newline at end of file diff --git a/server/StatusServer/RedisMgr.cpp b/server/StatusServer/RedisMgr.cpp index 596ae20..4f5a62c 100644 --- a/server/StatusServer/RedisMgr.cpp +++ b/server/StatusServer/RedisMgr.cpp @@ -78,6 +78,41 @@ bool RedisMgr::Set(const std::string &key, const std::string &value){ return true; } + +bool RedisMgr::SetWithExpire(const std::string& key, const std::string& value, int expire_seconds) { + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + + // ʹSETEXͬʱֵ͹ʱ + auto reply = (redisReply*)redisCommand(connect, "SETEX %s %d %s", + key.c_str(), expire_seconds, value.c_str()); + + if (NULL == reply) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure!" << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (!(reply->type == REDIS_REPLY_STATUS && + (strcmp(reply->str, "OK") == 0 || strcmp(reply->str, "ok") == 0))) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure!" << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + freeReplyObject(reply); + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] success!" << std::endl; + _con_pool->returnConnection(connect); + return true; +} + + bool RedisMgr::LPush(const std::string &key, const std::string &value) { auto connect = _con_pool->getConnection(); diff --git a/server/StatusServer/RedisMgr.h b/server/StatusServer/RedisMgr.h index d30282c..5b2ad4a 100644 --- a/server/StatusServer/RedisMgr.h +++ b/server/StatusServer/RedisMgr.h @@ -269,6 +269,7 @@ class RedisMgr: public Singleton, ~RedisMgr(); bool Get(const std::string &key, std::string& value); bool Set(const std::string &key, const std::string &value); + bool SetWithExpire(const std::string& key, const std::string& value, int expire_seconds); bool LPush(const std::string &key, const std::string &value); bool LPop(const std::string &key, std::string& value); bool RPush(const std::string& key, const std::string& value); diff --git "a/sql\345\244\207\344\273\275/chat_message.sql" "b/sql\345\244\207\344\273\275/chat_message.sql" new file mode 100644 index 0000000..15e5cc4 --- /dev/null +++ "b/sql\345\244\207\344\273\275/chat_message.sql" @@ -0,0 +1,38 @@ +/* + Navicat Premium Data Transfer + + Source Server : llfcmysql + Source Server Type : MySQL + Source Server Version : 80027 (8.0.27) + Source Host : 81.68.86.146:3308 + Source Schema : llfc + + Target Server Type : MySQL + Target Server Version : 80027 (8.0.27) + File Encoding : 65001 + + Date: 24/07/2025 18:01:29 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for chat_message +-- ---------------------------- +DROP TABLE IF EXISTS `chat_message`; +CREATE TABLE `chat_message` ( + `message_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `thread_id` bigint UNSIGNED NOT NULL, + `sender_id` bigint UNSIGNED NOT NULL, + `recv_id` bigint UNSIGNED NOT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `status` tinyint NOT NULL DEFAULT 0 COMMENT '0=未读 1=已读 2=撤回', + PRIMARY KEY (`message_id`) USING BTREE, + INDEX `idx_thread_created`(`thread_id` ASC, `created_at` ASC) USING BTREE, + INDEX `idx_thread_message`(`thread_id` ASC, `message_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 35 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; + +SET FOREIGN_KEY_CHECKS = 1; diff --git "a/sql\345\244\207\344\273\275/llfc.sql" "b/sql\345\244\207\344\273\275/llfc.sql" index 5c4d46d..10edfe3 100644 --- "a/sql\345\244\207\344\273\275/llfc.sql" +++ "b/sql\345\244\207\344\273\275/llfc.sql" @@ -1,7 +1,7 @@ /* Navicat Premium Data Transfer - Source Server : llfcmysql + Source Server : chat_server Source Server Type : MySQL Source Server Version : 80027 (8.0.27) Source Host : 81.68.86.146:3308 @@ -11,12 +11,168 @@ Target Server Version : 80027 (8.0.27) File Encoding : 65001 - Date: 03/08/2024 19:53:45 + Date: 07/02/2026 19:56:11 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; +-- ---------------------------- +-- Table structure for chat_message +-- ---------------------------- +DROP TABLE IF EXISTS `chat_message`; +CREATE TABLE `chat_message` ( + `message_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `thread_id` bigint UNSIGNED NOT NULL, + `sender_id` bigint UNSIGNED NOT NULL, + `recv_id` bigint UNSIGNED NOT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `status` tinyint NOT NULL DEFAULT 0 COMMENT '0=未读 1=已读 2=撤回', + `msg_type` tinyint NOT NULL DEFAULT 0 COMMENT '0=文本 1=图片 2=视频 3=文件', + PRIMARY KEY (`message_id`) USING BTREE, + INDEX `idx_thread_created`(`thread_id` ASC, `created_at` ASC) USING BTREE, + INDEX `idx_thread_message`(`thread_id` ASC, `message_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 355 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of chat_message +-- ---------------------------- +INSERT INTO `chat_message` VALUES (33, 35, 1002, 1019, '您好,我是llfc', '2025-07-02 06:41:08', '2025-07-24 08:27:45', 2, 0); +INSERT INTO `chat_message` VALUES (34, 35, 1019, 1002, 'We are friends now!', '2025-07-02 06:41:08', '2025-07-24 08:27:39', 2, 0); +INSERT INTO `chat_message` VALUES (35, 35, 1002, 1019, '你好,很高兴认识你', '2025-07-24 21:36:30', '2025-07-24 21:36:30', 2, 0); +INSERT INTO `chat_message` VALUES (36, 35, 1019, 1002, '我也是,很高兴认识你', '2025-07-24 21:36:43', '2025-07-24 21:36:43', 2, 0); +INSERT INTO `chat_message` VALUES (37, 35, 1019, 1002, '中午吃点什么?', '2025-07-25 22:48:04', '2025-07-25 22:48:04', 2, 0); +INSERT INTO `chat_message` VALUES (38, 35, 1002, 1019, '现在外卖三国杀,折扣力度大,赶紧薅羊毛', '2025-07-25 22:48:36', '2025-07-25 22:48:36', 2, 0); +INSERT INTO `chat_message` VALUES (39, 35, 1019, 1002, '刚看了下,我得了一个25减25的券,我去订外卖去了', '2025-07-25 23:09:26', '2025-07-25 23:09:26', 2, 0); +INSERT INTO `chat_message` VALUES (40, 35, 1002, 1019, '我怎么没看到,你在哪个平台?', '2025-07-25 23:09:40', '2025-07-25 23:09:40', 2, 0); +INSERT INTO `chat_message` VALUES (41, 35, 1019, 1002, '我看错了,那不是外卖券,那是超市打折券', '2025-07-25 23:10:20', '2025-07-25 23:10:20', 2, 0); +INSERT INTO `chat_message` VALUES (42, 35, 1019, 1002, '好吧,那我还是去看看外卖活动', '2025-07-27 09:07:21', '2025-07-27 09:07:21', 2, 0); +INSERT INTO `chat_message` VALUES (43, 35, 1002, 1019, '嗯,有什么推荐的外卖可以告诉我', '2025-07-27 09:07:37', '2025-07-27 09:07:37', 2, 0); +INSERT INTO `chat_message` VALUES (44, 35, 1019, 1002, '汉堡炸鸡怎么样?要不要一起订', '2025-07-29 17:40:20', '2025-07-29 17:40:20', 2, 0); +INSERT INTO `chat_message` VALUES (45, 36, 1176, 1175, '您好,我是yulinyi', '2025-08-22 03:07:31', '2025-08-22 03:07:31', 2, 0); +INSERT INTO `chat_message` VALUES (46, 36, 1175, 1176, 'We are friends now!', '2025-08-22 03:07:31', '2025-08-22 03:07:31', 2, 0); +INSERT INTO `chat_message` VALUES (47, 0, 1175, 1176, '你好', '2025-08-22 11:07:45', '2025-08-22 11:07:45', 2, 0); +INSERT INTO `chat_message` VALUES (48, 0, 1176, 1175, '你好', '2025-08-22 11:08:14', '2025-08-22 11:08:14', 2, 0); +INSERT INTO `chat_message` VALUES (49, 0, 1175, 1176, '怎么了', '2025-08-22 11:08:31', '2025-08-22 11:08:31', 2, 0); +INSERT INTO `chat_message` VALUES (50, 0, 1176, 1175, 'xiaodaji', '2025-08-22 11:09:09', '2025-08-22 11:09:09', 2, 0); +INSERT INTO `chat_message` VALUES (51, 0, 1175, 1176, 'lisishei', '2025-08-22 11:09:19', '2025-08-22 11:09:19', 2, 0); +INSERT INTO `chat_message` VALUES (52, 0, 1176, 1175, 'xiaohongshu', '2025-08-22 19:14:59', '2025-08-22 19:14:59', 2, 0); +INSERT INTO `chat_message` VALUES (53, 0, 1175, 1176, '你真是一个', '2025-08-23 14:29:29', '2025-08-23 14:29:29', 2, 0); +INSERT INTO `chat_message` VALUES (54, 0, 1175, 1176, 'ruhe', '2025-08-23 14:33:27', '2025-08-23 14:33:27', 2, 0); +INSERT INTO `chat_message` VALUES (55, 0, 1175, 1176, '666', '2025-08-23 14:33:42', '2025-08-23 14:33:42', 2, 0); +INSERT INTO `chat_message` VALUES (56, 0, 1175, 1176, '6666666', '2025-08-23 14:34:59', '2025-08-23 14:34:59', 2, 0); +INSERT INTO `chat_message` VALUES (57, 0, 1175, 1176, '1314142', '2025-08-23 14:50:01', '2025-08-23 14:50:01', 2, 0); +INSERT INTO `chat_message` VALUES (58, 0, 1175, 1176, '999', '2025-08-23 14:52:50', '2025-08-23 14:52:50', 2, 0); +INSERT INTO `chat_message` VALUES (59, 0, 1175, 1176, '0000000000000', '2025-08-23 15:13:43', '2025-08-23 15:13:43', 2, 0); +INSERT INTO `chat_message` VALUES (60, 0, 1175, 1176, 'aaaaaa', '2025-08-23 15:32:37', '2025-08-23 15:32:37', 2, 0); +INSERT INTO `chat_message` VALUES (61, 0, 1176, 1175, '909090', '2025-08-23 15:50:31', '2025-08-23 15:50:31', 2, 0); +INSERT INTO `chat_message` VALUES (62, 0, 1175, 1176, '007', '2025-08-23 16:00:40', '2025-08-23 16:00:40', 2, 0); +INSERT INTO `chat_message` VALUES (63, 0, 1175, 1176, 'bbbbbbb', '2025-08-23 16:30:29', '2025-08-23 16:30:29', 2, 0); +INSERT INTO `chat_message` VALUES (64, 0, 1175, 1176, 'ccccccc', '2025-08-23 16:43:35', '2025-08-23 16:43:35', 2, 0); +INSERT INTO `chat_message` VALUES (65, 0, 1175, 1176, 'xiaoshengbuxi', '2025-08-23 16:55:03', '2025-08-23 16:55:03', 2, 0); +INSERT INTO `chat_message` VALUES (66, 0, 1175, 1176, 'shengsi', '2025-08-23 17:02:41', '2025-08-23 17:02:41', 2, 0); +INSERT INTO `chat_message` VALUES (67, 0, 1176, 1175, 'whoareyou', '2025-08-23 17:11:41', '2025-08-23 17:11:41', 2, 0); +INSERT INTO `chat_message` VALUES (68, 0, 1175, 1176, 'xiao666', '2025-08-23 17:27:58', '2025-08-23 17:27:58', 2, 0); +INSERT INTO `chat_message` VALUES (69, 0, 1176, 1175, 'niye666', '2025-08-23 17:28:10', '2025-08-23 17:28:10', 2, 0); +INSERT INTO `chat_message` VALUES (70, 0, 1175, 1176, 'liubi', '2025-08-23 17:28:26', '2025-08-23 17:28:26', 2, 0); +INSERT INTO `chat_message` VALUES (71, 0, 1176, 1175, 'xiuer', '2025-08-23 17:28:38', '2025-08-23 17:28:38', 2, 0); +INSERT INTO `chat_message` VALUES (72, 0, 1176, 1175, 'nizhenniubi', '2025-08-23 17:38:43', '2025-08-23 17:38:43', 2, 0); +INSERT INTO `chat_message` VALUES (73, 0, 1175, 1176, '你也是', '2025-08-23 17:39:00', '2025-08-23 17:39:00', 2, 0); +INSERT INTO `chat_message` VALUES (74, 0, 1176, 1175, 'jizhenliu', '2025-08-23 17:39:08', '2025-08-23 17:39:08', 2, 0); +INSERT INTO `chat_message` VALUES (75, 0, 1175, 1176, '666', '2025-08-23 18:05:08', '2025-08-23 18:05:08', 2, 0); +INSERT INTO `chat_message` VALUES (76, 0, 1176, 1175, 'niyeliu', '2025-08-23 18:05:22', '2025-08-23 18:05:22', 2, 0); +INSERT INTO `chat_message` VALUES (77, 0, 1175, 1176, '00000', '2025-08-23 18:06:26', '2025-08-23 18:06:26', 2, 0); +INSERT INTO `chat_message` VALUES (78, 0, 1176, 1175, '77777', '2025-08-23 18:06:37', '2025-08-23 18:06:37', 2, 0); +INSERT INTO `chat_message` VALUES (79, 0, 1176, 1175, '1111111', '2025-08-23 18:07:21', '2025-08-23 18:07:21', 2, 0); +INSERT INTO `chat_message` VALUES (80, 0, 1176, 1175, 'lxxx', '2025-08-23 18:08:12', '2025-08-23 18:08:12', 2, 0); +INSERT INTO `chat_message` VALUES (81, 0, 1176, 1175, 'xxxxxxxx', '2025-08-23 18:18:28', '2025-08-23 18:18:28', 2, 0); +INSERT INTO `chat_message` VALUES (82, 0, 1176, 1175, 'shengshengbuxi', '2025-08-25 11:35:10', '2025-08-25 11:35:10', 2, 0); +INSERT INTO `chat_message` VALUES (83, 0, 1175, 1176, 'llllll', '2025-08-25 11:44:14', '2025-08-25 11:44:14', 2, 0); +INSERT INTO `chat_message` VALUES (84, 0, 1176, 1175, 'mmmmmmm', '2025-08-25 11:44:55', '2025-08-25 11:44:55', 2, 0); +INSERT INTO `chat_message` VALUES (85, 0, 1175, 1176, 'xxx', '2025-08-25 12:27:04', '2025-08-25 12:27:04', 2, 0); +INSERT INTO `chat_message` VALUES (86, 0, 1176, 1175, 'ddd', '2025-08-25 12:27:13', '2025-08-25 12:27:13', 2, 0); +INSERT INTO `chat_message` VALUES (87, 0, 1175, 1176, 'VVVVV', '2025-08-25 12:47:53', '2025-08-25 12:47:53', 2, 0); +INSERT INTO `chat_message` VALUES (88, 0, 1176, 1175, 'BBBBB', '2025-08-25 12:48:12', '2025-08-25 12:48:12', 2, 0); +INSERT INTO `chat_message` VALUES (89, 0, 1175, 1176, 'XXX', '2025-08-25 13:00:19', '2025-08-25 13:00:19', 2, 0); +INSERT INTO `chat_message` VALUES (90, 0, 1176, 1175, 'CCC', '2025-08-25 13:00:41', '2025-08-25 13:00:41', 2, 0); +INSERT INTO `chat_message` VALUES (91, 0, 1176, 1175, 'BBBB', '2025-08-25 13:01:41', '2025-08-25 13:01:41', 2, 0); +INSERT INTO `chat_message` VALUES (92, 0, 1176, 1175, '111', '2025-08-25 13:02:23', '2025-08-25 13:02:23', 2, 0); +INSERT INTO `chat_message` VALUES (93, 0, 1176, 1175, 'dddccc', '2025-08-25 13:02:50', '2025-08-25 13:02:50', 2, 0); +INSERT INTO `chat_message` VALUES (94, 0, 1175, 1176, 'xiaosheng', '2025-08-25 14:21:37', '2025-08-25 14:21:37', 2, 0); +INSERT INTO `chat_message` VALUES (95, 0, 1176, 1175, 'lingyi', '2025-08-25 14:22:07', '2025-08-25 14:22:07', 2, 0); +INSERT INTO `chat_message` VALUES (96, 0, 1175, 1176, 'mmmmmm', '2025-08-25 15:10:57', '2025-08-25 15:10:57', 2, 0); +INSERT INTO `chat_message` VALUES (97, 0, 1176, 1175, '555', '2025-08-25 15:14:32', '2025-08-25 15:14:32', 2, 0); +INSERT INTO `chat_message` VALUES (98, 0, 1175, 1176, 'liyue', '2025-08-25 16:25:15', '2025-08-25 16:25:15', 2, 0); +INSERT INTO `chat_message` VALUES (99, 0, 1176, 1175, 'mengde', '2025-08-25 16:25:38', '2025-08-25 16:25:38', 2, 0); +INSERT INTO `chat_message` VALUES (100, 0, 1175, 1176, 'xiaosheng', '2025-08-25 20:17:43', '2025-08-25 20:17:43', 2, 0); +INSERT INTO `chat_message` VALUES (101, 0, 1176, 1175, 'yulinyi', '2025-08-25 20:19:10', '2025-08-25 20:19:10', 2, 0); +INSERT INTO `chat_message` VALUES (102, 0, 1176, 1175, 'nihao', '2025-08-28 21:44:15', '2025-08-28 21:44:15', 2, 0); +INSERT INTO `chat_message` VALUES (103, 0, 1175, 1176, 'wobuhao', '2025-08-28 21:44:26', '2025-08-28 21:44:26', 2, 0); +INSERT INTO `chat_message` VALUES (104, 0, 1175, 1176, 'nice', '2025-08-28 21:44:34', '2025-08-28 21:44:34', 2, 0); +INSERT INTO `chat_message` VALUES (105, 0, 1176, 1175, 'bunice', '2025-08-28 21:44:41', '2025-08-28 21:44:41', 2, 0); +INSERT INTO `chat_message` VALUES (106, 0, 1176, 1175, 'ddddd', '2025-08-28 21:44:57', '2025-08-28 21:44:57', 2, 0); +INSERT INTO `chat_message` VALUES (107, 0, 1175, 1176, 'ccccc', '2025-08-28 21:45:01', '2025-08-28 21:45:01', 2, 0); +INSERT INTO `chat_message` VALUES (108, 0, 1175, 1176, '你好', '2025-10-09 23:33:53', '2025-10-09 23:33:53', 2, 0); +INSERT INTO `chat_message` VALUES (188, 0, 1175, 1176, 'nihao', '2025-12-20 17:24:49', '2025-12-20 17:24:49', 2, 0); +INSERT INTO `chat_message` VALUES (189, 0, 1175, 1176, 'nishishei', '2025-12-20 17:25:08', '2025-12-20 17:25:08', 2, 0); +INSERT INTO `chat_message` VALUES (190, 0, 1175, 1176, 'nishishei', '2025-12-20 17:25:39', '2025-12-20 17:25:39', 2, 0); +INSERT INTO `chat_message` VALUES (276, 40, 1267, 1268, '123', '2026-01-06 21:55:42', '2026-01-06 21:55:42', 2, 0); +INSERT INTO `chat_message` VALUES (277, 40, 1267, 1268, '4535434534', '2026-01-06 21:55:49', '2026-01-06 21:55:49', 2, 0); +INSERT INTO `chat_message` VALUES (278, 40, 1268, 1267, '123', '2026-01-06 21:57:20', '2026-01-06 21:57:20', 2, 0); +INSERT INTO `chat_message` VALUES (280, 41, 2179, 2181, '您好,我是saheun', '2026-01-30 02:20:52', '2026-01-30 02:20:52', 2, 0); +INSERT INTO `chat_message` VALUES (281, 41, 2181, 2179, 'We are friends now!', '2026-01-30 02:20:52', '2026-01-30 02:20:52', 2, 0); +INSERT INTO `chat_message` VALUES (282, 41, 2179, 2181, '1', '2026-01-30 10:21:04', '2026-01-30 10:21:04', 2, 0); +INSERT INTO `chat_message` VALUES (283, 41, 2179, 2181, '1234567', '2026-01-30 10:21:45', '2026-01-30 10:21:45', 2, 0); +INSERT INTO `chat_message` VALUES (284, 41, 2181, 2179, '123', '2026-01-30 11:44:19', '2026-01-30 11:44:19', 2, 0); +INSERT INTO `chat_message` VALUES (285, 42, 1019, 1005, 'We are friends now!', '2026-01-31 09:34:34', '2026-01-31 09:34:34', 2, 0); +INSERT INTO `chat_message` VALUES (286, 41, 2181, 2179, '测试model气泡', '2026-01-31 17:38:12', '2026-01-31 17:38:12', 2, 0); +INSERT INTO `chat_message` VALUES (287, 44, 1213, 1275, '您好,我是abc123', '2026-01-31 14:19:27', '2026-01-31 14:19:27', 2, 0); +INSERT INTO `chat_message` VALUES (288, 44, 1275, 1213, 'We are friends now!', '2026-01-31 14:19:27', '2026-01-31 14:19:27', 2, 0); +INSERT INTO `chat_message` VALUES (289, 44, 1275, 1213, '测试一下', '2026-02-01 14:16:17', '2026-02-01 14:16:17', 2, 0); +INSERT INTO `chat_message` VALUES (290, 45, 1275, 0, '测试一下这个群聊', '2026-02-01 19:30:40', '2026-02-01 19:30:40', 2, 0); +INSERT INTO `chat_message` VALUES (291, 45, 1213, 0, '好像现在没问题', '2026-02-01 19:30:57', '2026-02-01 19:30:57', 2, 0); +INSERT INTO `chat_message` VALUES (292, 46, 1275, 0, '这个呢', '2026-02-01 19:31:03', '2026-02-01 19:31:03', 2, 0); +INSERT INTO `chat_message` VALUES (293, 46, 1275, 0, 'nice兄弟,已经跑通,接下来是跨服', '2026-02-01 19:31:50', '2026-02-01 19:31:50', 2, 0); +INSERT INTO `chat_message` VALUES (294, 46, 1213, 0, '嗯', '2026-02-01 19:31:55', '2026-02-01 19:31:55', 2, 0); +INSERT INTO `chat_message` VALUES (295, 45, 1275, 0, '来吧,跨服务器的群聊', '2026-02-01 22:18:42', '2026-02-01 22:18:42', 2, 0); +INSERT INTO `chat_message` VALUES (296, 45, 1213, 0, '没收到,完蛋', '2026-02-01 22:20:05', '2026-02-01 22:20:05', 2, 0); +INSERT INTO `chat_message` VALUES (297, 45, 1213, 0, '测试1', '2026-02-01 22:43:53', '2026-02-01 22:43:53', 2, 0); +INSERT INTO `chat_message` VALUES (298, 45, 1213, 0, '测试2', '2026-02-01 22:55:11', '2026-02-01 22:55:11', 2, 0); +INSERT INTO `chat_message` VALUES (299, 45, 1275, 0, '成功收到测试2, 跨服务器的群聊已完成', '2026-02-01 22:55:59', '2026-02-01 22:55:59', 2, 0); +INSERT INTO `chat_message` VALUES (354, 35, 1002, 1019, '053ce9cc-a5ca-4990-bd96-a91e8fdbf359.png', '2026-02-06 17:08:32', '2026-02-06 09:09:04', 2, 1); + +-- ---------------------------- +-- Table structure for chat_thread +-- ---------------------------- +DROP TABLE IF EXISTS `chat_thread`; +CREATE TABLE `chat_thread` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `type` enum('private','group') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 50 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of chat_thread +-- ---------------------------- +INSERT INTO `chat_thread` VALUES (35, 'private', '2025-07-02 06:41:08'); +INSERT INTO `chat_thread` VALUES (36, 'private', '2025-08-22 03:07:31'); +INSERT INTO `chat_thread` VALUES (37, 'private', '2025-10-03 08:43:18'); +INSERT INTO `chat_thread` VALUES (38, 'private', '2025-12-09 10:00:37'); +INSERT INTO `chat_thread` VALUES (39, 'private', '2025-12-09 10:00:44'); +INSERT INTO `chat_thread` VALUES (40, 'private', '2026-01-06 13:55:39'); +INSERT INTO `chat_thread` VALUES (41, 'private', '2026-01-30 02:20:52'); +INSERT INTO `chat_thread` VALUES (42, 'private', '2026-01-31 09:34:34'); +INSERT INTO `chat_thread` VALUES (43, 'private', '2026-01-31 09:39:00'); +INSERT INTO `chat_thread` VALUES (44, 'private', '2026-01-31 14:19:27'); +INSERT INTO `chat_thread` VALUES (45, 'group', '2026-01-31 14:41:29'); +INSERT INTO `chat_thread` VALUES (46, 'group', '2026-01-31 14:53:29'); +INSERT INTO `chat_thread` VALUES (47, 'group', '2026-01-31 14:59:27'); +INSERT INTO `chat_thread` VALUES (48, 'group', '2026-01-31 15:11:13'); +INSERT INTO `chat_thread` VALUES (49, 'private', '2026-02-05 04:28:26'); + -- ---------------------------- -- Table structure for friend -- ---------------------------- @@ -28,7 +184,7 @@ CREATE TABLE `friend` ( `back` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `self_friend`(`self_id` ASC, `friend_id` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 89 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 619 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of friend @@ -38,9 +194,99 @@ INSERT INTO `friend` VALUES (56, 1054, 1055, ''); INSERT INTO `friend` VALUES (61, 1012, 1056, 'test28'); INSERT INTO `friend` VALUES (62, 1056, 1012, ''); INSERT INTO `friend` VALUES (63, 1012, 1050, 'test23'); -INSERT INTO `friend` VALUES (64, 1050, 1012, ''); -INSERT INTO `friend` VALUES (81, 1002, 1019, 'zack'); -INSERT INTO `friend` VALUES (82, 1019, 1002, ''); +INSERT INTO `friend` VALUES (89, 1038, 1037, 'chae'); +INSERT INTO `friend` VALUES (90, 1037, 1038, ''); +INSERT INTO `friend` VALUES (127, 2020, 2030, 'yyh'); +INSERT INTO `friend` VALUES (128, 2030, 2020, ''); +INSERT INTO `friend` VALUES (149, 2182, 2181, 'jmz'); +INSERT INTO `friend` VALUES (150, 2181, 2182, ''); +INSERT INTO `friend` VALUES (151, 1080, 1079, 'cpt1'); +INSERT INTO `friend` VALUES (152, 1079, 1080, ''); +INSERT INTO `friend` VALUES (155, 2020, 1090, 'yzmb'); +INSERT INTO `friend` VALUES (156, 1090, 2020, ''); +INSERT INTO `friend` VALUES (157, 1090, 2030, 'yyh'); +INSERT INTO `friend` VALUES (158, 2030, 1090, ''); +INSERT INTO `friend` VALUES (159, 2020, 1093, 'yzmb'); +INSERT INTO `friend` VALUES (160, 1093, 2020, ''); +INSERT INTO `friend` VALUES (161, 1093, 2030, 'yyh'); +INSERT INTO `friend` VALUES (162, 2030, 1093, ''); +INSERT INTO `friend` VALUES (163, 1085, 1079, 'cpt1'); +INSERT INTO `friend` VALUES (164, 1079, 1085, ''); +INSERT INTO `friend` VALUES (165, 1085, 1080, 'cpt2'); +INSERT INTO `friend` VALUES (166, 1080, 1085, ''); +INSERT INTO `friend` VALUES (167, 1087, 1094, 'ming'); +INSERT INTO `friend` VALUES (168, 1094, 1087, ''); +INSERT INTO `friend` VALUES (185, 1099, 1098, 'Fany'); +INSERT INTO `friend` VALUES (186, 1098, 1099, ''); +INSERT INTO `friend` VALUES (379, 1096, 1097, 'www'); +INSERT INTO `friend` VALUES (380, 1097, 1096, ''); +INSERT INTO `friend` VALUES (389, 1019, 1002, 'llfc'); +INSERT INTO `friend` VALUES (390, 1002, 1019, 'zack'); +INSERT INTO `friend` VALUES (391, 1120, 1122, 'Mrchang'); +INSERT INTO `friend` VALUES (392, 1122, 1120, ''); +INSERT INTO `friend` VALUES (393, 1121, 1120, 'KNO3'); +INSERT INTO `friend` VALUES (394, 1120, 1121, ''); +INSERT INTO `friend` VALUES (395, 1121, 1122, 'Mrchang'); +INSERT INTO `friend` VALUES (396, 1122, 1121, ''); +INSERT INTO `friend` VALUES (397, 1120, 1129, 'maotouying'); +INSERT INTO `friend` VALUES (398, 1129, 1120, ''); +INSERT INTO `friend` VALUES (401, 1120, 1134, 'gls'); +INSERT INTO `friend` VALUES (402, 1134, 1120, ''); +INSERT INTO `friend` VALUES (439, 1123, 1120, 'KNO3'); +INSERT INTO `friend` VALUES (440, 1120, 1123, ''); +INSERT INTO `friend` VALUES (441, 1123, 1126, 'jelly'); +INSERT INTO `friend` VALUES (442, 1126, 1123, ''); +INSERT INTO `friend` VALUES (469, 1003, 1008, 'zglx2008'); +INSERT INTO `friend` VALUES (470, 1008, 1003, ''); +INSERT INTO `friend` VALUES (471, 1142, 1114, 'zay'); +INSERT INTO `friend` VALUES (472, 1114, 1142, ''); +INSERT INTO `friend` VALUES (487, 1154, 1146, 'jmt'); +INSERT INTO `friend` VALUES (488, 1146, 1154, ''); +INSERT INTO `friend` VALUES (513, 1128, 1149, 'mwt'); +INSERT INTO `friend` VALUES (514, 1149, 1128, ''); +INSERT INTO `friend` VALUES (517, 1168, 1169, 'cbq'); +INSERT INTO `friend` VALUES (518, 1169, 1168, ''); +INSERT INTO `friend` VALUES (537, 1171, 1170, 'yanyan'); +INSERT INTO `friend` VALUES (538, 1170, 1171, ''); +INSERT INTO `friend` VALUES (539, 1175, 1176, '雨天'); +INSERT INTO `friend` VALUES (540, 1176, 1175, 'xiao'); +INSERT INTO `friend` VALUES (541, 1191, 1189, '我是沈梦洁'); +INSERT INTO `friend` VALUES (542, 1189, 1191, ''); +INSERT INTO `friend` VALUES (543, 1192, 1189, 'smj_网易'); +INSERT INTO `friend` VALUES (549, 1220, 1219, 'fxw'); +INSERT INTO `friend` VALUES (550, 1219, 1220, ''); +INSERT INTO `friend` VALUES (553, 1221, 1222, 'zhangzhihui 你好'); +INSERT INTO `friend` VALUES (554, 1222, 1221, ''); +INSERT INTO `friend` VALUES (555, 1221, 1219, 'fxw'); +INSERT INTO `friend` VALUES (556, 1219, 1221, ''); +INSERT INTO `friend` VALUES (567, 1258, 1257, 'sang'); +INSERT INTO `friend` VALUES (568, 1257, 1258, ''); +INSERT INTO `friend` VALUES (569, 1259, 1257, 'hpz'); +INSERT INTO `friend` VALUES (570, 1257, 1259, ''); +INSERT INTO `friend` VALUES (571, 1259, 1258, 'yan'); +INSERT INTO `friend` VALUES (572, 1258, 1259, ''); +INSERT INTO `friend` VALUES (573, 1250, 1251, 'zg'); +INSERT INTO `friend` VALUES (574, 1251, 1250, ''); +INSERT INTO `friend` VALUES (579, 1002, 1250, 'lfh'); +INSERT INTO `friend` VALUES (580, 1250, 1002, ''); +INSERT INTO `friend` VALUES (581, 1060, 1059, 'a'); +INSERT INTO `friend` VALUES (582, 1059, 1060, ''); +INSERT INTO `friend` VALUES (599, 1267, 1268, '我是1267'); +INSERT INTO `friend` VALUES (600, 1268, 1267, ''); +INSERT INTO `friend` VALUES (605, 1272, 1271, 'cat'); +INSERT INTO `friend` VALUES (606, 1271, 1272, ''); +INSERT INTO `friend` VALUES (607, 1274, 1273, 'kawa'); +INSERT INTO `friend` VALUES (608, 1273, 1274, ''); +INSERT INTO `friend` VALUES (609, 1278, 1257, '郝培智'); +INSERT INTO `friend` VALUES (610, 1257, 1278, ''); +INSERT INTO `friend` VALUES (611, 1062, 1061, 'lxh1'); +INSERT INTO `friend` VALUES (612, 1061, 1062, ''); +INSERT INTO `friend` VALUES (613, 2179, 2181, 'jmz'); +INSERT INTO `friend` VALUES (614, 2181, 2179, 'saheun'); +INSERT INTO `friend` VALUES (615, 1005, 1019, ''); +INSERT INTO `friend` VALUES (616, 1019, 1005, 'test'); +INSERT INTO `friend` VALUES (617, 1213, 1275, 'suliu'); +INSERT INTO `friend` VALUES (618, 1275, 1213, 'abc123'); -- ---------------------------- -- Table structure for friend_apply @@ -51,18 +297,168 @@ CREATE TABLE `friend_apply` ( `from_uid` int NOT NULL, `to_uid` int NOT NULL, `status` smallint NOT NULL DEFAULT 0, + `descs` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', + `back_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `from_to_uid`(`from_uid` ASC, `to_uid` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 68 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; +) ENGINE = InnoDB AUTO_INCREMENT = 451 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of friend_apply -- ---------------------------- -INSERT INTO `friend_apply` VALUES (6, 1023, 1002, 0); -INSERT INTO `friend_apply` VALUES (49, 1054, 1055, 1); -INSERT INTO `friend_apply` VALUES (52, 1056, 1012, 0); -INSERT INTO `friend_apply` VALUES (63, 1019, 1002, 1); -INSERT INTO `friend_apply` VALUES (64, 1032, 1035, 0); +INSERT INTO `friend_apply` VALUES (253, 1002, 1019, 1, '您好,我是llfc', 'zack'); +INSERT INTO `friend_apply` VALUES (254, 1122, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (255, 1122, 1121, 1, '', ''); +INSERT INTO `friend_apply` VALUES (257, 1120, 1121, 1, '', ''); +INSERT INTO `friend_apply` VALUES (258, 1129, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (260, 1120, 1123, 1, '', ''); +INSERT INTO `friend_apply` VALUES (262, 1134, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (271, 1126, 1123, 1, '', ''); +INSERT INTO `friend_apply` VALUES (272, 1132, 1002, 0, '', ''); +INSERT INTO `friend_apply` VALUES (273, 0, 1142, 0, '', ''); +INSERT INTO `friend_apply` VALUES (275, 0, 1114, 0, '', ''); +INSERT INTO `friend_apply` VALUES (276, 1008, 1003, 1, '', ''); +INSERT INTO `friend_apply` VALUES (278, 0, 1058, 0, '', ''); +INSERT INTO `friend_apply` VALUES (279, 0, 1055, 0, '', ''); +INSERT INTO `friend_apply` VALUES (281, 1114, 1142, 1, '', ''); +INSERT INTO `friend_apply` VALUES (306, 1161, 1154, 0, '', ''); +INSERT INTO `friend_apply` VALUES (323, 1149, 1128, 1, '', ''); +INSERT INTO `friend_apply` VALUES (341, 1169, 1168, 0, '', ''); +INSERT INTO `friend_apply` VALUES (353, 1170, 1171, 1, '', ''); +INSERT INTO `friend_apply` VALUES (355, 1175, 1176, 0, '您好,我是xiao', 'yulinyi'); +INSERT INTO `friend_apply` VALUES (356, 1176, 1175, 1, '您好,我是yulinyi', 'xiao'); +INSERT INTO `friend_apply` VALUES (357, 1189, 1191, 1, '', ''); +INSERT INTO `friend_apply` VALUES (358, 1189, 1192, 1, '', ''); +INSERT INTO `friend_apply` VALUES (382, 1219, 1220, 1, '', ''); +INSERT INTO `friend_apply` VALUES (383, 1221, 1220, 0, '', ''); +INSERT INTO `friend_apply` VALUES (384, 1222, 1221, 1, '', ''); +INSERT INTO `friend_apply` VALUES (385, 1219, 1221, 0, '', ''); +INSERT INTO `friend_apply` VALUES (405, 1257, 1258, 1, '', ''); +INSERT INTO `friend_apply` VALUES (406, 1257, 1259, 1, '', ''); +INSERT INTO `friend_apply` VALUES (407, 1258, 1259, 0, '', ''); +INSERT INTO `friend_apply` VALUES (408, 1251, 1250, 0, '', ''); +INSERT INTO `friend_apply` VALUES (409, 1250, 1002, 0, '', ''); +INSERT INTO `friend_apply` VALUES (411, 3, 1019, 0, '', ''); +INSERT INTO `friend_apply` VALUES (412, 1060, 1002, 0, '', ''); +INSERT INTO `friend_apply` VALUES (413, 1060, 1019, 0, '', ''); +INSERT INTO `friend_apply` VALUES (414, 1059, 1002, 0, '', ''); +INSERT INTO `friend_apply` VALUES (415, 1059, 1060, 1, '', ''); +INSERT INTO `friend_apply` VALUES (433, 1268, 1252, 0, '', ''); +INSERT INTO `friend_apply` VALUES (434, 1268, 1267, 1, '', ''); +INSERT INTO `friend_apply` VALUES (435, 1267, 1268, 1, '', ''); +INSERT INTO `friend_apply` VALUES (437, 1271, 1272, 1, '', ''); +INSERT INTO `friend_apply` VALUES (438, 1273, 1274, 1, '', ''); +INSERT INTO `friend_apply` VALUES (439, 1257, 1278, 1, '', ''); +INSERT INTO `friend_apply` VALUES (440, 1008, 1005, 0, '', ''); +INSERT INTO `friend_apply` VALUES (442, 1005, 1019, 1, '', ''); +INSERT INTO `friend_apply` VALUES (443, 1062, 1019, 0, '', ''); +INSERT INTO `friend_apply` VALUES (445, 1061, 1062, 1, '', ''); +INSERT INTO `friend_apply` VALUES (446, 2179, 2181, 1, '您好,我是saheun', 'jmz'); +INSERT INTO `friend_apply` VALUES (448, 1213, 1275, 1, '您好,我是abc123', 'suliu'); +INSERT INTO `friend_apply` VALUES (449, 1280, 1002, 0, '', ''); + +-- ---------------------------- +-- Table structure for group_chat +-- ---------------------------- +DROP TABLE IF EXISTS `group_chat`; +CREATE TABLE `group_chat` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '群聊名称', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of group_chat +-- ---------------------------- +INSERT INTO `group_chat` VALUES (45, NULL, '2026-01-31 14:41:30'); +INSERT INTO `group_chat` VALUES (46, NULL, '2026-01-31 14:53:29'); +INSERT INTO `group_chat` VALUES (47, NULL, '2026-01-31 14:59:28'); +INSERT INTO `group_chat` VALUES (48, NULL, '2026-01-31 15:11:14'); + +-- ---------------------------- +-- Table structure for group_chat_member +-- ---------------------------- +DROP TABLE IF EXISTS `group_chat_member`; +CREATE TABLE `group_chat_member` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用 group_chat_thread.thread_id', + `user_id` bigint UNSIGNED NOT NULL COMMENT '引用 user.user_id', + `role` tinyint NOT NULL DEFAULT 0 COMMENT '0=普通成员,1=管理员,2=创建者', + `joined_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `muted_until` timestamp NULL DEFAULT NULL COMMENT '如果被禁言,可存到什么时候', + PRIMARY KEY (`thread_id`, `user_id`) USING BTREE, + INDEX `idx_user_threads`(`user_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of group_chat_member +-- ---------------------------- +INSERT INTO `group_chat_member` VALUES (45, 1213, 0, '2026-01-31 14:41:30', NULL); +INSERT INTO `group_chat_member` VALUES (45, 1275, 2, '2026-01-31 14:41:30', NULL); +INSERT INTO `group_chat_member` VALUES (46, 1213, 0, '2026-01-31 14:53:29', NULL); +INSERT INTO `group_chat_member` VALUES (46, 1275, 2, '2026-01-31 14:53:29', NULL); +INSERT INTO `group_chat_member` VALUES (47, 1213, 0, '2026-01-31 14:59:28', NULL); +INSERT INTO `group_chat_member` VALUES (47, 1275, 2, '2026-01-31 14:59:28', NULL); +INSERT INTO `group_chat_member` VALUES (48, 1213, 0, '2026-01-31 15:11:14', NULL); +INSERT INTO `group_chat_member` VALUES (48, 1275, 2, '2026-01-31 15:11:14', NULL); + +-- ---------------------------- +-- Table structure for private_chat +-- ---------------------------- +DROP TABLE IF EXISTS `private_chat`; +CREATE TABLE `private_chat` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `user1_id` bigint UNSIGNED NOT NULL, + `user2_id` bigint UNSIGNED NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`) USING BTREE, + UNIQUE INDEX `uniq_private_thread`(`user1_id` ASC, `user2_id` ASC) USING BTREE, + INDEX `idx_private_user1_thread`(`user1_id` ASC, `thread_id` ASC) USING BTREE, + INDEX `idx_private_user2_thread`(`user2_id` ASC, `thread_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of private_chat +-- ---------------------------- +INSERT INTO `private_chat` VALUES (35, 1019, 1002, '2025-07-02 06:41:08'); +INSERT INTO `private_chat` VALUES (36, 1175, 1176, '2025-08-22 03:07:31'); +INSERT INTO `private_chat` VALUES (37, 0, 1217, '2025-10-03 08:43:18'); +INSERT INTO `private_chat` VALUES (38, 1093, 2020, '2025-12-09 10:00:37'); +INSERT INTO `private_chat` VALUES (39, 2020, 2030, '2025-12-09 10:00:44'); +INSERT INTO `private_chat` VALUES (40, 1267, 1268, '2026-01-06 13:55:39'); +INSERT INTO `private_chat` VALUES (41, 2181, 2179, '2026-01-30 02:20:52'); +INSERT INTO `private_chat` VALUES (42, 1019, 1005, '2026-01-31 09:34:34'); +INSERT INTO `private_chat` VALUES (43, 0, 2181, '2026-01-31 09:39:01'); +INSERT INTO `private_chat` VALUES (44, 1275, 1213, '2026-01-31 14:19:27'); +INSERT INTO `private_chat` VALUES (49, 0, 1291, '2026-02-05 04:28:26'); + +-- ---------------------------- +-- Table structure for test +-- ---------------------------- +DROP TABLE IF EXISTS `test`; +CREATE TABLE `test` ( + `id` int NOT NULL, + `product_no` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `price` decimal(10, 2) NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE, + INDEX `index_product_no_name`(`product_no` ASC, `name` ASC) USING BTREE, + INDEX `index_id_name`(`id` ASC, `name` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of test +-- ---------------------------- +INSERT INTO `test` VALUES (1, '0001', 'apple', 6.00); +INSERT INTO `test` VALUES (2, '0002', 'banana', 2.00); +INSERT INTO `test` VALUES (3, '0003', 'orange', 3.00); +INSERT INTO `test` VALUES (4, '0004', 'iphone13', 5000.00); +INSERT INTO `test` VALUES (5, '0005', 'ipad8', 3500.00); +INSERT INTO `test` VALUES (6, '0006', 'macbookpro', 10000.00); +INSERT INTO `test` VALUES (7, '0007', 'ps5', 4000.00); +INSERT INTO `test` VALUES (8, '0008', 'grape', 10.00); +INSERT INTO `test` VALUES (9, '0009', 'watermelon', 40.00); +INSERT INTO `test` VALUES (10, '0010', 'mango', 8.00); -- ---------------------------- -- Table structure for user @@ -82,12 +478,12 @@ CREATE TABLE `user` ( UNIQUE INDEX `uid`(`uid` ASC) USING BTREE, UNIQUE INDEX `email`(`email` ASC) USING BTREE, INDEX `name`(`name` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 61 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 745438 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of user -- ---------------------------- -INSERT INTO `user` VALUES (3, 1002, 'llfc', 'secondtonone1@163.com', '654321)', 'llfc', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (3, 1002, 'llfc', 'secondtonone1@163.com', '654321)', 'llfc', '', 0, ':/res/head_3.jpg'); INSERT INTO `user` VALUES (4, 1003, 'tc', '18165031775@qq.com', '123456', 'tc', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (5, 1004, 'yuanweihua', '1456188862@qq.com', '}kyn;89>?<', 'yuanweihua', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (6, 1005, 'test', '2022202210033@whu.edu.cn', '}kyn;89>?<', 'test', '', 0, ':/res/head_1.jpg'); @@ -96,22 +492,19 @@ INSERT INTO `user` VALUES (9, 1008, 'zglx2008', 'zglx2008@163.com', '123456', 'z INSERT INTO `user` VALUES (13, 1012, 'resettest', '1042958553@qq.com', '230745', 'resettest', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (14, 1013, 'rss_test', '1685229455@qq.com', '123456', 'rss_test', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (15, 1014, '123456789', '1152907774@qq.com', '123456789', '123456789', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (16, 1015, 'aaaaaaa', '3031719794@qq.com', '777777', 'aaaaaaa', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (17, 1016, 'aaa', '2996722319@qq.com', '222222', 'aaa', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (20, 1019, 'zack', '1017234088@qq.com', '654321)', 'zack', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (20, 1019, 'zack', '1017234088@qq.com', '654321)', 'zack', '', 0, '34a7d7cd-dcf6-4acf-be33-cbac757c59ed.png'); INSERT INTO `user` VALUES (21, 1020, 'aatext', '1584736136@qq.com', '745230', 'aatext', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (22, 1021, 'ferrero1', '1220292901@qq.com', '1234', 'ferrero1', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (23, 1022, 'ferrero2', '15504616642@163.com', '1234', 'ferrero2', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (24, 1023, 'lyf', '3194811890@qq.com', '123456', 'lyf', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (25, 1024, 'lh', '2494350589@qq.com', 'fb8::>:;8<', 'lh', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (26, 1025, 'jf', 'luojianfeng553@163.com', '745230', 'jf', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (33, 1031, 'zjm', '1013049201@qq.com', '745230', 'zjm', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (34, 1032, 'yxc', '1003314442@qq.com', '123', 'yxc', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (37, 1035, 'wangyu', '962087148@qq.com', '123456', 'wangyu', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (39, 1037, 'chae', '318192621@qq.com', '123456', 'chae', '', 0, ':/res/head_1.jpg'); -INSERT INTO `user` VALUES (40, 1038, 'summer', '1586856388@qq.com', '654321)', 'summer', '', 0, ':/res/head_2.jpg'); -INSERT INTO `user` VALUES (44, 1042, 'zzz', '3434321837@qq.com', '|l~745', '', '', 0, ''); -INSERT INTO `user` VALUES (45, 1043, 'sadda', 'z1668047679@163.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (39, 1037, 'chae', '318192621@qq.com', '777777', 'chae', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (40, 1038, 'summer', '1586856388@qq.com', '777777', 'summer', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (44, 1042, 'zzz', '3434321837@qq.com', '777777', '', '', 0, ''); +INSERT INTO `user` VALUES (45, 1043, 'sadda', 'z1668047679@163.com', '77777', '', '', 0, ''); INSERT INTO `user` VALUES (46, 1044, 'qwe', '1368326038@qq.com', '1234', '', '', 0, ''); INSERT INTO `user` VALUES (52, 1050, 'test23', '161945471@qq.com', '230745', 'test23', '', 0, ':/res/head_3.jpg'); INSERT INTO `user` VALUES (53, 1051, '123', '1767269204@qq.com', '123', '', '', 0, ''); @@ -121,20 +514,147 @@ INSERT INTO `user` VALUES (56, 1054, 'sqy', '3175614975@qq.com', '745230', 'sqy' INSERT INTO `user` VALUES (57, 1055, 'ocz', 'q3175614975@163.com', '745230', 'ocz', '', 0, ':/res/head_3.jpg'); INSERT INTO `user` VALUES (58, 1056, 'test28', '1669475972@qq.com', '230745', 'test28', '', 0, ':/res/head_1.jpg'); INSERT INTO `user` VALUES (60, 1058, 'NoOne', '1764850358@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (61, 2179, 'saheun', 'jinsaheun0926@outlook.com', '654321)', 'saheun', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (62, 2180, 'csx', '2843275253@qq.com', '654321)', 'csx', '', 0, ':/res/head_6.jpg'); +INSERT INTO `user` VALUES (63, 2020, 'rain', '20520@126.com', '745230', 'klaus', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (64, 2030, 'yyh', '285881076@qq.com', '745230', 'yyh', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (66, 2181, 'jmz', 'jinmz0101@outlook.com', '654321)', 'jmz', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (69, 2182, 'winter', 'winter010101@outlook.com', '654321)', 'winter', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (84, 1077, '氧白告', '3457468550@qq.com', '777777', '氧白告', '', 0, ':/res/head_21.jpg'); +INSERT INTO `user` VALUES (86, 1079, 'cpt1', 'chenpaiteng@qq.com', '777777', 'cpt1', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (87, 1080, 'cpt2', 'chenpaiteng@163.com', '777777', 'cpt2', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (95, 1087, 'ame', '1161761559@qq.com', '745230', 'ame', '', 0, ''); +INSERT INTO `user` VALUES (745235, 1093, 'yzmb', '11102766@qq.com', '745230', 'yzmb', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745236, 1094, 'ming', '1951831076@qq.com', '745230', 'ming', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745238, 1096, 'qqq', '1508945593@qq.com', 'wqctr', '', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745239, 1097, 'www', '2597586064@qq.com', '745230', '', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745240, 1098, 'Fany', '2848827727@qq.com', '745230', 'Fany', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745241, 1099, 'Zhang', '3228437938@qq.com', '745230', 'Zhang', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745242, 1100, '111', '3@q.com', '666666', '111', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745243, 1101, 'wdg', 'wdg@sb.com', '666666', 'wdg', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745244, 1102, 'HuYao', '3391870934@qq.com', '745230', 'HuYao', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745247, 1104, 'bishi', '3031719794@qq.com', '745745', 'bishi', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745251, 1108, 'aaa', '202201005117@email.sxu.edu.cn', '745230', '', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745252, 1109, '11', 'lv10052024@163.com', '1111', '', '', 0, ''); +INSERT INTO `user` VALUES (745257, 1114, 'zay', '1979034537@qq.com', '745230', 'zay', '', 0, ''); +INSERT INTO `user` VALUES (745263, 1120, 'KNO3', '3039647873@qq.com', '547547', 'KNO3', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745264, 1121, 'liushuai', '2159750441@qq.com', '745745', 'liushuai', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745265, 1122, 'Mrchang', '3482399524@qq.com', '745745', 'Mrchang', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745266, 1123, 'gordon', '1301858133@qq.com', '745230', 'gordon', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745269, 1126, 'jelly', 'gordon637@163.com', '745230', 'jelly', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745271, 1128, 'qyt', '2286765237@qq.com', '745230', 'qyt', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745272, 1129, 'maotouying', '2390742005@qq.com', '745745', 'maotouying', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745275, 1132, 'newday', '2805246514@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745276, 1133, 'haha', '18862007701@163.com', '745745', 'haha', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745277, 1134, 'gls', 'gxx@whu.edu.cn', '745745', 'gls', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745280, 1137, 'newdaytest', '15923025229@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745282, 1139, 'xyl', '2358078380@qq.com', '~j745', '', '', 0, ''); +INSERT INTO `user` VALUES (745283, 1140, 'dst', '2141478259@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745284, 1141, 'ywttest', '19120531599@163.com', '745230', 'ywttest', '', 0, ''); +INSERT INTO `user` VALUES (745285, 1142, 'wxy', '13674921583@163.com', '745230', 'wxy', '', 0, ''); +INSERT INTO `user` VALUES (745286, 1143, 'poison', '270111426@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745287, 1144, 'ejnqx', '15980307945@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745290, 1147, '1234', 'tangjwsr@163.com', '23458', '', '', 0, ''); +INSERT INTO `user` VALUES (745291, 1148, '1', '2207336992@qq.com', '11', '', '', 0, ''); +INSERT INTO `user` VALUES (745292, 1149, 'mwt', '2622412201@qq.com', '123456', 'mwt', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745293, 1150, 'gsh', '2225665686@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745294, 1151, 'ffff', '2060603454@qq.com', '6543210', 'ffff', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745295, 1152, 'hxz', '2381096717@qq.com', '745230', 'hxz', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745296, 1153, 'hua', '2276128113@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745304, 1146, 'jmt', '3208064665@qq.com', '745230', '', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745305, 1154, 'jmetin', 'jmetin@163.com', '745230', '', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745308, 1165, 'glc', '3503006364@qq.com', '741852', '', '', 0, ''); +INSERT INTO `user` VALUES (745310, 1167, 'glc2', '1099495783@qq.com', '147258', '', '', 0, ''); +INSERT INTO `user` VALUES (745311, 1168, 'cwb', '2967229515@qq.com', '745230', 'cwb', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745312, 1169, 'cbq', '359989105@qq.com', '745230', 'cbq', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745313, 1170, 'yanyan', '1776950301@qq.com', '745230', 'yanyan', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745314, 1171, 'yjh', 'jiahao_yan@163.com', '745230', 'yjh', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745315, 1172, 'crx', '15058762422@163.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745316, 1173, 'ccrx', '2803033275@qq.com', '1234567', '', '', 0, ''); +INSERT INTO `user` VALUES (745317, 1174, 'fangyee', 'fangyi0926@qq.com', '123456', 'fangyee', '', 0, ''); +INSERT INTO `user` VALUES (745318, 1175, 'xiao', '2557854108@qq.com', '745230', 'xiao', '', 0, '7dfce23d-8032-4d33-af31-2b0f15ec3f63.png'); +INSERT INTO `user` VALUES (745319, 1176, 'yulinyi', 'xuchen@superpiano.com.cn', '745230', 'yulinyi', '', 0, ''); +INSERT INTO `user` VALUES (745321, 1178, 'llfctest', '2055181763@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745322, 1179, 'jianghao', '1464709591@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745326, 1183, '1212', '1162534442@qq.com', '747474', '1212', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745327, 1184, 'malong1', '2781164632@qq.com', 'am`cbk;>9:::', 'malong1', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745330, 1187, 'momo', '2759615633@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745331, 1188, 'lry', '1194930127@qq.com', 'gyr9;;8::9:', 'lry', '', 0, ''); +INSERT INTO `user` VALUES (745332, 1189, 'smj', 'smj_0408@163.com', '745230', 'smj', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745333, 1190, 'Curl', '736605182@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745335, 1192, 'smjqq', '929713732@qq.com', 'ygb8:::<;>', 'smjqq', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745345, 1202, 'krico', '2657751462@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745348, 1205, 'z66', '1726549116@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745349, 1206, 'wxwx', '2895856612@qq.com', '123456.', '', '', 0, ''); +INSERT INTO `user` VALUES (745350, 1207, 'yukang2', '2296085080@qq.com', '745230', 'yukang2', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745354, 1211, 'wwx', '18624173901@163.com', 'ibrvpp', 'wwx', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745356, 1213, 'abc123', '2460123996@qq.com', '745230', 'abc123', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745360, 1217, 'makk', 'bwmlth@foxmail.com', '745230', 'makk', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745362, 1219, 'fxw', 'fxwchengxuyuan@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745363, 1220, 'libai', '1977370522@qq.com', '`~q745', '', '', 0, ''); +INSERT INTO `user` VALUES (745364, 1221, 'you', '1656377690@qq.com', '745230', 'you', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745365, 1222, 'zhangzhihui', 'youxw@cug.edu.cn', '745230', 'zhangzhihui', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745366, 1223, 'zsc', '3142277367@qq.com', '745230', 'zsc', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745367, 1224, '114514', '2315608252@qq.com', '114514', '', '', 0, ''); +INSERT INTO `user` VALUES (745368, 1225, 'll', '1451230636@qq.com', '032547', 'll', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745369, 1226, 'xiexinyu', '872448677@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745370, 1227, 'flytest1', 'fly2908@163.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745371, 1228, 'asda', '2976159675@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745372, 1229, 'as', '1653786255@qq.com', '12345', '', '', 0, ''); +INSERT INTO `user` VALUES (745373, 1230, 'lucktest', 'a2199189024@163.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745374, 1231, 'qwerty', '18714382065@163.com', '123456', 'qwerty', '', 0, ''); +INSERT INTO `user` VALUES (745375, 1232, 'ajhfgsdj', '13523955317@163.com', '123456', 'ajhfgsdj', '', 0, ''); +INSERT INTO `user` VALUES (745376, 1233, 'lw', '1070414135@qq.com', '1125', 'lw', '', 0, ''); +INSERT INTO `user` VALUES (745377, 1234, 'wl', '1755304361@qq.com', '2234', 'wl', '', 0, ''); +INSERT INTO `user` VALUES (745387, 1244, 'why', '1191416756@qq.com', '123', '', '', 0, ''); +INSERT INTO `user` VALUES (745393, 1250, 'lfh', '1551868104@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745394, 1251, 'zg', '2064571645@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745398, 1255, 'hpz', '111111@qq.com', '777777', 'hpz', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745399, 1256, 'jaychou', '222222@qq.com', '444444', 'jaychou', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745400, 1257, 'sang', '111222@qq.com', '777777', 'sang', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745401, 1258, 'yan', '333444@qq.com', '777777', 'yan', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745402, 1259, 'crl', '555666@qq.com', '777777', 'crl', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745403, 1260, 'qaq', '2075605318@qq.com', '745230', 'qaq', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745404, 1261, 'qwer', '666777@qq.com', '777777', 'qwer', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745406, 1263, 'admin', '1772274756@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745407, 1264, 'admin55555', '1772274746@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745410, 1267, 'mingqianss', 'xiaoxuezha@foxmail.com', '745230', 'mingqianss', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745411, 1268, 'mingqianss2', 'mingqiantjw@163.com', '745230', 'mingqianss2', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745412, 1269, 'mingw', '3186428847@qq.com', '745230', 'mingw', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745413, 1270, 'mmmm', '13593721169@163.com', '745230', 'mmmm', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745414, 1271, 'cat', '18368122687@163.com', '745230', 'cat', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745415, 1272, 'GuoLiJun', '15152541710@163.com', '745230', 'GuoLiJun', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745416, 1273, 'kawa', '19072984947@163.com', '745230', 'kawa', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745417, 1274, 'xxc', '1265865927@qq.com', '745230', 'xxc', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745418, 1275, 'suliu', '2406582339@qq.com', '745230', 'suliu', '', 0, ''); +INSERT INTO `user` VALUES (745419, 1276, 'dyue', '15371401089@163.com', '745230', 'dyue', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745420, 1277, 'dqh', '3234401829@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745421, 1278, 'xxx', '111444@qq.com', '777777', 'xxx', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745422, 1279, 'lixin', '177225@qq.com', '210', '', '', 0, ''); +INSERT INTO `user` VALUES (745423, 1280, 'codexin', '321115904@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745424, 1281, 'xx', '111555@qq.com', '777777', 'xx', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745425, 1282, 'qiu', '2279039011@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745426, 1283, 'hc', '603008751@qq.com', 'hc123', '', '', 0, ''); +INSERT INTO `user` VALUES (745427, 1284, 'f', '132@qq.com', 'f', '', '', 0, ''); +INSERT INTO `user` VALUES (745428, 1285, 'df', '232@qq.com', '123', '', '', 0, ''); +INSERT INTO `user` VALUES (745429, 1286, 'byb', '601189025@qq.com', '123456', 'byb', '', 0, ': / res / head_1.jpg'); +INSERT INTO `user` VALUES (745430, 1287, 'dyy', '1410624375@qq.com', '9:;<=>?0', '', '', 0, ''); +INSERT INTO `user` VALUES (745434, 1291, 'wei', '123456@qq.com', '745230', 'wei', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745437, 1294, 'sinan', '3055460182@qq.com', '745230', '', '', 0, ''); -- ---------------------------- -- Table structure for user_id -- ---------------------------- DROP TABLE IF EXISTS `user_id`; CREATE TABLE `user_id` ( - `id` int NOT NULL, + `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1295 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of user_id -- ---------------------------- -INSERT INTO `user_id` VALUES (1058); +INSERT INTO `user_id` VALUES (1294); -- ---------------------------- -- Procedure structure for reg_user @@ -154,8 +674,10 @@ BEGIN -- 设置返回值为-1,表示错误 SET result = -1; END; + -- 开始事务 START TRANSACTION; + -- 检查用户名是否已存在 IF EXISTS (SELECT 1 FROM `user` WHERE `name` = new_name) THEN SET result = 0; -- 用户名已存在 @@ -168,17 +690,66 @@ BEGIN ELSE -- email也不存在,更新user_id表 UPDATE `user_id` SET `id` = `id` + 1; + -- 获取更新后的id SELECT `id` INTO @new_id FROM `user_id`; + -- 在user表中插入新记录 INSERT INTO `user` (`uid`, `name`, `email`, `pwd`) VALUES (@new_id, new_name, new_email, new_pwd); -- 设置result为新插入的uid SET result = @new_id; -- 插入成功,返回新的uid COMMIT; + END IF; END IF; + END ;; delimiter ; +-- ---------------------------- +-- Procedure structure for reg_user_procedure +-- ---------------------------- +DROP PROCEDURE IF EXISTS `reg_user_procedure`; +delimiter ;; +CREATE PROCEDURE `reg_user_procedure`(IN `new_name` VARCHAR(255), + IN `new_email` VARCHAR(255), + IN `new_pwd` VARCHAR(255), + OUT `result` INT) +BEGIN + -- 如果在执行过程中遇到任何错误,则回滚事务 + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + -- 回滚事务 + ROLLBACK; + -- 设置返回值为-1,表示错误 + SET result = -1; + END; + -- 开始事务 + START TRANSACTION; + -- 检查用户名是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `name` = new_name) THEN + SET result = 0; -- 用户名已存在 + COMMIT; + ELSE + -- 用户名不存在,检查email是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `email` = new_email) THEN + SET result = 0; -- email已存在 + COMMIT; + ELSE + -- email也不存在,更新user_id表 + UPDATE `user_id` SET `id` = `id` + 1; + -- 获取更新后的id + SELECT `id` INTO @new_id FROM `user_id`; + -- 在user表中插入新记录 + INSERT INTO `user` (`uid`, `name`, `email`, `pwd`) VALUES (@new_id, new_name, new_email, new_pwd); + -- 设置result为新插入的uid + SET result = @new_id; -- 插入成功,返回新的uid + COMMIT; + END IF; + END IF; + END +;; +delimiter ; + SET FOREIGN_KEY_CHECKS = 1; diff --git "a/sql\345\244\207\344\273\275/llfc3.sql" "b/sql\345\244\207\344\273\275/llfc3.sql" new file mode 100644 index 0000000..4bdb953 --- /dev/null +++ "b/sql\345\244\207\344\273\275/llfc3.sql" @@ -0,0 +1,424 @@ +/* + Navicat Premium Data Transfer + + Source Server : llfcmysql + Source Server Type : MySQL + Source Server Version : 80027 (8.0.27) + Source Host : 81.68.86.146:3308 + Source Schema : llfc + + Target Server Type : MySQL + Target Server Version : 80027 (8.0.27) + File Encoding : 65001 + + Date: 24/07/2025 21:49:44 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for chat_message +-- ---------------------------- +DROP TABLE IF EXISTS `chat_message`; +CREATE TABLE `chat_message` ( + `message_id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `thread_id` bigint UNSIGNED NOT NULL, + `sender_id` bigint UNSIGNED NOT NULL, + `recv_id` bigint UNSIGNED NOT NULL, + `content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `status` tinyint NOT NULL DEFAULT 0 COMMENT '0=未读 1=已读 2=撤回', + PRIMARY KEY (`message_id`) USING BTREE, + INDEX `idx_thread_created`(`thread_id` ASC, `created_at` ASC) USING BTREE, + INDEX `idx_thread_message`(`thread_id` ASC, `message_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 37 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of chat_message +-- ---------------------------- +INSERT INTO `chat_message` VALUES (33, 35, 1002, 1019, '您好,我是llfc', '2025-07-02 06:41:08', '2025-07-24 08:27:45', 2); +INSERT INTO `chat_message` VALUES (34, 35, 1019, 1002, 'We are friends now!', '2025-07-02 06:41:08', '2025-07-24 08:27:39', 2); +INSERT INTO `chat_message` VALUES (35, 35, 1002, 1019, '你好,很高兴认识你', '2025-07-24 21:36:30', '2025-07-24 21:36:30', 2); +INSERT INTO `chat_message` VALUES (36, 35, 1019, 1002, '我也是,很高兴认识你', '2025-07-24 21:36:43', '2025-07-24 21:36:43', 2); + +-- ---------------------------- +-- Table structure for chat_thread +-- ---------------------------- +DROP TABLE IF EXISTS `chat_thread`; +CREATE TABLE `chat_thread` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, + `type` enum('private','group') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 36 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of chat_thread +-- ---------------------------- +INSERT INTO `chat_thread` VALUES (35, 'private', '2025-07-02 06:41:08'); + +-- ---------------------------- +-- Table structure for friend +-- ---------------------------- +DROP TABLE IF EXISTS `friend`; +CREATE TABLE `friend` ( + `id` int UNSIGNED NOT NULL AUTO_INCREMENT, + `self_id` int NOT NULL, + `friend_id` int NOT NULL, + `back` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `self_friend`(`self_id` ASC, `friend_id` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 473 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of friend +-- ---------------------------- +INSERT INTO `friend` VALUES (55, 1055, 1054, 'sqy'); +INSERT INTO `friend` VALUES (56, 1054, 1055, ''); +INSERT INTO `friend` VALUES (61, 1012, 1056, 'test28'); +INSERT INTO `friend` VALUES (62, 1056, 1012, ''); +INSERT INTO `friend` VALUES (63, 1012, 1050, 'test23'); +INSERT INTO `friend` VALUES (89, 1038, 1037, 'chae'); +INSERT INTO `friend` VALUES (90, 1037, 1038, ''); +INSERT INTO `friend` VALUES (127, 2020, 2030, 'yyh'); +INSERT INTO `friend` VALUES (128, 2030, 2020, ''); +INSERT INTO `friend` VALUES (149, 2182, 2181, 'jmz'); +INSERT INTO `friend` VALUES (150, 2181, 2182, ''); +INSERT INTO `friend` VALUES (151, 1080, 1079, 'cpt1'); +INSERT INTO `friend` VALUES (152, 1079, 1080, ''); +INSERT INTO `friend` VALUES (155, 2020, 1090, 'yzmb'); +INSERT INTO `friend` VALUES (156, 1090, 2020, ''); +INSERT INTO `friend` VALUES (157, 1090, 2030, 'yyh'); +INSERT INTO `friend` VALUES (158, 2030, 1090, ''); +INSERT INTO `friend` VALUES (159, 2020, 1093, 'yzmb'); +INSERT INTO `friend` VALUES (160, 1093, 2020, ''); +INSERT INTO `friend` VALUES (161, 1093, 2030, 'yyh'); +INSERT INTO `friend` VALUES (162, 2030, 1093, ''); +INSERT INTO `friend` VALUES (163, 1085, 1079, 'cpt1'); +INSERT INTO `friend` VALUES (164, 1079, 1085, ''); +INSERT INTO `friend` VALUES (165, 1085, 1080, 'cpt2'); +INSERT INTO `friend` VALUES (166, 1080, 1085, ''); +INSERT INTO `friend` VALUES (167, 1087, 1094, 'ming'); +INSERT INTO `friend` VALUES (168, 1094, 1087, ''); +INSERT INTO `friend` VALUES (185, 1099, 1098, 'Fany'); +INSERT INTO `friend` VALUES (186, 1098, 1099, ''); +INSERT INTO `friend` VALUES (379, 1096, 1097, 'www'); +INSERT INTO `friend` VALUES (380, 1097, 1096, ''); +INSERT INTO `friend` VALUES (389, 1019, 1002, 'llfc'); +INSERT INTO `friend` VALUES (390, 1002, 1019, 'zack'); +INSERT INTO `friend` VALUES (391, 1120, 1122, 'Mrchang'); +INSERT INTO `friend` VALUES (392, 1122, 1120, ''); +INSERT INTO `friend` VALUES (393, 1121, 1120, 'KNO3'); +INSERT INTO `friend` VALUES (394, 1120, 1121, ''); +INSERT INTO `friend` VALUES (395, 1121, 1122, 'Mrchang'); +INSERT INTO `friend` VALUES (396, 1122, 1121, ''); +INSERT INTO `friend` VALUES (397, 1120, 1129, 'maotouying'); +INSERT INTO `friend` VALUES (398, 1129, 1120, ''); +INSERT INTO `friend` VALUES (401, 1120, 1134, 'gls'); +INSERT INTO `friend` VALUES (402, 1134, 1120, ''); +INSERT INTO `friend` VALUES (439, 1123, 1120, 'KNO3'); +INSERT INTO `friend` VALUES (440, 1120, 1123, ''); +INSERT INTO `friend` VALUES (441, 1123, 1126, 'jelly'); +INSERT INTO `friend` VALUES (442, 1126, 1123, ''); +INSERT INTO `friend` VALUES (469, 1003, 1008, 'zglx2008'); +INSERT INTO `friend` VALUES (470, 1008, 1003, ''); +INSERT INTO `friend` VALUES (471, 1142, 1114, 'zay'); +INSERT INTO `friend` VALUES (472, 1114, 1142, ''); + +-- ---------------------------- +-- Table structure for friend_apply +-- ---------------------------- +DROP TABLE IF EXISTS `friend_apply`; +CREATE TABLE `friend_apply` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `from_uid` int NOT NULL, + `to_uid` int NOT NULL, + `status` smallint NOT NULL DEFAULT 0, + `descs` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', + `back_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `from_to_uid`(`from_uid` ASC, `to_uid` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 283 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of friend_apply +-- ---------------------------- +INSERT INTO `friend_apply` VALUES (253, 1002, 1019, 1, '您好,我是llfc', 'zack'); +INSERT INTO `friend_apply` VALUES (254, 1122, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (255, 1122, 1121, 1, '', ''); +INSERT INTO `friend_apply` VALUES (257, 1120, 1121, 1, '', ''); +INSERT INTO `friend_apply` VALUES (258, 1129, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (260, 1120, 1123, 1, '', ''); +INSERT INTO `friend_apply` VALUES (262, 1134, 1120, 1, '', ''); +INSERT INTO `friend_apply` VALUES (271, 1126, 1123, 1, '', ''); +INSERT INTO `friend_apply` VALUES (272, 1132, 1002, 0, '', ''); +INSERT INTO `friend_apply` VALUES (273, 0, 1142, 0, '', ''); +INSERT INTO `friend_apply` VALUES (275, 0, 1114, 0, '', ''); +INSERT INTO `friend_apply` VALUES (276, 1008, 1003, 1, '', ''); +INSERT INTO `friend_apply` VALUES (278, 0, 1058, 0, '', ''); +INSERT INTO `friend_apply` VALUES (279, 0, 1055, 0, '', ''); +INSERT INTO `friend_apply` VALUES (281, 1114, 1142, 1, '', ''); + +-- ---------------------------- +-- Table structure for group_chat +-- ---------------------------- +DROP TABLE IF EXISTS `group_chat`; +CREATE TABLE `group_chat` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '群聊名称', + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of group_chat +-- ---------------------------- + +-- ---------------------------- +-- Table structure for group_chat_member +-- ---------------------------- +DROP TABLE IF EXISTS `group_chat_member`; +CREATE TABLE `group_chat_member` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用 group_chat_thread.thread_id', + `user_id` bigint UNSIGNED NOT NULL COMMENT '引用 user.user_id', + `role` tinyint NOT NULL DEFAULT 0 COMMENT '0=普通成员,1=管理员,2=创建者', + `joined_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `muted_until` timestamp NULL DEFAULT NULL COMMENT '如果被禁言,可存到什么时候', + PRIMARY KEY (`thread_id`, `user_id`) USING BTREE, + INDEX `idx_user_threads`(`user_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of group_chat_member +-- ---------------------------- + +-- ---------------------------- +-- Table structure for private_chat +-- ---------------------------- +DROP TABLE IF EXISTS `private_chat`; +CREATE TABLE `private_chat` ( + `thread_id` bigint UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `user1_id` bigint UNSIGNED NOT NULL, + `user2_id` bigint UNSIGNED NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`) USING BTREE, + UNIQUE INDEX `uniq_private_thread`(`user1_id` ASC, `user2_id` ASC) USING BTREE, + INDEX `idx_private_user1_thread`(`user1_id` ASC, `thread_id` ASC) USING BTREE, + INDEX `idx_private_user2_thread`(`user2_id` ASC, `thread_id` ASC) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of private_chat +-- ---------------------------- +INSERT INTO `private_chat` VALUES (35, 1019, 1002, '2025-07-02 06:41:08'); + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` int NOT NULL AUTO_INCREMENT, + `uid` int NOT NULL DEFAULT 0, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `nick` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + `sex` int NOT NULL DEFAULT 0, + `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE, + UNIQUE INDEX `uid`(`uid` ASC) USING BTREE, + UNIQUE INDEX `email`(`email` ASC) USING BTREE, + INDEX `name`(`name` ASC) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 745294 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of user +-- ---------------------------- +INSERT INTO `user` VALUES (3, 1002, 'llfc', 'secondtonone1@163.com', '654321)', 'llfc', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (4, 1003, 'tc', '18165031775@qq.com', '123456', 'tc', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (5, 1004, 'yuanweihua', '1456188862@qq.com', '}kyn;89>?<', 'yuanweihua', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (6, 1005, 'test', '2022202210033@whu.edu.cn', '}kyn;89>?<', 'test', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (8, 1007, 'fhr', '3157199927@qq.com', 'xuexi1228', 'fhr', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (9, 1008, 'zglx2008', 'zglx2008@163.com', '123456', 'zglx2008', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (13, 1012, 'resettest', '1042958553@qq.com', '230745', 'resettest', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (14, 1013, 'rss_test', '1685229455@qq.com', '123456', 'rss_test', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (15, 1014, '123456789', '1152907774@qq.com', '123456789', '123456789', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (20, 1019, 'zack', '1017234088@qq.com', '654321)', 'zack', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (21, 1020, 'aatext', '1584736136@qq.com', '745230', 'aatext', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (22, 1021, 'ferrero1', '1220292901@qq.com', '1234', 'ferrero1', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (23, 1022, 'ferrero2', '15504616642@163.com', '1234', 'ferrero2', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (24, 1023, 'lyf', '3194811890@qq.com', '123456', 'lyf', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (25, 1024, 'lh', '2494350589@qq.com', 'fb8::>:;8<', 'lh', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (33, 1031, 'zjm', '1013049201@qq.com', '745230', 'zjm', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (34, 1032, 'yxc', '1003314442@qq.com', '123', 'yxc', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (37, 1035, 'wangyu', '962087148@qq.com', '123456', 'wangyu', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (39, 1037, 'chae', '318192621@qq.com', '777777', 'chae', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (40, 1038, 'summer', '1586856388@qq.com', '777777', 'summer', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (44, 1042, 'zzz', '3434321837@qq.com', '777777', '', '', 0, ''); +INSERT INTO `user` VALUES (45, 1043, 'sadda', 'z1668047679@163.com', '777777', '', '', 0, ''); +INSERT INTO `user` VALUES (46, 1044, 'qwe', '1368326038@qq.com', '1234', '', '', 0, ''); +INSERT INTO `user` VALUES (52, 1050, 'test23', '161945471@qq.com', '230745', 'test23', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (53, 1051, '123', '1767269204@qq.com', '123', '', '', 0, ''); +INSERT INTO `user` VALUES (54, 1052, 'zjc', '766741776@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (55, 1053, 'test_1', 'zzsr_0719@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (56, 1054, 'sqy', '3175614975@qq.com', '745230', 'sqy', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (57, 1055, 'ocz', 'q3175614975@163.com', '745230', 'ocz', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (58, 1056, 'test28', '1669475972@qq.com', '230745', 'test28', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (60, 1058, 'NoOne', '1764850358@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (61, 2179, 'saheun', 'jinsaheun0926@outlook.com', '654321)', 'saheun', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (62, 2180, 'csx', '2843275253@qq.com', '654321)', 'csx', '', 0, ':/res/head_6.jpg'); +INSERT INTO `user` VALUES (63, 2020, 'rain', '20520@126.com', '745230', 'klaus', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (64, 2030, 'yyh', '285881076@qq.com', '745230', 'yyh', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (66, 2181, 'jmz', 'jinmz0101@outlook.com', '654321)', 'jmz', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (69, 2182, 'winter', 'winter010101@outlook.com', '654321)', 'winter', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (84, 1077, '氧白告', '3457468550@qq.com', '777777', '氧白告', '', 0, ':/res/head_21.jpg'); +INSERT INTO `user` VALUES (86, 1079, 'cpt1', 'chenpaiteng@qq.com', '777777', 'cpt1', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (87, 1080, 'cpt2', 'chenpaiteng@163.com', '777777', 'cpt2', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (93, 1085, 'xiao', '2557854108@qq.com', '745230', 'xiao', '', 0, ''); +INSERT INTO `user` VALUES (95, 1087, 'ame', '1161761559@qq.com', '745230', 'ame', '', 0, ''); +INSERT INTO `user` VALUES (745235, 1093, 'yzmb', '11102766@qq.com', '745230', 'yzmb', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745236, 1094, 'ming', '1951831076@qq.com', '745230', 'ming', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745238, 1096, 'qqq', '1508945593@qq.com', 'wqctr', '', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745239, 1097, 'www', '2597586064@qq.com', '745230', '', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745240, 1098, 'Fany', '2848827727@qq.com', '745230', 'Fany', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745241, 1099, 'Zhang', '3228437938@qq.com', '745230', 'Zhang', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745242, 1100, '111', '3@q.com', '666666', '111', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745243, 1101, 'wdg', 'wdg@sb.com', '666666', 'wdg', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745244, 1102, 'HuYao', '3391870934@qq.com', '745230', 'HuYao', '', 0, ':/res/head_2.jpg'); +INSERT INTO `user` VALUES (745247, 1104, 'bishi', '3031719794@qq.com', '745745', 'bishi', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745251, 1108, 'aaa', '202201005117@email.sxu.edu.cn', '745230', '', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745252, 1109, '11', 'lv10052024@163.com', '1111', '', '', 0, ''); +INSERT INTO `user` VALUES (745255, 1112, 'ydjd', 'jiahao_yan@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745256, 1113, 'yanyan', '1776950301@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745257, 1114, 'zay', '1979034537@qq.com', '745230', 'zay', '', 0, ''); +INSERT INTO `user` VALUES (745263, 1120, 'KNO3', '3039647873@qq.com', '547547', 'KNO3', '', 0, ':/res/head_4.jpg'); +INSERT INTO `user` VALUES (745264, 1121, 'liushuai', '2159750441@qq.com', '745745', 'liushuai', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745265, 1122, 'Mrchang', '3482399524@qq.com', '745745', 'Mrchang', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745266, 1123, 'gordon', '1301858133@qq.com', '745230', 'gordon', '', 0, ':/res/head_3.jpg'); +INSERT INTO `user` VALUES (745269, 1126, 'jelly', 'gordon637@163.com', '745230', 'jelly', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745271, 1128, 'qyt', '2286765237@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745272, 1129, 'maotouying', '2390742005@qq.com', '745745', 'maotouying', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745275, 1132, 'newday', '2805246514@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745276, 1133, 'haha', '18862007701@163.com', '745745', 'haha', '', 0, ':/res/head_5.jpg'); +INSERT INTO `user` VALUES (745277, 1134, 'gls', 'gxx@whu.edu.cn', '745745', 'gls', '', 0, ':/res/head_1.jpg'); +INSERT INTO `user` VALUES (745280, 1137, 'newdaytest', '15923025229@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745282, 1139, 'xyl', '2358078380@qq.com', '~j745', '', '', 0, ''); +INSERT INTO `user` VALUES (745283, 1140, 'dst', '2141478259@qq.com', '123456', '', '', 0, ''); +INSERT INTO `user` VALUES (745284, 1141, 'ywttest', '19120531599@163.com', '032547', 'ywttest', '', 0, ''); +INSERT INTO `user` VALUES (745285, 1142, 'wxy', '13674921583@163.com', '745230', 'wxy', '', 0, ''); +INSERT INTO `user` VALUES (745286, 1143, 'poison', '270111426@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745287, 1144, 'ejnqx', '15980307945@163.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745289, 1146, 'jmt', '3208064665@qq.com', '745230', '', '', 0, ''); +INSERT INTO `user` VALUES (745290, 1147, '1234', 'tangjwsr@163.com', '23458', '', '', 0, ''); +INSERT INTO `user` VALUES (745291, 1148, '1', '2207336992@qq.com', '11', '', '', 0, ''); +INSERT INTO `user` VALUES (745292, 1149, 'mwt', '2622412201@qq.com', '123456', 'mwt', '', 0, ''); +INSERT INTO `user` VALUES (745293, 1150, 'gsh', '2225665686@qq.com', '123456', '', '', 0, ''); + +-- ---------------------------- +-- Table structure for user_id +-- ---------------------------- +DROP TABLE IF EXISTS `user_id`; +CREATE TABLE `user_id` ( + `id` int NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 1151 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Records of user_id +-- ---------------------------- +INSERT INTO `user_id` VALUES (1150); + +-- ---------------------------- +-- Procedure structure for reg_user +-- ---------------------------- +DROP PROCEDURE IF EXISTS `reg_user`; +delimiter ;; +CREATE PROCEDURE `reg_user`(IN `new_name` VARCHAR(255), + IN `new_email` VARCHAR(255), + IN `new_pwd` VARCHAR(255), + OUT `result` INT) +BEGIN + -- 如果在执行过程中遇到任何错误,则回滚事务 + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + -- 回滚事务 + ROLLBACK; + -- 设置返回值为-1,表示错误 + SET result = -1; + END; + -- 开始事务 + START TRANSACTION; + -- 检查用户名是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `name` = new_name) THEN + SET result = 0; -- 用户名已存在 + COMMIT; + ELSE + -- 用户名不存在,检查email是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `email` = new_email) THEN + SET result = 0; -- email已存在 + COMMIT; + ELSE + -- email也不存在,更新user_id表 + UPDATE `user_id` SET `id` = `id` + 1; + -- 获取更新后的id + SELECT `id` INTO @new_id FROM `user_id`; + -- 在user表中插入新记录 + INSERT INTO `user` (`uid`, `name`, `email`, `pwd`) VALUES (@new_id, new_name, new_email, new_pwd); + -- 设置result为新插入的uid + SET result = @new_id; -- 插入成功,返回新的uid + COMMIT; + END IF; + END IF; +END +;; +delimiter ; + +-- ---------------------------- +-- Procedure structure for reg_user_procedure +-- ---------------------------- +DROP PROCEDURE IF EXISTS `reg_user_procedure`; +delimiter ;; +CREATE PROCEDURE `reg_user_procedure`(IN `new_name` VARCHAR(255), + IN `new_email` VARCHAR(255), + IN `new_pwd` VARCHAR(255), + OUT `result` INT) +BEGIN + -- 如果在执行过程中遇到任何错误,则回滚事务 + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + -- 回滚事务 + ROLLBACK; + -- 设置返回值为-1,表示错误 + SET result = -1; + END; + -- 开始事务 + START TRANSACTION; + -- 检查用户名是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `name` = new_name) THEN + SET result = 0; -- 用户名已存在 + COMMIT; + ELSE + -- 用户名不存在,检查email是否已存在 + IF EXISTS (SELECT 1 FROM `user` WHERE `email` = new_email) THEN + SET result = 0; -- email已存在 + COMMIT; + ELSE + -- email也不存在,更新user_id表 + UPDATE `user_id` SET `id` = `id` + 1; + -- 获取更新后的id + SELECT `id` INTO @new_id FROM `user_id`; + -- 在user表中插入新记录 + INSERT INTO `user` (`uid`, `name`, `email`, `pwd`) VALUES (@new_id, new_name, new_email, new_pwd); + -- 设置result为新插入的uid + SET result = @new_id; -- 插入成功,返回新的uid + COMMIT; + END IF; + END IF; + END +;; +delimiter ; + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/webrtc-demo/server/package-lock.json b/webrtc-demo/server/package-lock.json new file mode 100644 index 0000000..9602143 --- /dev/null +++ b/webrtc-demo/server/package-lock.json @@ -0,0 +1,849 @@ +{ + "name": "server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "server", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^5.2.1", + "ws": "^8.19.0" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/body-parser": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/webrtc-demo/server/package.json b/webrtc-demo/server/package.json new file mode 100644 index 0000000..f9587c2 --- /dev/null +++ b/webrtc-demo/server/package.json @@ -0,0 +1,17 @@ +{ + "name": "server", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "express": "^5.2.1", + "ws": "^8.19.0" + } +} diff --git a/webrtc-demo/server/server.js b/webrtc-demo/server/server.js new file mode 100644 index 0000000..be87da1 --- /dev/null +++ b/webrtc-demo/server/server.js @@ -0,0 +1,137 @@ +import express from "express"; +import http from "http"; +import { WebSocketServer } from "ws"; + +import path from "path"; +import { fileURLToPath } from "url"; + +//获取当前文件的路径,server.js文件路径 +const __filename = fileURLToPath(import.meta.url); +//去掉文件名,获取目录的路径 +const __dirname = path.dirname(__filename); + +const app = express(); +// 把 web 目录设置成:server 的上一级 + /web +app.use(express.static(path.join(__dirname, "..", "web"))); +// 创建http服务 +const server = http.createServer(app); +//创建websocket +const wss = new WebSocketServer({ server }); + +/** + * rooms: Map> + */ +const rooms = new Map(); + +/** 给某个 ws 发送 JSON */ +function send(ws, data) { + //判断ws是否处于可用状态,将data序列化为字符串发送给ws的对端(客户端) + if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(data)); +} + +/** 房间内给除了自己之外的其他人转发 */ +function relayToOthers(roomId, sender, data) { + //ws集合 + const set = rooms.get(roomId); + if (!set) return; + for (const peer of set) { + //如果peer不是发送方,那么就是接收方的ws + if (peer !== sender) send(peer, data); + } +} + +function removeFromRoom(ws) { + //ws 中包含roomId + const roomId = ws.roomId; + if (!roomId) return; + //根据roomId找到集合 + const set = rooms.get(roomId); + if (!set) return; + //将ws从集合中删除 + set.delete(ws); + // 通知剩余的人:对方离开 + for (const peer of set) { + send(peer, { type: "peer-left" }); + } + //如果双方都离开,则删除房间 + if (set.size === 0) rooms.delete(roomId); + //将roomId设置为null + ws.roomId = null; +} + +wss.on("connection", (ws) => { + ws.roomId = null; + + ws.on("message", (buf) => { + let msg; + try { + msg = JSON.parse(buf.toString()); + } catch { + return; + } + //将msg中的key为type的value取出来到type存储 + /** + * { + * 'type' : 'join', + * 'roomId', '1001' + * } + */ + const { type } = msg; + + if (type === "join") { + const roomId = String(msg.roomId || "").trim(); + if (!roomId) return send(ws, { type: "error", message: "roomId is required" }); + + // 如果 ws 已在别的房间,先移除 + removeFromRoom(ws); + //利用或的短路效应,可以先根据roomId获取集合,如果没有则调用new Set(),如果有则使用roomId对应的集合 + const set = rooms.get(roomId) || new Set(); + if (set.size >= 2) { + return send(ws, { type: "full", roomId }); + } + + set.add(ws); + rooms.set(roomId, set); + ws.roomId = roomId; + + send(ws, { type: "joined", roomId, peers: set.size - 1 }); + + // 房间凑齐 2 人,通知双方开始协商 + if (set.size === 2) { + // 约定:后加入的人做 initiator(也可以反过来) + for (const peer of set) { + //判断找到peer和ws相等,也就是后加入的一端,如果不是后加入的isInitiator为false + //如果是isInitiator则为true + const isInitiator = peer === ws; + //广播,后加入的isInitiator为true,先加入的为false + send(peer, { type: "ready", isInitiator }); + } + } + return; + } + + // 后面的消息都必须在房间里 + const roomId = ws.roomId; + if (!roomId) return send(ws, { type: "error", message: "join a room first" }); + + // 透传 WebRTC 协商消息 + if (type === "offer" || type === "answer" || type === "ice") { + relayToOthers(roomId, ws, msg); + return; + } + + if (type === "leave") { + removeFromRoom(ws); + send(ws, { type: "left" }); + return; + } + }); + + ws.on("close", () => removeFromRoom(ws)); + ws.on("error", () => removeFromRoom(ws)); +}); + +const PORT = process.env.PORT || 3000; +server.listen(PORT, "0.0.0.0", () => { + console.log(`Signaling+Web server running: http://localhost:${PORT}`); +}); diff --git a/webrtc-demo/web/index.html b/webrtc-demo/web/index.html new file mode 100644 index 0000000..08f08fc --- /dev/null +++ b/webrtc-demo/web/index.html @@ -0,0 +1,275 @@ + + + + + + WebRTC 1v1 Room + + + +

WebRTC 双人视频房间

+
联系我微信1017234088,加入技术讨论群
+
+ + + + 未加入 +
+ +
状态:未连接
+ +
+
+
本地
+ +
+
+
远端
+ +
+
+ + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day37-\350\201\212\345\244\251\344\277\241\346\201\257\345\255\230\345\202\250\346\226\271\346\241\210.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day37-\350\201\212\345\244\251\344\277\241\346\201\257\345\255\230\345\202\250\346\226\271\346\241\210.md" new file mode 100644 index 0000000..fabe745 --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day37-\350\201\212\345\244\251\344\277\241\346\201\257\345\255\230\345\202\250\346\226\271\346\241\210.md" @@ -0,0 +1,3647 @@ +--- +title: 聊天信息存储方案 +date: 2025-05-28 12:56:16 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 需求分析 + +我们希望客户端在登录后,从服务器拉取聊天信息,并且展示。常规的设计中,客户端本地也会有一个数据库,缓存上一次获取的最后的聊天信息,如果客户端下线了,再次登录,只需要从服务器拉取未接受的数据即可。 + +所以综合考虑过后将需求列出 + +1. 客户端本地数据库缓存已经接受的消息(以后再做) +2. 客户端登录后,将本地数据的最大的消息id发送给服务器,服务器根据这个id去数据库查找,找到比这个id大的消息,将消息回传给客户端 +3. 客户端登录后,先加载旧的数据,再差异加载未读取的数据即可。 + +客户端本地数据库存储放在之后实现,所以我们客户端目前只发送消息id为0即可。 + +## 数据模型设计 + +1. **消息唯一标识** + - 在服务器端的 MySQL 表里,为每条消息分配一个全局唯一的自增主键(`message_id`),再配合时间戳(`created_at`)。 + - 客户端本地用同样的 `message_id` 做主键,这样就能很方便地做增量同步与去重。 +2. **会话/用户维度的索引** + - 如果支持多对多(群聊),再维护一个会话表(`thread_id`)和用户—会话关联表。 + - 查询和分页时,都按 `(thread_id, message_id)` 或 `(thread_id, created_at)` 建复合索引,加速筛选。 + + + +## 同步流程 + +1. **客户端登录时** + + 1. 从本地 SQLite 加载最近 N 条消息(按 `message_id` 或时间倒序),渲染到界面。 + + 2. 读取本地记录的「每个会话已同步到的最大 `message_id`」,发送给服务器: + + ```json + { + "action": "fetch_messages", + "thread_id": 123, + "since_id": 3456 + } + ``` + +2. **服务器端响应** + + - 查询 `WHERE thread_id=123 AND message_id>3456 ORDER BY message_id ASC LIMIT 1000` + - 返回消息列表(可以分页返回,大量时前端可循环拉取,或返回 `has_more` 标记)。 + +3. **客户端接收并保存** + + - 将服务器返回的消息批量插入本地 SQLite,注意用「主键冲突忽略(`INSERT OR IGNORE`)」防止重复。 + - 更新本地「已同步最大 `message_id`」。 + +4. **后续聊天时** + + - 新消息既推到服务器,也实时写入本地 SQLite。 + - 如果走长连接(`Asio` + 自定义协议或使用 WebSocket),服务器收到新消息后直接广播给在线客户端,并提示客户端写到本地。 + - 如果客户端离线,新消息积累在服务器,下一次登录再按 above 流程拉取。 + +## 聊天消息表 + +下面给出消息聊天表的字段和解释,包含了message_id, thread_id以及常见的其他字段 + +``` sql +CREATE TABLE `chat_message` ( + `message_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `thread_id` BIGINT UNSIGNED NOT NULL, + `sender_id` BIGINT UNSIGNED NOT NULL, + `recv_id` BIGINT UNSIGNED NOT NULL, + `content` TEXT NOT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0=未读 1=已读 2=撤回', + PRIMARY KEY (`message_id`), + KEY `idx_thread_created` (`thread_id`, `created_at`), + KEY `idx_thread_message` (`thread_id`, `message_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +``` + +### 字段说明 + +- `message_id`:全局自增主键,唯一标识一条消息。 +- `thread_id`:会话(单聊、群聊)ID,同一会话下的所有消息共用一个 `thread_id`。 +- `sender_id`:发送者用户 ID,指向用户表的主键。 +- `recv_id` : 接收者用户ID,指向用户表主键 +- `content`:消息正文,TEXT 类型,适合存储普通文字。 +- `created_at`:消息创建时间,自动记录插入时刻。 +- `updated_at`:消息更新时间,可用于标记“撤回”(status 变更)、编辑等操作。 +- `status`:消息状态,用于标记未读/已读/撤回等(也可扩展更多状态)。 + + + +### 索引设计 + +1. **主键索引**:`PRIMARY KEY (message_id)` 用于唯一检索消息。 +2. **会话+时间索引**:`KEY (thread_id, created_at)` 支持按会话分页、按时间范围查询。 +3. **会话+消息ID 索引**:`KEY (thread_id, message_id)` 支持按 `message_id` 做增量拉取(`WHERE thread_id=… AND message_id > since_id`)。 + +#### 可选扩展 + +- **群聊用户表**:如果支持群聊,需要一个 `thread_member` 表,记录每个 `thread_id` 下的成员及其角色。 +- **附件支持**:若要存储图片/文件,可额外建 `message_attachment` 表,字段例如 `attachment_id`、`message_id`、`file_url`、`file_type`。 +- **已读回执**:单独设计 `message_read` 表,记录哪些用户在何时已读了该消息,字段如 `(message_id, user_id, read_at)`。 + + + +## 会话消息表 + +### 全局聊天线程表 + +建立`chat_thread`主表,给它一个**全局自增**`id`,记录所有私聊/群聊的`线程`统一入口 + +``` sql +CREATE TABLE chat_thread ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `type` ENUM('private','group') NOT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); +``` + + + +### 单聊表设计 + +对于单聊,只有两个人,所以可以直接在private_chat表中定义两个字段存储user1_id和user2_id,这样能直接确定参与者 + +``` sql +CREATE TABLE `private_chat` ( + `thread_id` BIGINT UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `user1_id` BIGINT UNSIGNED NOT NULL, + `user2_id` BIGINT UNSIGNED NOT NULL, + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`), + UNIQUE KEY `uniq_private_thread` (`user1_id`, `user2_id`), -- 保证每对用户只能有一个私聊会话 + -- 以下两行就是我们要额外加的复合索引 + KEY `idx_private_user1_thread` (`user1_id`, `thread_id`), + KEY `idx_private_user2_thread` (`user2_id`, `thread_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +``` + +- 通过 `user1_id` 和 `user2_id` 唯一确定一个单聊会话 +- 询某两个用户的单聊时,直接 `SELECT` 即可。 + +### 群聊表设计 + +群聊相较于单聊要复杂一些,需要记录每个群聊的多名成员及其角色、权限等信息 + +先建一个独立的会话(线程)表: + +```sql +CREATE TABLE `group_chat` ( + `thread_id` BIGINT UNSIGNED NOT NULL COMMENT '引用chat_thread.id', + `name` VARCHAR(255) DEFAULT NULL COMMENT '群聊名称', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`thread_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +``` + +- 群聊会话表只存储群聊本身的信息(如群名称、创建时间等),`thread_id` 是唯一标识符 + +### 群聊成员表设计 + +- 群聊成员表用于存储群聊中各成员的信息(包括角色、加入时间、禁言等)。 + +``` sql +CREATE TABLE `group_chat_member` ( + `thread_id` BIGINT UNSIGNED NOT NULL COMMENT '引用 group_chat_thread.thread_id', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '引用 user.user_id', + `role` TINYINT NOT NULL DEFAULT 0 COMMENT '0=普通成员,1=管理员,2=创建者', + `joined_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + `muted_until` TIMESTAMP NULL COMMENT '如果被禁言,可存到什么时候', + PRIMARY KEY (`thread_id`, `user_id`), + KEY `idx_user_threads` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +``` + + + +## 前端聊天框调整 + +### 回顾 + +我们先回顾一下之前设计的聊天框 + +![https://cdn.llfc.club/1718417551126.jpg](https://cdn.llfc.club/1718417551126.jpg) + +对于我们自己发出的信息,我们可以实现这样一个网格布局管理 + +![https://cdn.llfc.club/1718423760358.jpg](https://cdn.llfc.club/1718423760358.jpg) + +`NameLabel`用来显示用户的名字,`Bubble`用来显示聊天信息,Spacer是个弹簧,保证将`NameLabel``,IconLabel`,`Bubble`等挤压到右侧。 + +如果是别人发出的消息,我们设置这样一个网格布局 + +![https://cdn.llfc.club/1718497364660.jpg](https://cdn.llfc.club/1718497364660.jpg) + +### 增加状态标签 + +因为自己发送的时候要增加发送状态(发送失败,未读,已读)三种,所以考虑将自己发送的消息改为如下 + + + +![image-20250601121313179](https://cdn.llfc.club/img/image-20250601121313179.png) + +大体结构如下 + +``` markdown + 列0 列1 列2 列3 + ┌───────┬───────────┬────────────┬──────────┐ +行 0 │ │ (空) │ m_pNameLabel │ m_pIconLabel │ + │ │ (col=1, │ (右对齐+8px)│ (跨两行、靠上) │ + │ │ 未放置)│ │ │ + ├───────┼───────────┼────────────┴──────────┤ +行 1 │ pSpacer│ m_pStatusLabel │ m_pBubble │ m_pIconLabel │ + │ │ (row=1, │ (聊天气泡) │ (继续占位) │ + │ │ col=1) │ │ │ + └───────┴───────────┴──────────────────────┘ + +``` + +代码修改如下 + +``` cpp +ChatItemBase::ChatItemBase(ChatRole role, QWidget *parent) + : QWidget(parent) + , m_role(role) +{ + m_pNameLabel = new QLabel(); + m_pNameLabel->setObjectName("chat_user_name"); + QFont font("Microsoft YaHei"); + font.setPointSize(9); + m_pNameLabel->setFont(font); + m_pNameLabel->setFixedHeight(20); + m_pIconLabel = new QLabel(); + m_pIconLabel->setScaledContents(true); + m_pIconLabel->setFixedSize(42, 42); + m_pBubble = new QWidget(); + QGridLayout *pGLayout = new QGridLayout(); + pGLayout->setVerticalSpacing(3); + pGLayout->setHorizontalSpacing(3); + pGLayout->setMargin(3); + QSpacerItem*pSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + //添加状态图标控件 + m_pStatusLabel = new QLabel(); + m_pStatusLabel->setFixedSize(16, 16); + m_pStatusLabel->setScaledContents(true); + + if(m_role == ChatRole::Self) + { + m_pNameLabel->setContentsMargins(0,0,8,0); + m_pNameLabel->setAlignment(Qt::AlignRight); + //名字标签 + pGLayout->addWidget(m_pNameLabel, 0,2, 1,1); + //icon 头像 + pGLayout->addWidget(m_pIconLabel, 0, 3, 2,1, Qt::AlignTop); + //第 0 列:依然是 pSpacer,占用第 1 行,第 0 列 + pGLayout->addItem(pSpacer, 1, 0, 1, 1); + //气泡控件 + pGLayout->addWidget(m_pBubble, 1,2, 1,1); + //状态图标 + pGLayout->addWidget(m_pStatusLabel, 1, 1, 1, 1, Qt::AlignCenter); + pGLayout->setColumnStretch(0, 2); + pGLayout->setColumnStretch(1, 0); // status 图标 (固定大小) + pGLayout->setColumnStretch(2, 3); // 名字 + 气泡 (主要拉伸区域) + pGLayout->setColumnStretch(3, 0); // 头像 (固定大小) + }else{ + m_pNameLabel->setContentsMargins(8,0,0,0); + m_pNameLabel->setAlignment(Qt::AlignLeft); + pGLayout->addWidget(m_pIconLabel, 0, 0, 2,1, Qt::AlignTop); + pGLayout->addWidget(m_pNameLabel, 0,1, 1,1); + pGLayout->addWidget(m_pBubble, 1,1, 1,1); + pGLayout->addItem(pSpacer, 2, 2, 1, 1); + pGLayout->setColumnStretch(1, 3); + pGLayout->setColumnStretch(2, 2); + } + this->setLayout(pGLayout); +} + +``` + +### 增加接口设置状态 + +``` cpp +void ChatItemBase::setStatus(int status) { + if (status == MsgStatus::UN_READ) { + m_pStatusLabel->setPixmap(QPixmap(":/res/unread.png")); + return; + } + + if (status == MsgStatus::SEND_FAILE) { + m_pStatusLabel->setPixmap(QPixmap(":/res/send_fail.png")); + return; + } + + if (status == MsgStatus::READED) { + m_pStatusLabel->setPixmap(QPixmap(":/res/readed.png")); + return; + } +} +``` + +## 客户端同步流程 + +客户端本地会有`sql`记录该用户所有聊天记录最后收到的消息信息,包括`message_id`,`thread_id`等,每次客户端登录将本地最大`messag_id`和`thread_id`发送给服务器,服务器按照每个`thread_id`将信息恢复给客户端,可支持分页返回。 + +**举例** + +比如第一次请求,客户端携带`message_id`为1001,`thread_id`为22,那么服务器就会去`chat_message`中升序查找,比`message_id`(1001)大且`thread_id`为22的消息,返回20条 + +客户端拿到20条消息后,可根据最后一个消息`messag_id`继续请求消息。 + +所以我们得出一个结论要拉取消息就要有`thread_id`以及`message_id`。 + +接下来的情形分为两种 + +**情况1** + +本地有`thread_id`,但是在该用户A离线的时候B用户给他发消息,因为他们之前没有聊过天,所以此时B会通知服务器在`private_chat`表中创建新的`thread_id`,但是A本地数据库没有这个`thread_id`,所以A需要在登录时拉取. + +拉取就传递目前A本地数据库中最大的`thead_id`以及自己的`user_id`给服务器,服务器去查找比这个`thread_id`大的会话列表返回即可,采取分页的方式,每次加载100个,并配合`load_more`字段通知客户端是否继续拉取 + +如果`load_more`字段为`true`则客户端继续拉取,传递上次服务器给它同步的最大的`thread_id`,服务器继续返回比`thread_id`大的会话列表。 + +直到`load_more`为`false`,客户端不再拉取。 + +**情况2** + +如果客户端换了新机器,本地没有记录信息,那么就需要在用户登录后向服务器发送`user_id`和`thread_id`,thread_id 请求从 0 开始,服务器将返回该用户的所有聊天`thread_id`,必须分页返回,并且携带 load_more 字段,字段和上面类似。 + + + +**一个服务器返回的数据格式如下** + +``` json +{ + "error":0, + "uid" : 1001, + "load_more":true, + + "threads":[ + { + "thread_id": 1001, + "type": "private", + "user1_id": 1019, + "user2_id": 1020 + }, + { + "thread_id": 1002, + "type": "group", + "user1_id": 0, + "user2_id": 0, + }, + { + "thread_id": 1003, + "type": "private", + "user1_id": 1019, + "user2_id": 1021 + }, + { + "thread_id": 1004, + "type": "group", + "user1_id": 0, + "user2_id": 0 + } + ] +} + +``` + +可采用如下sql语句查询 + +``` sql +-- 1) CTE 把私聊/群聊合并好 +WITH all_threads AS ( + SELECT + thread_id, + 'private' AS type, + user1_id, + user2_id + FROM private_chat + WHERE (user1_id = :me OR user2_id = :me) + AND thread_id > :last_id + UNION ALL + SELECT + thread_id, + 'group' AS type, + NULL AS user1_id, + NULL AS user2_id + FROM group_chat_member + WHERE user_id = :me + AND thread_id > :last_id +) +-- 2) 按 thread_id 升序,取 page_size+1 条 +SELECT * +FROM all_threads +ORDER BY thread_id +LIMIT :page_size + 1; + +``` + +然后在服务端(伪代码)处理结果: + +``` +def fetch_threads(me, last_id, page_size): + rows = db.query(sql, { "me": me, "last_id": last_id, "page_size": page_size }) + # rows 最多有 page_size+1 条 + if len(rows) > page_size: + load_more = True + rows = rows[:-1] # 丢掉第 page_size+1 条 + else: + load_more = False + + # 更新下一次游标:取最后一条的 thread_id + if rows: + next_last_id = rows[-1]["thread_id"] + else: + next_last_id = last_id + + return { + "data": rows, + "next_last_id": next_last_id, + "load_more": load_more + } +``` + +#### 说明 + +1. **为什么要多取 1 条?** + - 取 `page_size + 1` 条后,如果结果确实多出那 1 条,就说明“在本页之后”还有数据; + - 如果正好只有 `page_size` 条或更少,就可以断定已经取尽。 +2. **游标(cursor)模式 vs OFFSET** + - 用游标(`thread_id > last_id`)可以保证性能,避免大 OFFSET 带来的全表扫描。 + - 每次请求只跑新数据所在的索引范围。 +3. **客户端流程** + - **初次加载**:传 `last_id = 0`; + - **点「加载更多」**:传上次接口返回的 `next_last_id`; + - **收到 `load_more = false`**:表示已到末尾,不要再发更多请求。 + + + +当然为了提升效率,可以在用户登录后,选择是否同步消息的勾选框 + +如果勾选则调用上述sql语句查询该用户所有chat_thread返回。 + +如果没勾选,就不用加载chat_thread。 + + + +## 重构聊天item + +需要重构聊天左侧`item`列表结构,以支持聊天消息记录持久化存储。 + +默认情况下,会检索本地客户端是否有聊天记录信息, + +如果没有则需要请求所有`thread_id`列表,然后更新左侧`item`列表。 + +如果有,也需要差异化加载 thread_id 列表,比如说 A 下线了,B 和 A 通信,A 之前没有收到过 B 的信息,所以也要拉取所有新建立的会话。 + +所以当务之急是先把这个聊天列表加载好 + +因为我们没有为客户端设置本地数据库,所以我们默认每次用户登录都请求一下所有`thread_id`列表,这样方便测试效果 + +### Server返回聊天列表 + +`Server`需要根据用户`uid`返回他的聊天列表 + +**1 注册消息** + +``` cpp + _fun_callbacks[ID_LOAD_CHAT_THREAD_REQ] = std::bind(&LogicSystem::GetUserThreadsHandler, this, + placeholders::_1, placeholders::_2, placeholders::_3); +``` + +**2 实现获取聊天记录逻辑** + +``` cpp +void LogicSystem::GetUserThreadsHandler(std::shared_ptr session, + const short& msg_id, const string& msg_data) +{ + //从数据库加chat_threads记录 + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto uid = root["uid"].asInt(); + std::cout << "get uid threads " << uid << std::endl; + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["uid"] = uid; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_LOAD_CHAT_THREAD_RSP); + }); + + std::vector> threads; + bool res = GetUserThreads(uid, threads); + if (!res) { + rtvalue["error"] = ErrorCodes::UidInvalid; + return; + } + + //整理threads数据写入json返回 + for (auto& thread : threads) { + Json::Value thread_value; + thread_value["thread_id"] = int(thread->_thread_id); + thread_value["type"] = thread->_type; + thread_value["user1_id"] = thread->_user1_id; + thread_value["user2_id"] = thread->_user2_id; + rtvalue["threads"].append(thread_value); + } +} + +bool LogicSystem::GetUserThreads(int userId, + std::vector>& threads) +{ + return MysqlMgr::GetInstance()->GetUserThreads(userId, threads); +} +``` + +**3 数据库加载聊天** + +``` cpp +// 新增两个输出参数:loadMore, nextLastId +bool MysqlDao::GetUserThreads( + int64_t userId, + int64_t lastId, + int pageSize, + std::vector>& threads, + bool& loadMore, + int64_t& nextLastId) +{ + // 初始状态 + loadMore = false; + nextLastId = lastId; + threads.clear(); + + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + try { + // 准备分页查询:CTE + UNION ALL + ORDER + LIMIT N+1 + std::string sql = + "WITH all_threads AS ( " + " SELECT thread_id, 'private' AS type, user1_id, user2_id " + " FROM private_chat " + " WHERE (user1_id = ? OR user2_id = ?) " + " AND thread_id > ? " + " UNION ALL " + " SELECT thread_id, 'group' AS type, 0 AS user1_id, 0 AS user2_id " + " FROM group_chat_member " + " WHERE user_id = ? " + " AND thread_id > ? " + ") " + "SELECT thread_id, type, user1_id, user2_id " + " FROM all_threads " + " ORDER BY thread_id " + " LIMIT ?;"; + + std::unique_ptr pstmt( + conn->prepareStatement(sql)); + + // 绑定参数:? 对应 (userId, userId, lastId, userId, lastId, pageSize+1) + int idx = 1; + pstmt->setInt64(idx++, userId); // private.user1_id + pstmt->setInt64(idx++, userId); // private.user2_id + pstmt->setInt64(idx++, lastId); // private.thread_id > lastId + pstmt->setInt64(idx++, userId); // group.user_id + pstmt->setInt64(idx++, lastId); // group.thread_id > lastId + pstmt->setInt(idx++, pageSize + 1); // LIMIT pageSize+1 + + // 执行 + std::unique_ptr res(pstmt->executeQuery()); + + // 先把所有行读到临时容器 + std::vector> tmp; + while (res->next()) { + auto cti = std::make_shared(); + cti->_thread_id = res->getInt64("thread_id"); + cti->_type = res->getString("type"); + cti->_user1_id = res->getInt64("user1_id"); + cti->_user2_id = res->getInt64("user2_id"); + tmp.push_back(cti); + } + + // 判断是否多取到一条 + if ((int)tmp.size() > pageSize) { + loadMore = true; + tmp.pop_back(); // 丢掉第 pageSize+1 条 + } + + // 如果还有数据,更新 nextLastId 为最后一条的 thread_id + if (!tmp.empty()) { + nextLastId = tmp.back()->_thread_id; + } + + // 移入输出向量 + threads = std::move(tmp); + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() + << " (MySQL error code: " << e.getErrorCode() + << ", SQLState: " << e.getSQLState() << ")\n"; + return false; + } + + return true; +} + +``` + +### 客户端请求聊天列表 + +**1 完善`loading`对话框** + +完善加载对话框,调整下布局,增加一个`label`和旋转`gif`的布局 + +![image-20250605180346879](https://cdn.llfc.club/img/image-20250605180346879.png) + +布局界面 + +![image-20250605180401895](https://cdn.llfc.club/img/image-20250605180401895.png) + +接下来调整下代码 + +``` cpp +#ifndef LOADINGDLG_H +#define LOADINGDLG_H + +#include + +namespace Ui { +class LoadingDlg; +} + +class LoadingDlg : public QDialog +{ + Q_OBJECT + +public: + explicit LoadingDlg(QWidget *parent = nullptr, QString tip = "Loading..."); + ~LoadingDlg(); + +private: + Ui::LoadingDlg *ui; +}; + +#endif // LOADINGDLG_H + +``` + +具体实现 + +``` cpp +LoadingDlg::LoadingDlg(QWidget *parent, QString tip): + QDialog(parent), + ui(new Ui::LoadingDlg) +{ + ui->setupUi(this); + + // 1. 让这个 Widget 透明背景、无边框、拦截底部事件 + setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint | Qt::WindowStaysOnTopHint); + setAttribute(Qt::WA_TranslucentBackground);// 设置背景透明 + // 2. 让它覆盖父窗口整个面积 + if (parent) { + // 获取屏幕尺寸 + setFixedSize(parent->size()); // 设置对话框为全屏尺寸 + } + + if (parent) { + QPoint topLeft = parent->mapToGlobal(QPoint(0, 0)); + move(topLeft); + } + + // 3. 半透明黑色背景(alpha = 128,大约 50% 透明度) + // setStyleSheet("background-color: rgba(0, 0, 0, 128);"); + + QMovie *movie = new QMovie(":/res/loading2.gif"); // 加载动画的资源文件 + ui->loading_lb->setMovie(movie); + movie->start(); + // 3. 告诉 QMovie:将解码后的每一帧缩放到 100×100(固定大小) + movie->setScaledSize(ui->loading_lb->size()); + ui->status_lb->setText(tip); +} + +LoadingDlg::~LoadingDlg() +{ + delete ui; +} +``` + +**2 加载聊天记录** + +之前没有从数据库加载聊天记录,只是模拟从本地好友中加载为聊天记录了,现在需要将这部分从`ChatDialog`构造函数中移除 + +改为从服务器申请,并且此时展示`LoadingDlg`对话框,直到获取记录后,将`LoadingDlg`移除。 + +因为获取服务器记录是通过网络获取的,所以在客户端的`TcpMgr`中通过信号发送给`ChatDialog`界面 + +所以`ChatDialog`的构造函数改为如下 + +``` cpp +ChatDialog::ChatDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::ChatDialog), _b_loading(false), _mode(ChatUIMode::ChatMode), + _state(ChatUIMode::ChatMode), _last_widget(nullptr), _cur_chat_uid(0), _loading_dlg(nullptr) +{ + ui->setupUi(this); + + ui->add_btn->SetState("normal", "hover", "press"); + ui->add_btn->setProperty("state", "normal"); + QAction* searchAction = new QAction(ui->search_edit); + searchAction->setIcon(QIcon(":/res/search.png")); + ui->search_edit->addAction(searchAction, QLineEdit::LeadingPosition); + ui->search_edit->setPlaceholderText(QStringLiteral("搜索")); + + + // 创建一个清除动作并设置图标 + QAction* clearAction = new QAction(ui->search_edit); + clearAction->setIcon(QIcon(":/res/close_transparent.png")); + // 初始时不显示清除图标 + // 将清除动作添加到LineEdit的末尾位置 + ui->search_edit->addAction(clearAction, QLineEdit::TrailingPosition); + + // 当需要显示清除图标时,更改为实际的清除图标 + connect(ui->search_edit, &QLineEdit::textChanged, [clearAction](const QString& text) { + if (!text.isEmpty()) { + clearAction->setIcon(QIcon(":/res/close_search.png")); + } + else { + clearAction->setIcon(QIcon(":/res/close_transparent.png")); // 文本为空时,切换回透明图标 + } + + }); + + // 连接清除动作的触发信号到槽函数,用于清除文本 + connect(clearAction, &QAction::triggered, [this, clearAction]() { + ui->search_edit->clear(); + clearAction->setIcon(QIcon(":/res/close_transparent.png")); // 清除文本后,切换回透明图标 + ui->search_edit->clearFocus(); + //清除按钮被按下则不显示搜索框 + ShowSearch(false); + }); + + ui->search_edit->SetMaxLength(15); + + //连接加载信号和槽 + connect(ui->chat_user_list, &ChatUserList::sig_loading_chat_user, this, &ChatDialog::slot_loading_chat_user); + //模拟加载自己头像 + QString head_icon = UserMgr::GetInstance()->GetIcon(); + QPixmap pixmap(head_icon); // 加载图片 + QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->side_head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->side_head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + ui->side_chat_lb->setProperty("state", "normal"); + + ui->side_chat_lb->SetState("normal", "hover", "pressed", "selected_normal", "selected_hover", "selected_pressed"); + + ui->side_contact_lb->SetState("normal", "hover", "pressed", "selected_normal", "selected_hover", "selected_pressed"); + + ui->side_settings_lb->SetState("normal", "hover", "pressed", "selected_normal", "selected_hover", "selected_pressed"); + + AddLBGroup(ui->side_chat_lb); + AddLBGroup(ui->side_contact_lb); + AddLBGroup(ui->side_settings_lb); + + connect(ui->side_chat_lb, &StateWidget::clicked, this, &ChatDialog::slot_side_chat); + connect(ui->side_contact_lb, &StateWidget::clicked, this, &ChatDialog::slot_side_contact); + connect(ui->side_settings_lb, &StateWidget::clicked, this, &ChatDialog::slot_side_setting); + + //链接搜索框输入变化 + connect(ui->search_edit, &QLineEdit::textChanged, this, &ChatDialog::slot_text_changed); + + ShowSearch(false); + + //检测鼠标点击位置判断是否要清空搜索框 + this->installEventFilter(this); // 安装事件过滤器 + + //设置聊天label选中状态 + ui->side_chat_lb->SetSelected(true); + //设置选中条目 + SetSelectChatItem(); + //更新聊天界面信息 + SetSelectChatPage(); + + //连接加载联系人的信号和槽函数 + connect(ui->con_user_list, &ContactUserList::sig_loading_contact_user, + this, &ChatDialog::slot_loading_contact_user); + + //连接联系人页面点击好友申请条目的信号 + connect(ui->con_user_list, &ContactUserList::sig_switch_apply_friend_page, + this, &ChatDialog::slot_switch_apply_friend_page); + + //连接清除搜索框操作 + connect(ui->friend_apply_page, &ApplyFriendPage::sig_show_search, this, &ChatDialog::slot_show_search); + + //为searchlist 设置search edit + ui->search_list->SetSearchEdit(ui->search_edit); + + //连接申请添加好友信号 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_friend_apply, this, &ChatDialog::slot_apply_friend); + + //连接认证添加好友信号 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_add_auth_friend, this, &ChatDialog::slot_add_auth_friend); + + //链接自己认证回复信号 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_auth_rsp, this, + &ChatDialog::slot_auth_rsp); + + //连接点击联系人item发出的信号和用户信息展示槽函数 + connect(ui->con_user_list, &ContactUserList::sig_switch_friend_info_page, + this, &ChatDialog::slot_friend_info_page); + + //设置中心部件为chatpage + ui->stackedWidget->setCurrentWidget(ui->chat_page); + + + //连接searchlist跳转聊天信号 + connect(ui->search_list, &SearchList::sig_jump_chat_item, this, &ChatDialog::slot_jump_chat_item); + + //连接好友信息界面发送的点击事件 + connect(ui->friend_info_page, &FriendInfoPage::sig_jump_chat_item, this, + &ChatDialog::slot_jump_chat_item_from_infopage); + + //连接聊天列表点击信号 + connect(ui->chat_user_list, &QListWidget::itemClicked, this, &ChatDialog::slot_item_clicked); + + //连接对端消息通知 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_text_chat_msg, + this, &ChatDialog::slot_text_chat_msg); + + connect(ui->chat_page, &ChatPage::sig_append_send_chat_msg, this, &ChatDialog::slot_append_send_chat_msg); + + _timer = new QTimer(this); + connect(_timer, &QTimer::timeout, this, [this]() { + auto user_info = UserMgr::GetInstance()->GetUserInfo(); + QJsonObject textObj; + textObj["fromuid"] = user_info->_uid; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_HEART_BEAT_REQ, jsonData); + }); + + _timer->start(10000); + + //连接tcp返回的加载聊天回复 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_load_chat_thread, + this, &ChatDialog::slot_load_chat_thread); +} +``` + +当用户登录成功后会切换到聊天页面,此时请求聊天列表 + +``` cpp +void MainWindow::SlotSwitchChat() +{ + _chat_dlg = new ChatDialog(); + _chat_dlg->setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint); + setCentralWidget(_chat_dlg); + _chat_dlg->show(); + _login_dlg->hide(); + this->setMinimumSize(QSize(1050,900)); + this->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + _ui_status = CHAT_UI; + _chat_dlg->loadChatList(); +} +``` + +通过发送请求获取聊天记录 + +``` cpp +void ChatDialog::loadChatList() +{ + showLoadingDlg(true); + + //发送请求逻辑 + QJsonObject jsonObj; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj["uid"] = uid; + int last_chat_thread_id = UserMgr::GetInstance()->GetLastChatThreadId(); + jsonObj["thread_id"] = last_chat_thread_id; + + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_THREAD_REQ, jsonData); +} +``` + +`TCPMgr`注册从服务器获取回复的消息处理 + +``` cpp + _handlers.insert(ID_LOAD_CHAT_THREAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "chat thread json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get chat thread rsp failed, error is " << err; + return; + } + + qDebug() << "Receive chat thread rsp Success"; + + auto thread_array = jsonObj["threads"].toArray(); + std::vector> chat_threads; + for (const QJsonValue& value : thread_array) { + auto cti = std::make_shared(); + cti->_thread_id = value["thread_id"].toInt(); + cti->_type = value["type"].toString(); + cti->_user1_id = value["user1_id"].toInt(); + cti->_user2_id = value["user2_id"].toInt(); + chat_threads.push_back(cti); + } + + bool load_more = jsonObj["load_more"].toBool(); + int next_last_id = jsonObj["next_last_id"].toInt(); + //发送信号通知界面 + emit sig_load_chat_thread(load_more, next_last_id, chat_threads); + }); +``` + +`ChatDialog`接收`TcpMgr`发送的`sig_load_chat_thread`消息,然后触发如下函数,该函数主要加载聊天列表并且消除加载动画 + +``` cpp +void ChatDialog::slot_load_chat_thread(bool load_more, int last_thread_id, + std::vector> chat_threads) +{ + for (auto& cti : chat_threads) { + //先处理单聊,群聊跳过,以后添加 + if (cti->_type == "group") { + continue; + } + + auto uid = UserMgr::GetInstance()->GetUid(); + auto other_uid = 0; + if (uid == cti->_user1_id) { + other_uid = cti->_user2_id; + }else { + other_uid = cti->_user1_id; + } + + auto friend_info = UserMgr::GetInstance()->GetFriendById(other_uid); + if (!friend_info) { + continue; + } + + auto* chat_user_wid = new ChatUserWid(); + auto user_info = std::make_shared(friend_info); + chat_user_wid->SetInfo(user_info); + QListWidgetItem* item = new QListWidgetItem; + //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + item->setSizeHint(chat_user_wid->sizeHint()); + ui->chat_user_list->addItem(item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_items_added.insert(user_info->_uid, item); + + auto chat_thread_data = std::make_shared(); + chat_thread_data->_user1_id = uid; + chat_thread_data->_user2_id = other_uid; + chat_thread_data->_last_msg_id = 0; + chat_thread_data->_thread_id = cti->_thread_id; + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data); + } + + UserMgr::GetInstance()->SetLastChatThreadId(last_thread_id); + + if (load_more) { + //发送请求逻辑 + QJsonObject jsonObj; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj["uid"] = uid; + jsonObj["thread_id"] = last_thread_id; + + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_THREAD_REQ, jsonData); + return; + } + + //更新聊天界面信息 + SetSelectChatItem(); + SetSelectChatPage(); + showLoadingDlg(false); + +} +``` + + + +## 数据库构建 + +去`navicat`中执行上面数据模型设计中提到的几个`sql`语句 + +**1 创建`chat_thread`** + +**2 创建`group_chat`** + +![image-20250613154003601](https://cdn.llfc.club/img/image-20250613154003601.png) + +成功后显示 + +![image-20250605181826063](https://cdn.llfc.club/img/image-20250605181826063.png) + +**3 创建`group_member`** + +![image-20250613154030973](https://cdn.llfc.club/img/image-20250613154030973.png) + +成功后显示表 + +![image-20250605182001600](https://cdn.llfc.club/img/image-20250605182001600.png) + +**4 创建私聊表** + +![image-20250613154048586](https://cdn.llfc.club/img/image-20250613154048586.png) + +成功后显示 + +![image-20250605182147160](https://cdn.llfc.club/img/image-20250605182147160.png) + +**注意: 创建后没有数据,数据是我自己添加的,为了方便测试** + +开启服务器,客户端登陆后加载数据 + +效果如下 + +![image-20250605183518757](https://cdn.llfc.club/img/image-20250605183518757.png) + + + +## 首次单聊 + +A和B是好友,首次单聊,A发送给服务器创建聊天的请求。 + +服务器根据A的创建请求创建私聊,然后返回给客户端A。 + +**注意** + +因为聊天服务是异步的,而且是分布式的,所以有可能对方B就在此时发送消息给A,服务器已经创建好了,或者服务器正在调用`sql`创建。 + +所以对于创建请求,`sql`需要先查询是否已经被其他人创建了`thread_id`, 我们可以制定一个规则,任何一方创建thread_id,在写入私聊表`private_chat`时都需要保证最小的`uid`为`uid1_id`, 大的在`uid2_id`, 这样查询的时候也方便。 + +这个查询要加行级锁,避免分布式造成数据混乱。 + +**总结** + +所以创建单聊时,要先去`private_chat`表根据`uid`查询,如果查到了则返回这个`thread_id`, 这个查询要加行级锁。 + +如果没查到,则在`chat_thread`表创建`thread_id`并且插入`private_chat`表 + + + +**思路** + +我们整理下思路 + +1) 查询是否已存在私聊会话,如果存在则加锁行并返回 thread_id + +``` sql +SELECT thread_id +FROM private_chat +WHERE (user1_id = LEAST(:user1_id, :user2_id) AND user2_id = GREATEST(:user1_id, :user2_id)) + FOR UPDATE; -- 使用行级锁,避免并发冲突 +``` + +查询时使用 `LEAST` 和 `GREATEST` 来保证无论是 `user1_id` 还是 `user2_id`,都将较小的 ID 存放在 `user1_id`,较大的存放在 `user2_id`。这样可以避免不同的用户顺序导致查找不到匹配的记录。 + +`FOR UPDATE` 关键字会锁定这些查询行,确保在事务结束之前不会有其他并发的操作修改数据。 + + + +2. 如果未找到数据(查询返回空),则插入新记录: + +``` sql +-- 1. 在 chat_thread 表中创建新记录 +INSERT INTO chat_thread (type, created_at) +VALUES ('private', NOW()); +-- 2. 获取新插入的 thread_id(假设你可以通过 LAST_INSERT_ID 获取) +SELECT LAST_INSERT_ID(); +``` + +3. 将新生成的 thread_id 插入 private_chat 表 + +``` sql +INSERT INTO private_chat (thread_id, user1_id, user2_id, created_at) +VALUES (:new_thread_id, LEAST(:user1_id, :user2_id), GREATEST(:user1_id, :user2_id), NOW()); +``` + +使用 `INSERT INTO chat_thread` 创建新的聊天记录,并使用 `LAST_INSERT_ID()` 获取新生成的 `thread_id`。 + +将新 `thread_id` 插入到 `private_chat` 表中,同时使用 `LEAST` 和 `GREATEST` 确保较小的 ID 存入 `user1_id`,较大的存入 `user2_id`。 + +**问题分析** + +- **行级锁的生命周期:** + 行级锁(通过 `FOR UPDATE` 获得的锁)只在当前事务中有效。当查询结束后,锁会被释放。也就是说,如果我们查询了是否存在 `private_chat` 的记录并加了锁,但在查询完成后进行插入 `chat_thread` 和 `private_chat` 的操作时,其他并发请求可能会先插入新的私聊记录,从而造成数据冲突。 +- **可能的并发问题:** + 例如: + 1. 线程 A 执行查询,锁定了 `private_chat` 表的行; + 2. 线程 B 也执行了相同的查询,发现没有记录,于是开始插入 `chat_thread`; + 3. 线程 A 完成插入 `chat_thread` 和 `private_chat`,但线程 B 也在此时完成了它的插入,导致 `private_chat` 表中出现两个重复的记录。 + +**解决方案** + +为了确保并发操作的安全性,我们可以使用 **事务** 来保证在查询、插入 `chat_thread` 和 `private_chat` 表的过程中,数据的一致性和原子性。具体步骤如下: + +### 方案:使用事务(Atomic Transaction) + +我们可以使用 **事务** 来确保操作的一致性,整个操作从查询到插入都在一个事务中进行。这样即使存在多个并发请求,也能保证同一时间只有一个请求可以成功创建 `chat_thread` 和 `private_chat`。 + +**关键改动:** + +1. 在查询时加行级锁。 +2. 确保所有的数据库操作(查询和插入)都在一个事务中进行,这样可以防止并发插入的问题。 +3. 使用事务提交(`commit`)和回滚(`rollback`)确保数据一致性。 + +**关键代码** + +``` cpp +bool MysqlDao::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) +{ + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + try { + // 开启事务 + conn->setAutoCommit(false); + // 1. 查询是否已存在私聊并加行级锁 + int uid1 = std::min(user1_id, user2_id); + int uid2 = std::max(user1_id, user2_id); + std::string check_sql = + "SELECT thread_id FROM private_chat " + "WHERE (user1_id = ? AND user2_id = ?) " + "FOR UPDATE;"; + + std::unique_ptr pstmt(conn->prepareStatement(check_sql)); + pstmt->setInt64(1, uid1); + pstmt->setInt64(2, uid2); + std::unique_ptr res(pstmt->executeQuery()); + + if (res->next()) { + // 如果已存在,返回该 thread_id + thread_id = res->getInt("thread_id"); + conn->commit(); // 提交事务 + return true; + } + + // 2. 如果未找到,创建新的 chat_thread 和 private_chat 记录 + // 在 chat_thread 表插入新记录 + std::string insert_chat_thread_sql = + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());"; + + std::unique_ptr pstmt_insert_thread(conn->prepareStatement(insert_chat_thread_sql)); + pstmt_insert_thread->executeUpdate(); + + // 获取新插入的 thread_id + std::string get_last_insert_id_sql = "SELECT LAST_INSERT_ID();"; + std::unique_ptr pstmt_last_insert_id(conn->prepareStatement(get_last_insert_id_sql)); + std::unique_ptr res_last_id(pstmt_last_insert_id->executeQuery()); + res_last_id->next(); + thread_id = res_last_id->getInt(1); + + // 3. 在 private_chat 表插入新记录 + std::string insert_private_chat_sql = + "INSERT INTO private_chat (thread_id, user1_id, user2_id, created_at) " + "VALUES (?, ?, ?, NOW());"; + + + std::unique_ptr pstmt_insert_private(conn->prepareStatement(insert_private_chat_sql)); + pstmt_insert_private->setInt64(1, thread_id); + pstmt_insert_private->setInt64(2, uid1); + pstmt_insert_private->setInt64(3, uid2); + pstmt_insert_private->executeUpdate(); + + // 提交事务 + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } + return false; +} + +bool MysqlMgr::CreatePrivateChat(int user1_id, int user2_id, int& thread_id) +{ + return _dao.CreatePrivateChat(user1_id, user2_id, thread_id); +} +``` + +**LogicSystem**添加创建聊天的回调函数,并且注册 + +``` cpp +void LogicSystem::CreatePrivateChat(std::shared_ptr session, const short& msg_id, const string& msg_data) +{ + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto uid = root["uid"].asInt(); + auto other_id = root["other_id"].asInt(); + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["uid"] = uid; + rtvalue["other_id"] = other_id; + + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_LOAD_CHAT_THREAD_RSP); + }); + + int thread_id = 0; + bool res = MysqlMgr::GetInstance()->CreatePrivateChat(uid, other_id, thread_id); + if (!res) { + rtvalue["error"] = ErrorCodes::CREATE_CHAT_FAILED; + return; + } + + rtvalue["thread_id"] = thread_id; +} + +_fun_callbacks[ID_CREATE_PRIVATE_CHAT_REQ] = std::bind(&LogicSystem::CreatePrivateChat, this, + placeholders::_1, placeholders::_2, placeholders::_3); +``` + + + +### 客户端完善 + +在好友信息界面 + +``` cpp +void FriendInfoPage::on_msg_chat_clicked() +{ + qDebug() << "msg chat btn clicked"; + emit sig_jump_chat_item(_user_info); +} + +``` + +追踪这个信号,我们完善槽函数 + +``` cpp +void ChatDialog::slot_jump_chat_item_from_infopage(std::shared_ptr user_info) +{ + qDebug() << "slot jump chat item " << endl; + auto thread_id = UserMgr::GetInstance()->GetThreadIdByUid(user_info->_uid); + if (thread_id != -1) { + auto find_iter = _chat_thread_items.find(thread_id); + if (find_iter != _chat_thread_items.end()) { + qDebug() << "jump to chat item , uid is " << user_info->_uid; + ui->chat_user_list->scrollToItem(find_iter.value()); + ui->side_chat_lb->SetSelected(true); + SetSelectChatItem(user_info->_uid); + //更新聊天界面信息 + SetSelectChatPage(user_info->_uid); + slot_side_chat(); + return; + } //说明之前有缓存过聊天列表,只是被删除了,那么重新加进来即可 + else { + auto* chat_user_wid = new ChatUserWid(); + chat_user_wid->SetInfo(user_info); + QListWidgetItem* item = new QListWidgetItem; + qDebug() << "chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + ui->chat_user_list->insertItem(0, item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(thread_id, item); + ui->side_chat_lb->SetSelected(true); + SetSelectChatItem(user_info->_uid); + //更新聊天界面信息 + SetSelectChatPage(user_info->_uid); + slot_side_chat(); + return; + } + } + + //如果没找到,则发送创建请求 + auto uid = UserMgr::GetInstance()->GetUid(); + QJsonObject jsonObj; + jsonObj["uid"] = uid; + jsonObj["other_id"] = user_info->_uid; + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_CREATE_PRIVATE_CHAT_REQ, jsonData); +} + +``` + +客户端注册服务器返回的消息`ID_CREATE_PRIVATE_CHAT_RSP`,进行处理 + +``` cpp + _handlers.insert(ID_CREATE_PRIVATE_CHAT_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + int uid = jsonObj["uid"].toInt(); + int other_id = jsonObj["other_id"].toInt(); + int thread_id = jsonObj["thread_id"].toInt(); + + //发送信号通知界面 + emit sig_create_private_chat(uid, other_id, thread_id); + }); + +``` + +编写槽函数和`sig_create_private_chat`连接,并且增加聊天条目 + +``` cpp + //连接tcp返回的创建私聊的回复 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_create_private_chat, + this, &ChatDialog::slot_create_private_chat); +``` + +具体处理的槽函数 + +``` cpp +void ChatDialog::slot_create_private_chat(int uid, int other_id, int thread_id) +{ + auto* chat_user_wid = new ChatUserWid(); + auto user_info = UserMgr::GetInstance()->GetFriendById(other_id); + chat_user_wid->SetInfo(user_info); + QListWidgetItem* item = new QListWidgetItem; + item->setSizeHint(chat_user_wid->sizeHint()); + qDebug() << "chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + ui->chat_user_list->insertItem(0, item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(thread_id, item); + + auto chat_thread_data = std::make_shared(); + chat_thread_data->_user1_id = uid; + chat_thread_data->_user2_id = other_id; + chat_thread_data->_last_msg_id = 0; + chat_thread_data->_thread_id = thread_id; + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data, other_id); + + ui->side_chat_lb->SetSelected(true); + SetSelectChatItem(user_info->_uid); + //更新聊天界面信息 + SetSelectChatPage(user_info->_uid); + slot_side_chat(); + return; +} +``` + + + +## 聊天消息重构 + +### `ChaUserWid`重构 + +之前我们的会话列表由一个一个的`ChatUserWid`构成 + +![image-20250622085350930](https://cdn.llfc.club/img/image-20250622085350930.png) + +原来的`ChatUserWid`内部存储的是`UserInfo`结构,目前我们已经增加了`ChatThread`数据库内容,所以要将会话列表的每个`ChatUserWid`中存储`ChatThreadData`结构。 + +接下来我们定义这几个结构 + +``` cpp +class ChatUserWid : public ListItemBase +{ + Q_OBJECT + +public: + explicit ChatUserWid(QWidget *parent = nullptr); + ~ChatUserWid(); + QSize sizeHint() const override; + void SetChatData(std::shared_ptr chat_data); + std::shared_ptr GetChatData(); + void ShowRedPoint(bool bshow); + void updateLastMsg(std::vector> msgs); +private: + Ui::ChatUserWid *ui; + std::shared_ptr _chat_data; +}; +``` + +具体定义 + +``` cpp +void ChatUserWid::SetChatData(std::shared_ptr chat_data) { + _chat_data = chat_data; + auto other_id = _chat_data->GetOtherId(); + auto other_info = UserMgr::GetInstance()->GetFriendById(other_id); + // 加载图片 + QPixmap pixmap(other_info->_icon); + + // 设置图片自动缩放 + ui->icon_lb->setPixmap(pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + ui->icon_lb->setScaledContents(true); + + ui->user_name_lb->setText(other_info->_name); + + ui->user_chat_lb->setText(chat_data->GetLastMsg()); + +} + +std::shared_ptr ChatUserWid::GetChatData() +{ + return _chat_data; +} +``` + +这样我们就将聊天会话的信息写入到了`ChatUserWid`这样一个个小条目了。 + +### 消息类抽象 + +因为我们将来要存储文本,文件以及图片不同类型的消息,那么就将原来的消息抽象出一个基类 + +``` cpp +class ChatDataBase { +public: + ChatDataBase(int msg_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, + QString content,int _send_uid); + ChatDataBase(QString unique_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, + QString content, int send_uid); + int GetMsgId() { return _msg_id; } + int GetThreadId() { return _thread_id; } + ChatFormType GetFormType() { return _form_type; } + ChatMsgType GetMsgType() { return _msg_type; } + QString GetContent() { return _content; } + int GetSendUid() { return _send_uid; } + QString GetMsgContent(){return _content;} + void SetUniqueId(int unique_id); + QString GetUniqueId(); +private: + //客户端本地唯一标识 + QString _unique_id; + //消息id + int _msg_id; + //会话id + int _thread_id; + //群聊还是私聊 + ChatFormType _form_type; + //文本信息为0,图片为1,文件为2 + ChatMsgType _msg_type; + QString _content; + //发送者id + int _send_uid; +}; +``` + +然后基于上面的基类,我们可以定义不同类型的消息,如文本消息 + +``` cpp +class TextChatData : public ChatDataBase { +public: + + TextChatData(int msg_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, QString content, + int send_uid): + ChatDataBase(msg_id, thread_id, form_type, msg_type, content, send_uid) + { + + } + + TextChatData(QString unique_id, int thread_id, ChatFormType form_type, ChatMsgType msg_type, QString content, + int send_uid): + ChatDataBase(unique_id, thread_id, form_type, msg_type, content, send_uid) + { + + } + +}; +``` + +有了这个文本消息后,我们可以将基类指针`ChatDataBase`存储起来,将来通过实现虚函数,进行多态调用. + +### `ChatThreadData`聊天线程 + +聊天线程数据,重构和完善 + +``` cpp +//客户端本地存储的聊天线程数据结构 +class ChatThreadData { +public: + ChatThreadData(int other_id, int thread_id, int last_msg_id): + _other_id(other_id), _thread_id(thread_id), _last_msg_id(last_msg_id){} + void AddMsg(std::shared_ptr msg); + void SetLastMsgId(int msg_id); + void SetOtherId(int other_id); + int GetOtherId(); + QString GetGroupName(); + QMap> GetMsgMap(); + int GetThreadId(); + QMap>& GetMsgMapRef(); + void AppendMsg(int msg_id, std::shared_ptr base_msg); + QString GetLastMsg(); +private: + //如果是私聊,则为对方的id;如果是群聊,则为0 + int _other_id; + int _last_msg_id; + int _thread_id; + QString _last_msg; + //群聊信息,成员列表 + std::vector _group_members; + //群聊名称 + QString _group_name; + //缓存消息map,抽象为基类,因为会有图片等其他类型消息 + QMap> _msg_map; +}; +``` + +具体实现 + +``` cpp +void ChatThreadData::AddMsg(std::shared_ptr msg) +{ + _msg_map.insert(msg->GetMsgId(), msg); +} + +void ChatThreadData::SetLastMsgId(int msg_id) +{ + _last_msg_id = msg_id; +} + +void ChatThreadData::SetOtherId(int other_id) +{ + _other_id = other_id; +} + +int ChatThreadData::GetOtherId() { + return _other_id; +} + +QString ChatThreadData::GetGroupName() +{ + return _group_name; +} + +QMap> ChatThreadData::GetMsgMap() { + return _msg_map; +} + +int ChatThreadData::GetThreadId() +{ + return _thread_id; +} + +QMap>& ChatThreadData::GetMsgMapRef() +{ + return _msg_map; +} + + +void ChatThreadData::AppendMsg(int msg_id, std::shared_ptr base_msg) { + _msg_map.insert(msg_id, base_msg); + _last_msg = base_msg->GetMsgContent(); + _last_msg_id = msg_id; +} + +QString ChatThreadData::GetLastMsg() +{ + return _last_msg; +} + +``` + +## 好友认证 + +对于好友认证时,如果双方通过,也要默认建立聊天消息,并且产生会话列表. + +我们先从这块接入聊天消息列表,完善整体流程 + +### `proto`协议修改 + +因为认证添加好友后,会生成两条聊天信息(比如,我们已经是好友了等),同时通知给对方,协议格式增加和修改如下 + +``` cpp +message AddFriendMsg{ + int32 sender_id = 1; + string unique_id = 2; + int32 msg_id = 3; + int32 thread_id = 4; + string msgcontent = 5; +} + +message AuthFriendReq{ + int32 fromuid = 1; + int32 touid = 2; + repeated AddFriendMsg textmsgs = 3; +} + +message AuthFriendRsp{ + int32 error = 1; + int32 fromuid = 2; + int32 touid = 3; +} + +``` + +### 服务器接收好友申请 + +服务器收到A向B添加好友的请求,会更新数据库申请记录,同时转发给B + +``` cpp +void LogicSystem::AddFriendApply(std::shared_ptr session, const short& msg_id, const string& msg_data) +{ + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto uid = root["uid"].asInt(); + auto desc = root["applyname"].asString(); + auto bakname = root["bakname"].asString(); + auto touid = root["touid"].asInt(); + std::cout << "user login uid is " << uid << " applydesc is " + << desc << " bakname is " << bakname << " touid is " << touid << endl; + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_ADD_FRIEND_RSP); + }); + + //先更新数据库 + MysqlMgr::GetInstance()->AddFriendApply(uid, touid, desc, bakname); + + //查询redis 查找touid对应的server ip + auto to_str = std::to_string(touid); + auto to_ip_key = USERIPPREFIX + to_str; + std::string to_ip_value = ""; + bool b_ip = RedisMgr::GetInstance()->Get(to_ip_key, to_ip_value); + if (!b_ip) { + return; + } + + + auto& cfg = ConfigMgr::Inst(); + auto self_name = cfg["SelfServer"]["Name"]; + + + std::string base_key = USER_BASE_INFO + std::to_string(uid); + auto apply_info = std::make_shared(); + bool b_info = GetBaseInfo(base_key, uid, apply_info); + + //直接通知对方有申请消息 + if (to_ip_value == self_name) { + auto session = UserMgr::GetInstance()->GetSession(touid); + if (session) { + //在内存中则直接发送通知对方 + Json::Value notify; + notify["error"] = ErrorCodes::Success; + notify["applyuid"] = uid; + notify["name"] = apply_info->name; + notify["desc"] = desc; + if (b_info) { + notify["icon"] = apply_info->icon; + notify["sex"] = apply_info->sex; + notify["nick"] = apply_info->nick; + } + std::string return_str = notify.toStyledString(); + session->Send(return_str, ID_NOTIFY_ADD_FRIEND_REQ); + } + + return ; + } + + + AddFriendReq add_req; + add_req.set_applyuid(uid); + add_req.set_touid(touid); + add_req.set_name(apply_info->name); + add_req.set_desc(desc); + if (b_info) { + add_req.set_icon(apply_info->icon); + add_req.set_sex(apply_info->sex); + add_req.set_nick(apply_info->nick); + } + + //发送通知 + ChatGrpcClient::GetInstance()->NotifyAddFriend(to_ip_value,add_req); + +} +``` + +如果不在一个服务器,则通过`grpc`通知对端所在服务器, 对端服务器收到后,组织消息转发 + +``` cpp +Status ChatServiceImpl::NotifyAddFriend(ServerContext* context, const AddFriendReq* request, AddFriendRsp* reply) +{ + //查找用户是否在本服务器 + auto touid = request->touid(); + auto session = UserMgr::GetInstance()->GetSession(touid); + + Defer defer([request, reply]() { + reply->set_error(ErrorCodes::Success); + reply->set_applyuid(request->applyuid()); + reply->set_touid(request->touid()); + }); + + //用户不在内存中则直接返回 + if (session == nullptr) { + return Status::OK; + } + + //在内存中则直接发送通知对方 + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["applyuid"] = request->applyuid(); + rtvalue["name"] = request->name(); + rtvalue["desc"] = request->desc(); + rtvalue["icon"] = request->icon(); + rtvalue["sex"] = request->sex(); + rtvalue["nick"] = request->nick(); + + std::string return_str = rtvalue.toStyledString(); + + session->Send(return_str, ID_NOTIFY_ADD_FRIEND_REQ); + return Status::OK; +} +``` + +### 服务器收到同意申请 + +当B客户同意添加好友,会将请求发送给服务器 + +服务器收到后会执行 + +``` cpp +void LogicSystem::AuthFriendApply(std::shared_ptr session, const short& msg_id, const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto uid = root["fromuid"].asInt(); + auto touid = root["touid"].asInt(); + auto back_name = root["back"].asString(); + std::cout << "from " << uid << " auth friend to " << touid << std::endl; + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + auto user_info = std::make_shared(); + + std::string base_key = USER_BASE_INFO + std::to_string(touid); + bool b_info = GetBaseInfo(base_key, touid, user_info); + if (b_info) { + rtvalue["name"] = user_info->name; + rtvalue["nick"] = user_info->nick; + rtvalue["icon"] = user_info->icon; + rtvalue["sex"] = user_info->sex; + rtvalue["uid"] = touid; + } + else { + rtvalue["error"] = ErrorCodes::UidInvalid; + } + + + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_AUTH_FRIEND_RSP); + }); + + //先更新数据库, 放到事务中,此处不再处理 + //MysqlMgr::GetInstance()->AuthFriendApply(uid, touid); + + std::vector> chat_datas; + + //更新数据库添加好友 + MysqlMgr::GetInstance()->AddFriend(uid, touid,back_name, chat_datas); + + //查询redis 查找touid对应的server ip + auto to_str = std::to_string(touid); + auto to_ip_key = USERIPPREFIX + to_str; + std::string to_ip_value = ""; + bool b_ip = RedisMgr::GetInstance()->Get(to_ip_key, to_ip_value); + if (!b_ip) { + return; + } + + auto& cfg = ConfigMgr::Inst(); + auto self_name = cfg["SelfServer"]["Name"]; + //直接通知对方有认证通过消息 + if (to_ip_value == self_name) { + auto session = UserMgr::GetInstance()->GetSession(touid); + if (session) { + //在内存中则直接发送通知对方 + Json::Value notify; + notify["error"] = ErrorCodes::Success; + notify["fromuid"] = uid; + notify["touid"] = touid; + std::string base_key = USER_BASE_INFO + std::to_string(uid); + auto user_info = std::make_shared(); + bool b_info = GetBaseInfo(base_key, uid, user_info); + if (b_info) { + notify["name"] = user_info->name; + notify["nick"] = user_info->nick; + notify["icon"] = user_info->icon; + notify["sex"] = user_info->sex; + } + else { + notify["error"] = ErrorCodes::UidInvalid; + } + + for(auto & chat_data : chat_datas) + { + Json::Value chat; + chat["sender"] = chat_data->sender_id(); + chat["msg_id"] = chat_data->msg_id(); + chat["thread_id"] = chat_data->thread_id(); + chat["unique_id"] = chat_data->unique_id(); + chat["msg_content"] = chat_data->msgcontent(); + notify["chat_datas"].append(chat); + rtvalue["chat_datas"].append(chat); + } + + std::string return_str = notify.toStyledString(); + session->Send(return_str, ID_NOTIFY_AUTH_FRIEND_REQ); + } + + return ; + } + + + AuthFriendReq auth_req; + auth_req.set_fromuid(uid); + auth_req.set_touid(touid); + for(auto& chat_data : chat_datas) + { + auto text_msg = auth_req.add_textmsgs(); + text_msg->CopyFrom(*chat_data); + Json::Value chat; + chat["sender"] = chat_data->sender_id(); + chat["msg_id"] = chat_data->msg_id(); + chat["thread_id"] = chat_data->thread_id(); + chat["unique_id"] = chat_data->unique_id(); + chat["msg_content"] = chat_data->msgcontent(); + rtvalue["chat_datas"].append(chat); + } + //发送通知 + ChatGrpcClient::GetInstance()->NotifyAuthFriend(to_ip_value, auth_req); +} + +``` + +数据库处理 + +``` cpp +bool MysqlDao::AddFriend(const int& from, const int& to, std::string back_name, + std::vector>& chat_datas) { + auto con = pool_->getConnection(); + if (con == nullptr) { + return false; + } + + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + try { + + //开始事务 + con->_con->setAutoCommit(false); + std::string reverse_back; + std::string apply_desc; + + { + // 1. 锁定并读取 + std::unique_ptr selStmt(con->_con->prepareStatement( + "SELECT back_name, descs " + "FROM friend_apply " + "WHERE from_uid = ? AND to_uid = ? " + "FOR UPDATE" + )); + selStmt->setInt(1, to); + selStmt->setInt(2, from); + + std::unique_ptr rsSel(selStmt->executeQuery()); + + if (rsSel->next()) { + reverse_back = rsSel->getString("back_name"); + apply_desc = rsSel->getString("descs"); + } + else { + // 没有对应的申请记录,直接 rollback 并返回失败 + con->_con->rollback(); + return false; + } + } + + { + // 2. 执行真正的更新 + std::unique_ptr updStmt(con->_con->prepareStatement( + "UPDATE friend_apply " + "SET status = 1 " + "WHERE from_uid = ? AND to_uid = ?" + )); + + updStmt->setInt(1, to); + updStmt->setInt(2, from); + + if (updStmt->executeUpdate() != 1) { + // 更新行数不对,回滚 + con->_con->rollback(); + return false; + } + } + + { + // 3. 准备第一个SQL语句, 插入认证方好友数据 + std::unique_ptr pstmt(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?) " + )); + //反过来的申请时from,验证时to + pstmt->setInt(1, from); // from id + pstmt->setInt(2, to); + pstmt->setString(3, back_name); + // 执行更新 + int rowAffected = pstmt->executeUpdate(); + if (rowAffected < 0) { + con->_con->rollback(); + return false; + } + + //准备第二个SQL语句,插入申请方好友数据 + std::unique_ptr pstmt2(con->_con->prepareStatement("INSERT IGNORE INTO friend(self_id, friend_id, back) " + "VALUES (?, ?, ?) " + )); + //反过来的申请时from,验证时to + pstmt2->setInt(1, to); // from id + pstmt2->setInt(2, from); + pstmt2->setString(3, reverse_back); + // 执行更新 + int rowAffected2 = pstmt2->executeUpdate(); + if (rowAffected2 < 0) { + con->_con->rollback(); + return false; + } + } + + + + // 4. 创建 chat_thread + long long threadId = 0; + { + std::unique_ptr threadStmt(con->_con->prepareStatement( + "INSERT INTO chat_thread (type, created_at) VALUES ('private', NOW());" + )); + + threadStmt->executeUpdate(); + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + + if (rs->next()) { + threadId = rs->getInt64(1); + } + else { + return false; + } + } + + // 5. 插入 private_chat + { + std::unique_ptr pcStmt(con->_con->prepareStatement( + "INSERT INTO private_chat(thread_id, user1_id, user2_id) VALUES (?, ?, ?)" + )); + + pcStmt->setInt64(1, threadId); + pcStmt->setInt(2, from); + pcStmt->setInt(3, to); + if (pcStmt->executeUpdate() < 0) return false; + } + + // 6. 可选:插入初始消息到 chat_message + if (apply_desc.empty() == false) + { + std::unique_ptr msgStmt(con->_con->prepareStatement( + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content,created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + )); + + msgStmt->setInt64(1, threadId); + msgStmt->setInt(2, to); + msgStmt->setInt(3, from); + msgStmt->setString(4, apply_desc); + msgStmt->setInt(5, 0); + if (msgStmt->executeUpdate() < 0) { return false; } + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + auto messageId = rs->getInt64(1); + auto tx_data = std::make_shared(); + tx_data->set_sender_id(to); + tx_data->set_msg_id(messageId); + tx_data->set_msgcontent(apply_desc); + tx_data->set_thread_id(threadId); + tx_data->set_unique_id(""); + std::cout << "addfriend insert message success" << std::endl; + chat_datas.push_back(tx_data); + } + else { + return false; + } + } + + { + std::unique_ptr msgStmt(con->_con->prepareStatement( + "INSERT INTO chat_message(thread_id, sender_id, recv_id, content, created_at, updated_at, status) VALUES (?, ?, ?, ?,NOW(),NOW(),?)" + )); + + msgStmt->setInt64(1, threadId); + msgStmt->setInt(2, from); + msgStmt->setInt(3, to); + msgStmt->setString(4, "We are friends now!"); + + msgStmt->setInt(5, 0); + + if (msgStmt->executeUpdate() < 0) { return false; } + + std::unique_ptr stmt(con->_con->createStatement()); + std::unique_ptr rs( + stmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + auto messageId = rs->getInt64(1); + auto tx_data = std::make_shared(); + tx_data->set_sender_id(from); + tx_data->set_msg_id(messageId); + tx_data->set_msgcontent("We are friends now!"); + tx_data->set_thread_id(threadId); + tx_data->set_unique_id(""); + chat_datas.push_back(tx_data); + } + else { + return false; + } + } + + // 提交事务 + con->_con->commit(); + std::cout << "addfriend insert friends success" << std::endl; + + return true; + } + catch (sql::SQLException& e) { + // 如果发生错误,回滚事务 + if (con) { + con->_con->rollback(); + } + std::cerr << "SQLException: " << e.what(); + std::cerr << " (MySQL error code: " << e.getErrorCode(); + std::cerr << ", SQLState: " << e.getSQLState() << " )" << std::endl; + return false; + } + + + return true; +} +``` + +### 服务器收到同意通知 + +B同意A的申请,此时B所在的服务器会将同意的通知发送到A所在的服务器 + +下面是A所在的服务器收到请求后,发送通知给A的逻辑 + +``` cpp +Status ChatServiceImpl::NotifyAuthFriend(ServerContext* context, const AuthFriendReq* request, + AuthFriendRsp* reply) { + //查找用户是否在本服务器 + auto touid = request->touid(); + auto fromuid = request->fromuid(); + auto session = UserMgr::GetInstance()->GetSession(touid); + + Defer defer([request, reply]() { + reply->set_error(ErrorCodes::Success); + reply->set_fromuid(request->fromuid()); + reply->set_touid(request->touid()); + }); + + //用户不在内存中则直接返回 + if (session == nullptr) { + return Status::OK; + } + + //在内存中则直接发送通知对方 + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["fromuid"] = request->fromuid(); + rtvalue["touid"] = request->touid(); + + std::string base_key = USER_BASE_INFO + std::to_string(fromuid); + auto user_info = std::make_shared(); + bool b_info = GetBaseInfo(base_key, fromuid, user_info); + if (b_info) { + rtvalue["name"] = user_info->name; + rtvalue["nick"] = user_info->nick; + rtvalue["icon"] = user_info->icon; + rtvalue["sex"] = user_info->sex; + } + else { + rtvalue["error"] = ErrorCodes::UidInvalid; + } + + for(auto& msg : request->textmsgs()) { + Json::Value chat; + chat["sender"] = msg.sender_id(); + chat["msg_id"] = msg.msg_id(); + chat["thread_id"] = msg.thread_id(); + chat["unique_id"] = msg.unique_id(); + chat["msg_content"] = msg.msgcontent(); + rtvalue["chat_datas"].append(chat); + } + + std::string return_str = rtvalue.toStyledString(); + + session->Send(return_str, ID_NOTIFY_AUTH_FRIEND_REQ); + return Status::OK; +} +``` + +### 客户端收到好友同意回复 + +当A申请B加好友,B同意后,服务器会回复给B消息,这样B的客户端要处理同意的回包 + +``` cpp + _handlers.insert(ID_AUTH_FRIEND_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "Auth Friend Failed, err is Json Parse Err" << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Auth Friend Failed, err is " << err; + return; + } + + auto name = jsonObj["name"].toString(); + auto nick = jsonObj["nick"].toString(); + auto icon = jsonObj["icon"].toString(); + auto sex = jsonObj["sex"].toInt(); + auto uid = jsonObj["uid"].toInt(); + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto send_uid = data["sender"].toInt(); + auto msg_id = data["msg_id"].toInt(); + auto thread_id = data["thread_id"].toInt(); + auto unique_id = data["unique_id"].toInt(); + auto msg_content = data["msg_content"].toString(); + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid); + chat_datas.push_back(chat_data); + } + + auto rsp = std::make_shared(uid, name, nick, icon, sex); + rsp->SetChatDatas(chat_datas); + emit sig_auth_rsp(rsp); + + qDebug() << "Auth Friend Success " ; + }); +``` + +界面和好友状态更新 + +``` cpp +void ChatDialog::slot_auth_rsp(std::shared_ptr auth_rsp) +{ + qDebug() << "receive slot_auth_rsp uid is " << auth_rsp->_uid + << " name is " << auth_rsp->_name << " nick is " << auth_rsp->_nick; + + //判断如果已经是好友则跳过 + auto bfriend = UserMgr::GetInstance()->CheckFriendById(auth_rsp->_uid); + if (bfriend) { + return; + } + + UserMgr::GetInstance()->AddFriend(auth_rsp); + int randomValue = QRandomGenerator::global()->bounded(100); // 生成0到99之间的随机整数 + int str_i = randomValue % strs.size(); + int head_i = randomValue % heads.size(); + int name_i = randomValue % names.size(); + + auto* chat_user_wid = new ChatUserWid(); + auto chat_thread_data = std::make_shared(auth_rsp->_uid, auth_rsp->_thread_id, 0); + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data, auth_rsp->_uid); + for (auto& chat_msg : auth_rsp->_chat_datas) { + chat_thread_data->AppendMsg(chat_msg->GetMsgId(), chat_msg); + } + chat_user_wid->SetChatData(chat_thread_data); + QListWidgetItem* item = new QListWidgetItem; + //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + item->setSizeHint(chat_user_wid->sizeHint()); + ui->chat_user_list->insertItem(0, item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(auth_rsp->_thread_id, item); +} +``` + +### 客户端收到好友同意通知 + +A加B为好友,B同意后,服务器通知A,以下为A收到通知后的处理 + +``` cpp +_handlers.insert(ID_NOTIFY_AUTH_FRIEND_REQ, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "Auth Friend Failed, err is " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Auth Friend Failed, err is " << err; + return; + } + + int from_uid = jsonObj["fromuid"].toInt(); + QString name = jsonObj["name"].toString(); + QString nick = jsonObj["nick"].toString(); + QString icon = jsonObj["icon"].toString(); + int sex = jsonObj["sex"].toInt(); + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto send_uid = data["sender"].toInt(); + auto msg_id = data["msg_id"].toInt(); + auto thread_id = data["thread_id"].toInt(); + auto unique_id = data["unique_id"].toInt(); + auto msg_content = data["msg_content"].toString(); + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid); + chat_datas.push_back(chat_data); + } + + auto auth_info = std::make_shared(from_uid,name, + nick, icon, sex); + + auth_info->SetChatDatas(chat_datas); + + emit sig_add_auth_friend(auth_info); + }); +``` + +界面添加好友会话状态更新 + +``` cpp +void ChatDialog::slot_add_auth_friend(std::shared_ptr auth_info) { + qDebug() << "receive slot_add_auth__friend uid is " << auth_info->_uid + << " name is " << auth_info->_name << " nick is " << auth_info->_nick; + + //判断如果已经是好友则跳过 + auto bfriend = UserMgr::GetInstance()->CheckFriendById(auth_info->_uid); + if (bfriend) { + return; + } + + UserMgr::GetInstance()->AddFriend(auth_info); + + auto* chat_user_wid = new ChatUserWid(); + auto chat_thread_data = std::make_shared(auth_info->_uid, auth_info->_thread_id, 0); + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data, auth_info->_uid); + for (auto& chat_msg : auth_info->_chat_datas) { + chat_thread_data->AppendMsg(chat_msg->GetMsgId(), chat_msg); + } + + chat_user_wid->SetChatData(chat_thread_data); + QListWidgetItem* item = new QListWidgetItem; + //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + item->setSizeHint(chat_user_wid->sizeHint()); + ui->chat_user_list->insertItem(0, item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(auth_info->_thread_id, item); +} +``` + + + +### 效果展示 + +![image-20250622131525274](https://cdn.llfc.club/img/image-20250622131525274.png) + +## GRPC同步认证消息认证 + +分布式认证就是让两个客户端分别登录不同的服务器,注意因为我们修改了连接检测和记录的方式,改为通过心跳定时更新,为了避免两个客户端同时登录到一个服务器的情况,可以在一个客户端登录服务器后,另一个客户端延迟一分钟登录。 + +同时要注意`StatusServer`要将`getChatServer`这个函数打开 + +``` cpp +ChatServer StatusServiceImpl::getChatServer() { + std::lock_guard guard(_server_mtx); + auto minServer = _servers.begin()->second; + + auto count_str = RedisMgr::GetInstance()->HGet(LOGIN_COUNT, minServer.name); + if (count_str.empty()) { + //不存在则默认设置为最大 + minServer.con_count = INT_MAX; + } + else { + minServer.con_count = std::stoi(count_str); + } + + + // 使用范围基于for循环 + for ( auto& server : _servers) { + + if (server.second.name == minServer.name) { + continue; + } + + auto count_str = RedisMgr::GetInstance()->HGet(LOGIN_COUNT, server.second.name); + if (count_str.empty()) { + server.second.con_count = INT_MAX; + } + else { + server.second.con_count = std::stoi(count_str); + } + + if (server.second.con_count < minServer.con_count) { + minServer = server.second; + } + } + + return minServer; +} +``` + +两个客户端登录后,确保后台看到两个用户登录不同的`Server` + +1019用户登录`Server2` + +![image-20250625212522598](https://cdn.llfc.club/img/image-20250625212522598.png) + +1002用户登录`Server1` + +![image-20250625212740526](https://cdn.llfc.club/img/image-20250625212740526.png) + +这样二者都登陆成功了,然后任意一方向对方发送添加好友请求,另一方同意,看到的效果如下 + +![image-20250625212823862](https://cdn.llfc.club/img/image-20250625212823862.png) + +## 聊天记录增量加载 + +### 客户端逻辑 + +聊天记录增量加载,可以在加载完聊天会话列表后,继续分页加载聊天信息。 + +因为qt支持信号和槽函数机制,所以我们可以加载完会话列表后发送, 在`UserMgr`中设置一个当前加载的`_cur_load_chat_index`用来记录将要加载的会话消息。 + +我们对外暴露两个接口,分别是获取当前要加载会话信息,和下次加载的会话信息 + +``` cpp +std::shared_ptr UserMgr::GetCurLoadData() +{ + if (_cur_load_chat_index >= _chat_thread_ids.size()) { + return nullptr; + } + + auto iter = _chat_map.find(_chat_thread_ids[_cur_load_chat_index]); + if (iter == _chat_map.end()) { + return nullptr; + } + + return iter.value(); +} +``` + +然后封装加载消息的函数 + +``` cpp +void ChatDialog::loadChatMsg() { + + //发送聊天记录请求 + _cur_load_chat = UserMgr::GetInstance()->GetCurLoadData(); + if (_cur_load_chat == nullptr) { + return; + } + + showLoadingDlg(true); + + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); +} + +``` + +接下来我们在加载完会话列表后调用这个函数 + +``` cpp +void ChatDialog::slot_load_chat_thread(bool load_more, int last_thread_id, + std::vector> chat_threads) +{ + for (auto& cti : chat_threads) { + //先处理单聊,群聊跳过,以后添加 + if (cti->_type == "group") { + continue; + } + + auto uid = UserMgr::GetInstance()->GetUid(); + auto other_uid = 0; + if (uid == cti->_user1_id) { + other_uid = cti->_user2_id; + } + else { + other_uid = cti->_user1_id; + } + + auto chat_thread_data = std::make_shared(other_uid, cti->_thread_id, 0); + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data, other_uid); + + auto* chat_user_wid = new ChatUserWid(); + chat_user_wid->SetChatData(chat_thread_data); + QListWidgetItem* item = new QListWidgetItem; + //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + item->setSizeHint(chat_user_wid->sizeHint()); + ui->chat_user_list->addItem(item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(cti->_thread_id, item); + } + + UserMgr::GetInstance()->SetLastChatThreadId(last_thread_id); + + if (load_more) { + //发送请求逻辑 + QJsonObject jsonObj; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj["uid"] = uid; + jsonObj["thread_id"] = last_thread_id; + + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_THREAD_REQ, jsonData); + return; + } + + showLoadingDlg(false); + //继续加载聊天数据 + loadChatMsg(); +} +``` + +在收到服务器回复时处理消息 + +``` cpp +_handlers.insert(ID_LOAD_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + int thread_id = jsonObj["thread_id"].toInt(); + int last_msg_id = jsonObj["last_message_id"].toInt(); + bool load_more = jsonObj["load_more"].toBool(); + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto send_uid = data["sender"].toInt(); + auto msg_id = data["msg_id"].toInt(); + auto thread_id = data["thread_id"].toInt(); + auto unique_id = data["unique_id"].toInt(); + auto msg_content = data["msg_content"].toString(); + QString chat_time = data["chat_time"].toString(); + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid, chat_time); + chat_datas.push_back(chat_data); + } + + //发送信号通知界面 + emit sig_load_chat_msg(thread_id, last_msg_id, load_more, chat_datas); + }); +``` + +界面收到`sig_load_chat_msg`后添加消息,并且判断是否还有剩余消息加载 + +``` cpp +void ChatDialog::slot_load_chat_msg(int thread_id, int msg_id, bool load_more, std::vector> msglists) +{ + _cur_load_chat->SetLastMsgId(msg_id); + //加载聊天信息 + for (auto& chat_msg : msglists) { + _cur_load_chat->AppendMsg(chat_msg->GetMsgId(), chat_msg); + } + + //还有未加载完的消息,就继续加载 + if (load_more) { + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); + return; + } + + //获取下一个chat_thread + _cur_load_chat = UserMgr::GetInstance()->GetNextLoadData(); + //都加载完了 + if(!_cur_load_chat){ + //更新聊天界面信息 + SetSelectChatItem(); + SetSelectChatPage(); + showLoadingDlg(false); + return; + } + + //继续加载下一个聊天 + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); +} +``` + +### 服务器逻辑 + +注册消息 + +``` cpp +_fun_callbacks[ID_LOAD_CHAT_MSG_REQ] = std::bind(&LogicSystem::LoadChatMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); +``` + +具体逻辑处理 + +``` cpp +void LogicSystem::LoadChatMsg(std::shared_ptr session, + const short& msg_id, const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto thread_id = root["thread_id"].asInt(); + auto message_id = root["message_id"].asInt(); + + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["thread_id"] = thread_id; + + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_LOAD_CHAT_MSG_RSP); + }); + + int page_size = 10; + std::shared_ptr res = MysqlMgr::GetInstance()->LoadChatMsg(thread_id, message_id, page_size); + if (!res) { + rtvalue["error"] = ErrorCodes::LOAD_CHAT_FAILED; + return; + } + + rtvalue["last_message_id"] = res->next_cursor; + rtvalue["load_more"] = res->load_more; + for (auto& chat : res->messages) { + Json::Value chat_data; + chat_data["sender"] = chat.sender_id; + chat_data["msg_id"] = chat.message_id; + chat_data["thread_id"] = chat.thread_id; + chat_data["unique_id"] = 0; + chat_data["msg_content"] = chat.content; + chat_data["chat_time"] = chat.chat_time; + rtvalue["chat_datas"].append(chat_data); + } + +} + +``` + +数据库新增根据`thread_id`和`message_id`返回分页数据 + +``` cpp +std::shared_ptr MysqlMgr::LoadChatMsg(int threadId, int lastId, int pageSize) +{ + return _dao.LoadChatMsg(threadId, lastId, pageSize); +} +``` + +具体在`MysqlDao`层面实现分页加载 + +``` cpp +std::shared_ptr MysqlDao::LoadChatMsg(int thread_id, int last_message_id, int page_size) +{ + auto con = pool_->getConnection(); + if (!con) { + return nullptr; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + + try { + auto page_res = std::make_shared(); + page_res->load_more = false; + page_res->next_cursor = last_message_id; + + // SQL:多取一条,用于判断是否还有更多 + const std::string sql = R"( + SELECT message_id, thread_id, sender_id, recv_id, content, + created_at, updated_at, status + FROM chat_message + WHERE thread_id = ? + AND message_id > ? + ORDER BY message_id ASC + LIMIT ? + )"; + + uint32_t fetch_limit = page_size + 1; + auto pstmt = std::unique_ptr( + conn->prepareStatement(sql) + ); + pstmt->setInt(1, thread_id); + pstmt->setInt(2, last_message_id); + pstmt->setInt(3, fetch_limit); + + auto rs = std::unique_ptr(pstmt->executeQuery()); + + // 读取 fetch_limit 条记录 + while (rs->next()) { + ChatMessage msg; + msg.message_id = rs->getUInt64("message_id"); + msg.thread_id = rs->getUInt64("thread_id"); + msg.sender_id = rs->getUInt64("sender_id"); + msg.recv_id = rs->getUInt64("recv_id"); + msg.content = rs->getString("content"); + msg.chat_time = rs->getString("created_at"); + msg.status = rs->getInt("status"); + page_res->messages.push_back(std::move(msg)); + } + + return page_res; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return nullptr; + } + return nullptr; + +} +``` + +### 效果展示 + +![image-20250702125912799](https://cdn.llfc.club/img/image-20250702125912799.png) + + + + + +## 发送和接收消息同步 + +### 客户端缓存发送消息 + +我们需要在客户端缓存一下发送的消息,等到服务器回复后再将收到的消息放入`ChatThreadData`中。 + +为了标识消息的唯一性,我们需要在客户端生成唯一`unique_id`,构造成`ChatTextData`先放到`ChatThreadData`中存起来。 + +``` cpp + //已发送的消息,还未收到回应的。 + QMap> _msg_unrsp_map; +``` + +实现发送逻辑 + +``` cpp +void ChatPage::on_send_btn_clicked() +{ + if (_chat_data == nullptr) { + qDebug() << "friend_info is empty"; + return; + } + + auto user_info = UserMgr::GetInstance()->GetUserInfo(); + auto pTextEdit = ui->chatEdit; + ChatRole role = ChatRole::Self; + QString userName = user_info->_name; + QString userIcon = user_info->_icon; + + const QVector& msgList = pTextEdit->getMsgList(); + QJsonObject textObj; + QJsonArray textArray; + int txt_size = 0; + auto thread_id = _chat_data->GetThreadId(); + for(int i=0; i 1024){ + continue; + } + + QString type = msgList[i].msgFlag; + ChatItemBase *pChatItem = new ChatItemBase(role); + pChatItem->setUserName(userName); + pChatItem->setUserIcon(QPixmap(userIcon)); + QWidget *pBubble = nullptr; + //生成唯一id + QUuid uuid = QUuid::createUuid(); + //转为字符串 + QString uuidString = uuid.toString(); + if(type == "text") + { + pBubble = new TextBubble(role, msgList[i].content); + if(txt_size + msgList[i].content.length()> 1024){ + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + //将bubble和uid绑定,以后可以等网络返回消息后设置是否送达 + //_bubble_map[uuidString] = pBubble; + txt_size += msgList[i].content.length(); + QJsonObject obj; + QByteArray utf8Message = msgList[i].content.toUtf8(); + auto content = QString::fromUtf8(utf8Message); + obj["content"] = content; + obj["unique_id"] = uuidString; + textArray.append(obj); + //todo... 注意,此处先按私聊处理 + auto txt_msg = std::make_shared(uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, content, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString,txt_msg); + } + else if(type == "image") + { + pBubble = new PictureBubble(QPixmap(msgList[i].content) , role); + } + else if(type == "file") + { + + } + //发送消息 + if(pBubble != nullptr) + { + pChatItem->setWidget(pBubble); + pChatItem->setStatus(0); + ui->chat_data_list->appendChatItem(pChatItem); + _unrsp_item_map[uuidString] = pChatItem; + } + + } + + qDebug() << "textArray is " << textArray ; + //发送给服务器 + textObj["text_array"] = textArray; + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); +} + +``` + +相比于之前,我们在`json`中增加了`unique_id`和`thread_id`字段,服务器收到后根据`thread_id`生成消息放入到数据库,并携带`unique_id`回传给客户端。 + +客户端缓存消息放入`UserMgr`中 + +``` cpp + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString,txt_msg); +``` + +此外,客户端需要设置聊天文本状态为未回复 + +``` cpp +pChatItem->setStatus(0); +``` + + + +### 切换聊天不丢失状态 + +如果此时切换页面,再切回来,也要保证之前服务器未回复的消息能重新加载 + +切换的逻辑在 + +``` cpp +void ChatDialog::SetSelectChatPage(int thread_id) +{ + if (ui->chat_user_list->count() <= 0) { + return; + } + + if (thread_id == 0) { + auto item = ui->chat_user_list->item(0); + //转为widget + QWidget* widget = ui->chat_user_list->itemWidget(item); + if (!widget) { + return; + } + + auto con_item = qobject_cast(widget); + if (!con_item) { + return; + } + + //设置信息 + auto chat_data = con_item->GetChatData(); + ui->chat_page->SetChatData(chat_data); + return; + } + + auto find_iter = _chat_thread_items.find(thread_id); + if (find_iter == _chat_thread_items.end()) { + return; + } + + //转为widget + QWidget* widget = ui->chat_user_list->itemWidget(find_iter.value()); + if (!widget) { + return; + } + + //判断转化为自定义的widget + // 对自定义widget进行操作, 将item 转化为基类ListItemBase + ListItemBase* customItem = qobject_cast(widget); + if (!customItem) { + qDebug() << "qobject_cast(widget) is nullptr"; + return; + } + + auto itemType = customItem->GetItemType(); + if (itemType == CHAT_USER_ITEM) { + auto con_item = qobject_cast(customItem); + if (!con_item) { + return; + } + + //设置信息 + auto chat_data = con_item->GetChatData(); + ui->chat_page->SetChatData(chat_data); + + return; + } + +} +``` + +其中`SetChatData`是设置页面聊天信息列表 + +``` cpp +void ChatPage::SetChatData(std::shared_ptr chat_data) { + _chat_data = chat_data; + auto other_id = _chat_data->GetOtherId(); + if(other_id == 0) { + //说明是群聊 + ui->title_lb->setText(_chat_data->GetGroupName()); + //todo...加载群聊信息和成员信息 + return; + } + + //私聊 + auto friend_info = UserMgr::GetInstance()->GetFriendById(other_id); + if (friend_info == nullptr) { + return; + } + ui->title_lb->setText(friend_info->_name); + ui->chat_data_list->removeAllItem(); + _unrsp_item_map.clear(); + for(auto & msg : chat_data->GetMsgMapRef()){ + AppendChatMsg(msg); + } + + for (auto& msg : chat_data->GetMsgUnRspRef()) { + AppendChatMsg(msg); + } +} +``` + +这样我们可以加载服务器已经回复的和服务器未回复的。保证完全,具体添加逻辑 + +``` cpp +void ChatPage::AppendChatMsg(std::shared_ptr msg) +{ + auto self_info = UserMgr::GetInstance()->GetUserInfo(); + ChatRole role; + if (msg->GetSendUid() == self_info->_uid) { + role = ChatRole::Self; + ChatItemBase* pChatItem = new ChatItemBase(role); + + pChatItem->setUserName(self_info->_name); + pChatItem->setUserIcon(QPixmap(self_info->_icon)); + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + if (status == 0) { + _unrsp_item_map[msg->GetUniqueId()] = pChatItem; + } + } + else { + role = ChatRole::Other; + ChatItemBase* pChatItem = new ChatItemBase(role); + auto friend_info = UserMgr::GetInstance()->GetFriendById(msg->GetSendUid()); + if (friend_info == nullptr) { + return; + } + pChatItem->setUserName(friend_info->_name); + pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + if (status == 0) { + _unrsp_item_map[msg->GetUniqueId()] = pChatItem; + } + } + + +} + +``` + +其中`_unrsp_item_map`是聊天页面上的服务器未回复的聊天记录的,每次切换页面清掉,再重新创建加载。 + +这么做效率不高,后期给大家介绍Module View Delegate模式去优化聊天数据加载和管理。 + +这里先把持久化存储功能先实现再说。 + +### 客户端收到服务器回复 + +收到服务器回复后,需要组织数据发送给`ChatDialog`界面,将未回复的消息更新为已回复。 + +``` cpp + _handlers.insert(ID_TEXT_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "Chat Msg Rsp Failed, err is Json Parse Err" << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Chat Msg Rsp Failed, err is " << err; + return; + } + + qDebug() << "Receive Text Chat Rsp Success " ; + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto sender = jsonObj["fromuid"].toInt(); + + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto msg_id = data["message_id"].toInt(); + auto unique_id = data["unique_id"].toString(); + auto msg_content = data["content"].toString(); + QString chat_time = data["chat_time"].toString(); + int status = data["status"].toInt(); + auto chat_data = std::make_shared(msg_id,unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, sender, status, chat_time); + chat_datas.push_back(chat_data); + } + + //发送信号通知界面 + emit sig_chat_msg_rsp(thread_id, chat_datas); + + }); +``` + +将信号和槽函数连接 + +``` cpp +connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_chat_msg_rsp, this, &ChatDialog::slot_add_chat_msg); +``` + +会触发槽函数, 槽函数内部检测消息,将消息存储到已经回复列表中。 + +``` cpp +void ChatDialog::slot_add_chat_msg(int thread_id, std::vector> msglists) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(thread_id); + if (chat_data == nullptr) { + return; + } + + //将消息放入数据中管理 + for (auto& msg : msglists) { + chat_data->MoveMsg(msg); + + if (_cur_chat_thread_id != thread_id) { + continue; + } + //更新聊天界面信息 + ui->chat_page->UpdateChatStatus(msg->GetUniqueId(),msg->GetStatus()); + } + +} +``` + +转移逻辑, 其实就是去未回复中查找对应消息,如果有就移动到已回复列表,如果没有就直接将回复的消息插入已回复列表中 + +``` cpp +void ChatThreadData::MoveMsg(std::shared_ptr msg) { + auto iter = _msg_unrsp_map.find(msg->GetUniqueId()); + if (iter == _msg_unrsp_map.end()) { + AddMsg(msg); + return; + } + + iter.value()->SetStatus(2); + AddMsg(iter.value()); + _msg_unrsp_map.erase(iter); +} + +void ChatThreadData::AddMsg(std::shared_ptr msg) +{ + _msg_map.insert(msg->GetMsgId(), msg); + _last_msg = msg->GetMsgContent(); + _last_msg_id = msg->GetMsgId(); +} + +``` + + + +### 对端收到消息通知 + +客户端对端收到通知消息 + +``` cpp + _handlers.insert(ID_NOTIFY_TEXT_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "Notify Chat Msg Failed, err is Json Parse Err" << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Notify Chat Msg Failed, err is " << err; + return; + } + + qDebug() << "Receive Text Chat Notify Success " ; + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto sender = jsonObj["fromuid"].toInt(); + + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto msg_id = data["message_id"].toInt(); + auto unique_id = data["unique_id"].toString(); + auto msg_content = data["content"].toString(); + QString chat_time = data["chat_time"].toString(); + int status = data["status"].toInt(); + auto chat_data = std::make_shared(msg_id, unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, sender, status, chat_time); + chat_datas.push_back(chat_data); + } + + + emit sig_text_chat_msg(chat_datas); + }); +``` + +这个消息连接槽函数 + +``` cpp + //连接对端消息通知 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_text_chat_msg, + this, &ChatDialog::slot_text_chat_msg); +``` + +因为被通知,可能此时不在对应的会话中 + +``` cpp +void ChatDialog::slot_text_chat_msg(std::vector> msglists) +{ + for (auto& msg : msglists) { + + //更新数据 + auto thread_id = msg->GetThreadId(); + auto thread_data = UserMgr::GetInstance()->GetChatThreadByThreadId(thread_id); + + thread_data->AddMsg(msg); + + if (_cur_chat_thread_id != thread_id) { + continue; + } + + ui->chat_page->AppendChatMsg(msg); + } + +} +``` + +### 服务器逻辑 + +服务器在收到聊天消息后要将消息入库,并且判断对方是否通服,如果不是一个服务器,则用`grpc`通知对方所在的服务器,再通过对方服务器的`Session`通知对方。 + +如果是同一个服务器,则直接通过`Session`通知对方 + +``` cpp +void LogicSystem::DealChatTextMsg(std::shared_ptr session, const short& msg_id, const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto uid = root["fromuid"].asInt(); + auto touid = root["touid"].asInt(); + + const Json::Value arrays = root["text_array"]; + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + + rtvalue["fromuid"] = uid; + rtvalue["touid"] = touid; + auto thread_id = root["thread_id"].asInt(); + rtvalue["thread_id"] = thread_id; + std::vector> chat_datas; + auto timestamp = getCurrentTimestamp(); + for (const auto& txt_obj : arrays) { + auto content = txt_obj["content"].asString(); + auto unique_id = txt_obj["unique_id"].asString(); + std::cout << "content is " << content << std::endl; + std::cout << "unique_id is " << unique_id << std::endl; + auto chat_msg = std::make_shared(); + chat_msg->chat_time = timestamp; + chat_msg->sender_id = uid; + chat_msg->recv_id = touid; + chat_msg->unique_id = unique_id; + chat_msg->thread_id = thread_id; + chat_msg->content = content; + chat_msg->status = 2; + chat_datas.push_back(chat_msg); + } + + + //插入数据库 + MysqlMgr::GetInstance()->AddChatMsg(chat_datas); + + + for (const auto& chat_data : chat_datas) { + Json::Value chat_msg; + chat_msg["message_id"] = chat_data->message_id; + chat_msg["unique_id"] = chat_data->unique_id; + chat_msg["content"] = chat_data->content; + chat_msg["status"] = chat_data->status; + chat_msg["chat_time"] = chat_data->chat_time; + rtvalue["chat_datas"].append(chat_msg); + } + + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_TEXT_CHAT_MSG_RSP); + }); + + + //查询redis 查找touid对应的server ip + auto to_str = std::to_string(touid); + auto to_ip_key = USERIPPREFIX + to_str; + std::string to_ip_value = ""; + bool b_ip = RedisMgr::GetInstance()->Get(to_ip_key, to_ip_value); + if (!b_ip) { + return; + } + + auto& cfg = ConfigMgr::Inst(); + auto self_name = cfg["SelfServer"]["Name"]; + //直接通知对方有认证通过消息 + if (to_ip_value == self_name) { + auto session = UserMgr::GetInstance()->GetSession(touid); + if (session) { + //在内存中则直接发送通知对方 + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_NOTIFY_TEXT_CHAT_MSG_REQ); + } + + return ; + } + + + TextChatMsgReq text_msg_req; + text_msg_req.set_fromuid(uid); + text_msg_req.set_touid(touid); + text_msg_req.set_thread_id(thread_id); + for (const auto& chat_data : chat_datas) { + auto *text_msg = text_msg_req.add_textmsgs(); + text_msg->set_unique_id(chat_data->unique_id); + text_msg->set_msgcontent(chat_data->content); + text_msg->set_msg_id(chat_data->message_id); + text_msg->set_chat_time(chat_data->chat_time); + } + + + //发送通知 todo... + ChatGrpcClient::GetInstance()->NotifyTextChatMsg(to_ip_value, text_msg_req, rtvalue); +} + +``` + + + +### 数据库处理 + +``` cpp +bool MysqlMgr::AddChatMsg(std::vector>& chat_datas) { + return _dao.AddChatMsg(chat_datas); +} +``` + +`Dao`层做了详细的数据库操作 + +``` cpp +bool MysqlDao::AddChatMsg(std::vector>& chat_datas) { + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + auto& conn = con->_con; + + + try { + //关闭自动提交,以手动管理事务 + conn->setAutoCommit(false); + auto pstmt = std::unique_ptr( + conn->prepareStatement( + "INSERT INTO chat_message " + "(thread_id, sender_id, recv_id, content, created_at, updated_at, status) " + "VALUES (?, ?, ?, ?, ?, ?, ?)" + ) + ); + + for (auto& msg : chat_datas) { + // 普通字段 + pstmt->setUInt64(1, msg->thread_id); + pstmt->setUInt64(2, msg->sender_id); + pstmt->setUInt64(3, msg->recv_id); + pstmt->setString(4, msg->content); + + pstmt->setString(5, msg->chat_time); // created_at + pstmt->setString(6, msg->chat_time); // updated_at + + pstmt->setInt(7, msg->status); + pstmt->executeUpdate(); + + // 2. 取 LAST_INSERT_ID() + std::unique_ptr keyStmt( + conn->createStatement() + ); + std::unique_ptr rs( + keyStmt->executeQuery("SELECT LAST_INSERT_ID()") + ); + if (rs->next()) { + msg->message_id = rs->getUInt64(1); + } + else { + continue; + } + } + + conn->commit(); + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException: " << e.what() << std::endl; + conn->rollback(); + return false; + } + return true; + +} + +``` + +### grpc协议完善 + +``` protobuf +message TextChatMsgReq { + int32 fromuid = 1; + int32 touid = 2; + int32 thread_id = 3; + repeated TextChatData textmsgs = 4; +} + +message TextChatData{ + string unique_id = 1; + int32 msg_id = 2; + string msgcontent = 3; + string chat_time = 4; +} + +message TextChatMsgRsp { + int32 error = 1; + int32 fromuid = 2; + int32 touid = 3; + int32 thread_id = 4; + repeated TextChatData textmsgs = 5; +} +``` + +### 对端服务器处理 + +如果客户不在本服,则通知对端服务处理 + +``` cpp +Status ChatServiceImpl::NotifyTextChatMsg(::grpc::ServerContext* context, + const TextChatMsgReq* request, TextChatMsgRsp* reply) { + //查找用户是否在本服务器 + auto touid = request->touid(); + auto session = UserMgr::GetInstance()->GetSession(touid); + reply->set_error(ErrorCodes::Success); + + //用户不在内存中则直接返回 + if (session == nullptr) { + return Status::OK; + } + + //在内存中则直接发送通知对方 + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["fromuid"] = request->fromuid(); + rtvalue["touid"] = request->touid(); + rtvalue["thread_id"] = request->thread_id(); + //将聊天数据组织为数组 + Json::Value text_array; + for (auto& msg : request->textmsgs()) { + Json::Value element; + element["content"] = msg.msgcontent(); + element["unique_id"] = msg.unique_id(); + element["message_id"] = msg.msg_id(); + element["chat_time"] = msg.chat_time(); + text_array.append(element); + } + rtvalue["chat_datas"] = text_array; + + std::string return_str = rtvalue.toStyledString(); + + session->Send(return_str, ID_NOTIFY_TEXT_CHAT_MSG_REQ); + return Status::OK; +} +``` + +### 验证效果 + + + +![image-20250725233631386](https://cdn.llfc.club/img/image-20250725233631386.png) + +### 待完善部分 + +目前切换页面会将之前的记录删掉,这样每次重新加载会影响效率。 + +考虑以后采用多页缓存机制。 + +以后用Model View Delegate改造数据存储模式。 + +**使用 Model/View 架构(QListView + QAbstractListModel + Delegate)** + +- **思路**:不要手动往布局里插 widget,而是把 “一条聊天消息” 抽象成一个数据结构,存到自定义的 `QAbstractListModel`。 +- 在右侧放一个 `QListView`,并为它写一个 `QStyledItemDelegate`,统一负责绘制消息气泡、头像、时间等。 +- **优点**:Qt 的视图会自动做 **行缓存**(view recycling)、**懒加载** 等优化,数据量大也能保持流畅。 +- **切换用户**:只需 `model->setMessages(userMessages)`(内部发 `beginResetModel()`/`endResetModel()`),视图自动刷新。 + + + +**方案一:在同一个 Model 里 reset 数据** + +1. **维护一个消息列表** + + ```cpp + class ChatModel : public QAbstractListModel { + QVector m_msgs; + public: + // 必要的 override:rowCount(), data(), roleNames()... + + void setMessages(const QVector& msgs) { + beginResetModel(); + m_msgs = msgs; + endResetModel(); + } + }; + ``` + +2. **切换用户时** + + ```cpp + // 假设你有一个 ChatModel* model 和 QListView* listView + // listView->setModel(model); // 已经在初始化时做过一次 + void onUserClicked(const User& u) { + QVector msgs = loadMessagesFromDb(u.id); + model->setMessages(msgs); + // 可选:滚到最底部 + listView->scrollToBottom(); + } + ``` + +3. **优点** + + - 结构简单,一处 model,view 自动刷新。 + - 不需要销毁或创建 widget,性能最佳。 + +------ + +**方案二:每个用户一个 Model,切换指针** + +如果你希望把每个用户的数据和 model 分开管理,也可以为每个用户维护独立的 `ChatModel`: + +```cpp +QMap modelPool; + +void onUserClicked(const User& u) { + if (!modelPool.contains(u.id)) { + // 第一次点击,创建并加载 + ChatModel* m = new ChatModel(this); + m->setMessages(loadMessagesFromDb(u.id)); + modelPool[u.id] = m; + } + listView->setModel(modelPool[u.id]); + listView->scrollToBottom(); +} +``` + +- **优点**:切换立刻就有缓存好的数据,不用每次都从数据库/网络加载。 +- **缺点**:如果用户特别多,内存开销会比较大。 + +------ + +**更细粒度的更新** + +如果你不想一次 `beginResetModel()`/`endResetModel()` 重刷全表,还可以在 model 里实现增删改接口: + +```cpp +void ChatModel::appendMessage(const Message& m) { + beginInsertRows(QModelIndex(), m_msgs.size(), m_msgs.size()); + m_msgs.append(m); + endInsertRows(); +} +void ChatModel::clearMessages() { + beginRemoveRows(QModelIndex(), 0, m_msgs.size()-1); + m_msgs.clear(); + endRemoveRows(); +} +``` + +- 切换用户时先 `clearMessages()`,然后循环 `appendMessage()`。 +- 这样 view 能做更细粒度的动画或局部刷新。 + +------ + +**总结** + +- **最简单**:一个 model,内部维护 `QVector`,切换时调用 `setMessages()`。 +- **缓存多用户**:给每个用户分配一个 model,切换时调用 `listView->setModel(...)`。 +- **增量更新**:用 `beginInsertRows`/`beginRemoveRows` 实现局部刷新。 + +选哪种方案,取决于你的聊天数据量和内存/加载开销: + +- 少量用户、消息量大 → 方案一(reset)+ 分页加载 +- 用户量多、切换频繁 → 方案二(model 池) +- 想要炫酷的动画或更精细性能 → 增量更新。 diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day38-\346\226\255\347\202\271\347\273\255\344\274\240.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day38-\346\226\255\347\202\271\347\273\255\344\274\240.md" new file mode 100644 index 0000000..fd1d01f --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day38-\346\226\255\347\202\271\347\273\255\344\274\240.md" @@ -0,0 +1,3130 @@ +--- +title: 断点续传 +date: 2025-07-29 10:15:50 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 独立网络线程 + + + +### 独立前 + +![image-20250803111220495](https://cdn.llfc.club/img/image-20250803111220495.png) + +### 独立后 + + + + + +![image-20250803111620510](https://cdn.llfc.club/img/image-20250803111620510.png) + +### 槽函数连接方式 + +![image-20250803114247485](https://cdn.llfc.club/img/image-20250803114247485.png) + + + + + +1. 直接连接 + + `connect(发送者, 信号, [](信号参数){})`; + +​ 这种槽函数在发送者所在线程触发。 + +2. 增加接收者 + + `connect(发送者,信号,接收者,槽函数)` + + 如果发送者和接收者在同一个线程,则槽函数调用的线程就是发送者所在的线程。 + +3. 发送者和接收者不在一个线程,connect默认采用队列连接方式 + +​ `connect(发送者,信号,接收者,槽函数)` + +​ 槽函数在接收者所在的线程触发。好处就是解耦合。 + + + +### 元对象系统 + +1. 信号和槽 +2. 反射 +3. 动态增加函数和属性 + +当我们信号和槽连接方式采用队列连接,那么信号的参数会被封装为元对象,投递到队列中。 + +要想支持元对象有两种方式 + +1. 继承于QObject,并且类内填写Q_OBJECT宏 +2. 声明并且注册元对象类 + + + +为了支持高并发情况下断点续传,考虑将目前项目中`TcpMgr`中网络模块独立到独立线程 + +**封装`TcpThread`类** + +利用`RAII`思想封装线程启动和回收 + +``` cpp +class TcpThread:public std::enable_shared_from_this { +public: + TcpThread(); + ~TcpThread(); +private: + QThread* _tcp_thread; +}; +``` + +具体实现 + +``` cpp +TcpThread::TcpThread() +{ + _tcp_thread = new QThread(); + TcpMgr::GetInstance()->moveToThread(_tcp_thread); + QObject::connect(_tcp_thread, &QThread::finished, _tcp_thread, &QObject::deleteLater); + + _tcp_thread->start(); +} + +TcpThread::~TcpThread() +{ + _tcp_thread->quit(); +} + +``` + +主函数启动时记得提前启动线程,将`TcpMgr`转移到独立线程中 + +``` cpp + //启动tcp线程 + TcpThread tcpthread; + MainWindow w; + w.show(); + return a.exec(); +``` + + + +测试发现,登录卡住,检测是信号`sig_connect_tcp`发送了,槽函数`slot_tcp_connect`没触发。 + +``` cpp + //连接tcp连接请求的信号和槽函数 + connect(this, &LoginDialog::sig_connect_tcp, TcpMgr::GetInstance().get(), &TcpMgr::slot_tcp_connect); +``` + + + +为了测试 + +先在`TcpMgr`中添加测试槽函数 + +``` cpp + void slot_test() { + qDebug() << "receve thread is " << QThread::currentThread(); + qDebug() << "slot test......"; + } +``` + +在`LoginDialog`中连接信号 + +``` cpp +connect(this, &LoginDialog::sig_test, TcpMgr::GetInstance().get(), &TcpMgr::slot_test); +``` + +在发送`sig_connect_tcp`处发送`sig_test` + +``` cpp +void LoginDialog::initHttpHandlers() +{ + //注册获取登录回包逻辑 + _handlers.insert(ReqId::ID_LOGIN_USER, [this](QJsonObject jsonObj){ + int error = jsonObj["error"].toInt(); + if(error != ErrorCodes::SUCCESS){ + showTip(tr("参数错误"),false); + enableBtn(true); + return; + } + auto email = jsonObj["email"].toString(); + + //发送信号通知tcpMgr发送长链接 + ServerInfo si; + si.Uid = jsonObj["uid"].toInt(); + si.Host = jsonObj["host"].toString(); + si.Port = jsonObj["port"].toString(); + si.Token = jsonObj["token"].toString(); + + _uid = si.Uid; + _token = si.Token; + qDebug()<< "email is " << email << " uid is " << si.Uid <<" host is " + << si.Host << " Port is " << si.Port << " Token is " << si.Token; + emit sig_connect_tcp(si); + emit sig_test(); + }); +} +``` + +测试,是可以看到能触发slot_test函数得,而且线程id显示是子线程中触发得槽函数。 + +那么`sig_connect_tcp`信号发出,没有触发槽函数,就是因为信号得参数类型不支持元对象系统。 + +为了支持元对象系统,我们需要在信号的参数`ServerInfo`类实现默认构造,同时声明为元对象类型 + +``` cpp +struct ServerInfo{ +public: + ServerInfo() = default; + ServerInfo(const ServerInfo& other):Host(other.Host),Port(other.Port),Token(other.Token),Uid(other.Uid){} + QString Host; + QString Port; + QString Token; + int Uid; +}; + +Q_DECLARE_METATYPE(ServerInfo) +``` + +在`TcpMgr`中注册这个元对象类型 + +``` cpp +qRegisterMetaType("ServerInfo"); +``` + +再次测试就通过登录了,但是在发送后续得消息时,又遇到了自定义类型作为参数得情况,我们需要和上面一样,依次声明元对象类型并且注册。 + +如下列举一个,还有很多,不再详细列举 + +``` cpp +class SearchInfo { +public: + SearchInfo(int uid, QString name, QString nick, QString desc, int sex, QString icon); + SearchInfo() = default; + int _uid; + QString _name; + QString _nick; + QString _desc; + int _sex; + QString _icon; +}; + +Q_DECLARE_METATYPE(SearchInfo) +Q_DECLARE_METATYPE(std::shared_ptr) + +``` + +`TcpMgr`封装注册元对象函数 + +``` cpp +void TcpMgr::registerMetaType() { + // 注册所有自定义类型 + qRegisterMetaType("ServerInfo"); + qRegisterMetaType("SearchInfo"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AddFriendApply"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("ApplyInfo"); + + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AuthRsp"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("UserInfo"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("ReqId"); +} +``` + +在构造函数中调用 + +``` cpp +TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_message_len(0) +{ + registerMetaType(); + //... +} +``` + +再次测试就通过了 + +这里给大家讲讲为什么单线程情况下,信号可以携带自定义类型作为参数,不用设定元对象就可以传输,而跨线程不可以。 + +在 Qt 的信号/槽机制中,信号参数的传递方式取决于连接(`connect`)的类型,而连接类型又由发信号对象和接收槽对象所在的线程决定: + +1. **同线程(Direct Connection)** + + - 如果信号和槽都在同一个线程里,默认使用 **Direct Connection**。 + - Direct Connection 本质上就是一个普通的 C++ 函数调用,参数直接按值或按引用传递,编译时就已经知道了类型,不需要任何额外的元类型信息。 + - 因此,即使你没有把 `SearchInfo` 注册为 `QMetaType`,编译器也能直接生成函数调用代码,信号里就可以直接传递 `SearchInfo`。 + +2. **跨线程(Queued Connection)** + + - 如果信号发送者和接收者不在同一个线程,Qt 会自动把连接转成 **Queued Connection**。 + + - Queued Connection 的实现是:当信号发出时,Qt 会把信号参数打包成一个事件(`QEvent`),然后把事件放到目标线程的事件队列里;目标线程的事件循环(`QCoreApplication::processEvents()`)再把这个事件取出来,调用槽函数。 + + - 这里的“打包”与“解包”就需要运行时才能确定参数类型,以及如何拷贝或序列化这个类型——这正是 Qt 元对象系统(`QMetaType`)要干的事情。 + + - 如果没有把 `SearchInfo` 声明成一个元类型,Qt 就不知道如何在内部把它从一个线程“打包”到事件里,又如何在另一线程里还原。 + + - 因此,**跨线程传递自定义类型**,必须在类型定义后加上: + + ```cpp + Q_DECLARE_METATYPE(SearchInfo) + ``` + + 并在运行时注册(通常在 `main()` 里调用一次): + + ```cpp + qRegisterMetaType("SearchInfo"); + ``` + +------ + +**小结** + +- **同线程**:Direct Connection,编译时直接调用,**不需要** `Q_DECLARE_METATYPE`。 +- **跨线程**:Queued Connection,需要运行时打包/解包参数,**必须**用 `Q_DECLARE_METATYPE`(以及 `qRegisterMetaType`)来注册你的自定义类型。 + + + +### 添加发送队列 + + + +### `UserMgr`线程安全 + +为了保证多线程情况下访问数据的安全性,对`UserMgr`类的操作加锁 + +``` cpp + std::mutex _mtx; +``` + +在获取数据和设置数据的地方都进行加锁, 比如 + +``` cpp +std::shared_ptr UserMgr::GetUserInfo() +{ + std::lock_guard lock(_mtx); + return _user_info; +} +``` + +还有很多不再赘述 + + + +## 设置发送队列 + +默认情况下`qt`的`socket`都是非阻塞的。 + +所以调用`socket.write(数据)`可能会直接返回`-1` + +返回`-1`表示网络出错,一般都是`EWOULD_BLOCK/EAGAIN`造成的。表示发送缓冲区已经满了,无法继续发送。 + +而我们之前的逻辑,无论在哪个线程,想要发送数据,统一发送信号 + +``` cpp + void sig_send_data(ReqId reqId, QByteArray data); +``` + +会触发`TcpMgr`的槽函数 + +``` cpp +void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes) +{ + uint16_t id = reqId; + + // 计算长度(使用网络字节序转换) + quint16 len = static_cast(dataBytes.length()); + + // 创建一个QByteArray用于存储要发送的所有数据 + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + + // 设置数据流使用网络字节序 + out.setByteOrder(QDataStream::BigEndian); + + // 写入ID和长度 + out << id << len; + + // 添加字符串数据 + block.append(dataBytes); + + + qint64 written = _socket.write(block); + qDebug() << "tcp mgr send byte data is" << _current_block + << ", write() returned" << written; +} +``` + +上述函数在网络情况良好的时候不会产生问题,但是如果网络发送情况频繁的时候,就容易出现written为-1的情况。 + +也就是发送缓冲区满了,导致发送失败。 + +对于这种情况,我们可以模仿我们的服务器写法,添加一个发送队列,然后将要发送的数据投递到发送队列 + +``` cpp + //发送队列 + QQueue _send_queue; + //正在发送的包 + QByteArray _current_block; + //当前已发送的字节数 + qint64 _bytes_sent; + //是否正在发送 + bool _pending; +``` + +修改发送逻辑 + +``` cpp +void TcpMgr::slot_send_data(ReqId reqId, QByteArray dataBytes) +{ + uint16_t id = reqId; + + // 计算长度(使用网络字节序转换) + quint16 len = static_cast(dataBytes.length()); + + // 创建一个QByteArray用于存储要发送的所有数据 + QByteArray block; + QDataStream out(&block, QIODevice::WriteOnly); + + // 设置数据流使用网络字节序 + out.setByteOrder(QDataStream::BigEndian); + + // 写入ID和长度 + out << id << len; + + // 添加字符串数据 + block.append(dataBytes); + + //判断是否正在发送 + if (_pending) { + //放入队列直接返回,因为目前有数据正在发送 + _send_queue.enqueue(block); + return; + } + + // 没有正在发送,把这包设为“当前块”,重置计数,并写出去 + _current_block = block; // ← 保存当前正在发送的 block + _bytes_sent = 0; // ← 归零 + _pending = true; // ← 标记正在发送 + + qint64 written = _socket.write(_current_block); + qDebug() << "tcp mgr send byte data is" << _current_block + << ", write() returned" << written; +} +``` + +我们需要监听发送返回的数据,`QT`也提供了类似于`asio`的异步回调功能,只是在发送完成后返回一个信号`void bytesWritten(qint64 bytes);` + +我们连接这个信号 + +``` cpp + QObject::connect(&_socket, &QTcpSocket::bytesWritten, this, [this](qint64 bytes) { + //更新发送数据 + _bytes_sent += bytes; + //未发送完整 + if (_bytes_sent < _current_block.size()) { + //继续发送 + auto data_to_send = _current_block.mid(_bytes_sent); + _socket.write(data_to_send); + return; + } + + //发送完全,则查看队列是否为空 + if (_send_queue.isEmpty()) { + //队列为空,说明已经将所有数据发送完成,将pending设置为false,这样后续要发送数据时可以继续发送 + _current_block.clear(); + _pending = false; + _bytes_sent = 0; + return; + } + + //队列不为空,则取出队首元素 + _current_block = _send_queue.dequeue(); + _bytes_sent = 0; + _pending = true; + qint64 w2 = _socket.write(_current_block); + qDebug() << "[TcpMgr] Dequeued and write() returned" << w2; + }); +``` + +`_pending`控制发送还是放入队列。 + + + +## 断点续传思路 + +### 思路图 + + + +![image-20250810113255940](https://cdn.llfc.club/img/image-20250810113255940.png) + + + +### 修改上传逻辑 + +原来的传输逻辑,采用的是循环上传,就是将一个文件拆分成多个报文段,循环上传,而不等待服务器每次回复 + +``` cpp +void MainWindow::on_uploadBtn_clicked() +{ + ui->uploadBtn->setEnabled(false); + // 打开文件 + QFile file(_file_name); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + // 保存当前文件指针位置 + qint64 originalPos = file.pos(); + QCryptographicHash hash(QCryptographicHash::Md5); + if (!hash.addData(&file)) { + qWarning() << "Failed to read data from file:" << _file_name; + return ; + } + + _file_md5 = hash.result().toHex(); // 返回十六进制字符串 + + // 读取文件内容并发送 + QByteArray buffer; + int seq = 0; + + QFileInfo fileInfo(_file_name); // 创建 QFileInfo 对象 + + QString fileName = fileInfo.fileName(); // 获取文件名 + qDebug() << "文件名是:" << fileName; // 输出文件名 + int total_size = fileInfo.size(); + int last_seq = 0; + if(total_size % MAX_FILE_LEN){ + last_seq = (total_size/MAX_FILE_LEN)+1; + }else{ + last_seq = total_size/MAX_FILE_LEN; + } + + // 恢复文件指针到原来的位置 + file.seek(originalPos); + + while (!file.atEnd()) { + //每次读取2048字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject jsonObj; + // 将文件内容转换为 Base64 编码(可选) + QString base64Data = buffer.toBase64(); + //qDebug() << "send data is " << base64Data; + ++seq; + jsonObj["md5"] = _file_md5; + jsonObj["name"] = fileName; + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq-1)*MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + + if(buffer.size() + (seq-1)*MAX_FILE_LEN == total_size){ + jsonObj["last"] = 1; + }else{ + jsonObj["last"] = 0; + } + + jsonObj["data"]= base64Data; + jsonObj["last_seq"] = last_seq; + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + TcpClient::Inst().sendMsg(ID_UPLOAD_FILE_REQ, send_data); + //startDelay(500); + } + + //关闭文件 + file.close(); + +} +``` + +现在需要改为分段上传,每次上传后,等待服务器返回响应后再上传下一个 + +``` cpp +void MainWindow::on_uploadBtn_clicked() +{ + ui->uploadBtn->setEnabled(false); + ui->pauseBtn->setEnabled(true); + // 打开文件 + QFile file(_file_name); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + // 保存当前文件指针位置 + qint64 originalPos = file.pos(); + QCryptographicHash hash(QCryptographicHash::Md5); + if (!hash.addData(&file)) { + qWarning() << "Failed to read data from file:" << _file_name; + return ; + } + + _file_md5 = hash.result().toHex(); // 返回十六进制字符串 + + // 读取文件内容并发送 + QByteArray buffer; + int seq = 0; + + // 创建 QFileInfo 对象 + auto fileInfo = std::make_shared(_file_name); + + QString fileName = fileInfo->fileName(); // 获取文件名 + qDebug() << "文件名是:" << fileName; // 输出文件名 + int total_size = fileInfo->size(); + int last_seq = 0; + if(total_size % MAX_FILE_LEN){ + last_seq = (total_size/MAX_FILE_LEN)+1; + }else{ + last_seq = total_size/MAX_FILE_LEN; + } + + // 恢复文件指针到原来的位置 + file.seek(originalPos); + + //改为读取第一块并发送 + //每次读取2048字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject jsonObj; + // 将文件内容转换为 Base64 编码(可选) + QString base64Data = buffer.toBase64(); + //qDebug() << "send data is " << base64Data; + ++seq; + jsonObj["md5"] = _file_md5; + jsonObj["name"] = fileName; + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq-1)*MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + + if(buffer.size() + (seq-1)*MAX_FILE_LEN == total_size){ + jsonObj["last"] = 1; + }else{ + jsonObj["last"] = 0; + } + + jsonObj["data"]= base64Data; + jsonObj["last_seq"] = last_seq; + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + TcpClient::Inst().sendMsg(ID_UPLOAD_FILE_REQ, send_data); + LogicMgr::Inst()->AddMD5File(_file_md5, fileInfo); + //关闭文件 + file.close(); + +} +``` + +### 收到响应后续传 + +当客户端收到服务器的回包后,解析后传递给`LogicMgr`, `LogicMgr`中需要将后续的报文段发送给服务器。我们封装如下逻辑 + +``` cpp +void LogicWorker::InitHandlers() +{ + //注册上传消息 + _handlers[ID_UPLOAD_FILE_RSP] = [this](QJsonObject obj){ + auto err = obj["error"].toInt(); + if(err != RSP_SUCCESS){ + qDebug() << "upload msg rsp err is " << err; + return; + } + + auto name = obj["name"].toString(); + auto total_size = obj["total_size"].toInt(); + auto trans_size = obj["trans_size"].toInt(); + auto md5 = obj["md5"].toString(); + auto seq = obj["seq"].toInt(); + + qDebug() << "recv : " << name << " file trans_size is " << trans_size; + emit sig_trans_size(trans_size); + + //判断trans_size是否和total_size相等 + if(total_size == trans_size){ + return; + } + + auto file_info = LogicMgr::Inst()->GetFileInfo(md5); + if(!file_info){ + return; + } + //再次组织数据发送 + QFile file(file_info->filePath()); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(trans_size); + + if(LogicMgr::Inst()->Pause()){ + return ; + } + QByteArray buffer; + seq++; + //每次读取2048字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject jsonObj; + // 将文件内容转换为 Base64 编码(可选) + QString base64Data = buffer.toBase64(); + + jsonObj["md5"] = md5; + jsonObj["name"] = file_info->fileName(); + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq-1)*MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + + if(buffer.size() + (seq-1)*MAX_FILE_LEN == total_size){ + jsonObj["last"] = 1; + }else{ + jsonObj["last"] = 0; + } + + jsonObj["data"]= base64Data; + jsonObj["last_seq"] = obj["last_seq"].toInt(); + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + TcpClient::Inst().sendMsg(ID_UPLOAD_FILE_REQ, send_data); + + file.close(); + }; + +} +``` + +其中`sig_trans_size`为信号,通知主界面显示进度 + +### 暂停和续传 + +客户端需增加暂停和续传按钮,支持传说过程中暂停,点击后再继续上传等功能 + +``` cpp +void MainWindow::slot_pause_continue() +{ + //续传状态或者初始状态,按下暂停按钮 + if(_cur_state == INIT || _cur_state == CONTINUE){ + //设置当前状态为暂停状态 + _b_pause = true; + ui->pauseBtn->setText("继续"); + _cur_state = PAUSE; + LogicMgr::Inst()->SetPause(true); + return; + } + + //判断当前为暂停状态,则点击后开启续传 + if(_cur_state == PAUSE){ + _b_pause = false; + ui->pauseBtn->setText("暂停"); + _cur_state = CONTINUE ; + LogicMgr::Inst()->SetPause(false); + //发送请求获取文件信息,继续上传 + auto file_info = LogicMgr::Inst()->GetFileInfo(_file_md5); + + QJsonObject jsonObj; + + jsonObj["md5"] = _file_md5; + + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + TcpClient::Inst().sendMsg(ID_SYNC_FILE_REQ, send_data); + + return; + } +} + +``` + +这里继续上传需要请求一下服务器,同步之前的上传进度。 + +我们添加了新的协议`ID_SYNC_FILE_REQ`, 服务器收到后将状态和进度返回,客户端响应 + +``` cpp + _handlers[ID_SYNC_FILE_RSP] = [this](QJsonObject obj){ + auto err = obj["error"].toInt(); + if(err != RSP_SUCCESS){ + qDebug() << " msg rsp err is " << err; + return; + } + + auto md5 = obj["md5"].toString(); + auto seq = obj["seq"].toInt(); + auto total_size = obj["total_size"].toInt(); + + auto file_info = LogicMgr::Inst()->GetFileInfo(md5); + if(!file_info){ + qDebug() << "not found file" ; + return; + } + + //再次组织数据发送 + QFile file(file_info->filePath()); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + auto trans_size = obj["trans_size"].toInt(); + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(trans_size); + + if(LogicMgr::Inst()->Pause()){ + return ; + } + QByteArray buffer; + seq++; + //每次读取2048字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject jsonObj; + // 将文件内容转换为 Base64 编码(可选) + QString base64Data = buffer.toBase64(); + + jsonObj["md5"] = md5; + jsonObj["name"] = file_info->fileName(); + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq-1)*MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + + if(buffer.size() + (seq-1)*MAX_FILE_LEN == total_size){ + jsonObj["last"] = 1; + }else{ + jsonObj["last"] = 0; + } + + jsonObj["data"]= base64Data; + jsonObj["last_seq"] = obj["last_seq"].toInt(); + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + TcpClient::Inst().sendMsg(ID_UPLOAD_FILE_REQ, send_data); + + file.close(); + }; +``` + +客户端根据返回的进度,按照偏移量读取指定文件,并且继续上报。 + +如果健壮一点,可以判断服务器返回的错误信息,根据错误,提示主界面做出交互显示等。这里不再赘述。 + +到此客户端设计完成。 + +### 单线程服务器改造 + +单线程服务器改造不大,只需要增加同步文件进度信息的处理逻辑,以及优化之前的上传处理逻辑即可 + +``` cpp + _fun_callbacks[ID_UPLOAD_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto data = root["data"].asString(); + //std::cout << "recv file data is " << data << std::endl; + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_FILE_RSP); + }); + + // 解码 + std::string decoded = base64_decode(data); + + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / name).string(); + std::cout << "file_path_str is " << file_path_str << std::endl; + + if (seq != 1) { + auto iter = _map_md5_files.find(md5); + if (iter == _map_md5_files.end()) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + std::lock_guard lock(_file_mtx); + _map_md5_files[md5] = file_info; + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + std::lock_guard lock(_file_mtx); + auto file_info = _map_md5_files[md5]; + file_info->_seq = seq; + file_info->_trans_size = trans_size; + } + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + return ; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + return ; + } + + outfile.close(); + std::cout << "文件已成功保存为: " << name << std::endl; + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["md5"] = md5; + }; + + + _fun_callbacks[ID_SYNC_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_SYNC_FILE_RSP); + }); + + auto md5 = root["md5"].asString(); + + auto iter = _map_md5_files.find(md5); + if (iter == _map_md5_files.end()) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = iter->second->_total_size; + rtvalue["seq"] = iter->second->_seq; + rtvalue["name"] = iter->second->_name; + rtvalue["trans_size"] = iter->second->_trans_size; + rtvalue["md5"] = md5; + + }; +``` + +### 多线程服务器 + +多线程服务器改造和单线程类似 + +只不过将处理逻辑放入`LogicWorker`中 + +``` cpp +void LogicWorker::RegisterCallBacks() +{ + _fun_callbacks[ID_TEST_MSG_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto data = root["data"].asString(); + std::cout << "recv test data is " << data << std::endl; + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_TEST_MSG_RSP); + }); + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["data"] = data; + }; + + _fun_callbacks[ID_UPLOAD_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / name).string(); + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_FILE_RSP); + }); + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + LogicSystem::GetInstance()->AddMD5File(md5, file_info); + } + else { + auto file_info = LogicSystem::GetInstance()->GetFileInfo(md5); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, name, seq, total_size, + trans_size, last, file_data), + index + ); + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + }; + + + + _fun_callbacks[ID_SYNC_FILE_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_SYNC_FILE_RSP); + }); + + auto md5 = root["md5"].asString(); + + auto file = LogicSystem::GetInstance()->GetFileInfo(md5); + if (file == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = file->_total_size; + rtvalue["seq"] = file->_seq; + rtvalue["name"] = file->_name; + rtvalue["trans_size"] = file->_trans_size; + rtvalue["md5"] = md5; + + }; +} +``` + +将进度信息存储在`LogicSystem`中,后续可参考填写入`redis`,方便后续分布式扩展,注意如果填写了多个资源服务器,还有写入服务器信息,这个不再赘述和进阶,我们只用一个资源服务器做演示,后续读者可自己进阶分布式设计。 + +``` cpp +void LogicSystem::AddMD5File(std::string md5, std::shared_ptr fileinfo) { + std::lock_guard lock(_file_mtx); + _map_md5_files[md5] = fileinfo; +} + +std::shared_ptr LogicSystem::GetFileInfo(std::string md5) { + std::lock_guard lock(_file_mtx); + auto iter = _map_md5_files.find(md5); + if (iter == _map_md5_files.end()) { + return nullptr; + } + + return iter->second; +} +``` + +## 集成资源服务器 + +### 新架构形式 + +集成资源服务器后的架构为 + +![image-20250905105415106](https://cdn.llfc.club/img/image-20250905105415106.png) + +将上述多线程服务器,整合到项目目录,同时设置资源属性表,复用之前的就可以了。 + +注意资源服务器配置要稍作修改 + +``` cpp +[GateServer] +Port = 8080 +[VarifyServer] +Host = 127.0.0.1 +Port = 50051 +[StatusServer] +Host = 127.0.0.1 +Port = 50052 +[SelfServer] +Name = reserver +Host = 0.0.0.0 +Port = 9090 +RPCPort = 51055 +[Mysql] +Host = 81.68.86.146 +Port = 3308 +User = root +Passwd = 123456. +Schema = llfc +[Redis] +Host = 81.68.86.146 +Port = 6380 +Passwd = 123456 + +[Static] +Path = static +[Output] +Path = bin + +``` + + + +## 客户端新增资源网络类 + +### 构造函数解析 + +因为客户端需要长连接资源服务器,采用TCP方式上传文件,所以需要封装一个单例的`FileTcpMgr`类,用于上传资源。 + +``` cpp +class FileTcpMgr : public QObject, public Singleton, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + friend class Singleton; + ~FileTcpMgr(); + void SendData(ReqId reqId, QByteArray data); + void CloseConnection(); +private: + void initHandlers(); + explicit FileTcpMgr(QObject *parent = nullptr); + + void registerMetaType(); + void handleMsg(ReqId id, int len, QByteArray data); + + QTcpSocket _socket; + QString _host; + uint16_t _port; + QByteArray _buffer; + bool _b_recv_pending; + quint16 _message_id; + quint32 _message_len; + QMap> _handlers; + //发送队列 + QQueue _send_queue; + //正在发送的包 + QByteArray _current_block; + //当前已发送的字节数 + qint64 _bytes_sent; + //是否正在发送 + bool _pending; +signals: + void sig_send_data(ReqId reqId, QByteArray data); + void sig_con_success(bool bsuccess); + void sig_connection_closed(); +public slots: + void slot_send_data(ReqId reqId, QByteArray data); + void slot_tcp_connect(std::shared_ptr si); +}; +``` + +构造函数具体实现 + +``` cpp +FileTcpMgr::FileTcpMgr(QObject *parent) : QObject(parent), +_host(""), _port(0), _b_recv_pending(false), _message_id(0), _message_len(0), _bytes_sent(0), _pending(false) +{ + registerMetaType(); + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { + qDebug() << "Connected to server!"; + emit sig_con_success(true); + }); + + + QObject::connect(&_socket, &QTcpSocket::readyRead, this, [&]() { + // 当有数据可读时,读取所有数据 + // 读取所有数据并追加到缓冲区 + _buffer.append(_socket.readAll()); + + QDataStream stream(&_buffer, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_5_0); + + forever { + //先解析头部 + if(!_b_recv_pending){ + // 检查缓冲区中的数据是否足够解析出一个消息头(消息ID + 消息长度) + if (_buffer.size() < FILE_UPLOAD_HEAD_LEN) { + return; // 数据不够,等待更多数据 + } + + // 预读取消息ID和消息长度,但不从缓冲区中移除 + stream >> _message_id >> _message_len; + + //将buffer 中的前六个字节移除 + _buffer = _buffer.mid(FILE_UPLOAD_HEAD_LEN); + + // 输出读取的数据 + qDebug() << "Message ID:" << _message_id << ", Length:" << _message_len; + + } + + //buffer剩余长读是否满足消息体长度,不满足则退出继续等待接受 + if(_buffer.size() < _message_len){ + _b_recv_pending = true; + return; + } + + _b_recv_pending = false; + // 读取消息体 + QByteArray messageBody = _buffer.mid(0, _message_len); + qDebug() << "receive body msg is " << messageBody ; + + _buffer = _buffer.mid(_message_len); + handleMsg(ReqId(_message_id),_message_len, messageBody); + } + + }); + + + //5.15 之后版本 +// QObject::connect(&_socket, QOverload::of(&QTcpSocket::errorOccurred), [&](QAbstractSocket::SocketError socketError) { +// Q_UNUSED(socketError) +// qDebug() << "Error:" << _socket.errorString(); +// }); + + // 处理错误(适用于Qt 5.15之前的版本) + QObject::connect(&_socket, static_cast(&QTcpSocket::error), + this, + [&](QTcpSocket::SocketError socketError) { + qDebug() << "Error:" << _socket.errorString() ; + //todo... 根据错误类型做不同的处理 + switch (socketError) { + case QTcpSocket::ConnectionRefusedError: + qDebug() << "Connection Refused!"; + emit sig_con_success(false); + break; + case QTcpSocket::RemoteHostClosedError: + qDebug() << "Remote Host Closed Connection!"; + break; + case QTcpSocket::HostNotFoundError: + qDebug() << "Host Not Found!"; + emit sig_con_success(false); + break; + case QTcpSocket::SocketTimeoutError: + qDebug() << "Connection Timeout!"; + emit sig_con_success(false); + break; + case QTcpSocket::NetworkError: + //qDebug() << "Network Error!"; + break; + default: + //qDebug() << "Other Error!"; + break; + } + }); + + // 处理连接断开 + QObject::connect(&_socket, &QTcpSocket::disconnected, this,[&]() { + qDebug() << "Disconnected from server."; + emit sig_connection_closed(); + }); + + + //连接发送信号用来发送数据 + QObject::connect(this, &FileTcpMgr::sig_send_data, this, &FileTcpMgr::slot_send_data); + + //连接发送信号 + QObject::connect(&_socket, &QTcpSocket::bytesWritten, this, [this](qint64 bytes) { + //更新发送数据 + _bytes_sent += bytes; + //未发送完整 + if (_bytes_sent < _current_block.size()) { + //继续发送 + auto data_to_send = _current_block.mid(_bytes_sent); + _socket.write(data_to_send); + return; + } + + //发送完全,则查看队列是否为空 + if (_send_queue.isEmpty()) { + //队列为空,说明已经将所有数据发送完成,将pending设置为false,这样后续要发送数据时可以继续发送 + _current_block.clear(); + _pending = false; + _bytes_sent = 0; + return; + } + + //队列不为空,则取出队首元素 + _current_block = _send_queue.dequeue(); + _bytes_sent = 0; + _pending = true; + qint64 w2 = _socket.write(_current_block); + qDebug() << "[TcpMgr] Dequeued and write() returned" << w2; + }); + + //连接 + QObject::connect(this, &FileTcpMgr::sig_close, this, &FileTcpMgr::slot_tcp_close); + //注册消息 + initHandlers(); + +} +``` + +简单描述下上述构造函数做的事情: + +1. 成功连接服务器后,会触发`QTcpSocket::connected`信号,从而回调`lambda`表达式,发送`sig_con_success`信号 +2. 接收服务器传输的数据,会触发`QTcpSocket::readyRead`信号,从而回调`lambda`表达式,在这里处理头部信息和包体信息。进行`TLV`协议解析后回调`handleMsg`。 +3. 捕获`QTcpSocket::SocketError`信号,当出错后回调`lambda`表达式发送信号通知主界面错误。 +4. 捕获连接断开信号`QTcpSocket::disconnected`,回调`lambda`表达式,通知主界面连接断开。 +5. 连接发送信号`sig_send_data`,因为`socket`在独立线程,不能直接调用发送,所以改为异步发送,触发槽函数`slot_send_data` +6. 因为异步发送,可能存在未发送完全的情况,所以我们用`QTcpSocket::bytesWritten`来检测发送了多少字节,通过`lambda`表达式回调处理,继续发送数据。 +7. 因为`socket`被独立为单独线程,所以关闭也不能直接调用`close(socket)`, 需要统一在槽函数中处理。 + +注册元对象系统的逻辑不再赘述。 + +### 连接槽函数 + +我们实现槽函数`slot_tcp_connect`用来创建客户端到资源服务器的连接 + +``` cpp +void FileTcpMgr::slot_tcp_connect(std::shared_ptr si) +{ + qDebug()<< "receive tcp connect signal"; + // 尝试连接到服务器 + qDebug() << "Connecting to server..."; + _host = si->_res_host; + _port = static_cast(si->_res_port.toUInt()); + _socket.connectToHost(_host, _port); +} +``` + + + +### 注册处理流程 + +注册上传头像回调逻辑 + +``` cpp +void FileTcpMgr::initHandlers() +{ + //todo 接收上传用户头像回复 + _handlers.insert(ID_UPLOAD_HEAD_ICON_RSP, [this](ReqId id, int len, QByteArray data){ + Q_UNUSED(len); + qDebug()<< "handle id is "<< id ; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if(jsonDoc.isNull()){ + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug()<< "data jsonobj is " << recvObj ; + + if(!recvObj.contains("error")){ + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err ; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if(err != ErrorCodes::SUCCESS){ + qDebug() << "Login Failed, err is " << err ; + //emit upload_failed(); + return; + } + + auto md5 = recvObj["md5"].toString(); + auto seq = recvObj["seq"].toInt(); + auto trans_size = recvObj["trans_size"].toInt(); + auto uid = recvObj["uid"].toInt(); + auto total_size = recvObj["total_size"].toInt(); + auto name = recvObj["name"].toString(); + + qDebug() << "recv : " << name << "file trans_size is " << trans_size; + //判断trans_size和total_size相等 + if(total_size == trans_size){ + return; + } + + auto file_info = UserMgr::GetInstance()->GetFileInfoByMD5(md5); + if(!file_info){ + return; + } + + //再次组织数据发送 + QFile file(file_info->filePath()); + if(!file.open(QIODevice::ReadOnly)){ + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(trans_size); + QByteArray buffer; + seq ++; + //每次读取2048字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = md5; + sendObj["name"] = file_info->fileName(); + sendObj["seq"] = seq; + sendObj["trans_size"] = buffer.size() + (seq-1)*MAX_FILE_LEN; + sendObj["total_size"] = total_size; + + if(buffer.size() + (seq-1)*MAX_FILE_LEN >= total_size){ + sendObj["last"] = 1; + }else{ + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = recvObj["last_seq"].toInt(); + sendObj["uid"] = uid; + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + SendData(ID_UPLOAD_HEAD_ICON_REQ, send_data); + + file.close(); + }); + +} +``` + + + +### 独立文件线程 + +对于上传我们独立到文件上报线程中 + +``` cpp +class FileTcpThread: public std::enable_shared_from_this{ +public: + FileTcpThread(); + ~FileTcpThread(); +private: + QThread * _file_tcp_thread; + +}; +``` + +具体实现 + +``` cpp +FileTcpThread::FileTcpThread() +{ + _file_tcp_thread = new QThread(); + FileTcpMgr::GetInstance()->moveToThread(_file_tcp_thread); + QObject::connect(_file_tcp_thread, &QThread::finished, _file_tcp_thread, &QObject::deleteLater); + _file_tcp_thread->start(); +} + +FileTcpThread::~FileTcpThread() +{ + _file_tcp_thread->quit(); +} + +``` + +主函数调用 + +``` cpp +#include "mainwindow.h" +#include +#include +#include "global.h" +#include "tcpmgr.h" +#include "filetcpmgr.h" +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QFile qss(":/style/stylesheet.qss"); + + if( qss.open(QFile::ReadOnly)) + { + qDebug("open success"); + QString style = QLatin1String(qss.readAll()); + a.setStyleSheet(style); + qss.close(); + }else{ + qDebug("Open failed"); + } + + + // 获取当前应用程序的路径 + QString app_path = QCoreApplication::applicationDirPath(); + // 拼接文件名 + QString fileName = "config.ini"; + QString config_path = QDir::toNativeSeparators(app_path + + QDir::separator() + fileName); + + QSettings settings(config_path, QSettings::IniFormat); + QString gate_host = settings.value("GateServer/host").toString(); + QString gate_port = settings.value("GateServer/port").toString(); + gate_url_prefix = "http://"+gate_host+":"+gate_port; + + //启动tcp线程 + TcpThread tcpthread; + //启动资源网络线程 + FileTcpThread file_tcp_thread; + MainWindow w; + w.show(); + return a.exec(); +} + +``` + +原来的登录流程稍作修改,连接好`ChatServer`后,连接`ResourceServer`, 最后再让用户登录。 + +## 服务器逻辑 + +服务器新增文件上报逻辑处理, 在`LogicWorker::RegisterCallBacks`中添加 + +``` cpp +_fun_callbacks[ID_UPLOAD_HEAD_ICON_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto uid = root["uid"].asInt(); + auto token = root["token"].asString(); + auto last_seq = root["last_seq"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + }); + + //第一个包校验一下token是否合理 + if (seq == 1) { + //从redis获取用户token是否正确 + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + return; + } + } + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + LogicSystem::GetInstance()->AddMD5File(md5, file_info); + } + else { + auto file_info = LogicSystem::GetInstance()->GetFileInfo(md5); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, file_path_str, name, seq, total_size, + trans_size, last, file_data), + index + ); + + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["last_seq"] = last_seq; + }; + +``` + + + +## 源码 + +[https://gitee.com/secondtonone1/llfcchat](https://gitee.com/secondtonone1/llfcchat) + +效果展示: + +上传前 + +![image-20250905145321372](https://cdn.llfc.club/img/image-20250905145321372.png) + + + +上传后 + +![image-20250905145408921](https://cdn.llfc.club/img/image-20250905145408921.png) + + + +服务器存储成功 + +![image-20250905145440949](https://cdn.llfc.club/img/image-20250905145440949.png) + + + + + +## 续传信息持久化 + +增加`redis`接口 + +``` cpp +bool RedisMgr::SetFileInfo(const std::string& md5, std::shared_ptr file_info) +{ + Json::Reader reader; + Json::Value root; + root["file_path_str"] = file_info->_file_path_str; + root["name"] = file_info->_name; + root["seq"] = file_info->_seq; + root["total_size"] = file_info->_total_size; + root["trans_size"] = file_info->_trans_size; + auto file_info_str = root.toStyledString(); + auto redis_key = "file_upload_" + md5; + bool success = SetExp(redis_key, file_info_str, 3600); + return success; +} +``` + +新增超时设置 + +``` cpp +bool RedisMgr::SetExp(const std::string& key, const std::string& value, int expire_seconds) { + //执行redis命令行 + auto connect = _con_pool->getConnection(); + if (connect == nullptr) { + return false; + } + auto reply = (redisReply*)redisCommand(connect, "SETEX %s %d %s", key.c_str(), + expire_seconds, + value.c_str()); + + if (NULL == reply) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure ! " << std::endl; + _con_pool->returnConnection(connect); + return false; + } + + if (!(reply->type == REDIS_REPLY_STATUS && + (strcmp(reply->str, "OK") == 0 || strcmp(reply->str, "ok") == 0))) { + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] failure ! " << std::endl; + freeReplyObject(reply); + _con_pool->returnConnection(connect); + return false; + } + + freeReplyObject(reply); + std::cout << "Execute command [ SETEX " << key << " " << expire_seconds + << " " << value << " ] success ! " << std::endl; + _con_pool->returnConnection(connect); + return true; +} +``` + +每次收到上传信息后,更新上传进度到redis中 + +``` cpp +_fun_callbacks[ID_UPLOAD_HEAD_ICON_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto uid = root["uid"].asInt(); + auto token = root["token"].asString(); + auto last_seq = root["last_seq"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + auto callback = [=](const Json::Value& result) { + + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["last_seq"] = last_seq; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + }; + + //第一个包校验一下token是否合理 + if (seq == 1) { + //从redis获取用户token是否正确 + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + //LogicSystem::GetInstance()->AddMD5File(md5, file_info); + //改为用redis存储 + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + else { + //auto file_info = LogicSystem::GetInstance()->GetFileInfo(md5); + //改为从redis中加载 + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + + }; + +``` + + + +## 资源url更新 + +因为上头像传资源后,要将资源的路径存储到`mysql`数据库中,所以我们新增`MysqlMgr`,这个直接从`ChatServer`拷贝一份即可。 + +但是要注意,添加如下函数 + +``` cpp +bool MysqlMgr::UpdateUserIcon(int uid, const std::string& icon) { + return _dao.UpdateHeadInfo(uid, icon); +} + +``` + +`Dao`层面实现更新头像逻辑 + +``` cpp +bool MysqlDao::UpdateHeadInfo(int uid, const std::string& icon) +{ + auto con = pool_->getConnection(); + if (!con) { + return false; + } + Defer defer([this, &con]() { + pool_->returnConnection(std::move(con)); + }); + + auto& conn = con->_con; + try { + std::string update_sql = + "UPDATE user SET icon = ? WHERE uid = ?;"; + + std::unique_ptr pstmt(conn->prepareStatement(update_sql)); + pstmt->setString(1, icon); + pstmt->setInt64(2, uid); + + int affected_rows = pstmt->executeUpdate(); + + // 检查是否有行被更新(可选) + if (affected_rows == 0) { + std::cerr << "No user found with uid: " << uid << std::endl; + return false; + } + + return true; + } + catch (sql::SQLException& e) { + std::cerr << "SQLException in UpdateHeadInfo: " << e.what() << std::endl; + return false; + } + return false; +} + +``` + + + +## 封装异步回调 + +之前我们处理文件上传是异步方式,将要保存的文件投递给消息队列,交给独立线程后台保存。我们没有等待处理完成就直接将消息回传给客户端,这么做不是很好,所以改为异步方式,简单的方式就是通过回调函数处理,或者包装一个future等待。这里考虑保留异步结构,所以还是用回调处理 + +``` cpp +struct FileTask { + FileTask(std::shared_ptr session, int uid, std::string path, std::string name, + int seq, int total_size, int trans_size, int last, + std::string file_data, + std::function callback) :_session(session), _uid(uid), + _seq(seq), _path(path), _name(name), _total_size(total_size), + _trans_size(trans_size), _last(last), _file_data(file_data), _callback(callback) + {} + ~FileTask(){} + std::shared_ptr _session; + int _uid; + int _seq ; + std::string _path; + std::string _name ; + int _total_size ; + int _trans_size ; + int _last ; + std::string _file_data; + std::function _callback; //添加回调函数 +}; +``` + +改进后的处理 + +``` cpp + _fun_callbacks[ID_UPLOAD_HEAD_ICON_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto uid = root["uid"].asInt(); + auto token = root["token"].asString(); + auto last_seq = root["last_seq"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + auto callback = [=](const Json::Value& result) { + + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + rtvalue["last_seq"] = last_seq; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + }; + + //第一个包校验一下token是否合理 + if (seq == 1) { + //从redis获取用户token是否正确 + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + //LogicSystem::GetInstance()->AddMD5File(md5, file_info); + //改为用redis存储 + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + else { + //auto file_info = LogicSystem::GetInstance()->GetFileInfo(md5); + //改为从redis中加载 + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + + }; +``` + +`callback`是我们封装的回调函数,投递给`FileTask`, 将来在后台线程处理`FileTask`时回调。 + +``` cpp +void FileWorker::task_callback(std::shared_ptr task) +{ + // 解码 + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (task->_seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return ; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return ; + } + + outfile.close(); + if (last) { + std::cout << "文件已成功保存为: " << task->_name << std::endl; + //更新头像 + MysqlMgr::GetInstance()->UpdateUserIcon(task->_uid, filename); + //获取用户信息 + auto user_info = MysqlMgr::GetInstance()->GetUser(task->_uid); + if (user_info == nullptr) { + return ; + } + + //将数据库内容写入redis缓存 + Json::Value redis_root; + redis_root["uid"] = task->_uid; + redis_root["pwd"] = user_info->pwd; + redis_root["name"] = user_info->name; + redis_root["email"] = user_info->email; + redis_root["nick"] = user_info->nick; + redis_root["desc"] = user_info->desc; + redis_root["sex"] = user_info->sex; + redis_root["icon"] = user_info->icon; + std::string base_key = USER_BASE_INFO + std::to_string(task->_uid); + RedisMgr::GetInstance()->Set(base_key, redis_root.toStyledString()); + } + + if (task->_callback) { + task->_callback(result); + } + +} +``` + +## 客户端上传逻辑修改 + +``` cpp +//上传头像 +void UserInfoPage::slot_up_load() +{ + // 1. 让对话框也能选 *.webp + QString filename = QFileDialog::getOpenFileName( + this, + tr("选择图片"), + QString(), + tr("图片文件 (*.png *.jpg *.jpeg *.bmp *.webp)") + ); + if (filename.isEmpty()) + return; + + // 2. 直接用 QPixmap::load() 加载,无需手动区分格式 + QPixmap inputImage; + if (!inputImage.load(filename)) { + QMessageBox::critical( + this, + tr("错误"), + tr("加载图片失败!请确认已部署 WebP 插件。"), + QMessageBox::Ok + ); + return; + } + + QPixmap image = ImageCropperDialog::getCroppedImage(filename, 600, 400, CropperShape::CIRCLE); + if (image.isNull()) + return; + + QPixmap scaledPixmap = image.scaled( ui->head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + QString storageDir = QStandardPaths::writableLocation( + QStandardPaths::AppDataLocation); + // 2. 在其下再建一个 avatars 子目录 + QDir dir(storageDir); + if (!dir.exists("avatars")) { + if (!dir.mkpath("avatars")) { + qWarning() << "无法创建 avatars 目录:" << dir.filePath("avatars"); + QMessageBox::warning( + this, + tr("错误"), + tr("无法创建存储目录,请检查权限或磁盘空间。") + ); + return; + } + } + // 3. 拼接最终的文件名 head.png + QString file_name = generateUniqueIconName(); + QString filePath = dir.filePath("avatars" + + QString(QDir::separator()) + file_name); + + // 4. 保存 scaledPixmap 为 PNG(无损、最高质量) + if (!scaledPixmap.save(filePath, "PNG")) { + QMessageBox::warning( + this, + tr("保存失败"), + tr("头像保存失败,请检查权限或磁盘空间。") + ); + } else { + qDebug() << "头像已保存到:" << filePath; + // 以后读取直接用同一路径:storageDir/avatars/head.png + } + + //实现头像上传 + QFile file(filePath); + if(!file.open(QIODevice::ReadOnly)){ + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + //保存当前文件位置指针 + qint64 originalPos = file.pos(); + + QCryptographicHash hash(QCryptographicHash::Md5); + if (!hash.addData(&file)) { + qWarning() << "Failed to read data from file:" << filePath; + return ; + } + + // 5. 转化为16进制字符串 + QString file_md5 = hash.result().toHex(); // 返回十六进制字符串 + + //读取文件内容并发送 + QByteArray buffer; + int seq = 0; + + //创建QFileInfo 对象 + auto fileInfo = std::make_shared(filePath); + //获取文件名 + QString fileName = fileInfo->fileName(); + //文件名 + qDebug() << "文件名是: " << fileName; + + //获取文件大小 + int total_size = fileInfo->size(); + //最后一个发送序列 + int last_seq = 0; + //获取最后一个发送序列 + if(total_size % MAX_FILE_LEN){ + last_seq = (total_size / MAX_FILE_LEN) +1; + }else{ + last_seq = total_size / MAX_FILE_LEN; + } + + // 恢复文件指针到原来的位置 + file.seek(originalPos); + + //每次读取MAX_FILE_LEN字节并发送 + buffer = file.read(MAX_FILE_LEN); + + QJsonObject jsonObj; + //将文件内容转化为Base64 编码(可选) + QString base64Data = buffer.toBase64(); + ++seq; + jsonObj["md5"] = file_md5; + jsonObj["name"] = file_name; + jsonObj["seq"] = seq; + jsonObj["trans_size"] = buffer.size() + (seq - 1) * MAX_FILE_LEN; + jsonObj["total_size"] = total_size; + jsonObj["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj["uid"] = UserMgr::GetInstance()->GetUid(); + + if (buffer.size() + (seq - 1) * MAX_FILE_LEN == total_size) { + jsonObj["last"] = 1; + } else { + jsonObj["last"] = 0; + } + + jsonObj["data"] = base64Data; + jsonObj["last_seq"] = last_seq; + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + //将md5信息和文件信息关联存储 + UserMgr::GetInstance()->AddNameFile(file_name, fileInfo); + //发送消息 + FileTcpMgr::GetInstance()->SendData(ID_UPLOAD_HEAD_ICON_REQ, send_data); + file.close(); +} +``` + + + +## 客户端加载头像 + +服务器将上传的头像信息保存为`url`更新到`mysql`中,接下来客户端登录需要加载新的头像 + +在`ChatDialog`的构造函数中将头像加载逻辑修改为 + +``` cpp + //模拟加载自己头像 + QString head_icon = UserMgr::GetInstance()->GetIcon(); + //使用正则表达式检查是否使用默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(head_icon); + if (match.hasMatch()) { + // 如果是默认头像(:/res/head_X.jpg 格式) + QPixmap pixmap(head_icon); // 加载默认头像图片 + QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->side_head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->side_head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(head_icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled(ui->side_head_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->side_head_lb->setPixmap(scaledPixmap); + ui->side_head_lb->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } +``` + +聊天页面也需要修改头像加载逻辑 + +``` cpp +void ChatPage::AppendChatMsg(std::shared_ptr msg) +{ + auto self_info = UserMgr::GetInstance()->GetUserInfo(); + ChatRole role; + if (msg->GetSendUid() == self_info->_uid) { + role = ChatRole::Self; + ChatItemBase* pChatItem = new ChatItemBase(role); + + pChatItem->setUserName(self_info->_name); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(self_info->_icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(self_info->_icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(self_info->_icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + if (status == 0) { + _unrsp_item_map[msg->GetUniqueId()] = pChatItem; + } + } + else { + role = ChatRole::Other; + ChatItemBase* pChatItem = new ChatItemBase(role); + auto friend_info = UserMgr::GetInstance()->GetFriendById(msg->GetSendUid()); + if (friend_info == nullptr) { + return; + } + pChatItem->setUserName(friend_info->_name); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(friend_info->_icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(friend_info->_icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + if (status == 0) { + _unrsp_item_map[msg->GetUniqueId()] = pChatItem; + } + } + + +} +``` + +聊天列表中加载头像逻辑修改一下 + +``` cpp +void ChatUserWid::SetChatData(std::shared_ptr chat_data) { + _chat_data = chat_data; + auto other_id = _chat_data->GetOtherId(); + auto other_info = UserMgr::GetInstance()->GetFriendById(other_id); + // 加载图片 + + QString head_icon = UserMgr::GetInstance()->GetIcon(); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(other_info->_icon); + + if (match.hasMatch()) { + // 如果是默认头像(:/res/head_X.jpg 格式) + QPixmap pixmap(other_info->_icon); // 加载默认头像图片 + QPixmap scaledPixmap = pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->icon_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->icon_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(other_info->_icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled(ui->icon_lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui->icon_lb->setPixmap(scaledPixmap); + ui->icon_lb->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + ui->user_name_lb->setText(other_info->_name); + + ui->user_chat_lb->setText(chat_data->GetLastMsg()); +} +``` + +用户信息加载头像 + +``` cpp +UserInfoPage::UserInfoPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::UserInfoPage) +{ + ui->setupUi(this); + auto icon = UserMgr::GetInstance()->GetIcon(); + qDebug() << "icon is " << icon ; + + //使用正则表达式检查是否使用默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(icon); + if (match.hasMatch()) { + QPixmap pixmap(icon); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(QFileInfo(icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + + + //获取nick + auto nick = UserMgr::GetInstance()->GetNick(); + //获取name + auto name = UserMgr::GetInstance()->GetName(); + //描述 + auto desc = UserMgr::GetInstance()->GetDesc(); + ui->nick_ed->setText(nick); + ui->name_ed->setText(name); + ui->desc_ed->setText(desc); + //连接上 + connect(ui->up_btn, &QPushButton::clicked, this, &UserInfoPage::slot_up_load); +} +``` + + + +## 测试效果 + +![image-20250923094811744](https://cdn.llfc.club/img/image-20250923094811744.png) + + + +## 客户端断点下载资源 + +### 客户端请求下载 + +在客户端加载本地资源发现不存在的时候,需要请求服务器,获取资源。 + +如果资源比较大,需要分批下载,也就是支持断点下载。 + +我们先拿`UserInfoPage`举例 + +``` cpp +UserInfoPage::UserInfoPage(QWidget *parent) : + QWidget(parent), + ui(new Ui::UserInfoPage) +{ + ui->setupUi(this); + auto icon = UserMgr::GetInstance()->GetIcon(); + qDebug() << "icon is " << icon ; + + //使用正则表达式检查是否使用默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(icon); + if (match.hasMatch()) { + QPixmap pixmap(icon); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QDir avatarsDir(storageDir + "/avatars"); + // 确保目录存在 + if (avatarsDir.exists()) { + auto file_name = QFileInfo(icon).fileName(); + QString avatarPath = avatarsDir.filePath(QFileInfo(icon).fileName()); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + return; + } + + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + UserMgr::GetInstance()->AddLabelToReset(avatarPath, ui->head_lb); + //先加载默认的 + QPixmap pixmap(":/res/head_1.jpg"); + QPixmap scaledPixmap = pixmap.scaled(ui->head_lb->size(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); // 将图片缩放到label的大小 + ui->head_lb->setPixmap(scaledPixmap); // 将缩放后的图片设置到QLabel上 + ui->head_lb->setScaledContents(true); // 设置QLabel自动缩放图片内容以适应大小 + + //判断是否正在下载 + bool is_loading = UserMgr::GetInstance()->IsDownLoading(file_name); + if (is_loading) { + qWarning() << "正在下载: " << file_name; + return; + } + //发送请求获取资源 + auto download_info = std::make_shared(); + download_info->_name = file_name; + download_info->_current_size = 0; + download_info->_seq = 1; + download_info->_total_size = 0; + download_info->_client_path = avatarPath; + //添加文件到管理者 + UserMgr::GetInstance()->AddDownloadFile(file_name, download_info); + //发送消息 + FileTcpMgr::GetInstance()->SendDownloadInfo(download_info); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + } + } + + + + //获取nick + auto nick = UserMgr::GetInstance()->GetNick(); + //获取name + auto name = UserMgr::GetInstance()->GetName(); + //描述 + auto desc = UserMgr::GetInstance()->GetDesc(); + ui->nick_ed->setText(nick); + ui->name_ed->setText(name); + ui->desc_ed->setText(desc); + //连接上 + connect(ui->up_btn, &QPushButton::clicked, this, &UserInfoPage::slot_up_load); +} +``` + +如果本地资源不存在,则需要向服务器请求。 + +### 封装请求资源接口 + +**判断资源是否正在下载** + +``` cpp + +bool UserMgr::IsDownLoading(QString name) { + std::lock_guard lock(_down_load_mtx); + auto iter = _name_to_download_info.find(name); + if (iter == _name_to_download_info.end()) { + return false; + } + + return true; +} +``` + +如果资源加载成功,很可能处于正在下载,所以也要判断一下。 + +如果资源未加载成功,则需要向服务器下载资源。先讲要下载的资源和要加载资源的空间缓存起来。 + +``` cpp +void UserMgr::AddLabelToReset(QString path, QLabel* label) +{ + auto iter = _name_to_reset_labels.find(path); + if (iter == _name_to_reset_labels.end()) { + QList list; + list.append(label); + _name_to_reset_labels.insert(path, list); + return; + } + + iter->append(label); +} +``` + +**结构如下图** + +![image-20251004125019778](https://cdn.llfc.club/img/image-20251004125019778.png) + +### 更新正在下载资源 + +``` cpp +void UserMgr::AddDownloadFile(QString name, + std::shared_ptr file_info) { + std::lock_guard lock(_down_load_mtx); + _name_to_download_info[name] = file_info; +} +``` + +### 发送下载请求 + +``` cpp +void FileTcpMgr::SendDownloadInfo(std::shared_ptr download) { + QJsonObject jsonObj; + jsonObj["name"] = download->_name; + jsonObj["seq"] = download->_seq; + jsonObj["trans_size"] = 0; + jsonObj["total_size"] = 0; + jsonObj["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj["uid"] = UserMgr::GetInstance()->GetUid(); + jsonObj["client_path"] = download->_client_path; + + QJsonDocument doc(jsonObj); + auto send_data = doc.toJson(); + + SendData(ID_DOWN_LOAD_FILE_REQ, send_data); +} +``` + + + +### 接收服务器回传 + +``` cpp + _handlers.insert(ID_DOWN_LOAD_FILE_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive download file info rsp success"; + + QString base64Data = jsonObj["data"].toString(); + QString clientPath = jsonObj["client_path"].toString(); + int seq = jsonObj["seq"].toInt(); + bool is_last = jsonObj["is_last"].toBool(); + QString total_size_str = jsonObj["total_size"].toString(); + qint64 total_size = total_size_str.toLongLong(nullptr); + QString current_size_str = jsonObj["current_size"].toString(); + qint64 current_size = current_size_str.toLongLong(nullptr); + QString name = jsonObj["name"].toString(); + + auto file_info = UserMgr::GetInstance()->GetDownloadInfo(name); + if (file_info == nullptr) { + qDebug() << "file: " << name << " not found"; + return; + } + + file_info->_current_size = current_size; + file_info->_total_size = total_size; + + //Base64解码 + QByteArray decodedData = QByteArray::fromBase64(base64Data.toUtf8()); + QFile file(clientPath); + + // 根据 seq 决定打开模式 + QIODevice::OpenMode mode; + if (seq == 1) { + // 第一个包,覆盖写入 + mode = QIODevice::WriteOnly; + } + else { + // 后续包,追加写入 + mode = QIODevice::WriteOnly | QIODevice::Append; + } + + if (!file.open(mode)) { + qDebug() << "Failed to open file for writing:" << clientPath; + qDebug() << "Error:" << file.errorString(); + return; + } + + + qint64 bytesWritten = file.write(decodedData); + if (bytesWritten != decodedData.size()) { + qDebug() << "Failed to write all data. Written:" << bytesWritten + << "Expected:" << decodedData.size(); + } + + file.close(); + + qDebug() << "Successfully wrote" << bytesWritten << "bytes to file"; + qDebug() << "Progress:" << current_size << "/" << total_size + << "(" << (current_size * 100 / total_size) << "%)"; + + if (is_last) { + qDebug() << "File download completed:" << clientPath; + UserMgr::GetInstance()->RmvDownloadFile(name); + //发送信号通知主界面重新加载label + emit sig_reset_label_icon(clientPath); + } + else { + //继续请求 + file_info->_seq = seq+1; + FileTcpMgr::GetInstance()->SendDownloadInfo(file_info); + } + }); +``` + +1. 判断seq是否为1,如果为1则说明新的文件,需要创建并保存 +2. 如果seq不为1,则说明是续传文件,更新追加就可以了 +3. 如果`is_last`字段为true,说明是最后一个包,那么移除缓存的下载信息,同时将信息发送到主界面更新图标 + + + +### 更新页面逻辑 + +在`ChatDialog`界面中响应这个信号 + +``` cpp +//重置label icon +connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_reset_label_icon, this, &ChatDialog::slot_reset_icon); +``` + +槽函数处理 + +``` cpp +void ChatDialog::slot_reset_icon(QString path) { + UserMgr::GetInstance()->ResetLabelIcon(path); +} +``` + +`UserMgr`中封装重置`icon`逻辑 + +``` cpp +void UserMgr::ResetLabelIcon(QString path) +{ + auto iter = _name_to_reset_labels.find(path); + if (iter == _name_to_reset_labels.end()) { + return; + } + + for (auto ele_iter = iter.value().begin(); ele_iter != iter.value().end(); ele_iter++) { + QPixmap pixmap(path); // 加载上传的头像图片 + if (!pixmap.isNull()) { + QPixmap scaledPixmap = pixmap.scaled((*ele_iter)->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + (*ele_iter)->setPixmap(scaledPixmap); + (*ele_iter)->setScaledContents(true); + } + else { + qWarning() << "无法加载上传的头像:" << path; + } + } + + _name_to_reset_labels.erase(iter); +} +``` + +### 测试效果 + +## 服务器断点传输逻辑 + +**增加下载worker** + +``` cpp +class DownloadWorker { +public: + DownloadWorker(); + ~DownloadWorker(); + void PostTask(std::shared_ptr task); +private: + void task_callback(std::shared_ptr); + std::thread _work_thread; + std::queue> _task_que; + std::atomic _b_stop; + std::mutex _mtx; + std::condition_variable _cv; +}; +``` + +`DownloadWorker`处理逻辑和之前的`FileWorker`类似 + +``` cpp +DownloadWorker::DownloadWorker() :_b_stop(false) +{ + _work_thread = std::thread([this]() { + while (!_b_stop) { + std::unique_lock lock(_mtx); + _cv.wait(lock, [this]() { + if (_b_stop) { + return true; + } + + if (_task_que.empty()) { + return false; + } + + return true; + }); + + if (_b_stop) { + break; + } + + auto task = _task_que.front(); + _task_que.pop(); + task_callback(task); + } + }); +} + +DownloadWorker::~DownloadWorker() +{ + _b_stop = true; + _cv.notify_one(); + _work_thread.join(); +} + +void DownloadWorker::PostTask(std::shared_ptr task) +{ + { + std::lock_guard lock(_mtx); + _task_que.push(task); + } + + _cv.notify_one(); +} + +void DownloadWorker::task_callback(std::shared_ptr task) +{ + // 解码 + auto file_path_str = task->_file_path; + + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + if (!boost::filesystem::exists(file_path)) { + std::cerr << "文件不存在: " << file_path_str << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + + std::ifstream infile(file_path_str, std::ios::binary); + if (!infile) { + std::cerr << "无法打开文件进行读取。" << std::endl; + result["error"] = ErrorCodes::FileReadPermissionFailed; + task->_callback(result); + return; + } + + std::shared_ptr file_info = nullptr; + + if (task->_seq == 1) { + // 获取文件大小 + infile.seekg(0, std::ios::end); + std::streamsize file_size = infile.tellg(); + infile.seekg(0, std::ios::beg); + //如果为空,则创建FileInfo 构造数据存储 + file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = filename; + file_info->_seq = 1; + + file_info->_total_size = file_size; + file_info->_trans_size = 0; + // 立即保存到 Redis,覆盖旧数据,设置过期时间 + RedisMgr::GetInstance()->SetDownLoadInfo(filename, file_info); + std::cout << "[新下载] 文件: " << filename + << ", 大小: " << file_size << " 字节" << std::endl; + } + else { + //断点续传,从 Redis 获取历史信息 + file_info = RedisMgr::GetInstance()->GetDownloadInfo(filename); + if (file_info == nullptr) { + // Redis 中没有信息(可能过期了) + std::cerr << "断点续传失败,Redis 中无下载信息: " << filename << std::endl; + result["error"] = ErrorCodes::RedisReadErr; + task->_callback(result); + infile.close(); + return; + } + + // 验证序列号是否匹配 + if (task->_seq != file_info->_seq) { + std::cerr << "序列号不匹配,期望: " << file_info->_seq + << ", 实际: " << task->_seq << std::endl; + result["error"] = ErrorCodes::FileSeqInvalid; + task->_callback(result); + infile.close(); + return; + } + + std::cout << "[续传] 文件: " << filename + << ", seq: " << task->_seq + << ", 进度: " << file_info->_trans_size + << "/" << file_info->_total_size << std::endl; + } + + // 计算当前偏移量 + std::streamsize offset = ((std::streamsize)task->_seq - 1) * MAX_FILE_LEN; + if (offset >= file_info->_total_size) { + std::cerr << "偏移量超出文件大小。" << std::endl; + result["error"] = ErrorCodes::FileOffsetInvalid; + task->_callback(result); + infile.close(); + return; + } + + // 定位到指定偏移量 + infile.seekg(offset); + + // 读取最多2048字节 + char buffer[MAX_FILE_LEN]; + infile.read(buffer, MAX_FILE_LEN); + //获取read实际读取多少字节 + std::streamsize bytes_read = infile.gcount(); + + if (bytes_read <= 0) { + std::cerr << "读取文件失败。" << std::endl; + result["error"] = ErrorCodes::FileReadFailed; + task->_callback(result); + infile.close(); + return; + } + + // 将读取的数据进行base64编码 + std::string data_to_encode(buffer, bytes_read); + std::string encoded_data = base64_encode(data_to_encode); + + // 检查是否是最后一个包 + std::streamsize current_pos = offset + bytes_read; + bool is_last = (current_pos >= file_info->_total_size); + + // 设置返回结果 + result["data"] = encoded_data; + result["seq"] = task->_seq; + result["total_size"] = std::to_string(file_info->_total_size); + result["current_size"] = std::to_string(current_pos); + result["is_last"] = is_last; + + infile.close(); + + if (is_last) { + std::cout << "文件读取完成: " << file_path_str << std::endl; + RedisMgr::GetInstance()->DelDownLoadInfo(filename); + } + else { + //更新信息 + file_info->_seq++; + file_info->_trans_size = offset + bytes_read; + //更新redis + RedisMgr::GetInstance()->SetDownLoadInfo(filename, file_info); + } + + if (task->_callback) { + task->_callback(result); + } + +} + +``` + +在`FileSystem`中创建`worker` + +``` cpp +FileSystem::FileSystem() +{ + for (int i = 0; i < FILE_WORKER_COUNT; i++) { + _file_workers.push_back(std::make_shared()); + } + + for (int i = 0; i < DOWN_LOAD_WORKER_COUNT; i++) { + _down_load_worker.push_back(std::make_shared()); + } +} +``` + + + +### 测试效果 + +将头像资源从本地删除后,重新登录时或者切换页面会引发资源重新加载,向服务器请求资源后再设置到界面显示。 + +![image-20251004153501602](https://cdn.llfc.club/img/image-20251004153501602.png) + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day39-\345\244\232\345\252\222\344\275\223\344\277\241\346\201\257\344\274\240\350\276\223.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day39-\345\244\232\345\252\222\344\275\223\344\277\241\346\201\257\344\274\240\350\276\223.md" new file mode 100644 index 0000000..0f0fd34 --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day39-\345\244\232\345\252\222\344\275\223\344\277\241\346\201\257\344\274\240\350\276\223.md" @@ -0,0 +1,1483 @@ +--- +title: 多媒体信息传输 +date: 2025-11-14 20:23:24 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 前言 + +前面实现了聊天信息的存储和加载,以及实现了一些资源的上传和下载。 + +接下来实现聊天中传输多媒体消息的逻辑,基本包括图片传输,视频传输和播放,文件传输等。 + +为了更顺利的实现功能,我打算先以图片聊天传输为切入点,然后再实现视频传输,文件传输等。 + +## 图片传输思路 + +在聊天中传输图片 + +- 一方面是要把聊天消息传输到`ChatServer`中 +- 另一方面在收到`ChatServer`的回复后,将资源断点续传方式传输给`ResourceServer` +- ``ResourceServer`需要采用断点上传方式回复给客户端。 +- `ResourceServer`将接收完整资源后,需要通过`grpc`将消息发送给`ChatServer`更新消息为已经上传完成的状态。 +- `ChatServer`收到消息后更新数据,并且做消息推送,推送给消息关联的双方。推送给发送方资源已经上传完成。推送给接收方资源已经上传完成 +- 发送方将图片设置为已上传状态,接收方则展示预览图,并显示进度百分比。 +- 后期还要优化,发送方在上传资源的时候显示圆圈百分比。已经响应点击事件,暂停或者继续。 + +![image-20251114211632712](https://cdn.llfc.club/img/image-20251114211632712.png) + + + + + +## MsgInfo完善 + +我修改了MsgInfo的结构,以支持图片视频等多媒体资源在聊天中传输 + +``` cpp +struct MsgInfo{ + + MsgInfo(MsgType msgtype, QString text_or_url, QPixmap pixmap, QString unique_name, qint64 total_size, QString md5) + :_msg_type(msgtype), _text_or_url(text_or_url), _preview_pix(pixmap),_unique_name(unique_name),_total_size(total_size), + _current_size(0),_seq(1),_md5(md5) + {} + + MsgType _msg_type; + QString _text_or_url;//表示文件和图像的url,文本信息 + QPixmap _preview_pix;//文件和图片的缩略图 + QString _unique_name; //文件唯一名字 + qint64 _total_size; //文件总大小 + qint64 _current_size; //传输大小 + qint64 _seq; //传输序号 + QString _md5; //文件md5 +}; +``` + +- 将内容字段改为`_text_or_url`,表示文件和图像的url,或者纯文本信息 +- `_preview_pix`为文件或者图片的缩略图,如果为视频则需要抽取第一帧作为缩略图,如果文件则设置指定格式即可 +- `_unique_name`为文件唯一名字,生成唯一名字有一个好处,同一个文件可以多次传输,每个文件按不同副本保存。当然也可以保存为同一份,采用md5做区分,总之这里先按照不同的副本存储在服务器。 +- `_total_size`用来统计文件的总大小 +- `_current_size`用来表示当前已经传输的大小 +- `_seq`表示传输的序号,将来做断点续传使用 +- `_md5`文件传输用的md5 + +## 修改插入消息的逻辑 + +``` cpp +void MessageTextEdit::insertMsgList(QVector> &list, MsgType msgtype, + QString text_or_url, QPixmap preview_pix, + QString unique_name, uint64_t total_size, QString md5) { + + auto msg_info = std::make_shared(msgtype, text_or_url, preview_pix, unique_name, total_size, md5); + list.append(msg_info); + +} +``` + +将消息插入到消息列表,第一个参数是可选择的,有时我们需要将消息插入到全局消息列表。有时需要将消息插入到资源消息列表。 + +比如当我们拖动一个多媒体资源到富文本编辑框的时候,就是将这个资源的信息插入到资源消息列表。 + +当我们汇总所有的消息,用来发送的时候,就需要将消息添加到全局消息列表。 + +## 图片气泡框 + +![image-20251115152713630](https://cdn.llfc.club/img/image-20251115152713630.png) + + + +**声明** + +``` cpp +class PictureBubble : public BubbleFrame +{ + Q_OBJECT +public: + PictureBubble(const QPixmap &picture, ChatRole role, QWidget *parent = nullptr); +}; +``` + +**具体实现** + +``` cpp +#include "PictureBubble.h" +#include + + +#define PIC_MAX_WIDTH 160 +#define PIC_MAX_HEIGHT 90 + +PictureBubble::PictureBubble(const QPixmap &picture, ChatRole role, QWidget *parent) + :BubbleFrame(role, parent) +{ + QLabel *lb = new QLabel(); + lb->setScaledContents(true); + QPixmap pix = picture.scaled(QSize(PIC_MAX_WIDTH, PIC_MAX_HEIGHT), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + lb->setPixmap(pix); + this->setWidget(lb); + + int left_margin = this->layout()->contentsMargins().left(); + int right_margin = this->layout()->contentsMargins().right(); + int v_margin = this->layout()->contentsMargins().bottom(); + setFixedSize(pix.width()+left_margin + right_margin, pix.height() + v_margin *2); +} +``` + +## 图片聊天消息 + +**实现** + +``` cpp +class ImgChatData : public ChatDataBase { +public: + ImgChatData(std::shared_ptr msg_info, QString unique_id, + int thread_id, ChatFormType form_type, ChatMsgType msg_type, + int send_uid, int status, QString chat_time = ""): + ChatDataBase(unique_id,thread_id, form_type, msg_type, msg_info->_text_or_url, + send_uid, status, chat_time), _msg_info(msg_info){ + + } + + std::shared_ptr _msg_info; +}; + +Q_DECLARE_METATYPE(std::shared_ptr) +``` + +## 发送消息逻辑 + +![image-20251115154431242](https://cdn.llfc.club/img/image-20251115154431242.png) + + + +修改发送消息的逻辑,发送图片时,需要将之前的文本消息发送出去,再发送图片 + +``` cpp +void ChatPage::on_send_btn_clicked() { + if (_chat_data == nullptr) { + qDebug() << "friend_info is empty"; + return; + } + + auto user_info = UserMgr::GetInstance()->GetUserInfo(); + auto pTextEdit = ui->chatEdit; + ChatRole role = ChatRole::Self; + QString userName = user_info->_name; + QString userIcon = user_info->_icon; + + const QVector>& msgList = pTextEdit->getMsgList(); + QJsonObject textObj; + QJsonArray textArray; + int txt_size = 0; + auto thread_id = _chat_data->GetThreadId(); + for (int i = 0; i < msgList.size(); ++i) + { + //消息内容长度不合规就跳过 + if (msgList[i]->_text_or_url.length() > 1024) { + continue; + } + + MsgType type = msgList[i]->_msg_type; + ChatItemBase* pChatItem = new ChatItemBase(role); + pChatItem->setUserName(userName); + SetSelfIcon(pChatItem, user_info->_icon); + QWidget* pBubble = nullptr; + //生成唯一id + QUuid uuid = QUuid::createUuid(); + //转为字符串 + QString uuidString = uuid.toString(); + if (type == MsgType::TEXT_MSG) + { + pBubble = new TextBubble(role, msgList[i]->_text_or_url); + if (txt_size + msgList[i]->_text_or_url.length() > 1024) { + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + //将bubble和uid绑定,以后可以等网络返回消息后设置是否送达 + //_bubble_map[uuidString] = pBubble; + txt_size += msgList[i]->_text_or_url.length(); + QJsonObject obj; + QByteArray utf8Message = msgList[i]->_text_or_url.toUtf8(); + auto content = QString::fromUtf8(utf8Message); + obj["content"] = content; + obj["unique_id"] = uuidString; + textArray.append(obj); + //todo... 注意,此处先按私聊处理 + auto txt_msg = std::make_shared(uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, content, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString, txt_msg); + } + else if (type == MsgType::IMG_MSG) + { + //将之前缓存的文本发送过去 + if (txt_size) { + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + pBubble = new PictureBubble(QPixmap(msgList[i]->_text_or_url), role); + //需要组织成文件发送,具体参考头像上传 + auto img_msg = std::make_shared(msgList[i],uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString, img_msg); + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["md5"] = msgList[i]->_md5; + textObj["name"] = msgList[i]->_unique_name; + textObj["token"] = UserMgr::GetInstance()->GetToken(); + textObj["unique_id"] = uuidString; + //文件信息加入管理 + UserMgr::GetInstance()->AddTransFile(msgList[i]->_unique_name, msgList[i]); + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_IMG_CHAT_MSG_REQ, jsonData); + } + else if (type == MsgType::FILE_MSG) + { + + } + //发送消息 + if (pBubble != nullptr) + { + pChatItem->setWidget(pBubble); + pChatItem->setStatus(0); + ui->chat_data_list->appendChatItem(pChatItem); + _unrsp_item_map[uuidString] = pChatItem; + } + + } + + qDebug() << "textArray is " << textArray; + //发送给服务器 + textObj["text_array"] = textArray; + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); +} + +``` + +## 接收服务器返回 + +先注册消息,用于跨线程调用 + +``` cpp +void TcpMgr::registerMetaType() { + // 注册所有自定义类型 + qRegisterMetaType("ServerInfo"); + qRegisterMetaType("SearchInfo"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AddFriendApply"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("ApplyInfo"); + + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("AuthRsp"); + qRegisterMetaType>("std::shared_ptr"); + + qRegisterMetaType("UserInfo"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>>("std::vector>"); + + qRegisterMetaType>("std::shared_ptr"); + qRegisterMetaType("ReqId"); + qRegisterMetaType>("std::shared_ptr"); +} +``` + +注册消息 + +``` cpp +void TcpMgr::initHandlers() +{ + _handlers.insert(ID_IMG_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto unique_id = jsonObj["unique_id"].toString(); + auto unique_name = jsonObj["unique_name"].toString(); + + auto sender = jsonObj["fromuid"].toInt(); + auto msg_id = jsonObj["message_id"].toInt(); + QString chat_time = jsonObj["chat_time"].toString(); + int status = jsonObj["status"].toInt(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + + auto chat_data = std::make_shared(file_info, unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, sender, status, chat_time); + + //发送信号通知界面 + emit sig_chat_img_rsp(thread_id, chat_data); + }); + +} +``` + +## 服务器接收图片消息 + +先注册消息 + +``` cpp +void LogicSystem::RegisterCallBacks() { + + _fun_callbacks[ID_LOAD_CHAT_MSG_REQ] = std::bind(&LogicSystem::LoadChatMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); + + _fun_callbacks[ID_IMG_CHAT_MSG_REQ] = std::bind(&LogicSystem::DealChatImgMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); +} +``` + +处理聊天中的图片消息 + +``` cpp +void LogicSystem::DealChatImgMsg(std::shared_ptr session, + const short& msg_id, const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto uid = root["fromuid"].asInt(); + auto touid = root["touid"].asInt(); + + auto md5 = root["md5"].asString(); + auto unique_name = root["name"].asString(); + auto token = root["token"].asString(); + auto unique_id = root["unique_id"].asString(); + auto chat_time = root["chat_time"].asString(); + auto status = root["status"].asInt(); + + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + + rtvalue["fromuid"] = uid; + rtvalue["touid"] = touid; + auto thread_id = root["thread_id"].asInt(); + rtvalue["thread_id"] = thread_id; + rtvalue["md5"] = md5; + rtvalue["unique_name"] = unique_name; + rtvalue["unique_id"] = unique_id; + rtvalue["chat_time"] = chat_time; + rtvalue["status"] = status; + + auto timestamp = getCurrentTimestamp(); + auto chat_msg = std::make_shared(); + chat_msg->chat_time = timestamp; + chat_msg->sender_id = uid; + chat_msg->recv_id = touid; + chat_msg->unique_id = unique_id; + chat_msg->thread_id = thread_id; + chat_msg->content = unique_name; + chat_msg->status = MsgStatus::UN_UPLOAD; + + + //插入数据库 + MysqlMgr::GetInstance()->AddChatMsg(chat_msg); + + Defer defer([this, &rtvalue, session]() { + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_MSG_RSP); + }); + + //发送通知 todo... 以后等文件上传完成再通知 +} +``` + +## 聊天资源断点续传 + +![image-20251114211632712](https://cdn.llfc.club/img/image-20251114211632712.png) + +之前我们实现了1和2,接下来在客户端Client收到ChatServer的回复消息2后,需要执行步骤3 + +这期间要在客户端和服务器之间实现断点续传。 + +### 发送资源 + +``` cpp + _handlers.insert(ID_IMG_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto unique_id = jsonObj["unique_id"].toString(); + auto unique_name = jsonObj["unique_name"].toString(); + + auto sender = jsonObj["fromuid"].toInt(); + auto msg_id = jsonObj["message_id"].toInt(); + QString chat_time = jsonObj["chat_time"].toString(); + int status = jsonObj["status"].toInt(); + auto text_or_url = jsonObj["text_or_url"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + + auto chat_data = std::make_shared(file_info, unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, sender, status, chat_time); + + //发送信号通知界面 + emit sig_chat_img_rsp(thread_id, chat_data); + + //创建QFileInfo 对象 todo 留作以后收到服务器返回消息后再发送 + QFile file(file_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + file.seek(file_info->_current_size); + auto buffer = file.read(MAX_FILE_LEN); + qDebug() << "buffer is " << buffer; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + QJsonObject file_obj; + file_obj["name"] = file_info->_unique_name; + file_obj["unique_id"] = unique_id; + file_obj["seq"] = file_info->_seq; + file_info->_current_size = buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN; + file_obj["trans_size"] = file_info->_current_size; + file_obj["total_size"] = file_info->_total_size; + file_obj["token"] = UserMgr::GetInstance()->GetToken(); + file_obj["md5"] = file_info->_md5; + file_obj["uid"] = UserMgr::GetInstance()->GetUid(); + file_obj["data"] = base64Data; + + if (buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN >= file_info->_total_size) { + file_obj["last"] = 1; + } + else { + file_obj["last"] = 0; + } + + //发送文件 todo 留作以后收到服务器返回消息后再发送 + QJsonDocument doc_file(file_obj); + QByteArray fileData = doc_file.toJson(QJsonDocument::Compact); + + //发送消息给ResourceServer + FileTcpMgr::GetInstance()->SendData(ReqId::ID_IMG_CHAT_UPLOAD_REQ, fileData); + + }); +``` + +我们的客户端在收到服务器的回复(步骤2)之后,立刻读取文件,发送第一个包,这里通过`FileTcpMgr`发送资源给`ResourceServer` + +### 资源服务器存储 + +我们实现断点续传,在`LogicWorker`中注册处理逻辑 + +``` cpp +void LogicWorker::RegisterCallBacks() +{ + _fun_callbacks[ID_IMG_CHAT_UPLOAD_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_UPLOAD_RSP); + }; + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_UPLOAD_HEAD_ICON_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_IMG_CHAT_UPLOAD_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + }; +} +``` + +1. 通过callback存储回调函数,一同包裹进`FileInfo`, 回调函数通过`=`捕获所有局部变量,这样构造了一个伪闭包。 +2. 我们将包裹好的`FileInfo`投递到`FileSystem`中,交给其中的线程池,由多个`FileWorker`线程处理 + +我们跟进`FileSystem`的投递逻辑 + +``` cpp +void FileSystem::PostMsgToQue(shared_ptr msg, int index) +{ + _file_workers[index]->PostTask(msg); +} +``` + +`FileWorker`投递逻辑 + +``` cpp +void FileWorker::PostTask(std::shared_ptr task) +{ + { + std::lock_guard lock(_mtx); + //借鉴python万物皆对象思想,构造伪闭包将函数对象扔到队列中 + _task_que.push([task, this]() { + task_callback(task); + }); + } + + _cv.notify_one(); +} +``` + +我们将任务直接包裹到一个`lambda`表达式中,利用python万物皆对象的思想,结合C++语法,将这个可调用对象投递给队列。 + +将来可调用对象从队列取出后就会调用这个`lambda`表达式, 进而调用`task_callback`函数 + +``` cpp +FileWorker::FileWorker() :_b_stop(false) +{ + RegisterHandlers(); + _work_thread = std::thread([this]() { + while (!_b_stop) { + std::unique_lock lock(_mtx); + _cv.wait(lock, [this]() { + if (_b_stop) { + return true; + } + + if (_task_que.empty()) { + return false; + } + + return true; + }); + + if (_b_stop) { + break; + } + + auto task_call = _task_que.front(); + _task_que.pop(); + task_call(); + } + + }); +} +``` + +调用逻辑 + +``` cpp +void FileWorker::task_callback(std::shared_ptr task) +{ + auto iter = _handlers.find(task->_msg_id); + if (iter == _handlers.end()) { + return; + } + + iter->second(task); +} +``` + +从`_handlers`中根据消息id检索,取出回调函数,传入`task`参数调用 + +`_handlers`的注册逻辑 + +``` cpp +void FileWorker::RegisterHandlers() +{ + //处理头像上传 + _handlers[ID_UPLOAD_HEAD_ICON_REQ] = [this](std::shared_ptr task) { + // 解码 + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (task->_seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "文件已成功保存为: " << task->_name << std::endl; + //更新头像 + MysqlMgr::GetInstance()->UpdateUserIcon(task->_uid, filename); + //获取用户信息 + auto user_info = MysqlMgr::GetInstance()->GetUser(task->_uid); + if (user_info == nullptr) { + return; + } + + //将数据库内容写入redis缓存 + Json::Value redis_root; + redis_root["uid"] = task->_uid; + redis_root["pwd"] = user_info->pwd; + redis_root["name"] = user_info->name; + redis_root["email"] = user_info->email; + redis_root["nick"] = user_info->nick; + redis_root["desc"] = user_info->desc; + redis_root["sex"] = user_info->sex; + redis_root["icon"] = user_info->icon; + std::string base_key = USER_BASE_INFO + std::to_string(task->_uid); + RedisMgr::GetInstance()->Set(base_key, redis_root.toStyledString()); + } + + if (task->_callback) { + task->_callback(result); + } + }; + + //处理聊天图片上传 + _handlers[ID_IMG_CHAT_UPLOAD_REQ] = [this](std::shared_ptr task) { + // 解码 + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (task->_seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "文件已成功保存为: " << task->_name << std::endl; + //todo...更新数据库聊天图像上传状态 + //通过grpc通知ChatServer + } + + if (task->_callback) { + task->_callback(result); + } + }; +} +``` + +比如是聊天图片上传的请求,就调用如下 + +``` cpp +_handlers[ID_IMG_CHAT_UPLOAD_REQ] = [this](std::shared_ptr task) { + // 解码 + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (task->_seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "文件已成功保存为: " << task->_name << std::endl; + //todo...更新数据库聊天图像上传状态 + //通过grpc通知ChatServer + } + + if (task->_callback) { + task->_callback(result); + } + }; +``` + +在这个逻辑里我们打开文件,并采取追加的方式将数据写入服务器所在的磁盘目录保存 + +### 测试效果 + +![image-20251123112409697](https://cdn.llfc.club/img/image-20251123112409697.png) + + + +![image-20251123112343094](https://cdn.llfc.club/img/image-20251123112343094.png) + +### 结论 + +1. 经过测试,可以实现断点续传上传聊天资源的功能 +2. 但是对于大文件,采用串行方式断点续传效率很慢 +3. 考虑搞一个拥塞窗口多序列传输,本质上还是通过网络线程串行上传,但不是等待服务器回复后才上传,而是通过一个拥塞窗口控制发送频率。 + +## 设计拥塞窗口提高发送效率 + +### 思路分析 + +**客户端发送端单线程还是多线程** + +本质上客户端如果采用切片的方式将一个文件切割为多个小文件,可以不考虑顺序,将来汇总服务器的回包统计是否传输完成即可。 + +但是对于同一个`socket`多线程调用`send`会产生数据错乱,对于`asio`这种网络库,我们采用的是发送队列控制顺序,保证互斥性,一个包发送完成再发送下一个。 + +对于`QT`其底层封装了发送队列,支持多线程并发调用`send`,但是本质上底层的发送还是很串行化。 + +所以对于现有的结构,我们通过跨线程的方式,将要发送的数据投递给`FileMgr`所在的线程的消息队列,统一发送。 + +这个结构不用改。 + +**客户端发送逻辑修改** + +客户端不再等待服务器回包后再发送,而是将切割好的包一次性添加到发送队列。 + +但是如果文件过大,要几百个包,一次性会堆满队列,另外循环发送几百个包会造成网络拥塞,导致服务器一段时间只为这一个客户端服务,这是不可取的。 + +**拥塞窗口设计** + +为了解决这个问题,我们可以优先将要发送的数据放入拥塞窗口,处于拥塞窗口的数据优先发送 + +其余的数据投递到队列中。 + +如果文件数据过多,可以优先将一部分数据放入队列,等到队列队列大小缩小后继续放入数据。 + +当客户端收到服务器回包后,做错误判断,如果无误则从队列取出数据放到拥塞窗口中继续发送。 + +队列减小到一定阈值后,将文件剩余未发送的包继续填充到队列中。 + +![image-20251123115425162](https://cdn.llfc.club/img/image-20251123115425162.png) + +这么做还要考虑如果发送失败,就要清除队列中该次未发送的数据包。 + +如果发送两个文件,队列中的数据将会是交叉的。所以对于错误处理,要考虑剔除发送失败的包。 + +**数据结构设计:** + +```cpp +struct SendTask { + int file_id; // 文件唯一标识 + int chunk_id; // 分片序号 + int total_chunks; // 总分片数 + vector data; // 数据内容 + int retry_count; // 重试次数 +}; +``` + +**队列管理:** + +- 使用map>区分不同文件的数据包 +- 发送失败时,只清除对应file_id的所有待发送包 +- 维护已发送但未确认的包列表,便于超时重传 + +### 服务器逻辑 + +**服务器是多线程还是单线程** + +服务器可以采用多线程方式处理收到的文件包,可以采用多线程的方式写如文件,但是对于同一个文件要加锁。 + +本质上同一个时刻只有一个线程可以对文件进行读写。所以干脆就用一个线程负责一个文件的写,可以根据session_id区分不同的连接,对于同一个连接采用同一个`FileWorker`执行写就可以了。 + +这样不用加锁还保证线程安全了。 + +![image-20251123123519059](https://cdn.llfc.club/img/image-20251123123519059.png) + +**服务器乱序存储** + +服务器不再用原来的线性方式将内容追加到磁盘上。 + +而是优先接收客户端的第一个包,获取文件信息,然后按照`seq`个数创建文件大小,在最后一个字节写入空,这样整个空文件就构造好了。 + +![image-20251123122259919](https://cdn.llfc.club/img/image-20251123122259919.png) + + + +然后服务器每次接收到客户端的乱序序列后,将内容写入对应的偏移位置。并且回复客户端,将序列号和文件基本信息回复给客户端。 + +![image-20251123122429328](https://cdn.llfc.club/img/image-20251123122429328.png) + +## 客户端实现拥塞窗口 + +### 窗口大小成员 + +在`FileTcpMgr`中添加成员变量 + +``` cpp +class FileTcpMgr : public QObject, public Singleton, + public std::enable_shared_from_this{ + + //发送的拥塞窗口,控制发送数量 + int _cwnd_size; +} +``` + +### 封装发送逻辑 + +``` cpp +class FileTcpMgr : public QObject, public Singleton, + public std::enable_shared_from_this +{ + Q_OBJECT +public: + void BatchSend(std::shared_ptr msg_info); +} +``` + +具体实现 + +``` cpp +void FileTcpMgr::BatchSend(std::shared_ptr msg_info) { + + if ((msg_info->_seq) * MAX_FILE_LEN >= msg_info->_total_size) { + qDebug() << "file has sent finished"; + return; + } + + if (MAX_CWND_SIZE - _cwnd_size == 0) { + return; + } + + //打开 + QFile file(msg_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(msg_info->_seq * MAX_FILE_LEN); + + bool b_last = false; + //再次组织数据发送 + for (; MAX_CWND_SIZE - _cwnd_size > 0; ) { + + QByteArray buffer; + msg_info->_seq++; + //放入发送未回包集合 + msg_info->_flighting_seqs.insert(msg_info->_seq); + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = msg_info->_md5; + sendObj["name"] = msg_info->_unique_name; + sendObj["seq"] = msg_info->_seq; + sendObj["trans_size"] = buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN; + sendObj["total_size"] = msg_info->_total_size; + + b_last = false; + if (buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN >= msg_info->_total_size) { + sendObj["last"] = 1; + b_last = true; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = msg_info->_max_seq; + sendObj["uid"] = UserMgr::GetInstance()->GetUid(); + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + //直接发送,其实是放入tcpmgr发送队列 + SendData(ID_IMG_CHAT_UPLOAD_REQ, send_data); + _cwnd_size++; + //如果 + if (b_last) { + break; + } + } + + file.close(); +} +``` + +### 同步发送信息 + +考虑以后很多场景都会将发送信息同步给服务器,所以单独抽象了一个发送协议 + +在`TcpMgr`收到聊天消息回复后,可以考虑先将图片信息同步给资源服务器 + +``` cpp + _handlers.insert(ID_IMG_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto unique_id = jsonObj["unique_id"].toString(); + auto unique_name = jsonObj["unique_name"].toString(); + + auto sender = jsonObj["fromuid"].toInt(); + auto msg_id = jsonObj["message_id"].toInt(); + QString chat_time = jsonObj["chat_time"].toString(); + int status = jsonObj["status"].toInt(); + auto text_or_url = jsonObj["text_or_url"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + + auto chat_data = std::make_shared(file_info, unique_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, sender, status, chat_time); + + //发送信号通知界面 + emit sig_chat_img_rsp(thread_id, chat_data); + + //管理消息,添加序列号到正在发送集合 + file_info->_flighting_seqs.insert(file_info->_seq); + + //发送消息 + QFile file(file_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file:" << file.errorString(); + return; + } + + file.seek(file_info->_current_size); + auto buffer = file.read(MAX_FILE_LEN); + qDebug() << "buffer is " << buffer; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + QJsonObject file_obj; + file_obj["name"] = file_info->_unique_name; + file_obj["unique_id"] = unique_id; + file_obj["seq"] = file_info->_seq; + file_info->_current_size = buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN; + file_obj["trans_size"] = file_info->_current_size; + file_obj["total_size"] = file_info->_total_size; + file_obj["token"] = UserMgr::GetInstance()->GetToken(); + file_obj["md5"] = file_info->_md5; + file_obj["uid"] = UserMgr::GetInstance()->GetUid(); + file_obj["data"] = base64Data; + + if (buffer.size() + (file_info->_seq - 1) * MAX_FILE_LEN >= file_info->_total_size) { + file_obj["last"] = 1; + } + else { + file_obj["last"] = 0; + } + + //发送文件 todo 留作以后收到服务器返回消息后再发送 + QJsonDocument doc_file(file_obj); + QByteArray fileData = doc_file.toJson(QJsonDocument::Compact); + + //发送消息给ResourceServer + FileTcpMgr::GetInstance()->SendData(ReqId::ID_FILE_INFO_SYNC_REQ, fileData); + + }); +``` + +### 处理同步信息回包 + +``` cpp + _handlers.insert(ID_FILE_INFO_SYNC_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败,将来可能断点重传等 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + //为了简单起见,先处理网络正常情况 + auto seq = recvObj["seq"].toInt(); + auto name = recvObj["name"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeTransFile(); + + return; + } + + BatchSend(file_info); + }); +``` + +之后的处理逻辑就和聊天图片上传一样,只是这个是一次上传多个。 + +有个更好的改进点就是不用等到服务器写完,服务器就回复给客户端,但是逻辑控制更复杂,如果后续写失败,还要回滚之类的,更麻烦。这里还是保留原逻辑,服务器写完就回复,只不过客户端不是等待回复后一个一个发送了,开始的时候是一起发送,用拥塞窗口控制。后续还是会收到限制,因为受限于服务器写,这次就先这样了,以后在考虑做优化。 + + + +### 响应资源回复 + +``` cpp + _handlers.insert(ID_IMG_CHAT_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeTransFile(); + BatchSend(free_file); + return; + } + + BatchSend(file_info); }); +``` + + + +## 服务器响应同步信息 + +``` cpp +_fun_callbacks[ID_FILE_INFO_SYNC_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + }; + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_FILE_INFO_SYNC_RSP); + return; + } + } + + + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_FILE_INFO_SYNC_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + }; +``` + +其余逻辑不变。 + +### 测试效果 + +![image-20251213174219570](https://cdn.llfc.club/img/image-20251213174219570.png) + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day40-\350\201\212\345\244\251\345\233\276\347\211\207\350\265\204\346\272\220\347\273\255\344\274\240\345\222\214\350\277\233\345\272\246\346\230\276\347\244\272.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day40-\350\201\212\345\244\251\345\233\276\347\211\207\350\265\204\346\272\220\347\273\255\344\274\240\345\222\214\350\277\233\345\272\246\346\230\276\347\244\272.md" new file mode 100644 index 0000000..e12969a --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day40-\350\201\212\345\244\251\345\233\276\347\211\207\350\265\204\346\272\220\347\273\255\344\274\240\345\222\214\350\277\233\345\272\246\346\230\276\347\244\272.md" @@ -0,0 +1,1100 @@ +--- +title: 聊天图片资源续传和进度显示 +date: 2026-01-02 08:22:03 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 增加上传可视化进度 + +之前我们传输图片的时候,只能通过服务器查看上传进度。客户端无法感知上传进度,所以考虑在图片传输基础上,显示上传进度。 + +### 封装可点击标签 + +``` cpp +#pragma once +#include +#include +#include + +class ClickableLabel : + public QLabel +{ + Q_OBJECT +public: + explicit ClickableLabel(QWidget* parent = nullptr); + void setIconOverlay(const QIcon& icon); //设置遮罩图标 + void showIconOverlay(bool show); //显示/隐藏遮罩图标 +protected: + void mousePressEvent(QMouseEvent* event) override; + void enterEvent(QEvent* event) override; + void leaveEvent(QEvent* event) override; + void paintEvent(QPaintEvent* event) override; + +signals: + void clicked(); + +private: + QIcon m_overlayIcon; + bool m_showOverlay; + bool m_hovered; +}; +``` + +具体实现 + +``` cpp +#include "ClickableLabel.h" +#include +#include +// ClickableLabel.cpp +ClickableLabel::ClickableLabel(QWidget* parent) + : QLabel(parent) + , m_showOverlay(false) + , m_hovered(false) +{ + setCursor(Qt::PointingHandCursor); + setMouseTracking(true); +} + +void ClickableLabel::mousePressEvent(QMouseEvent* event) +{ + if (event->button() == Qt::LeftButton) { + emit clicked(); + } + QLabel::mousePressEvent(event); +} + +void ClickableLabel::enterEvent(QEvent* event) +{ + m_hovered = true; + update(); + QLabel::enterEvent(event); +} + +void ClickableLabel::leaveEvent(QEvent* event) +{ + m_hovered = false; + update(); + QLabel::leaveEvent(event); +} + +void ClickableLabel::paintEvent(QPaintEvent* event) +{ + QLabel::paintEvent(event); + + if (m_showOverlay && !m_overlayIcon.isNull()) { + QPainter painter(this); + + // 绘制半透明遮罩 + if (m_hovered) { + painter.fillRect(rect(), QColor(0, 0, 0, 100)); + } + else { + painter.fillRect(rect(), QColor(0, 0, 0, 60)); + } + + // 绘制图标 + int iconSize = qMin(width(), height()) / 3; // 图标大小为图片的1/3 + QRect iconRect( + (width() - iconSize) / 2, + (height() - iconSize) / 2, + iconSize, + iconSize + ); + + m_overlayIcon.paint(&painter, iconRect); + } +} + +void ClickableLabel::setIconOverlay(const QIcon& icon) +{ + m_overlayIcon = icon; + update(); +} + +void ClickableLabel::showIconOverlay(bool show) +{ + m_showOverlay = show; + update(); +} +``` + +### 图片设置可点击和进度条 + +![image-20260102111204491](https://cdn.llfc.club/img/image-20260102111204491.png) + +在图片中添加可点击的标签,并且添加进度条 + +``` cpp +#ifndef PICTUREBUBBLE_H +#define PICTUREBUBBLE_H + +#include "BubbleFrame.h" +#include +#include +#include "ClickableLabel.h" +#include +#include "global.h" +class PictureBubble : public BubbleFrame +{ + Q_OBJECT +public: + + + PictureBubble(const QPixmap& picture, ChatRole role,int total, QWidget* parent = nullptr); + + void setProgress(int value); + void showProgress(bool show); + void setState(TransferState state); + void resumeState(); + void setMsgInfo(std::shared_ptr msg); + TransferState state() const { return m_state; } + +signals: + void pauseRequested(QString unique_name, TransferType transfer_type); // 请求暂停 + void resumeRequested(QString unique_name, TransferType transfer_type); // 请求继续 + void cancelRequested(QString unique_name, TransferType transfer_type); // 请求取消 + +private slots: + void onPictureClicked(); + +private: + void updateIconOverlay(); + void adjustSize(); + +private: + ClickableLabel* m_picLabel; + QProgressBar* m_progressBar; + TransferState m_state; + + QIcon m_pauseIcon; + QIcon m_playIcon; + QIcon m_downloadIcon; + QSize m_pixmapSize; + QVBoxLayout* m_vLayout; + int m_total_size; + std::shared_ptr _msg_info; +}; + +#endif // PICTUREBUBBLE_H + +``` + +构造函数里添加进度条和样式。 + +``` cpp +PictureBubble::PictureBubble(const QPixmap &picture, ChatRole role, int total, QWidget *parent) + :BubbleFrame(role, parent), m_state(TransferState::None), m_total_size(total) +{ + // 加载图标(使用Qt内置图标或自定义图标) + m_pauseIcon = style()->standardIcon(QStyle::SP_MediaPause); + m_playIcon = style()->standardIcon(QStyle::SP_MediaPlay); + m_downloadIcon = style()->standardIcon(QStyle::SP_ArrowDown); + + // 创建容器 + QWidget* container = new QWidget(); + m_vLayout = new QVBoxLayout(container); + m_vLayout->setContentsMargins(0, 0, 0, 0); + m_vLayout->setSpacing(5); + + + // 创建可点击的图片标签 + m_picLabel = new ClickableLabel(); + m_picLabel->setScaledContents(true); + QPixmap pix = picture.scaled(QSize(PIC_MAX_WIDTH, PIC_MAX_HEIGHT), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + m_pixmapSize = pix.size(); + m_picLabel->setPixmap(pix); + m_picLabel->setFixedSize(pix.size()); + + connect(m_picLabel, &ClickableLabel::clicked, + this, &PictureBubble::onPictureClicked); + + // 创建进度条 + m_progressBar = new QProgressBar(); + m_progressBar->setFixedWidth(pix.width()); + m_progressBar->setFixedHeight(10); + m_progressBar->setRange(0, 100); + m_progressBar->setValue(0); + m_progressBar->setTextVisible(true); + setState(TransferState::None); + + // 样式美化 + m_progressBar->setStyleSheet( + "QProgressBar {" + " border: 1px solid #ccc;" + " border-radius: 3px;" + " text-align: center;" + " background-color: #f0f0f0;" + " font-size: 10px;" + "}" + "QProgressBar::chunk {" + " background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, " + " stop:0 #4CAF50, stop:1 #45a049);" + " border-radius: 2px;" + "}" + ); + + m_vLayout->addWidget(m_picLabel); + m_vLayout->addWidget(m_progressBar); + this->setWidget(container); + adjustSize(); +} +``` + +设置传输状态为None,进度条初始值为0 + +调整界面设置,将图片拉伸包括进度条 + +``` cpp +void PictureBubble::adjustSize() +{ + int left_margin = this->layout()->contentsMargins().left(); + int right_margin = this->layout()->contentsMargins().right(); + int v_margin = this->layout()->contentsMargins().bottom(); + + int width = m_pixmapSize.width() + left_margin + right_margin; + int height = m_pixmapSize.height() + v_margin * 2; + + if (m_progressBar->isHidden() == false) { + height += m_progressBar->height() + m_vLayout->spacing(); + } + + setFixedSize(width, height); +} +``` + +封装设置进度函数 + +``` cpp +void PictureBubble::setProgress(int value) +{ + float percent = (value / (m_total_size*1.0))*100; + m_progressBar->setValue(percent); + if (percent >= 100) { + setState(TransferState::Completed); + } +} +``` + +展示进度条 + +``` cpp +void PictureBubble::showProgress(bool show) +{ + m_progressBar->show(); + adjustSize(); +} +``` + +当传输停止后,点击后会恢复,恢复传输或者下载状态,逻辑如下 + +``` cpp +void PictureBubble::resumeState() { + if (_msg_info->_transfer_type == TransferType::Download) { + _msg_info->_transfer_state = TransferState::Downloading; + m_state = TransferState::Downloading; + updateIconOverlay(); + return; + } + + if (_msg_info->_transfer_type == TransferType::Upload) { + _msg_info->_transfer_state = TransferState::Uploading; + m_state = TransferState::Uploading; + updateIconOverlay(); + return; + } +} +``` + +设置状态逻辑如下, 状态分为None,下载,上传,暂停,传输完成,传输失败等。 + +``` cpp +void PictureBubble::setState(TransferState state) +{ + m_state = state; + if (_msg_info) { + _msg_info->_transfer_state = state; + } + + updateIconOverlay(); + + // 根据状态显示/隐藏进度条 + switch (state) { + case TransferState::Downloading: + case TransferState::Uploading: + case TransferState::Paused: + showProgress(true); + break; + case TransferState::Completed: + // 完成后延迟隐藏进度条 + QTimer::singleShot(1000, this, [this]() { + showProgress(false); + }); + break; + case TransferState::None: + case TransferState::Failed: + showProgress(false); + break; + } +} +``` + +为了更好的控制传输逻辑,将`std::shared_ptr`作为成员变量设置给`PictureBubble` + +这样在点击图片后,可以发送图片关联的消息`id`和`unique_name` + +点击图片触发槽函数 + +``` cpp +void PictureBubble::onPictureClicked() +{ + switch (m_state) { + case TransferState::Downloading: + case TransferState::Uploading: + // 暂停 + setState(TransferState::Paused); + emit pauseRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Paused: + // 继续 + resumeState(); // + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Failed: + // 重试 + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + default: + // 其他状态可以实现查看大图等功能 + break; + } +} + +``` + +根据状态发送不同的信号,如果是下载或者暂停状态,则发送暂停信号。 + +如果是暂停状态,则发送继续下载或者继续上传状态。 + +``` cpp +void PictureBubble::updateIconOverlay() +{ + switch (m_state) { + case TransferState::Downloading: + case TransferState::Uploading: + m_picLabel->setIconOverlay(m_pauseIcon); + m_picLabel->showIconOverlay(true); + break; + + case TransferState::Paused: + m_picLabel->setIconOverlay(m_playIcon); + m_picLabel->showIconOverlay(true); + break; + + case TransferState::Failed: + m_picLabel->setIconOverlay(m_downloadIcon); // 或重试图标 + m_picLabel->showIconOverlay(true); + break; + + default: + m_picLabel->showIconOverlay(false); + break; + } +} +``` + +### 链接状态信号 + +在`ChatPage`的构造函数中添加信号和槽函数链接 + +``` cpp +//链接暂停信号 +connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); +//链接恢复信号 +connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); +``` + +槽函数中设置文件为暂停状态 + +``` cpp +void ChatPage::on_clicked_paused(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->PauseTransFileByName(unique_name); +} +``` + +槽函数中设置为续传或者下载状态,并且调用`FileMgr`续传之前未传递完成的内容 + +``` cpp +void ChatPage::on_clicked_resume(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->ResumeTransFileByName(unique_name); + //继续发送或者下载 + if (transfer_type == TransferType::Upload) { + FileTcpMgr::GetInstance()->ContinueUploadFile(unique_name); + return; + } + + if (transfer_type == TransferType::Download) { + return; + } +} +``` + +### 续传逻辑 + +`FileTcpMgr`发送信号`sig_continue_upload_file`, 这么做的好处是,发送信号的线程和接收信号的线程不一致,也可以跨线程调用。 + +``` cpp +void FileTcpMgr::ContinueUploadFile(QString unique_name) { + emit sig_continue_upload_file(unique_name); +} +``` + +在`FileTcpMgr`中链接了这个信号 + +``` cpp + //链接续传信号 + QObject::connect(this, &FileTcpMgr::sig_continue_upload_file, this, &FileTcpMgr::slot_continue_upload_file); +``` + +槽函数`slot_continue_upload_file` + +``` cpp +void FileTcpMgr::slot_continue_upload_file(QString unique_name) { + auto msg_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + if (msg_info == nullptr) { + return; + } + //将待发送序列号更新为已经确认接收的序列号,然后基于此序列号再递增。 + msg_info->_seq = msg_info->_last_confirmed_seq; + + if ((msg_info->_seq) * MAX_FILE_LEN >= msg_info->_total_size) { + qDebug() << "file has sent finished"; + return; + } + + if (MAX_CWND_SIZE - _cwnd_size == 0) { + return; + } + + //打开 + QFile file(msg_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(msg_info->_seq * MAX_FILE_LEN); + + bool b_last = false; + //再次组织数据发送 + for (; MAX_CWND_SIZE - _cwnd_size > 0; ) { + + QByteArray buffer; + msg_info->_seq++; + //放入发送未回包集合 + msg_info->_flighting_seqs.insert(msg_info->_seq); + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = msg_info->_md5; + sendObj["name"] = msg_info->_unique_name; + sendObj["seq"] = msg_info->_seq; + msg_info->_current_size = buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN; + sendObj["trans_size"] = msg_info->_current_size; + sendObj["total_size"] = msg_info->_total_size; + + b_last = false; + if (buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN >= msg_info->_total_size) { + sendObj["last"] = 1; + b_last = true; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = msg_info->_max_seq; + sendObj["uid"] = UserMgr::GetInstance()->GetUid(); + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + //直接发送,其实是放入tcpmgr发送队列 + SendData(ID_IMG_CHAT_CONTINUE_UPLOAD_REQ, send_data); + _cwnd_size++; + //如果 + if (b_last) { + break; + } + } + + file.close(); +} +``` + +`ID_IMG_CHAT_CONTINUE_UPLOAD_REQ`为断点续传请求 + +``` cpp + ID_IMG_CHAT_CONTINUE_UPLOAD_REQ = 1043, //续传聊天图片资源请求 + ID_IMG_CHAT_CONTINUE_UPLOAD_RSP = 1044, //续传聊天图片资源回复 +``` + +### 响应续传回复 + +``` cpp + _handlers.insert(ID_IMG_CHAT_CONTINUE_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file); + return; + } + + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + + //发送信号,更新图片上传进度 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info); }); +``` + +`sig_update_upload_progress`信号为更新进度,因为在接收到服务器回包前,文件状态可能被设置为暂停,所以要判断一下文件状态是否为暂停,如果为暂停,则不发送后续内容。否则直接发送后续内容。 + +`sig_update_upload_progress`信号,也会在正常上传服务器,服务器回复给客户端时,客户端发送 + +比如上传图片信息回复逻辑里 + +``` cpp +_handlers.insert(ID_IMG_CHAT_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file); + return; + } + + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + + //发送信号,更新图片上传进度 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info); }); + + _handlers.insert(ID_IMG_CHAT_CONTINUE_UPLOAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + _cwnd_size--; + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + auto name = recvObj["name"].toString(); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + auto md5 = file_info->_md5; + auto seq = recvObj["seq"].toInt(); + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file); + return; + } + + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + + //发送信号,更新图片上传进度 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info); }); +} + +``` + +同步信息回复也会发送进度上传信号 + +``` cpp + _handlers.insert(ID_FILE_INFO_SYNC_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject recvObj = jsonDoc.object(); + qDebug() << "data jsonobj is " << recvObj; + + if (!recvObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "icon upload_failed, err is Json Parse Err" << err; + //todo ... 提示上传失败,将来可能断点重传等 + //emit upload_failed(); + return; + } + + int err = recvObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "Login Failed, err is " << err; + //emit upload_failed(); + return; + } + + //为了简单起见,先处理网络正常情况 + auto seq = recvObj["seq"].toInt(); + auto name = recvObj["name"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (!file_info) { + return; + } + + //根据seq从未接收集合移动到已接收集合中 + file_info->_flighting_seqs.erase(seq); + //将seq放入已收到集合中 + file_info->_rsp_seqs.insert(seq); + + //计算当前最后确认的序列号 + while (file_info->_rsp_seqs.count(file_info->_last_confirmed_seq + 1)) { + ++file_info->_last_confirmed_seq; + } + + qDebug() << "recv : " << name << "file seq is " << seq; + //判断最大序列和最后确认序列号相等,说明收全了 + if (file_info->_last_confirmed_seq == file_info->_max_seq) { + //更新已经传输的文件大小 + file_info->_rsp_size = file_info->_total_size; + //通知界面显示 + emit sig_update_upload_progress(file_info); + UserMgr::GetInstance()->RmvTransFileByName(name); + //todo 此处添加发送其他待发送的文件 + auto free_file = UserMgr::GetInstance()->GetFreeUploadFile(); + if (free_file == nullptr) { + return; + } + BatchSend(free_file); + return; + } + //更新已经传输的文件大小 + file_info->_rsp_size = (file_info->_last_confirmed_seq) * MAX_FILE_LEN; + //通知界面显示 + emit sig_update_upload_progress(file_info); + //如果传输状态不为上传,则直接返回。 + if (!UserMgr::GetInstance()->TransFileIsUploading(name)) { + return; + } + BatchSend(file_info); + }); + +``` + +在`ChatPage`中链接进度上传信号和槽函数 + +``` cpp + //接收tcp返回的上传进度信息 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_update_upload_progress, + this, &ChatDialog::slot_update_upload_progress); +``` + +接收进度上传信号 + +``` cpp +void ChatDialog::slot_update_upload_progress(std::shared_ptr msg_info) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(msg_info->_thread_id); + if (chat_data == nullptr) { + return; + } + + //更新消息,其实不用更新,都是共享msg_info的一块内存,这里为了安全还是再次更新下 + + chat_data->UpdateProgress(msg_info); + + if (_cur_chat_thread_id != msg_info->_thread_id) { + return; + } + + + //更新聊天界面信息 + ui->chat_page->UpdateFileProgress(msg_info); +} +``` + +调用`ChatPage`的`UpdateFileProgress`函数 + +``` cpp +void ChatPage::UpdateFileProgress(std::shared_ptr msg_info) { + auto iter = _base_item_map.find(msg_info->_msg_id); + if (iter == _base_item_map.end()) { + return; + } + + if (msg_info->_msg_type == MsgType::IMG_MSG) { + auto bubble = iter.value()->getBubble(); + PictureBubble* pic_bubble = dynamic_cast(bubble); + pic_bubble->setProgress(msg_info->_rsp_size); + } +} +``` + +根据消息类型为图片,则调用`PictureBubble`更新图片进度 + + + +## 服务器 + +`ResoureServer`服务器要响应断点续传请求 + +`LogicWorker`注册消息处理 + +``` cpp +_fun_callbacks[ID_IMG_CHAT_CONTINUE_UPLOAD_REQ] = [this](shared_ptr session, const short& msg_id, + const string& msg_data) { + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + auto md5 = root["md5"].asString(); + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size = root["total_size"].asInt(); + auto trans_size = root["trans_size"].asInt(); + auto last = root["last"].asInt(); + auto file_data = root["data"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto uid = root["uid"].asInt(); + //转化为字符串 + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / uid_str / name).string(); + Json::Value rtvalue; + + auto callback = [=](const Json::Value& result) { + + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["total_size"] = total_size; + rtvalue["seq"] = seq; + rtvalue["name"] = name; + rtvalue["trans_size"] = trans_size; + rtvalue["last"] = last; + rtvalue["md5"] = md5; + rtvalue["uid"] = uid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + }; + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % FILE_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + //第一个包 + if (seq == 1) { + //构造数据存储 + auto file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = name; + file_info->_seq = seq; + file_info->_total_size = total_size; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + } + else { + auto file_info = RedisMgr::GetInstance()->GetFileInfo(name); + if (file_info == nullptr) { + rtvalue["error"] = ErrorCodes::FileNotExists; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + file_info->_seq = seq; + file_info->_trans_size = trans_size; + bool success = RedisMgr::GetInstance()->SetFileInfo(name, file_info); + if (!success) { + rtvalue["error"] = ErrorCodes::FileSaveRedisFailed; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_CONTINUE_UPLOAD_RSP); + return; + } + } + FileSystem::GetInstance()->PostMsgToQue( + std::make_shared(session, ID_IMG_CHAT_CONTINUE_UPLOAD_REQ, uid, file_path_str, name, seq, total_size, + trans_size, last, file_data, callback), + index + ); + }; +``` + +在`FileWorker`响应图片上传逻辑 + +``` cpp +//处理续传图片请求 + _handlers[ID_IMG_CHAT_CONTINUE_UPLOAD_REQ] = [this](std::shared_ptr task) { + // 解码 + std::string decoded = base64_decode(task->_file_data); + + auto file_path_str = task->_path; + auto last = task->_last; + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + boost::filesystem::path dir_path = file_path.parent_path(); + // 获取完整文件名(包含扩展名) + std::string filename = file_path.filename().string(); + Json::Value result; + result["error"] = ErrorCodes::Success; + + // Check if directory exists, if not, create it + if (!boost::filesystem::exists(dir_path)) { + if (!boost::filesystem::create_directories(dir_path)) { + std::cerr << "Failed to create directory: " << dir_path.string() << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + } + + + std::ofstream outfile; + //第一个包 + if (task->_seq == 1) { + // 打开文件,如果存在则清空,不存在则创建 + outfile.open(file_path_str, std::ios::binary | std::ios::trunc); + } + else { + // 保存为文件 + outfile.open(file_path_str, std::ios::binary | std::ios::app); + } + + + if (!outfile) { + std::cerr << "无法打开文件进行写入。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.write(decoded.data(), decoded.size()); + if (!outfile) { + std::cerr << "写入文件失败。" << std::endl; + result["error"] = ErrorCodes::FileWritePermissionFailed; + task->_callback(result); + return; + } + + outfile.close(); + if (last) { + std::cout << "文件已成功保存为: " << task->_name << std::endl; + //todo...更新数据库聊天图像上传状态 + //todo...通过grpc通知ChatServer + } + + if (task->_callback) { + task->_callback(result); + } + }; +``` + +## 效果展示 + +![image-20260102101925154](https://cdn.llfc.club/img/image-20260102101925154.png) + + + +![image-20260102102645373](https://cdn.llfc.club/img/image-20260102102645373.png) + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day41-\351\200\232\347\237\245\345\256\242\346\210\267\347\253\257\345\274\202\346\255\245\344\270\213\350\275\275\350\201\212\345\244\251\345\233\276\347\211\207.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day41-\351\200\232\347\237\245\345\256\242\346\210\267\347\253\257\345\274\202\346\255\245\344\270\213\350\275\275\350\201\212\345\244\251\345\233\276\347\211\207.md" new file mode 100644 index 0000000..008314a --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day41-\351\200\232\347\237\245\345\256\242\346\210\267\347\253\257\345\274\202\346\255\245\344\270\213\350\275\275\350\201\212\345\244\251\345\233\276\347\211\207.md" @@ -0,0 +1,1107 @@ +--- +title: rpc通知客户端异步下载聊天图片 +date: 2026-02-08 12:24:00 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 前情回顾 + +前面我们搞定了1,2,3以及5过程 + + + +![image-20260208131004814](https://cdn.llfc.club/image-20260208131004814.png) + +今天主要完成 + +4,6和7 + +## 资源服务器grpc设置 + +因为资源服务器要通知`ChatServer`,所以要设置grpc客户端 + +完善下proto协议,新增消息通知请求 + +![image-20260208133832656](https://cdn.llfc.club/image-20260208133832656.png) + +具体代码逻辑 + +``` protobuf +message NotifyChatImgReq{ + int32 from_uid = 1; + int32 to_uid = 2; + int32 message_id = 3; + string file_name = 4; + int64 total_size = 5; + int32 thread_id =6; +} + +message NotifyChatImgRsp{ + int32 error = 1; + int32 from_uid = 2; + int32 to_uid = 3; + int32 message_id = 4; + string file_name = 5; + int64 total_size = 6; + int32 thread_id =7; +} + +service ChatService { + rpc NotifyAddFriend(AddFriendReq) returns (AddFriendRsp) {} + rpc RplyAddFriend(RplyFriendReq) returns (RplyFriendRsp) {} + rpc SendChatMsg(SendChatMsgReq) returns (SendChatMsgRsp) {} + rpc NotifyAuthFriend(AuthFriendReq) returns (AuthFriendRsp) {} + rpc NotifyTextChatMsg(TextChatMsgReq) returns (TextChatMsgRsp){} + rpc NotifyKickUser(KickUserReq) returns (KickUserRsp){} + rpc NotifyChatImgMsg(NotifyChatImgReq) returns (NotifyChatImgRsp){} +} +``` + +实现grpc客户端逻辑如下: + +``` cpp +#pragma once +#include "const.h" +#include "Singleton.h" +#include "ConfigMgr.h" +#include "message.grpc.pb.h" +#include "message.pb.h" +#include +#include +#include +using grpc::Channel; +using grpc::Status; +using grpc::ClientContext; + + +using message::ChatService; +using message::NotifyChatImgReq; +using message::NotifyChatImgRsp; + +class ChatServerConPool { +public: + ChatServerConPool(size_t poolSize, std::string host, std::string port) + : poolSize_(poolSize), host_(host), port_(port), b_stop_(false) { + for (size_t i = 0; i < poolSize_; ++i) { + + std::shared_ptr channel = grpc::CreateChannel(host + ":" + port, + grpc::InsecureChannelCredentials()); + + connections_.push(ChatService::NewStub(channel)); + } + } + + ~ChatServerConPool() { + std::lock_guard lock(mutex_); + Close(); + while (!connections_.empty()) { + connections_.pop(); + } + } + + std::unique_ptr getConnection() { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { + if (b_stop_) { + return true; + } + return !connections_.empty(); + }); + //如果停止则直接返回空指针 + if (b_stop_) { + return nullptr; + } + auto context = std::move(connections_.front()); + connections_.pop(); + return context; + } + + void returnConnection(std::unique_ptr context) { + std::lock_guard lock(mutex_); + if (b_stop_) { + return; + } + connections_.push(std::move(context)); + cond_.notify_one(); + } + + void Close() { + b_stop_ = true; + cond_.notify_all(); + } + +private: + atomic b_stop_; + size_t poolSize_; + std::string host_; + std::string port_; + std::queue> connections_; + std::mutex mutex_; + std::condition_variable cond_; +}; + +class ChatServerGrpcClient :public Singleton +{ + friend class Singleton; +public: + ~ChatServerGrpcClient() { + + } + NotifyChatImgRsp NotifyChatImgMsg(int message_id, std::string chatserver); +private: + ChatServerGrpcClient(); + //sever_ip到连接池的映射, > + std::unordered_map> _hash_pools; +}; +``` + +具体实现 + +``` cpp +#include "ChatServerGrpcClient.h" +#include "MysqlMgr.h" + +NotifyChatImgRsp ChatServerGrpcClient::NotifyChatImgMsg(int message_id,std::string chatserver) +{ + ClientContext context; + NotifyChatImgRsp reply; + NotifyChatImgReq request; + request.set_message_id(message_id); + if (_hash_pools.find(chatserver) == _hash_pools.end()) { + reply.set_error(ErrorCodes::ServerIpErr); + return reply; + } + auto chat_msg = MysqlMgr::GetInstance()->GetChatMsgById(message_id); + request.set_file_name(chat_msg->content); + request.set_from_uid(chat_msg->sender_id); + request.set_to_uid(chat_msg->recv_id); + request.set_thread_id(chat_msg->thread_id); + // 资源文件路径 + auto file_dir = ConfigMgr::Inst().GetFileOutPath(); + //该消息是接收方客户端发送过来的,服务器将资源存储在发送方的文件夹中 + auto uid_str = std::to_string(chat_msg->sender_id); + auto file_path = (file_dir / uid_str / chat_msg->content); + boost::uintmax_t file_size = boost::filesystem::file_size(file_path); + request.set_total_size(file_size); + + auto &pool_ = _hash_pools[chatserver]; + auto stub = pool_->getConnection(); + Status status = stub->NotifyChatImgMsg(&context, request, &reply); + Defer defer([&stub, &pool_, this]() { + pool_->returnConnection(std::move(stub)); + }); + if (status.ok()) { + return reply; + } + else { + reply.set_error(ErrorCodes::RPCFailed); + return reply; + } +} + +ChatServerGrpcClient::ChatServerGrpcClient() +{ + auto& gCfgMgr = ConfigMgr::Inst(); + std::string host1 = gCfgMgr["chatserver1"]["Host"]; + std::string port1 = gCfgMgr["chatserver1"]["Port"]; + _hash_pools["chatserver1"] = std::make_unique(5, host1, port1); + + std::string host2 = gCfgMgr["chatserver2"]["Host"]; + std::string port2 = gCfgMgr["chatserver2"]["Port"]; + _hash_pools["chatserver2"] = std::make_unique(5, host2, port2); +} + +``` + +实现了通知接口,用来通知ChatServer图片消息上传完成,让ChatServer再通知其他客户端. + +## ChatServer响应资源服务器通知 + +ChatServer的proto也需要进行同样配置,这里略去 + +具体在ChatServiceImpl中添加响应消息通知的逻辑 + +``` cpp +Status ChatServiceImpl::NotifyChatImgMsg(::grpc::ServerContext* context, const ::message::NotifyChatImgReq* request, ::message::NotifyChatImgRsp* response) +{ + //查找用户是否在本服务器 + auto uid = request->to_uid(); + auto session = UserMgr::GetInstance()->GetSession(uid); + + Defer defer([request, response]() { + //设置具体的回包信息 + response->set_error(ErrorCodes::Success); + response->set_message_id(request->message_id()); + }); + + //用户不在内存中则直接返回 + if (session == nullptr) { + //这里只是返回1个状态 + return Status::OK; + } + + //在内存中则直接发送通知对方 + session->NotifyChatImgRecv(request); + //这里只是返回1个状态 + return Status::OK; +} +``` + +通过Session通知客户端 + +``` cpp +void CSession::NotifyChatImgRecv(const ::message::NotifyChatImgReq* request) { + Json::Value rtvalue; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["message_id"] = request->message_id(); + rtvalue["sender_id"] = request->from_uid(); + rtvalue["receiver_id"] = request->to_uid(); + rtvalue["img_name"] = request->file_name(); + rtvalue["total_size"] = std::to_string(request->total_size()); + rtvalue["thread_id"] = request->thread_id(); + + std::string return_str = rtvalue.toStyledString(); + //通知图片聊天信息 + Send(return_str, ID_NOTIFY_IMG_CHAT_MSG_REQ); + return; +} +``` + +## 客户端获取通知 + +客户端收到服务器通知后,会优先查看本地资源是否存在,如果存在则直接加载图片,添加聊天记录到页面。 + +如果不存在则组织下载,但是也需要将消息添加到聊天界面。 + +``` cpp + _handlers.insert(ID_NOTIFY_IMG_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + qDebug() << "receive notify img chat msg req success" ; + + + //收到消息后转发给页面 + auto thread_id = jsonObj["thread_id"].toInt(); + auto sender_id = jsonObj["sender_id"].toInt(); + auto message_id = jsonObj["message_id"].toInt(); + auto receiver_id = jsonObj["receiver_id"].toInt(); + auto img_name = jsonObj["img_name"].toString(); + auto total_size_str = jsonObj["total_size"].toString(); + auto total_size = total_size_str.toLongLong(); + auto uid = UserMgr::GetInstance()->GetUid(); + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir +"/user/"+ QString::number(uid)+ "/chatimg/" + QString::number(sender_id); + auto file_info = UserMgr::GetInstance()->GetTransFileByName(img_name); + //正常情况是找不到的,所以这里初始化一个文件信息放入UserMgr中管理 + if (!file_info) { + //预览图先默认空白,md5为空 + file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, CreateLoadingPlaceholder(200, 200), img_name, total_size, ""); + UserMgr::GetInstance()->AddTransFile(img_name, file_info); + } + + file_info->_msg_id = message_id; + file_info->_sender = sender_id; + file_info->_receiver = receiver_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::Uploading; + + auto img_chat_data_ptr = std::make_shared(file_info, "", + thread_id, ChatFormType::PRIVATE, ChatMsgType::PIC, + sender_id, MsgStatus::READED); + + + emit sig_img_chat_msg(img_chat_data_ptr); + + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = img_name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = "0"; + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = sender_id; + jsonObj_send["receiver_id"] = receiver_id; + jsonObj_send["message_id"] = message_id; + jsonObj_send["uid"] = uid; + //客户端存储聊天记录,按照如下格式存储C:\Users\secon\AppData\Roaming\llfcchat\chatimg\uid, uid为对方uid + QDir chatimgDir(img_path_str); + jsonObj["client_path"] = img_path_str; + if (!chatimgDir.exists()) { + chatimgDir.mkpath("."); // 创建当前路径 + } + + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + }); +``` + +收到服务器通知后,开始构造json数据,发送ID_IMG_CHAT_DOWN_REQ请求 + +## 聊天记录添加 + +客户端在请求服务器资源的时候,因为本地没有资源,可以先在聊天界面生成一个预览的空白图片,同时显示进度条 + +这部分逻辑是在客户端的tcpmgr中处理服务器通知聊天消息的逻辑里 + +``` cpp +_handlers.insert(ID_NOTIFY_IMG_CHAT_MSG_REQ, [this](ReqId id, int len, QByteArray data) { + //... + //发送给界面显示 + emit sig_img_chat_msg(img_chat_data_ptr); +} +``` + +客户端将图片消息发送给界面显示 + +在ChatDialog的构造函数中添加信号槽链接 + +``` cpp +connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_img_chat_msg, + this, &ChatDialog::slot_img_chat_msg); +``` + +ChatDialog收到该信号后,会触发添加消息的逻辑 + +``` cpp +void ChatDialog::slot_img_chat_msg(std::shared_ptr imgchat) { + //更新数据 + auto thread_id = imgchat->GetThreadId(); + auto thread_data = UserMgr::GetInstance()->GetChatThreadByThreadId(thread_id); + thread_data->AddMsg(imgchat); + if (_cur_chat_thread_id != thread_id) { + return; + } + ui->chat_page->AppendOtherMsg(imgchat); +} +``` + +添加其他消息的逻辑, 此处都是将其他人发送的图片消息添加到聊天界面显示 + +``` cpp +void ChatPage::AppendOtherMsg(std::shared_ptr msg) { + auto self_info = UserMgr::GetInstance()->GetUserInfo(); + ChatRole role; + if (msg->GetSendUid() == self_info->_uid) { + role = ChatRole::Self; + ChatItemBase* pChatItem = new ChatItemBase(role); + + pChatItem->setUserName(self_info->_name); + SetSelfIcon(pChatItem, self_info->_icon); + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + else if (msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } + + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + _base_item_map[msg->GetMsgId()] = pChatItem; + } + else { + role = ChatRole::Other; + ChatItemBase* pChatItem = new ChatItemBase(role); + auto friend_info = UserMgr::GetInstance()->GetFriendById(msg->GetSendUid()); + if (friend_info == nullptr) { + return; + } + pChatItem->setUserName(friend_info->_name); + + // 使用正则表达式检查是否是默认头像 + QRegularExpression regex("^:/res/head_(\\d+)\\.jpg$"); + QRegularExpressionMatch match = regex.match(friend_info->_icon); + if (match.hasMatch()) { + pChatItem->setUserIcon(QPixmap(friend_info->_icon)); + } + else { + // 如果是用户上传的头像,获取存储目录 + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + auto uid = UserMgr::GetInstance()->GetUid(); + QDir avatarsDir(storageDir + "/user/" + QString::number(uid) + "/avatars"); + auto file_name = QFileInfo(self_info->_icon).fileName(); + // 确保目录存在 + if (avatarsDir.exists()) { + QString avatarPath = avatarsDir.filePath(file_name); // 获取上传头像的完整路径 + QPixmap pixmap(avatarPath); // 加载上传的头像图片 + if (!pixmap.isNull()) { + pChatItem->setUserIcon(pixmap); + } + else { + qWarning() << "无法加载上传的头像:" << avatarPath; + auto icon_label = pChatItem->getIconLabel(); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } + } + else { + qWarning() << "头像存储目录不存在:" << avatarsDir.path(); + //创建目录 + avatarsDir.mkpath("."); + auto icon_label = pChatItem->getIconLabel(); + QString avatarPath = avatarsDir.filePath(file_name); + LoadHeadIcon(avatarPath, icon_label, file_name, "self_icon"); + } + } + + QWidget* pBubble = nullptr; + if (msg->GetMsgType() == ChatMsgType::TEXT) { + pBubble = new TextBubble(role, msg->GetMsgContent()); + } + else if (msg->GetMsgType() == ChatMsgType::PIC) { + auto img_msg = dynamic_pointer_cast(msg); + auto pic_bubble = new PictureBubble(img_msg->_msg_info->_preview_pix, role, img_msg->_msg_info->_total_size); + pic_bubble->setMsgInfo(img_msg->_msg_info); + pBubble = pic_bubble; + //连接暂停和恢复信号 + connect(dynamic_cast(pBubble), &PictureBubble::pauseRequested, + this, &ChatPage::on_clicked_paused); + connect(dynamic_cast(pBubble), &PictureBubble::resumeRequested, + this, &ChatPage::on_clicked_resume); + } + pChatItem->setWidget(pBubble); + auto status = msg->GetStatus(); + pChatItem->setStatus(status); + ui->chat_data_list->appendChatItem(pChatItem); + _base_item_map[msg->GetMsgId()] = pChatItem; + } +} +``` + +## 资源服务器响应下载请求 + +LogicWorker中增加请求的处理 + +``` cpp +_fun_callbacks[ID_IMG_CHAT_DOWN_REQ] = [this](std::shared_ptr session, const short& msg_req_id, + const string& msg_data) { + + Json::Reader reader; + Json::Value root; + reader.parse(msg_data, root); + + auto seq = root["seq"].asInt(); + auto name = root["name"].asString(); + auto total_size_str = root["total_size"].asString(); + auto trans_size_str = root["trans_size"].asString(); + auto file_path = ConfigMgr::Inst().GetFileOutPath(); + auto message_id = root["message_id"].asInt(); + auto sender = root["sender_id"].asInt(); + auto receiver = root["receiver_id"].asInt(); + auto token = root["token"].asString(); + auto uid = root["uid"].asInt(); + + auto callback = [=](const Json::Value& result) { + // 在异步任务完成后调用 + Json::Value rtvalue = result; + rtvalue["error"] = ErrorCodes::Success; + rtvalue["name"] = name; + rtvalue["sender_id"] = sender; + rtvalue["receiver_id"] = receiver; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + }; + + // 使用 std::hash 对字符串进行哈希 + std::hash hash_fn; + size_t hash_value = hash_fn(name); // 生成哈希值 + int index = hash_value % DOWN_LOAD_WORKER_COUNT; + std::cout << "Hash value: " << hash_value << std::endl; + + + //第一个包校验一下token是否合理 + if (seq == 1) { + //从redis获取用户token是否正确 + std::string uid_str = std::to_string(uid); + std::string token_key = USERTOKENPREFIX + uid_str; + std::string token_value = ""; + bool success = RedisMgr::GetInstance()->Get(token_key, token_value); + Json::Value rtvalue; + if (!success) { + rtvalue["error"] = ErrorCodes::UidInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + return; + } + + if (token_value != token) { + rtvalue["error"] = ErrorCodes::TokenInvalid; + std::string return_str = rtvalue.toStyledString(); + session->Send(return_str, ID_IMG_CHAT_DOWN_RSP); + return; + } + } + + auto sender_str = std::to_string(sender); + //转化为字符串 + auto uid_str = std::to_string(uid); + auto file_path_str = (file_path / sender_str / name).string(); + + auto down_load_task = std::make_shared(session, uid, name, seq, file_path_str, callback); + + FileSystem::GetInstance()->PostDownloadTaskToQue(down_load_task,index); + }; +``` + +LogicWorker将请求投递给FileSystem队列,FileSystem队列排队处理消息,被DownloaderWorker处理 + +``` cpp +void DownloadWorker::task_callback(std::shared_ptr task) +{ + // 解码 + auto file_path_str = task->_file_path; + + //std::cout << "file_path_str is " << file_path_str << std::endl; + + boost::filesystem::path file_path(file_path_str); + + Json::Value result; + result["error"] = ErrorCodes::Success; + + if (!boost::filesystem::exists(file_path)) { + std::cerr << "文件不存在: " << file_path_str << std::endl; + result["error"] = ErrorCodes::FileNotExists; + task->_callback(result); + return; + } + + std::ifstream infile(file_path_str, std::ios::binary); + if (!infile) { + std::cerr << "无法打开文件进行读取。" << std::endl; + result["error"] = ErrorCodes::FileReadPermissionFailed; + task->_callback(result); + return; + } + + std::shared_ptr file_info = nullptr; + + if (task->_seq == 1) { + // 获取文件大小 + infile.seekg(0, std::ios::end); + std::streamsize file_size = infile.tellg(); + infile.seekg(0, std::ios::beg); + //如果为空,则创建FileInfo 构造数据存储 + file_info = std::make_shared(); + file_info->_file_path_str = file_path_str; + file_info->_name = task->_name; + file_info->_seq = 1; + + file_info->_total_size = file_size; + file_info->_trans_size = 0; + // 立即保存到 Redis,覆盖旧数据,设置过期时间 + RedisMgr::GetInstance()->SetDownLoadInfo(task->_name, file_info); + std::cout << "[新下载] 文件: " << task->_name + << ", 大小: " << file_size << " 字节" << std::endl; + } + else { + //断点续传,从 Redis 获取历史信息 + file_info = RedisMgr::GetInstance()->GetDownloadInfo(task->_name); + if (file_info == nullptr) { + // Redis 中没有信息(可能过期了) + std::cerr << "断点续传失败,Redis 中无下载信息: " << task->_name << std::endl; + result["error"] = ErrorCodes::RedisReadErr; + task->_callback(result); + infile.close(); + return; + } + // 验证序列号是否匹配 + if (task->_seq != file_info->_seq) { + std::cerr << "序列号不匹配,期望: " << file_info->_seq + << ", 实际: " << task->_seq << std::endl; + result["error"] = ErrorCodes::FileSeqInvalid; + task->_callback(result); + infile.close(); + return; + } + + std::cout << "[续传] 文件: " << task->_name + << ", seq: " << task->_seq + << ", 进度: " << file_info->_trans_size + << "/" << file_info->_total_size << std::endl; + } + + // 计算当前偏移量 + std::streamsize offset = ((std::streamsize)task->_seq - 1) * MAX_FILE_LEN; + if (offset >= file_info->_total_size) { + std::cerr << "偏移量超出文件大小。" << std::endl; + result["error"] = ErrorCodes::FileOffsetInvalid; + task->_callback(result); + infile.close(); + return; + } + + // 定位到指定偏移量 + infile.seekg(offset); + + // 读取最多MAX_FILE_LEN字节 + char buffer[MAX_FILE_LEN]; + infile.read(buffer, MAX_FILE_LEN); + //获取read实际读取多少字节 + std::streamsize bytes_read = infile.gcount(); + + if (bytes_read <= 0) { + std::cerr << "读取文件失败。" << std::endl; + result["error"] = ErrorCodes::FileReadFailed; + task->_callback(result); + infile.close(); + return; + } + + // 将读取的数据进行base64编码 + std::string data_to_encode(buffer, bytes_read); + std::string encoded_data = base64_encode(data_to_encode); + + // 检查是否是最后一个包 + std::streamsize current_pos = offset + bytes_read; + bool is_last = (current_pos >= file_info->_total_size); + + // 设置返回结果 + result["data"] = encoded_data; + result["seq"] = task->_seq; + result["total_size"] = std::to_string(file_info->_total_size); + result["current_size"] = std::to_string(current_pos); + result["is_last"] = is_last; + + infile.close(); + + if (is_last) { + std::cout << "文件读取完成: " << file_path_str << std::endl; + RedisMgr::GetInstance()->DelDownLoadInfo(task->_name); + } + else { + //更新信息 + file_info->_seq++; + file_info->_trans_size = offset + bytes_read; + //更新redis + RedisMgr::GetInstance()->SetDownLoadInfo(task->_name, file_info); + } + + if (task->_callback) { + task->_callback(result); + } + +} +``` + +资源服务器每次收到请求后,由DownloadWorker从队列中获取请求,查询服务器资源,将资源按照seq计算偏移量最后读取数据发送给客户端。 + +## 客户端存储下载的资源 + +客户端需要存储服务器传输的资源 + +``` cpp +_handlers.insert(ID_IMG_CHAT_DOWN_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive download file info rsp success"; + + QString base64Data = jsonObj["data"].toString(); + int seq = jsonObj["seq"].toInt(); + bool is_last = jsonObj["is_last"].toBool(); + QString total_size_str = jsonObj["total_size"].toString(); + qint64 total_size = total_size_str.toLongLong(nullptr); + QString current_size_str = jsonObj["current_size"].toString(); + qint64 current_size = current_size_str.toLongLong(nullptr); + QString name = jsonObj["name"].toString(); + + auto file_info = UserMgr::GetInstance()->GetTransFileByName(name); + if (file_info == nullptr) { + qDebug() << "file: " << name << " not found"; + return; + } + + file_info->_current_size = current_size; + file_info->_rsp_size = current_size; + file_info->_total_size = total_size; + auto clientPath = file_info->_text_or_url; + + //Base64解码 + QByteArray decodedData = QByteArray::fromBase64(base64Data.toUtf8()); + auto file_path = clientPath + "/" + name; + QFile file(file_path); + + // 根据 seq 决定打开模式 + QIODevice::OpenMode mode; + if (seq == 1) { + // 第一个包,覆盖写入 + mode = QIODevice::WriteOnly; + } + else { + // 后续包,追加写入 + mode = QIODevice::WriteOnly | QIODevice::Append; + } + + if (!file.open(mode)) { + qDebug() << "Failed to open file for writing:" << clientPath; + qDebug() << "Error:" << file.errorString(); + return; + } + + + qint64 bytesWritten = file.write(decodedData); + if (bytesWritten != decodedData.size()) { + qDebug() << "Failed to write all data. Written:" << bytesWritten + << "Expected:" << decodedData.size(); + } + + file.close(); + + qDebug() << "Successfully wrote" << bytesWritten << "bytes to file"; + qDebug() << "Progress:" << current_size << "/" << total_size + << "(" << (current_size * 100 / total_size) << "%)"; + + if (is_last) { + qDebug() << "File download completed:" << clientPath; + UserMgr::GetInstance()->RmvTransFileByName(name); + //通知界面下载完成 + emit sig_download_finish(file_info, file_path); + } + else { + //继续请求 + file_info->_seq = seq + 1; + file_info->_last_confirmed_seq = seq; + if (file_info->_transfer_state == TransferState::Paused) { + //暂停状态,则直接返回 + return; + } + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = QString::number(file_info->_current_size); + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = file_info->_sender; + jsonObj_send["receiver_id"] = file_info->_receiver; + jsonObj_send["message_id"] = file_info->_msg_id; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj_send["uid"] = uid; + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); + //todo...通知界面更新进度 + emit sig_update_download_progress(file_info); + } + }); + +``` + +通过QFile类实现文件写入。 + +## 客户端进度显示 + +为了让客户端更为直观的显示下载进度,可以在收到服务器消息后,将文件下载进度同步给界面,同时显示支持暂停和继续 + +进度通知在上述逻辑中 + +``` cpp + +_handlers.insert(ID_IMG_CHAT_DOWN_RSP, [this](ReqId id, int len, QByteArray data) { + //... + emit sig_update_download_progress(file_info); +}); +``` + +同样是在ChatDialog构造函数中添加消息链接 + +``` cpp + //接收tcp返回的下载进度信息 + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_update_download_progress, + this, &ChatDialog::slot_update_download_progress); +``` + +进度处理槽函数 + +``` cpp +void ChatDialog::slot_update_download_progress(std::shared_ptr msg_info) { + auto chat_data = UserMgr::GetInstance()->GetChatThreadByThreadId(msg_info->_thread_id); + if (chat_data == nullptr) { + return; + } + + //更新消息,其实不用更新,都是共享msg_info的一块内存,这里为了安全还是再次更新下 + + chat_data->UpdateProgress(msg_info); + + if (_cur_chat_thread_id != msg_info->_thread_id) { + return; + } + + + //更新聊天界面信息 + ui->chat_page->UpdateFileProgress(msg_info); +} +``` + +在ChatPage中详细处理更新 + +``` cpp +void ChatPage::UpdateFileProgress(std::shared_ptr msg_info) { + auto iter = _base_item_map.find(msg_info->_msg_id); + if (iter == _base_item_map.end()) { + return; + } + + if (msg_info->_msg_type == MsgType::IMG_MSG) { + auto bubble = iter.value()->getBubble(); + PictureBubble* pic_bubble = dynamic_cast(bubble); + pic_bubble->setProgress(msg_info->_rsp_size, msg_info->_total_size); + } + +} +``` + +PicBubble中完成状态显示 + +``` cpp +void PictureBubble::setProgress(int value, int total_value) +{ + if (m_total_size != total_value) { + m_total_size = total_value; + } + float percent = (value / (m_total_size*1.0))*100; + m_progressBar->setValue(percent); + if (percent >= 100) { + setState(TransferState::Completed); + } +} +``` + +## 断点续传 + +因为在客户端收到服务器通知的图片聊天信息的时候,已经通过sig_img_chat_msg将消息发送给ChatDialog添加到页面上了。同时传输了图片的状态为下载中。 + +点击继续和暂停的逻辑可以复用PicBubble的逻辑 + +``` cpp +void PictureBubble::onPictureClicked() +{ + switch (m_state) { + case TransferState::Downloading: + case TransferState::Uploading: + // 暂停 + setState(TransferState::Paused); + emit pauseRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Paused: + // 继续 + resumeState(); // + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + case TransferState::Failed: + // 重试 + emit resumeRequested(_msg_info->_unique_name, _msg_info->_transfer_type); + break; + + default: + // 其他状态可以实现查看大图等功能 + break; + } +} +``` + +接下来我们响应暂停和继续,这部分逻辑也已经复用之前的逻辑即可 + +暂停逻辑 + +``` cpp +void ChatPage::on_clicked_paused(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->PauseTransFileByName(unique_name); +} + +void UserMgr::PauseTransFileByName(QString name) { + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return; + } + + iter.value()->_transfer_state = TransferState::Paused; +} +``` + +恢复逻辑 + +``` cpp + +void ChatPage::on_clicked_resume(QString unique_name, TransferType transfer_type) +{ + UserMgr::GetInstance()->ResumeTransFileByName(unique_name); + //继续发送或者下载 + if (transfer_type == TransferType::Upload) { + FileTcpMgr::GetInstance()->ContinueUploadFile(unique_name); + return; + } + + if (transfer_type == TransferType::Download) { + FileTcpMgr::GetInstance()->ContinueDownloadFile(unique_name); + return; + } +} + +void UserMgr::ResumeTransFileByName(QString name) +{ + std::lock_guard mtx(_trans_mtx); + auto iter = _name_to_msg_info.find(name); + if (iter == _name_to_msg_info.end()) { + return; + } + + if (iter.value()->_transfer_type == TransferType::Download) { + iter.value()->_transfer_state = TransferState::Downloading; + return; + } + + if (iter.value()->_transfer_type == TransferType::Upload) { + iter.value()->_transfer_state = TransferState::Uploading; + return; + } +} +``` + +发送继续下载信号通知FileTcpMgr继续下载 + +``` cpp +void FileTcpMgr::ContinueDownloadFile(QString unique_name) { + emit sig_continue_download_file(unique_name); +} +``` + +FileTcpMgr响应下载逻辑 + +``` cpp +void FileTcpMgr::slot_continue_download_file(QString unique_name) { + auto file_info = UserMgr::GetInstance()->GetTransFileByName(unique_name); + if (file_info == nullptr) { + return; + } + + if (file_info->_current_size >= file_info->_total_size) { + qDebug() << "file has received finished"; + return; + } + + //组织请求,准备下载 + QJsonObject jsonObj_send; + jsonObj_send["name"] = unique_name; + jsonObj_send["seq"] = file_info->_seq; + jsonObj_send["trans_size"] = QString::number(file_info->_current_size); + jsonObj_send["total_size"] = QString::number(file_info->_total_size); + jsonObj_send["token"] = UserMgr::GetInstance()->GetToken(); + jsonObj_send["sender_id"] = file_info->_sender; + jsonObj_send["receiver_id"] = file_info->_receiver; + jsonObj_send["message_id"] = file_info->_msg_id; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj_send["uid"] = uid; + QJsonDocument doc(jsonObj_send); + auto send_data = doc.toJson(); + FileTcpMgr::GetInstance()->SendData(ID_IMG_CHAT_DOWN_REQ, send_data); +} +``` + +通过上述逻辑可以实现客户端的断点下载和暂停。 + +## 效果演示 + + + +![image-20260208162803229](https://cdn.llfc.club/image-20260208162803229.png) + + + +**源码链接** + +https://gitee.com/secondtonone1/llfcchat + +**注意第二季分支为Season_2** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day42-\347\224\250\346\210\267\345\212\240\350\275\275\350\201\212\345\244\251\350\265\204\346\272\220.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day42-\347\224\250\346\210\267\345\212\240\350\275\275\350\201\212\345\244\251\350\265\204\346\272\220.md" new file mode 100644 index 0000000..0c01064 --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day42-\347\224\250\346\210\267\345\212\240\350\275\275\350\201\212\345\244\251\350\265\204\346\272\220.md" @@ -0,0 +1,1147 @@ +--- +title: 用户登录加载聊天资源 +date: 2026-02-09 07:43:06 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 前情回顾 + +前面我们实现了聊天资源的下载和上传,以及异步通知断点下载等功能。 + +今天主要实现登录后聊天信息的加载,之前把文本信息的加载实现了,现在需要实现用户登录后图片信息的加载。 + +这个功能做完,聊天的基本功能就都收尾了,有意思的是好像一个圆圈,我们又回到了最初的原点,从登录逻辑出发,补充聊天资源加载 + +## 登录流程回顾 + +![image-20260209150133552](https://cdn.llfc.club/image-20260209150133552.png) + + + +> 点击登录按钮后,通过HttpMgr发送登录请求 + +``` cpp +void LoginDialog::on_login_btn_clicked() +{ + qDebug()<<"login btn clicked"; + if(checkUserValid() == false){ + return; + } + + if(checkPwdValid() == false){ + return ; + } + + enableBtn(false); + auto email = ui->email_edit->text(); + auto pwd = ui->pass_edit->text(); + //发送http请求登录 + QJsonObject json_obj; + json_obj["email"] = email; + json_obj["passwd"] = xorString(pwd); + HttpMgr::GetInstance()->PostHttpReq(QUrl(gate_url_prefix+"/user_login"), + json_obj, ReqId::ID_LOGIN_USER,Modules::LOGINMOD); +} +``` + +> HttpMgr内部封装了PostHttpReq接口,这是异步http请求,会提前构造好一个reply,以及注册一个回调函数,将来GateServer将登录信息返回后会出发这个回调函数 + +``` cpp +void HttpMgr::PostHttpReq(QUrl url, QJsonObject json, ReqId req_id, Modules mod) +{ + //创建一个HTTP POST请求,并设置请求头和请求体 + QByteArray data = QJsonDocument(json).toJson(); + //通过url构造请求 + QNetworkRequest request(url); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(data.length())); + //发送请求,并处理响应, 获取自己的智能指针,构造伪闭包并增加智能指针引用计数 + auto self = shared_from_this(); + QNetworkReply * reply = _manager.post(request, data); + //设置信号和槽等待发送完成 + QObject::connect(reply, &QNetworkReply::finished, [reply, self, req_id, mod](){ + //处理错误的情况 + if(reply->error() != QNetworkReply::NoError){ + qDebug() << reply->errorString(); + //发送信号通知完成 + emit self->sig_http_finish(req_id, "", ErrorCodes::ERR_NETWORK, mod); + reply->deleteLater(); + return; + } + + //无错误则读回请求 + QString res = reply->readAll(); + + //发送信号通知完成 + emit self->sig_http_finish(req_id, res, ErrorCodes::SUCCESS,mod); + reply->deleteLater(); + return; + }); +} +``` + +我们查看下GateServer的处理流程 + +``` cpp +bool LogicSystem::HandlePost(std::string path, std::shared_ptr con) { + if (_post_handlers.find(path) == _post_handlers.end()) { + return false; + } + + _post_handlers[path](con); + return true; +} +``` + +服务器会根据客户端传递的url进行分析,然后去_post_handlers中根据path查找并调用回调函数 + +回调函数在LogicSystem中提前注册到_post_handlers中 + +``` cpp +void LogicSystem::RegPost(std::string url, HttpHandler handler) { + _post_handlers.insert(make_pair(url, handler)); +} +``` + +在构造函数中调用RegPost注册消息 + +``` cpp + //用户登录逻辑 + RegPost("/user_login", [](std::shared_ptr connection) { + auto body_str = boost::beast::buffers_to_string(connection->_request.body().data()); + std::cout << "receive body is " << body_str << std::endl; + connection->_response.set(http::field::content_type, "text/json"); + Json::Value root; + Json::Reader reader; + Json::Value src_root; + bool parse_success = reader.parse(body_str, src_root); + if (!parse_success) { + std::cout << "Failed to parse JSON data!" << std::endl; + root["error"] = ErrorCodes::Error_Json; + std::string jsonstr = root.toStyledString(); + beast::ostream(connection->_response.body()) << jsonstr; + return true; + } + + auto email = src_root["email"].asString(); + auto pwd = src_root["passwd"].asString(); + UserInfo userInfo; + //查询数据库判断用户名和密码是否匹配 + bool pwd_valid = MysqlMgr::GetInstance()->CheckPwd(email, pwd, userInfo); + if (!pwd_valid) { + std::cout << " user pwd not match" << std::endl; + root["error"] = ErrorCodes::PasswdInvalid; + std::string jsonstr = root.toStyledString(); + beast::ostream(connection->_response.body()) << jsonstr; + return true; + } + + //查询StatusServer找到合适的连接 + auto reply = StatusGrpcClient::GetInstance()->GetChatServer(userInfo.uid); + if (reply.error()) { + std::cout << " grpc get chat server failed, error is " << reply.error()<< std::endl; + root["error"] = ErrorCodes::RPCFailed; + std::string jsonstr = root.toStyledString(); + beast::ostream(connection->_response.body()) << jsonstr; + return true; + } + + std::cout << "succeed to load userinfo uid is " << userInfo.uid << std::endl; + root["error"] = 0; + root["email"] = email; + root["uid"] = userInfo.uid; + root["token"] = reply.token(); + root["chathost"] = reply.host(); + root["chatport"] = reply.port(); + auto& gCfgMgr = ConfigMgr::Inst(); + std::string res_port = gCfgMgr["ResServer"]["Port"]; + std::string res_host = gCfgMgr["ResServer"]["Host"]; + root["reshost"] = res_host; + root["resport"] = res_port; + + std::string jsonstr = root.toStyledString(); + beast::ostream(connection->_response.body()) << jsonstr; + return true; + }); +``` + +所以GateServer会触发上面的lambda表达式处理 + +在lambda表达式中调用GRPC连接池,向StatusServer发送请求,获取可用的聊天服务器地址,将聊天服务器地址返回给GateServer,GateServer再将地址返回给客户端, rpc封装 + +``` cpp +GetChatServerRsp StatusGrpcClient::GetChatServer(int uid) +{ + ClientContext context; + GetChatServerRsp reply; + GetChatServerReq request; + request.set_uid(uid); + auto stub = pool_->getConnection(); + Status status = stub->GetChatServer(&context, request, &reply); + Defer defer([&stub, this]() { + pool_->returnConnection(std::move(stub)); + }); + if (status.ok()) { + return reply; + } + else { + reply.set_error(ErrorCodes::RPCFailed); + return reply; + } +} +``` + +客户端收到GateServer回复后,客户端会根据消息ID为`ReqId::ID_LOGIN_USER`发送`sig_http_finish`信号通知 + +该信号连接了 + +``` cpp +HttpMgr::HttpMgr() +{ + //连接http请求和完成信号,信号槽机制保证队列消费 + connect(this, &HttpMgr::sig_http_finish, this, &HttpMgr::slot_http_finish); +} +``` + +分别对应三个请求的处理 + +``` cpp +void HttpMgr::slot_http_finish(ReqId id, QString res, ErrorCodes err, Modules mod) +{ + if(mod == Modules::REGISTERMOD){ + //发送信号通知指定模块http响应结束 + emit sig_reg_mod_finish(id, res, err); + } + + if(mod == Modules::RESETMOD){ + //发送信号通知指定模块http响应结束 + emit sig_reset_mod_finish(id, res, err); + } + + if(mod == Modules::LOGINMOD){ + emit sig_login_mod_finish(id, res, err); + } +} +``` + +对于登录请求,主要逻辑在sig_login_mod_finish信号发出看,该信号在LoginDialog中连接 + +``` cpp + //连接登录回包信号 + connect(HttpMgr::GetInstance().get(), &HttpMgr::sig_login_mod_finish, this, + &LoginDialog::slot_login_mod_finish); +``` + +进而出发槽函数 + +``` cpp +void LoginDialog::slot_login_mod_finish(ReqId id, QString res, ErrorCodes err) +{ + if(err != ErrorCodes::SUCCESS){ + showTip(tr("网络请求错误"),false); + return; + } + + // 解析 JSON 字符串,res需转化为QByteArray + QJsonDocument jsonDoc = QJsonDocument::fromJson(res.toUtf8()); + //json解析错误 + if(jsonDoc.isNull()){ + showTip(tr("json解析错误"),false); + return; + } + + //json解析错误 + if(!jsonDoc.isObject()){ + showTip(tr("json解析错误"),false); + return; + } + + + //调用对应的逻辑,根据id回调。 + _handlers[id](jsonDoc.object()); + + return; +} +``` + +槽函数中根据id获取提前注册好的回调函数 + +``` cpp +_handlers[id](jsonDoc.object()); +``` + +之前的注册逻辑 + +``` cpp +void LoginDialog::initHttpHandlers() +{ + //注册获取登录回包逻辑 + _handlers.insert(ReqId::ID_LOGIN_USER, [this](QJsonObject jsonObj){ + int error = jsonObj["error"].toInt(); + if(error != ErrorCodes::SUCCESS){ + showTip(tr("参数错误"),false); + enableBtn(true); + return; + } + auto email = jsonObj["email"].toString(); + + //发送信号通知tcpMgr发送长链接 + _si = std::make_shared(); + + _si->_uid = jsonObj["uid"].toInt(); + _si->_chat_host = jsonObj["chathost"].toString(); + _si->_chat_port = jsonObj["chatport"].toString(); + _si->_token = jsonObj["token"].toString(); + + _si->_res_host = jsonObj["reshost"].toString(); + _si->_res_port = jsonObj["resport"].toString(); + + + qDebug()<< "email is " << email << " uid is " << _si->_uid <<" chat host is " + << _si->_chat_host << " chat port is " + << _si->_chat_port << " token is " << _si->_token + << " res host is " << _si->_res_host + << " res port is " << _si->_res_port; + emit sig_connect_tcp(_si); + // qDebug() << "send thread is " << QThread::currentThread(); + // emit sig_test(); + }); +} +``` + +所以当消息到来时会出发上面的lambda表达式,进而发出sig_connect_tcp信号, 该信号链接槽函数slot_tcp_connect + +``` cpp + //连接tcp连接请求的信号和槽函数 + connect(this, &LoginDialog::sig_connect_tcp, TcpMgr::GetInstance().get(), &TcpMgr::slot_tcp_connect); +``` + +槽函数内根据host地址链接指定的tcpserver + +``` cpp +void TcpMgr::slot_tcp_connect(std::shared_ptr si) +{ + qDebug()<< "receive tcp connect signal"; + // 尝试连接到服务器 + qDebug() << "Connecting to chat server..."; + _host = si->_chat_host; + _port = static_cast(si->_chat_port.toUInt()); + _socket.connectToHost(_host, _port); +} +``` + +_socket 是QTcpSocket类型,发出连接请求后,如果和服务器建立好连接后,会触发链接成功的回调, 在TcpMgr的构造函数中提前注册了消息和回调函数 + +``` cpp +TcpMgr::TcpMgr():_host(""),_port(0),_b_recv_pending(false),_message_id(0),_message_len(0),_bytes_sent(0),_pending(false) +{ + registerMetaType(); + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { + qDebug() << "Connected to server!"; + // 连接建立后发送消息 + emit sig_con_success(true); + }); + + QObject::connect(&_socket, &QTcpSocket::readyRead, this, [&]() { + // 当有数据可读时,读取所有数据 + // 读取所有数据并追加到缓冲区 + _buffer.append(_socket.readAll()); + + forever { + //先解析头部 + if(!_b_recv_pending){ + // 检查缓冲区中的数据是否足够解析出一个消息头(消息ID + 消息长度) + if (_buffer.size() < static_cast(sizeof(quint16) * 2)) { + return; // 数据不够,等待更多数据 + } + + // ✅ 每次都重新创建stream + QDataStream stream(_buffer); + stream.setVersion(QDataStream::Qt_5_0); + stream >> _message_id >> _message_len; + _buffer.remove(0, sizeof(quint16) * 2); // 使用remove代替mid赋值 + qDebug() << "Message ID:" << _message_id << ", Length:" << _message_len; + + } + + //buffer剩余长读是否满足消息体长度,不满足则退出继续等待接受 + if(_buffer.size() < _message_len){ + _b_recv_pending = true; + return; + } + + _b_recv_pending = false; + // 读取消息体 + QByteArray messageBody = _buffer.mid(0, _message_len); + qDebug() << "receive body msg is " << messageBody ; + + _buffer = _buffer.mid(_message_len); + handleMsg(ReqId(_message_id),_message_len, messageBody); + } + + }); + + //5.15 之后版本 +// QObject::connect(&_socket, QOverload::of(&QTcpSocket::errorOccurred), [&](QAbstractSocket::SocketError socketError) { +// Q_UNUSED(socketError) +// qDebug() << "Error:" << _socket.errorString(); +// }); + + // 处理错误(适用于Qt 5.15之前的版本) + QObject::connect(&_socket, static_cast(&QTcpSocket::error), + this, + [&](QTcpSocket::SocketError socketError) { + qDebug() << "Error:" << _socket.errorString() ; + switch (socketError) { + case QTcpSocket::ConnectionRefusedError: + qDebug() << "Connection Refused!"; + emit sig_con_success(false); + break; + case QTcpSocket::RemoteHostClosedError: + qDebug() << "Remote Host Closed Connection!"; + break; + case QTcpSocket::HostNotFoundError: + qDebug() << "Host Not Found!"; + emit sig_con_success(false); + break; + case QTcpSocket::SocketTimeoutError: + qDebug() << "Connection Timeout!"; + emit sig_con_success(false); + break; + case QTcpSocket::NetworkError: + qDebug() << "Network Error!"; + break; + default: + qDebug() << "Other Error!"; + break; + } + }); + + // 处理连接断开 + QObject::connect(&_socket, &QTcpSocket::disconnected, this,[&]() { + qDebug() << "Disconnected from server."; + //并且发送通知到界面 + emit sig_connection_closed(); + }); + //连接发送信号用来发送数据 + QObject::connect(this, &TcpMgr::sig_send_data, this, &TcpMgr::slot_send_data); + + //连接发送信号 + QObject::connect(&_socket, &QTcpSocket::bytesWritten, this, [this](qint64 bytes) { + //更新发送数据 + _bytes_sent += bytes; + //未发送完整 + if (_bytes_sent < _current_block.size()) { + //继续发送 + auto data_to_send = _current_block.mid(_bytes_sent); + _socket.write(data_to_send); + return; + } + + //发送完全,则查看队列是否为空 + if (_send_queue.isEmpty()) { + //队列为空,说明已经将所有数据发送完成,将pending设置为false,这样后续要发送数据时可以继续发送 + _current_block.clear(); + _pending = false; + _bytes_sent = 0; + return; + } + + //队列不为空,则取出队首元素 + _current_block = _send_queue.dequeue(); + _bytes_sent = 0; + _pending = true; + qint64 w2 = _socket.write(_current_block); + qDebug() << "[TcpMgr] Dequeued and write() returned" << w2; + }); + + + //关闭socket + connect(this, &TcpMgr::sig_close, this, &TcpMgr::slot_tcp_close); + //注册消息 + initHandlers(); + +} +``` + +当客户端和服务器建立连接后,会出发下面的lambda表达式 + +``` cpp + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { + qDebug() << "Connected to server!"; + // 连接建立后发送消息 + emit sig_con_success(true); + }); +``` + +从而发出sig_con_success信号, 信号连接了槽函数slot_tcp_con_finish + +``` cpp +//连接tcp管理者发出的连接成功信号 + connect(TcpMgr::GetInstance().get(), &TcpMgr::sig_con_success, this, &LoginDialog::slot_tcp_con_finish); +``` + +槽函数里链接资源服务器 + +``` cpp +void LoginDialog::slot_tcp_con_finish(bool bsuccess) +{ + if(bsuccess){ + showTip(tr("聊天服务连接成功,正在连接资源服务器..."),true); + emit sig_connect_res_server(_si); + }else{ + showTip(tr("网络异常"), false); + } +} +``` + +该信号连接了槽函数 + +``` cpp + //连接tcp连接资源服务器请求的信号和槽函数 + connect(this, &LoginDialog::sig_connect_res_server, + FileTcpMgr::GetInstance().get(), &FileTcpMgr::slot_tcp_connect); +``` + +链接资源服务器的逻辑和之前链接ChatServer类似 + +``` cpp +void FileTcpMgr::slot_tcp_connect(std::shared_ptr si) +{ + qDebug() << "receive tcp connect signal"; + // 尝试连接到服务器 + qDebug() << "Connecting to server..."; + _host = si->_res_host; + _port = static_cast(si->_res_port.toUInt()); + _socket.connectToHost(_host, _port); +} +``` + +当客户端链接资源服务器成功了,就会出发lambda表达式 + +``` cpp + QObject::connect(&_socket, &QTcpSocket::connected, this, [&]() { + qDebug() << "Connected to server!"; + emit sig_con_success(true); + }); +``` + +信号sig_con_success和槽函数链接 + +``` cpp + connect(FileTcpMgr::GetInstance().get(), &FileTcpMgr::sig_con_success, this, &LoginDialog::slot_res_con_finish); +``` + +进而触发这个函数,内部发送登录请求给ChatServer + +``` cpp +void LoginDialog::slot_res_con_finish(bool bsuccess) +{ + if(bsuccess){ + showTip(tr("聊天服务连接成功,正在登录..."),true); + QJsonObject jsonObj; + jsonObj["uid"] = _si->_uid; + jsonObj["token"] = _si->_token; + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Indented); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_CHAT_LOGIN, jsonData); + + }else{ + showTip(tr("网络异常"),false); + enableBtn(true); + } +} +``` + +这里略去ChatServer的处理,客户端收到ID_CHAT_LOGIN_RSP回复后,出发lambda表达式 + +``` cpp + _handlers.insert(ID_CHAT_LOGIN_RSP, [this](ReqId id, int len, QByteArray data){ + Q_UNUSED(len); + qDebug()<< "handle id is "<< id ; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if(jsonDoc.isNull()){ + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + qDebug()<< "data jsonobj is " << jsonObj ; + + if(!jsonObj.contains("error")){ + int err = ErrorCodes::ERR_JSON; + qDebug() << "Login Failed, err is Json Parse Err" << err ; + emit sig_login_failed(err); + return; + } + + int err = jsonObj["error"].toInt(); + if(err != ErrorCodes::SUCCESS){ + qDebug() << "Login Failed, err is " << err ; + emit sig_login_failed(err); + return; + } + + auto uid = jsonObj["uid"].toInt(); + auto name = jsonObj["name"].toString(); + auto nick = jsonObj["nick"].toString(); + auto icon = jsonObj["icon"].toString(); + auto sex = jsonObj["sex"].toInt(); + auto desc = jsonObj["desc"].toString(); + auto user_info = std::make_shared(uid, name, nick, icon, sex,"",desc); + + UserMgr::GetInstance()->SetUserInfo(user_info); + UserMgr::GetInstance()->SetToken(jsonObj["token"].toString()); + if(jsonObj.contains("apply_list")){ + UserMgr::GetInstance()->AppendApplyList(jsonObj["apply_list"].toArray()); + } + + //添加好友列表 + if (jsonObj.contains("friend_list")) { + UserMgr::GetInstance()->AppendFriendList(jsonObj["friend_list"].toArray()); + } + + emit sig_swich_chatdlg(); + }); + +``` + +将用户信息,以及好友列表,申请列表等数据组织好后存储UserMgr中,然后发送信号sig_swich_chatdlg跳转到登录界面 + +链接信号 + +``` cpp + //连接创建聊天界面信号 + connect(TcpMgr::GetInstance().get(),&TcpMgr::sig_swich_chatdlg, this, &MainWindow::SlotSwitchChat); +``` + +跳转逻辑 + +``` cpp + +void MainWindow::SlotSwitchChat() +{ + _chat_dlg = new ChatDialog(); + _chat_dlg->setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint); + setCentralWidget(_chat_dlg); + _chat_dlg->show(); + _login_dlg->hide(); + this->setMinimumSize(QSize(1050,900)); + this->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + _ui_status = CHAT_UI; + _chat_dlg->loadChatList(); +} +``` + +至此完成登录界面加载以及聊天记录加载,聊天记录加载具体流程看下面 + +## 加载聊天记录 + +其中加载聊天记录核心逻辑 + +``` cpp +void ChatDialog::loadChatList() +{ + showLoadingDlg(true); + //发送请求逻辑 + QJsonObject jsonObj; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj["uid"] = uid; + int last_chat_thread_id = UserMgr::GetInstance()->GetLastChatThreadId(); + jsonObj["thread_id"] = last_chat_thread_id; + + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_THREAD_REQ, jsonData); +} +``` + +发送ID_LOAD_CHAT_THREAD_REQ逻辑给ChatServer,略去服务器处理流程,客户端会受到会话列表的回复数据 + +``` cpp +_handlers.insert(ID_LOAD_CHAT_THREAD_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "chat thread json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get chat thread rsp failed, error is " << err; + return; + } + + qDebug() << "Receive chat thread rsp Success"; + + auto thread_array = jsonObj["threads"].toArray(); + std::vector> chat_threads; + for (const QJsonValue& value : thread_array) { + auto cti = std::make_shared(); + cti->_thread_id = value["thread_id"].toInt(); + cti->_type = value["type"].toString(); + cti->_user1_id = value["user1_id"].toInt(); + cti->_user2_id = value["user2_id"].toInt(); + chat_threads.push_back(cti); + } + + bool load_more = jsonObj["load_more"].toBool(); + int next_last_id = jsonObj["next_last_id"].toInt(); + //发送信号通知界面 + emit sig_load_chat_thread(load_more, next_last_id, chat_threads); + }); +``` + +解析会话列表,按照会话id请求每个会话具体内容 + +``` cpp +void ChatDialog::slot_load_chat_thread(bool load_more, int last_thread_id, + std::vector> chat_threads) +{ + for (auto& cti : chat_threads) { + //先处理单聊,群聊跳过,以后添加 + if (cti->_type == "group") { + continue; + } + + auto uid = UserMgr::GetInstance()->GetUid(); + auto other_uid = 0; + if (uid == cti->_user1_id) { + other_uid = cti->_user2_id; + } + else { + other_uid = cti->_user1_id; + } + + auto chat_thread_data = std::make_shared(other_uid, cti->_thread_id, 0); + UserMgr::GetInstance()->AddChatThreadData(chat_thread_data, other_uid); + + auto* chat_user_wid = new ChatUserWid(); + chat_user_wid->SetChatData(chat_thread_data); + QListWidgetItem* item = new QListWidgetItem; + //qDebug()<<"chat_user_wid sizeHint is " << chat_user_wid->sizeHint(); + item->setSizeHint(chat_user_wid->sizeHint()); + ui->chat_user_list->addItem(item); + ui->chat_user_list->setItemWidget(item, chat_user_wid); + _chat_thread_items.insert(cti->_thread_id, item); + } + + UserMgr::GetInstance()->SetLastChatThreadId(last_thread_id); + + if (load_more) { + //发送请求逻辑 + QJsonObject jsonObj; + auto uid = UserMgr::GetInstance()->GetUid(); + jsonObj["uid"] = uid; + jsonObj["thread_id"] = last_thread_id; + + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_THREAD_REQ, jsonData); + return; + } + + showLoadingDlg(false); + //继续加载聊天数据 + loadChatMsg(); +} +``` + +如果load_more为true,说明有会话没加载完,需要继续加载,等到所有会话信息加载成功后,load_more为false,则将当前会话的消息列表添加到聊天界面。如果会话列表加载完成了,则继续加载会话内部的多个消息。 + +``` cpp +void ChatDialog::loadChatMsg() { + + //发送聊天记录请求 + _cur_load_chat = UserMgr::GetInstance()->GetCurLoadData(); + if (_cur_load_chat == nullptr) { + return; + } + + showLoadingDlg(true); + + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); +} +``` + +回包消息处理 + +``` cpp + _handlers.insert(ID_LOAD_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + int thread_id = jsonObj["thread_id"].toInt(); + int last_msg_id = jsonObj["last_message_id"].toInt(); + bool load_more = jsonObj["load_more"].toBool(); + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto send_uid = data["sender"].toInt(); + auto msg_id = data["msg_id"].toInt(); + auto thread_id = data["thread_id"].toInt(); + auto unique_id = data["unique_id"].toInt(); + auto msg_content = data["msg_content"].toString(); + QString chat_time = data["chat_time"].toString(); + int status = data["status"].toInt(); + int msg_type = data["msg_type"].toInt(); + int recv_id = data["receiver"].toInt(); + if (msg_type == int(ChatMsgType::TEXT)) { + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + + if (msg_type == int(ChatMsgType::PIC)) { + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(send_uid); + QString img_path = img_path_str + "/" + msg_content; + //文件不存在,则创建空白图片占位,同时组织数据准备发送 + if (QFile::exists(img_path) == false) { + + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + //如果文件存在 + //如果文件存在则直接构建MsgInfo + // 获取文件大小 + QFileInfo fileInfo(img_path); + qint64 file_size = fileInfo.size(); + //从文件路径加载QPixmap + QPixmap pixmap(img_path); + //如果图片加载失败,也是创建占位符,然后组织发送 + if (pixmap.isNull()) { + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + + //说明图片加载正确,构建真实图片 + auto file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, + pixmap, msg_content, file_size, ""); + file_info->_msg_id = msg_id; + file_info->_sender = send_uid; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::None; + //放入chat_datas列表 + auto chat_data = std::make_shared(file_info,"", thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + } + + //发送信号通知界面 + emit sig_load_chat_msg(thread_id, last_msg_id, load_more, chat_datas); + }); +``` + +这里加载了thread会话信息,以及每个会话的消息列表,如果消息列表没有加载完全,则继续发送信号sig_load_chat_msg信号继续加载消息。 + +最终在此处将所有会话的所有消息加载完成 + +``` cpp +void ChatDialog::slot_load_chat_msg(int thread_id, int msg_id, bool load_more, + std::vector> msglists) +{ + _cur_load_chat->SetLastMsgId(msg_id); + //加载聊天信息 + for (auto& chat_msg : msglists) { + _cur_load_chat->AppendMsg(chat_msg->GetMsgId(), chat_msg); + } + + //还有未加载完的消息,就继续加载 + if (load_more) { + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); + return; + } + + //获取下一个chat_thread + _cur_load_chat = UserMgr::GetInstance()->GetNextLoadData(); + //都加载完了 + if(!_cur_load_chat){ + //更新聊天界面信息 + SetSelectChatItem(); + SetSelectChatPage(); + showLoadingDlg(false); + return; + } + + //继续加载下一个聊天 + //发送请求给服务器 + //发送请求逻辑 + QJsonObject jsonObj; + jsonObj["thread_id"] = _cur_load_chat->GetThreadId(); + jsonObj["message_id"] = _cur_load_chat->GetLastMsgId(); + + QJsonDocument doc(jsonObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_LOAD_CHAT_MSG_REQ, jsonData); +} + +``` + +## 资源消息加载 + +核心的资源消息加载是在ID_LOAD_CHAT_MSG_RSP回报的逻辑里 + +``` cpp +_handlers.insert(ID_LOAD_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) { + Q_UNUSED(len); + qDebug() << "handle id is " << id << " data is " << data; + // 将QByteArray转换为QJsonDocument + QJsonDocument jsonDoc = QJsonDocument::fromJson(data); + + // 检查转换是否成功 + if (jsonDoc.isNull()) { + qDebug() << "Failed to create QJsonDocument."; + return; + } + + QJsonObject jsonObj = jsonDoc.object(); + + if (!jsonObj.contains("error")) { + int err = ErrorCodes::ERR_JSON; + qDebug() << "parse create private chat json parse failed " << err; + return; + } + + int err = jsonObj["error"].toInt(); + if (err != ErrorCodes::SUCCESS) { + qDebug() << "get create private chat failed, error is " << err; + return; + } + + qDebug() << "Receive create private chat rsp Success"; + + int thread_id = jsonObj["thread_id"].toInt(); + int last_msg_id = jsonObj["last_message_id"].toInt(); + bool load_more = jsonObj["load_more"].toBool(); + + std::vector> chat_datas; + for (const QJsonValue& data : jsonObj["chat_datas"].toArray()) { + auto send_uid = data["sender"].toInt(); + auto msg_id = data["msg_id"].toInt(); + auto thread_id = data["thread_id"].toInt(); + auto unique_id = data["unique_id"].toInt(); + auto msg_content = data["msg_content"].toString(); + QString chat_time = data["chat_time"].toString(); + int status = data["status"].toInt(); + int msg_type = data["msg_type"].toInt(); + int recv_id = data["receiver"].toInt(); + if (msg_type == int(ChatMsgType::TEXT)) { + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + + if (msg_type == int(ChatMsgType::PIC)) { + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(send_uid); + QString img_path = img_path_str + "/" + msg_content; + //文件不存在,则创建空白图片占位,同时组织数据准备发送 + if (QFile::exists(img_path) == false) { + + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + //如果文件存在 + //如果文件存在则直接构建MsgInfo + // 获取文件大小 + QFileInfo fileInfo(img_path); + qint64 file_size = fileInfo.size(); + //从文件路径加载QPixmap + QPixmap pixmap(img_path); + //如果图片加载失败,也是创建占位符,然后组织发送 + if (pixmap.isNull()) { + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + + //说明图片加载正确,构建真实图片 + auto file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, + pixmap, msg_content, file_size, ""); + file_info->_msg_id = msg_id; + file_info->_sender = send_uid; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::None; + //放入chat_datas列表 + auto chat_data = std::make_shared(file_info,"", thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + } + + //发送信号通知界面 + emit sig_load_chat_msg(thread_id, last_msg_id, load_more, chat_datas); + }); +``` + +核心逻辑是这部分 + +``` cpp + + if (msg_type == int(ChatMsgType::TEXT)) { + auto chat_data = std::make_shared(msg_id, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, msg_content, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } + + if (msg_type == int(ChatMsgType::PIC)) { + auto uid = UserMgr::GetInstance()->GetUid(); + QString storageDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + QString img_path_str = storageDir + "/user/" + QString::number(uid) + "/chatimg/" + QString::number(send_uid); + QString img_path = img_path_str + "/" + msg_content; + //文件不存在,则创建空白图片占位,同时组织数据准备发送 + if (QFile::exists(img_path) == false) { + + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + //如果文件存在 + //如果文件存在则直接构建MsgInfo + // 获取文件大小 + QFileInfo fileInfo(img_path); + qint64 file_size = fileInfo.size(); + //从文件路径加载QPixmap + QPixmap pixmap(img_path); + //如果图片加载失败,也是创建占位符,然后组织发送 + if (pixmap.isNull()) { + CreatePlaceholderImgMsgL(img_path_str, msg_content, + msg_id, thread_id, send_uid, recv_id, status, chat_time, + chat_datas); + continue; + } + + //说明图片加载正确,构建真实图片 + auto file_info = std::make_shared(MsgType::IMG_MSG, img_path_str, + pixmap, msg_content, file_size, ""); + file_info->_msg_id = msg_id; + file_info->_sender = send_uid; + file_info->_receiver = recv_id; + file_info->_thread_id = thread_id; + //设置文件传输的类型 + file_info->_transfer_type = TransferType::Download; + //设置文件传输状态 + file_info->_transfer_state = TransferState::None; + //放入chat_datas列表 + auto chat_data = std::make_shared(file_info,"", thread_id, ChatFormType::PRIVATE, + ChatMsgType::PIC, send_uid, status, chat_time); + chat_datas.push_back(chat_data); + continue; + } +``` + + + + + + + + + + + + + + + + + + + diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day43-webrtc\347\232\204coturn\346\234\215\345\212\241\346\220\255\345\273\272.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day43-webrtc\347\232\204coturn\346\234\215\345\212\241\346\220\255\345\273\272.md" new file mode 100644 index 0000000..2e64c2d --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day43-webrtc\347\232\204coturn\346\234\215\345\212\241\346\220\255\345\273\272.md" @@ -0,0 +1,395 @@ +--- +title: webrtc的coturn服务搭建 +date: 2026-02-11 08:51:30 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +## 前情回顾 + +前面我们已经将聊天的基本功能完成了,接下来来安装coturn服务,生成webrtc视频通信 + +coturn服务集成了stun和turn服务器 + +------ + +**三个常用的概念** + +> **STUN = 告诉你自己是谁** +> **TURN = 帮你转发数据** +> **coturn = STUN/TURN 的服务器实现软件** + +------ + +![image-20260212125500580](https://cdn.llfc.club/image-20260212125500580.png) + + + +## 为什么需要 STUN / TURN? + +因为现在大部分设备都在 **NAT(内网)后面**: + +``` +手机/电脑 → 路由器(NAT) → 公网 +``` + +内网 IP(192.168.x.x)在公网是看不到的。 + +WebRTC / 视频通话 / P2P 通信 就必须解决: + +👉 “我怎么让对方知道我的公网地址?” + +------ + +## STUN 是什么? + +### 全称: + +Session Traversal Utilities for NAT + +### 作用: + +👉 **告诉客户端:你的公网 IP 和端口是多少** + +工作流程: + +``` +客户端 → STUN服务器 +STUN服务器 → 告诉你:你在公网看到的地址是 1.2.3.4:5678 +``` + +然后客户端把这个地址发给对方。 + +------ + +### ✅ 优点 + +- 轻量 +- 免费 +- 不转发数据 + +### ❌ 缺点 + +- 只能在 NAT 允许打洞的情况下成功 +- 对称 NAT 基本失败 + +------ + +## TURN 是什么? + +### 全称: + +Traversal Using Relays around NAT + +### 作用: + +👉 **当打洞失败时,帮你转发数据** + +工作模式: + +``` +A → TURN服务器 → B +``` + +TURN 服务器相当于一个“中转站”。 + +------ + +### ✅ 优点 + +- 几乎 100% 成功 +- 解决所有 NAT 问题 + +### ❌ 缺点 + +- 服务器要承担带宽 +- 成本高 + +------ + +## coturn 是什么? + +👉 coturn 是一个 **开源的 STUN + TURN 服务器软件** + +官网: + https://github.com/coturn/coturn + +你部署 coturn 之后: + +- 可以当 STUN 服务器 +- 也可以当 TURN 服务器 + +------ + +### 三者关系图 + +``` + WebRTC 通信 + │ + ┌───────────┴───────────┐ + │ │ + 先尝试 STUN 如果失败 → TURN + │ │ + 直接P2P通信 通过服务器转发 + │ + coturn + (实现STUN和TURN的程序) +``` + + + +## 安装coturn + +因为docker被限制,自己尝试安装了docker拉取coturn服务还是超时,所以果断选择本机安装。 + +本机安装有两种方式,一种源码方式,一种集成服务安装。 + +官方推荐集成服务安装,源码安装是为了制作自己的webrtc服务,修改源码才用到,这里我们不用。 + +``` bash +# 更新软件包 +sudo apt update + +# 安装 Coturn +sudo apt install coturn -y + +# 查看版本 +turnserver --help | head -1 + +``` + +## 修改配置文件 + +先备份原来的配置文件 + +``` bash +sudo cp /etc/turnserver.conf /etc/turnserver.conf.bak +``` + +再修改配置文件 + +``` bash +sudo vim /etc/turnserver.conf +``` + +改为如下内容 + +``` bash +# 监听端口 +listening-ip = 0.0.0.0 +listening-port=3478 +tls-listening-port=5349 + +# 外部 IP +external-ip=81.68.86.146 +#relay-ip=81.68.86.146 + +# 启用指纹 +fingerprint + +# 使用长期凭证机制 +lt-cred-mech + +# 用户认证 +user=webrtc:Kx9mP2qL8rY5tZ + +# Realm +realm=turn.example.com + +# 日志 +log-file=/var/log/turnserver/turnserver.log +verbose + +# 端口范围 +min-port=49152 +max-port=65535 + +# 拒绝私有 IP +no-multicast-peers +denied-peer-ip=0.0.0.0-0.255.255.255 +denied-peer-ip=10.0.0.0-10.255.255.255 +denied-peer-ip=172.16.0.0-172.31.255.255 +denied-peer-ip=192.168.0.0-192.168.255.255 + +``` + +## 创建日志目录 + +```bash +# 创建日志目录 +sudo mkdir -p /var/log/turnserver + +# 设置权限 +sudo chown turnserver:turnserver /var/log/turnserver +``` + +### 验证服务 + +```bash +# 查看端口监听 +sudo netstat -tuln | grep 3478 + +# 查看日志 +sudo tail -f /var/log/turnserver/turnserver.log + +# 或者 +sudo journalctl -u coturn -f +``` + + + +## 启用并启动服务 + +``` +# 启用 Coturn 服务 +sudo sed -i 's/#TURNSERVER_ENABLED=1/TURNSERVER_ENABLED=1/' /etc/default/coturn + +# 启动服务 +sudo systemctl enable coturn +sudo systemctl start coturn + +# 查看状态 +sudo systemctl status coturn +``` + +如果出错,可以手动编辑设置启动 Coturn 服务 + +``` +# 编辑配置文件 +sudo vim /etc/default/coturn +``` + +找到这一行: + +``` +#TURNSERVER_ENABLED=1 +``` + +**去掉注释符号 `#`**,改为: + +``` +TURNSERVER_ENABLED=1 +``` + +保存并且退出 + +## 常用管理命令 + +```bash +# 启动服务 +sudo systemctl start coturn + +# 停止服务 +sudo systemctl stop coturn + +# 重启服务 +sudo systemctl restart coturn + +# 查看状态 +sudo systemctl status coturn + +# 查看日志 +sudo journalctl -u coturn -n 100 -f + +# 查看配置文件 +sudo cat /etc/turnserver.conf +``` + +------ + +## 云服务器开启端口 + +### 必须开放的端口: + +- **3478** (UDP + TCP) - STUN/TURN 主端口 +- **49152-65535** (UDP) - TURN 数据中继端口范围 + +### 可选端口(如果使用 TLS): + +- **5349** (UDP + TCP) - TURN over TLS + +------ + +## 腾讯云安全组配置步骤 + +### 1. 登录腾讯云控制台 + +访问:https://console.cloud.tencent.com/cvm/instance + +### 2. 配置安全组 + +``` +控制台 → 云服务器 → 实例列表 → 找到你的服务器 → 安全组 → 修改规则 +``` + +### 3. 添加入站规则 + +| 类型 | 端口范围 | 协议 | 来源 | 策略 | +| ------ | ----------- | ---- | --------- | ---- | +| 自定义 | 3478 | UDP | 0.0.0.0/0 | 允许 | +| 自定义 | 3478 | TCP | 0.0.0.0/0 | 允许 | +| 自定义 | 49152-65535 | UDP | 0.0.0.0/0 | 允许 | +| 自定义 | 5349 | UDP | 0.0.0.0/0 | 允许 | +| 自定义 | 5349 | TCP | 0.0.0.0/0 | 允许 | + +------ + +![image-20260211135234856](https://cdn.llfc.club/image-20260211135234856.png) + +## 快速验证端口是否开放 + +在你的服务器上执行: + +``` +# 查看 Coturn 是否监听端口 +sudo netstat -tuln | grep -E '3478|5349' + +# 应该看到类似输出: +# udp 0 0 0.0.0.0:3478 0.0.0.0:* +# tcp 0 0 0.0.0.0:3478 0.0.0.0:* +``` + +从外部测试(在你的本地电脑上): + +``` +# 测试 UDP 端口(需要安装 nc) +nc -u -v 81.68.86.146 3478 + +# 测试 TCP 端口 +nc -v 81.68.86.146 3478 +``` + +## 测试 TURN 服务 + +访问测试页面:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/ + +填入: + +- **TURN URI**: `turn:81.68.86.146:3478` +- **Username**: `webrtc` +- **Password**: `Kx9mP2qL8rY5tZ` + +点击 **Gather candidates**,如果看到 `relay` 类型的候选者,说明成功! + +先添加,然后点击add server + +![image-20260211132631986](https://cdn.llfc.club/image-20260211132631986.png) + +然后点击下方 + +![image-20260211133328948](https://cdn.llfc.club/image-20260211133328948.png) + +------ + +## 如果需要修改配置 + +``` +# 编辑配置文件 +sudo vim /etc/turnserver.conf + +# 保存后重启服务 +sudo systemctl restart coturn + +# 查看日志确认 +sudo journalctl -u coturn -f +``` diff --git "a/\345\274\200\345\217\221\346\226\207\346\241\243/day44-webrtc\344\277\241\344\273\244\346\234\215\345\212\241\345\231\250\345\256\236\347\216\260.md" "b/\345\274\200\345\217\221\346\226\207\346\241\243/day44-webrtc\344\277\241\344\273\244\346\234\215\345\212\241\345\231\250\345\256\236\347\216\260.md" new file mode 100644 index 0000000..604a22a --- /dev/null +++ "b/\345\274\200\345\217\221\346\226\207\346\241\243/day44-webrtc\344\277\241\344\273\244\346\234\215\345\212\241\345\231\250\345\256\236\347\216\260.md" @@ -0,0 +1,467 @@ +--- +title: webrtc信令服务器实现 +date: 2026-02-11 19:23:38 +tags: [C++聊天项目] +categories: [C++聊天项目] +--- + +# WebRTC 1v1 视频通话技术方案(Node.js + WebSocket) + +------ + +# 一、整体架构设计 + +## 1.1 系统架构图 + +``` +浏览器A ─────┐ + │ (SDP / ICE 交换) +浏览器B ─────┼──── WebSocket ─── 信令服务器 (Node.js) + │ + │ + 媒体流 (P2P / TURN 中继) +``` + +## 1.2 组件职责 + +| 组件 | 职责 | +| ----------- | ---------------------------------- | +| 前端浏览器 | 建立 RTCPeerConnection,采集音视频 | +| 信令服务器 | 交换 offer / answer / ice | +| TURN 服务器 | NAT 穿透失败时中继媒体流 | +| STUN | 获取公网候选地址 | + +------ + +# 二、信令服务器技术选型 + +| 技术 | 原因 | +| -------- | --------------------- | +| Express | 快速搭建 HTTP 服务 | +| ws | 轻量级 WebSocket 实现 | +| 原生 Map | 管理房间 | + +信令服务器不参与媒体传输,只负责: + +- 房间管理 +- 消息转发 + + + +# 三、核心代码结构解析 + +## 3.0通信流程 + +![image-20260213085510995](https://cdn.llfc.club/image-20260213085510995.png) + + + +------ + +## 3.1 静态资源加载 + +```js +app.use(express.static(path.join(__dirname, "..", "web"))); +``` + +### 作用 + +- 将 web 目录暴露为 HTTP 静态站点 +- 访问 [http://localhost:3000](http://localhost:3000/) 即加载 index.html + +------ + +## 3.2 WebSocket 服务器创建 + +```js +const wss = new WebSocketServer({ server }); +``` + +说明: + +- 复用 HTTP 服务器 +- WebSocket 与 HTTP 共享 3000 端口 + +------ + +# 四、房间模型设计 + +```js +const rooms = new Map(); +``` + +结构: + +``` +Map> +``` + +示例: + +``` +rooms = { + "1001" => Set(wsA, wsB) +} +``` + +设计思想: + +- 每个房间最多 2 人 +- 每个 ws 保存自己所属 roomId + +------ + +# 五、信令流程设计 + +## 5.1 加入房间流程 + +客户端发送: + +```json +{ + "type": "join", + "roomId": "1001" +} +``` + +服务器逻辑: + +1. 检查 roomId +2. 从旧房间移除 +3. 如果人数 >= 2 返回 full +4. 加入房间 +5. 返回 joined +6. 如果人数 == 2,发送 ready + +------ + +## 5.2 ready 阶段 + +当房间人数 = 2 时: + +```js +send(peer, { type: "ready", isInitiator }); +``` + +设计: + +- 后加入者作为 initiator +- initiator 负责创建 offer + +------ + +## 5.3 WebRTC 协商流程 + +### 时序图 + +``` +Initiator Receiver + | | + | ---- offer ----------> | + | | + | <--- answer -----------| + | | + | <--- ICE --------------| + | ---- ICE ------------> | +``` + +------ + +## 5.4 信令转发逻辑 + +```js +if (type === "offer" || type === "answer" || type === "ice") { + relayToOthers(roomId, ws, msg); +} +``` + +服务器不解析 SDP,不参与媒体。 + +它只是“转发器”。 + +------ + +# 六、核心函数解析 + +------ + +## 6.1 send() + +```js +function send(ws, data) { + if (ws.readyState === ws.OPEN) + ws.send(JSON.stringify(data)); +} +``` + +说明: + +- 统一发送 JSON +- 防止向已关闭连接发送数据 + +------ + +## 6.2 relayToOthers() + +```js +function relayToOthers(roomId, sender, data) +``` + +功能: + +- 向房间内除自己外的人广播 +- 实现一对一信令交换 + +------ + +## 6.3 removeFromRoom() + +负责: + +- 用户离开 +- 通知房间剩余成员 +- 清理空房间 + +防止内存泄漏。 + +------ + +# 七、连接生命周期管理 + +```js +ws.on("close", () => removeFromRoom(ws)); +ws.on("error", () => removeFromRoom(ws)); +``` + +说明: + +- 防止异常断开导致房间脏数据 +- 保证 rooms 数据一致性 + +------ + +## 完整源码 + +``` js +import express from "express"; +import http from "http"; +import { WebSocketServer } from "ws"; + +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const app = express(); +// 把 web 目录设置成:server 的上一级 + /web +app.use(express.static(path.join(__dirname, "..", "web"))); + +const server = http.createServer(app); +const wss = new WebSocketServer({ server }); + +/** + * rooms: Map> + */ +const rooms = new Map(); + +/** 给某个 ws 发送 JSON */ +function send(ws, data) { + if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(data)); +} + +/** 房间内给除了自己之外的其他人转发 */ +function relayToOthers(roomId, sender, data) { + const set = rooms.get(roomId); + if (!set) return; + for (const peer of set) { + if (peer !== sender) send(peer, data); + } +} + +function removeFromRoom(ws) { + const roomId = ws.roomId; + if (!roomId) return; + + const set = rooms.get(roomId); + if (!set) return; + + set.delete(ws); + // 通知剩余的人:对方离开 + for (const peer of set) { + send(peer, { type: "peer-left" }); + } + + if (set.size === 0) rooms.delete(roomId); + ws.roomId = null; +} + +wss.on("connection", (ws) => { + ws.roomId = null; + + ws.on("message", (buf) => { + let msg; + try { + msg = JSON.parse(buf.toString()); + } catch { + return; + } + + const { type } = msg; + + if (type === "join") { + const roomId = String(msg.roomId || "").trim(); + if (!roomId) return send(ws, { type: "error", message: "roomId is required" }); + + // 如果 ws 已在别的房间,先移除 + removeFromRoom(ws); + + const set = rooms.get(roomId) || new Set(); + if (set.size >= 2) { + return send(ws, { type: "full", roomId }); + } + + set.add(ws); + rooms.set(roomId, set); + ws.roomId = roomId; + + send(ws, { type: "joined", roomId, peers: set.size - 1 }); + + // 房间凑齐 2 人,通知双方开始协商 + if (set.size === 2) { + // 约定:后加入的人做 initiator(也可以反过来) + for (const peer of set) { + const isInitiator = peer === ws; + send(peer, { type: "ready", isInitiator }); + } + } + return; + } + + // 后面的消息都必须在房间里 + const roomId = ws.roomId; + if (!roomId) return send(ws, { type: "error", message: "join a room first" }); + + // 透传 WebRTC 协商消息 + if (type === "offer" || type === "answer" || type === "ice") { + relayToOthers(roomId, ws, msg); + return; + } + + if (type === "leave") { + removeFromRoom(ws); + send(ws, { type: "left" }); + return; + } + }); + + ws.on("close", () => removeFromRoom(ws)); + ws.on("error", () => removeFromRoom(ws)); +}); + +const PORT = process.env.PORT || 3000; +server.listen(PORT, "0.0.0.0", () => { + console.log(`Signaling+Web server running: http://localhost:${PORT}`); +}); + +``` + + + +# 八、为什么信令服务器不处理媒体? + +因为: + +WebRTC 是 P2P 协议。 + +媒体路径: + +``` +浏览器A ←→ 浏览器B +``` + +不是: + +``` +浏览器A → 服务器 → 浏览器B +``` + +除非使用 SFU。 + +------ + +# 九、当前版本限制 + +| 项目 | 当前实现 | +| -------- | --------- | +| 房间人数 | 最多 2 人 | +| 认证 | 无 | +| 房间权限 | 无 | +| 重连机制 | 无 | +| 多人视频 | 不支持 | + +------ + +# 十、如何扩展为多人房间(技术方向) + +当前结构: + +``` +Map> +``` + +升级方案: + +1. 为每个 ws 分配唯一 peerId +2. 信令改为定向发送 +3. 前端维护: + +``` +Map +``` + +每加入一个人: + +- 为其创建一个新的 PeerConnection +- 动态创建 video 元素 + +这叫: + +> Mesh 架构 + +------ + +# 十一、生产环境建议 + +## 1️⃣ 使用 HTTPS + WSS + +WebRTC 在公网通常必须 HTTPS。 + +## 2️⃣ TURN 使用动态签名 + +不要写死: + +``` +user=webrtc:password +``` + +应改为: + +``` +use-auth-secret +static-auth-secret=xxx +``` + +防止带宽被盗用。 + +## 3️⃣ 加入房间认证 + +目前任何人知道房间号即可进入。 + +应加入: + +- token +- 用户身份 + +------ + diff --git "a/\346\233\264\346\226\260\350\256\260\345\275\225.md" "b/\346\233\264\346\226\260\350\256\260\345\275\225.md" new file mode 100644 index 0000000..2b326f8 --- /dev/null +++ "b/\346\233\264\346\226\260\350\256\260\345\275\225.md" @@ -0,0 +1,302 @@ +## 2025/10/27 + +### 调整MsgInfo + +``` cpp +struct MsgInfo{ + + MsgInfo(MsgType msgtype, QString text_or_url, QPixmap pixmap, QString unique_name, qint64 total_size, QString md5) + :_msg_type(msgtype), _text_or_url(text_or_url), _preview_pix(pixmap),_unique_name(unique_name),_total_size(total_size), + _current_size(0),_seq(1),_md5(md5) + {} + + MsgType _msg_type; + QString _text_or_url;//表示文件和图像的url,文本信息 + QPixmap _preview_pix;//文件和图片的缩略图 + QString _unique_name; //文件唯一名字 + qint64 _total_size; //文件总大小 + qint64 _current_size; //传输大小 + qint64 _seq; //传输序号 + QString _md5; //文件md5 +}; +``` + +### 修改插入消息的逻辑 + +``` cpp +void MessageTextEdit::insertMsgList(QVector> &list, MsgType msgtype, + QString text_or_url, QPixmap preview_pix, + QString unique_name, uint64_t total_size, QString md5) { + + auto msg_info = std::make_shared(msgtype, text_or_url, preview_pix, unique_name, total_size, md5); + list.append(msg_info); + +} +``` + +### 修改发送拼接逻辑 + +``` cpp +void ChatPage::on_send_btn_clicked() { + if (_chat_data == nullptr) { + qDebug() << "friend_info is empty"; + return; + } + + auto user_info = UserMgr::GetInstance()->GetUserInfo(); + auto pTextEdit = ui->chatEdit; + ChatRole role = ChatRole::Self; + QString userName = user_info->_name; + QString userIcon = user_info->_icon; + + const QVector>& msgList = pTextEdit->getMsgList(); + QJsonObject textObj; + QJsonArray textArray; + int txt_size = 0; + auto thread_id = _chat_data->GetThreadId(); + for (int i = 0; i < msgList.size(); ++i) + { + //消息内容长度不合规就跳过 + if (msgList[i]->_text_or_url.length() > 1024) { + continue; + } + + MsgType type = msgList[i]->_msg_type; + ChatItemBase* pChatItem = new ChatItemBase(role); + pChatItem->setUserName(userName); + SetSelfIcon(pChatItem, user_info->_icon); + QWidget* pBubble = nullptr; + //生成唯一id + QUuid uuid = QUuid::createUuid(); + //转为字符串 + QString uuidString = uuid.toString(); + if (type == MsgType::TEXT_MSG) + { + pBubble = new TextBubble(role, msgList[i]->_text_or_url); + if (txt_size + msgList[i]->_text_or_url.length() > 1024) { + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + //将bubble和uid绑定,以后可以等网络返回消息后设置是否送达 + //_bubble_map[uuidString] = pBubble; + txt_size += msgList[i]->_text_or_url.length(); + QJsonObject obj; + QByteArray utf8Message = msgList[i]->_text_or_url.toUtf8(); + auto content = QString::fromUtf8(utf8Message); + obj["content"] = content; + obj["unique_id"] = uuidString; + textArray.append(obj); + //todo... 注意,此处先按私聊处理 + auto txt_msg = std::make_shared(uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, content, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString, txt_msg); + } + else if (type == MsgType::IMG_MSG) + { + //将之前缓存的文本发送过去 + if (txt_size) { + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["text_array"] = textArray; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); + } + + pBubble = new PictureBubble(QPixmap(msgList[i]->_text_or_url), role); + //需要组织成文件发送,具体参考头像上传 + auto img_msg = std::make_shared(msgList[i],uuidString, thread_id, ChatFormType::PRIVATE, + ChatMsgType::TEXT, user_info->_uid, 0); + //将未回复的消息加入到未回复列表中,以便后续处理 + _chat_data->AppendUnRspMsg(uuidString, img_msg); + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + textObj["md5"] = msgList[i]->_md5; + textObj["name"] = msgList[i]->_unique_name; + textObj["token"] = UserMgr::GetInstance()->GetToken(); + textObj["unique_id"] = uuidString; + //创建QFileInfo 对象 + QFile file(msgList[i]->_text_or_url); + file.seek(msgList[i]->_current_size); + auto buffer = file.read(MAX_FILE_LEN); + msgList[i]->_seq++; + QJsonObject file_obj; + file_obj["name"] = msgList[i]->_unique_name; + file_obj["unique_id"] = uuidString; + file_obj["seq"] = msgList[i]->_seq; + msgList[i]->_current_size = buffer.size() + (msgList[i]->_seq - 1) * MAX_FILE_LEN; + file_obj["trans_size"] = msgList[i]->_current_size; + file_obj["total_size"] = msgList[i]->_total_size; + file_obj["token"] = UserMgr::GetInstance()->GetToken(); + //文件信息加入管理 + UserMgr::GetInstance()->AddTransFile(msgList[i]->_unique_name, msgList[i]); + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_IMG_CHAT_MSG_REQ, jsonData); + + //发送文件 + QJsonDocument doc_file(file_obj); + QByteArray fileData = doc_file.toJson(QJsonDocument::Compact); + //发送tcp请求给资源服务器 + emit FileTcpMgr::GetInstance()->sig_send_data(ReqId::ID_IMG_CHAT_UPLOAD_REQ, fileData); + + } + else if (type == MsgType::FILE_MSG) + { + + } + //发送消息 + if (pBubble != nullptr) + { + pChatItem->setWidget(pBubble); + pChatItem->setStatus(0); + ui->chat_data_list->appendChatItem(pChatItem); + _unrsp_item_map[uuidString] = pChatItem; + } + + } + + qDebug() << "textArray is " << textArray; + //发送给服务器 + textObj["text_array"] = textArray; + textObj["fromuid"] = user_info->_uid; + textObj["touid"] = _chat_data->GetOtherId(); + textObj["thread_id"] = thread_id; + QJsonDocument doc(textObj); + QByteArray jsonData = doc.toJson(QJsonDocument::Compact); + //发送并清空之前累计的文本列表 + txt_size = 0; + textArray = QJsonArray(); + textObj = QJsonObject(); + //发送tcp请求给chat server + emit TcpMgr::GetInstance()->sig_send_data(ReqId::ID_TEXT_CHAT_MSG_REQ, jsonData); +} +``` + + + +### 客户端和服务器消息状态新增 + +``` cpp +enum MsgStatus{ + UN_READ = 0, //对方未读 + SEND_FAILED = 1, //发送失败 + READED = 2, //对方已读 + UN_UPLOAD = 3 //未上传完成 +}; +``` + +### chatserver接收消息逻辑 + +``` cpp +_fun_callbacks[ID_IMG_CHAT_MSG_REQ] = std::bind(&LogicSystem::DealChatImgMsg, this, + placeholders::_1, placeholders::_2, placeholders::_3); +void LogicSystem::DealChatImgMsg(std::shared_ptr session, + const short& msg_id, const string& msg_data) { +``` + + + +### 接收服务器回传 + +``` cpp +_handlers.insert(ID_IMG_CHAT_MSG_RSP, [this](ReqId id, int len, QByteArray data) +``` + +## 2025/12/13 + +### 新增发送拥塞窗口 + +``` C++ +void FileTcpMgr::BatchSend(std::shared_ptr msg_info) { + + if ((msg_info->_seq) * MAX_FILE_LEN >= msg_info->_total_size) { + qDebug() << "file has sent finished"; + return; + } + + //打开 + QFile file(msg_info->_text_or_url); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Could not open file: " << file.errorString(); + return; + } + + //文件偏移到已经发送的位置,继续读取发送 + file.seek(msg_info->_seq * MAX_FILE_LEN); + + bool b_last = false; + //再次组织数据发送 + for (int i = 0; i < MAX_CWND_SIZE - _cwnd_size; i++) { + + QByteArray buffer; + msg_info->_seq++; + //放入发送未回包集合 + msg_info->_flighting_seqs.insert(msg_info->_seq); + //每次读取MAX_FILE_LEN字节发送 + buffer = file.read(MAX_FILE_LEN); + QJsonObject sendObj; + //将文件内容转换为base64编码 + QString base64Data = buffer.toBase64(); + sendObj["md5"] = msg_info->_md5; + sendObj["name"] = msg_info->_unique_name; + sendObj["seq"] = msg_info->_seq; + sendObj["trans_size"] = buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN; + sendObj["total_size"] = msg_info->_total_size; + + b_last = false; + if (buffer.size() + (msg_info->_seq - 1) * MAX_FILE_LEN >= msg_info->_total_size) { + sendObj["last"] = 1; + b_last = true; + } + else { + sendObj["last"] = 0; + } + + sendObj["data"] = base64Data; + sendObj["last_seq"] = msg_info->_max_seq; + sendObj["uid"] = UserMgr::GetInstance()->GetUid(); + QJsonDocument doc(sendObj); + auto send_data = doc.toJson(); + //直接发送,其实是放入tcpmgr发送队列 + SendData(ID_IMG_CHAT_UPLOAD_REQ, send_data); + + //如果 + if (b_last) { + break; + } + } + + file.close(); +} +``` + +### 服务器接收信息同步逻辑 + +``` cpp +``` + + + + + diff --git "a/\347\254\254\344\270\211\345\255\243\345\276\205\345\201\232\344\272\213\344\273\266.md" "b/\347\254\254\344\270\211\345\255\243\345\276\205\345\201\232\344\272\213\344\273\266.md" new file mode 100644 index 0000000..861c812 --- /dev/null +++ "b/\347\254\254\344\270\211\345\255\243\345\276\205\345\201\232\344\272\213\344\273\266.md" @@ -0,0 +1,12 @@ +# 第三季待做事项 + +## 将webrtc+QT结合 + +## 增强Status服务,作为中心调度 + +## 新增客户端本地数据库 + +## Go语言讲解改造信令服务器 + +## 多人视频通话,MESH或者SFU +