This repository has been archived on 2021-11-25. You can view files and clone it, but cannot push or open issues/pull-requests.
KChatWSServer/KChatWSServer.cpp

290 lines
10 KiB
C++
Raw Permalink Normal View History

2018-09-07 16:07:30 +08:00
<EFBFBD><EFBFBD>#include "gsock.h"
#include "gsock_helper.h"
#include <string>
#include <iostream>
#include <sstream>
#include <thread>
#include <vector>
#include <algorithm>
#include <mutex>
#include <queue>
#include "websocket.h"
using namespace std;
// <EFBFBD>mo`<EFBFBD>. c gُ*N<EFBFBD><EFBFBD>v<EFBFBD>eP<EFBFBD>S<EFBFBD>N<EFBFBD>~<EFBFBD>~<EFBFBD><EFBFBD><EFBFBD>Sm_sockvec
mutex m_msgbus;
vector<string> msgbus;
// socket<EFBFBD>. <EFBFBD>la<EFBFBD>Y<EFBFBD>g<EFBFBD><EFBFBD><EFBFBD>`<EFBFBD><EFBFBD><EFBFBD>S$N*N<EFBFBD><EFBFBD>_{<EFBFBD>HQ<EFBFBD><EFBFBD><EFBFBD>S<EFBFBD>mo`<EFBFBD>R<EFBFBD>
mutex m_sockvec;
vector<pair<sock*, string>> sockvec;
condition_variable cond_msg;
void ChatWorker()
{
unique_lock<mutex> ulk(m_msgbus);
while (true)
{
cond_msg.wait(ulk);
unique_lock<mutex> ulsk(m_sockvec);
for (auto iter = sockvec.begin(); iter != sockvec.end(); )
{
bool bad = false;
for (const auto& msg : msgbus)
{
if (SendMsg(*(iter->first), msg) <= 0)
{
bad = true;
break;
}
}
if (bad)
{
delete iter->first;
iter = sockvec.erase(iter);
}
else ++iter;
}
msgbus.clear();
}
}
std::string MessageFilter(const std::string& str)
{
std::string output;
for (const auto& c : str)
{
if (c == '<' || c == '>') output.push_back(' ');
else output.push_back(c);
}
return output;
}
// <EFBFBD>(udk<EFBFBD>QpeKNMR<EFBFBD>_{<EFBFBD><EFBFBD>]<EFBFBD>~c gm_sockvec<EFBFBD>
// ԏ<EFBFBD>V-1h<EFBFBD>f<EFBFBD>mo`<EFBFBD>S<EFBFBD><EFBFBD><EFBFBD><EFBFBD>.FOsock\*g<EFBFBD><EFBFBD>ʑ>e.
int SendOnlineList_L(sock* ps)
{
if (SendMsg(*ps, "#*Lclr") <= 0)
{
return -1;
}
else
{
// <EFBFBD>S<EFBFBD>(W<EFBFBD>~Rh<EFBFBD>
for (auto xter = sockvec.cbegin(); xter != sockvec.cend(); ++xter)
{
if (SendMsg(*ps, string("#*Ladd ") + xter->second) <= 0)
{
return -1;
}
}
return 0;
}
}
// <EFBFBD>(udk<EFBFBD>QpeKNMR<EFBFBD>_{<EFBFBD><EFBFBD>]<EFBFBD>~c gm_sockvec<EFBFBD>
void NoticeJoin_L(sock* ps, const string& thisName)
{
for (auto iter = sockvec.begin(); iter != sockvec.end();)
{
if (iter->first != ps)
{
// N/f<EFBFBD>e<EFBFBD>ReQ<EFBFBD>v(u7bۏL<EFBFBD><EFBFBD>Xϑ<EFBFBD><EFBFBD>w
if (SendMsg(*(iter->first), string("#*Ladd ") + thisName) <= 0)
{
delete iter->first;
iter = sockvec.erase(iter);
}
else
{
++iter;
}
}
else
{
// <EFBFBD>Y<EFBFBD>g/f<EFBFBD>e<EFBFBD>ReQ<EFBFBD>v(u7bR<EFBFBD>S<EFBFBD>(W<EFBFBD>~Rh<EFBFBD>
if (SendOnlineList_L(ps) < 0)
{
delete ps;
iter = sockvec.erase(iter);
}
else
{
++iter;
}
}
}
}
// 1: <EFBFBD>mo`/fcommand <EFBFBD>N<EFBFBD>]<EFBFBD>~<EFBFBD>[bYt
// 0: <EFBFBD>mo` N/fcommand
// -1: <EFBFBD>mo`&{Tcommand<h_,FO N/f<EFBFBD>]<EFBFBD>w<EFBFBD>vcommand
int DoCommand(const std::string& str,std::string& thisName)
{
if (str.size() < 6)
{
return 0;
}
string head = str.substr(0, 6);
if (head == "*#nick" && str.size() >= 8) // 5f<EFBFBD>y<EFBFBD>S<EFBFBD>f
{
string cmd1 = "#*Ldel " + thisName;
string cmd2 = "#*Ladd " + str.substr(7);
{
unique_lock<mutex> ulk(m_msgbus);
msgbus.push_back(cmd1);
msgbus.push_back(cmd2);
cond_msg.notify_all();
}
cout << "Nickname changed from " << thisName << " to " << str.substr(7) << endl;
thisName = str.substr(7);
return 1;
}
// *g<EFBFBD>w}T<EFBFBD>N
else if (str.substr(0, 2) == "*#") // FO/f&{T}T<EFBFBD>Nw<EFBFBD><EFBFBD>Y&{
{
return -1;
}
else
{
return 0;
}
}
void Worker(sock* ps)
{
sock& s = *ps;
if (Handshake(s) < 0)
{
cout << "Failed to finish Handshake on " << ps << endl;
return;
}
string thisName;
{
string firstmsg;
int xret = ReadMsg(s, firstmsg);
if (xret <= 0 || firstmsg.size() < 6) // <EFBFBD><EFBFBD> N<EFBFBD>Qegb<EFBFBD>}T<EFBFBD>N*Y<EFBFBD>w<EFBFBD>N
{
delete ps;
return;
}
string firstcmd = firstmsg.substr(0, 6);
if (firstcmd == "*#newj")
{
thisName = "NoName";
}
else if (firstcmd == "*#name")
{
if (firstmsg.size() < 8) // }T<EFBFBD>N*Y<EFBFBD>w<EFBFBD>N
{
delete ps;
return;
}
else
{
thisName = firstmsg.substr(7);
}
}
else {
// ^<EFBFBD><EFBFBD>l<EFBFBD>v(u7bbc<EFBFBD>N
delete ps;
return;
}
}
// <EFBFBD><EFBFBD>dkY,(u7b:NT<EFBFBD>l(u7b. <EFBFBD>ReQ0R<EFBFBD>[7b<EFBFBD>zRh<EFBFBD>-Nv^N/T<EFBFBD>R<EFBFBD><EFBFBD>w.
{
unique_lock<mutex> xlk(m_sockvec);
sockvec.push_back(make_pair(ps, thisName));
NoticeJoin_L(ps, thisName);
}
string data;
while (true)
{
int ret = ReadMsg(s, data);
cout << "ReadMsg: " << ret << endl;
cout << data << endl;
if (ret <= 0) break;
data = MessageFilter(data);
if (DoCommand(data, thisName) != 0)
{
continue;
}
unique_lock<mutex> ulk(m_msgbus);
msgbus.push_back(data);
cond_msg.notify_all();
}
// 1uread<EFBFBD>[<EFBFBD><EFBFBD><EFBFBD>v<EFBFBD><EFBFBD>Q
bool found = false;
{
// <EFBFBD>g~bS_MRworker<EFBFBD>vsocket. ~b0R<EFBFBD>v݋<EFBFBD>N<EFBFBD>R-N<EFBFBD>yd<EFBFBD>
unique_lock<mutex> ulk(m_sockvec);
for (auto iter = sockvec.begin(); iter != sockvec.end(); ++iter)
{
if (iter->first == ps)
{
sockvec.erase(iter);
found = true;
break;
}
}
}
// <EFBFBD>Y<EFBFBD>g~b0R,R1u<EFBFBD><EFBFBD><EFBFBD>]ʑ>eD<EFBFBD><EFBFBD>n.(&TR1uChatWorkerʑ>eُ*Nsocket,sS<EFBFBD>V:Nsend<EFBFBD>Q<EFBFBD><EFBFBD>[<EFBFBD><EFBFBD><EFBFBD>v<EFBFBD><EFBFBD>Q)
if (found)
{
delete ps;
}
// <EFBFBD>c<EFBFBD><EFBFBD><EFBFBD>Q<EFBFBD>mo`0R<EFBFBD>R-N
{
data = "#*Ldel ";
data.append(thisName);
string xdata(thisName);
xdata.append(" disconnected.");
unique_lock<mutex> ulk(m_msgbus);
msgbus.push_back(data);
msgbus.push_back(xdata);
cond_msg.notify_all();
}
}
int main()
{
serversock t;
if (t.bind(59505) < 0 || t.listen(10) < 0)
{
cout << "Failed to bind or listen." << endl;
}
thread tdc(ChatWorker);
tdc.detach();
while (true)
{
sock* ps = new sock;
sock& s = *ps;
int ret = t.accept(s);
if (ret < 0)
{
cout << "Failed to accept. Stop." << endl;
break;
}
cout << "Accepted: " << ps << endl;
thread td(Worker, ps);
td.detach();
}
return 0;
}