Logo Search packages:      
Sourcecode: capisuite version File versions  Download package

void Capi::readMessage ( void   )  throw (CapiMsgError, CapiError, CapiWrongState, CapiExternalError) [private]

read Message from CAPI and process it accordingly

This method handles all incoming messages. It is called by run() and will call special handler methods of Connection mainly. Prints messages for debug purposes.

Exceptions:
CapiMsgError directly raised when CAPI_GET_MESSAGE or LISTEN_REQ fails, may also be raised by all called *_ind, *_conf handlers
CapiError directly raised when general error occurs (unknown call references, unknown message, ... received)
CapiWrongState may be raised by all called *_ind(), *_conf() handlers
CapiExternalError may be raised by some called *_ind(), *_conf() handlers

Definition at line 433 of file capi.cpp.

References application, applId, ApplicationInterface::callWaiting(), connections, DDIBaseLength, DDILength, DDIStopNumbers, debug, debug_level, describeParamInfo(), error, info_resp(), and prefix().

Referenced by run().

{
      _cmsg nachricht;
      unsigned info=CAPI_GET_CMSG(&nachricht, applId);  // don't use capi20_get_message here as CAPI_GET_CMSG does disassembling of message parameters for us
      switch (info) {
            case CapiNoError:           //----- a message has been read -----
                        switch (nachricht.Subcommand) {
                        case CAPI_CONF:    // confirmation
                              switch (nachricht.Command) {
                                    case CAPI_ALERT: {
                                          _cdword plci=ALERT_CONF_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<ALERT_CONF, PLCI: 0x" << hex << ALERT_CONF_PLCI(&nachricht) << ", Info 0x" << ALERT_CONF_INFO(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in ALERT_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->alert_conf(nachricht);
                                    } break;

                                    case CAPI_CONNECT: {
                                          _cdword pseudoPLCI=0xFACE0000 | nachricht.Messagenumber; // pseudo PLCI as set by connect_req
                                          _cdword plci=CONNECT_CONF_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_CONF, PLCI: 0x" << hex << CONNECT_CONF_PLCI(&nachricht) << ", Info 0x" << CONNECT_CONF_INFO(&nachricht) << endl;
                                          if (connections.count(pseudoPLCI)==0)
                                                throw(CapiError("MessageNumber unknown in CONNECT_CONF","Capi::readMessage()"));
                                          else {
                                                connections[plci]=connections[pseudoPLCI];
                                                connections.erase(pseudoPLCI);
                                                connections[plci]->connect_conf(nachricht);
                                          }
                                    } break;

                                    case CAPI_CONNECT_B3: {
                                          _cdword plci=CONNECT_B3_CONF_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_B3_CONF, NCCI: 0x" << hex << CONNECT_B3_CONF_NCCI(&nachricht) << ", Info 0x" << CONNECT_B3_CONF_INFO(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in CONNECT_B3_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->connect_b3_conf(nachricht);
                                    } break;

                                    case CAPI_SELECT_B_PROTOCOL: {
                                          _cdword plci=SELECT_B_PROTOCOL_CONF_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<SELECT_B_PROTOCOL_CONF, PLCI: 0x" << hex << SELECT_B_PROTOCOL_CONF_PLCI(&nachricht) << ", Info 0x" << SELECT_B_PROTOCOL_CONF_INFO(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in SELECT_B_PROTOCOL_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->select_b_protocol_conf(nachricht);
                                    } break;

                                    case CAPI_LISTEN:
                                          if (debug_level >= 2)
                                                debug << prefix() << "<LISTEN_CONF Controller 0x" << hex << LISTEN_CONF_CONTROLLER(&nachricht) << " Info 0x" << LISTEN_CONF_INFO(&nachricht) << endl;

                                          if (LISTEN_CONF_INFO(&nachricht)!=0)
                                                throw CapiMsgError(LISTEN_CONF_INFO(&nachricht),"LISTEN_REQ was unsuccesful "+Capi::describeParamInfo(LISTEN_CONF_INFO(&nachricht)),"Capi::readMessage()");

                                    break;

                                    case CAPI_DATA_B3: {
                                          _cdword plci=DATA_B3_CONF_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 3)
                                                debug << prefix() << "<DATA_B3_CONF, NCCI 0x" << hex << DATA_B3_CONF_NCCI(&nachricht) << dec << ", DataHandle " << DATA_B3_CONF_DATAHANDLE(&nachricht)
                                                      << ", Info 0x" << DATA_B3_CONF_INFO(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DATA_B3_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->data_b3_conf(nachricht);
                                    } break;


                                    case CAPI_FACILITY:
                                          switch (FACILITY_CONF_FACILITYSELECTOR(&nachricht)) {
                                                case 1: { // DTMF
                                                      _cdword plci=FACILITY_CONF_PLCI(&nachricht) & 0xFFFF; // this *should* be PLCI but who knows, so let's mask it to be sure
                                                      if (debug_level >= 2)
                                                            debug << prefix() << "<FACILITY_CONF PLCI 0x" << hex << FACILITY_CONF_PLCI(&nachricht) << " Info 0x" << FACILITY_CONF_INFO(&nachricht)
                                                                     << " FacilitySelector 0x" << FACILITY_CONF_FACILITYSELECTOR(&nachricht) << endl;

                                                      if (connections.count(plci)==0)
                                                            throw(CapiError("PLCI unknown in FACILITY_CONF","Capi::readMessage()"));
                                                      else
                                                            connections[plci]->facility_conf_DTMF(nachricht);
                                                } break;

                                                default:
                                                      error << prefix() << "WARNING: PLCI " << hex << FACILITY_CONF_PLCI(&nachricht) << ": unsupported facility selector " << FACILITY_CONF_FACILITYSELECTOR(&nachricht) << " in FACILITY_CONF" << endl;
                                                break;
                                          }
                                    break;

                                    case CAPI_DISCONNECT_B3: {
                                          _cdword plci=DISCONNECT_B3_CONF_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 2)
                                                debug << prefix() << "<DISCONNECT_B3_CONF NCCI 0x" << hex << DISCONNECT_B3_CONF_NCCI(&nachricht) << " Info 0x" << DISCONNECT_B3_CONF_INFO(&nachricht)
                                                        << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DISCONNECT_B3_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->disconnect_b3_conf(nachricht);
                                    } break;

                                    case CAPI_DISCONNECT: { // TODO: perhaps we should handle NCPI telling us fax infos here??
                                          _cdword plci=DISCONNECT_CONF_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<DISCONNECT_CONF PLCI 0x" << hex << DISCONNECT_CONF_PLCI(&nachricht) << " Info 0x" << DISCONNECT_CONF_INFO(&nachricht)
                                                         << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DISCONNECT_CONF","Capi::readMessage()"));
                                          else
                                                connections[plci]->disconnect_conf(nachricht);
                                    } break;
                              }
                              break;

                        case CAPI_IND:     // indication
                                    switch (nachricht.Command) {
                                    case CAPI_CONNECT: { // call for us
                                          _cdword plci=CONNECT_IND_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_IND PLCI 0x" << hex << plci << " CIP 0x" << CONNECT_IND_CIPVALUE(&nachricht) << endl;

                                          if (connections.count(plci)>0)
                                                throw(CapiError("PLCI used twice from CAPI in CONNECT_IND","Capi::readMessage()"));
                                          else {
                                                Connection *c=new Connection(nachricht,this,DDILength,DDIBaseLength,DDIStopNumbers);
                                                connections[plci]=c;
                                                if (!DDILength) // if we have PtP then wait until DDI is complete
                                                      application->callWaiting(c);
                                          }
                                    } break;

                                    case CAPI_CONNECT_ACTIVE: {
                                          _cdword plci=CONNECT_IND_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_ACTIVE_IND PLCI 0x" << hex << plci << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in CONNECT_ACTIVE_IND","Capi::readMessage()"));
                                          else
                                                connections[plci]->connect_active_ind(nachricht);
                                    } break;

                                    case CAPI_CONNECT_B3: {
                                          _cdword plci=CONNECT_B3_IND_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_B3_IND NCCI 0x" << hex << CONNECT_B3_IND_NCCI(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in CONNECT_B3_IND","Capi::readMessage()"));
                                          else
                                                connections[plci]->connect_b3_ind(nachricht);
                                    } break;

                                    case CAPI_CONNECT_B3_ACTIVE: {
                                          _cdword plci=CONNECT_B3_ACTIVE_IND_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 2)
                                                debug << prefix() << "<CONNECT_B3_ACTIVE_IND NCCI 0x" << hex << CONNECT_B3_ACTIVE_IND_NCCI(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in CONNECT_B3_ACTIVE_IND","Capi::readMessage()"));
                                          else
                                                connections[plci]->connect_b3_active_ind(nachricht);
                                    } break;

                                    case CAPI_DISCONNECT: {  // call gone, we'll confirm to CAPI
                                          _cdword plci=DISCONNECT_IND_PLCI(&nachricht);
                                          if (debug_level >= 2)
                                                debug << prefix() << "<DISCONNECT_IND PLCI 0x" << hex << plci << " Reason 0x" << DISCONNECT_IND_REASON(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DISCONNECT_IND","Capi::readMessage()"));
                                          else {
                                                connections[plci]->disconnect_ind(nachricht);
                                          }
                                    } break;

                                    case CAPI_DISCONNECT_B3: {
                                          _cdword plci=DISCONNECT_B3_IND_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 2)
                                                debug << prefix() << "<DISCONNECT_B3_IND NCCI 0x" << hex << DISCONNECT_B3_IND_NCCI(&nachricht) << " Reason 0x" << DISCONNECT_B3_IND_REASON_B3(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DISCONNECT_B3_IND","Capi::readMessage()"));
                                          else
                                                connections[plci]->disconnect_b3_ind(nachricht);
                                    } break;

                                    case CAPI_DATA_B3: {
                                          _cdword plci=DATA_B3_IND_NCCI(&nachricht) & 0xFFFF; // PLCI is coded in the least 2 octets of NCCI
                                          if (debug_level >= 3)
                                                debug << prefix() << "<DATA_B3_IND: NCCI 0x" << hex << DATA_B3_IND_NCCI(&nachricht) << dec << ", DataLength " << DATA_B3_IND_DATALENGTH(&nachricht)
                                                            << hex << ", DataHandle 0x" << DATA_B3_IND_DATAHANDLE(&nachricht) << ", Flags 0x" << DATA_B3_IND_FLAGS(&nachricht) << endl;
                                          if (connections.count(plci)==0)
                                                throw(CapiError("PLCI unknown in DATA_B3_IND","Capi::readMessage()"));
                                          else
                                                connections[plci]->data_b3_ind(nachricht);
                                    } break;

                                    case CAPI_FACILITY:
                                          switch (FACILITY_IND_FACILITYSELECTOR(&nachricht)) {
                                                case 1: { // DTMF
                                                      _cdword plci=FACILITY_IND_PLCI(&nachricht) & 0xFFFF; // we *should* get PLCI but just to be sure we mask the NCCI-part out...
                                                      if (debug_level >= 2)
                                                            debug << prefix() << "<FACILITY_IND: PLCI 0x" << hex << FACILITY_IND_PLCI(&nachricht) << ", FacilitySelector 0x" << FACILITY_IND_FACILITYSELECTOR(&nachricht) << endl;

                                                      if (connections.count(plci)==0)
                                                            throw(CapiError("PLCI unknown in FACILITY_IND","Capi::readMessage()"));
                                                      else
                                                            connections[plci]->facility_ind_DTMF(nachricht);
                                                } break;

                                                default:
                                                      error << prefix() << "WARNING: PLCI " << hex << (FACILITY_IND_PLCI(&nachricht) & 0xFFFF) << ": Unsupported facility selector " << FACILITY_IND_FACILITYSELECTOR(&nachricht) << " in FACILITY_IND" << endl;
                                                break;
                                          }
                                    break;

                                    case CAPI_INFO:
                                          switch (INFO_IND_INFONUMBER(&nachricht)) {
                                                case 0x8001: { // ALERTING
                                                      _cdword plci=INFO_IND_PLCI(&nachricht);
                                                      if (debug_level >= 2)
                                                            debug << prefix() << "<INFO_IND: PLCI 0x" << hex << plci << ", InfoNumber ALERTING " << endl;
                                                      if (connections.count(plci)==0)
                                                            throw(CapiError("PLCI unknown in INFO_IND","Capi::readMessage()"));
                                                      else
                                                            connections[plci]->info_ind_alerting(nachricht);
                                                } break;

                                                case 0x70: { // Called Party Number
                                                      _cdword plci=INFO_IND_PLCI(&nachricht);
                                                      if (debug_level >= 2)
                                                            debug << prefix() << "<INFO_IND: PLCI 0x" << hex << plci << ", InfoNumber CalledPartyNr " << endl;
                                                      
                                                      bool nrComplete;
                                                      if (connections.count(plci)==0)
                                                            throw(CapiError("PLCI unknown in INFO_IND","Capi::readMessage()"));
                                                      else {
                                                            nrComplete=connections[plci]->info_ind_called_party_nr(nachricht);
                                                            if (nrComplete && DDILength)
                                                                  application->callWaiting(connections[plci]);
                                                      }
                                                } break;

                                                default:
                                                      if (debug_level >= 2)
                                                            debug << prefix() << "<INFO_IND: Controller/PLCI 0x" << hex << INFO_IND_PLCI(&nachricht) << ", InfoNumber " << INFO_IND_INFONUMBER(&nachricht) << " (ignoring)" << endl;
                                                      info_resp(nachricht.Messagenumber,INFO_IND_PLCI(&nachricht));
                                                break;
                                          }
                                    break;


                                    default:
                                          stringstream err;
                                          err << "Indication 0x" << hex << static_cast<int>(nachricht.Command) << " not handled" << ends;
                                                throw (CapiError(err.str(),"Capi::readMessage()"));
                                    break;
                                    }
                        break;

                              default:       //----- neither indication nor confirmation ???? -----
                              throw(CapiError("Unknown subcommand in function Handle_CAPI_Msg","Capi::readMessage()"));
                        break;
                        }
            break;
            case CapiReceiveQueueEmpty:
                        throw (CapiError("readMessage called but no message available?","Capi::readMessage()"));
            break;

            default:
                        throw (CapiMsgError(info,"Error while CAPI_GET_CMSG: "+Capi::describeParamInfo(info),"Capi::readMessage()"));
            break;
      }
}


Generated by  Doxygen 1.6.0   Back to index