libisdn
|
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