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