Update or create a new entry in the TMSI table. If we are assigning TMSIs to the MS, return the new TMSI, else 0. This routine checks to see if the record for this IMSI already exists; the caller actually knows this and could inform us, however there is a great deal of logic with many options between the original TMSITable lookup and updating the TMSITable entry here, so I deemed it more robust an
| 463 | // the TMSITable entry here, so I deemed it more robust and resistant to future changes if this routine ignores that |
| 464 | // and does another lookup of the IMSI to see if the record already exists. |
| 465 | uint32_t TMSITable::tmsiTabCreateOrUpdate( |
| 466 | const string imsi, |
| 467 | TmsiTableStore *store, |
| 468 | const GSM::L3LocationAreaIdentity * lai, |
| 469 | uint32_t oldTmsi) |
| 470 | { |
| 471 | // Create or find an entry based on IMSI. |
| 472 | // Return assigned TMSI. |
| 473 | assert(mTmsiDB); |
| 474 | bool sendTmsis = configSendTmsis(); |
| 475 | unsigned now = (unsigned)time(NULL); |
| 476 | |
| 477 | ScopedLock lock(sTmsiMutex,__FILE__,__LINE__); // This lock should be redundant - sql serializes access, but it may prevent sql retry failures. |
| 478 | |
| 479 | unsigned oldRawTmsi = tmsiTabGetTMSI(imsi,false); |
| 480 | bool isNewRecord = (oldRawTmsi == 0); |
| 481 | |
| 482 | TSqlQuery *queryp; // dufus language |
| 483 | TSqlInsert foo; |
| 484 | TSqlUpdate bar; |
| 485 | if (isNewRecord) { |
| 486 | // Create a new record. |
| 487 | queryp = &foo; queryp->reserve(200); |
| 488 | queryp->append("INSERT INTO TMSI_TABLE ("); |
| 489 | queryp->addc("IMSI",imsi); |
| 490 | queryp->addc("CREATED",now); |
| 491 | queryp->addc("ACCESSED",now); |
| 492 | } else { |
| 493 | queryp = &bar; queryp->reserve(200); |
| 494 | // Update existing record. |
| 495 | queryp->append("UPDATE TMSI_TABLE SET "); |
| 496 | } |
| 497 | uint32_t tmsi = 0; |
| 498 | |
| 499 | if (sendTmsis) { |
| 500 | // We are handling several cases here. If it is a new record we are allocating a new tmsi for the first time, |
| 501 | // or if it is an existing record that was created without an assigned tmsi, ie, it has a fake tmsi, |
| 502 | // then we are updating it to a real tmsi. |
| 503 | // We never go backwards, ie, once we allocate a real tmsi, we never change it back to a fake tmsi, |
| 504 | // because we want to reserve the tmsi for this handset effectively forever. |
| 505 | if (! tmsiIsValid(oldRawTmsi)) { |
| 506 | gReports.incr("OpenBTS.GSM.MM.TMSI.Assigned"); |
| 507 | tmsi = allocateTmsi(); |
| 508 | queryp->addc("TMSI",tmsi2table(tmsi)); |
| 509 | } else { |
| 510 | tmsi = oldRawTmsi; |
| 511 | } |
| 512 | } else { |
| 513 | if (isNewRecord) { |
| 514 | // We are creating a new record. |
| 515 | // sqlite3 would auto-assign a unique TMSI higher than any other in |
| 516 | // the table, but we need to handle the initial case for the first fake tmsi. |
| 517 | tmsi = ++sHighestFakeTmsi; |
| 518 | queryp->addc("TMSI",tmsi2table(tmsi)); |
| 519 | } |
| 520 | } |
| 521 | queryp->addStore(store); |
| 522 |
no test coverage detected