unsigned Pager::pageAll() { // Traverse the full list and page all IDs. // Remove expired IDs. // Return the number of IDs paged. // This is a linear time operation. mLock.lock(); // Clear expired entries. PagingEntryList::iterator lp = mPageIDs.begin(); while (lp != mPageIDs.end()) { if (!lp->expired()) ++lp; else { // DO NOT remove the transaction entry here. // It may be in use in an active call. LOG(INFO) << "erasing " << lp->ID(); lp=mPageIDs.erase(lp); } } LOG(INFO) << "paging " << mPageIDs.size() << " mobile(s)"; // Page remaining entries, two at a time if possible. // These PCH send operations are non-blocking. lp = mPageIDs.begin(); while (lp != mPageIDs.end()) { // FIXME -- This completely ignores the paging groups. // HACK -- So we send every page twice. // That will probably mean a different Pager for each subchannel. // See GSM 04.08 10.5.2.11 and GSM 05.02 6.5.2. const L3MobileIdentity& id1 = lp->ID(); ChannelType type1 = lp->type(); ++lp; if (lp==mPageIDs.end()) { // Just one ID left? LOG(DEBUG) << "paging " << id1; gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); break; } // Page by pairs when possible. const L3MobileIdentity& id2 = lp->ID(); ChannelType type2 = lp->type(); ++lp; LOG(DEBUG) << "paging " << id1 << " and " << id2; gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1,id2,type2)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1,id2,type2)); } mLock.unlock(); return mPageIDs.size(); }
void Pager::addID(const L3MobileIdentity& newID, ChannelType chanType, TransactionEntry& transaction, unsigned wLife) { transaction.Q931State(TransactionEntry::Paging); transaction.T3113().set(wLife); gTransactionTable.update(transaction); // Add a mobile ID to the paging list for a given lifetime. mLock.lock(); // If this ID is already in the list, just reset its timer. // Uhg, another linear time search. // This would be faster if the paging list were ordered by ID. // But the list should usually be short, so it may not be worth the effort. for (PagingEntryList::iterator lp = mPageIDs.begin(); lp != mPageIDs.end(); ++lp) { if (lp->ID()==newID) { LOG(DEBUG) << newID << " already in table"; lp->renew(wLife); mPageSignal.signal(); mLock.unlock(); return; } } // If this ID is new, put it in the list. mPageIDs.push_back(PagingEntry(newID,chanType,transaction.ID(),wLife)); LOG(INFO) << newID << " added to table"; mPageSignal.signal(); mLock.unlock(); }
unsigned Pager::removeID(const L3MobileIdentity& delID) { // Return the associated transaction ID, or 0 if none found. unsigned retVal = 0; LOG(INFO) << delID; mLock.lock(); for (PagingEntryList::iterator lp = mPageIDs.begin(); lp != mPageIDs.end(); ++lp) { if (lp->ID()==delID) { retVal = lp->transactionID(); mPageIDs.erase(lp); break; } } mLock.unlock(); return retVal; }
unsigned Pager::pageAll() { // Traverse the full list and page all IDs. // Remove expired IDs. // Return the number of IDs paged. // This is a linear time operation. mLock.lock(); // Clear expired entries. PagingEntryList::iterator lp = mPageIDs.begin(); while (lp != mPageIDs.end()) { if (!lp->expired()) ++lp; else { // DO NOT remove the transaction entry here. // It may be in use in an active call. LOG(INFO) << "erasing " << lp->ID(); lp=mPageIDs.erase(lp); } } LOG(INFO) << "paging " << mPageIDs.size() << " mobile(s)"; // Page remaining entries, two at a time if possible. // These PCH send operations are non-blocking. lp = mPageIDs.begin(); while (lp != mPageIDs.end()) { // FIXME -- This completely ignores the paging groups. // HACK -- So we send every page twice. // That will probably mean a different Pager for each subchannel. // See GSM 04.08 10.5.2.11 and GSM 05.02 6.5.2. //const FuzzingL3MobileIdentity &FuzzingID1=lp->FuzzingID(); const L3MobileIdentity& id1 = lp->ID(); ChannelType type1 = lp->type(); ++lp; if(gFuzzingControl.state()==L3Fuzzing&&gFuzzingControl.PD()==GSM::L3MobilityManagementPD&&gFuzzingControl.MTI()==L3MMMessage::LocationUpdatingAccept){ LOG(INFO)<<"Sending Paging Request for Location Updating Accept Fuzzing: "<<id1; COUT("Sending SendingPaging Request for Location Updating Accept Fuzzing: "<<id1); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); removeID(id1); break; } if(gFuzzingControl.state()==L3Fuzzing&&gFuzzingControl.PD()==GSM::L3MobilityManagementPD&&gFuzzingControl.MTI()==L3MMMessage::MMInformation){ LOG(INFO)<<"SendingPaging Request for Fuzzing L3MMInformation "<<id1; COUT("Sending SendingPaging Request for L3MMInformation "<<id1); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); removeID(id1); break; } if(gFuzzingControl.state()==TestPhoneConnect){ LOG(INFO)<<"SendingPaging Request for testing Phone connection state"<<id1; COUT("Sending SendingPaging Request for testing Phone connection state "<<id1); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); removeID(id1); break; } if (lp==mPageIDs.end()) { // Just one ID left? LOG(INFO) << "L3PagingRequestType1 is "<<L3PagingRequestType1(id1,type1); LOG(INFO) << "paging " << id1; gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1)); break; } // Page by pairs when possible. const L3MobileIdentity& id2 = lp->ID(); ChannelType type2 = lp->type(); ++lp; LOG(INFO) << "paging " << id1 << " and " << id2; gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1,id2,type2)); gBTS.getPCH(0)->send(L3PagingRequestType1(id1,type1,id2,type2)); } mLock.unlock(); return mPageIDs.size(); }