libisdn
Q931call.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   FileName:             Q931call.c
00004 
00005   Contents:             call related api functions.
00006                         See q931.h for description.
00007 
00008   License/Copyright:
00009 
00010   Copyright (c) 2008, Stefan Knoblich, axsentis GmbH. All rights reserved.
00011   email: s.knoblich@axsentis.de
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 axsentis GmbH 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 <string.h>
00041 #include <assert.h>
00042 
00043 #include "Q931.h"
00044 #include "Q931priv.h"
00045 
00046 /*
00047  * State handling
00048  */
00049 void Q931CallSetState(struct Q931_Call *call, const L3INT state)
00050 {
00051         assert(call);
00052 
00053         if (Q931CallIsGlobal(call))
00054                 return;
00055 
00056         Q931Log(Q931CallGetTrunk(call), Q931_LOG_DEBUG, "Call going from state %d -> %d\n",
00057                                          (call->State & 0xff), (state & 0xff));
00058 
00059         call->State = state;
00060 }
00061 
00062 Q931_API L3INT Q931CallGetState(const struct Q931_Call *call)
00063 {
00064         assert(call);
00065 
00066         return call->State;
00067 }
00068 
00069 
00070 /*
00071  * Allocate / Destroy call handle
00072  */
00073 static struct Q931_Call *Q931FindFreeCall(const Q931_TrunkInfo_t *trunk)
00074 {
00075         struct Q931_Call *call = NULL;
00076         L3INT i;
00077 
00078         /* call[0] reserved for global CRV */
00079         for (i = 1; i < Q931MAXCALLPERTRUNK; i++) {
00080                 if (!trunk->call[i].InUse) {
00081                         call = (struct Q931_Call *)&trunk->call[i];
00082                         break;
00083                 }
00084         }
00085         return call;
00086 }
00087 
00097 struct Q931_Call *Q931CallNew(Q931_TrunkInfo_t *trunk)
00098 {
00099         struct Q931_Call *call = NULL;
00100         L3INT crv = 0;
00101 
00102         /* find free call handle */
00103         call = Q931FindFreeCall(trunk);
00104         if (!call) {
00105                 /* No free call handle found */
00106                 return NULL;
00107         }
00108         call->InUse = 1;
00109 
00110         Q931Log(trunk, Q931_LOG_INFO, "Found a free call, trying to find a new CRV\n");
00111 
00112         /* get new call reference */
00113         crv = Q931GetUniqueCRV(trunk);
00114         if (!crv) {
00115                 goto crverror;
00116         }
00117 
00118         Q931Log(trunk, Q931_LOG_INFO, "Using crv %d for new call\n", crv);
00119 
00120         /* set parameters & state */
00121         call->Direction = Q931_DIRECTION_OUTBOUND;
00122         call->CRV   = crv;
00123         call->Trunk = trunk;            /* yah, sucks, but makes the api easier */
00124 
00125         Q931CallSetState(call, (trunk->NetUser == Q931_NT) ? Q931_N0 : Q931_U0);
00126 
00127         return call;
00128 
00129 crverror:
00130         call->InUse = 0;
00131         return NULL;
00132 }
00133 
00134 struct Q931_Call *Q931CallNewIncoming(Q931_TrunkInfo_t *trunk, const L3INT crv)
00135 {
00136         struct Q931_Call *call = NULL;
00137 
00138         /* find free call handle */
00139         call = Q931FindFreeCall(trunk);
00140         if (!call) {
00141                 /* No free call handle found */
00142                 return NULL;
00143         }
00144         call->InUse = 1;
00145 
00146         /* set parameters & state */
00147         call->Direction = Q931_DIRECTION_INBOUND;
00148         call->CRV   = crv;
00149         call->Trunk = trunk;            /* yah, sucks, but makes the api easier */
00150 
00151         Q931CallSetState(call, (trunk->NetUser == Q931_NT) ? Q931_N0 : Q931_U0);
00152 
00153         return call;
00154 }
00155 
00156 
00165 L3INT Q931CallRelease(struct Q931_Call *call)
00166 {
00167         L3INT state;
00168 
00169         assert(call);
00170 
00171         if (Q931CallIsGlobal(call))
00172                 return 0;
00173 
00174         /* add some sanity checks here */
00175         state = Q931CallGetState(call);
00176 
00177         if (state != Q931_U0 || state != Q931_N0) {
00178                 /* error */
00179                 return -1;
00180         }
00181 
00182         /* reset completely */
00183         memset(call, 0, sizeof(struct Q931_Call));
00184 
00185         return 0;
00186 }
00187 
00188 
00189 /*
00190  * Accessor functions for private data
00191  */
00192 Q931_API void Q931CallSetPrivate(struct Q931_Call *call, const void *priv)
00193 {
00194         assert(call);
00195 
00196         call->pvt = (void *)priv;
00197 }
00198 
00199 Q931_API void * Q931CallGetPrivate(const struct Q931_Call *call)
00200 {
00201         assert(call);
00202 
00203         return call->pvt;
00204 }
00205 
00206 Q931_API Q931_TrunkInfo_t * Q931CallGetTrunk(const struct Q931_Call *call)
00207 {
00208         assert(call);
00209         assert(call->Trunk);
00210 
00211         return call->Trunk;
00212 }
00213 
00214 Q931_API L3INT Q931CallGetCRV(const struct Q931_Call *call)
00215 {
00216         assert(call);
00217 
00218         return call->CRV;
00219 }
00220 
00221 Q931_API L3INT Q931CallGetDirection(const struct Q931_Call *call)
00222 {
00223         assert(call);
00224 
00225         return call->Direction;
00226 }
00227 
00228 Q931_API L3BOOL Q931CallIsOutgoing(const struct Q931_Call *call)
00229 {
00230         assert(call);
00231 
00232         return call->Direction == Q931_DIRECTION_OUTBOUND;
00233 }
00234 
00235 
00236 /*
00237  *
00238  */
00239 struct Q931CallStateName
00240 {
00241         L3INT id;
00242         const L3CHAR *name;
00243 
00244 } Q931CallStateNames[] = {
00245         { Q931_U0, "Null" },
00246         { Q931_U1, "Call initiated" },
00247         { Q931_U2, "Overlap sending" },
00248         { Q931_U3, "Outgoing call proceeding" },
00249         { Q931_U4, "Call delivered" },
00250         { Q931_U6, "Call present" },
00251         { Q931_U7, "Call received" },
00252         { Q931_U8, "Connect request" },
00253         { Q931_U9, "Incoming call proceeding" },
00254         { Q931_U10, "Active" },
00255         { Q931_U11, "Disconnect request" },
00256         { Q931_U12, "Disconnect indication" },
00257         { Q931_U15, "Suspend request" },
00258         { Q931_U17, "Resume request" },
00259         { Q931_U19, "Release request" },
00260         { Q931_U25, "Overlap receiving" },
00261 
00262         { Q931_N0, "Null" },
00263         { Q931_N1, "Call initiated" },
00264         { Q931_N2, "Overlap sending" },
00265         { Q931_N3, "Outgoing call proceeding" },
00266         { Q931_N4, "Call delivered" },
00267         { Q931_N6, "Call present" },
00268         { Q931_N7, "Call received" },
00269         { Q931_N8, "Connect request" },
00270         { Q931_N9, "Incoming call proceeding" },
00271         { Q931_N10, "Active" },
00272         { Q931_N11, "Disconnect request" },
00273         { Q931_N12, "Disconnect indication" },
00274         { Q931_N15, "Suspend request" },
00275         { Q931_N17, "Resume request" },
00276         { Q931_N19, "Release request" },
00277         { Q931_N22, "N22" },                    /* whatever it's name is... */
00278         { Q931_N25, "Overlap receiving" },
00279 
00280         { 0, NULL }
00281 };
00282 
00283 Q931_API const char * Q931CallGetStateName(const struct Q931_Call *call)
00284 {
00285         struct Q931CallStateName *ptr = Q931CallStateNames;
00286         L3INT state;
00287 
00288         assert(call);
00289 
00290         state = Q931CallGetState(call);
00291 
00292         while (ptr->name) {
00293                 if (ptr->id == state) {
00294                         return ptr->name;
00295                 }
00296                 ptr++;
00297         }
00298         return "Unknown/Invalid";
00299 }
00300 
00301 struct Q931CallEventName
00302 {
00303         L3INT id;
00304         const L3CHAR *name;
00305 
00306 } Q931CallEventNames[] = {
00307         { Q931_EVENT_SETUP_INDICATION,          "Setup indication" },
00308         { Q931_EVENT_SETUP_CONFIRM,             "Setup confirm" },
00309         { Q931_EVENT_SETUP_COMPLETE_INDICATION, "Setup complete indication" },
00310         { Q931_EVENT_MORE_INFO_INDICATION,      "More information indication" },
00311         { Q931_EVENT_REJECT_INDICATION,         "Reject indication" },
00312         { Q931_EVENT_PROCEEDING_INDICATION,     "Proceeding indication" },
00313         { Q931_EVENT_ALERTING_INDICATION,       "Alerting indication" },
00314         { Q931_EVENT_PROGRESS_INDICATION,       "Progress indication" },
00315         { Q931_EVENT_NOTIFY_INDICATION,         "Notify indication" },
00316         { Q931_EVENT_RELEASE_INDICATION,        "Release indication" },
00317         { Q931_EVENT_SUSPEND_CONFIRM,           "Suspend confirm" },
00318         { Q931_EVENT_RESUME_CONFIRM,            "Resume confirm" },
00319         { Q931_EVENT_DISCONNECT_INDICATION,     "Disconnect indication" },
00320         { Q931_EVENT_INFORMATION_INDICATION,    "Information indication" },
00321         { Q931_EVENT_STATUS_INDICATION,         "Status indication" },
00322         { Q931_EVENT_RESTART_CONFIRM,           "Restart confirm" },
00323 
00324         /* Requests (L4 -> L3) (?) */
00325         { Q931_EVENT_SETUP_RESPONSE,      "Setup response" },
00326         { Q931_EVENT_REJECT_REQUEST,      "Reject request" },
00327         { Q931_EVENT_INFORMATION_REQUEST, "Information request" },
00328         { Q931_EVENT_ALERTING_REQUEST,    "Alerting request" },
00329         { Q931_EVENT_PROGRESS_REQUEST,    "Progress request" },
00330         { Q931_EVENT_PROCEEDING_REQUEST,  "Proceeding request" },
00331         { Q931_EVENT_NOTIFY_REQUEST,      "Notify request" },
00332         { Q931_EVENT_SUSPEND_REQUEST,     "Suspend request" },
00333         { Q931_EVENT_DISCONNECT_REQUEST,  "Disconnect request" },
00334         { Q931_EVENT_RESTART_REQUEST,     "Restart request" },
00335 
00336         /* misc events (L2/L3 -> L4) */
00337         { Q931_EVENT_TIMEOUT_INDICATION,    "Timeout indication" },
00338         { Q931_EVENT_DL_FAILURE_INDICATION, "Datalink Layer failure indication" },
00339 
00340         { 0, NULL },
00341 };
00342 
00343 Q931_API const char * Q931CallGetEventName(const L3INT event)
00344 {
00345         struct Q931CallEventName *ptr = Q931CallEventNames;
00346 
00347         while (ptr->name) {
00348                 if (ptr->id == event) {
00349                         return ptr->name;
00350                 }
00351                 ptr++;
00352         }
00353         return "Unknown";
00354 }
00355 
00356 struct Q931CallTimerName
00357 {
00358         L3INT id;
00359         const L3CHAR *name;
00360 
00361 } Q931CallTimerNames[] = {
00362         { Q931_TIMER_T300, "T300" },
00363         { Q931_TIMER_T301, "T301" },
00364         { Q931_TIMER_T302, "T302" },
00365         { Q931_TIMER_T303, "T303" },
00366         { Q931_TIMER_T304, "T304" },
00367         { Q931_TIMER_T305, "T305" },
00368         { Q931_TIMER_T306, "T306" },
00369         { Q931_TIMER_T307, "T307" },
00370         { Q931_TIMER_T308, "T308" },
00371         { Q931_TIMER_T309, "T309" },
00372         { Q931_TIMER_T310, "T310" },
00373         { Q931_TIMER_T311, "T311" },
00374         { Q931_TIMER_T312, "T312" },
00375         { Q931_TIMER_T313, "T313" },
00376         { Q931_TIMER_T314, "T314" },
00377         { Q931_TIMER_T315, "T315" },
00378         { Q931_TIMER_T316, "T316" },
00379         { Q931_TIMER_T317, "T317" },
00380         { Q931_TIMER_T318, "T318" },
00381         { Q931_TIMER_T319, "T319" },
00382         { Q931_TIMER_T320, "T320" },
00383         { Q931_TIMER_T321, "T321" },
00384         { Q931_TIMER_T322, "T322" },
00385 
00386         { 0, NULL }
00387 };
00388 
00389 Q931_API const char * Q931CallGetTimerName(const L3USHORT timer)
00390 {
00391         struct Q931CallTimerName *ptr = Q931CallTimerNames;
00392 
00393         while (ptr->name) {
00394                 if (ptr->id == timer) {
00395                         return ptr->name;
00396                 }
00397                 ptr++;
00398         }
00399         return "Unknown";
00400 }
00401 
00402 
00403 
00404 Q931_API struct Q931_Call * Q931GetCallByCRV(const Q931_TrunkInfo_t *trunk, const L3INT crv)
00405 {
00406         struct Q931_Call *call = NULL;
00407         int i = 0;
00408 
00409         assert(trunk);
00410 
00411         if (!crv) {
00412                 /* global call context */
00413                 return (struct Q931_Call *)&trunk->call[0];
00414         }
00415 
00416         /* call[0] reserved for global CRV */
00417         for (i = 1; i < Q931MAXCALLPERTRUNK; i++) {
00418                 call = (struct Q931_Call *)&trunk->call[i];
00419 
00420                 if (call->InUse && call->CRV == crv) {
00421                         return call;
00422                 }
00423         }
00424         return NULL;
00425 }
00426 
00427 struct Q931_Call *Q931GetCallByIndex(const Q931_TrunkInfo_t *trunk, const L3INT idx)
00428 {
00429         struct Q931_Call *call = NULL;
00430 
00431         assert(trunk);
00432 
00433         call = (struct Q931_Call *)&trunk->call[idx];
00434         if (call->InUse) {
00435                 return call;
00436         }
00437         return NULL;
00438 }
00439 
00440 Q931_API struct Q931_Call * Q931GetGlobalCall(const Q931_TrunkInfo_t *trunk)
00441 {
00442         return (struct Q931_Call *)&trunk->call[0];
00443 }
00444 
00445 Q931_API L3BOOL Q931CallIsGlobal(const struct Q931_Call *call)
00446 {
00447         return (call->CRV == 0);
00448 }
00449 
00456 void Q931CallStartTimer(struct Q931_Call *call, L3USHORT timer)
00457 {
00458         Q931_TrunkInfo_t *trunk = NULL;
00459         L3ULONG duration;
00460 
00461         assert(call);
00462 
00463         trunk = Q931CallGetTrunk(call);
00464         assert(trunk);
00465 
00466         duration = Q931DialectGetTimeout(trunk->Dialect, timer);
00467 
00468         if (duration) {
00469                 call->Timer    = Q931GetTime() + duration;
00470                 call->TimerID  = timer;
00471                 call->TimerCnt = 0;
00472 
00473                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Starting timer %d (timeout: %d ms) for call %d [0x%x]\n", timer, duration, Q931CallGetCRV(call), Q931CallGetCRV(call));
00474         }
00475 }
00476 
00484 void Q931CallRestartTimer(struct Q931_Call *call, L3USHORT timer)
00485 {
00486         Q931_TrunkInfo_t *trunk = NULL;
00487         L3ULONG duration;
00488 
00489         assert(call);
00490 
00491         trunk = Q931CallGetTrunk(call);
00492         assert(trunk);
00493 
00494         duration = Q931DialectGetTimeout(trunk->Dialect, timer);
00495 
00496         if (duration) {
00497                 call->Timer    = Q931GetTime() + duration;
00498                 call->TimerID  = timer;
00499 
00500                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Restarting timer %d (timeout: %d ms) for call %d [0x%x]\n", timer, duration, Q931CallGetCRV(call), Q931CallGetCRV(call));
00501         }
00502 }
00503 
00510 void Q931CallStopTimer(struct Q931_Call *call, L3USHORT timer)
00511 {
00512         assert(call);
00513 
00514         if (call->TimerID == timer) {
00515                 call->TimerID = Q931_TIMER_NONE;
00516 
00517                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Stopping timer %d for call %d [0x%x]\n", timer, Q931CallGetCRV(call), Q931CallGetCRV(call));
00518         }
00519 }
00520 
00526 void Q931CallStopAllTimers(struct Q931_Call *call)
00527 {
00528         assert(call);
00529 
00530         call->TimerID = Q931_TIMER_NONE;
00531 
00532         Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Stopped all timers for call %d [0x%x]\n", Q931CallGetCRV(call), Q931CallGetCRV(call));
00533 }
00534 
00541 Q931_API L3USHORT Q931CallGetTimerID(const struct Q931_Call *call)
00542 {
00543         return call->TimerID;
00544 }
00545 
00554 Q931_API L3UCHAR Q931CallGetTimerExpireCount(const struct Q931_Call *call)
00555 {
00556         return call->TimerCnt;
00557 }
00558 
00559 
00566 void Q931CallIncrementTimerExpireCount(struct Q931_Call *call)
00567 {
00568         call->TimerCnt++;
00569 }
00570 
00571 /*
00572  * Event
00573  */
00574 
00581 Q931_API void Q931SetCallEventCB(Q931_TrunkInfo_t *trunk, const Q931CallEventCB_t cb, const void *priv)
00582 {
00583         assert(trunk);
00584         assert(cb);
00585 
00586         trunk->CallEventCBProc = (Q931CallEventCB_t)cb;
00587         trunk->PrivateDataCallEventCB = (void *)priv;
00588 }
00589 
00595 void Q931CallSendEvent(const struct Q931_Call *call, const struct Q931_CallEvent *event)
00596 {
00597         Q931_TrunkInfo_t *trunk = Q931CallGetTrunk(call);
00598 
00599         assert(trunk);
00600         assert(event);
00601 
00602         if (!event || event->id == Q931_EVENT_NONE || event->type == Q931_EVENT_TYPE_NONE)
00603                 return;
00604 
00605         if (trunk->CallEventCBProc) {
00606                 Q931Log(trunk, Q931_LOG_DEBUG, "Sending call event to Layer4 [call: %d, id: %d, type: %d]\n", Q931CallGetCRV(call), event->id, event->type);
00607 
00608                 trunk->CallEventCBProc((struct Q931_Call *)call, (struct Q931_CallEvent *)event, trunk->PrivateDataCallEventCB);
00609         }
00610 }
00611 
00615 void Q931CallInitEvent(struct Q931_CallEvent *event)
00616 {
00617         memset(event, 0, sizeof(struct Q931_CallEvent));
00618 }
00619 
00620 /************************************************************************************************
00621  *  V2 - Enqueue events in the call handle and send them to layer 4, after processing everything
00622  ************************************************************************************************/
00623 
00627 struct Q931_CallEvent *Q931CallNewEvent(struct Q931_Call *call)
00628 {
00629         assert(call);
00630 
00631         if (call->numevents == Q931_CALL_MAX_EVENTS)
00632                 return NULL;
00633 
00634         return &call->events[call->numevents];
00635 }
00636 
00641 void Q931CallQueueEvent(struct Q931_Call *call, struct Q931_CallEvent *event)
00642 {
00643         assert(call);
00644 
00645         call->numevents++;
00646 }
00647 
00651 void Q931CallFlushEvents(struct Q931_Call *call)
00652 {
00653         assert(call);
00654 
00655         memset(call->events, 0, Q931_CALL_MAX_EVENTS * sizeof(struct Q931_CallEvent));
00656         call->numevents = 0;
00657 }
00658 
00662 void Q931CallSendQueuedEvents(struct Q931_Call *call)
00663 {
00664         int i;
00665 
00666         assert(call);
00667 
00668         for (i = 0; i < call->numevents; i++) {
00669                 Q931CallSendEvent(call, &call->events[i]);
00670         }
00671 
00672         Q931CallFlushEvents(call);
00673 }
00674 
00678 Q931_API L3INT Q931CallEventGetType(const struct Q931_CallEvent *event)
00679 {
00680         return event->type;
00681 }
00682 
00686 Q931_API L3INT Q931CallEventGetId(const struct Q931_CallEvent *event)
00687 {
00688         return event->id;
00689 }
00690 
00695 Q931_API void * Q931CallEventGetData(const struct Q931_CallEvent *event)
00696 {
00697         switch (event->type) {
00698         case Q931_EVENT_TYPE_TIMER:
00699                 return (void *)&event->data.timer;
00700 
00701         case Q931_EVENT_TYPE_MESSAGE:
00702                 return (void *)&event->data.message;
00703 
00704         default:
00705                 return NULL;
00706         }
00707 }
00708 
00709 
00710 /************************************************************************************************
00711  * Debug information
00712  ************************************************************************************************/
00713 
00714 #include <stdio.h>
00715 
00716 #define TMP_BUFSIZE     4096
00717 #define TMP_PUTS(fmt) \
00718         strncat(tmp + offset, fmt, size - offset - 1);  \
00719         offset += strlen(tmp + offset);
00720 #define TMP_APPEND(fmt, args...) \
00721         offset += snprintf(tmp + offset, size - offset, fmt, ##args);
00722 
00726 static L3INT __Q931CallDumpInformation(const struct Q931_Call *call, char *tmp, const int size)
00727 {
00728         int offset = 0;
00729         int x;
00730 
00731         TMP_APPEND("\tGlobal call:   %s\n",      Q931CallIsGlobal(call) ? "Yes (CRV: 0)" : "No");
00732         TMP_APPEND("\tDirection:     %s\n",      Q931CallIsOutgoing(call) ? "Outbound" : "Inbound");
00733         TMP_APPEND("\tState:         %d '%s'\n", Q931CallGetState(call), Q931CallGetStateName(call));
00734         TMP_APPEND("\tL4 User data:  %p\n",      Q931CallGetPrivate(call));
00735 
00736         /* Timer information */
00737         if (call->TimerID != Q931_TIMER_NONE) {
00738                 TMP_APPEND("\tTimer:         '%s', time left: %5lu ms, expired: %d time(s)\n",
00739                                 Q931CallGetTimerName(call->TimerID), (call->Timer - Q931GetTime()),
00740                                 Q931CallGetTimerExpireCount(call));
00741         }
00742 
00743         /* Dump events queued */
00744         TMP_APPEND("\tEvents queued: %d\n", call->numevents);
00745 
00746         for (x = 0; x < call->numevents; x++) {
00747                 const struct Q931_CallEvent *event = &call->events[x];
00748 
00749                 TMP_APPEND("\t\t<%2d> %s\n", x, Q931CallGetEventName(event->id));
00750         }
00751 
00752         return offset;
00753 }
00754 
00760 Q931_API L3INT Q931CallDump(const struct Q931_Call *call)
00761 {
00762         Q931_TrunkInfo_t *trunk = Q931CallGetTrunk(call);
00763         char tmp[TMP_BUFSIZE >> 2] = { 0 };
00764         int offset = 0;
00765         int size   = sizeof(tmp);
00766 
00767         /* header */
00768         TMP_PUTS("Call Information:\n");
00769         TMP_APPEND("============================== Call: %3d (%#02x) =============================\n", Q931CallGetCRV(call), Q931CallGetCRV(call));
00770 
00771         offset += __Q931CallDumpInformation(call, tmp + offset, size - offset);
00772 
00773         /* footer */
00774         TMP_PUTS("---------------------------------------------------------------------------------\n");
00775 
00776         Q931Log(trunk, Q931_LOG_DEBUG, "%s\n", tmp);
00777         return Q931E_NO_ERROR;
00778 }
00779 
00785 Q931_API L3INT Q931DumpAllCalls(const Q931_TrunkInfo_t *trunk)
00786 {
00787         struct Q931_Call *call;
00788         char tmp[TMP_BUFSIZE] = { 0 };
00789         int offset = 0;
00790         int count  = 0;
00791         int size   = sizeof(tmp);
00792         int x;
00793 
00794         /* header */
00795         TMP_PUTS("Information of all active calls:\n");
00796         TMP_PUTS("==================================== Calldump ===================================\n");
00797 
00798         for (x = 0; x < Q931MAXCALLPERTRUNK; x++) {
00799                 if (!(call = Q931GetCallByIndex(trunk, x))) {
00800                         continue;
00801                 }
00802 
00803                 /* skip inactive calls */
00804                 if ((Q931CallGetState(call) & 0xff) == Q931_U0) {
00805                         continue;
00806                 }
00807 
00808                 /* per-call header */
00809                 TMP_APPEND("* CRV: %3d (%#02x)\n", Q931CallGetCRV(call), Q931CallGetCRV(call));
00810 
00811                 /* Add call's information */
00812                 offset += __Q931CallDumpInformation(call, tmp + offset, size - offset);
00813                 count++;
00814         }
00815 
00816         /* footer */
00817         TMP_APPEND("-----------------------------------------------------------------[ %2d call(s) ]--\n", count);
00818 
00819         Q931Log(trunk, Q931_LOG_DEBUG, "%s\n", tmp);
00820         return Q931E_NO_ERROR;
00821 }
00822