|
|
| 1 |
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 |
/* |
| 3 |
* This program is free software; you can redistribute it and/or modify |
| 4 |
* it under the terms of the GNU General Public License version 2 as |
| 5 |
* published by the Free Software Foundation; |
| 6 |
* |
| 7 |
* This program is distributed in the hope that it will be useful, |
| 8 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 9 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 10 |
* GNU General Public License for more details. |
| 11 |
* |
| 12 |
* You should have received a copy of the GNU General Public License |
| 13 |
* along with this program; if not, write to the Free Software |
| 14 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 15 |
* |
| 16 |
* Author: Junling Bu <linlinjavaer@gmail.com> |
| 17 |
*/ |
| 18 |
|
| 19 |
#ifndef WSMP_SOCKET_H |
| 20 |
#define WSMP_SOCKET_H |
| 21 |
|
| 22 |
#include "ns3/node.h" |
| 23 |
|
| 24 |
namespace ns3 { |
| 25 |
|
| 26 |
#define PSID_LENGTH_MASK_ONE 0x7f |
| 27 |
#define PSID_LENGTH_MASK_TWO 0xbf |
| 28 |
#define PSID_LENGTH_MASK_THREE 0xdf |
| 29 |
#define PSID_LENGTH_MASK_FOUR 0xef |
| 30 |
|
| 31 |
/** |
| 32 |
* The range of PSID is |
| 33 |
* 1. 0x00 ~ 0x7f |
| 34 |
* 2. 0x8000 ~ 0xbfff |
| 35 |
* 3. 0xc00000 ~ 0xdfffff |
| 36 |
* 4. 0xe0000000 ~ 0xefffffff |
| 37 |
* Other number will be taken as invalid. |
| 38 |
* See IEEE 1609.3 section 8.1.3 and Annex H "PSID examples" |
| 39 |
* |
| 40 |
* Usage: |
| 41 |
* Psid validPsid1 = Psid(0x01); |
| 42 |
* Psid validPsid2 = Psid(0x80, 0x01); |
| 43 |
* Psid validPsid3 = Psid(0xc0, 0x00, 0x01); |
| 44 |
* Psid validPsid4 = Psid(0xef, 0x00, 0x00, 0x01); |
| 45 |
* Psid invalidPsid1 = Psid(); // this is an invalid PSID which cannot be used for transmit. |
| 46 |
* Psid invalidPsid2 = Psid(0x81); // this is an invalid PSID which cannot be used for transmit. |
| 47 |
* |
| 48 |
* A special "null" Psid is invalid, but here is used internally by class WsmpProtocol. |
| 49 |
* Users should not use the "null" Psid for transmit. |
| 50 |
*/ |
| 51 |
|
| 52 |
class Psid { |
| 53 |
public: |
| 54 |
Psid (); |
| 55 |
Psid (uint8_t data0); |
| 56 |
Psid (uint8_t data0, uint8_t data1); |
| 57 |
Psid (uint8_t data0, uint8_t data1, uint8_t data2); |
| 58 |
Psid (uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3); |
| 59 |
Psid (uint8_t * data, uint8_t length); |
| 60 |
|
| 61 |
bool IsValid (void) const; |
| 62 |
|
| 63 |
bool IsNull (void) const; |
| 64 |
|
| 65 |
bool IsEqualTo (const Psid & psid) const; |
| 66 |
|
| 67 |
const uint8_t * GetData (void) const; |
| 68 |
uint8_t GetLength (void) const; |
| 69 |
|
| 70 |
private: |
| 71 |
void Assert (void); |
| 72 |
|
| 73 |
friend std::ostream& operator<< (std::ostream& os, const Psid & psid); |
| 74 |
friend bool operator == (const Psid &a, const Psid &b); |
| 75 |
friend bool operator != (const Psid &a, const Psid &b); |
| 76 |
|
| 77 |
uint8_t m_data[4]; |
| 78 |
uint8_t m_length; |
| 79 |
}; |
| 80 |
|
| 81 |
std::ostream& operator<< (std::ostream& os, const Psid & psid); |
| 82 |
bool operator == (const Psid &a, const Psid &b); |
| 83 |
bool operator != (const Psid &a, const Psid &b); |
| 84 |
|
| 85 |
/** |
| 86 |
* WSMP Normal, see 5.5, 7.3.2 |
| 87 |
* WSMP Safety supplement, see Annex F |
| 88 |
* WSMP Identify supplement, see IEEE 1609.1 |
| 89 |
* |
| 90 |
*/ |
| 91 |
enum WsmpElementId { |
| 92 |
WSMP_N, |
| 93 |
WSMP_S, |
| 94 |
WSMP_I, |
| 95 |
WSMP_UNKNOW, |
| 96 |
}; |
| 97 |
|
| 98 |
class WsmpInfo { |
| 99 |
public: |
| 100 |
WsmpInfo () |
| 101 |
: m_channel (0), |
| 102 |
m_channelExtension (false), |
| 103 |
m_datarate (0), |
| 104 |
m_datarateExtension (false), |
| 105 |
m_power (0), |
| 106 |
m_powerExtension (false), |
| 107 |
m_id (WSMP_N), |
| 108 |
m_priority (7) |
| 109 |
{ |
| 110 |
|
| 111 |
} |
| 112 |
|
| 113 |
void SetChannelNumber (uint8_t channel, bool extensonEnabled) |
| 114 |
{ |
| 115 |
m_channel = channel; |
| 116 |
m_channelExtension = extensonEnabled; |
| 117 |
} |
| 118 |
|
| 119 |
uint8_t GetChannelNumber (void) |
| 120 |
{ |
| 121 |
return m_channel; |
| 122 |
} |
| 123 |
|
| 124 |
bool IsChannelNumberExtension (void) |
| 125 |
{ |
| 126 |
return m_channelExtension; |
| 127 |
} |
| 128 |
|
| 129 |
void SetDataRate (uint8_t datarate, bool extensionEnabled) |
| 130 |
{ |
| 131 |
m_datarate = datarate; |
| 132 |
m_datarateExtension = extensionEnabled; |
| 133 |
} |
| 134 |
|
| 135 |
uint8_t GetDataRate (void) |
| 136 |
{ |
| 137 |
return m_datarate; |
| 138 |
} |
| 139 |
|
| 140 |
bool IsDatatRateExtension (void) |
| 141 |
{ |
| 142 |
return m_datarateExtension; |
| 143 |
} |
| 144 |
|
| 145 |
void SetTxPower (uint8_t power, bool extensionEnabled) |
| 146 |
{ |
| 147 |
m_power = power; |
| 148 |
m_powerExtension = extensionEnabled; |
| 149 |
} |
| 150 |
|
| 151 |
uint8_t GetTxPower (void) |
| 152 |
{ |
| 153 |
return m_power; |
| 154 |
} |
| 155 |
|
| 156 |
bool IsTxPowerExtension (void) |
| 157 |
{ |
| 158 |
return m_powerExtension; |
| 159 |
} |
| 160 |
|
| 161 |
void SetElementId (WsmpElementId id) |
| 162 |
{ |
| 163 |
m_id = id; |
| 164 |
} |
| 165 |
|
| 166 |
WsmpElementId GetElementId (void) |
| 167 |
{ |
| 168 |
return m_id; |
| 169 |
} |
| 170 |
|
| 171 |
void SetUserPriority (uint8_t priority) |
| 172 |
{ |
| 173 |
m_priority = priority; |
| 174 |
} |
| 175 |
|
| 176 |
uint8_t GetUserPriority (void) |
| 177 |
{ |
| 178 |
return m_priority; |
| 179 |
} |
| 180 |
|
| 181 |
private: |
| 182 |
uint8_t m_channel; |
| 183 |
bool m_channelExtension; |
| 184 |
uint8_t m_datarate; |
| 185 |
bool m_datarateExtension; |
| 186 |
uint8_t m_power; |
| 187 |
bool m_powerExtension; |
| 188 |
WsmpElementId m_id; |
| 189 |
uint8_t m_priority; |
| 190 |
}; |
| 191 |
|
| 192 |
/** |
| 193 |
* \brief A low-level Socket API |
| 194 |
* \ingroup wave |
| 195 |
* |
| 196 |
* WsmpSocket API is similar with BSD Socket API, but still differs from BSD Socket API, |
| 197 |
* thus this class does not inherit directly from ns3::Socket class. |
| 198 |
* |
| 199 |
* To satisfy users who are familiar with UDP, here also providers connectionless methods. |
| 200 |
* - For transmit: Connect, Send, Close |
| 201 |
* - For receipt: Bind, Recv, Close. |
| 202 |
* |
| 203 |
* Usage: |
| 204 |
* TypeId tid = TypeId::LookupByName ("ns3::WsmpSocketFactory"); |
| 205 |
* |
| 206 |
* Ptr<WsmpSocket> recv = WsmpSocket::CreateSocket (c.Get (0), tid); |
| 207 |
* Psid psid = Psid(0x80, 0x01); |
| 208 |
* recv->Bind (psid); |
| 209 |
* recv->SetRecvCallback (MakeCallback (&ReceivePacket)); |
| 210 |
* |
| 211 |
* Ptr<WsmpSocket> source = WsmpSocket::CreateSocket (c.Get (1), tid); |
| 212 |
* source->Connect (Mac48Address::GetBroadcast(), psid); |
| 213 |
* Simulator::Schedule(Seconds (1.0), &SendPacket, source); |
| 214 |
*/ |
| 215 |
class WsmpSocket : public Object { |
| 216 |
public: |
| 217 |
/** |
| 218 |
* \brief Get the type ID. |
| 219 |
* \return the object TypeId |
| 220 |
*/ |
| 221 |
static TypeId GetTypeId (void); |
| 222 |
WsmpSocket(); |
| 223 |
virtual ~WsmpSocket(); |
| 224 |
|
| 225 |
/** |
| 226 |
* This method wraps the creation of sockets that is performed |
| 227 |
* on a given node by a WsmpSocketFactory specified by TypeId. |
| 228 |
* |
| 229 |
* \return A smart pointer to a newly created socket. |
| 230 |
* |
| 231 |
* \param node The node on which to create the socket |
| 232 |
* \param tid The TypeId of a WsmpSocketFactory class to use |
| 233 |
*/ |
| 234 |
static Ptr<WsmpSocket> CreateSocket (Ptr<Node> node, TypeId tid); |
| 235 |
|
| 236 |
/** |
| 237 |
* \brief Notify application when new data is available to be read. |
| 238 |
* \param callback This callback is intended to notify a socket that would |
| 239 |
* have been blocked in a blocking socket model that data is available to be read. |
| 240 |
*/ |
| 241 |
void SetRecvCallback (Callback<void, Ptr<WsmpSocket> > callback); |
| 242 |
|
| 243 |
/** |
| 244 |
* \brief Allocate a local endpoint for this socket. |
| 245 |
* \returns 0 on success, -1 on failure. |
| 246 |
* |
| 247 |
* Note: This WsmpSocket::Bind() behavior is different from Socket::Bind(). |
| 248 |
* Socket::Bind() will randomly select a unused Port for Recv, |
| 249 |
* while WsmpSocket::Bind() will only bind a special "null" Psid, so that |
| 250 |
* any incoming WSMP packet will notify the RecvCallback. |
| 251 |
*/ |
| 252 |
virtual int Bind (void) = 0; |
| 253 |
/** |
| 254 |
* \brief Allocate a local endpoint for this socket. |
| 255 |
* \param psid the psid to try to allocate |
| 256 |
* \returns 0 on success, -1 on failure. |
| 257 |
*/ |
| 258 |
virtual int Bind (const Psid &psid) = 0; |
| 259 |
|
| 260 |
/** |
| 261 |
* \brief Initiate a connection to all of remote hosts |
| 262 |
* \param psid Psid of remote. |
| 263 |
* \returns 0 on success, -1 on error (in which case errno is set). |
| 264 |
* |
| 265 |
* Note: Although it is named "connect", the WSMP protocol is only a |
| 266 |
* connectionless service, thus this method is just a convenient and |
| 267 |
* helpful function for Send (Packet) method. |
| 268 |
*/ |
| 269 |
virtual int Connect (const Psid &psid) = 0; |
| 270 |
/** |
| 271 |
* \brief Initiate a connection to a remote host |
| 272 |
* \param peer the peer address |
| 273 |
* \param psid the psid in the WSMP header of this packet |
| 274 |
* \returns 0 on success, -1 on error (in which case errno is set). |
| 275 |
* |
| 276 |
* Note: Although it is named "connect", the WSMP protocol is only a |
| 277 |
* connectionless service, thus this method is just a convenient and |
| 278 |
* helpful function for Send (Packet) method. |
| 279 |
*/ |
| 280 |
virtual int Connect (const Address &peer, const Psid &psid) = 0; |
| 281 |
/** |
| 282 |
* \brief Initiate a connection to a remote host |
| 283 |
* \param peer the peer address |
| 284 |
* \param psid the psid in the WSMP header of this packet |
| 285 |
* \param info the transmit and extension information of this packet |
| 286 |
* \returns 0 on success, -1 on error (in which case errno is set). |
| 287 |
* |
| 288 |
* Note: Although it is named "connect", the WSMP protocol is only a |
| 289 |
* connectionless service, thus this method is just a convenient and |
| 290 |
* helpful function for Send (Packet) method. |
| 291 |
*/ |
| 292 |
virtual int Connect (const Address &peer, const Psid &psid, const WsmpInfo &info) = 0; |
| 293 |
|
| 294 |
/** |
| 295 |
* \brief Send data (or dummy data) to the remote host |
| 296 |
* |
| 297 |
* \param packet ns3::Packet to send |
| 298 |
* \returns the number of bytes accepted for transmission if no error |
| 299 |
* occurs, and negative otherwise. |
| 300 |
*/ |
| 301 |
virtual int Send (Ptr<Packet> packet) = 0; |
| 302 |
/** |
| 303 |
* \brief Send data (or dummy data) to the remote host |
| 304 |
* |
| 305 |
* \param packet ns3::Packet to send |
| 306 |
* \param peer the peer address |
| 307 |
* \param psid the psid in the WSMP header of this packet |
| 308 |
* \param info the transmit and extension information of this packet |
| 309 |
* \returns the number of bytes accepted for transmission if no error |
| 310 |
* occurs, and negative otherwise. |
| 311 |
* |
| 312 |
* Note: Although WsmpInfo parameter can determine the transmit channel number, |
| 313 |
* Users should assign channel access for request channel by using WaveNetDevice::StartSch, |
| 314 |
* otherwise the created WaveNetDevice only assigns default continuous CCH channel access. |
| 315 |
*/ |
| 316 |
virtual int SendTo (Ptr<Packet> packet, const Address & peer, const Psid & psid, const WsmpInfo & info) = 0; |
| 317 |
|
| 318 |
/** |
| 319 |
* \brief Read a single packet from the socket |
| 320 |
* |
| 321 |
* \returns Ptr<Packet> of the next in-sequence packet. Returns |
| 322 |
* 0 if the socket cannot return a next in-sequence packet. |
| 323 |
*/ |
| 324 |
virtual Ptr<Packet> Recv (void) = 0; |
| 325 |
/** |
| 326 |
* \brief Recv data from the remote host |
| 327 |
* |
| 328 |
* \param address the peer address |
| 329 |
* \param psid the psid in the WMSP header of coming packet |
| 330 |
* \param info the extension information in the WSMP header of coming packet |
| 331 |
* \returns Ptr<Packet> of the next in-sequence packet. Returns |
| 332 |
* 0 if the socket cannot return a next in-sequence packet. |
| 333 |
*/ |
| 334 |
virtual Ptr<Packet> RecvFrom (Address & address, Psid & psid, WsmpInfo & info) = 0; |
| 335 |
|
| 336 |
/** |
| 337 |
* \returns The number of bytes which can be sent in a single Send call. |
| 338 |
*/ |
| 339 |
virtual uint32_t GetTxAvailable (void) const = 0; |
| 340 |
/** |
| 341 |
* Return number of bytes which can be returned from one or |
| 342 |
* multiple calls to Recv. |
| 343 |
* Must be possible to call this method from the Recv callback. |
| 344 |
* |
| 345 |
* \returns the number of bytes which can be returned from one or |
| 346 |
* multiple Recv calls. |
| 347 |
*/ |
| 348 |
virtual uint32_t GetRxAvailable (void) const = 0; |
| 349 |
|
| 350 |
/** |
| 351 |
* \brief Close a socket. |
| 352 |
* \returns zero on success, -1 on failure. |
| 353 |
* |
| 354 |
* After the Close call, the socket is no longer valid, and cannot |
| 355 |
* safely be used for subsequent operations. |
| 356 |
*/ |
| 357 |
virtual int Close (void) = 0; |
| 358 |
|
| 359 |
protected: |
| 360 |
/** |
| 361 |
* \brief Notify through the callback (if set) that some data have been received. |
| 362 |
*/ |
| 363 |
void NotifyDataRecv (void); |
| 364 |
|
| 365 |
private: |
| 366 |
Callback<void, Ptr<WsmpSocket> > m_receivedData; |
| 367 |
}; |
| 368 |
|
| 369 |
} // namespace ns3 |
| 370 |
|
| 371 |
#endif /* WSMP_SOCKET_H */ |