mirror of
https://github.com/wfjm/w11.git
synced 2026-04-30 13:42:21 +00:00
add HasPort/HasVirt(); Port() and Virt() return reference
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// $Id: RlinkConnect.cpp 1076 2018-12-02 12:45:49Z mueller $
|
||||
// $Id: RlinkConnect.cpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2011-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 2.8 add HasPort(); return ref for Port()
|
||||
// 2018-12-01 1076 2.7 use unique_ptr instead of scoped_ptr
|
||||
// 2018-11-30 1075 2.6.4 use list-init; use range loop
|
||||
// 2018-10-27 1059 2.6.3 coverity fixup (uncaught exception in dtor)
|
||||
@@ -176,19 +177,19 @@ bool RlinkConnect::Open(const std::string& name, RerrMsg& emsg)
|
||||
Close();
|
||||
|
||||
fupPort = move(RlinkPortFactory::Open(name, emsg));
|
||||
if (!fupPort) return false;
|
||||
if (!HasPort()) return false;
|
||||
|
||||
fSndPkt.SetXonEscape(fupPort->XonEnable()); // transfer XON enable
|
||||
fSndPkt.SetXonEscape(Port().XonEnable()); // transfer XON enable
|
||||
|
||||
fupPort->SetLogFile(fspLog);
|
||||
fupPort->SetTraceLevel(fTraceLevel);
|
||||
Port().SetLogFile(fspLog);
|
||||
Port().SetTraceLevel(fTraceLevel);
|
||||
|
||||
fLinkInitDone = false;
|
||||
fRbufSize = 2048; // use minimum (2kB) as startup
|
||||
fSysId = 0xffffffff;
|
||||
fUsrAcc = 0x00000000;
|
||||
|
||||
if (! fupPort->Url().FindOpt("noinit")) {
|
||||
if (! Port().Url().FindOpt("noinit")) {
|
||||
if (!LinkInit(emsg)) {
|
||||
Close();
|
||||
return false;
|
||||
@@ -203,13 +204,13 @@ bool RlinkConnect::Open(const std::string& name, RerrMsg& emsg)
|
||||
|
||||
void RlinkConnect::Close()
|
||||
{
|
||||
if (!fupPort) return;
|
||||
if (!HasPort()) return;
|
||||
|
||||
if (fpServ) fpServ->Stop(); // stop server in case still running
|
||||
|
||||
if (fupPort->Url().FindOpt("keep")) {
|
||||
if (Port().Url().FindOpt("keep")) {
|
||||
RerrMsg emsg;
|
||||
fSndPkt.SndKeep(fupPort.get(), emsg);
|
||||
fSndPkt.SndKeep(Port(), emsg);
|
||||
}
|
||||
|
||||
fupPort.reset();
|
||||
@@ -513,7 +514,7 @@ int RlinkConnect::WaitAttn(const Rtime& timeout, Rtime& twait,
|
||||
Rtime tbeg = tnow;
|
||||
|
||||
while (tnow < tend) {
|
||||
int irc = fRcvPkt.ReadData(fupPort.get(), tend-tnow, emsg);
|
||||
int irc = fRcvPkt.ReadData(Port(), tend-tnow, emsg);
|
||||
if (irc == RlinkPort::kTout) return -1;
|
||||
if (irc == RlinkPort::kErr) return -2;
|
||||
tnow.GetClock(CLOCK_MONOTONIC);
|
||||
@@ -547,7 +548,7 @@ bool RlinkConnect::SndOob(uint16_t addr, uint16_t data, RerrMsg& emsg)
|
||||
{
|
||||
boost::lock_guard<RlinkConnect> lock(*this);
|
||||
fStats.Inc(kStatNSndOob);
|
||||
return fSndPkt.SndOob(fupPort.get(), addr, data, emsg);
|
||||
return fSndPkt.SndOob(Port(), addr, data, emsg);
|
||||
}
|
||||
|
||||
//------------------------------------------+-----------------------------------
|
||||
@@ -556,7 +557,7 @@ bool RlinkConnect::SndOob(uint16_t addr, uint16_t data, RerrMsg& emsg)
|
||||
bool RlinkConnect::SndAttn(RerrMsg& emsg)
|
||||
{
|
||||
boost::lock_guard<RlinkConnect> lock(*this);
|
||||
return fSndPkt.SndAttn(fupPort.get(), emsg);
|
||||
return fSndPkt.SndAttn(Port(), emsg);
|
||||
}
|
||||
|
||||
//------------------------------------------+-----------------------------------
|
||||
@@ -619,7 +620,7 @@ void RlinkConnect::SetDumpLevel(uint32_t lvl)
|
||||
void RlinkConnect::SetTraceLevel(uint32_t lvl)
|
||||
{
|
||||
fTraceLevel = lvl;
|
||||
if (fupPort) fupPort->SetTraceLevel(lvl);
|
||||
if (HasPort()) Port().SetTraceLevel(lvl);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -687,8 +688,8 @@ void RlinkConnect::Dump(std::ostream& os, int ind, const char* text,
|
||||
RosFill bl(ind);
|
||||
os << bl << (text?text:"--") << "RlinkConnect @ " << this << endl;
|
||||
|
||||
if (fupPort) {
|
||||
fupPort->Dump(os, ind+2, "fupPort: ", detail);
|
||||
if (HasPort()) {
|
||||
Port().Dump(os, ind+2, "fupPort: ", detail);
|
||||
} else {
|
||||
os << bl << " fupPort: " << fupPort.get() << endl;
|
||||
}
|
||||
@@ -740,7 +741,7 @@ void RlinkConnect::HandleUnsolicitedData()
|
||||
|
||||
boost::lock_guard<RlinkConnect> lock(*this);
|
||||
RerrMsg emsg;
|
||||
int irc = fRcvPkt.ReadData(fupPort.get(), Rtime(), emsg);
|
||||
int irc = fRcvPkt.ReadData(Port(), Rtime(), emsg);
|
||||
if (irc == 0) return;
|
||||
if (irc < 0) {
|
||||
RlogMsg lmsg(*fspLog, 'E');
|
||||
@@ -766,7 +767,7 @@ bool RlinkConnect::ExecPart(RlinkCommandList& clist, size_t ibeg, size_t iend,
|
||||
EncodeRequest(clist, ibeg, iend);
|
||||
|
||||
// FIXME_code: handle send fail properly;
|
||||
if (!fSndPkt.SndPacket(fupPort.get(), emsg)) return false;
|
||||
if (!fSndPkt.SndPacket(Port(), emsg)) return false;
|
||||
|
||||
// FIXME_code: handle recoveries
|
||||
// FIXME_code: use proper value for timeout (rest time for Exec ?)
|
||||
@@ -1084,7 +1085,7 @@ bool RlinkConnect::ReadResponse(const Rtime& timeout, RerrMsg& emsg)
|
||||
Rtime tend = tnow + timeout;
|
||||
|
||||
while (tnow < tend) {
|
||||
int irc = fRcvPkt.ReadData(fupPort.get(), tend-tnow, emsg);
|
||||
int irc = fRcvPkt.ReadData(Port(), tend-tnow, emsg);
|
||||
if (irc <= 0) {
|
||||
RlogMsg lmsg(*fspLog, 'E');
|
||||
lmsg << "ReadResponse: IO error or timeout: " << emsg;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id: RlinkConnect.hpp 1078 2018-12-08 14:19:03Z mueller $
|
||||
// $Id: RlinkConnect.hpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2011-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 2.8 add HasPort(); return ref for Port()
|
||||
// 2018-12-07 1078 2.7.1 use std::shared_ptr instead of boost
|
||||
// 2018-12-01 1076 2.7 use unique_ptr instead of scoped_ptr
|
||||
// 2017-04-22 883 2.6.3 add rbus monitor probe, add HasRbmon()
|
||||
@@ -87,7 +88,9 @@ namespace Retro {
|
||||
bool Open(const std::string& name, RerrMsg& emsg);
|
||||
void Close();
|
||||
bool IsOpen() const;
|
||||
RlinkPort* Port() const;
|
||||
bool HasPort() const;
|
||||
RlinkPort& Port();
|
||||
const RlinkPort& Port() const;
|
||||
|
||||
bool LinkInit(RerrMsg& emsg);
|
||||
bool LinkInitDone() const;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id: RlinkConnect.ipp 1078 2018-12-08 14:19:03Z mueller $
|
||||
// $Id: RlinkConnect.ipp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2011-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 2.7 add HasPort; return ref for Port()
|
||||
// 2018-12-07 1078 2.6.1 use std::shared_ptr instead of boost
|
||||
// 2018-12-01 1076 2.6 use unique_ptr instead of scoped_ptr
|
||||
// 2017-04-22 883 2.5.2 add rbus monitor probe, add HasRbmon()
|
||||
@@ -50,9 +51,25 @@ inline bool RlinkConnect::IsOpen() const
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
inline RlinkPort* RlinkConnect::Port() const
|
||||
inline bool RlinkConnect::HasPort() const
|
||||
{
|
||||
return fupPort.get();
|
||||
return bool(fupPort);
|
||||
}
|
||||
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
inline RlinkPort& RlinkConnect::Port()
|
||||
{
|
||||
return *fupPort;
|
||||
}
|
||||
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
inline const RlinkPort& RlinkConnect::Port() const
|
||||
{
|
||||
return *fupPort;
|
||||
}
|
||||
|
||||
//------------------------------------------+-----------------------------------
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// $Id: RlinkPacketBufRcv.cpp 983 2018-01-02 20:35:59Z mueller $
|
||||
// $Id: RlinkPacketBufRcv.cpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2014-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
// Copyright 2014-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
// This program is free software; you may redistribute and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 1.2 use ref not ptr for RlinkPort
|
||||
// 2017-04-07 868 1.1.1 Dump(): add detail arg
|
||||
// 2017-02-19 853 1.1 use Rtime
|
||||
// 2014-12-25 621 1.0.1 Reorganize packet send/revd stats
|
||||
@@ -76,10 +77,10 @@ RlinkPacketBufRcv::~RlinkPacketBufRcv()
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
int RlinkPacketBufRcv::ReadData(RlinkPort* port, const Rtime& timeout,
|
||||
int RlinkPacketBufRcv::ReadData(RlinkPort& port, const Rtime& timeout,
|
||||
RerrMsg& emsg)
|
||||
{
|
||||
if (port == nullptr)
|
||||
if (&port==nullptr || !port.IsOpen())
|
||||
throw Rexception("RlinkPacketBufRcv::ReadData()",
|
||||
"Bad state: port not open");
|
||||
if (fRawBufDone != fRawBufSize)
|
||||
@@ -89,7 +90,7 @@ int RlinkPacketBufRcv::ReadData(RlinkPort* port, const Rtime& timeout,
|
||||
fRawBufDone = 0;
|
||||
fRawBufSize = 0;
|
||||
|
||||
int irc = port->Read(fRawBuf, sizeof(fRawBuf), timeout, emsg);
|
||||
int irc = port.Read(fRawBuf, sizeof(fRawBuf), timeout, emsg);
|
||||
|
||||
if (timeout.IsZero() && irc == RlinkPort::kTout) return 0;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// $Id: RlinkPacketBufRcv.hpp 1052 2018-09-30 08:10:52Z mueller $
|
||||
// $Id: RlinkPacketBufRcv.hpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2014-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
// Copyright 2014-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
// This program is free software; you may redistribute and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 1.2 use ref not ptr for RlinkPort
|
||||
// 2017-04-07 868 1.1.1 Dump(): add detail arg
|
||||
// 2017-02-19 853 1.1 use Rtime
|
||||
// 2014-12-25 621 1.0.1 Reorganize packet send/revd stats
|
||||
@@ -40,7 +41,7 @@ namespace Retro {
|
||||
RlinkPacketBufRcv();
|
||||
~RlinkPacketBufRcv();
|
||||
|
||||
int ReadData(RlinkPort* port, const Rtime& timeout,
|
||||
int ReadData(RlinkPort& port, const Rtime& timeout,
|
||||
RerrMsg& emsg);
|
||||
bool ProcessData();
|
||||
void AcceptPacket();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// $Id: RlinkPacketBufSnd.cpp 983 2018-01-02 20:35:59Z mueller $
|
||||
// $Id: RlinkPacketBufSnd.cpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2014-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
// Copyright 2014-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
// This program is free software; you may redistribute and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 1.2 use ref not ptr for RlinkPort
|
||||
// 2017-04-07 868 1.1.1 Dump(): add detail arg
|
||||
// 2015-04-11 666 1.1 handle xon/xoff escaping, add (Set)XonEscape()
|
||||
// 2014-12-25 621 1.0.1 Reorganize packet send/revd stats
|
||||
@@ -89,7 +90,7 @@ void RlinkPacketBufSnd::PutWithCrc(const uint16_t* pdata, size_t count)
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndPacket(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndPacket(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
size_t nesc = 0;
|
||||
size_t nxesc = 0;
|
||||
@@ -138,7 +139,7 @@ bool RlinkPacketBufSnd::SndPacket(RlinkPort* port, RerrMsg& emsg)
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
|
||||
bool RlinkPacketBufSnd::SndOob(RlinkPort& port, uint16_t addr, uint16_t data,
|
||||
RerrMsg& emsg)
|
||||
{
|
||||
Init();
|
||||
@@ -161,7 +162,7 @@ bool RlinkPacketBufSnd::SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndKeep(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndKeep(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
Init();
|
||||
|
||||
@@ -175,7 +176,7 @@ bool RlinkPacketBufSnd::SndKeep(RlinkPort* port, RerrMsg& emsg)
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndAttn(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndAttn(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
Init();
|
||||
|
||||
@@ -187,7 +188,7 @@ bool RlinkPacketBufSnd::SndAttn(RlinkPort* port, RerrMsg& emsg)
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndNak(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndNak(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
Init();
|
||||
|
||||
@@ -199,7 +200,7 @@ bool RlinkPacketBufSnd::SndNak(RlinkPort* port, RerrMsg& emsg)
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndUnJam(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndUnJam(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
Init();
|
||||
|
||||
@@ -236,13 +237,13 @@ void RlinkPacketBufSnd::Dump(std::ostream& os, int ind, const char* text,
|
||||
//------------------------------------------+-----------------------------------
|
||||
//! FIXME_docs
|
||||
|
||||
bool RlinkPacketBufSnd::SndRaw(RlinkPort* port, RerrMsg& emsg)
|
||||
bool RlinkPacketBufSnd::SndRaw(RlinkPort& port, RerrMsg& emsg)
|
||||
{
|
||||
if (port==0 || !port->IsOpen())
|
||||
if (&port==nullptr || !port.IsOpen())
|
||||
throw Rexception("RlinkPacketBufSnd::SndRaw()", "Bad state: port not open");
|
||||
|
||||
size_t rawbufsize = fRawBuf.size();
|
||||
int irc = port->Write(fRawBuf.data(), rawbufsize, emsg);
|
||||
int irc = port.Write(fRawBuf.data(), rawbufsize, emsg);
|
||||
if (irc < 0) return false;
|
||||
if ((size_t)irc != rawbufsize) {
|
||||
emsg.Init("RlinkPacketBufSnd::SndRaw()", "failed to write all data");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// $Id: RlinkPacketBufSnd.hpp 983 2018-01-02 20:35:59Z mueller $
|
||||
// $Id: RlinkPacketBufSnd.hpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2014-2017 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
// Copyright 2014-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
// This program is free software; you may redistribute and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
@@ -13,6 +13,7 @@
|
||||
//
|
||||
// Revision History:
|
||||
// Date Rev Version Comment
|
||||
// 2018-12-08 1079 1.2 use ref not ptr for RlinkPort
|
||||
// 2017-04-07 868 1.1.2 Dump(): add detail arg
|
||||
// 2015-04-11 666 1.1 handle xon/xoff escaping, add (Set)XonEscape()
|
||||
// 2014-12-25 621 1.0.1 Reorganize packet send/revd stats
|
||||
@@ -38,7 +39,7 @@ namespace Retro {
|
||||
public:
|
||||
|
||||
RlinkPacketBufSnd();
|
||||
~RlinkPacketBufSnd();
|
||||
~RlinkPacketBufSnd();
|
||||
|
||||
void SetXonEscape(bool xon);
|
||||
bool XonEscape() const;
|
||||
@@ -52,13 +53,13 @@ namespace Retro {
|
||||
|
||||
void PutRawEsc(uint8_t ec);
|
||||
|
||||
bool SndPacket(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
|
||||
bool SndPacket(RlinkPort& port, RerrMsg& emsg);
|
||||
bool SndOob(RlinkPort& port, uint16_t addr, uint16_t data,
|
||||
RerrMsg& emsg);
|
||||
bool SndKeep(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndAttn(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndNak(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndUnJam(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndKeep(RlinkPort& port, RerrMsg& emsg);
|
||||
bool SndAttn(RlinkPort& port, RerrMsg& emsg);
|
||||
bool SndNak(RlinkPort& port, RerrMsg& emsg);
|
||||
bool SndUnJam(RlinkPort& port, RerrMsg& emsg);
|
||||
|
||||
size_t RawSize() const;
|
||||
|
||||
@@ -73,7 +74,7 @@ namespace Retro {
|
||||
};
|
||||
|
||||
protected:
|
||||
bool SndRaw(RlinkPort* port, RerrMsg& emsg);
|
||||
bool SndRaw(RlinkPort& port, RerrMsg& emsg);
|
||||
|
||||
protected:
|
||||
bool fXonEscape; //!< escape XON/XOFF
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// $Id: RlinkServer.cpp 1078 2018-12-08 14:19:03Z mueller $
|
||||
// $Id: RlinkServer.cpp 1079 2018-12-09 10:56:59Z mueller $
|
||||
//
|
||||
// Copyright 2013-2018 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
|
||||
//
|
||||
@@ -413,7 +413,7 @@ void RlinkServer::StartOrResume(bool resume)
|
||||
Exec(clist);
|
||||
|
||||
// setup poll handler for Rlink traffic
|
||||
int rlinkfd = fspConn->Port()->FdRead();
|
||||
int rlinkfd = fspConn->Port().FdRead();
|
||||
if (!fELoop.TestPollHandler(rlinkfd, POLLIN))
|
||||
fELoop.AddPollHandler(boost::bind(&RlinkServer::RlinkHandler, this, _1),
|
||||
rlinkfd, POLLIN);
|
||||
|
||||
Reference in New Issue
Block a user