/* * The RF class models a broadcast-based wireless system via UDP services. * The layer simulates collisions properly (packets involved in a collision * are never delivered to the MAC layer), and provides the carrier-sense * facility required to implement a CSMA-like system. The RF layer knows * nothing about addresing, packet structures, etc. It simply takes a * collection of bytes from the caller and broadcasts them. Similarly, * incoming transmissions from any and all sources are collected and * delivered, as long as they were not involved in a collision. * * Note that most switches and routers are configured not to pass UDP * broadcast traffic. This limits the use of the simulated RF layer to machines * within the same physical subnet. * * By default, the IP broadcast address 255.255.255.255 is used. This can * be changed by editing the bcastAddr array, defined at the top of RF.cpp. * * Brad Richards, 10/2008 */ // The SIFS inter-frame spacing time, in milliseconds #define aSIFSTime 100 // The slot time, in milliseconds #define aSlotTime 200 // The minimum size of the collision window #define aCWmin 3 // The maximum size of the collision window #define aCWmax 31 // The maximum nubmer of retransmission attempts #define dot11RetryLimit 5 // The maximum number of bytes allowed in an RF packet #define aMPDUMaximumLength 2048 #include class RF { public: /* * The constructor initializes the simulated RF transceiver and prepares it * for use. An RF instance initializes its internal clock when created, and * reports all times as milliseconds since creation, so times are not * directly comparable across RF transceivers. (It prints the exact time * of creation though, and this information could be used to convert local * times to absolute wall-clock time if one really wanted to.) It is not * possible to create more than one RF layer on a single machine, as they * must bind to a fixed port and will conflict. * The C++ constructor creates a JVM instance, loads the Java RF * class, and links the C++ member functions to their Java counterparts * The RF.class file must be in the same directory as RF.cpp for this to * work. */ RF(); /* * Each thread must call this method before attempting to use any of the * other member functions. No harm is done if an already-attached thread * calls this method again. */ void attachThread(); /* * This non-blocking method returns true if the RF layer has * one or more packets to deliver to the caller. Since the RF layer is * broadcast based, and has no notion of addresses, it will deliver any * intact packet that it observes on the channel. In other words, this * method might return true even if the packet wasn't intended for the * MAC layer that called dataWaiting(). */ bool dataWaiting(); /* * The RF layer's local clock. Returns the number of milliseconds elapsed * since the RF layer was created. (Uses System.nanoTime() internally in an * effort to improve accuracy on Windows machines.) */ long long clock(); /* * Returns the number of milliseconds elapsed since the last transmission * on the shared channel ended. If the channel is currently in use, this * method returns zero. Note that the elapsed time reported is the time * since the last transmission by any host, and is therefore not * necessarily the time since this host last transmitted. */ long long getIdleTime(); /* * Inspects the shared channel to see if it's currently being used. This * method does not block, and returns true if at least one host is * currently broadcasting, false otherwise. */ bool inUse(); /* * The receive method blocks until an RF packet arrives, then copies * its contents into the buffer provided by the caller. As with the * sockets routines, receive will respect the size of the buffer as * specified by the second argument. The actual number of bytes * received is returned. If blocking is unacceptable, only call * receive() once dataWaiting() reveals that a packet has arrived. */ int receive(char* buf, int bufSize); /* * This routine broadcasts the specified number of bytes from the * user-provided buffer. It returns the number of bytes sent. */ int transmit(char* buf, int len); private: JavaVM *jvm; jclass rfClass; jobject theRF; jmethodID constructorID; jmethodID inUseID; jmethodID getIdleTimeID; jmethodID dataWaitingID; jmethodID receiveID; jmethodID transmitID; jmethodID clockID; JNIEnv *getEnvPtr(); };