Handle TCH traffic during a call. This is called from the dedicated thread created for a combination I full rate TCH in GSMConfig. It is called from DCCHDispatch. Prior to L3rewrite TCH traffic and messages were handled by callManagementLoop(), which called pollInCall(), updateGSMSignalling()
| 819 | // It is called from DCCHDispatch. |
| 820 | // Prior to L3rewrite TCH traffic and messages were handled by callManagementLoop(), which called pollInCall(), updateGSMSignalling() |
| 821 | static void l3CallTrafficLoop(L3LogicalChannel *dcch) |
| 822 | { |
| 823 | assert(dcch->chtype() == FACCHType); |
| 824 | GSM::TCHFACCHLogicalChannel *tch = dynamic_cast<typeof(tch)>(dcch); |
| 825 | // The gReports call invokes sqlite3 which takes tenths of seconds, which is too long |
| 826 | // during a voice call, and especially a handover, so only call gReports if nothing else is pending. |
| 827 | bool needReports = true; |
| 828 | int nextDelay = 0; |
| 829 | |
| 830 | //LOG(INFO) << "call connected "<<*tran; |
| 831 | size_t fCount = 0; // A rough count of frames. |
| 832 | // chanRunning checks for loss in L3. radioFailure checks for loss in L2. |
| 833 | // Original code used throw...catch but during channel reassignment the channel state is terminated by changing |
| 834 | // the state by a different thread, so we just the same method for all cases and terminate by changing the channel state. |
| 835 | unsigned alternate = 0; |
| 836 | while (dcch->chanRunning()) { |
| 837 | if (tch->radioFailure()) { |
| 838 | LOG(NOTICE) << "radio link failure, dropped call"<<LOGVAR(dcch); |
| 839 | //gNewTransactionTable.ttLostChannel(dcch); |
| 840 | // The radioFailure already waited for the timeout, so now we can immediately drop the channel. |
| 841 | dcch->chanRelease(HARDRELEASE); // Kill off all the transactions associated with this channel. |
| 842 | //tran->getDialog()->dialogCancel(); //was forceSIPClearing |
| 843 | //tran->teRemove(); |
| 844 | return; |
| 845 | } |
| 846 | // The voiceTrans will not yet be set when this loop starts. |
| 847 | // The MS establishes SABM over LAPDm which sends up an ESTABLISH primitive, |
| 848 | // then we get the AssignmentComplete L3 message over this FACCH channel, |
| 849 | // which calls the controling state machine to set voiceTrans. |
| 850 | RefCntPointer<TranEntry> rtran = dcch->chanGetVoiceTran(); |
| 851 | TranEntry *tran = rtran.self(); |
| 852 | LOG(DEBUG) <<dcch <<" main loop"<<LOGVAR(nextDelay)<<" found tran:"<<(tran!=NULL); // warning: tran may be NULL. |
| 853 | if (tran != NULL) { |
| 854 | if (tran->deadOrRemoved()) { |
| 855 | // This is ok. If there is something else ongoing (eg SMS) when the voice call ends |
| 856 | // we should keep the channel open until that ends. |
| 857 | LOG(NOTICE) << "attempting to use a defunct Transaction"<<LOGVAR(dcch)<<LOGVAR(*tran); |
| 858 | // TODO: We should not be closing the channel here; we whould wait |
| 859 | dcch->chanClose(L3RRCause::PreemptiveRelease,RELEASE); |
| 860 | return; |
| 861 | } |
| 862 | // TODO: This needs to check all the transactions in the MMContext. |
| 863 | // The termination request comes from the CLI or from RadioResource to make room for an SOS call. |
| 864 | if (tran->terminationRequested()) { |
| 865 | LOG(DEBUG)<<dcch<<" terminationRequested"; |
| 866 | tran->terminateHook(); // Gives the L3Procedure state machine a chance to do something first. |
| 867 | dcch->chanClose(L3RRCause::PreemptiveRelease,RELEASE); |
| 868 | return; // We wont be back. |
| 869 | } |
| 870 | if (tran->getGSMState() == CCState::HandoverOutbound) { |
| 871 | if (outboundHandoverTransfer(tran,dcch)) { |
| 872 | LOG(DEBUG)<<dcch<<" outboundHandover"; |
| 873 | dcch->chanRelease(HARDRELEASE); |
| 874 | return; // We wont be back. |
| 875 | } |
| 876 | } |
| 877 | |
| 878 | // Any Q.931 timer expired? |
no test coverage detected