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 <assert.h>
00040 
00041 #define Q931PRIVATE
00042 #include "Q931.h"
00043 #include "memory.h"
00044 
00045 /*
00046  * State handling
00047  */
00048 void Q931CallSetState(struct Q931_Call *call, const L3INT state)
00049 {
00050         assert(call);
00051 
00052         if (Q931CallIsGlobal(call))
00053                 return;
00054 
00055         Q931Log(Q931CallGetTrunk(call), Q931_LOG_DEBUG, "Call going from state %d -> %d\n",
00056                                          (call->State & 0xff), (state & 0xff));
00057 
00058         call->State = state;
00059 }
00060 
00061 L3INT Q931CallGetState(const struct Q931_Call *call)
00062 {
00063         assert(call);
00064 
00065         return call->State;
00066 }
00067 
00068 
00069 /*
00070  * Allocate / Destroy call handle
00071  */
00072 static struct Q931_Call *Q931FindFreeCall(const Q931_TrunkInfo_t *trunk)
00073 {
00074         struct Q931_Call *call = NULL;
00075         L3INT i;
00076 
00077         /* call[0] reserved for global CRV */
00078         for (i = 1; i < Q931MAXCALLPERTRUNK; i++) {
00079                 if (!trunk->call[i].InUse) {
00080                         call = (struct Q931_Call *)&trunk->call[i];
00081                         break;
00082                 }
00083         }
00084         return call;
00085 }
00086 
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 void Q931CallSetPrivate(struct Q931_Call *call, const void *priv)
00193 {
00194         assert(call);
00195 
00196         call->pvt = (void *)priv;
00197 }
00198 
00199 void *Q931CallGetPrivate(const struct Q931_Call *call)
00200 {
00201         assert(call);
00202 
00203         return call->pvt;
00204 }
00205 
00206 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 L3INT Q931CallGetCRV(const struct Q931_Call *call)
00215 {
00216         assert(call);
00217 
00218         return call->CRV;
00219 }
00220 
00221 L3INT Q931CallGetDirection(const struct Q931_Call *call)
00222 {
00223         assert(call);
00224 
00225         return call->Direction;
00226 }
00227 
00228 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 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 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 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 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 
00438         return NULL;
00439 }
00440 
00441 struct Q931_Call *Q931GetGlobalCall(const Q931_TrunkInfo_t *trunk)
00442 {
00443         return (struct Q931_Call *)&trunk->call[0];
00444 }
00445 
00446 L3BOOL Q931CallIsGlobal(const struct Q931_Call *call)
00447 {
00448         return (call->CRV == 0);
00449 }
00450 
00457 void Q931CallDump(const struct Q931_Call *call)
00458 {
00459         assert(call);
00460         assert(call->InUse);
00461 
00462         /* TODO */
00463         Q931Log(Q931CallGetTrunk(call), Q931_LOG_DEBUG,
00464                                 "Call %#x, direction: %s, state: %d (\"%s\")\n\tTimer active: %s",
00465                                 call->CRV,
00466                                 (call->Direction) ? "Outbound" : "Inbound",
00467                                 Q931CallGetState(call),
00468                                 Q931CallGetStateName(call),
00469                                 (call->TimerID) ? Q931CallGetTimerName(call->TimerID) : "None");
00470 }
00471 
00472 
00479 void Q931CallStartTimer(struct Q931_Call *call, L3USHORT timer)
00480 {
00481         Q931_TrunkInfo_t *trunk = NULL;
00482         L3ULONG duration;
00483 
00484         assert(call);
00485 
00486         trunk = Q931CallGetTrunk(call);
00487         assert(trunk);
00488 
00489         duration = Q931DialectGetTimeout(trunk->Dialect, timer);
00490 
00491         if (duration) {
00492                 call->Timer    = Q931GetTime() + duration;
00493                 call->TimerID  = timer;
00494                 call->TimerCnt = 0;
00495 
00496                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Starting timer %d (timeout: %d ms) for call %d [0x%x]\n", timer, duration, Q931CallGetCRV(call), Q931CallGetCRV(call));
00497         }
00498 }
00499 
00507 void Q931CallRestartTimer(struct Q931_Call *call, L3USHORT timer)
00508 {
00509         Q931_TrunkInfo_t *trunk = NULL;
00510         L3ULONG duration;
00511 
00512         assert(call);
00513 
00514         trunk = Q931CallGetTrunk(call);
00515         assert(trunk);
00516 
00517         duration = Q931DialectGetTimeout(trunk->Dialect, timer);
00518 
00519         if (duration) {
00520                 call->Timer    = Q931GetTime() + duration;
00521                 call->TimerID  = timer;
00522 
00523                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Restarting timer %d (timeout: %d ms) for call %d [0x%x]\n", timer, duration, Q931CallGetCRV(call), Q931CallGetCRV(call));
00524         }
00525 }
00526 
00533 void Q931CallStopTimer(struct Q931_Call *call, L3USHORT timer)
00534 {
00535         assert(call);
00536 
00537         if (call->TimerID == timer) {
00538                 call->TimerID = Q931_TIMER_NONE;
00539 
00540                 Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Stopping timer %d for call %d [0x%x]\n", timer, Q931CallGetCRV(call), Q931CallGetCRV(call));
00541         }
00542 }
00543 
00549 void Q931CallStopAllTimers(struct Q931_Call *call)
00550 {
00551         assert(call);
00552 
00553         call->TimerID = Q931_TIMER_NONE;
00554 
00555         Q931Log(Q931CallGetTrunk(call), Q931_LOG_NOTICE, "Stopped all timers for call %d [0x%x]\n", Q931CallGetCRV(call), Q931CallGetCRV(call));
00556 }
00557 
00564 L3USHORT Q931CallGetTimerID(const struct Q931_Call *call)
00565 {
00566         return call->TimerID;
00567 }
00568 
00577 L3UCHAR Q931CallGetTimerExpireCount(const struct Q931_Call *call)
00578 {
00579         return call->TimerCnt;
00580 }
00581 
00582 
00589 void Q931CallIncrementTimerExpireCount(struct Q931_Call *call)
00590 {
00591         call->TimerCnt++;
00592 }
00593 
00594 /*
00595  * Event
00596  */
00597 
00604 void Q931SetCallEventCB(Q931_TrunkInfo_t *trunk, const Q931CallEventCB_t cb, const void *priv)
00605 {
00606         assert(trunk);
00607         assert(cb);
00608 
00609         trunk->CallEventCBProc = (Q931CallEventCB_t)cb;
00610         trunk->PrivateDataCallEventCB = (void *)priv;
00611 }
00612 
00618 void Q931CallSendEvent(const struct Q931_Call *call, const struct Q931_CallEvent *event)
00619 {
00620         Q931_TrunkInfo_t *trunk = Q931CallGetTrunk(call);
00621 
00622         assert(trunk);
00623         assert(event);
00624 
00625         if (!event || event->id == Q931_EVENT_NONE || event->type == Q931_EVENT_TYPE_NONE)
00626                 return;
00627 
00628         if (trunk->CallEventCBProc) {
00629                 Q931Log(trunk, Q931_LOG_DEBUG, "Sending call event to Layer4 [call: %d, id: %d, type: %d]\n", Q931CallGetCRV(call), event->id, event->type);
00630 
00631                 trunk->CallEventCBProc((struct Q931_Call *)call, (struct Q931_CallEvent *)event, trunk->PrivateDataCallEventCB);
00632         }
00633 }
00634 
00638 void Q931CallInitEvent(struct Q931_CallEvent *event)
00639 {
00640         memset(event, 0, sizeof(struct Q931_CallEvent));
00641 }
00642 
00643 /************************************************************************************************
00644  *  V2 - Enqueue events in the call handle and send them to layer 4, after processing everything
00645  ************************************************************************************************/
00646 
00650 struct Q931_CallEvent *Q931CallNewEvent(struct Q931_Call *call)
00651 {
00652         assert(call);
00653 
00654         if (call->numevents == Q931_CALL_MAX_EVENTS)
00655                 return NULL;
00656 
00657         return &call->events[call->numevents];
00658 }
00659 
00664 void Q931CallQueueEvent(struct Q931_Call *call, struct Q931_CallEvent *event)
00665 {
00666         assert(call);
00667 
00668         call->numevents++;
00669 }
00670 
00674 void Q931CallFlushEvents(struct Q931_Call *call)
00675 {
00676         assert(call);
00677 
00678         memset(call->events, 0, Q931_CALL_MAX_EVENTS * sizeof(struct Q931_CallEvent));
00679         call->numevents = 0;
00680 }
00681 
00685 void Q931CallSendQueuedEvents(struct Q931_Call *call)
00686 {
00687         int i;
00688 
00689         assert(call);
00690 
00691         for (i = 0; i < call->numevents; i++) {
00692                 Q931CallSendEvent(call, &call->events[i]);
00693         }
00694 
00695         Q931CallFlushEvents(call);
00696 }
00697 
00701 L3INT Q931CallEventGetType(const struct Q931_CallEvent *event)
00702 {
00703         return event->type;
00704 }
00705 
00709 L3INT Q931CallEventGetId(const struct Q931_CallEvent *event)
00710 {
00711         return event->id;
00712 }
00713 
00718 void *Q931CallEventGetData(const struct Q931_CallEvent *event)
00719 {
00720         switch (event->type) {
00721         case Q931_EVENT_TYPE_TIMER:
00722                 return (void *)&event->timer;
00723 
00724         case Q931_EVENT_TYPE_MESSAGE:
00725                 return (void *)&event->message;
00726 
00727         default:
00728                 return NULL;
00729         }
00730 }

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