many changes
This commit is contained in:
@@ -4,16 +4,21 @@ SRC := $(CAS)/generic
|
||||
CA := $(CAS)/../ca
|
||||
IOSRC := $(CAS)/io/bsdSocket
|
||||
STSRC := $(SRC)/st
|
||||
USER_VPATH := $(SRC) $(STSRC) $(IOSRC)
|
||||
USR_VPATH := $(SRC) $(STSRC) $(IOSRC)
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
SRC_DIRS += $(CAS)/generic $(CAS)/singleThread
|
||||
SRC_DIRS += $(CAS)/generic
|
||||
|
||||
# sometimes it's good to have different C/C++ flags, not now:
|
||||
USR_CFLAGS = -I$(SRC) -I$(IOSRC) -I$(STSRC) -I$(CA) -DcaNetAddrSock
|
||||
USR_CXXFLAGS = $(USR_CFLAGS)
|
||||
|
||||
INC += casdef.h
|
||||
INC += casEventMask.h
|
||||
INC += casInternal.h
|
||||
INC += caNetAddr.h
|
||||
|
||||
LIBSRCS += caServer.cc
|
||||
LIBSRCS += caServerI.cc
|
||||
LIBSRCS += casCoreClient.cc
|
||||
|
||||
@@ -82,7 +82,7 @@ caStatus exPV::update(gdd &valueIn)
|
||||
# endif
|
||||
|
||||
cas = this->updateValue (valueIn);
|
||||
if (cas || this->pValue==NULL) {
|
||||
if ( cas || ( ! this->pValue.valid() ) ) {
|
||||
return cas;
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ void exPV::interestDelete()
|
||||
void exPV::show(unsigned level) const
|
||||
{
|
||||
if (level>1u) {
|
||||
if (this->pValue!=NULL) {
|
||||
if ( this->pValue.valid () ) {
|
||||
printf("exPV: cond=%d\n", this->pValue->getStat());
|
||||
printf("exPV: sevr=%d\n", this->pValue->getSevr());
|
||||
printf("exPV: value=%f\n", (double) *this->pValue);
|
||||
@@ -321,11 +321,11 @@ caStatus exPV::getValue(gdd &value)
|
||||
{
|
||||
caStatus status;
|
||||
|
||||
if (this->pValue!=NULL) {
|
||||
if ( this->pValue.valid () ) {
|
||||
gddStatus gdds;
|
||||
|
||||
gdds = gddApplicationTypeTable::
|
||||
app_table.smartCopy(&value, this->pValue);
|
||||
app_table.smartCopy (&value, & (*this->pValue) );
|
||||
if (gdds) {
|
||||
status = S_cas_noConvert;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ void exScalarPV::scan()
|
||||
this->currentTime = osiTime::getCurrent();
|
||||
|
||||
pDD = new gddScalar (gddAppType_value, aitEnumFloat32);
|
||||
if (pDD==NULL) {
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ void exScalarPV::scan()
|
||||
assert (!gddStatus);
|
||||
|
||||
radians = (rand () * 2.0 * myPI)/RAND_MAX;
|
||||
if (this->pValue!=NULL) {
|
||||
if ( this->pValue.valid () ) {
|
||||
this->pValue->getConvert(newValue);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -70,7 +70,7 @@ void exVectorPV::scan()
|
||||
|
||||
pDD = new gddAtomic (gddAppType_value, aitEnumFloat32,
|
||||
1u, this->info.getElementCount());
|
||||
if (pDD==NULL) {
|
||||
if ( ! pDD.valid () ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ void exVectorPV::scan()
|
||||
// current value
|
||||
//
|
||||
pCF=NULL;
|
||||
if (this->pValue!=NULL) {
|
||||
if ( this->pValue.valid () ) {
|
||||
if (this->pValue->dimension()==1u) {
|
||||
const gddBounds *pB = this->pValue->getBounds();
|
||||
if (pB[0u].size()==this->info.getElementCount()) {
|
||||
@@ -208,7 +208,7 @@ caStatus exVectorPV::updateValue(gdd &valueIn)
|
||||
//
|
||||
pNewValue = new gddAtomic (gddAppType_value, aitEnumFloat32,
|
||||
1u, this->info.getElementCount());
|
||||
if (pNewValue==NULL) {
|
||||
if ( ! pNewValue.valid () ) {
|
||||
return S_casApp_noMemory;
|
||||
}
|
||||
|
||||
@@ -223,9 +223,9 @@ caStatus exVectorPV::updateValue(gdd &valueIn)
|
||||
// copy over the old values if they exist
|
||||
// (or initialize all elements to zero)
|
||||
//
|
||||
if (this->pValue!=NULL) {
|
||||
gdds = pNewValue->copy(this->pValue);
|
||||
if (gdds) {
|
||||
if ( this->pValue.valid () ) {
|
||||
gdds = pNewValue->copy( &(*this->pValue) );
|
||||
if ( gdds ) {
|
||||
return S_cas_noConvert;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,30 +59,28 @@ casChannelI::~casChannelI()
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLIterBD<casAsyncIOI> iterAIO(this->ioInProgList.first());
|
||||
while ( iterAIO!=tsDLIterBD<casAsyncIOI>::eol() ) {
|
||||
tsDLIterBD<casAsyncIOI> iterAIO ( this->ioInProgList.first () );
|
||||
while ( iterAIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIterBD<casAsyncIOI> tmpAIO = iterAIO;
|
||||
++tmpAIO;
|
||||
iterAIO->serverDestroy();
|
||||
iterAIO->serverDestroy ();
|
||||
iterAIO = tmpAIO;
|
||||
}
|
||||
|
||||
//
|
||||
// cancel the monitors
|
||||
//
|
||||
tsDLIterBD<casMonitor> iterMon (this->monitorList.first());
|
||||
while ( iterMon!=tsDLIterBD<casMonitor>::eol() ) {
|
||||
casMonitor *pMonitor;
|
||||
tsDLIterBD <casMonitor> iterMon ( this->monitorList.first () );
|
||||
while ( iterMon.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIterBD<casMonitor> tmpMon = iterMon;
|
||||
pMonitor = tmpMon;
|
||||
tsDLIterBD <casMonitor> tmpMon = iterMon;
|
||||
++tmpMon;
|
||||
delete pMonitor;
|
||||
iterMon->destroy ();
|
||||
iterMon = tmpMon;
|
||||
}
|
||||
|
||||
@@ -106,8 +104,8 @@ void casChannelI::clearOutstandingReads()
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
tsDLIterBD<casAsyncIOI> iterIO(this->ioInProgList.first());
|
||||
while (iterIO!=tsDLIterBD<casAsyncIOI>::eol() ) {
|
||||
tsDLIterBD <casAsyncIOI> iterIO ( this->ioInProgList.first () );
|
||||
while ( iterIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
@@ -128,12 +126,12 @@ void casChannelI::show(unsigned level) const
|
||||
this->lock();
|
||||
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
if ( iter!=tsDLIterBD<casMonitor>::eol() ) {
|
||||
if ( iter.valid () ) {
|
||||
printf("List of CA events (monitors) for \"%s\".\n",
|
||||
this->pv.getName());
|
||||
}
|
||||
while ( iter!=tsDLIterBD<casMonitor>::eol() ) {
|
||||
iter->show(level);
|
||||
while ( iter.valid () ) {
|
||||
iter->show ( level );
|
||||
++iter;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ inline void casChannelI::postEvent (const casEventMask &select, const smartConst
|
||||
this->lock();
|
||||
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
while ( iter != tsDLIterBD<casMonitor>::eol() ) {
|
||||
while ( iter.valid () ) {
|
||||
iter->post (select, pEvent);
|
||||
++iter;
|
||||
}
|
||||
@@ -102,19 +102,18 @@ inline void casChannelI::addMonitor(casMonitor &mon)
|
||||
// sane clients will require only one or two monitors
|
||||
// per channel)
|
||||
//
|
||||
inline casMonitor *casChannelI::findMonitor(const caResId clientIdIn)
|
||||
inline tsDLIterBD <casMonitor> casChannelI::findMonitor (const caResId clientIdIn)
|
||||
{
|
||||
this->lock();
|
||||
tsDLIterBD<casMonitor> iter(this->monitorList.first());
|
||||
while ( iter!=tsDLIterBD<casMonitor>::eol() ) {
|
||||
if ( clientIdIn == iter->getClientId()) {
|
||||
casMonitor *pMon = iter;
|
||||
return pMon;
|
||||
this->lock ();
|
||||
tsDLIterBD <casMonitor> iter ( this->monitorList.first () );
|
||||
while ( iter.valid () ) {
|
||||
if ( clientIdIn == iter->getClientId () ) {
|
||||
break;
|
||||
}
|
||||
++iter;
|
||||
iter++;
|
||||
}
|
||||
this->unlock();
|
||||
return NULL;
|
||||
this->unlock ();
|
||||
return iter;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -62,13 +62,13 @@ casCoreClient::~casCoreClient()
|
||||
//
|
||||
// cancel any pending asynchronous IO
|
||||
//
|
||||
while (iterIO!=tsDLIterBD<casAsyncIOI>::eol()) {
|
||||
while ( iterIO.valid () ) {
|
||||
//
|
||||
// destructor removes from this list
|
||||
//
|
||||
tsDLIterBD<casAsyncIOI> tmpIO = iterIO;
|
||||
tsDLIterBD <casAsyncIOI> tmpIO = iterIO;
|
||||
++tmpIO;
|
||||
iterIO->serverDestroy();
|
||||
iterIO->serverDestroy ();
|
||||
iterIO = tmpIO;
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ public:
|
||||
// sane clients will require only one or two monitors
|
||||
// per channel)
|
||||
//
|
||||
casMonitor *findMonitor (const caResId clientIdIn);
|
||||
tsDLIterBD <casMonitor> findMonitor (const caResId clientIdIn);
|
||||
|
||||
casPVI &getPVI () const
|
||||
{
|
||||
|
||||
@@ -62,8 +62,8 @@ casPVI::~casPVI()
|
||||
//
|
||||
// delete any attached channels
|
||||
//
|
||||
tsDLIterBD<casPVListChan> iter(this->chanList.first());
|
||||
while (iter!=tsDLIterBD<casPVListChan>::eol()) {
|
||||
tsDLIterBD <casPVListChan> iter ( this->chanList.first () );
|
||||
while ( iter.valid () ) {
|
||||
//
|
||||
// deleting the channel removes it from the list
|
||||
//
|
||||
|
||||
@@ -136,7 +136,7 @@ inline void casPVI::postEvent (const casEventMask &select, const smartConstGDDPo
|
||||
|
||||
this->lock();
|
||||
tsDLIterBD<casPVListChan> iter(this->chanList.first());
|
||||
while ( iter != tsDLIterBD<casPVListChan>::eol() ) {
|
||||
while ( iter.valid () ) {
|
||||
iter->postEvent(select, pEvent);
|
||||
++iter;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ casStrmClient::~casStrmClient()
|
||||
// delete all channel attached
|
||||
//
|
||||
tsDLIterBD<casChannelI> iter(this->chanList.first());
|
||||
while (iter!=tsDLIterBD<casChannelI>::eol()) {
|
||||
while ( iter.valid () ) {
|
||||
//
|
||||
// destroying the channel removes it from the list
|
||||
//
|
||||
@@ -510,7 +510,7 @@ static smartGDDPointer createDBRDD (unsigned dbrType, aitIndex dbrCount)
|
||||
aitUint32 valIndex;
|
||||
aitUint32 gddStatus;
|
||||
aitUint16 appType;
|
||||
smartGDDPointer pVal;
|
||||
gdd *pVal;
|
||||
|
||||
/*
|
||||
* DBR type has already been checked, but it is possible
|
||||
@@ -529,17 +529,17 @@ static smartGDDPointer createDBRDD (unsigned dbrType, aitIndex dbrCount)
|
||||
// create the descriptor
|
||||
//
|
||||
pDescRet = gddApplicationTypeTable::app_table.getDD (appType);
|
||||
if (!pDescRet) {
|
||||
if ( ! pDescRet.valid () ) {
|
||||
return pDescRet;
|
||||
}
|
||||
|
||||
if (pDescRet->isContainer()) {
|
||||
if ( pDescRet->isContainer () ) {
|
||||
|
||||
//
|
||||
// unable to change the bounds on the managed GDD that is
|
||||
// returned for DBR types
|
||||
//
|
||||
if (dbrCount>1 ) {
|
||||
if ( dbrCount > 1 ) {
|
||||
pDescRet = (gdd *) new gdd (*pDescRet);
|
||||
//
|
||||
// smart pointer class maintains the ref count from here down
|
||||
@@ -554,30 +554,30 @@ static smartGDDPointer createDBRDD (unsigned dbrType, aitIndex dbrCount)
|
||||
gddStatus =
|
||||
gddApplicationTypeTable::app_table.mapAppToIndex
|
||||
(appType, gddAppType_value, valIndex);
|
||||
if (gddStatus) {
|
||||
if ( gddStatus ) {
|
||||
pDescRet = NULL;
|
||||
return pDescRet;
|
||||
}
|
||||
pVal = pDescRet->getDD (valIndex);
|
||||
if (!pVal) {
|
||||
pVal = pDescRet->getDD ( valIndex );
|
||||
if ( ! pVal ) {
|
||||
pDescRet = NULL;
|
||||
return pDescRet;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pVal = pDescRet;
|
||||
pVal = & ( *pDescRet );
|
||||
}
|
||||
|
||||
if (pVal->isScalar()) {
|
||||
if ( pVal->isScalar () ) {
|
||||
if (dbrCount<=1u) {
|
||||
return S_cas_success;
|
||||
return pDescRet;
|
||||
}
|
||||
|
||||
//
|
||||
// scalar and managed (and need to set the bounds)
|
||||
// => out of luck (cant modify bounds)
|
||||
//
|
||||
if (pDescRet->isManaged()) {
|
||||
if ( pDescRet->isManaged () ) {
|
||||
pDescRet = NULL;
|
||||
return pDescRet;
|
||||
}
|
||||
@@ -586,27 +586,27 @@ static smartGDDPointer createDBRDD (unsigned dbrType, aitIndex dbrCount)
|
||||
// convert to atomic
|
||||
//
|
||||
gddBounds bds;
|
||||
bds.setSize(dbrCount);
|
||||
bds.setFirst(0u);
|
||||
pVal->setDimension(1u, &bds);
|
||||
bds.setSize ( dbrCount );
|
||||
bds.setFirst ( 0u );
|
||||
pVal->setDimension ( 1u, &bds );
|
||||
}
|
||||
else if (pVal->isAtomic()) {
|
||||
const gddBounds* pB = pVal->getBounds();
|
||||
else if ( pVal->isAtomic () ) {
|
||||
const gddBounds* pB = pVal->getBounds ();
|
||||
aitIndex bound = dbrCount;
|
||||
unsigned dim;
|
||||
int modAllowed;
|
||||
|
||||
if (pDescRet->isManaged() || pDescRet->isFlat()) {
|
||||
if ( pDescRet->isManaged () || pDescRet->isFlat () ) {
|
||||
modAllowed = FALSE;
|
||||
}
|
||||
else {
|
||||
modAllowed = TRUE;
|
||||
}
|
||||
|
||||
for (dim=0u; dim<(unsigned)pVal->dimension(); dim++) {
|
||||
if (pB[dim].first()!=0u && pB[dim].size()!=bound) {
|
||||
if (modAllowed) {
|
||||
pVal->setBound(dim, 0u, bound);
|
||||
for ( dim=0u; dim < (unsigned) pVal->dimension (); dim++ ) {
|
||||
if ( pB[dim].first () != 0u && pB[dim].size() != bound ) {
|
||||
if ( modAllowed ) {
|
||||
pVal->setBound( dim, 0u, bound );
|
||||
}
|
||||
else {
|
||||
pDescRet = NULL;
|
||||
@@ -976,7 +976,7 @@ caStatus casStrmClient::hostNameAction()
|
||||
this->pHostName = pMalloc;
|
||||
|
||||
tsDLIterBD<casChannelI> iter(this->chanList.first());
|
||||
while ( iter!=tsDLIterBD<casChannelI>::eol() ) {
|
||||
while ( iter.valid () ) {
|
||||
iter->setOwner(this->pUserName, this->pHostName);
|
||||
++iter;
|
||||
}
|
||||
@@ -1023,9 +1023,9 @@ caStatus casStrmClient::clientNameAction()
|
||||
}
|
||||
this->pUserName = pMalloc;
|
||||
|
||||
tsDLIterBD<casChannelI> iter(this->chanList.first());
|
||||
while ( iter!=tsDLIterBD<casChannelI>::eol() ) {
|
||||
iter->setOwner(this->pUserName, this->pHostName);
|
||||
tsDLIterBD <casChannelI> iter ( this->chanList.first () );
|
||||
while ( iter.valid () ) {
|
||||
iter->setOwner ( this->pUserName, this->pHostName );
|
||||
++iter;
|
||||
}
|
||||
this->unlock();
|
||||
@@ -1499,7 +1499,6 @@ caStatus casStrmClient::eventCancelAction ()
|
||||
void *dp = this->ctx.getData ();
|
||||
casChannelI *pciu;
|
||||
caHdr *reply;
|
||||
casMonitor *pMon;
|
||||
int status;
|
||||
|
||||
/*
|
||||
@@ -1520,8 +1519,8 @@ caStatus casStrmClient::eventCancelAction ()
|
||||
/*
|
||||
* verify the event (monitor)
|
||||
*/
|
||||
pMon = pciu->findMonitor (mp->m_available);
|
||||
if (!pMon) {
|
||||
tsDLIterBD < casMonitor > pMon = pciu->findMonitor ( mp->m_available );
|
||||
if ( ! pMon.valid () ) {
|
||||
//
|
||||
// this indicates client or server library corruption
|
||||
//
|
||||
@@ -1545,7 +1544,7 @@ caStatus casStrmClient::eventCancelAction ()
|
||||
|
||||
this->commitMsg ();
|
||||
|
||||
delete pMon;
|
||||
pMon->destroy ();
|
||||
|
||||
return S_cas_success;
|
||||
}
|
||||
@@ -1621,8 +1620,8 @@ caStatus casStrmClient::readSyncAction()
|
||||
//
|
||||
this->lock();
|
||||
tsDLIterBD<casChannelI> iter(this->chanList.first());
|
||||
while ( iter!=tsDLIterBD<casChannelI>::eol() ) {
|
||||
iter->clearOutstandingReads();
|
||||
while ( iter.valid () ) {
|
||||
iter->clearOutstandingReads ();
|
||||
++iter;
|
||||
}
|
||||
this->unlock();
|
||||
@@ -1928,7 +1927,7 @@ caStatus casStrmClient::read (smartGDDPointer &pDescRet)
|
||||
caStatus status;
|
||||
|
||||
pDescRet = createDBRDD (pHdr->m_dataType, pHdr->m_count);
|
||||
if (!pDescRet) {
|
||||
if ( ! pDescRet ) {
|
||||
return S_cas_noMemory;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "server.h"
|
||||
#include "osiSigPipeIgnore.h"
|
||||
|
||||
static char *getToken(const char **ppString, char *pBuf, unsigned bufSIze);
|
||||
static char *getToken (const char **ppString, char *pBuf, unsigned bufSIze);
|
||||
|
||||
int caServerIO::staticInitialized;
|
||||
|
||||
@@ -19,7 +19,7 @@ int caServerIO::staticInitialized;
|
||||
//
|
||||
caServerIO::caServerIO ()
|
||||
{
|
||||
if (!bsdSockAttach()) {
|
||||
if ( ! osiSockAttach () ) {
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ void caServerIO::locateInterfaces ()
|
||||
//
|
||||
caServerIO::~caServerIO()
|
||||
{
|
||||
bsdSockRelease();
|
||||
osiSockRelease();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -51,7 +51,7 @@ casDGIntfIO::casDGIntfIO (caServerI &serverIn, const caNetAddr &addr,
|
||||
|
||||
ellInit(&this->beaconAddrList);
|
||||
|
||||
if (!bsdSockAttach()) {
|
||||
if ( ! osiSockAttach () ) {
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
@@ -202,17 +202,21 @@ casDGIntfIO::casDGIntfIO (caServerI &serverIn, const caNetAddr &addr,
|
||||
//
|
||||
casDGIntfIO::~casDGIntfIO()
|
||||
{
|
||||
if (this->sock!=INVALID_SOCKET) {
|
||||
socket_close(this->sock);
|
||||
if ( this->sock != INVALID_SOCKET ) {
|
||||
socket_close ( this->sock );
|
||||
}
|
||||
|
||||
if (this->bcastRecvSock!=INVALID_SOCKET) {
|
||||
socket_close(this->bcastRecvSock);
|
||||
if ( this->bcastRecvSock != INVALID_SOCKET ) {
|
||||
socket_close ( this->bcastRecvSock );
|
||||
}
|
||||
|
||||
if ( this->beaconSock != INVALID_SOCKET ) {
|
||||
socket_close ( this->beaconSock );
|
||||
}
|
||||
|
||||
ellFree(&this->beaconAddrList);
|
||||
ellFree ( &this->beaconAddrList );
|
||||
|
||||
bsdSockRelease();
|
||||
osiSockRelease ();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -367,8 +371,6 @@ void casDGIntfIO::sendBeaconIO (char &msg, unsigned length, aitUint16 &portField
|
||||
else if (addr.sa.sa_family==AF_INET) {
|
||||
addrField = addr.ia.sin_addr.s_addr;
|
||||
|
||||
printf ("sending beacon specifying port %u addr %x\n", portField, addr.ia.sin_addr.s_addr);
|
||||
|
||||
status = sendto (this->beaconSock, &msg, length, 0,
|
||||
&pAddr->addr.sa, sizeof(pAddr->addr.sa));
|
||||
if (status < 0) {
|
||||
@@ -527,7 +529,7 @@ SOCKET casDGIntfIO::makeSockDG ()
|
||||
status = setsockopt(
|
||||
newSock,
|
||||
SOL_SOCKET,
|
||||
s SO_REUSEADDR,
|
||||
SO_REUSEADDR,
|
||||
(char *) &yes,
|
||||
sizeof (yes));
|
||||
if (status<0) {
|
||||
|
||||
@@ -26,7 +26,7 @@ casIntfIO::casIntfIO (const caNetAddr &addrIn) :
|
||||
int status;
|
||||
int addrSize;
|
||||
|
||||
if (!bsdSockAttach()) {
|
||||
if ( ! osiSockAttach () ) {
|
||||
throw S_cas_internal;
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ casIntfIO::~casIntfIO()
|
||||
socket_close(this->sock);
|
||||
}
|
||||
|
||||
bsdSockRelease();
|
||||
osiSockRelease ();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user