Q931.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   FileName:      Q931.c
00004 
00005   Contents:      Implementation of Q.931 stack main interface functions. 
00006                                 See q931.h for description. 
00007 
00008   License/Copyright:
00009 
00010   Copyright (c) 2007, Jan Vidar Berger, Case Labs, Ltd. All rights reserved.
00011   email:janvb@caselaboratories.com  
00012 
00013   Redistribution and use in source and binary forms, with or without 
00014   modification, are permitted provided that the following conditions are 
00015   met:
00016 
00017         * Redistributions of source code must retain the above copyright notice, 
00018           this list of conditions and the following disclaimer.
00019         * Redistributions in binary form must reproduce the above copyright notice, 
00020           this list of conditions and the following disclaimer in the documentation 
00021           and/or other materials provided with the distribution.
00022         * Neither the name of the Case Labs, Ltd nor the names of its contributors 
00023           may be used to endorse or promote products derived from this software 
00024           without specific prior written permission.
00025 
00026   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00027   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00029   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
00030   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00031   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00032   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00033   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00034   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00035   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
00036   POSSIBILITY OF SUCH DAMAGE.
00037 *****************************************************************************/
00038 
00039 #define Q931PRIVATE
00040 
00041 #include "Q921.h"
00042 #include "Q931.h"
00043 
00044 #if defined(HAVE_DIALECT_5ESS)
00045 #include "5ESS.h"
00046 #endif
00047 
00048 #if defined(HAVE_DIALECT_DSS1)
00049 #include "DSS1.h"
00050 #endif
00051 
00052 /*****************************************************************************
00053 
00054   Dialect function pointers tables.
00055 
00056   The following function pointer arrays define pack/unpack functions and 
00057   processing furnctions for the different Q.931 based dialects.
00058 
00059   The arrays are initialized with pointers to dummy functions and later
00060   overrided with pointers to actual functions as new dialects are added.
00061 
00062   The initial Q.931 will as an example define 2 dialects as it treats User
00063   and Network mode as separate ISDN dialects.
00064 
00065   The API messages Q931AddProc, Q931AddMes, Q931AddIE are used to initialize
00066   these table entries during system inititialization of a stack.
00067 
00068 *****************************************************************************/
00069 
00070 /*****************************************************************************
00071 
00072   Core system tables and variables.
00073 
00074 *****************************************************************************/
00075 
00076 L3INT Q931L4HeaderSpace = {0};  /* header space to be ignoder/inserted */
00077                                 /* at head of each message. */
00078 
00079 L3INT Q931L2HeaderSpace = {4};  /* Q921 header space, sapi, tei etc */
00080 
00081 /*****************************************************************************
00082 
00083   Main interface callback functions. 
00084 
00085 *****************************************************************************/
00086 
00087 L3ULONG (*Q931GetTimeProc) (void) = NULL;       /* callback for func reading time in ms */
00088 
00089 /*****************************************************************************
00090 
00091   Function:      Q931SetL4HeaderSpace
00092 
00093   Description:  Set the # of bytes to be inserted/ignored at the head of
00094                 each message. Q931 will issue a message with space for header
00095                 and the user will use this to fill in whatever header info
00096                 is required to support the architecture used.
00097 
00098 *****************************************************************************/
00099 void Q931SetL4HeaderSpace(L3INT space)
00100 {
00101         Q931L4HeaderSpace = space;
00102 }
00103 
00104 /*****************************************************************************
00105 
00106   Function:      Q931SetL2HeaderSpace
00107 
00108   Description:  Set the # of bytes to be inserted/ignored at the head of
00109                 each message. Q931 will issue a message with space for header
00110                 and the user will use this to fill in whatever header info
00111                 is required to support the architecture used.
00112 
00113 *****************************************************************************/
00114 void Q931SetL2HeaderSpace(L3INT space)
00115 {
00116         Q931L2HeaderSpace = space;
00117 }
00118 
00119 /*****************************************************************************
00120 
00121   Function:      Q931ProcDummy
00122 
00123   Description:  Dummy function for message processing.
00124 
00125 *****************************************************************************/
00126 L3INT Q931ProcDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b,L3INT c)
00127 {
00128         return Q931E_INTERNAL;
00129 }
00130 
00131 /*****************************************************************************
00132 
00133   Function:      Q931UmesDummy
00134 
00135   Description:  Dummy function for message processing
00136 
00137 *****************************************************************************/
00138 L3INT Q931UmesDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size)
00139 {
00140         return Q931E_UNKNOWN_MESSAGE;
00141 }
00142 
00143 /*****************************************************************************
00144 
00145   Function:      Q931UieDummy
00146 
00147   Description:  Dummy function for message processing
00148 
00149 *****************************************************************************/
00150 L3INT Q931UieDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR * IBuf, L3UCHAR * OBuf, L3INT *IOff, L3INT *OOff)
00151 {
00152         return Q931E_UNKNOWN_IE;
00153 }
00154 
00155 /*****************************************************************************
00156 
00157   Function:      Q931PmesDummy
00158 
00159   Description:  Dummy function for message processing
00160 
00161 *****************************************************************************/
00162 L3INT Q931PmesDummy(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
00163 {
00164         return Q931E_UNKNOWN_MESSAGE;
00165 }
00166 
00167 /*****************************************************************************
00168 
00169   Function:      Q931PieDummy
00170 
00171   Description:  Dummy function for message processing
00172 
00173 *****************************************************************************/
00174 L3INT Q931PieDummy(Q931_TrunkInfo_t *pTrunk,L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
00175 {
00176         return Q931E_UNKNOWN_IE;
00177 }
00178 
00179 /*****************************************************************************
00180 
00181   Function:      Q931TxDummy
00182 
00183   Description:  Dummy function for message processing
00184 
00185 *****************************************************************************/
00186 L3INT Q931TxDummy(Q931_TrunkInfo_t *pTrunk, L3UCHAR * b, L3INT n)
00187 {
00188         return Q931E_MISSING_CB;
00189 }
00190 
00191 /*****************************************************************************
00192 
00193   Function:      Q931Initialize
00194 
00195   Description:  This function Initialize the stack. 
00196   
00197                 Will set up the trunk array, channel
00198                 arrays and initialize Q931 function arrays before it finally
00199                 set up EuroISDN processing with User as dialect 0 and 
00200                 Network as dialect 1.
00201 
00202   Note:          Initialization of other stacks should be inserted after
00203                 the initialization of EuroISDN.
00204 
00205 *****************************************************************************/
00210 void Q931Initialize(void)
00211 {
00212         /*
00213          * Initialize Q.931 dialect registry and register dialects
00214          */
00215         Q931DialectRegistryInit();
00216 
00217         /* Register Q.931 */
00218         Q931DialectRegister(Q931_Dialect_Q931, Q931_TE, Q931CreateTE);
00219         Q931DialectRegister(Q931_Dialect_Q931, Q931_NT, Q931CreateNT);
00220 
00221         /* Register DSS1 */
00222         Q931DialectRegister(Q931_Dialect_DSS1, Q931_TE, DSS1CreateTE);
00223         Q931DialectRegister(Q931_Dialect_DSS1, Q931_NT, DSS1CreateNT);
00224 
00225 #if 0
00226         /* Register 5ESS */
00227         Q931DialectRegister(Q931_Dialect_5ESS, Q931_TE, ATT5ESSCreateTE);
00228         Q931DialectRegister(Q931_Dialect_5ESS, Q931_NT, ATT5ESSCreateNT);
00229 #endif
00230 }
00231 
00237 void Q931TimerTick(Q931_TrunkInfo_t *pTrunk)
00238 {
00239         struct Q931_Call *call = NULL;
00240         L3ULONG now = 0;
00241         L3INT x;
00242 
00243         /* TODO: Loop through all active calls, check timers and call timout procs
00244          * if timers are expired.
00245          * Implement a function array so each dialect can deal with their own
00246          * timeouts.
00247          */
00248         now = Q931GetTime();
00249 
00250         for (x = 0; x < Q931MAXCALLPERTRUNK; x++) {
00251                 call = &pTrunk->call[x];
00252 
00253                 if (!call->InUse || !call->Timer || !call->TimerID)
00254                         continue;
00255 
00256                 if (call->Timer <= now) {
00257                         int id = call->TimerID; /* Q931CallStopTimer resets the TimerID */
00258 
00259                         /* Stop Timer */
00260                         Q931CallStopTimer(call, id);
00261 
00262                         /* Increment expire counter */
00263                         Q931CallIncrementTimerExpireCount(call);
00264 
00265                         /* Invoke dialect timeout callback */
00266                         Q931Timeout(pTrunk, call, id);
00267 
00268                         /*
00269                          * Release CRV if call has gone back to Null state after timer event
00270                          * and send an event to L4 before doing so
00271                          */
00272                         if (!Q931CallIsGlobal(call)) {
00273                                 if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00274                                         /* Send event, so L4 can clean up */
00275                                         struct Q931_CallEvent event;
00276 
00277                                         event.id    = Q931_EVENT_RELEASE_CRV;
00278                                         event.type  = Q931_EVENT_TYPE_CRV;
00279                                         event.error = 0;
00280 
00281                                         Q931CallSendEvent(call, &event);
00282 
00283                                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00284 
00285                                         /* Release call */
00286                                         Q931CallRelease(call);
00287                                 }
00288                         }
00289                 }
00290         }
00291 }
00292 
00293 /*****************************************************************************
00294 
00295   Function:      Q931Rx23
00296 
00297   Description:  Receive message from layer 2 (LAPD). Receiving a message 
00298                                 is always done in 2 steps. First the message must be 
00299                                 interpreted and translated to a static struct. Secondly
00300                                 the message is processed and responded to.
00301 
00302                                 The Q.931 message contains a static header that is 
00303                                 interpreted in this function. The rest is interpreted
00304                                 in a sub function according to mestype.
00305 
00306   Parameters:   pTrunk  [IN]    Ptr to trunk info.
00307                                 buf      [IN]   Ptr to buffer containing message.
00308                                 Size    [IN]    Size of message.
00309 
00310   Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
00311                                 see q931errors.h for details.
00312 
00313 *****************************************************************************/
00314 L3INT Q931Rx23(Q931_TrunkInfo_t *pTrunk, L3INT ind, L3UCHAR tei, L3UCHAR * buf, L3INT Size)
00315 {
00316         L3UCHAR *Mes = NULL;
00317         L3INT RetCode = Q931E_NO_ERROR;
00318         Q931mes_Generic *m = (Q931mes_Generic *) pTrunk->L3Buf;
00319         struct Q931_Call *call = NULL;
00320         L3INT ISize;
00321         L3INT IOff = 0;
00322         L3INT L2HSize = Q931L2HeaderSpace;
00323 
00324         switch (ind) {
00325         case Q921_DL_UNIT_DATA:         /* DL-UNITDATA indication (UI frame, 3 byte header) */
00326                 L2HSize = 3;
00327 
00328         case Q921_DL_DATA:              /* DL-DATA indication (I frame, 4 byte header) */
00329                 /* Reset our decode buffer */
00330                 memset(pTrunk->L3Buf, 0, sizeof(pTrunk->L3Buf));
00331 
00332                 /* L2 Header Offset */
00333                 Mes = &buf[L2HSize];
00334 
00335                 /* Protocol Discriminator */
00336                 m->ProtDisc = Mes[IOff++];
00337 
00338                 /* CRV */
00339                 m->CRVFlag = (Mes[IOff + 1] >> 7) & 0x01;
00340                 m->CRV = Q931Uie_CRV(pTrunk, Mes, m->buf, &IOff, &ISize);
00341 
00342                 /* Message Type */
00343                 m->MesType = Mes[IOff++];
00344 
00345                 /* Store tei */
00346                 m->Tei = tei;
00347 
00348                 /* d'oh a little ugly but this saves us from:
00349                  *      a) doing Q.921 work in the lower levels (extracting the TEI ourselves)
00350                  *      b) adding a tei parameter to _all_ Proc functions
00351                  * TODO: a little ugly, merge into next codeblock
00352                  */
00353                 if (tei && m->CRV) {
00354                         /* Find the call using CRV */
00355                         call = Q931GetCallByCRV(pTrunk, m->CRV);
00356                         if (call && !call->Tei) {
00357                                 call->Tei = tei;
00358                         }
00359                 }
00360 
00361                 /* vvv new code start here */
00362                 if (m->CRV) {
00363                         /* Lookup call reference */
00364                         call = Q931GetCallByCRV(pTrunk, m->CRV);
00365                         if (!call) {
00366                                 /* oops, no call found */
00367                                 if(m->MesType == Q931mes_SETUP) {
00368                                         /* Setup message, create new call handle */
00369                                         call = Q931CallNewIncoming(pTrunk, m->CRV);
00370                                 } else {
00371                                         /* Not a setup message -> INVALID CRV */
00372                                         /* TODO: respond with proper RELEASE COMPLETE + cause combination */
00373                                         return Q931E_INVALID_CRV;
00374                                 }
00375 
00376                                 /* Still no call handle? */
00377                                 if (!call) {
00378                                         /* blah, failed to allocate new call -> Disconnect */
00379                                         Q931Disconnect(pTrunk, MSGF_FROM_L2, m->CRV, 42);
00380                                         return Q931E_INTERNAL;
00381                                 }
00382                         }
00383 
00384                         /* Diagnostic message */
00385                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Call is in state %d [%s]\n", Q931CallGetState(call), Q931CallGetStateName(call));
00386                 } else {
00387                         /* Global CRV ?? */
00388                         call = Q931GetGlobalCall(pTrunk);
00389 
00390                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Using global call for message\n");
00391                 }
00392                 /* ^^^ new code ends here */
00393 
00394                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Received message from Q.921 (ind %d, tei %d, size %d)\nMesType: %d, CRVFlag %d (%s), CRV %d (Dialect: %s)\n", ind, m->Tei, Size,
00395                                                  m->MesType, m->CRVFlag, m->CRVFlag ? "Terminator" : "Originator", m->CRV, Q931DialectGetName(pTrunk->Dialect));
00396 
00397                 RetCode = Q931Umes(pTrunk, m->MesType, Mes, (Q931mes_Generic *)pTrunk->L3Buf, IOff, Size - L2HSize);
00398                 if (RetCode >= Q931E_NO_ERROR) {
00399                         RetCode = Q931Proc(pTrunk, pTrunk->L3Buf, 2);
00400                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Q931Proc[%s][%d]() returned %d\n", Q931DialectGetName(pTrunk->Dialect), m->MesType, RetCode);
00401                 } else {
00402                         Q931Log(pTrunk, Q931_LOG_DEBUG, "Q931Umes[%s][%d]() returned %d\n", Q931DialectGetName(pTrunk->Dialect), m->MesType, RetCode);
00403                 }
00404 
00405                 /* Error handling for Umes() and Proc() */
00406                 if (RetCode < Q931E_NO_ERROR) {
00407                         /* Initialize response message */
00408 
00409                         /* TODO: Add Error codes for Mandatory IE missing and error */
00410                         switch (RetCode) {
00411                         case Q931E_MANDATORY_IE_MISSING:
00412                                 /* Send STATUS with cause 96 */
00413                                 RetCode = Q931StatusEnquiryResponse(pTrunk, buf, call, Q850_CAUSE_MANDATORY_IE_MISSING);
00414                                 break;
00415 
00416                         case Q931E_ILLEGAL_IE:                  /* ?? */
00417                                 /* Send STATUS with cause 96 */
00418                                 RetCode = Q931StatusEnquiryResponse(pTrunk, buf, call, Q850_CAUSE_IE_NONEXIST);
00419                                 break;
00420 
00421                         case Q931E_UNKNOWN_IE:
00422                                 /* Send STATUS with cause 100 */
00423                                 RetCode = Q931StatusEnquiryResponse(pTrunk, buf, call, Q850_CAUSE_INVALID_IE_CONTENTS);
00424                                 break;
00425 
00426                         case Q931E_UNEXPECTED_MESSAGE:
00427                         case Q931E_UNRECOGNIZED_MESSAGE:
00428                                 /* Ignore in State 0 */
00429                                 if ((Q931CallGetState(call) & 0xff) == Q931_U0)
00430                                         goto out;
00431 
00432                                 /* Ignore for RELEASE and RELEASE COMPLETE */
00433                                 if (m->MesType == Q931mes_RELEASE || m->MesType == Q931mes_RELEASE_COMPLETE)
00434                                         goto out;
00435 
00436                                 if (Q931TrunkGetStatusEnquiry(pTrunk)) {
00437                                         /* Send STATUS ENQUIRY */
00438                                         Q931InitMesGeneric(m);
00439                                         m->CRV     = Q931CallGetCRV(call);
00440                                         m->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00441                                         m->MesType = Q931mes_STATUS_ENQUIRY;
00442 
00443                                         /* TODO: check and / or fire up T322 */
00444                                         RetCode = Q931Tx32Data(pTrunk, 0, buf, m->Size);
00445                                 } else {
00446                                         /* Send STATUS with cause X */
00447                                         RetCode = Q931StatusEnquiryResponse(pTrunk, buf, call, 
00448                                                                                         (RetCode == Q931E_UNEXPECTED_MESSAGE) ? Q850_CAUSE_WRONG_MESSAGE : Q850_CAUSE_MESSAGE_TYPE_NONEXIST);
00449                                 }
00450                                 break;
00451 
00452                         default:        /* unhandled / unknown error (ignore) */
00453                                 break;
00454                         }
00455                 }
00456                 break;
00457 
00458         default:
00459                 break;
00460         }
00461 
00462 out:
00463         if (call) {
00464                 /* Send queued call events to layer 4 (if any) */
00465                 Q931CallSendQueuedEvents(call);
00466 
00467                 /*
00468                  * Release CRV if call is still (or again) in Null state,
00469                  * and send an event to L4 before doing so
00470                  *
00471                  * TODO: Remove Q931CallRelease() calls from Q931Proc_*
00472                  *       functions
00473                  */
00474                 if (!Q931CallIsGlobal(call)) {
00475                         if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00476                                 /* Send event, so L4 can clean up */
00477                                 struct Q931_CallEvent event;
00478 
00479                                 event.id    = Q931_EVENT_RELEASE_CRV;
00480                                 event.type  = Q931_EVENT_TYPE_CRV;
00481                                 event.error = 0;
00482 
00483                                 Q931CallSendEvent(call, &event);
00484 
00485                                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00486 
00487                                 /* Release call */
00488                                 Q931CallRelease(call);
00489                         }
00490                 }
00491         }
00492         return RetCode;
00493 }
00494 
00495 /*****************************************************************************
00496 
00497   Function:      Q931Tx34
00498 
00499   Description:  Called from the stack to send a message to layer 4.
00500 
00501   Parameters:   Mes[IN]  Ptr to message buffer.
00502                 Size[IN]        Message size in bytes.
00503 
00504   Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
00505                 see q931errors.h for details.
00506 
00507 *****************************************************************************/
00508 L3INT Q931Tx34(Q931_TrunkInfo_t *pTrunk, L3UCHAR * Mes, L3INT Size)
00509 {
00510         Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Layer4 (size: %d)\n", Size);
00511 
00512         if (pTrunk->Q931Tx34CBProc) {
00513                 return pTrunk->Q931Tx34CBProc(pTrunk->PrivateData34, Mes, Size);
00514         }
00515         return Q931E_MISSING_CB;        
00516 }
00517 
00518 /*****************************************************************************
00519 
00520   Function:      Q931Rx43
00521 
00522   Description:  Receive message from Layer 4 (application).
00523 
00524   Parameters:   pTrunk[IN]  Trunk #.
00525                 buf[IN]  Message Pointer.
00526                 Size[IN]        Message size in bytes.
00527 
00528   Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
00529                 see q931errors.h for details.
00530 
00531 *****************************************************************************/
00532 L3INT Q931Rx43(Q931_TrunkInfo_t *pTrunk,L3UCHAR * buf, L3INT Size)
00533 {
00534         Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace];
00535         L3INT RetCode = Q931E_NO_ERROR;
00536         struct Q931_Call *call = NULL;
00537 
00538         Q931Log(pTrunk, Q931_LOG_DEBUG, "Receiving message from Layer4 (size: %d, type: %d [0x%x], CRV: %d, CRVFlag: %d)\n", Size, ptr->MesType, ptr->MesType, ptr->CRV, ptr->CRVFlag);
00539 
00540         /*
00541          * Check if message is valid in current state & dialect
00542          */
00543 
00544         /* Get call handle */
00545         if (ptr->CRV) {
00546                 /* Find the call using CRV */
00547                 call = Q931GetCallByCRV(pTrunk, ptr->CRV);
00548                 if(!call)
00549                         return Q931E_INVALID_CRV;
00550 
00551                 /* SAFEGUARD: make sure the CRVFlag is set correctly */
00552                 ptr->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00553         } else {
00554                 /* global call handle */
00555                 call = Q931GetGlobalCall(pTrunk);
00556         }
00557 
00558         /* Check if message can be handled */
00559         if (!Q931DialectGetMesProc(pTrunk->Dialect, ptr->MesType)) {
00560                 RetCode = Q931E_UNRECOGNIZED_MESSAGE;
00561 
00562                 Q931Log(pTrunk, Q931_LOG_WARNING, "Unrecognized message from Layer 4 (size: %d, type: %d)\n", Size, ptr->MesType);
00563 
00564                 /* Ignore unknown message? */
00565                 if (Q931TrunkIsSetFlag(pTrunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
00566                         RetCode = Q931E_NO_ERROR;
00567                 }
00568                 goto out;
00569         }
00570 
00571         /* Check if message is valid in current call state */
00572         if (!Q931DialectIsEventLegal(pTrunk->Dialect, Q931CallGetState(call), ptr->MesType, 4)) {
00573                 RetCode = Q931E_UNEXPECTED_MESSAGE;
00574 
00575                 Q931Log(pTrunk, Q931_LOG_ERROR, "Unexpected message (invalid in current state) from Layer 4 (size: %d, type: %d [0x%x])\n", Size, ptr->MesType, ptr->MesType);
00576                 goto out;
00577         }
00578 
00579         Q931Log(pTrunk, Q931_LOG_NOTICE, "Handling message from Layer4 in %s call state: %d\n", Q931CallIsGlobal(call) ? "global" : "", Q931CallGetState(call));
00580 
00581         RetCode = Q931Proc(pTrunk, buf, 4);
00582 
00583 out:
00584         if (call) {
00585                 /*
00586                  * Release CRV if call is still (or again) in Null state,
00587                  * and send an event to L4 before doing so
00588                  *
00589                  * TODO: Remove Q931CallRelease() calls from Q931Proc_*
00590                  *       functions
00591                  */
00592                 if (!Q931CallIsGlobal(call)) {
00593                         if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00594                                 /* Send event, so L4 can clean up */
00595                                 struct Q931_CallEvent event;
00596 
00597                                 event.id    = Q931_EVENT_RELEASE_CRV;
00598                                 event.type  = Q931_EVENT_TYPE_CRV;
00599                                 event.error = 0;
00600 
00601                                 Q931CallSendEvent(call, &event);
00602 
00603                                 Q931Log(pTrunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00604 
00605                                 /* Release call */
00606                                 Q931CallRelease(call);
00607                         }
00608                 }
00609         }
00610 
00611         Q931Log(pTrunk, Q931_LOG_DEBUG, "Q931Rx43 return code: %d\n", RetCode);
00612         return RetCode;
00613 }
00614 
00615 /*****************************************************************************
00616 
00617   Function:      Q931Tx32
00618 
00619   Description:  Called from the stack to send a message to L2. The input is 
00620                                 always a non-packed message so it will first make a proper
00621                                 call to create a packed message before it transmits that
00622                                 message to layer 2.
00623 
00624   Parameters:   pTrunk[IN]  Trunk #  
00625                                 buf[IN]  Ptr to message buffer.
00626                                 Size[IN]        Message size in bytes.
00627 
00628   Return Value: Error Code. 0 = No Error, < 0 :error, > 0 : Warning
00629                                 see q931errors.h for details.
00630 
00631 *****************************************************************************/
00632 L3INT Q931Tx32Data(Q931_TrunkInfo_t *pTrunk, L3UCHAR bcast, L3UCHAR * Mes, L3INT Size)
00633 {
00634         Q931mes_Generic *ptr = (Q931mes_Generic*)Mes;
00635         L3INT RetCode = Q931E_NO_ERROR;
00636         L3INT Offset = bcast ? (Q931L2HeaderSpace - 1) : Q931L2HeaderSpace;
00637         L3INT OSize;
00638         L3UCHAR tei = 0;
00639 
00640         Q931Log(pTrunk, Q931_LOG_DEBUG, "Sending message to Q.921 (size: %d)\n", Size);
00641 
00642         memset(pTrunk->L2Buf, 0, sizeof(pTrunk->L2Buf));
00643 
00644         if (ptr->CRV) {
00645                 struct Q931_Call *call;
00646 
00647                 /* Find the call using CRV */
00648                 call = Q931GetCallByCRV(pTrunk, ptr->CRV);
00649                 if(!call)
00650                         return Q931E_INVALID_CRV;
00651 
00652                 tei = call->Tei;
00653 
00654                 /* SAFEGUARD: make sure the CRVFlag is set correctly */
00655                 ptr->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00656         }
00657 
00658         /* Call pack function through table. */
00659         RetCode = Q931Pmes(pTrunk, ptr->MesType, (Q931mes_Generic *)Mes, Size, &pTrunk->L2Buf[Offset], &OSize);
00660         if (RetCode >= Q931E_NO_ERROR) {
00661 
00662                 if (pTrunk->Q931Tx32CBProc) {
00663                         RetCode = pTrunk->Q931Tx32CBProc(pTrunk->PrivateData32, bcast ? Q921_DL_UNIT_DATA : Q921_DL_DATA, tei, pTrunk->L2Buf, OSize + Offset);
00664                         if (RetCode > 0) {
00665                                 /* L2 returns number of packets sent */
00666                                 RetCode = Q931E_NO_ERROR;
00667                         }
00668                 } else {
00669                         RetCode = Q931E_MISSING_CB;
00670                 }
00671         }
00672 
00673         return RetCode;
00674 }
00675 
00676 
00677 /*****************************************************************************
00678 
00679   Function:      Q931SetError
00680 
00681   Description:  Called from the stack to indicate an error. 
00682 
00683   Parameters:   ErrID      ID of ie or message causing error.
00684                 ErrPar1  Error parameter 1
00685                 ErrPar2  Error parameter 2.
00686 
00687 
00688 *****************************************************************************/
00689 void Q931SetError(Q931_TrunkInfo_t *pTrunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2)
00690 {
00691         if (pTrunk->Q931ErrorCBProc) {
00692                 pTrunk->Q931ErrorCBProc(pTrunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
00693         }
00694 }
00695 
00696 
00697 L3INT Q931ReleaseCRV(Q931_TrunkInfo_t *pTrunk, L3INT CRV)
00698 {
00699         struct Q931_Call *call;
00700 
00701         call = Q931GetCallByCRV(pTrunk, CRV);
00702         if (!call)
00703                 return Q931E_INVALID_CRV;
00704 
00705         call->InUse = 0;
00706         return Q931E_NO_ERROR;
00707 }
00708 
00709 L3ULONG Q931GetTime()
00710 {
00711         L3ULONG tNow = 0;
00712         static L3ULONG tLast = 0;
00713 
00714         if (Q931GetTimeProc != NULL) {
00715                 tNow = Q931GetTimeProc();
00716                 if (tNow < tLast) {     /* wrapped */
00717                         /* TODO */
00718                 }
00719                 tLast = tNow;
00720         }
00721         return tNow;
00722 }
00723 
00724 void Q931SetGetTimeCB(L3ULONG (*callback)(void))
00725 {
00726         Q931GetTimeProc = callback;
00727 }
00728 
00729 
00730 /*****************************************************************************
00731   Function:      Q931AddStateEntry
00732 
00733   Description:  Find an empty entry in the dialects state table and add this
00734                                 entry.
00735 *****************************************************************************/
00736 void Q931AddStateEntry(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR flags)
00737 {
00738         return;
00739 }
00740 
00741 /*****************************************************************************
00742   Function:      Q931IsEventLegal
00743 
00744   Description:  Check state table for matching criteria to indicate if this
00745                                 Message is legal in this state or not.
00746 
00747   Note:          Someone write a bsearch or invent something smart here
00748                                 please - sequential is ok for now.
00749 *****************************************************************************/
00750 L3BOOL Q931IsEventLegal(L3UCHAR iD, L3INT iState, L3INT iMes, L3UCHAR dirflags)
00751 {
00752         return L3FALSE;
00753 }
00754 
00755 /*****************************************************************************
00756   Function:      q931_error_to_name()
00757 
00758   Description:  Check state table for matching criteria to indicate if this
00759                                 Message is legal in this state or not.
00760 
00761   Note:          Someone write a bsearch or invent something smart here
00762                                 please - sequential is ok for now.
00763 *****************************************************************************/
00764 static const char *q931_error_names[] = {
00765         "Q931E_NO_ERROR",                       /* 0 */
00766 
00767         "Q931E_UNKNOWN_MESSAGE",                /* -3001 */
00768         "Q931E_ILLEGAL_IE",                     /* -3002 */
00769         "Q931E_UNKNOWN_IE",                     /* -3003 */
00770         "Q931E_BEARERCAP",                      /* -3004 */
00771         "Q931E_HLCOMP",                         /* -3005 */
00772         "Q931E_LLCOMP",                         /* -3006 */
00773         "Q931E_INTERNAL",                       /* -3007 */
00774         "Q931E_MISSING_CB",                     /* -3008 */
00775         "Q931E_UNEXPECTED_MESSAGE",             /* -3009 */
00776         "Q931E_ILLEGAL_MESSAGE",                /* -3010 */
00777         "Q931E_TOMANYCALLS",                    /* -3011 */
00778         "Q931E_INVALID_CRV",                    /* -3012 */
00779         "Q931E_CALLID",                         /* -3013 */
00780         "Q931E_CALLSTATE",                      /* -3014 */
00781         "Q931E_CALLEDSUB",                      /* -3015 */
00782         "Q931E_CALLEDNUM",                      /* -3016 */
00783         "Q931E_CALLINGNUM",                     /* -3017 */
00784         "Q931E_CALLINGSUB",                     /* -3018 */
00785         "Q931E_CAUSE",                          /* -3019 */
00786         "Q931E_CHANID",                         /* -3020 */
00787         "Q931E_DATETIME",                       /* -3021 */
00788         "Q931E_DISPLAY",                        /* -3022 */
00789         "Q931E_KEYPADFAC",                      /* -3023 */
00790         "Q931E_NETFAC",                         /* -3024 */
00791         "Q931E_NOTIFIND",                       /* -3025 */
00792         "Q931E_PROGIND",                        /* -3026 */
00793         "Q931E_RESTARTIND",                     /* -3027 */
00794         "Q931E_SEGMENT",                        /* -3028 */
00795         "Q931E_SIGNAL",                         /* -3029 */
00796         "Q931E_GENERIC_DIGITS",                 /* -3030 */
00797 
00798         "Q931E_MANDATORY_IE_MISSING",           /* -3031 */
00799         "Q931E_UNRECOGNIZED_MESSAGE",           /* -3032 */
00800 };
00801 
00802 #define Q931_MAX_ERROR 32
00803 
00804 const char *q931_error_to_name(q931_error_t error)
00805 {
00806         int index = 0;
00807         if ((int)error < 0) {
00808                 index = (((int)error * -1) -3000);
00809         }
00810         if (index < 0 || index > Q931_MAX_ERROR) {
00811                 return "";
00812         }
00813         return q931_error_names[index];
00814 }
00815 /*
00816  * Logging
00817  */
00818 #include <stdarg.h>
00819 
00820 L3INT Q931Log(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...)
00821 {
00822         char buf[Q931_LOGBUFSIZE];
00823         L3INT len;
00824         va_list ap;
00825 
00826         if (!trunk->Q931LogCBProc)
00827                 return 0;
00828 
00829         if (trunk->loglevel < level)
00830                 return 0;
00831 
00832         va_start(ap, fmt);
00833 
00834         len = vsnprintf(buf, sizeof(buf)-1, fmt, ap);
00835         if (len <= 0) {
00836                 /* TODO: error handling */
00837                 return -1;
00838         }
00839         if (len >= sizeof(buf))
00840                 len = sizeof(buf) - 1;
00841 
00842         buf[len] = '\0';
00843 
00844         va_end(ap);
00845 
00846         return trunk->Q931LogCBProc(trunk->PrivateDataLog, level, buf, len);
00847 }
00848 
00853 void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv)
00854 {
00855         trunk->Q931LogCBProc  = func;
00856         trunk->PrivateDataLog = priv;
00857 }
00858 
00863 void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level)
00864 {
00865         if(!trunk) {
00866                 return;
00867         }
00868 
00869         if (level < Q931_LOG_NONE) {
00870                 level = Q931_LOG_NONE;
00871         } else if (level > Q931_LOG_DEBUG) {
00872                 level = Q931_LOG_DEBUG;
00873         }
00874         trunk->loglevel = level;
00875 }
00876 
00883 L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *pTrunk, struct Q931_Call *call)
00884 {
00885         Q931Log(pTrunk, Q931_LOG_DEBUG, "Timer %d of call %d timed out\n", call->TimerID, call->CRV);
00886 
00887         return 0;
00888 }
00889 
00890 
00891 
00892 /**************************************************************************************
00893  *  Trunk helper functions
00894  **************************************************************************************/
00895 #include <assert.h>
00896 
00897 void Q931TrunkSetFlag(Q931_TrunkInfo_t *trunk, L3INT flag)
00898 {
00899         trunk->flags |= flag;
00900 }
00901 
00902 void Q931TrunkClearFlag(Q931_TrunkInfo_t *trunk, L3INT flag)
00903 {
00904         trunk->flags &= ~flag;
00905 }
00906 
00907 void Q931TrunkClearAllFlags(Q931_TrunkInfo_t *trunk)
00908 {
00909         trunk->flags = 0;
00910 }
00911 
00912 L3BOOL Q931TrunkIsSetFlag(const Q931_TrunkInfo_t *trunk, const L3INT flag)
00913 {
00914         return ((trunk->flags & flag) != 0);
00915 }
00916 
00917 /* High-level access */
00918 #define Q931_TRUNK_FLAG_SET_FUNC(_name, _flag)                  \
00919         void _name(Q931_TrunkInfo_t *trunk, L3BOOL enable) {    \
00920                 assert(trunk);                                  \
00921                 if (enable) {                                   \
00922                         Q931TrunkSetFlag(trunk, _flag);         \
00923                 } else {                                        \
00924                         Q931TrunkClearFlag(trunk, _flag);       \
00925                 }                                               \
00926         }
00927 
00928 #define Q931_TRUNK_FLAG_GET_FUNC(_name, _flag)                  \
00929         L3BOOL _name(Q931_TrunkInfo_t *trunk) {                 \
00930                 assert(trunk);                                  \
00931                 return Q931TrunkIsSetFlag(trunk, _flag);        \
00932         }
00933 
00934 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoSetupAck,     Q931_TFLAG_AUTO_SETUP_ACK);
00935 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoServiceAck,   Q931_TFLAG_AUTO_SERVICE_ACK);
00936 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoConnectAck,   Q931_TFLAG_AUTO_CONNECT_ACK);
00937 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoRestartAck,   Q931_TFLAG_AUTO_RESTART_ACK);
00938 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetStatusEnquiry,    Q931_TFLAG_STATUS_ENQUIRY);
00939 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreUnknownMsg, Q931_TFLAG_IGNORE_UNKNOWN_MSG);
00940 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreUnknownIEs, Q931_TFLAG_IGNORE_UNKNOWN_IE);
00941 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreIllegalIEs, Q931_TFLAG_IGNORE_ILLEGAL_IE);
00942 
00943 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoSetupAck,     Q931_TFLAG_AUTO_SETUP_ACK);
00944 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoServiceAck,   Q931_TFLAG_AUTO_SERVICE_ACK);
00945 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoConnectAck,   Q931_TFLAG_AUTO_CONNECT_ACK);
00946 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoRestartAck,   Q931_TFLAG_AUTO_RESTART_ACK);
00947 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetStatusEnquiry,    Q931_TFLAG_STATUS_ENQUIRY);
00948 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreUnknownMsg, Q931_TFLAG_IGNORE_UNKNOWN_MSG);
00949 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreUnknownIEs, Q931_TFLAG_IGNORE_UNKNOWN_IE);
00950 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreIllegalIEs, Q931_TFLAG_IGNORE_ILLEGAL_IE);
00951 
00960 void Q931TrunkSetRelaxedMode(Q931_TrunkInfo_t *trunk, L3BOOL enable)
00961 {
00962         int flags = (Q931_TFLAG_IGNORE_UNKNOWN_MSG | Q931_TFLAG_IGNORE_UNKNOWN_IE | Q931_TFLAG_IGNORE_ILLEGAL_IE);
00963         assert(trunk);
00964 
00965         if (enable) {
00966                 Q931TrunkSetFlag(trunk, flags);
00967         } else {
00968                 Q931TrunkClearFlag(trunk, flags);
00969         }
00970 }
00971 
00972 
00973 /***********************************************************************
00974  * Message, IE, Timer callback helpers
00975  ***********************************************************************/
00976 L3INT Q931Proc(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf, L3INT iFrom)
00977 {
00978         Q931mes_Header  *pMes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
00979         q931proc_func_t *func = Q931DialectGetMesProc(pTrunk->Dialect, pMes->MesType);
00980 
00981         if (func) {
00982                 return func(pTrunk, buf, iFrom);
00983         }
00984 
00985         /* Ignore unknown message? */
00986         if (Q931TrunkIsSetFlag(pTrunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
00987                 return Q931E_NO_ERROR;
00988         }
00989 
00990         func = Q931DialectGetUnknownMesProc(pTrunk->Dialect);
00991         if (func) {
00992                 return func(pTrunk, buf, iFrom);
00993         }
00994         return Q931E_INTERNAL;
00995 }
00996 
00997 L3INT Q931ProcInvalid(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf, L3INT iFrom)
00998 {
00999         q931proc_func_t *func = Q931DialectGetInvalidMesProc(pTrunk->Dialect);
01000 
01001         if (func) {
01002                 return func(pTrunk, buf, iFrom);
01003         }
01004         return Q931E_INTERNAL;  
01005 }
01006 
01007 L3INT Q931Umes(Q931_TrunkInfo_t *pTrunk, L3UCHAR id, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size)
01008 {
01009         q931umes_func_t *func = Q931DialectGetUmesProc(pTrunk->Dialect, id);
01010 
01011         if (func) {
01012                 return func(pTrunk, IBuf, OBuf, IOff, Size);
01013         }
01014 
01015         /* Ignore unknown message? */
01016         if (Q931TrunkIsSetFlag(pTrunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
01017                 return Q931E_NO_ERROR;
01018         }
01019 
01020         return Q931E_INTERNAL;
01021 }
01022 
01023 L3INT Q931Pmes(Q931_TrunkInfo_t *pTrunk, L3UCHAR id, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
01024 {
01025         q931pmes_func_t *func = Q931DialectGetPmesProc(pTrunk->Dialect, id);
01026 
01027         if (func) {
01028                 return func(pTrunk, IBuf, ISize, OBuf, OSize);
01029         }
01030         return Q931E_INTERNAL;
01031 }
01032 
01033 L3INT Q931Uie(Q931_TrunkInfo_t *pTrunk, L3UCHAR id, Q931mes_Generic *pMes, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
01034 {
01035         q931uie_func_t *func = Q931DialectGetUieProc(pTrunk->Dialect, id);
01036 
01037         if (func) {
01038                 return func(pTrunk, pMes, IBuf, OBuf, IOff, OOff);
01039         }
01040         return Q931E_INTERNAL;
01041 }
01042 
01043 L3INT Q931Pie(Q931_TrunkInfo_t *pTrunk, L3UCHAR id, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01044 {
01045         q931pie_func_t *func = Q931DialectGetPieProc(pTrunk->Dialect, id);
01046 
01047         if (func) {
01048                 return func(pTrunk, IBuf, OBuf, Octet);
01049         }
01050         return Q931E_INTERNAL;
01051 }
01052 
01053 L3BOOL Q931UieIsNull(Q931_TrunkInfo_t *pTrunk, L3UCHAR id)
01054 {
01055         return (!Q931DialectGetUieProc(pTrunk->Dialect, id));
01056 }
01057 
01058 L3BOOL Q931PieIsNull(Q931_TrunkInfo_t *pTrunk, L3UCHAR id)
01059 {
01060         return (!Q931DialectGetPieProc(pTrunk->Dialect, id));
01061 }
01062 
01063 L3INT Q931Timeout(Q931_TrunkInfo_t *pTrunk, struct Q931_Call *call, L3UCHAR timer)
01064 {
01065         q931timeout_func_t *func = Q931DialectGetTimerProc(pTrunk->Dialect, timer);
01066 
01067         if (func) {
01068                 return func(pTrunk, call);
01069         }
01070         return Q931E_INTERNAL;
01071 }
01072 
01073 
01074 /*
01075  * Default handler for unexpected / unknown messages
01076  */
01077 L3INT Q931ProcUnknownMessage(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf, L3INT iFrom)
01078 {
01079         Q931mes_Header *mes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
01080 
01081         Q931Log(pTrunk, Q931_LOG_NOTICE, "Unknown message %#hx received\n", mes->MesType);
01082 
01083         return Q931E_NO_ERROR;
01084 }
01085 
01086 L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf, L3INT iFrom)
01087 {
01088         Q931mes_Header *mes = (Q931mes_Header *)&buf[Q931L4HeaderSpace];
01089 
01090         Q931Log(pTrunk, Q931_LOG_NOTICE, "Unexpected/Invalid message %#hx received\n", mes->MesType);
01091 
01092         return Q931E_NO_ERROR;
01093 }
01094 

Generated on Tue Apr 7 17:38:19 2009 for mod_ssh by  doxygen 1.5.4