libisdn
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 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <stdarg.h>
00042 #include <string.h>
00043 
00044 #include "Q921.h"
00045 #include "Q931.h"
00046 #include "Q931priv.h"
00047 #include "Q931call.h"
00048 
00049 #if defined(HAVE_DIALECT_5ESS)
00050 #include "5ESS.h"
00051 #endif
00052 
00053 /* Global variables */
00054 
00055 L3INT Q931L4HeaderSpace = {0};  /* header space to be ignoder/inserted */
00056                                 /* at head of each message. */
00057 L3INT Q931L2HeaderSpace = {4};  /* Q921 header space, sapi, tei etc */
00058 
00059 L3ULONG (*Q931GetTimeProc) (void) = NULL;       /* callback for func reading time in ms */
00060 
00061 /*****************************************************************************
00062 
00063   Function:      Q931SetL4HeaderSpace
00064 
00065   Description:  Set the # of bytes to be inserted/ignored at the head of
00066                 each message. Q931 will issue a message with space for header
00067                 and the user will use this to fill in whatever header info
00068                 is required to support the architecture used.
00069 
00070 *****************************************************************************/
00071 void Q931SetL4HeaderSpace(L3INT space)
00072 {
00073         Q931L4HeaderSpace = space;
00074 }
00075 
00076 /*****************************************************************************
00077 
00078   Function:      Q931SetL2HeaderSpace
00079 
00080   Description:  Set the # of bytes to be inserted/ignored at the head of
00081                 each message. Q931 will issue a message with space for header
00082                 and the user will use this to fill in whatever header info
00083                 is required to support the architecture used.
00084 
00085 *****************************************************************************/
00086 void Q931SetL2HeaderSpace(L3INT space)
00087 {
00088         Q931L2HeaderSpace = space;
00089 }
00090 
00091 
00102 L3INT Q931ProcDummy(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, q931_msg_from_t from)
00103 {
00104         return Q931E_INTERNAL;
00105 }
00106 
00119 L3INT Q931UmesDummy(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size, struct Q931MesgErrors *errs)
00120 {
00121         return Q931E_UNKNOWN_MESSAGE;
00122 }
00123 
00136 L3INT Q931UieDummy(Q931_TrunkInfo_t *trunk, Q931mes_Generic *msg, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
00137 {
00138         return Q931E_UNKNOWN_IE;
00139 }
00140 
00152 L3INT Q931PmesDummy(Q931_TrunkInfo_t *trunk, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
00153 {
00154         return Q931E_UNKNOWN_MESSAGE;
00155 }
00156 
00167 L3INT Q931PieDummy(Q931_TrunkInfo_t *trunk, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
00168 {
00169         return Q931E_UNKNOWN_IE;
00170 }
00171 
00172 
00173 
00178 Q931_API void Q931Initialize(void)
00179 {
00180         /*
00181          * Initialize Q.931 dialect registry and register dialects
00182          */
00183         Q931DialectRegistryInit();
00184 
00185         /* Register Q.931 */
00186         Q931DialectRegister(Q931_Dialect_Q931, Q931_TE, Q931CreateTE);
00187         Q931DialectRegister(Q931_Dialect_Q931, Q931_NT, Q931CreateNT);
00188 
00189 #if defined(HAVE_DIALECT_5ESS)
00190         /* Register 5ESS */
00191         Q931DialectRegister(Q931_Dialect_5ESS, Q931_TE, ATT5ESSCreateTE);
00192 /*      Q931DialectRegister(Q931_Dialect_5ESS, Q931_NT, ATT5ESSCreateNT); */
00193 #endif
00194 }
00195 
00201 Q931_API void Q931TimerTick(Q931_TrunkInfo_t *trunk)
00202 {
00203         struct Q931_Call *call = NULL;
00204         L3ULONG now = 0;
00205         L3INT x;
00206 
00207         /* TODO: Loop through all active calls, check timers and call timout procs
00208          * if timers are expired.
00209          * Implement a function array so each dialect can deal with their own
00210          * timeouts.
00211          */
00212         now = Q931GetTime();
00213 
00214         for (x = 0; x < Q931MAXCALLPERTRUNK; x++) {
00215                 call = &trunk->call[x];
00216 
00217                 if (!call->InUse || !call->Timer || !call->TimerID)
00218                         continue;
00219 
00220                 if (call->Timer <= now) {
00221                         int id = call->TimerID; /* Q931CallStopTimer resets the TimerID */
00222 
00223                         /* Stop Timer */
00224                         Q931CallStopTimer(call, id);
00225 
00226                         /* Increment expire counter */
00227                         Q931CallIncrementTimerExpireCount(call);
00228 
00229                         /* Invoke dialect timeout callback */
00230                         Q931Timeout(trunk, call, id);
00231 
00232                         /*
00233                          * Release CRV if call has gone back to Null state after timer event
00234                          * and send an event to L4 before doing so
00235                          */
00236                         if (!Q931CallIsGlobal(call)) {
00237                                 if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00238                                         /* Send event, so L4 can clean up */
00239                                         struct Q931_CallEvent event;
00240 
00241                                         event.id    = Q931_EVENT_RELEASE_CRV;
00242                                         event.type  = Q931_EVENT_TYPE_CRV;
00243                                         event.error = 0;
00244 
00245                                         Q931CallSendEvent(call, &event);
00246 
00247                                         Q931Log(trunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00248 
00249                                         /* Release call */
00250                                         Q931CallRelease(call);
00251                                 }
00252                         }
00253                 }
00254         }
00255 }
00256 
00257 
00267 Q931_API L3INT Q931Rx23(Q931_TrunkInfo_t *trunk, L3INT ind, L3UCHAR tei, L3UCHAR *buf, L3INT Size)
00268 {
00269         L3UCHAR *Mes = NULL;
00270         L3INT RetCode = Q931E_NO_ERROR;
00271         Q931mes_Generic *m = (Q931mes_Generic *) trunk->L3Buf;
00272         struct Q931_Call *call = NULL;
00273         struct Q931MesgErrors Errs;
00274         L3INT ISize;
00275         L3INT IOff = 0;
00276         L3INT L2HSize = Q931L2HeaderSpace;
00277 
00278         switch (ind) {
00279         case Q921_DL_UNIT_DATA:         /* DL-UNITDATA indication (UI frame, 3 byte header) */
00280                 L2HSize = 3;
00281 
00282         case Q921_DL_DATA:              /* DL-DATA indication (I frame, 4 byte header) */
00283                 /* Reset our decode buffer */
00284                 memset(trunk->L3Buf, 0, sizeof(trunk->L3Buf));
00285 
00286                 /* L2 Header Offset */
00287                 Mes = &buf[L2HSize];
00288 
00289                 /* Protocol Discriminator */
00290                 m->ProtDisc = Mes[IOff++];
00291 
00292                 /* CRV */
00293                 m->CRVFlag = (Mes[IOff + 1] >> 7) & 0x01;
00294                 m->CRV = Q931Uie_CRV(trunk, Mes, m->buf, &IOff, &ISize);
00295 
00296                 /* Message Type */
00297                 m->MesType = Mes[IOff++];
00298 
00299                 /* Store tei */
00300                 m->Tei = tei;
00301 
00302                 /* vvv new code starts here */
00303                 if (m->CRV) {
00304                         /* Lookup call reference */
00305                         call = Q931GetCallByCRV(trunk, m->CRV);
00306                         if (!call) {
00307                                 /* oops, no call found */
00308                                 if (m->MesType == Q931mes_SETUP) {
00309                                         /* Setup message, create new call handle */
00310                                         call = Q931CallNewIncoming(trunk, m->CRV);
00311                                 } else {
00312                                         /* Not a setup message -> INVALID CRV */
00313                                         /* TODO: respond with proper RELEASE COMPLETE + cause combination */
00314                                         return Q931E_INVALID_CRV;
00315                                 }
00316 
00317                                 /* Still no call handle? */
00318                                 if (!call) {
00319                                         /* blah, failed to allocate new call -> Disconnect */
00320                                         Q931Disconnect(trunk, MSGF_FROM_L2, m->CRV, 42);
00321                                         return Q931E_INTERNAL;
00322                                 }
00323                         }
00324 
00325                         /* d'oh a little ugly but this saves us from:
00326                          *      a) doing Q.921 work in the lower levels (extracting the TEI ourselves)
00327                          *      b) adding a tei parameter to _all_ Proc functions
00328                          */
00329                         if (tei && !call->Tei) {
00330                                 call->Tei = tei;
00331                         }
00332 
00333                         /* Diagnostic message */
00334                         Q931Log(trunk, Q931_LOG_DEBUG, "Call is in state %d [%s]\n", Q931CallGetState(call), Q931CallGetStateName(call));
00335                 } else {
00336                         /* Global CRV ?? */
00337                         call = Q931GetGlobalCall(trunk);
00338 
00339                         Q931Log(trunk, Q931_LOG_DEBUG, "Using global call for message\n");
00340                 }
00341                 /* ^^^ new code ends here */
00342 
00343                 Q931Log(trunk, 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,
00344                                                  m->MesType, m->CRVFlag, m->CRVFlag ? "Terminator" : "Originator", m->CRV, Q931DialectGetName(trunk->Dialect));
00345 
00346                 Q931MesgErrorsInit(&Errs, m->MesType);
00347 
00348                 RetCode = Q931Umes(trunk, m->MesType, Mes, (Q931mes_Generic *)trunk->L3Buf, IOff, Size - L2HSize, &Errs);
00349                 if (RetCode >= Q931E_NO_ERROR) {
00350                         RetCode = Q931Proc(trunk, call, (Q931mes_Generic *)trunk->L3Buf, Q931_MSG_FROM_L2);
00351                         Q931Log(trunk, Q931_LOG_DEBUG, "Q931Proc[%s][0x%02x]() returned %d\n", Q931DialectGetName(trunk->Dialect), m->MesType, RetCode);
00352                 } else {
00353                         Q931Log(trunk, Q931_LOG_DEBUG, "Q931Umes[%s][0x%02x]() returned %d\n", Q931DialectGetName(trunk->Dialect), m->MesType, RetCode);
00354 
00355                         /* Output error report */
00356                         Q931MesgErrorsPrint(trunk, &Errs, Mes, Size - L2HSize);
00357                 }
00358 
00359                 /* Error handling for Umes() and Proc() */
00360                 if (RetCode < Q931E_NO_ERROR) {
00361                         /* Initialize response message */
00362 
00363                         /* TODO: Add Error codes for Mandatory IE missing and error */
00364                         switch (RetCode) {
00365                         case Q931E_MANDATORY_IE_MISSING:
00366                                 /* Send STATUS with cause 96 */
00367                                 RetCode = Q931StatusEnquiryResponse(trunk, call, Q850_CAUSE_MANDATORY_IE_MISSING);
00368                                 break;
00369 
00370                         case Q931E_ILLEGAL_IE:                  /* ?? */
00371                                 /* Send STATUS with cause 96 */
00372                                 RetCode = Q931StatusEnquiryResponse(trunk, call, Q850_CAUSE_IE_NONEXIST);
00373                                 break;
00374 
00375                         case Q931E_UNKNOWN_IE:
00376                                 /* Send STATUS with cause 100 */
00377                                 RetCode = Q931StatusEnquiryResponse(trunk, call, Q850_CAUSE_INVALID_IE_CONTENTS);
00378                                 break;
00379 
00380                         case Q931E_UNEXPECTED_MESSAGE:
00381                         case Q931E_UNRECOGNIZED_MESSAGE:
00382                                 /* Ignore in State 0 */
00383                                 if ((Q931CallGetState(call) & 0xff) == Q931_U0)
00384                                         goto out;
00385 
00386                                 /* Ignore for RELEASE and RELEASE COMPLETE */
00387                                 if (m->MesType == Q931mes_RELEASE || m->MesType == Q931mes_RELEASE_COMPLETE)
00388                                         goto out;
00389 
00390                                 if (Q931TrunkGetStatusEnquiry(trunk)) {
00391                                         /* Send STATUS ENQUIRY */
00392                                         Q931InitMesGeneric(m);
00393                                         m->CRV     = Q931CallGetCRV(call);
00394                                         m->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00395                                         m->MesType = Q931mes_STATUS_ENQUIRY;
00396 
00397                                         /* TODO: check and / or fire up T322 */
00398                                         RetCode = Q931Tx32(trunk, 0, m, m->Size);
00399                                 } else {
00400                                         /* Send STATUS with cause X */
00401                                         RetCode = Q931StatusEnquiryResponse(trunk, call,
00402                                                                 (RetCode == Q931E_UNEXPECTED_MESSAGE) ? Q850_CAUSE_WRONG_MESSAGE : Q850_CAUSE_MESSAGE_TYPE_NONEXIST);
00403                                 }
00404                                 break;
00405 
00406                         default:        /* unhandled / unknown error (ignore) */
00407                                 break;
00408                         }
00409                 }
00410                 break;
00411 
00412         default:
00413                 break;
00414         }
00415 
00416 out:
00417         if (call) {
00418                 /* Send queued call events to layer 4 (if any) */
00419                 Q931CallSendQueuedEvents(call);
00420 
00421                 /*
00422                  * Release CRV if call is still (or again) in Null state,
00423                  * and send an event to L4 before doing so
00424                  *
00425                  * TODO: Remove Q931CallRelease() calls from Q931Proc_*
00426                  *       functions
00427                  */
00428                 if (!Q931CallIsGlobal(call)) {
00429                         if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00430                                 /* Send event, so L4 can clean up */
00431                                 struct Q931_CallEvent event;
00432 
00433                                 event.id    = Q931_EVENT_RELEASE_CRV;
00434                                 event.type  = Q931_EVENT_TYPE_CRV;
00435                                 event.error = 0;
00436 
00437                                 Q931CallSendEvent(call, &event);
00438 
00439                                 Q931Log(trunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00440 
00441                                 /* Release call */
00442                                 Q931CallRelease(call);
00443                         }
00444                 }
00445         }
00446         return RetCode;
00447 }
00448 
00449 
00460 L3INT Q931Tx34(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, int size)
00461 {
00462         Q931Log(trunk, Q931_LOG_DEBUG, "Sending message to Layer4 (size: %d)\n", size);
00463 
00464         if (trunk->Q931Tx34CBProc) {
00465                 return trunk->Q931Tx34CBProc(trunk->PrivateData34, call, msg, size);
00466         }
00467         return Q931E_MISSING_CB;
00468 }
00469 
00470 
00478 Q931_API L3INT Q931Rx43(Q931_TrunkInfo_t *trunk, Q931mes_Generic *msg, int size)
00479 {
00480         L3INT RetCode = Q931E_NO_ERROR;
00481         struct Q931_Call *call = NULL;
00482 
00483         Q931Log(trunk, Q931_LOG_DEBUG, "Receiving message from Layer4 (size: %d, type: %d [0x%x], CRV: %d, CRVFlag: %d)\n", size, msg->MesType, msg->MesType, msg->CRV, msg->CRVFlag);
00484 
00485         /*
00486          * Check if message is valid in current state & dialect
00487          */
00488 
00489         /* Get call handle */
00490         if (msg->CRV) {
00491                 /* Find the call using CRV */
00492                 call = Q931GetCallByCRV(trunk, msg->CRV);
00493                 if(!call)
00494                         return Q931E_INVALID_CRV;
00495 
00496                 /* SAFEGUARD: make sure the CRVFlag is set correctly */
00497                 msg->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00498         } else {
00499                 /* global call handle */
00500                 call = Q931GetGlobalCall(trunk);
00501         }
00502 
00503         /* Check if message can be handled */
00504         if (!Q931DialectGetMesProc(trunk->Dialect, msg->MesType)) {
00505                 RetCode = Q931E_UNRECOGNIZED_MESSAGE;
00506 
00507                 Q931Log(trunk, Q931_LOG_WARNING, "Unrecognized message from Layer 4 (size: %d, type: %d)\n", size, msg->MesType);
00508 
00509                 /* Ignore unknown message? */
00510                 if (Q931TrunkIsSetFlag(trunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
00511                         RetCode = Q931E_NO_ERROR;
00512                 }
00513                 goto out;
00514         }
00515 
00516         /* Check if message is valid in current call state */
00517         if (!Q931DialectIsEventLegal(trunk->Dialect, Q931CallGetState(call), msg->MesType, Q931_MSG_FROM_L4)) {
00518                 RetCode = Q931E_UNEXPECTED_MESSAGE;
00519 
00520                 Q931Log(trunk, Q931_LOG_ERROR, "Unexpected message (invalid in current state) from Layer 4 (size: %d, type: %d [0x%x])\n", size, msg->MesType, msg->MesType);
00521                 goto out;
00522         }
00523 
00524         Q931Log(trunk, Q931_LOG_NOTICE, "Handling message from Layer4 in %s call state: %d\n", Q931CallIsGlobal(call) ? "global" : "", Q931CallGetState(call));
00525 
00526         RetCode = Q931Proc(trunk, call, msg, Q931_MSG_FROM_L4);
00527 out:
00528         if (call) {
00529                 /*
00530                  * Release CRV if call is still (or again) in Null state,
00531                  * and send an event to L4 before doing so
00532                  *
00533                  * TODO: Remove Q931CallRelease() calls from Q931Proc_*
00534                  *       functions
00535                  */
00536                 if (!Q931CallIsGlobal(call)) {
00537                         if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00538                                 /* Send event, so L4 can clean up */
00539                                 struct Q931_CallEvent event;
00540 
00541                                 event.id    = Q931_EVENT_RELEASE_CRV;
00542                                 event.type  = Q931_EVENT_TYPE_CRV;
00543                                 event.error = 0;
00544 
00545                                 Q931CallSendEvent(call, &event);
00546 
00547                                 Q931Log(trunk, Q931_LOG_DEBUG, "Garbage-collecting call %d\n", Q931CallGetCRV(call));
00548 
00549                                 /* Release call */
00550                                 Q931CallRelease(call);
00551                         }
00552                 }
00553         }
00554 
00555         Q931Log(trunk, Q931_LOG_DEBUG, "Q931Rx43 return code: %d\n", RetCode);
00556         return RetCode;
00557 }
00558 
00559 
00570 L3INT Q931Tx32(Q931_TrunkInfo_t *trunk, L3UCHAR bcast, Q931mes_Generic *msg, int size)
00571 {
00572         L3INT RetCode = Q931E_NO_ERROR;
00573         L3INT Offset = bcast ? (Q931L2HeaderSpace - 1) : Q931L2HeaderSpace;
00574         L3INT OSize;
00575         L3UCHAR tei = 0;
00576 
00577         Q931Log(trunk, Q931_LOG_DEBUG, "Sending message to Q.921 (size: %d)\n", size);
00578 
00579         memset(trunk->L2Buf, 0, sizeof(trunk->L2Buf));
00580 
00581         if (msg->CRV) {
00582                 struct Q931_Call *call;
00583 
00584                 /* Find the call using CRV */
00585                 call = Q931GetCallByCRV(trunk, msg->CRV);
00586                 if(!call)
00587                         return Q931E_INVALID_CRV;
00588 
00589                 tei = call->Tei;
00590 
00591                 /* SAFEGUARD: make sure the CRVFlag is set correctly */
00592                 msg->CRVFlag = Q931CallIsOutgoing(call) ? 0 : 1;
00593         }
00594 
00595         /* Call pack function through table. */
00596         RetCode = Q931Pmes(trunk, msg->MesType, msg, size, &trunk->L2Buf[Offset], &OSize);
00597         if (RetCode >= Q931E_NO_ERROR) {
00598                 if (trunk->Q931Tx32CBProc) {
00599                         RetCode = trunk->Q931Tx32CBProc(trunk->PrivateData32, bcast ? Q921_DL_UNIT_DATA : Q921_DL_DATA, tei, trunk->L2Buf, OSize + Offset);
00600                         if (RetCode > 0) {
00601                                 /* L2 returns number of packets sent */
00602                                 RetCode = Q931E_NO_ERROR;
00603                         }
00604                 } else {
00605                         RetCode = Q931E_MISSING_CB;
00606                 }
00607         }
00608 
00609         return RetCode;
00610 }
00611 
00612 
00621 void Q931SetError(Q931_TrunkInfo_t *trunk,L3INT ErrID, L3INT ErrPar1, L3INT ErrPar2)
00622 {
00623         if (trunk->Q931ErrorCBProc) {
00624                 trunk->Q931ErrorCBProc(trunk->PrivateData34, ErrID, ErrPar1, ErrPar2);
00625         }
00626 }
00627 
00628 
00635 Q931_API L3INT Q931ReleaseCRV(Q931_TrunkInfo_t *trunk, L3INT crv)
00636 {
00637         struct Q931_Call *call;
00638 
00639         call = Q931GetCallByCRV(trunk, crv);
00640         if (!call)
00641                 return Q931E_INVALID_CRV;
00642 
00643         call->InUse = 0;
00644         return Q931E_NO_ERROR;
00645 }
00646 
00654 L3ULONG Q931GetTime()
00655 {
00656         L3ULONG tNow = 0;
00657         static L3ULONG tLast = 0;
00658 
00659         if (Q931GetTimeProc != NULL) {
00660                 tNow = Q931GetTimeProc();
00661                 if (tNow < tLast) {     /* wrapped */
00662                         /* TODO */
00663                 }
00664                 tLast = tNow;
00665         }
00666         return tNow;
00667 }
00668 
00669 
00675 Q931_API void Q931SetGetTimeCB(L3ULONG (*callback)(void))
00676 {
00677         Q931GetTimeProc = callback;
00678 }
00679 
00680 
00686 static const char *q931_error_names[] = {
00687         "Q931E_NO_ERROR",                       /* 0 */
00688 
00689         "Q931E_UNKNOWN_MESSAGE",                /* -3001 */
00690         "Q931E_ILLEGAL_IE",                     /* -3002 */
00691         "Q931E_UNKNOWN_IE",                     /* -3003 */
00692         "Q931E_BEARERCAP",                      /* -3004 */
00693         "Q931E_HLCOMP",                         /* -3005 */
00694         "Q931E_LLCOMP",                         /* -3006 */
00695         "Q931E_INTERNAL",                       /* -3007 */
00696         "Q931E_MISSING_CB",                     /* -3008 */
00697         "Q931E_UNEXPECTED_MESSAGE",             /* -3009 */
00698         "Q931E_ILLEGAL_MESSAGE",                /* -3010 */
00699         "Q931E_TOMANYCALLS",                    /* -3011 */
00700         "Q931E_INVALID_CRV",                    /* -3012 */
00701         "Q931E_CALLID",                         /* -3013 */
00702         "Q931E_CALLSTATE",                      /* -3014 */
00703         "Q931E_CALLEDSUB",                      /* -3015 */
00704         "Q931E_CALLEDNUM",                      /* -3016 */
00705         "Q931E_CALLINGNUM",                     /* -3017 */
00706         "Q931E_CALLINGSUB",                     /* -3018 */
00707         "Q931E_CAUSE",                          /* -3019 */
00708         "Q931E_CHANID",                         /* -3020 */
00709         "Q931E_DATETIME",                       /* -3021 */
00710         "Q931E_DISPLAY",                        /* -3022 */
00711         "Q931E_KEYPADFAC",                      /* -3023 */
00712         "Q931E_NETFAC",                         /* -3024 */
00713         "Q931E_NOTIFIND",                       /* -3025 */
00714         "Q931E_PROGIND",                        /* -3026 */
00715         "Q931E_RESTARTIND",                     /* -3027 */
00716         "Q931E_SEGMENT",                        /* -3028 */
00717         "Q931E_SIGNAL",                         /* -3029 */
00718         "Q931E_GENERIC_DIGITS",                 /* -3030 */
00719 
00720         "Q931E_MANDATORY_IE_MISSING",           /* -3031 */
00721         "Q931E_UNRECOGNIZED_MESSAGE",           /* -3032 */
00722 };
00723 
00724 #define Q931_MAX_ERROR 32
00725 
00731 Q931_API const char *q931_error_to_name(q931_error_t error)
00732 {
00733         int index = 0;
00734         if ((int)error < 0) {
00735                 index = (((int)error * -1) -3000);
00736         }
00737         if (index < 0 || index > Q931_MAX_ERROR) {
00738                 return "";
00739         }
00740         return q931_error_names[index];
00741 }
00742 
00743 /*
00744  * Logging
00745  */
00746 #include <stdarg.h>
00747 
00758 L3INT Q931Log(const Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *fmt, ...)
00759 {
00760         char buf[Q931_LOGBUFSIZE];
00761         L3INT len;
00762         va_list ap;
00763 
00764         if (!trunk->Q931LogCBProc)
00765                 return 0;
00766 
00767         if (trunk->loglevel < level)
00768                 return 0;
00769 
00770         va_start(ap, fmt);
00771 
00772         len = vsnprintf(buf, sizeof(buf)-1, fmt, ap);
00773         if (len <= 0) {
00774                 /* TODO: error handling */
00775                 return -1;
00776         }
00777         if (len >= sizeof(buf))
00778                 len = sizeof(buf) - 1;
00779 
00780         buf[len] = '\0';
00781 
00782         va_end(ap);
00783 
00784         return trunk->Q931LogCBProc(trunk->PrivateDataLog, level, buf, len);
00785 }
00786 
00787 L3INT Q931LogRaw(const Q931_TrunkInfo_t *trunk, Q931LogLevel_t level, const char *str)
00788 {
00789         if (!trunk->Q931LogCBProc)
00790                 return 0;
00791 
00792         if (trunk->loglevel < level)
00793                 return 0;
00794 
00795         return trunk->Q931LogCBProc(trunk->PrivateDataLog, level, str, strlen(str));
00796 }
00797 
00804 Q931_API void Q931SetLogCB(Q931_TrunkInfo_t *trunk, Q931LogCB_t func, void *priv)
00805 {
00806         trunk->Q931LogCBProc  = func;
00807         trunk->PrivateDataLog = priv;
00808 }
00809 
00810 
00816 Q931_API void Q931SetLogLevel(Q931_TrunkInfo_t *trunk, Q931LogLevel_t level)
00817 {
00818         if(!trunk) {
00819                 return;
00820         }
00821 
00822         if (level < Q931_LOG_NONE) {
00823                 level = Q931_LOG_NONE;
00824         } else if (level > Q931_LOG_DEBUG) {
00825                 level = Q931_LOG_DEBUG;
00826         }
00827         trunk->loglevel = level;
00828 }
00829 
00830 
00836 Q931_API Q931LogLevel_t Q931GetLogLevel(Q931_TrunkInfo_t *trunk)
00837 {
00838         if(!trunk) {
00839                 return Q931_LOG_NONE;
00840         }
00841         return trunk->loglevel;
00842 }
00843 
00848 static const char *loglevel_names[] = {
00849         [Q931_LOG_DEBUG]   = "debug",
00850         [Q931_LOG_INFO]    = "info",
00851         [Q931_LOG_NOTICE]  = "notice",
00852         [Q931_LOG_WARNING] = "warning",
00853         [Q931_LOG_ERROR]   = "error",
00854         [Q931_LOG_ALERT]   = "alert",
00855         [Q931_LOG_CRIT]    = "critical",
00856         [Q931_LOG_EMERG]   = "emergency"
00857 };
00858 
00865 Q931_API const char *Q931GetLogLevelName(Q931_TrunkInfo_t *trunk)
00866 {
00867         if(!trunk) {
00868                 return "unknown";
00869         }
00870         if (trunk->loglevel == Q931_LOG_NONE) {
00871                 return "none";
00872         }
00873         return loglevel_names[trunk->loglevel];
00874 }
00875 
00884 L3INT Q931TimeoutDummy(Q931_TrunkInfo_t *trunk, struct Q931_Call *call)
00885 {
00886         Q931Log(trunk, Q931_LOG_DEBUG, "Timer %d of call %d timed out\n", call->TimerID, call->CRV);
00887         return Q931E_NO_ERROR;
00888 }
00889 
00890 
00891 /**************************************************************************************
00892  *  Trunk helper functions
00893  **************************************************************************************/
00894 #include <assert.h>
00895 
00902 void Q931TrunkSetFlag(Q931_TrunkInfo_t *trunk, L3INT flag)
00903 {
00904         trunk->flags |= flag;
00905 }
00906 
00913 void Q931TrunkClearFlag(Q931_TrunkInfo_t *trunk, L3INT flag)
00914 {
00915         trunk->flags &= ~flag;
00916 }
00917 
00923 void Q931TrunkClearAllFlags(Q931_TrunkInfo_t *trunk)
00924 {
00925         trunk->flags = 0;
00926 }
00927 
00935 L3BOOL Q931TrunkIsSetFlag(const Q931_TrunkInfo_t *trunk, const L3INT flag)
00936 {
00937         return ((trunk->flags & flag) != 0);
00938 }
00939 
00946 #define Q931_TRUNK_FLAG_SET_FUNC(_name, _flag)                  \
00947         Q931_API void _name(Q931_TrunkInfo_t *trunk, L3BOOL enable) {   \
00948                 assert(trunk);                                  \
00949                 if (enable) {                                   \
00950                         Q931TrunkSetFlag(trunk, _flag);         \
00951                 } else {                                        \
00952                         Q931TrunkClearFlag(trunk, _flag);       \
00953                 }                                               \
00954         }
00955 
00962 #define Q931_TRUNK_FLAG_GET_FUNC(_name, _flag)                  \
00963         Q931_API L3BOOL _name(Q931_TrunkInfo_t *trunk) {        \
00964                 assert(trunk);                                  \
00965                 return Q931TrunkIsSetFlag(trunk, _flag);        \
00966         }
00967 
00968 
00969 /*
00970  * definition of actual accessor functions
00971  */
00972 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoSetupAck,     Q931_TFLAG_AUTO_SETUP_ACK)
00973 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoServiceAck,   Q931_TFLAG_AUTO_SERVICE_ACK)
00974 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoConnectAck,   Q931_TFLAG_AUTO_CONNECT_ACK)
00975 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetAutoRestartAck,   Q931_TFLAG_AUTO_RESTART_ACK)
00976 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetStatusEnquiry,    Q931_TFLAG_STATUS_ENQUIRY)
00977 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreUnknownMsg, Q931_TFLAG_IGNORE_UNKNOWN_MSG)
00978 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreUnknownIEs, Q931_TFLAG_IGNORE_UNKNOWN_IE)
00979 Q931_TRUNK_FLAG_SET_FUNC(Q931TrunkSetIgnoreIllegalIEs, Q931_TFLAG_IGNORE_ILLEGAL_IE)
00980 
00981 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoSetupAck,     Q931_TFLAG_AUTO_SETUP_ACK)
00982 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoServiceAck,   Q931_TFLAG_AUTO_SERVICE_ACK)
00983 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoConnectAck,   Q931_TFLAG_AUTO_CONNECT_ACK)
00984 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetAutoRestartAck,   Q931_TFLAG_AUTO_RESTART_ACK)
00985 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetStatusEnquiry,    Q931_TFLAG_STATUS_ENQUIRY)
00986 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreUnknownMsg, Q931_TFLAG_IGNORE_UNKNOWN_MSG)
00987 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreUnknownIEs, Q931_TFLAG_IGNORE_UNKNOWN_IE)
00988 Q931_TRUNK_FLAG_GET_FUNC(Q931TrunkGetIgnoreIllegalIEs, Q931_TFLAG_IGNORE_ILLEGAL_IE)
00989 
00990 
00997 Q931_API void Q931TrunkSetRelaxedMode(Q931_TrunkInfo_t *trunk, L3BOOL enable)
00998 {
00999         int flags = (Q931_TFLAG_IGNORE_UNKNOWN_MSG | Q931_TFLAG_IGNORE_UNKNOWN_IE | Q931_TFLAG_IGNORE_ILLEGAL_IE);
01000         assert(trunk);
01001 
01002         if (enable) {
01003                 Q931TrunkSetFlag(trunk, flags);
01004         } else {
01005                 Q931TrunkClearFlag(trunk, flags);
01006         }
01007 }
01008 
01009 
01020 L3INT Q931Proc(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, q931_msg_from_t from)
01021 {
01022         q931proc_func_t *func = Q931DialectGetMesProc(trunk->Dialect, msg->MesType);
01023 
01024         /* check if message is valid in this state */
01025         if (!Q931DialectIsEventLegal(trunk->Dialect, Q931CallGetState(call), msg->MesType, from))
01026                 return Q931E_UNEXPECTED_MESSAGE;
01027 
01028         if (func) {
01029                 L3INT retval = func(trunk, call, msg, from);
01030 
01031                 switch (retval) {
01032                 case Q931E_UNEXPECTED_MESSAGE:
01033                         {
01034                                 Q931Log(trunk, Q931_LOG_ERROR, "Unexpected message 0x%02x for call 0x%04x in state '%s'\n",
01035                                                 msg->MesType,
01036                                                 Q931CallGetCRV(call),
01037                                                 Q931CallGetStateName(call));
01038                         }
01039                         break;
01040                 default:
01041                         break;
01042                 }
01043                 return retval;
01044         }
01045 
01046         /* Ignore unknown message? */
01047         if (Q931TrunkIsSetFlag(trunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
01048                 return Q931E_NO_ERROR;
01049         }
01050 
01051         func = Q931DialectGetUnknownMesProc(trunk->Dialect);
01052         if (func) {
01053                 return func(trunk, call, msg, from);
01054         }
01055         return Q931E_INTERNAL;
01056 }
01057 
01058 
01069 L3INT Q931ProcInvalid(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, q931_msg_from_t from)
01070 {
01071         q931proc_func_t *func = Q931DialectGetInvalidMesProc(trunk->Dialect);
01072 
01073         if (func) {
01074                 return func(trunk, call, msg, from);
01075         }
01076         return Q931E_INTERNAL;
01077 }
01078 
01079 
01093 L3INT Q931Umes(Q931_TrunkInfo_t *trunk, L3UCHAR id, L3UCHAR *IBuf, Q931mes_Generic *OBuf, L3INT IOff, L3INT Size, struct Q931MesgErrors *errs)
01094 {
01095         q931umes_func_t *func = Q931DialectGetUmesProc(trunk->Dialect, id);
01096 
01097         if (func) {
01098                 return func(trunk, IBuf, OBuf, IOff, Size, errs);
01099         }
01100 
01101         /* unknown message */
01102 /*      Q931MesgErrorsAdd(errs, Q931_MSGE_UNKNOWN); */
01103 
01104         /* Ignore unknown message? */
01105         if (Q931TrunkIsSetFlag(trunk, Q931_TFLAG_IGNORE_UNKNOWN_MSG)) {
01106                 return Q931E_NO_ERROR;
01107         }
01108 
01109         return Q931E_INTERNAL;
01110 }
01111 
01112 
01125 L3INT Q931Pmes(Q931_TrunkInfo_t *trunk, L3UCHAR id, Q931mes_Generic *IBuf, L3INT ISize, L3UCHAR *OBuf, L3INT *OSize)
01126 {
01127         q931pmes_func_t *func = Q931DialectGetPmesProc(trunk->Dialect, id);
01128 
01129         if (func) {
01130                 return func(trunk, IBuf, ISize, OBuf, OSize);
01131         }
01132         return Q931E_INTERNAL;
01133 }
01134 
01135 
01149 L3INT Q931Uie(Q931_TrunkInfo_t *trunk, L3UCHAR id, Q931mes_Generic *pMes, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *IOff, L3INT *OOff)
01150 {
01151         q931uie_func_t *func = Q931DialectGetUieProc(trunk->Dialect, id);
01152 
01153         if (func) {
01154                 return func(trunk, pMes, IBuf, OBuf, IOff, OOff);
01155         }
01156         return Q931E_INTERNAL;
01157 }
01158 
01159 
01171 L3INT Q931Pie(Q931_TrunkInfo_t *trunk, L3UCHAR id, L3UCHAR *IBuf, L3UCHAR *OBuf, L3INT *Octet)
01172 {
01173         q931pie_func_t *func = Q931DialectGetPieProc(trunk->Dialect, id);
01174 
01175         if (func) {
01176                 return func(trunk, IBuf, OBuf, Octet);
01177         }
01178         return Q931E_INTERNAL;
01179 }
01180 
01189 L3INT Q931Die(Q931_TrunkInfo_t *trunk, Q931ie_Generic *ie, struct strstream *ostream)
01190 {
01191         q931die_func_t *func = Q931DialectGetDieProc(trunk->Dialect, ie->IEId);
01192 
01193         if (func) {
01194                 return func(trunk, ie, ostream);
01195         }
01196         return Q931E_INTERNAL;
01197 }
01198 
01207 L3BOOL Q931UieIsNull(Q931_TrunkInfo_t *trunk, L3UCHAR id)
01208 {
01209         return (!Q931DialectGetUieProc(trunk->Dialect, id));
01210 }
01211 
01220 L3BOOL Q931PieIsNull(Q931_TrunkInfo_t *trunk, L3UCHAR id)
01221 {
01222         return (!Q931DialectGetPieProc(trunk->Dialect, id));
01223 }
01224 
01233 L3BOOL Q931DieIsNull(Q931_TrunkInfo_t *trunk, L3UCHAR id)
01234 {
01235         return (!Q931DialectGetDieProc(trunk->Dialect, id));
01236 }
01237 
01247 L3INT Q931Timeout(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, L3UCHAR timer)
01248 {
01249         q931timeout_func_t *func = Q931DialectGetTimerProc(trunk->Dialect, timer);
01250 
01251         if (func) {
01252                 return func(trunk, call);
01253         }
01254         return Q931E_INTERNAL;
01255 }
01256 
01257 
01268 L3INT Q931ProcUnknownMessage(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, q931_msg_from_t from)
01269 {
01270         Q931Log(trunk, Q931_LOG_NOTICE, "Unknown message %#02hhx received\n", msg->MesType);
01271         return Q931E_NO_ERROR;
01272 }
01273 
01284 L3INT Q931ProcUnexpectedMessage(Q931_TrunkInfo_t *trunk, struct Q931_Call *call, Q931mes_Generic *msg, q931_msg_from_t from)
01285 {
01286         Q931Log(trunk, Q931_LOG_NOTICE, "Unexpected/Invalid message %#02hhx received\n", msg->MesType);
01287         return Q931E_NO_ERROR;
01288 }
01289