本文整理汇总了C++中TransactionEntry类的典型用法代码示例。如果您正苦于以下问题:C++ TransactionEntry类的具体用法?C++ TransactionEntry怎么用?C++ TransactionEntry使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了TransactionEntry类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: assert
void Control::AssignmentCompleteHandler(const L3AssignmentComplete *confirm, TCHFACCHLogicalChannel *TCH)
{
// The assignment complete handler is used to
// tie together split transactions across a TCH assignment
// in non-VEA call setup.
assert(TCH);
assert(confirm);
LOG(DEBUG) << *confirm;
// Check the transaction table to know what to do next.
TransactionEntry transaction;
if (!gTransactionTable.find(TCH->transactionID(),transaction)) {
LOG(WARN) << "Assignment Complete with no transaction record for ID " << TCH->transactionID();
throw UnexpectedMessage();
}
LOG(INFO) << "service="<<transaction.service().type();
// These "controller" functions don't return until the call is cleared.
switch (transaction.service().type()) {
case L3CMServiceType::MobileOriginatedCall:
MOCController(transaction,TCH);
break;
case L3CMServiceType::MobileTerminatedCall:
MTCController(transaction,TCH);
break;
default:
LOG(WARN) << "unsupported service " << transaction.service();
throw UnsupportedMessage(transaction.ID());
}
// If we got here, the call is cleared.
}
示例2: clearTransactionHistory
void Control::clearTransactionHistory( TransactionEntry& transaction )
{
SIP::SIPEngine& engine = transaction.SIP();
LOG(DEBUG) << engine.callID()<<" "<< transaction.ID();
gSIPInterface.removeCall(engine.callID());
gTransactionTable.remove(transaction.ID());
}
示例3: frames
/**
Check GSM signalling.
Can block for up to 52 GSM L1 frames (240 ms) because LCH::send is blocking.
@param transaction The call's TransactionEntry.
@param LCH The call's logical channel (TCH/FACCH or SDCCH).
@return true If the call was cleared.
*/
bool updateGSMSignalling(TransactionEntry &transaction, LogicalChannel *LCH, unsigned timeout=0)
{
if (transaction.Q931State()==TransactionEntry::NullState) return true;
// Any Q.931 timer expired?
if (transaction.timerExpired()) {
// Cause 0x66, "recover on timer expiry"
abortCall(transaction,LCH,L3Cause(0x66));
return true;
}
// Look for a control message from MS side.
if (L3Frame *l3 = LCH->recv(timeout)) {
// Check for lower-layer error.
if (l3->primitive() == ERROR) return true;
// Parse and dispatch.
L3Message *l3msg = parseL3(*l3);
delete l3;
bool cleared = false;
if (l3msg) {
LOG(DEBUG) << "received " << *l3msg;
cleared = callManagementDispatchGSM(transaction, LCH, l3msg);
delete l3msg;
}
return cleared;
}
// If we are here, we have timed out, but assume the call is still running.
return false;
}
示例4: addID
void Pager::addID(const FuzzingL3MobileIdentity& 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->FuzzingID()==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();
}
示例5: callManagementLoop
/**
This is the standard call manangement loop, regardless of the origination type.
This function returns when the call is cleared and the channel is released.
@param transaction The transaction record for this call, will be cleared on exit.
@param TCH The TCH+FACCH for the call.
*/
void callManagementLoop(TransactionEntry &transaction, TCHFACCHLogicalChannel* TCH)
{
LOG(INFO) << transaction.subscriber() << " call connected";
transaction.SIP().FlushRTP();
// poll everything until the call is cleared
while (!pollInCall(transaction,TCH)) { }
clearTransactionHistory(transaction);
}
示例6: forceSIPClearing
/**
Force clearing on the SIP side.
@param transaction The call transaction record.
*/
void forceSIPClearing(TransactionEntry& transaction)
{
LOG(INFO) << "SIP state " << transaction.SIP().state();
if (transaction.SIP().state()==SIP::Cleared) return;
if (transaction.SIP().state()!=SIP::Clearing) {
// This also changes the SIP state to "clearing".
transaction.SIP().MODSendBYE();
} else {
transaction.SIP().MODResendBYE();
}
transaction.SIP().MODWaitForOK();
gTransactionTable.update(transaction);
}
示例7: update
void TransactionTable::update(const TransactionEntry& value)
{
// ID==0 is a non-valid special case.
assert(value.ID());
mLock.lock();
if (mTable.find(value.ID())==mTable.end()) {
mLock.unlock();
LOG(WARN) << "attempt to update non-existent transaction entry with key " << value.ID();
return;
}
mTable[value.ID()]=value;
mLock.unlock();
}
示例8: add
void TransactionTable::add(const TransactionEntry& value)
{
LOG(INFO) << "new transaction " << value;
mLock.lock();
mTable[value.ID()]=value;
mLock.unlock();
}
示例9: updateCallTraffic
/**
Update vocoder data transfers in both directions.
@param transaction The transaction object for this call.
@param TCH The traffic channel for this call.
@return True if anything was transferred.
*/
bool updateCallTraffic(TransactionEntry &transaction, TCHFACCHLogicalChannel *TCH)
{
bool activity = false;
SIPEngine& engine = transaction.SIP();
// Transfer in the downlink direction (RTP->GSM).
// Blocking call. On average returns 1 time per 20 ms.
// Returns non-zero if anything really happened.
// Make the rxFrame buffer big enough for G.711.
unsigned char rxFrame[160];
if (engine.RxFrame(rxFrame)) {
activity = true;
TCH->sendTCH(rxFrame);
}
// Transfer in the uplink direction (GSM->RTP).
// Flush FIFO to limit latency.
unsigned maxQ = gConfig.getNum("GSM.MaxSpeechLatency");
while (TCH->queueSize()>maxQ) delete[] TCH->recvTCH();
if (unsigned char *txFrame = TCH->recvTCH()) {
activity = true;
// Send on RTP.
engine.TxFrame(txFrame);
delete[] txFrame;
}
// Return a flag so the caller will know if anything transferred.
return activity;
}
示例10: forceGSMClearing
/**
Force clearing on the GSM side.
@param transaction The call transaction record.
@param LCH The logical channel.
@param cause The L3 abort cause.
*/
void forceGSMClearing(TransactionEntry& transaction, LogicalChannel *LCH, const L3Cause& cause)
{
LOG(INFO) << "Q.931 state " << transaction.Q931State();
if (transaction.Q931State()==TransactionEntry::NullState) return;
if (!transaction.clearing()) {
LCH->send(L3Disconnect(1-transaction.TIFlag(),transaction.TIValue(),cause));
}
LCH->send(L3ReleaseComplete(1-transaction.TIFlag(),transaction.TIValue()));
LCH->send(L3ChannelRelease());
transaction.resetTimers();
transaction.Q931State(TransactionEntry::NullState);
LCH->send(RELEASE);
gTransactionTable.update(transaction);
}
示例11: assert
void Control::MOSMSController(const GSM::L3CMServiceRequest *req, GSM::LogicalChannel *LCH)
{
assert(req);
assert(req->serviceType().type() == GSM::L3CMServiceType::ShortMessage);
assert(LCH);
assert(LCH->type() != GSM::SACCHType);
LOG(INFO) << "MOSMS, req " << *req;
// If we got a TMSI, find the IMSI.
// Note that this is a copy, not a reference.
GSM::L3MobileIdentity mobileID = req->mobileID();
resolveIMSI(mobileID,LCH);
// Create a transaction record.
TransactionEntry *transaction = new TransactionEntry(gConfig.getStr("SIP.Proxy.SMS").c_str(),mobileID,LCH);
gTransactionTable.add(transaction);
LOG(DEBUG) << "MOSMS: transaction: " << *transaction;
// See GSM 04.11 Arrow Diagram A5 for the transaction
// Step 1 MS->Network CP-DATA containing RP-DATA
// Step 2 Network->MS CP-ACK
// Step 3 Network->MS CP-DATA containing RP-ACK
// Step 4 MS->Network CP-ACK
// LAPDm operation, from GSM 04.11, Annex F:
// """
// Case A: Mobile originating short message transfer, no parallel call:
// The mobile station side will initiate SAPI 3 establishment by a SABM command
// on the DCCH after the cipher mode has been set. If no hand over occurs, the
// SAPI 3 link will stay up until the last CP-ACK is received by the MSC, and
// the clearing procedure is invoked.
// """
// FIXME: check provisioning
if (gConfig.getNum("GSM.Authentication")||gConfig.getNum("GSM.Encryption")) {
AuthenticationParameters authParams(mobileID);
registerIMSI(authParams, LCH);
authenticate(authParams, LCH);
}
// Let the phone know we're going ahead with the transaction.
if (LCH->isDecrypting()) {
LOG(INFO) << "Decryption ACTIVE for:" << mobileID << " CMServiceAccept NOT sent, because CipherModeCommand implies it.";
}
else {
LOG(INFO) << "Decryption NOT active for: " << mobileID << " Sending CMServiceAccept";
LCH->send(GSM::L3CMServiceAccept());
}
// Wait for SAP3 to connect.
// The first read on SAP3 is the ESTABLISH primitive.
delete getFrameSMS(LCH,GSM::ESTABLISH);
// Step 1
// Now get the first message.
// Should be CP-DATA, containing RP-DATA.
GSM::L3Frame *CM = getFrameSMS(LCH);
LOG(DEBUG) << "data from MS " << *CM;
if (CM->MTI()!=CPMessage::DATA) {
LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI();
delete CM;
throw UnexpectedMessage();
}
unsigned L3TI = CM->TI() | 0x08;
transaction->L3TI(L3TI);
// Step 2
// Respond with CP-ACK.
// This just means that we got the message.
LOG(INFO) << "sending CPAck";
LCH->send(CPAck(L3TI),3);
// Parse the message in CM and process RP part.
// This is where we actually parse the message and send it out.
// FIXME -- We need to set the message ref correctly,
// even if the parsing fails.
// The compiler gives a warning here. Let it. It will remind someone to fix it.
unsigned ref;
bool success = false;
try {
CPData data;
data.parse(*CM);
LOG(INFO) << "CPData " << data;
// Transfer out the RPDU -> TPDU -> delivery.
ref = data.RPDU().reference();
// This handler invokes higher-layer parsers, too.
success = handleRPDU(transaction,data.RPDU());
}
catch (SMSReadError) {
LOG(WARNING) << "SMS parsing failed (above L3)";
// Cause 95, "semantically incorrect message".
LCH->send(CPData(L3TI,RPError(95,ref)),3);
delete CM;
throw UnexpectedMessage();
}
catch (GSM::L3ReadError) {
LOG(WARNING) << "SMS parsing failed (in L3)";
//.........这里部分代码省略.........
示例12: assert
void Control::PagingResponseHandler(const L3PagingResponse* resp, LogicalChannel* DCCH)
{
assert(resp);
assert(DCCH);
LOG(INFO) << *resp;
// If we got a TMSI, find the IMSI.
L3MobileIdentity mobileID = resp->mobileIdentity();
if (mobileID.type()==TMSIType) {
const char *IMSI = gTMSITable.IMSI(mobileID.TMSI());
if (IMSI) mobileID = L3MobileIdentity(IMSI);
else {
// Don't try too hard to resolve.
// The handset is supposed to respond with the same ID type as in the request.
LOG(NOTICE) << "Paging Reponse with non-valid TMSI";
// Cause 0x60 "Invalid mandatory information"
DCCH->send(L3ChannelRelease(0x60));
return;
}
}
// Delete the Mobile ID from the paging list to free up CCCH bandwidth.
// ... if it was not deleted by a timer already ...
gBTS.pager().removeID(mobileID);
// Find the transction table entry that was created when the phone was paged.
// We have to look up by mobile ID since the paging entry may have been
// erased before this handler was called. That's too bad.
// HACK -- We also flush stray transactions until we find what we
// are looking for.
TransactionEntry transaction;
while (true) {
if (!gTransactionTable.find(mobileID,transaction)) {
LOG(WARN) << "Paging Reponse with no transaction record for " << mobileID;
// Cause 0x41 means "call already cleared".
DCCH->send(L3ChannelRelease(0x41));
return;
}
// We are looking for a mobile-terminated transaction.
// The transaction controller will take it from here.
switch (transaction.service().type()) {
case L3CMServiceType::MobileTerminatedCall:
MTCStarter(transaction, DCCH, mobileID);
return;
case L3CMServiceType::TestCall:
TestCall(transaction, DCCH);
return;
case L3CMServiceType::MobileTerminatedShortMessage:
MTSMSController(transaction, DCCH);
return;
default:
// Flush stray MOC entries.
// There should not be any, but...
LOG(WARN) << "flushing stray " << transaction.service().type() << " transaction entry";
gTransactionTable.remove(transaction.ID());
continue;
}
}
// The transaction may or may not be cleared,
// depending on the assignment type.
}
示例13: LOG
bool SIPInterface::checkInvite( osip_message_t * msg )
{
LOG(DEBUG);
// Is there even a method?
const char *method = msg->sip_method;
if (!method) return false;
// Check for INVITE or MESSAGE methods.
GSM::ChannelType requiredChannel;
bool channelAvailable = false;
bool shouldPage = true;
GSM::L3CMServiceType serviceType;
if (strcmp(method,"INVITE") == 0) {
// INVITE is for MTC.
// Set the required channel type to match the assignment style.
if (gConfig.defines("GSM.VEA")) {
// Very early assignment.
requiredChannel = GSM::TCHFType;
channelAvailable = gBTS.TCHAvailable();
} else {
// Early assignment
requiredChannel = GSM::SDCCHType;
channelAvailable = gBTS.SDCCHAvailable() && gBTS.TCHAvailable();
}
serviceType = L3CMServiceType::MobileTerminatedCall;
}
else if (strcmp(method,"MESSAGE") == 0) {
// MESSAGE is for MTSMS or USSD
if ( strcmp(gConfig.getStr("USSD.SIP.user"), msg->from->url->username)==0
&& strcmp(gConfig.getStr("USSD.SIP.domain"), msg->from->url->host)==0)
{
LOG(INFO) << "received MESSAGE is USSD from: "
<< msg->from->url->username << "@" << msg->from->url->host;
requiredChannel = GSM::SDCCHType;
// TODO:: Understand how to behave when we need to page?
channelAvailable = true; //gBTS.SDCCHAvailable();
serviceType = L3CMServiceType::SupplementaryService;
}
else
{
LOG(INFO) << "received MESSAGE is SMS from: "
<< msg->from->url->username << "@" << msg->from->url->host;
requiredChannel = GSM::SDCCHType;
channelAvailable = gBTS.SDCCHAvailable();
serviceType = L3CMServiceType::MobileTerminatedShortMessage;
}
}
else {
// We must not handle this method.
LOG(DEBUG) << "non-initiating SIP method " << method;
return false;
}
// Check gBTS for channel availability.
if (!channelAvailable) {
// FIXME -- Send 503 "Service Unavailable" response on SIP interface.
LOG(NOTICE) << "MTC CONGESTION, no " << requiredChannel << " availble for assignment";
return false;
}
LOG(INFO) << "set up MTC paging for channel=" << requiredChannel;
// Get call_id from invite message.
if (!msg->call_id) {
// FIXME -- Send appropriate error on SIP interface.
LOG(WARN) << "Incoming INVITE/MESSAGE with no call ID";
return false;
}
// Don't free call_id_num. It points into msg->call_id.
const char * call_id_num = osip_call_id_get_number(msg->call_id);
// Get request username (IMSI) from invite.
// Form of the name is IMSI<digits>, and it should always be 19 char.
const char * IMSI = msg->req_uri->username;
LOG(INFO) << msg->sip_method << " to "<< IMSI;
// IMSIs are 14 or 15 char + "IMSI" prefix
unsigned namelen = strlen(IMSI);
if ((namelen>19)||(namelen<18)) {
LOG(WARN) << "INVITE/MESSAGE with malformed username \"" << IMSI << "\"";
return false;
}
// Skip first 4 char "IMSI".
IMSI+=4;
// Make the mobile id we need for transaction and paging entries.
L3MobileIdentity mobile_id(IMSI);
// Check SIP map. Repeated entry? Page again.
// Skip this for USSD.
if ( mSIPMap.map().readNoBlock(call_id_num) != NULL) {
TransactionEntry transaction;
if (!gTransactionTable.find(mobile_id,transaction)) {
// FIXME -- Send "call leg non-existent" response on SIP interface.
LOG(WARN) << "repeated INVITE/MESSAGE with no transaction record";
// Delete the bogus FIFO.
mSIPMap.remove(call_id_num);
return false;
}
LOG(INFO) << "repeated SIP INVITE/MESSAGE, repaging for transaction " << transaction;
gBTS.pager().addID(mobile_id,requiredChannel,transaction);
//.........这里部分代码省略.........
示例14: assert
/**
This function starts MOC on the SDCCH to the point of TCH assignment.
@param req The CM Service Request that started all of this.
@param LCH The logical used to initiate call setup.
*/
void Control::MOCStarter(const GSM::L3CMServiceRequest* req, GSM::LogicalChannel *LCH)
{
assert(LCH);
assert(req);
LOG(INFO) << *req;
// Determine if very early assignment already happened.
bool veryEarly = (LCH->type()==GSM::FACCHType);
// If we got a TMSI, find the IMSI.
// Note that this is a copy, not a reference.
GSM::L3MobileIdentity mobileID = req->mobileID();
resolveIMSI(mobileID,LCH);
// FIXME -- At this point, verify the that subscriber has access to this service.
// If the subscriber isn't authorized, send a CM Service Reject with
// cause code, 0x41, "requested service option not subscribed",
// followed by a Channel Release with cause code 0x6f, "unspecified".
// Otherwise, proceed to the next section of code.
// For now, we are assuming that the phone won't make a call if it didn't
// get registered.
// Allocate a TCH for the call, if we don't have it already.
GSM::TCHFACCHLogicalChannel *TCH = NULL;
if (!veryEarly) {
TCH = allocateTCH(dynamic_cast<GSM::LogicalChannel*>(LCH));
// It's OK to just return on failure; allocateTCH cleaned up already,
// and the SIP side and transaction record don't exist yet.
if (TCH==NULL) return;
}
// Let the phone know we're going ahead with the transaction.
LOG(INFO) << "sending CMServiceAccept";
LCH->send(GSM::L3CMServiceAccept());
// Get the Setup message.
// GSM 04.08 5.2.1.2
GSM::L3Message* msg_setup = getMessage(LCH);
const GSM::L3Setup *setup = dynamic_cast<const GSM::L3Setup*>(msg_setup);
if (!setup) {
if (msg_setup) {
LOG(WARNING) << "Unexpected message " << *msg_setup;
delete msg_setup;
}
throw UnexpectedMessage();
}
LOG(INFO) << *setup;
// Pull out the L3 short transaction information now.
// See GSM 04.07 11.2.3.1.3.
// Set the high bit, since this TI came from the MS.
unsigned L3TI = setup->TI() | 0x08;
if (!setup->haveCalledPartyBCDNumber()) {
// FIXME -- This is quick-and-dirty, not following GSM 04.08 5.
LOG(WARNING) << "MOC setup with no number";
// Cause 0x60 "Invalid mandatory information"
LCH->send(GSM::L3ReleaseComplete(L3TI,0x60));
LCH->send(GSM::L3ChannelRelease());
// The SIP side and transaction record don't exist yet.
// So we're done.
delete msg_setup;
return;
}
LOG(DEBUG) << "SIP start engine";
// Get the users sip_uri by pulling out the IMSI.
//const char *IMSI = mobileID.digits();
// Pull out Number user is trying to call and use as the sip_uri.
const char *bcdDigits = setup->calledPartyBCDNumber().digits();
// Create a transaction table entry so the TCH controller knows what to do later.
// The transaction on the TCH will be a continuation of this one.
TransactionEntry *transaction = new TransactionEntry(
gConfig.getStr("SIP.Proxy.Speech").c_str(),
mobileID,
LCH,
req->serviceType(),
L3TI,
setup->calledPartyBCDNumber());
LOG(DEBUG) << "transaction: " << *transaction;
gTransactionTable.add(transaction);
// At this point, we have enough information start the SIP call setup.
// We also have a SIP side and a transaction that will need to be
// cleaned up on abort or clearing.
// Now start a call by contacting asterisk.
// Engine methods will return their current state.
// The remote party will start ringing soon.
LOG(DEBUG) << "starting SIP (INVITE) Calling "<<bcdDigits;
unsigned basePort = allocateRTPPorts();
transaction->MOCSendINVITE(bcdDigits,gConfig.getStr("SIP.Local.IP").c_str(),basePort,SIP::RTPGSM610);
LOG(DEBUG) << "transaction: " << *transaction;
// Once we can start SIP call setup, send Call Proceeding.
//.........这里部分代码省略.........
示例15: LOG
void Control::MTCController(TransactionEntry& transaction, TCHFACCHLogicalChannel* TCH)
{
// Early Assignment Mobile Terminated Call.
// Transaction table in 04.08 7.3.3 figure 7.10a
LOG(DEBUG) << "transaction: " << transaction;
unsigned L3TI = transaction.TIValue();
assert(transaction.TIFlag()==1);
assert(TCH);
// Get the alerting message.
LOG(INFO) << "waiting for GSM Alerting and Connect";
while (transaction.Q931State()!=TransactionEntry::Active) {
if (updateGSMSignalling(transaction,TCH,1000)) return;
if (transaction.Q931State()==TransactionEntry::Active) break;
if (transaction.Q931State()==TransactionEntry::CallReceived) {
LOG(DEBUG) << "sending SIP Ringing";
transaction.SIP().MTCSendRinging();
}
// Check for SIP cancel, too.
if (transaction.SIP().MTCWaitForACK()==SIP::Fail) {
return abortCall(transaction,TCH,L3Cause(0x7F));
}
}
gTransactionTable.update(transaction);
LOG(INFO) << "allocating port and sending SIP OKAY";
unsigned RTPPorts = allocateRTPPorts();
SIPState state = transaction.SIP().MTCSendOK(RTPPorts,SIP::RTPGSM610);
while (state!=SIP::Active) {
LOG(DEBUG) << "wait for SIP OKAY-ACK";
if (updateGSMSignalling(transaction,TCH)) return;
state = transaction.SIP().MTCWaitForACK();
LOG(DEBUG) << "SIP call state "<< state;
switch (state) {
case SIP::Active:
break;
case SIP::Fail:
return abortCall(transaction,TCH,L3Cause(0x7F));
case SIP::Timeout:
state = transaction.SIP().MTCSendOK(RTPPorts,SIP::RTPGSM610);
break;
case SIP::Connecting:
break;
default:
LOG(NOTICE) << "SIP unexpected state " << state;
break;
}
}
transaction.SIP().MTCInitRTP();
gTransactionTable.update(transaction);
// Send Connect Ack to make it all official.
LOG(DEBUG) << "MTC send GSM Connect Acknowledge";
TCH->send(L3ConnectAcknowledge(0,L3TI));
// At this point, everything is ready to run for the call.
// The radio link should have been cleared with the call.
gTransactionTable.update(transaction);
callManagementLoop(transaction,TCH);
}