add management frame implementations
This commit is contained in:
@@ -22,7 +22,72 @@
|
||||
namespace ns3 {
|
||||
|
||||
CapabilityInformation::CapabilityInformation ()
|
||||
: m_capability (0)
|
||||
{}
|
||||
|
||||
void
|
||||
CapabilityInformation::SetEss (void)
|
||||
{
|
||||
Set (0);
|
||||
Clear (1);
|
||||
}
|
||||
void
|
||||
CapabilityInformation::SetIbss (void)
|
||||
{
|
||||
Clear (0);
|
||||
Set (1);
|
||||
}
|
||||
|
||||
bool
|
||||
CapabilityInformation::IsEss (void) const
|
||||
{
|
||||
return Is (0);
|
||||
}
|
||||
bool
|
||||
CapabilityInformation::IsIbss (void) const
|
||||
{
|
||||
return Is (1);
|
||||
}
|
||||
|
||||
void
|
||||
CapabilityInformation::Set (uint8_t n)
|
||||
{
|
||||
uint32_t mask = 1<<n;
|
||||
m_capability |= mask;
|
||||
}
|
||||
|
||||
void
|
||||
CapabilityInformation::Clear (uint8_t n)
|
||||
{
|
||||
uint32_t mask = 1<<n;
|
||||
m_capability &= ~mask;
|
||||
}
|
||||
|
||||
bool
|
||||
CapabilityInformation::Is (uint8_t n) const
|
||||
{
|
||||
uint32_t mask = 1<<n;
|
||||
return (m_capability & mask) == mask;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
CapabilityInformation::GetSerializedSize (void) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
Buffer::Iterator
|
||||
CapabilityInformation::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
start.WriteHtonU16 (m_capability);
|
||||
return start;
|
||||
}
|
||||
Buffer::Iterator
|
||||
CapabilityInformation::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
m_capability = start.ReadNtohU16 ();
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -21,13 +21,29 @@
|
||||
#define CAPABILITY_INFORMATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ns3/buffer.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class CapabilityInformation {
|
||||
class CapabilityInformation
|
||||
{
|
||||
public:
|
||||
CapabilityInformation ();
|
||||
|
||||
void SetEss (void);
|
||||
void SetIbss (void);
|
||||
|
||||
bool IsEss (void) const;
|
||||
bool IsIbss (void) const;
|
||||
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
Buffer::Iterator Serialize (Buffer::Iterator start) const;
|
||||
Buffer::Iterator Deserialize (Buffer::Iterator start);
|
||||
private:
|
||||
bool Is (uint8_t n) const;
|
||||
void Set (uint8_t n);
|
||||
void Clear (uint8_t n);
|
||||
uint16_t m_capability;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
345
src/devices/wifi/mgt-headers.cc
Normal file
345
src/devices/wifi/mgt-headers.cc
Normal file
@@ -0,0 +1,345 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006 INRIA
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#include "mgt-headers.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/assert.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/***********************************************************
|
||||
* Probe Request
|
||||
***********************************************************/
|
||||
|
||||
MgtProbeRequestHeader::~MgtProbeRequestHeader ()
|
||||
{}
|
||||
|
||||
void
|
||||
MgtProbeRequestHeader::SetSsid (Ssid ssid)
|
||||
{
|
||||
m_ssid = ssid;
|
||||
}
|
||||
Ssid
|
||||
MgtProbeRequestHeader::GetSsid (void) const
|
||||
{
|
||||
return m_ssid;
|
||||
}
|
||||
void
|
||||
MgtProbeRequestHeader::SetSupportedRates (SupportedRates rates)
|
||||
{
|
||||
m_rates = rates;
|
||||
}
|
||||
|
||||
SupportedRates
|
||||
MgtProbeRequestHeader::GetSupportedRates (void) const
|
||||
{
|
||||
return m_rates;
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeRequestHeader::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t size = 0;
|
||||
size += m_ssid.GetSerializedSize ();
|
||||
size += m_rates.GetSerializedSize ();
|
||||
return size;
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeRequestHeader::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = AllocateUid<MgtProbeRequestHeader> ("MgtProbeRequestHeader.ns3.inria.fr");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
MgtProbeRequestHeader::GetName (void) const
|
||||
{
|
||||
return "PROBEREQ";
|
||||
}
|
||||
void
|
||||
MgtProbeRequestHeader::Print (std::ostream &os) const
|
||||
{
|
||||
//XXX
|
||||
}
|
||||
void
|
||||
MgtProbeRequestHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_ssid.Serialize (i);
|
||||
i = m_rates.Serialize (i);
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeRequestHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_ssid.Deserialize (i);
|
||||
i = m_rates.Deserialize (i);
|
||||
return i.GetDistanceFrom (start);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************
|
||||
* Probe Response
|
||||
***********************************************************/
|
||||
|
||||
MgtProbeResponseHeader::MgtProbeResponseHeader ()
|
||||
{}
|
||||
MgtProbeResponseHeader::~MgtProbeResponseHeader ()
|
||||
{}
|
||||
|
||||
Ssid
|
||||
MgtProbeResponseHeader::GetSsid (void) const
|
||||
{
|
||||
return m_ssid;
|
||||
}
|
||||
uint64_t
|
||||
MgtProbeResponseHeader::GetBeaconIntervalUs (void) const
|
||||
{
|
||||
return m_beaconInterval;
|
||||
}
|
||||
SupportedRates
|
||||
MgtProbeResponseHeader::GetSupportedRates (void) const
|
||||
{
|
||||
return m_rates;
|
||||
}
|
||||
|
||||
void
|
||||
MgtProbeResponseHeader::SetSsid (Ssid ssid)
|
||||
{
|
||||
m_ssid = ssid;
|
||||
}
|
||||
void
|
||||
MgtProbeResponseHeader::SetBeaconIntervalUs (uint64_t us)
|
||||
{
|
||||
m_beaconInterval = us;
|
||||
}
|
||||
void
|
||||
MgtProbeResponseHeader::SetSupportedRates (SupportedRates rates)
|
||||
{
|
||||
m_rates = rates;
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = AllocateUid<MgtProbeResponseHeader> ("MgtProbeResponseHeader.ns3.inria.fr");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
MgtProbeResponseHeader::GetName (void) const
|
||||
{
|
||||
return "PROBERESP";
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t size = 0;
|
||||
size += 8; // timestamp
|
||||
size += 2; // beacon interval
|
||||
size += m_capability.GetSerializedSize ();
|
||||
size += m_ssid.GetSerializedSize ();
|
||||
size += m_rates.GetSerializedSize ();
|
||||
size += 3; // ds parameter set
|
||||
// xxx
|
||||
return size;
|
||||
}
|
||||
void
|
||||
MgtProbeResponseHeader::Print (std::ostream &os) const
|
||||
{
|
||||
//XXX
|
||||
}
|
||||
void
|
||||
MgtProbeResponseHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
// timestamp
|
||||
// beacon interval
|
||||
// capability information
|
||||
// ssid
|
||||
// supported rates
|
||||
// fh parameter set
|
||||
// ds parameter set
|
||||
// cf parameter set
|
||||
// ibss parameter set
|
||||
//XXX
|
||||
Buffer::Iterator i = start;
|
||||
i.WriteHtonU64 (Simulator::Now ().GetMicroSeconds ());
|
||||
i.WriteHtonU16 (m_beaconInterval / 1024);
|
||||
i = m_capability.Serialize (i);
|
||||
i = m_ssid.Serialize (i);
|
||||
i = m_rates.Serialize (i);
|
||||
i.Next (3); // ds parameter set.
|
||||
}
|
||||
uint32_t
|
||||
MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i.Next (8); // timestamp
|
||||
m_beaconInterval = i.ReadNtohU16 ();
|
||||
m_beaconInterval *= 1024;
|
||||
i = m_capability.Deserialize (i);
|
||||
i = m_ssid.Deserialize (i);
|
||||
i = m_rates.Deserialize (i);
|
||||
i.Next (3); // ds parameter set
|
||||
return i.GetDistanceFrom (start);
|
||||
}
|
||||
|
||||
|
||||
MgtAssocRequestHeader::MgtAssocRequestHeader ()
|
||||
{}
|
||||
MgtAssocRequestHeader::~MgtAssocRequestHeader ()
|
||||
{}
|
||||
|
||||
void
|
||||
MgtAssocRequestHeader::SetSsid (Ssid ssid)
|
||||
{
|
||||
m_ssid = ssid;
|
||||
}
|
||||
void
|
||||
MgtAssocRequestHeader::SetSupportedRates (SupportedRates rates)
|
||||
{
|
||||
m_rates = rates;
|
||||
}
|
||||
void
|
||||
MgtAssocRequestHeader::SetListenInterval (uint16_t interval)
|
||||
{
|
||||
m_listenInterval = interval;
|
||||
}
|
||||
Ssid
|
||||
MgtAssocRequestHeader::GetSsid (void) const
|
||||
{
|
||||
return m_ssid;
|
||||
}
|
||||
SupportedRates
|
||||
MgtAssocRequestHeader::GetSupportedRates (void) const
|
||||
{
|
||||
return m_rates;
|
||||
}
|
||||
uint16_t
|
||||
MgtAssocRequestHeader::GetListenInterval (void) const
|
||||
{
|
||||
return m_listenInterval;
|
||||
}
|
||||
uint32_t
|
||||
MgtAssocRequestHeader::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = AllocateUid<MgtAssocRequestHeader> ("MgtAssocRequestHeader.ns3.inria.fr");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
MgtAssocRequestHeader::GetName (void) const
|
||||
{
|
||||
return "ASSOCREQ";
|
||||
}
|
||||
uint32_t
|
||||
MgtAssocRequestHeader::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t size = 0;
|
||||
size += m_capability.GetSerializedSize ();
|
||||
size += 2;
|
||||
size += m_ssid.GetSerializedSize ();
|
||||
size += m_rates.GetSerializedSize ();
|
||||
return size;
|
||||
}
|
||||
void
|
||||
MgtAssocRequestHeader::Print (std::ostream &os) const
|
||||
{
|
||||
//XXX
|
||||
}
|
||||
void
|
||||
MgtAssocRequestHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_capability.Serialize (i);
|
||||
i.WriteHtonU16 (m_listenInterval);
|
||||
i = m_ssid.Serialize (i);
|
||||
i = m_rates.Serialize (i);
|
||||
}
|
||||
uint32_t
|
||||
MgtAssocRequestHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_capability.Deserialize (i);
|
||||
m_listenInterval = i.ReadNtohU16 ();
|
||||
i = m_ssid.Deserialize (i);
|
||||
i = m_rates.Deserialize (i);
|
||||
return i.GetDistanceFrom (start);
|
||||
}
|
||||
|
||||
MgtAssocResponseHeader::MgtAssocResponseHeader ()
|
||||
{}
|
||||
MgtAssocResponseHeader::~MgtAssocResponseHeader ()
|
||||
{}
|
||||
|
||||
StatusCode
|
||||
MgtAssocResponseHeader::GetStatusCode (void)
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
void
|
||||
MgtAssocResponseHeader::SetStatusCode (StatusCode code)
|
||||
{
|
||||
m_code = code;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MgtAssocResponseHeader::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = AllocateUid<MgtAssocResponseHeader> ("MgtAssocResponseHeader.ns3.inria.fr");
|
||||
return uid;
|
||||
}
|
||||
std::string
|
||||
MgtAssocResponseHeader::GetName (void) const
|
||||
{
|
||||
return "ASSOCRESP";
|
||||
}
|
||||
uint32_t
|
||||
MgtAssocResponseHeader::GetSerializedSize (void) const
|
||||
{
|
||||
uint32_t size = 0;
|
||||
size += m_capability.GetSerializedSize ();
|
||||
size += m_code.GetSerializedSize ();
|
||||
size += 2; // aid
|
||||
size += m_rates.GetSerializedSize ();
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
MgtAssocResponseHeader::Print (std::ostream &os) const
|
||||
{
|
||||
//XXX
|
||||
}
|
||||
void
|
||||
MgtAssocResponseHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_capability.Serialize (i);
|
||||
i = m_code.Serialize (i);
|
||||
i.WriteHtonU16 (m_aid);
|
||||
i = m_rates.Serialize (i);
|
||||
}
|
||||
uint32_t
|
||||
MgtAssocResponseHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
i = m_capability.Deserialize (i);
|
||||
i = m_code.Deserialize (i);
|
||||
m_aid = i.ReadNtohU16 ();
|
||||
i = m_rates.Deserialize (i);
|
||||
return i.GetDistanceFrom (start);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
136
src/devices/wifi/mgt-headers.h
Normal file
136
src/devices/wifi/mgt-headers.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2006 INRIA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
|
||||
*/
|
||||
#ifndef MGT_HEADERS_H
|
||||
#define MGT_HEADERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ns3/header.h"
|
||||
#include "status-code.h"
|
||||
#include "capability-information.h"
|
||||
#include "supported-rates.h"
|
||||
#include "ssid.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class MgtAssocRequestHeader : public Header
|
||||
{
|
||||
public:
|
||||
MgtAssocRequestHeader ();
|
||||
~MgtAssocRequestHeader ();
|
||||
|
||||
void SetSsid (Ssid ssid);
|
||||
void SetSupportedRates (SupportedRates rates);
|
||||
void SetListenInterval (uint16_t interval);
|
||||
|
||||
Ssid GetSsid (void) const;
|
||||
SupportedRates GetSupportedRates (void) const;
|
||||
uint16_t GetListenInterval (void) const;
|
||||
|
||||
static uint32_t GetUid (void);
|
||||
std::string GetName (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
private:
|
||||
Ssid m_ssid;
|
||||
SupportedRates m_rates;
|
||||
CapabilityInformation m_capability;
|
||||
uint16_t m_listenInterval;
|
||||
};
|
||||
|
||||
class MgtAssocResponseHeader : public Header {
|
||||
public:
|
||||
MgtAssocResponseHeader ();
|
||||
~MgtAssocResponseHeader ();
|
||||
|
||||
StatusCode GetStatusCode (void);
|
||||
void SetStatusCode (StatusCode code);
|
||||
|
||||
static uint32_t GetUid (void);
|
||||
std::string GetName (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
private:
|
||||
SupportedRates m_rates;
|
||||
CapabilityInformation m_capability;
|
||||
StatusCode m_code;
|
||||
uint16_t m_aid;
|
||||
};
|
||||
|
||||
class MgtProbeRequestHeader : public Header {
|
||||
public:
|
||||
~MgtProbeRequestHeader ();
|
||||
|
||||
void SetSsid (Ssid ssid);
|
||||
void SetSupportedRates (SupportedRates rates);
|
||||
Ssid GetSsid (void) const;
|
||||
SupportedRates GetSupportedRates (void) const;
|
||||
|
||||
static uint32_t GetUid (void);
|
||||
std::string GetName (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
uint32_t Deserialize (Buffer::Iterator start);
|
||||
private:
|
||||
|
||||
Ssid m_ssid;
|
||||
SupportedRates m_rates;
|
||||
};
|
||||
|
||||
class MgtProbeResponseHeader : public Header {
|
||||
public:
|
||||
MgtProbeResponseHeader ();
|
||||
~MgtProbeResponseHeader ();
|
||||
|
||||
Ssid GetSsid (void) const;
|
||||
uint64_t GetBeaconIntervalUs (void) const;
|
||||
SupportedRates GetSupportedRates (void) const;
|
||||
|
||||
void SetSsid (Ssid ssid);
|
||||
void SetBeaconIntervalUs (uint64_t us);
|
||||
void SetSupportedRates (SupportedRates rates);
|
||||
|
||||
static uint32_t GetUid (void);
|
||||
std::string GetName (void) const;
|
||||
void Print (std::ostream &os) const;
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
void Serialize (Buffer::Iterator start) const;
|
||||
uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
private:
|
||||
Ssid m_ssid;
|
||||
uint64_t m_beaconInterval;
|
||||
SupportedRates m_rates;
|
||||
CapabilityInformation m_capability;
|
||||
};
|
||||
|
||||
class MgtBeaconHeader : public MgtProbeResponseHeader {};
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* MGT_HEADERS_H */
|
||||
@@ -40,21 +40,22 @@ StatusCode::IsSuccess (void) const
|
||||
{
|
||||
return (m_code == 0)?true:false;
|
||||
}
|
||||
uint16_t
|
||||
StatusCode::PeekCode (void) const
|
||||
{
|
||||
return m_code;
|
||||
}
|
||||
void
|
||||
StatusCode::SetCode (uint16_t code)
|
||||
{
|
||||
m_code = code;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
StatusCode::GetSize (void) const
|
||||
StatusCode::GetSerializedSize (void) const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
Buffer::Iterator
|
||||
StatusCode::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
start.WriteHtonU16 (m_code);
|
||||
return start;
|
||||
}
|
||||
Buffer::Iterator
|
||||
StatusCode::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
m_code = start.ReadNtohU16 ();
|
||||
return start;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#define STATUS_CODE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ns3/buffer.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
@@ -31,9 +32,10 @@ public:
|
||||
void SetFailure (void);
|
||||
|
||||
bool IsSuccess (void) const;
|
||||
uint16_t PeekCode (void) const;
|
||||
void SetCode (uint16_t code);
|
||||
uint32_t GetSize (void) const;
|
||||
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
Buffer::Iterator Serialize (Buffer::Iterator start) const;
|
||||
Buffer::Iterator Deserialize (Buffer::Iterator start);
|
||||
private:
|
||||
uint16_t m_code;
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ def build(bld):
|
||||
'supported-rates.cc',
|
||||
'capability-information.cc',
|
||||
'status-code.cc',
|
||||
'mgt-headers.cc',
|
||||
]
|
||||
headers = bld.create_obj('ns3header')
|
||||
headers.source = [
|
||||
|
||||
Reference in New Issue
Block a user