|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include "Ieee80211AgentSTA.h" 00020 #include "Ieee80211Primitives_m.h" 00021 #include "NotifierConsts.h" 00022 00023 00024 00025 Define_Module(Ieee80211AgentSTA); 00026 00027 #define MK_STARTUP 1 00028 00029 void Ieee80211AgentSTA::initialize(int stage) 00030 { 00031 if (stage==0) 00032 { 00033 // read parameters 00034 activeScan = par("activeScan"); 00035 probeDelay = par("probeDelay"); 00036 minChannelTime = par("minChannelTime"); 00037 maxChannelTime = par("maxChannelTime"); 00038 authenticationTimeout = par("authenticationTimeout"); 00039 associationTimeout = par("associationTimeout"); 00040 cStringTokenizer tokenizer(par("channelsToScan")); 00041 const char *token; 00042 while ((token = tokenizer.nextToken())!=NULL) 00043 channelsToScan.push_back(atoi(token)); 00044 00045 NotificationBoard *nb = NotificationBoardAccess().get(); 00046 nb->subscribe(this, NF_L2_BEACON_LOST); 00047 00048 // start up: send scan request 00049 scheduleAt(simTime()+uniform(0,maxChannelTime), new cMessage("startUp", MK_STARTUP)); 00050 } 00051 } 00052 00053 void Ieee80211AgentSTA::handleMessage(cMessage *msg) 00054 { 00055 if (msg->isSelfMessage()) 00056 handleTimer(msg); 00057 else 00058 handleResponse(msg); 00059 } 00060 00061 void Ieee80211AgentSTA::handleTimer(cMessage *msg) 00062 { 00063 if (msg->getKind()==MK_STARTUP) 00064 { 00065 EV << "Starting up\n"; 00066 sendScanRequest(); 00067 delete msg; 00068 } 00069 else 00070 { 00071 error("internal error: unrecognized timer '%s'", msg->getName()); 00072 } 00073 } 00074 00075 void Ieee80211AgentSTA::handleResponse(cMessage *msg) 00076 { 00077 cPolymorphic *ctrl = msg->removeControlInfo(); 00078 delete msg; 00079 00080 EV << "Processing confirmation from mgmt: " << ctrl->getClassName() << "\n"; 00081 00082 if (dynamic_cast<Ieee80211Prim_ScanConfirm *>(ctrl)) 00083 processScanConfirm((Ieee80211Prim_ScanConfirm *)ctrl); 00084 else if (dynamic_cast<Ieee80211Prim_AuthenticateConfirm *>(ctrl)) 00085 processAuthenticateConfirm((Ieee80211Prim_AuthenticateConfirm *)ctrl); 00086 else if (dynamic_cast<Ieee80211Prim_AssociateConfirm *>(ctrl)) 00087 processAssociateConfirm((Ieee80211Prim_AssociateConfirm *)ctrl); 00088 else if (dynamic_cast<Ieee80211Prim_ReassociateConfirm *>(ctrl)) 00089 processReassociateConfirm((Ieee80211Prim_ReassociateConfirm *)ctrl); 00090 else if (ctrl) 00091 error("handleResponse(): unrecognized control info class `%s'", ctrl->getClassName()); 00092 else 00093 error("handleResponse(): control info is NULL"); 00094 delete ctrl; 00095 } 00096 00097 void Ieee80211AgentSTA::receiveChangeNotification(int category, const cPolymorphic *details) 00098 { 00099 Enter_Method_Silent(); 00100 printNotificationBanner(category, details); 00101 00102 if (category == NF_L2_BEACON_LOST) 00103 { 00104 //XXX should check details if it's about this NIC 00105 EV << "beacon lost, starting scanning again\n"; 00106 getParentModule()->getParentModule()->bubble("Beacon lost!"); 00107 //sendDisassociateRequest(); 00108 sendScanRequest(); 00109 } 00110 } 00111 00112 void Ieee80211AgentSTA::sendRequest(Ieee80211PrimRequest *req) 00113 { 00114 cMessage *msg = new cMessage(req->getClassName()); 00115 msg->setControlInfo(req); 00116 send(msg, "mgmtOut"); 00117 } 00118 00119 00120 void Ieee80211AgentSTA::sendScanRequest() 00121 { 00122 EV << "Sending ScanRequest primitive to mgmt\n"; 00123 Ieee80211Prim_ScanRequest *req = new Ieee80211Prim_ScanRequest(); 00124 req->setBSSType(BSSTYPE_INFRASTRUCTURE); 00125 req->setActiveScan(activeScan); 00126 req->setProbeDelay(probeDelay); 00127 req->setMinChannelTime(minChannelTime); 00128 req->setMaxChannelTime(maxChannelTime); 00129 req->setChannelListArraySize(channelsToScan.size()); 00130 for (int i=0; i<(int)channelsToScan.size(); i++) 00131 req->setChannelList(i, channelsToScan[i]); 00132 //XXX BSSID, SSID are left at default ("any") 00133 00134 sendRequest(req); 00135 } 00136 00137 void Ieee80211AgentSTA::sendAuthenticateRequest(const MACAddress& address) 00138 { 00139 EV << "Sending AuthenticateRequest primitive to mgmt\n"; 00140 Ieee80211Prim_AuthenticateRequest *req = new Ieee80211Prim_AuthenticateRequest(); 00141 req->setAddress(address); 00142 req->setTimeout(authenticationTimeout); 00143 sendRequest(req); 00144 } 00145 00146 void Ieee80211AgentSTA::sendDeauthenticateRequest(const MACAddress& address, int reasonCode) 00147 { 00148 EV << "Sending DeauthenticateRequest primitive to mgmt\n"; 00149 Ieee80211Prim_DeauthenticateRequest *req = new Ieee80211Prim_DeauthenticateRequest(); 00150 req->setAddress(address); 00151 req->setReasonCode(reasonCode); 00152 sendRequest(req); 00153 } 00154 00155 void Ieee80211AgentSTA::sendAssociateRequest(const MACAddress& address) 00156 { 00157 EV << "Sending AssociateRequest primitive to mgmt\n"; 00158 Ieee80211Prim_AssociateRequest *req = new Ieee80211Prim_AssociateRequest(); 00159 req->setAddress(address); 00160 req->setTimeout(associationTimeout); 00161 sendRequest(req); 00162 } 00163 00164 void Ieee80211AgentSTA::sendReassociateRequest(const MACAddress& address) 00165 { 00166 EV << "Sending ReassociateRequest primitive to mgmt\n"; 00167 Ieee80211Prim_ReassociateRequest *req = new Ieee80211Prim_ReassociateRequest(); 00168 req->setAddress(address); 00169 req->setTimeout(associationTimeout); 00170 sendRequest(req); 00171 } 00172 00173 void Ieee80211AgentSTA::sendDisassociateRequest(const MACAddress& address, int reasonCode) 00174 { 00175 EV << "Sending DisassociateRequest primitive to mgmt\n"; 00176 Ieee80211Prim_DisassociateRequest *req = new Ieee80211Prim_DisassociateRequest(); 00177 req->setAddress(address); 00178 req->setReasonCode(reasonCode); 00179 sendRequest(req); 00180 } 00181 00182 void Ieee80211AgentSTA::processScanConfirm(Ieee80211Prim_ScanConfirm *resp) 00183 { 00184 // choose best AP 00185 int bssIndex = chooseBSS(resp); 00186 if (bssIndex==-1) 00187 { 00188 EV << "No (suitable) AP found, continue scanning\n"; 00189 sendScanRequest(); 00190 return; 00191 } 00192 00193 dumpAPList(resp); 00194 00195 Ieee80211Prim_BSSDescription& bssDesc = resp->getBssList(bssIndex); 00196 EV << "Chosen AP address=" << bssDesc.getBSSID() << " from list, starting authentication\n"; 00197 sendAuthenticateRequest(bssDesc.getBSSID()); 00198 } 00199 00200 void Ieee80211AgentSTA::dumpAPList(Ieee80211Prim_ScanConfirm *resp) 00201 { 00202 EV << "Received AP list:\n"; 00203 for (int i=0; i<(int)resp->getBssListArraySize(); i++) 00204 { 00205 Ieee80211Prim_BSSDescription& bssDesc = resp->getBssList(i); 00206 EV << " " << i << ". " 00207 << " address=" << bssDesc.getBSSID() 00208 << " channel=" << bssDesc.getChannelNumber() 00209 << " SSID=" << bssDesc.getSSID() 00210 << " beaconIntvl=" << bssDesc.getBeaconInterval() 00211 << " rxPower=" << bssDesc.getRxPower() 00212 << endl; 00213 // later: supportedRates 00214 } 00215 } 00216 00217 int Ieee80211AgentSTA::chooseBSS(Ieee80211Prim_ScanConfirm *resp) 00218 { 00219 if (resp->getBssListArraySize()==0) 00220 return -1; 00221 00222 // here, just choose the one with the greatest receive power 00223 // TODO and which supports a good data rate we support 00224 int bestIndex = 0; 00225 for (int i=0; i<(int)resp->getBssListArraySize(); i++) 00226 if (resp->getBssList(i).getRxPower() > resp->getBssList(bestIndex).getRxPower()) 00227 bestIndex = i; 00228 return bestIndex; 00229 } 00230 00231 void Ieee80211AgentSTA::processAuthenticateConfirm(Ieee80211Prim_AuthenticateConfirm *resp) 00232 { 00233 if (resp->getResultCode()!=PRC_SUCCESS) 00234 { 00235 EV << "Authentication error\n"; 00236 00237 // try scanning again, maybe we'll have better luck next time, possibly with a different AP 00238 EV << "Going back to scanning\n"; 00239 sendScanRequest(); 00240 } 00241 else 00242 { 00243 EV << "Authentication successful, let's try to associate\n"; 00244 sendAssociateRequest(resp->getAddress()); 00245 } 00246 } 00247 00248 void Ieee80211AgentSTA::processAssociateConfirm(Ieee80211Prim_AssociateConfirm *resp) 00249 { 00250 if (resp->getResultCode()!=PRC_SUCCESS) 00251 { 00252 EV << "Association error\n"; 00253 00254 // try scanning again, maybe we'll have better luck next time, possibly with a different AP 00255 EV << "Going back to scanning\n"; 00256 sendScanRequest(); 00257 } 00258 else 00259 { 00260 EV << "Association successful\n"; 00261 // we are happy! 00262 getParentModule()->getParentModule()->bubble("Associated with AP"); 00263 } 00264 } 00265 00266 void Ieee80211AgentSTA::processReassociateConfirm(Ieee80211Prim_ReassociateConfirm *resp) 00267 { 00268 // treat the same way as AssociateConfirm 00269 if (resp->getResultCode()!=PRC_SUCCESS) 00270 { 00271 EV << "Reassociation error\n"; 00272 EV << "Going back to scanning\n"; 00273 sendScanRequest(); 00274 } 00275 else 00276 { 00277 EV << "Reassociation successful\n"; 00278 // we are happy! 00279 } 00280 } 00281