Wed Apr 6 11:30:09 2011

Asterisk developer's documentation


res_pktccops.c File Reference

PacketCable COPS. More...

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <arpa/inet.h>
#include <signal.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/lock.h"
#include "asterisk/pktccops.h"

Go to the source code of this file.

Data Structures

struct  cmts_list
struct  cops_cmts
struct  cops_ippool
struct  copsmsg
struct  gate_list
struct  gatespec
struct  ippool_list
struct  pktcobj

Defines

#define AST_API_MODULE
#define COPS_HEADER_SIZE   8
#define COPS_OBJECT_HEADER_SIZE   4
#define DEFAULT_COPS_PORT   "2126"
#define GATE_INFO_OBJ_SIZE   24
#define GATE_SET_OBJ_SIZE   144
#define GATEID_OBJ_SIZE   8
#define PKTCCOPS_DESTROY_CURRENT_GATE
#define PKTCCOPS_SCOMMAND_GATE_ALLOC   1
#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ACK   2
#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ERR   3
#define PKTCCOPS_SCOMMAND_GATE_CLOSE   14
#define PKTCCOPS_SCOMMAND_GATE_DELETE   10
#define PKTCCOPS_SCOMMAND_GATE_DELETE_ACK   11
#define PKTCCOPS_SCOMMAND_GATE_DELETE_ERR   12
#define PKTCCOPS_SCOMMAND_GATE_INFO   7
#define PKTCCOPS_SCOMMAND_GATE_INFO_ACK   8
#define PKTCCOPS_SCOMMAND_GATE_INFO_ERR   9
#define PKTCCOPS_SCOMMAND_GATE_OPEN   13
#define PKTCCOPS_SCOMMAND_GATE_SET   4
#define PKTCCOPS_SCOMMAND_GATE_SET_ACK   5
#define PKTCCOPS_SCOMMAND_GATE_SET_ERR   6
#define SENDFLAGS   MSG_NOSIGNAL | MSG_DONTWAIT

Functions

static void __reg_module (void)
static void __unreg_module (void)
cops_gate *AST_OPTIONAL_API_NAME() ast_pktccops_gate_alloc (int cmd, struct cops_gate *gate, uint32_t mta, uint32_t actcount, float bitrate, uint32_t psize, uint32_t ssip, uint16_t ssport, int(*const got_dq_gi)(struct cops_gate *gate), int(*const gate_remove)(struct cops_gate *gate))
static int cops_connect (char *host, char *port)
static uint16_t cops_construct_gate (int cmd, char *p, uint16_t trid, uint32_t mtahost, uint32_t actcount, float rate, uint32_t psizegateid, uint32_t ssip, uint16_t ssport, uint32_t gateid, struct cops_cmts *cmts)
static uint16_t cops_constructgatespec (struct gatespec *gs, char *res)
static void cops_freemsg (struct copsmsg *p)
static struct cops_gatecops_gate_cmd (int cmd, struct cops_cmts *cmts, uint16_t trid, uint32_t mta, uint32_t actcount, float bitrate, uint32_t psize, uint32_t ssip, uint16_t ssport, struct cops_gate *gate)
static int cops_getmsg (int sfd, struct copsmsg *recmsg)
static int cops_sendmsg (int sfd, struct copsmsg *sendmsg)
static void * do_pktccops (void *data)
static uint32_t ftoieeef (float n)
static int load_module (void)
static int load_pktccops_config (void)
static int pktccops_add_ippool (struct cops_ippool *ippool)
static char * pktccops_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pktccops_gatedel (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pktccops_gateset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pktccops_show_cmtses (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pktccops_show_gates (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * pktccops_show_pools (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void pktccops_unregister_cmtses (void)
static void pktccops_unregister_ippools (void)
static int reload_module (void)
static int restart_pktc_thread (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "PktcCOPS manager for MGCP" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_pktccops []
static uint16_t cops_trid = 0
static int gateinfoperiod = 60
static int gatetimeout = 150
static uint32_t keepalive = 60
static ast_mutex_t pktccops_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static pthread_t pktccops_thread = AST_PTHREADT_NULL
static int pktccopsdebug = 0
static int pktcreload = 0
static uint16_t t1 = 250
static uint16_t t7 = 200
static uint16_t t8 = 300


Detailed Description

PacketCable COPS.

Author:
Attila Domjan <attila.domjan.hu@gmail.com>
Note:
This module is an add-on to chan_mgcp. It adds support for the PacketCable MGCP variation called NCS. Res_pktccops implements COPS (RFC 2748), a protocol used to manage dynamic bandwith allocation in CMTS's (HFC gateways). When you use NCS, you need to talk COPS with the CMTS to complete the calls.

Definition in file res_pktccops.c.


Define Documentation

#define AST_API_MODULE

Definition at line 63 of file res_pktccops.c.

#define COPS_HEADER_SIZE   8

Definition at line 68 of file res_pktccops.c.

Referenced by cops_gate_cmd(), cops_getmsg(), cops_sendmsg(), and do_pktccops().

#define COPS_OBJECT_HEADER_SIZE   4

Definition at line 69 of file res_pktccops.c.

Referenced by cops_gate_cmd(), cops_getmsg(), and do_pktccops().

#define DEFAULT_COPS_PORT   "2126"

Definition at line 66 of file res_pktccops.c.

#define GATE_INFO_OBJ_SIZE   24

Definition at line 72 of file res_pktccops.c.

Referenced by cops_gate_cmd().

#define GATE_SET_OBJ_SIZE   144

Definition at line 70 of file res_pktccops.c.

Referenced by cops_gate_cmd().

#define GATEID_OBJ_SIZE   8

Definition at line 71 of file res_pktccops.c.

Referenced by cops_gate_cmd().

#define PKTCCOPS_DESTROY_CURRENT_GATE

Value:

AST_LIST_REMOVE_CURRENT(list);  \
      if (gate->gate_remove) {        \
         gate->gate_remove(gate);    \
      }                               \
      ast_free(gate);

Definition at line 694 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_ALLOC   1

Definition at line 74 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ACK   2

Definition at line 75 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ERR   3

Definition at line 76 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_CLOSE   14

Definition at line 87 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_DELETE   10

Definition at line 83 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_DELETE_ACK   11

Definition at line 84 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_DELETE_ERR   12

Definition at line 85 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_INFO   7

Definition at line 80 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_INFO_ACK   8

Definition at line 81 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_INFO_ERR   9

Definition at line 82 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_OPEN   13

Definition at line 86 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_SET   4

Definition at line 77 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_SET_ACK   5

Definition at line 78 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_SET_ERR   6

Definition at line 79 of file res_pktccops.c.

Referenced by do_pktccops().

#define SENDFLAGS   MSG_NOSIGNAL | MSG_DONTWAIT

Referenced by cops_sendmsg().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1517 of file res_pktccops.c.

static void __unreg_module ( void   )  [static]

Definition at line 1517 of file res_pktccops.c.

struct cops_gate* AST_OPTIONAL_API_NAME() ast_pktccops_gate_alloc ( int  cmd,
struct cops_gate gate,
uint32_t  mta,
uint32_t  actcount,
float  bitrate,
uint32_t  psize,
uint32_t  ssip,
uint16_t  ssport,
int(*)(struct cops_gate *gate)  got_dq_gi,
int(*)(struct cops_gate *gate)  gate_remove 
)

Definition at line 469 of file res_pktccops.c.

References ast_debug, ast_log(), cops_gate_cmd(), cops_gate::gate_remove, GATE_SET_HAVE_GATEID, cops_gate::gateid, cops_gate::got_dq_gi, LOG_WARNING, and pktcreload.

Referenced by mgcp_alloc_pktcgate(), and mgcp_hangup().

00474 {
00475    while (pktcreload) {
00476       sched_yield();
00477    }
00478 
00479    if (cmd == GATE_SET_HAVE_GATEID && gate) {
00480       ast_debug(3, "------- gate modify gateid 0x%x ssip: 0x%x\n", gate->gateid, ssip);
00481       /* TODO implement it */
00482       ast_log(LOG_WARNING, "Modify GateID not implemented\n");
00483    } 
00484    
00485    if ((gate = cops_gate_cmd(cmd, NULL, cops_trid++, mta, actcount, bitrate, psize, ssip, ssport, gate))) {
00486       ast_debug(3, "COPS: Allocating gate for mta: 0x%x\n", mta);
00487       gate->got_dq_gi = got_dq_gi;
00488       gate->gate_remove = gate_remove;
00489       return(gate);
00490    } else {
00491       ast_debug(3, "COPS: Couldn't allocate gate for mta: 0x%x\n", mta); 
00492       return NULL;
00493    }
00494 }

static int cops_connect ( char *  host,
char *  port 
) [static]

Definition at line 650 of file res_pktccops.c.

References ast_debug, ast_log(), and LOG_WARNING.

Referenced by do_pktccops().

00651 {
00652    int s, sfd = -1, flags;
00653    struct addrinfo hints;
00654    struct addrinfo *rp;
00655    struct addrinfo *result;
00656 #ifdef HAVE_SO_NOSIGPIPE
00657    int trueval = 1;
00658 #endif
00659 
00660    memset(&hints, 0, sizeof(struct addrinfo));
00661 
00662    hints.ai_family = AF_UNSPEC;    
00663    hints.ai_socktype = SOCK_STREAM;
00664    hints.ai_flags = 0;
00665    hints.ai_protocol = 0;
00666 
00667    s = getaddrinfo(host, port, &hints, &result);
00668    if (s != 0) {
00669       ast_log(LOG_WARNING, "COPS: getaddrinfo: %s\n", gai_strerror(s));
00670       return -1;
00671    }
00672 
00673    for (rp = result; rp != NULL; rp = rp->ai_next) {
00674       sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
00675       if (sfd == -1) {
00676          ast_log(LOG_WARNING, "Failed socket\n");
00677       }
00678       flags = fcntl(sfd, F_GETFL);
00679       fcntl(sfd, F_SETFL, flags | O_NONBLOCK);
00680 #ifdef HAVE_SO_NOSIGPIPE
00681       setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval));
00682 #endif
00683       connect(sfd, rp->ai_addr, rp->ai_addrlen);
00684       if (sfd == -1) {
00685          ast_log(LOG_WARNING, "Failed connect\n");
00686       }
00687    }
00688    freeaddrinfo(result);
00689 
00690    ast_debug(3, "Connecting to cmts:  %s:%s\n", host, port);
00691    return(sfd);
00692 }

static uint16_t cops_construct_gate ( int  cmd,
char *  p,
uint16_t  trid,
uint32_t  mtahost,
uint32_t  actcount,
float  rate,
uint32_t  psizegateid,
uint32_t  ssip,
uint16_t  ssport,
uint32_t  gateid,
struct cops_cmts cmts 
) [static]

Definition at line 222 of file res_pktccops.c.

References ast_debug, gatespec::b, cops_constructgatespec(), gatespec::diffserv, gatespec::direction, gatespec::dstip, gatespec::dstp, gatespec::flags, ftoieeef(), GATE_DEL, GATE_INFO, GATE_SET_HAVE_GATEID, gatespec::m, gatespec::mm, gatespec::p, PKTCCOPS_SCOMMAND_GATE_DELETE, PKTCCOPS_SCOMMAND_GATE_INFO, PKTCCOPS_SCOMMAND_GATE_SET, gatespec::protocolid, gatespec::r, gatespec::rate, gatespec::s, gatespec::sessionclass, gatespec::srcip, gatespec::srcp, cops_cmts::t1, gatespec::t1, cops_cmts::t7, gatespec::t7, cops_cmts::t8, and gatespec::t8.

Referenced by cops_gate_cmd().

00225 {
00226    struct gatespec gs;
00227    int offset = 0;
00228    
00229    ast_debug(3, "CMD: %d\n", cmd);
00230 
00231    /* Transaction Identifier 8 octets */
00232    *(p + offset++) = 0;
00233    *(p + offset++) = 8; /* length */
00234    *(p + offset++) = 1; /* snum */
00235    *(p + offset++) = 1; /* stype */
00236    *((uint16_t *) (p + offset)) = htons(trid);
00237    offset += 2;
00238    *(p + offset++) = 0;
00239    *(p + offset++) = (cmd == GATE_DEL) ? PKTCCOPS_SCOMMAND_GATE_DELETE : (cmd != GATE_INFO) ? PKTCCOPS_SCOMMAND_GATE_SET : PKTCCOPS_SCOMMAND_GATE_INFO; /* 4: GATE-SET, 7: GATE-INFO */
00240 
00241    /*Subscriper Identifier 8 octets */
00242    *(p + offset++) = 0;
00243    *(p + offset++) = 8; /* length */
00244    *(p + offset++) = 2; /* snum */
00245    *(p + offset++) = 1; /* stype */
00246    *((uint32_t *) (p + offset)) = htonl(mtahost);
00247    offset += 4;
00248    
00249    if (cmd == GATE_INFO || cmd == GATE_SET_HAVE_GATEID || cmd == GATE_DEL) {
00250       /* Gate ID 8 Octets */
00251       *(p + offset++) = 0;
00252       *(p + offset++) = 8; /* length */
00253       *(p + offset++) = 3; /* snum */
00254       *(p + offset++) = 1; /* stype */
00255       *((uint32_t *) (p + offset)) = htonl(gateid);
00256       offset += 4;
00257       if (cmd == GATE_INFO || cmd == GATE_DEL) {
00258          return offset;
00259       }
00260    
00261    }
00262 
00263    /* Activity Count 8 octets */
00264    *(p + offset++) = 0;
00265    *(p + offset++) = 8; /* length */
00266    *(p + offset++) = 4; /* snum */
00267    *(p + offset++) = 1; /* stype */
00268    *((uint32_t *) (p + offset)) = htonl(actcount);
00269    offset += 4;
00270 
00271 
00272    /* Gate Spec 2*60 Octets */
00273    gs.direction = 0; /* DS */
00274    gs.protocolid = 17; /* UDP */
00275    gs.flags = 0;
00276    gs.sessionclass = 1;
00277    gs.srcip = htonl(ssip);
00278    gs.dstip = htonl(mtahost);
00279    gs.srcp = htons(ssport);
00280    gs.dstp = 0;
00281 /* gs.diffserv = 0xa0;*/
00282    gs.diffserv = 0;
00283    gs.t1 = htons(cmts->t1);
00284    gs.t7 = htons(cmts->t7);
00285    gs.t8 = htons(cmts->t8);
00286    gs.r = ftoieeef(rate);
00287    gs.b = ftoieeef(psizegateid);
00288    gs.p = ftoieeef(rate);
00289    gs.m = htonl((uint32_t) psizegateid);
00290    gs.mm = htonl((uint32_t) psizegateid);
00291    gs.rate = ftoieeef(rate);
00292    gs.s = htonl(800);
00293 
00294 
00295    *(p + offset) = 0;
00296    offset++;
00297    *(p + offset) = 60; /* length */
00298    offset++;
00299    *(p + offset) = 5; /* snum */
00300    offset++;
00301    *(p + offset) = 1; /* stype */
00302    offset++;
00303    offset += cops_constructgatespec(&gs, p + offset);
00304 
00305 
00306    gs.direction = 1; /* US */
00307    gs.srcip = htonl(mtahost);
00308    gs.dstip = htonl(ssip);
00309    gs.srcp = 0;
00310    gs.dstp = htons(ssport);
00311    *(p + offset) = 0;
00312    offset++;
00313    *(p + offset) = 60; /* length */
00314    offset++;
00315    *(p + offset) = 5; /* snum */
00316    offset++;
00317    *(p + offset) = 1; /* stype */
00318    offset++;
00319    offset += cops_constructgatespec(&gs, p + offset);
00320 
00321    return(offset);
00322 }

static uint16_t cops_constructgatespec ( struct gatespec gs,
char *  res 
) [static]

Definition at line 183 of file res_pktccops.c.

References gatespec::b, gatespec::diffserv, gatespec::direction, gatespec::dstip, gatespec::dstp, gatespec::flags, gatespec::m, gatespec::mm, gatespec::p, gatespec::protocolid, gatespec::r, gatespec::rate, gatespec::s, gatespec::sessionclass, gatespec::srcip, gatespec::srcp, gatespec::t1, gatespec::t7, and gatespec::t8.

Referenced by cops_construct_gate().

00184 {
00185    if (res == NULL) {
00186       return 0;
00187    }
00188    
00189    *res = (char) gs->direction;
00190    *(res + 1) = (char) gs->protocolid;
00191    *(res + 2) = (char) gs->flags;
00192    *(res + 3) = (char) gs->sessionclass;
00193 
00194    *((uint32_t *) (res + 4)) = gs->srcip;
00195    *((uint32_t *) (res + 8)) = gs->dstip;
00196 
00197    *((uint16_t *) (res + 12)) = gs->srcp;
00198    *((uint16_t *) (res + 14)) = gs->dstp;
00199 
00200    *(res + 16) = (char) gs->diffserv;
00201    *(res + 17) = 0; /* reserved */
00202    *(res + 18) = 0; /* reserved */
00203    *(res + 19) = 0; /* reserved */
00204 
00205    *((uint16_t *) (res + 20)) = gs->t1;
00206    *(res + 22) = 0; /* reserved */
00207    *(res + 23) = 0; /* reserved */
00208 
00209    *((uint16_t *) (res + 24)) = gs->t7;
00210    *((uint16_t *) (res + 26)) = gs->t8;
00211 
00212    *((uint32_t *) (res + 28)) = gs->r;
00213    *((uint32_t *) (res + 32)) = gs->b;
00214    *((uint32_t *) (res + 36)) = gs->p;
00215    *((uint32_t *) (res + 40)) = gs->m;
00216    *((uint32_t *) (res + 44)) = gs->mm;
00217    *((uint32_t *) (res + 48)) = gs->rate;
00218    *((uint32_t *) (res + 52)) = gs->s;
00219    return 56; /* length */
00220 };

static void cops_freemsg ( struct copsmsg p  )  [static]

Definition at line 454 of file res_pktccops.c.

References ast_free, pktcobj::contents, free, copsmsg::msg, pktcobj::next, and copsmsg::object.

Referenced by cops_gate_cmd(), and do_pktccops().

00455 {
00456    struct pktcobj *pnext;
00457    free(p->msg);
00458    p->msg = NULL;
00459    while (p->object != NULL) {
00460          pnext = p->object->next;
00461          ast_free(p->object->contents);
00462          p->object->contents = NULL;
00463          ast_free(p->object);
00464          p->object = pnext;
00465    }
00466    p->object = NULL;
00467 }

static struct cops_gate * cops_gate_cmd ( int  cmd,
struct cops_cmts cmts,
uint16_t  trid,
uint32_t  mta,
uint32_t  actcount,
float  bitrate,
uint32_t  psize,
uint32_t  ssip,
uint16_t  ssport,
struct cops_gate gate 
) [static]

Definition at line 496 of file res_pktccops.c.

References ast_calloc, ast_debug, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), copsmsg::clienttype, cops_gate::cmts, cops_ippool::cmts, pktcobj::cnum, pktcobj::contents, cops_construct_gate(), cops_freemsg(), COPS_HEADER_SIZE, COPS_OBJECT_HEADER_SIZE, cops_sendmsg(), pktcobj::ctype, free, GATE_ALLOC_PROGRESS, GATE_DEL, GATE_INFO, GATE_INFO_OBJ_SIZE, GATE_SET, GATE_SET_HAVE_GATEID, GATE_SET_OBJ_SIZE, cops_gate::gateid, GATEID_OBJ_SIZE, cops_cmts::handle, cops_gate::in_transaction, copsmsg::length, pktcobj::length, cops_cmts::list, LOG_WARNING, malloc, copsmsg::msg, cops_cmts::name, pktcobj::next, copsmsg::object, copsmsg::opcode, pktccopsdebug, cops_cmts::sfd, cops_ippool::start, stop, cops_gate::trid, and copsmsg::verflag.

Referenced by ast_pktccops_gate_alloc(), do_pktccops(), pktccops_gatedel(), and pktccops_gateset().

00499 {
00500    struct copsmsg *gateset;
00501    struct cops_gate *new;
00502    struct cops_ippool *ippool;
00503 
00504    if (cmd == GATE_DEL) {
00505       if (gate == NULL) {
00506          return NULL;
00507       } else {
00508          cmts = gate->cmts;
00509       }
00510    }
00511 
00512    if (!cmts) {
00513       AST_LIST_LOCK(&ippool_list);
00514       AST_LIST_TRAVERSE(&ippool_list, ippool, list) {
00515          if (mta >= ippool->start && mta <= ippool->stop) {
00516             cmts = ippool->cmts;
00517             break;
00518          }
00519       }
00520       AST_LIST_UNLOCK(&ippool_list);
00521       if (!cmts) {
00522          ast_log(LOG_WARNING, "COPS: couldn't find cmts for mta: 0x%x\n", mta);
00523          return NULL;
00524       }
00525       if (cmts->sfd < 0) {
00526          ast_log(LOG_WARNING, "CMTS: %s not connected\n", cmts->name);
00527          return NULL;
00528       }
00529    }
00530 
00531    if (cmd == GATE_SET) {
00532       new = ast_calloc(1, sizeof(*new));
00533       new->gateid = 0;
00534       new->trid = trid;
00535       new->mta = mta;
00536       new->state = GATE_ALLOC_PROGRESS;
00537       new->checked = time(NULL);
00538       new->allocated = time(NULL);
00539       new->cmts = cmts;
00540       new->got_dq_gi = NULL;
00541       new->gate_remove = NULL;
00542       new->gate_open = NULL;
00543       new->tech_pvt = NULL;
00544       new->deltimer = 0;
00545       AST_LIST_LOCK(&gate_list);
00546       AST_LIST_INSERT_HEAD(&gate_list, new, list);
00547       AST_LIST_UNLOCK(&gate_list);
00548       gate = new;
00549    } else {
00550       if (gate) {
00551          gate->trid = trid;
00552       }
00553    }
00554    
00555    gate->in_transaction = time(NULL);
00556 
00557    if (!(gateset = malloc(sizeof(struct copsmsg)))) {
00558       free(gateset);
00559       return NULL;
00560    }
00561    gateset->msg = NULL;
00562    gateset->verflag = 0x10;
00563    gateset->opcode = 2; /* Decision */
00564    gateset->clienttype = 0x8008; /* =PacketCable */
00565    
00566    /* Handle object */
00567    gateset->object = malloc(sizeof(struct pktcobj));
00568    if (!gateset->object) {
00569       cops_freemsg(gateset);
00570       free(gateset);
00571       return NULL;
00572    }
00573    gateset->object->length = COPS_OBJECT_HEADER_SIZE + 4;
00574    gateset->object->cnum = 1; /* Handle */
00575    gateset->object->ctype = 1; /* client */
00576    if (!(gateset->object->contents = malloc(sizeof(uint32_t)))) {
00577       cops_freemsg(gateset);
00578       free(gateset);
00579       return NULL;
00580    }
00581    *((uint32_t *) gateset->object->contents) = htonl(cmts->handle);
00582 
00583    /* Context Object */
00584    if (!(gateset->object->next = malloc(sizeof(struct pktcobj)))) {
00585       cops_freemsg(gateset);
00586       free(gateset);
00587       return NULL;
00588    }
00589    gateset->object->next->length = COPS_OBJECT_HEADER_SIZE + 4;
00590    gateset->object->next->cnum = 2; /* Context */
00591    gateset->object->next->ctype = 1; /* Context */
00592    if (!(gateset->object->next->contents = malloc(sizeof(uint32_t)))) {
00593       cops_freemsg(gateset);
00594       free(gateset);
00595       return NULL;
00596    }
00597    *((uint32_t *) gateset->object->next->contents) = htonl(0x00080000); /* R-Type = 8 configuration request, M-Type = 0 */
00598 
00599    /* Decision Object: Flags */
00600    if (!(gateset->object->next->next = malloc(sizeof(struct pktcobj)))) {
00601       cops_freemsg(gateset);
00602       free(gateset);
00603       return NULL;
00604    }
00605    gateset->object->next->next->length = COPS_OBJECT_HEADER_SIZE + 4;
00606    gateset->object->next->next->cnum = 6; /* Decision */
00607    gateset->object->next->next->ctype = 1; /* Flags */
00608    if (!(gateset->object->next->next->contents = malloc(sizeof(uint32_t)))) {
00609       cops_freemsg(gateset);
00610       free(gateset);
00611       return NULL;
00612    }
00613    *((uint32_t *) gateset->object->next->next->contents) = htonl(0x00010001); /* Install, Trigger Error */
00614 
00615    /* Decision Object: Data */
00616    if (!(gateset->object->next->next->next = malloc(sizeof(struct pktcobj)))) {
00617       cops_freemsg(gateset);
00618       free(gateset);
00619       return NULL;
00620    }
00621    gateset->object->next->next->next->length = COPS_OBJECT_HEADER_SIZE + ((cmd != GATE_INFO && cmd != GATE_DEL) ? GATE_SET_OBJ_SIZE : GATE_INFO_OBJ_SIZE) + ((cmd == GATE_SET_HAVE_GATEID) ? GATEID_OBJ_SIZE : 0);
00622    gateset->object->next->next->next->cnum = 6; /* Decision */
00623    gateset->object->next->next->next->ctype = 4; /* Decision Data */
00624    gateset->object->next->next->next->contents = malloc(((cmd != GATE_INFO && cmd != GATE_DEL) ? GATE_SET_OBJ_SIZE : GATE_INFO_OBJ_SIZE) + ((cmd == GATE_SET_HAVE_GATEID) ? GATEID_OBJ_SIZE : 0));
00625    if (!gateset->object->next->next->next->contents) {
00626       cops_freemsg(gateset);
00627       free(gateset);
00628       return NULL;
00629    }
00630    gateset->object->next->next->next->next = NULL;
00631    
00632    gateset->length = COPS_HEADER_SIZE + gateset->object->length + gateset->object->next->length + gateset->object->next->next->length + gateset->object->next->next->next->length;
00633 
00634    if ((cmd == GATE_INFO || cmd == GATE_SET_HAVE_GATEID || cmd == GATE_DEL) && gate) {
00635       ast_debug(1, "Construct gate with gateid: 0x%x\n", gate->gateid);
00636       cops_construct_gate(cmd, gateset->object->next->next->next->contents, trid, mta, actcount, bitrate, psize, ssip, ssport, gate->gateid, cmts);
00637    } else {
00638       ast_debug(1, "Construct new gate\n");
00639       cops_construct_gate(cmd, gateset->object->next->next->next->contents, trid, mta, actcount, bitrate, psize, ssip, ssport, 0, cmts);
00640    }
00641    if (pktccopsdebug) {
00642       ast_debug(3, "send cmd\n");
00643    }
00644    cops_sendmsg(cmts->sfd, gateset);
00645    cops_freemsg(gateset);
00646    free(gateset);
00647    return gate;
00648 }

static int cops_getmsg ( int  sfd,
struct copsmsg recmsg 
) [static]

Definition at line 324 of file res_pktccops.c.

References ast_debug, copsmsg::clienttype, pktcobj::cnum, pktcobj::contents, COPS_HEADER_SIZE, COPS_OBJECT_HEADER_SIZE, pktcobj::ctype, len(), pktcobj::length, copsmsg::length, malloc, copsmsg::msg, pktcobj::next, copsmsg::object, copsmsg::opcode, and copsmsg::verflag.

Referenced by do_pktccops().

00325 {
00326    int len, lent;
00327    char buf[COPS_HEADER_SIZE];
00328    struct pktcobj *pobject = NULL;
00329    uint16_t *ubuf = (uint16_t *) buf;
00330    recmsg->msg = NULL;
00331    recmsg->object = NULL;
00332    len = recv(sfd, buf, COPS_HEADER_SIZE, MSG_DONTWAIT);
00333    if (len < COPS_HEADER_SIZE) {
00334       return len;
00335    }
00336    recmsg->verflag = *buf;
00337    recmsg->opcode = *(buf + 1);
00338    recmsg->clienttype = ntohs(*((uint16_t *) (buf + 2)));
00339    recmsg->length = ntohl(*((uint32_t *) (buf + 4)));
00340    /* Eg KA msg*/
00341    if (recmsg->clienttype != 0x8008 ) {
00342       if (!(recmsg->msg = malloc(recmsg->length - COPS_HEADER_SIZE))) {
00343          return -1;
00344       }
00345       lent = recv(sfd, recmsg->msg, recmsg->length - COPS_HEADER_SIZE, MSG_DONTWAIT);
00346       if (lent < recmsg->length - COPS_HEADER_SIZE) {
00347          return lent;
00348       }
00349       len += len;
00350    } else {
00351       /* PacketCable Objects */
00352       while (len < recmsg->length) {
00353          if (len == COPS_HEADER_SIZE) {
00354             /* 1st round */
00355             if (!(recmsg->object = malloc(sizeof(struct pktcobj)))) {
00356                return -1;
00357             }
00358             pobject = recmsg->object;
00359          } else {
00360             if (!(pobject->next = malloc(sizeof(struct pktcobj)))) {
00361                return -1;
00362             }
00363             pobject = pobject->next;
00364          }
00365          pobject->next = NULL;
00366          lent = recv(sfd, buf, COPS_OBJECT_HEADER_SIZE, MSG_DONTWAIT);
00367          if (lent < COPS_OBJECT_HEADER_SIZE) {
00368             ast_debug(3, "Too short object header len: %i\n", lent);
00369             return lent;
00370          }
00371          len += lent;
00372          pobject->length = ntohs(*ubuf);
00373          pobject->cnum = *(buf + 2);
00374          pobject->ctype = *(buf + 3);
00375          if (!(pobject->contents = malloc(pobject->length - COPS_OBJECT_HEADER_SIZE))) {
00376             return -1;
00377          }
00378          lent = recv(sfd, pobject->contents, pobject->length - COPS_OBJECT_HEADER_SIZE, MSG_DONTWAIT);
00379          if (lent < pobject->length - COPS_OBJECT_HEADER_SIZE) {
00380             ast_debug(3, "Too short object content len: %i\n", lent);
00381             return lent;
00382          }
00383          len += lent;
00384       }
00385    }
00386    return len;
00387 }

static int cops_sendmsg ( int  sfd,
struct copsmsg sendmsg 
) [static]

Definition at line 389 of file res_pktccops.c.

References ast_debug, ast_log(), copsmsg::clienttype, pktcobj::cnum, pktcobj::contents, COPS_HEADER_SIZE, pktcobj::ctype, errno, free, pktcobj::length, copsmsg::length, LOG_WARNING, malloc, copsmsg::msg, pktcobj::next, copsmsg::object, copsmsg::opcode, SENDFLAGS, and copsmsg::verflag.

Referenced by cops_gate_cmd(), and do_pktccops().

00390 {
00391    char *buf;
00392    int bufpos;
00393    struct pktcobj *pobject;
00394    
00395    if (sfd < 0) {
00396       return -1;
00397    }
00398 
00399    ast_debug(3, "COPS: sending opcode: %i len: %i\n", sendmsg->opcode, sendmsg->length);
00400    if (sendmsg->length < COPS_HEADER_SIZE) {
00401       ast_log(LOG_WARNING, "COPS: invalid msg size!!!\n");
00402       return -1;
00403    }
00404    if (!(buf = malloc((size_t) sendmsg->length))) {
00405       return -1;
00406    }
00407    *buf = sendmsg->verflag ;
00408    *(buf + 1) = sendmsg->opcode;
00409    *((uint16_t *)(buf + 2)) = htons(sendmsg->clienttype);
00410    *((uint32_t *)(buf + 4)) = htonl(sendmsg->length);
00411 
00412    if (sendmsg->msg != NULL) {
00413       memcpy(buf + COPS_HEADER_SIZE, sendmsg->msg, sendmsg->length - COPS_HEADER_SIZE);
00414    } else if (sendmsg->object != NULL) {
00415       bufpos = 8;
00416       pobject = sendmsg->object;
00417       while(pobject != NULL) {
00418          ast_debug(3, "COPS: Sending Object : cnum: %i ctype %i len: %i\n", pobject->cnum, pobject->ctype, pobject->length);
00419          if (sendmsg->length < bufpos + pobject->length) {
00420             ast_log(LOG_WARNING, "COPS: Invalid msg size len: %i objectlen: %i\n", sendmsg->length, pobject->length);
00421             free(buf);
00422             return -1;
00423          }
00424          *(uint16_t *) (buf + bufpos) = htons(pobject->length);
00425          *(buf + bufpos + 2) = pobject->cnum;
00426          *(buf + bufpos + 3) = pobject->ctype;
00427          if (sendmsg->length < pobject->length + bufpos) {
00428             ast_log(LOG_WARNING, "COPS: Error sum of object len more the msg len %i < %i\n", sendmsg->length, pobject->length + bufpos);
00429             free(buf);
00430             return -1;
00431          }
00432          memcpy((buf + bufpos + 4), pobject->contents, pobject->length - 4);
00433          bufpos += pobject->length;
00434          pobject = pobject->next;
00435       }
00436    }
00437    
00438    errno = 0;
00439 #ifdef HAVE_MSG_NOSIGNAL
00440 #define  SENDFLAGS   MSG_NOSIGNAL | MSG_DONTWAIT
00441 #else
00442 #define  SENDFLAGS   MSG_DONTWAIT
00443 #endif
00444    if (send(sfd, buf, sendmsg->length, SENDFLAGS) == -1) {
00445       ast_log(LOG_WARNING, "COPS: Send failed errno=%i\n", errno);
00446       free(buf);
00447       return -2;
00448    }
00449 #undef SENDFLAGS
00450    free(buf);
00451    return 0;
00452 }

static void* do_pktccops ( void *  data  )  [static]

Definition at line 701 of file res_pktccops.c.

References ast_debug, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_poll, ast_poll_fd_index(), ast_realloc, cops_gate::checked, copsmsg::clienttype, cops_gate::cmts, pktcobj::cnum, pktcobj::contents, cops_connect(), cops_freemsg(), cops_gate_cmd(), cops_getmsg(), COPS_HEADER_SIZE, COPS_OBJECT_HEADER_SIZE, cops_sendmsg(), pktcobj::ctype, cops_gate::deltimer, free, GATE_ALLOC_FAILED, GATE_ALLOCATED, GATE_CLOSED, GATE_CLOSED_ERR, GATE_DEL, GATE_DELETED, GATE_INFO, cops_gate::gate_open, GATE_OPEN, GATE_TIMEOUT, cops_gate::gateid, gateinfoperiod, gatetimeout, cops_gate::got_dq_gi, cops_cmts::handle, cops_cmts::host, cops_gate::in_transaction, cops_cmts::katimer, cops_cmts::keepalive, len(), pktcobj::length, copsmsg::length, cops_cmts::list, load_pktccops_config(), LOG_WARNING, malloc, copsmsg::msg, cops_gate::mta, cops_cmts::name, cops_cmts::need_delete, pktcobj::next, copsmsg::object, copsmsg::opcode, PKTCCOPS_DESTROY_CURRENT_GATE, PKTCCOPS_SCOMMAND_GATE_CLOSE, PKTCCOPS_SCOMMAND_GATE_DELETE_ACK, PKTCCOPS_SCOMMAND_GATE_INFO_ACK, PKTCCOPS_SCOMMAND_GATE_INFO_ERR, PKTCCOPS_SCOMMAND_GATE_OPEN, PKTCCOPS_SCOMMAND_GATE_SET_ACK, PKTCCOPS_SCOMMAND_GATE_SET_ERR, pktccops_unregister_ippools(), pktcreload, cops_cmts::port, cops_cmts::sfd, cops_gate::state, cops_cmts::state, cops_gate::trid, and copsmsg::verflag.

Referenced by restart_pktc_thread().

00702 {
00703    int res, nfds, len;
00704    struct copsmsg *recmsg, *sendmsg;
00705    struct copsmsg recmsgb, sendmsgb;
00706    struct pollfd *pfds = NULL, *tmp;
00707    struct pktcobj *pobject;
00708    struct cops_cmts *cmts;
00709    struct cops_gate *gate;
00710    char *sobjp;
00711    uint16_t snst, sobjlen, scommand, recvtrid, actcount, reason, subreason;
00712    uint32_t gateid, subscrid, pktcerror;
00713    time_t last_exec = 0;
00714 
00715    recmsg = &recmsgb;
00716    sendmsg = &sendmsgb;
00717 
00718    ast_debug(3, "COPS: thread started\n");
00719 
00720    for (;;) {
00721       ast_free(pfds);
00722       pfds = NULL;
00723       nfds = 0;
00724       AST_LIST_LOCK(&cmts_list);
00725       AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
00726          if (last_exec != time(NULL)) {
00727             if (cmts->state == 2 && cmts->katimer + cmts->keepalive < time(NULL)) {
00728                ast_log(LOG_WARNING, "KA timer (%is) expired cmts: %s\n",  cmts->keepalive, cmts->name);
00729                cmts->state = 0;
00730                cmts->katimer = -1;
00731                close(cmts->sfd);
00732                cmts->sfd = -1;
00733             }
00734          }
00735          if (cmts->sfd > 0) {
00736             if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
00737                continue;
00738             }
00739             pfds = tmp;
00740             pfds[nfds].fd = cmts->sfd;
00741             pfds[nfds].events = POLLIN;
00742             pfds[nfds].revents = 0;
00743             nfds++;
00744          } else {
00745             cmts->sfd = cops_connect(cmts->host, cmts->port);
00746             if (cmts->sfd > 0) {
00747                cmts->state = 1;
00748                if (cmts->sfd > 0) {
00749                   if (!(tmp = ast_realloc(pfds, (nfds + 1) * sizeof(*pfds)))) {
00750                      continue;
00751                   }
00752                   pfds = tmp;
00753                   pfds[nfds].fd = cmts->sfd;
00754                   pfds[nfds].events = POLLIN;
00755                   pfds[nfds].revents = 0;
00756                   nfds++;
00757                }
00758             }
00759          }
00760       }
00761       AST_LIST_UNLOCK(&cmts_list);
00762 
00763       if (last_exec != time(NULL)) {
00764          last_exec = time(NULL);
00765          AST_LIST_LOCK(&gate_list);
00766          AST_LIST_TRAVERSE_SAFE_BEGIN(&gate_list, gate, list) {
00767             if (gate) {
00768                if (gate->deltimer && gate->deltimer < time(NULL)) {
00769                   gate->deltimer = time(NULL) + 5;
00770                   gate->trid = cops_trid++;
00771                   cops_gate_cmd(GATE_DEL, gate->cmts, gate->trid, 0, 0, 0, 0, 0, 0, gate);
00772                   ast_debug(3, "COPS: requested Gate-Del: CMTS: %s gateid: 0x%x\n", (gate->cmts) ? gate->cmts->name : "null", gate->gateid);
00773                }
00774                if (time(NULL) - gate->checked > gatetimeout) {
00775                   ast_debug(3, "COPS: remove from list GATE, CMTS: %s gateid: 0x%x\n", (gate->cmts) ? gate->cmts->name : "null", gate->gateid);
00776                   gate->state = GATE_TIMEOUT;
00777                   PKTCCOPS_DESTROY_CURRENT_GATE;
00778                } else if (time(NULL) - gate->checked > gateinfoperiod && (gate->state == GATE_ALLOCATED || gate->state == GATE_OPEN)) {
00779                   if (gate->cmts && (!gate->in_transaction || ( gate->in_transaction + 5 ) < time(NULL))) {
00780                      gate->trid = cops_trid++;
00781                      ast_debug(3, "COPS: Gate-Info send to CMTS: %s gateid: 0x%x\n", gate->cmts->name, gate->gateid);
00782                      cops_gate_cmd(GATE_INFO, gate->cmts, gate->trid, gate->mta, 0, 0, 0, 0, 0, gate);
00783                   }
00784                }
00785             }
00786          }
00787          AST_LIST_TRAVERSE_SAFE_END;
00788          AST_LIST_UNLOCK(&gate_list);
00789       }
00790 
00791       if (pktcreload == 2) {
00792          pktcreload = 0;
00793       }
00794       if ((res = ast_poll(pfds, nfds, 1000))) {
00795          AST_LIST_LOCK(&cmts_list);
00796          AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
00797             int idx;
00798             if ((idx = ast_poll_fd_index(pfds, nfds, cmts->sfd)) > -1 && (pfds[idx].revents & POLLIN)) {
00799                len = cops_getmsg(cmts->sfd, recmsg);
00800                if (len > 0) {
00801                   ast_debug(3, "COPS: got from %s:\n Header: versflag=0x%.2x opcode=%i clienttype=0x%.4x msglength=%i\n",
00802                      cmts->name, recmsg->verflag, recmsg->opcode, recmsg->clienttype, recmsg->length);
00803                   if (recmsg->object != NULL) {
00804                      pobject = recmsg->object;
00805                      while (pobject != NULL) {
00806                         ast_debug(3, " OBJECT: length=%i cnum=%i ctype=%i\n", pobject->length, pobject->cnum, pobject->ctype);
00807                         if (recmsg->opcode == 1 && pobject->cnum == 1 && pobject->ctype == 1 ) {
00808                            cmts->handle = ntohl(*((uint32_t *) pobject->contents));
00809                            ast_debug(3, "    REQ client handle: %i\n", cmts->handle);
00810                            cmts->state = 2;
00811                            cmts->katimer = time(NULL);
00812                         } else if (pobject->cnum == 9 && pobject->ctype == 1) {
00813                            sobjp = pobject->contents;
00814                            subscrid = 0;
00815                            recvtrid = 0;
00816                            scommand = 0;
00817                            pktcerror = 0;
00818                            actcount = 0;
00819                            gateid = 0;
00820                            reason = 0;
00821                            subreason = 0;
00822                            while (sobjp < (pobject->contents + pobject->length - 4)) {
00823                               sobjlen = ntohs(*((uint16_t *) sobjp));
00824                               snst = ntohs(*((uint16_t *) (sobjp + 2)));
00825                               ast_debug(3, "   S-Num S-type: 0x%.4x len: %i\n", snst, sobjlen);
00826                               if (snst == 0x0101 ) {
00827                                  recvtrid = ntohs(*((uint16_t *) (sobjp + 4)));
00828                                  scommand = ntohs(*((uint16_t *) (sobjp + 6)));              
00829                                  ast_debug(3, "     Transaction Identifier command: %i trid %i\n", scommand, recvtrid);
00830                               } else if (snst == 0x0201) {
00831                                  subscrid = ntohl(*((uint32_t *) (sobjp + 4)));
00832                                  ast_debug(3, "     Subscriber ID: 0x%.8x\n", subscrid);
00833                               } else if (snst == 0x0301) {
00834                                  gateid = ntohl(*((uint32_t *) (sobjp + 4)));
00835                                  ast_debug(3, "      Gate ID: 0x%x 0x%.8x\n", gateid, gateid);
00836                               } else if (snst == 0x0401) {
00837                                  actcount = ntohs(*((uint16_t *) (sobjp + 6)));
00838                                  ast_debug(3, "      Activity Count: %i\n", actcount);
00839                               } else if (snst == 0x0901) {
00840                                  pktcerror = ntohl(*((uint32_t *) (sobjp + 4)));
00841                                  ast_debug(3, "      PKTC Error: 0x%.8x\n", pktcerror);
00842                               } else if (snst == 0x0d01) {
00843                                  reason = ntohs(*((uint16_t *) (sobjp + 4)));
00844                                  subreason = ntohs(*((uint16_t *) (sobjp + 6)));
00845                                  ast_debug(3, "      Reason: %u Subreason: %u\n", reason, subreason);
00846                               }
00847                               sobjp += sobjlen;
00848                               if (!sobjlen)
00849                                  break;
00850                            }
00851                            if (scommand == PKTCCOPS_SCOMMAND_GATE_CLOSE || scommand == PKTCCOPS_SCOMMAND_GATE_OPEN) {
00852                               AST_LIST_LOCK(&gate_list);
00853                               AST_LIST_TRAVERSE_SAFE_BEGIN(&gate_list, gate, list) {
00854                                  if (gate->cmts == cmts && gate->gateid == gateid) {
00855                                     if (scommand == PKTCCOPS_SCOMMAND_GATE_CLOSE && gate->state != GATE_CLOSED && gate->state != GATE_CLOSED_ERR ) {
00856                                        ast_debug(3, "COPS Gate Close Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00857                                        if (subreason) {
00858                                           gate->state = GATE_CLOSED_ERR;
00859                                           PKTCCOPS_DESTROY_CURRENT_GATE;
00860                                        } else {
00861                                           gate->state = GATE_CLOSED;
00862                                           PKTCCOPS_DESTROY_CURRENT_GATE;
00863                                        }
00864                                        break;
00865                                     } else if (scommand == PKTCCOPS_SCOMMAND_GATE_OPEN && gate->state == GATE_ALLOCATED) {
00866                                        ast_debug(3, "COPS Gate Open Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00867                                        gate->state = GATE_OPEN;
00868                                        if (gate->gate_open) {
00869                                           ast_debug(3, "Calling GATE-OPEN callback function\n");
00870                                           gate->gate_open(gate);
00871                                           gate->gate_open = NULL;
00872                                        }
00873                                        break;
00874                                     } 
00875                                  }
00876                               }
00877                               AST_LIST_TRAVERSE_SAFE_END;
00878                               AST_LIST_UNLOCK(&gate_list);
00879                            } else if (scommand == PKTCCOPS_SCOMMAND_GATE_SET_ACK || scommand == PKTCCOPS_SCOMMAND_GATE_SET_ERR || scommand == PKTCCOPS_SCOMMAND_GATE_INFO_ACK || scommand == PKTCCOPS_SCOMMAND_GATE_INFO_ERR || scommand == PKTCCOPS_SCOMMAND_GATE_DELETE_ACK) {
00880                               AST_LIST_LOCK(&gate_list);
00881                               AST_LIST_TRAVERSE_SAFE_BEGIN(&gate_list, gate, list) {
00882                                  if (gate->cmts == cmts && gate->trid == recvtrid) {
00883                                     gate->gateid = gateid;
00884                                     gate->checked = time(NULL);
00885                                     if (scommand == PKTCCOPS_SCOMMAND_GATE_SET_ACK) {
00886                                        ast_debug(3, "COPS Gate Set Ack Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00887                                        gate->state = GATE_ALLOCATED;
00888                                        if (gate->got_dq_gi) {
00889                                           gate->got_dq_gi(gate);
00890                                           gate->got_dq_gi = NULL;
00891                                        }
00892                                     } else if (scommand == PKTCCOPS_SCOMMAND_GATE_SET_ERR) {
00893                                        ast_debug(3, "COPS Gate Set Error TrId: %i ErrorCode: 0x%.8x CMTS: %s\n ", recvtrid, pktcerror, cmts->name);
00894                                        gate->state = GATE_ALLOC_FAILED;
00895                                        if (gate->got_dq_gi) {
00896                                           gate->got_dq_gi(gate);
00897                                           gate->got_dq_gi = NULL;
00898                                        }
00899                                        PKTCCOPS_DESTROY_CURRENT_GATE;
00900                                     } else if (scommand == PKTCCOPS_SCOMMAND_GATE_INFO_ACK) {
00901                                        ast_debug(3, "COPS Gate Info Ack Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00902                                     } else if (scommand == PKTCCOPS_SCOMMAND_GATE_INFO_ERR) {
00903                                        ast_debug(3, "COPS Gate Info Error Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00904                                        gate->state = GATE_ALLOC_FAILED;
00905                                        PKTCCOPS_DESTROY_CURRENT_GATE;
00906                                     } else if (scommand == PKTCCOPS_SCOMMAND_GATE_DELETE_ACK) {
00907                                        ast_debug(3, "COPS Gate Deleted Gate ID: 0x%x TrId: %i CMTS: %s\n", gateid, recvtrid, cmts->name);
00908                                        gate->state = GATE_DELETED;
00909                                        PKTCCOPS_DESTROY_CURRENT_GATE;
00910                                     }
00911                                     gate->in_transaction = 0;
00912                                     break;
00913                                  }
00914                               }
00915                               AST_LIST_TRAVERSE_SAFE_END;
00916                               AST_LIST_UNLOCK(&gate_list);
00917                            }
00918                         }
00919                         pobject = pobject->next;
00920                      }
00921                   }
00922 
00923                   if (recmsg->opcode == 6 && recmsg->object && recmsg->object->cnum == 11 && recmsg->object->ctype == 1) {
00924                      ast_debug(3, "COPS: Client open %s\n", cmts->name);
00925                      sendmsg->msg = NULL;
00926                      sendmsg->verflag = 0x10;
00927                      sendmsg->opcode = 7; /* Client Accept */
00928                      sendmsg->clienttype = 0x8008; /* =PacketCable */
00929                      sendmsg->length = COPS_HEADER_SIZE + COPS_OBJECT_HEADER_SIZE + 4;
00930                      sendmsg->object = malloc(sizeof(struct pktcobj));
00931                      sendmsg->object->length = 4 + COPS_OBJECT_HEADER_SIZE;
00932                      sendmsg->object->cnum = 10; /* keppalive timer*/
00933                      sendmsg->object->ctype = 1;
00934                      sendmsg->object->contents = malloc(sizeof(uint32_t));
00935                      *((uint32_t *) sendmsg->object->contents) = htonl(cmts->keepalive & 0x0000ffff);
00936                      sendmsg->object->next = NULL;
00937                      cops_sendmsg(cmts->sfd, sendmsg);
00938                      cops_freemsg(sendmsg);
00939                   } else if (recmsg->opcode == 9) {
00940                      ast_debug(3, "COPS: Keepalive Request got echoing back %s\n", cmts->name);
00941                      cops_sendmsg(cmts->sfd, recmsg);
00942                      cmts->state = 2;
00943                      cmts->katimer = time(NULL);
00944                   }
00945                } 
00946                if (len <= 0) {
00947                   ast_debug(3, "COPS: lost connection to %s\n", cmts->name);
00948                   close(cmts->sfd);
00949                   cmts->sfd = -1;
00950                   cmts->state = 0;
00951                }
00952                cops_freemsg(recmsg);
00953             }
00954          }
00955          AST_LIST_UNLOCK(&cmts_list);        
00956       }
00957       if (pktcreload) {
00958          ast_debug(3, "Reloading pktccops...\n");
00959          AST_LIST_LOCK(&gate_list);
00960          AST_LIST_LOCK(&cmts_list);
00961          pktccops_unregister_ippools();
00962          AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
00963             cmts->need_delete = 1;
00964          }
00965          load_pktccops_config();
00966          AST_LIST_TRAVERSE_SAFE_BEGIN(&cmts_list, cmts, list) {
00967             if (cmts && cmts->need_delete) {
00968                AST_LIST_TRAVERSE(&gate_list, gate, list) {
00969                   if (gate->cmts == cmts) {
00970                      ast_debug(3, "Null gate %s\n", gate->cmts->name);
00971                      gate->cmts = NULL;
00972                   }
00973                   gate->in_transaction = 0;
00974                }
00975                AST_LIST_UNLOCK(&gate_list);
00976                ast_debug(3, "removing cmts: %s\n", cmts->name);
00977                if (cmts->sfd > 0) {
00978                   close(cmts->sfd);
00979                }
00980                AST_LIST_REMOVE_CURRENT(list);
00981                free(cmts);
00982             }
00983          }
00984          AST_LIST_TRAVERSE_SAFE_END;
00985          AST_LIST_UNLOCK(&cmts_list);
00986          AST_LIST_UNLOCK(&gate_list);
00987          pktcreload = 2;
00988       }
00989       pthread_testcancel();
00990    }
00991    return NULL;
00992 }

static uint32_t ftoieeef ( float  n  )  [static]

Definition at line 176 of file res_pktccops.c.

Referenced by cops_construct_gate().

00177 {
00178    uint32_t res;
00179    memcpy(&res, &n, 4);
00180    return htonl(res);
00181 }

static int load_module ( void   )  [static]

Definition at line 1466 of file res_pktccops.c.

References ast_cli_register_multiple(), AST_LIST_LOCK, AST_LIST_UNLOCK, AST_MODULE_LOAD_DECLINE, cli_pktccops, load_pktccops_config(), and restart_pktc_thread().

01467 {
01468    int res;
01469    AST_LIST_LOCK(&cmts_list);
01470    res = load_pktccops_config();
01471    AST_LIST_UNLOCK(&cmts_list);
01472    if (res == -1) {
01473       return AST_MODULE_LOAD_DECLINE;
01474    }
01475    ast_cli_register_multiple(cli_pktccops, sizeof(cli_pktccops) / sizeof(struct ast_cli_entry));
01476    restart_pktc_thread();
01477    return 0;
01478 }

static int load_pktccops_config ( void   )  [static]

Definition at line 1023 of file res_pktccops.c.

References ast_category_browse(), ast_config_load, ast_log(), ast_variable_browse(), config, config_flags, f, LOG_WARNING, ast_variable::name, ast_variable::next, update(), and ast_variable::value.

Referenced by do_pktccops(), and load_module().

01024 {
01025    static char *cfg = "res_pktccops.conf";
01026    struct ast_config *config;
01027    struct ast_variable *v;
01028    struct cops_cmts *cmts;
01029    struct cops_ippool *new_ippool;
01030    const char *host, *cat, *port;
01031    int sfd, update;
01032    int res = 0;
01033    uint16_t t1_temp, t7_temp, t8_temp;
01034    uint32_t keepalive_temp;
01035    unsigned int a,b,c,d,e,f,g,h;
01036    struct ast_flags config_flags = {0};
01037 
01038    if (!(config = ast_config_load(cfg, config_flags))) {
01039       ast_log(LOG_WARNING, "Unable to load config file res_pktccops.conf\n");
01040       return -1;
01041    }
01042    for (cat = ast_category_browse(config, NULL); cat; cat = ast_category_browse(config, cat)) {
01043       if (!strcmp(cat, "general")) {
01044          for (v = ast_variable_browse(config, cat); v; v = v->next) {
01045             if (!strcasecmp(v->name, "t1")) {
01046                t1 = atoi(v->value);
01047             } else if (!strcasecmp(v->name, "t7")) {
01048                t7 = atoi(v->value);
01049             } else if (!strcasecmp(v->name, "t8")) {
01050                t8 = atoi(v->value);
01051             } else if (!strcasecmp(v->name, "keepalive")) {
01052                keepalive = atoi(v->value);
01053             } else if (!strcasecmp(v->name, "gateinfoperiod")) {
01054                gateinfoperiod = atoi(v->value);
01055             } else if (!strcasecmp(v->name, "gatetimeout")) {
01056                gatetimeout = atoi(v->value);
01057             } else {
01058                ast_log(LOG_WARNING, "Unkown option %s in general section of res_ptkccops.conf\n", v->name);
01059             }
01060          }        
01061       } else {
01062          /* Defaults */
01063          host = NULL;
01064          port = NULL;
01065          sfd = 0;
01066          t1_temp = t1;
01067          t7_temp = t7;
01068          t8_temp = t8;
01069          keepalive_temp = keepalive;
01070 
01071          for (v = ast_variable_browse(config, cat); v; v = v->next) {
01072             if (!strcasecmp(v->name, "host")) {
01073                host = v->value;           
01074             } else if (!strcasecmp(v->name, "port")) {
01075                port = v->value;
01076             } else if (!strcasecmp(v->name, "t1")) {
01077                t1_temp = atoi(v->value);
01078             } else if (!strcasecmp(v->name, "t7")) {
01079                t7_temp = atoi(v->value);
01080             } else if (!strcasecmp(v->name, "t8")) {
01081                t8_temp = atoi(v->value);
01082             } else if (!strcasecmp(v->name, "keepalive")) {
01083                keepalive_temp = atoi(v->value);
01084             } else if (!strcasecmp(v->name, "pool")) {
01085                /* we weill parse it in 2nd round */
01086             } else {
01087                ast_log(LOG_WARNING, "Unkown option %s in res_ptkccops.conf\n", v->name);
01088             }
01089          }
01090 
01091          update = 0;
01092          AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
01093             if (!strcmp(cmts->name, cat)) {
01094                update = 1;
01095                break;
01096             }
01097 
01098          }
01099          if (!update) {
01100             cmts = ast_calloc(1, sizeof(*cmts));
01101             if (!cmts) {
01102                res = -1;
01103                break;
01104             }
01105             AST_LIST_INSERT_HEAD(&cmts_list, cmts, list);
01106          }
01107          if (cat) {
01108             ast_copy_string(cmts->name, cat, sizeof(cmts->name));
01109          }
01110          if (host) {
01111             ast_copy_string(cmts->host, host, sizeof(cmts->host));
01112          }
01113          if (port) {
01114             ast_copy_string(cmts->port, port, sizeof(cmts->port));
01115          } else {
01116             ast_copy_string(cmts->port, DEFAULT_COPS_PORT, sizeof(cmts->port));
01117          }
01118 
01119          cmts->t1 = t1_temp;
01120          cmts->t7 = t7_temp;
01121          cmts->t8 = t8_temp;
01122          cmts->keepalive = keepalive_temp;
01123          if (!update) {
01124             cmts->state = 0;
01125             cmts->sfd = -1;
01126          }
01127          cmts->need_delete = 0;
01128          for (v = ast_variable_browse(config, cat); v; v = v->next) {
01129             /* parse ipppol when we have cmts ptr */
01130             if (!strcasecmp(v->name, "pool")) {
01131                if (sscanf(v->value, "%3u.%3u.%3u.%3u %3u.%3u.%3u.%3u", &a, &b, &c, &d, &e, &f, &g, &h) == 8) {
01132                   new_ippool = ast_calloc(1, sizeof(*new_ippool));
01133                   if (!new_ippool) {
01134                      res = -1;
01135                      break;
01136                   }
01137                   new_ippool->start = a << 24 | b << 16 | c << 8 | d;
01138                   new_ippool->stop = e << 24 | f << 16 | g << 8 | h;
01139                   new_ippool->cmts = cmts;
01140                   pktccops_add_ippool(new_ippool);
01141                } else {
01142                   ast_log(LOG_WARNING, "Invalid ip pool format in res_pktccops.conf\n");
01143                }
01144             }
01145          }
01146       }
01147    }
01148    ast_config_destroy(config);
01149    return res;
01150 }

static int pktccops_add_ippool ( struct cops_ippool ippool  )  [static]

Definition at line 1423 of file res_pktccops.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_cli_entry::list, and LOG_WARNING.

01424 {
01425    if (ippool) {
01426       AST_LIST_LOCK(&ippool_list);
01427       AST_LIST_INSERT_HEAD(&ippool_list, ippool, list);
01428       AST_LIST_UNLOCK(&ippool_list);
01429       return 0;
01430    } else {
01431       ast_log(LOG_WARNING, "Attempted to register NULL ippool?\n");
01432       return -1;
01433    }
01434 }

static char* pktccops_debug ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1386 of file res_pktccops.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, pktccopsdebug, and ast_cli_entry::usage.

01387 {
01388    switch (cmd) {
01389    case CLI_INIT:
01390       e->command = "pktccops set debug {on|off}";
01391       e->usage = 
01392          "Usage: pktccops set debug {on|off}\n"
01393          "  Turn on/off debuging\n";
01394       return NULL;
01395    case CLI_GENERATE:
01396       return NULL;
01397    }
01398 
01399    if (a->argc != e->args)
01400       return CLI_SHOWUSAGE;
01401    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
01402       pktccopsdebug = 1;
01403       ast_cli(a->fd, "PktcCOPS Debugging Enabled\n");
01404    } else if (!strncasecmp(a->argv[e->args - 1], "off", 2)) {
01405       pktccopsdebug = 0;
01406       ast_cli(a->fd, "PktcCOPS Debugging Disabled\n");
01407    } else {
01408       return CLI_SHOWUSAGE;
01409    }
01410    return CLI_SUCCESS;
01411 
01412 }

static char* pktccops_gatedel ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1268 of file res_pktccops.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cops_gate::cmts, ast_cli_entry::command, cops_gate_cmd(), ast_cli_args::fd, GATE_DEL, cops_gate::gateid, cops_cmts::list, cops_cmts::name, and ast_cli_entry::usage.

01269 {
01270    int found = 0;
01271    int trid;
01272    uint32_t gateid;
01273    struct cops_gate *gate;
01274    struct cops_cmts *cmts;
01275 
01276    switch (cmd) {
01277    case CLI_INIT:
01278       e->command = "pktccops gatedel";
01279       e->usage = 
01280          "Usage: pktccops gatedel <cmts> <gateid>\n"
01281          "       Send Gate-Del to cmts.\n";
01282       return NULL;
01283    case CLI_GENERATE:
01284       return NULL;
01285    }
01286 
01287    if (a->argc < 4)
01288       return CLI_SHOWUSAGE;
01289 
01290    AST_LIST_LOCK(&cmts_list);
01291    AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
01292       if (!strcmp(cmts->name, a->argv[2])) {
01293          ast_cli(a->fd, "Found cmts: %s\n", cmts->name);
01294          found = 1;
01295          break;
01296       }
01297    }
01298    AST_LIST_UNLOCK(&cmts_list);
01299    
01300    if (!found)
01301       return CLI_SHOWUSAGE;
01302 
01303    trid = cops_trid++;
01304    if (!sscanf(a->argv[3], "%x", &gateid)) {
01305       ast_cli(a->fd, "bad gate specification (%s)\n", a->argv[3]);   
01306       return CLI_SHOWUSAGE;
01307    }
01308 
01309    found = 0;
01310    AST_LIST_LOCK(&gate_list);
01311    AST_LIST_TRAVERSE(&gate_list, gate, list) {
01312       if (gate->gateid == gateid && gate->cmts == cmts) {
01313          found = 1;
01314          break;
01315       }
01316    }
01317       
01318    if (!found) {
01319       ast_cli(a->fd, "gate not found: %s\n", a->argv[3]);
01320       return CLI_SHOWUSAGE;
01321    }
01322 
01323    AST_LIST_UNLOCK(&gate_list);
01324    cops_gate_cmd(GATE_DEL, cmts, trid, 0, 0, 0, 0, 0, 0, gate);
01325    return CLI_SUCCESS;
01326 }

static char* pktccops_gateset ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1328 of file res_pktccops.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, cops_gate::cmts, ast_cli_entry::command, cops_gate_cmd(), ast_cli_args::fd, GATE_SET, cops_cmts::name, and ast_cli_entry::usage.

01329 {
01330    int foundcmts = 0;
01331    int trid;
01332    unsigned int an,bn,cn,dn;
01333    uint32_t mta, ssip;
01334    struct cops_cmts *cmts;
01335    struct cops_gate *gate;
01336 
01337    switch (cmd) {
01338    case CLI_INIT:
01339       e->command = "pktccops gateset";
01340       e->usage = 
01341          "Usage: pktccops gateset <cmts> <mta> <acctcount> <bitrate> <packet size> <switch ip> <switch port>\n"
01342          "       Send Gate-Set to cmts.\n";
01343       return NULL;
01344    case CLI_GENERATE:
01345       return NULL;
01346    }
01347 
01348    if (a->argc < 9)
01349       return CLI_SHOWUSAGE;
01350 
01351    if (!strncmp(a->argv[2], "null", sizeof(a->argv[2]))) {
01352       cmts = NULL;
01353    } else {
01354       AST_LIST_LOCK(&cmts_list);
01355       AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
01356          if (!strcmp(cmts->name, a->argv[2])) {
01357             ast_cli(a->fd, "Found cmts: %s\n", cmts->name);
01358             foundcmts = 1;
01359             break;
01360          }
01361       }
01362       AST_LIST_UNLOCK(&cmts_list);
01363       if (!foundcmts) {
01364          ast_cli(a->fd, "CMTS not found: %s\n", a->argv[2]);
01365          return CLI_SHOWUSAGE;
01366       }
01367    }
01368 
01369    trid = cops_trid++;
01370    if (sscanf(a->argv[3], "%3u.%3u.%3u.%3u", &an, &bn, &cn, &dn) != 4) {
01371       ast_cli(a->fd, "MTA specification (%s) does not look like an ipaddr\n", a->argv[3]);
01372       return CLI_SHOWUSAGE;
01373    }
01374    mta = an << 24 | bn << 16 | cn << 8 | dn;
01375 
01376    if (sscanf(a->argv[7], "%3u.%3u.%3u.%3u", &an, &bn, &cn, &dn) != 4) {
01377       ast_cli(a->fd, "SSIP specification (%s) does not look like an ipaddr\n", a->argv[7]);
01378       return CLI_SHOWUSAGE;
01379    }
01380    ssip = an << 24 | bn << 16 | cn << 8 | dn;
01381 
01382    gate = cops_gate_cmd(GATE_SET, cmts, trid, mta, atoi(a->argv[4]), atof(a->argv[5]), atoi(a->argv[6]), ssip, atoi(a->argv[8]), NULL);
01383    return CLI_SUCCESS;
01384 }

static char* pktccops_show_cmtses ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1152 of file res_pktccops.c.

References ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, cops_cmts::host, cops_cmts::katimer, cops_cmts::list, cops_cmts::name, cops_cmts::port, cops_cmts::state, and ast_cli_entry::usage.

01153 {
01154    struct cops_cmts *cmts;
01155    char statedesc[16];
01156    int katimer;
01157    
01158    switch(cmd) {
01159    case CLI_INIT:
01160       e->command = "pktccops show cmtses";
01161       e->usage = 
01162          "Usage: pktccops show cmtses\n"
01163          "       List PacketCable COPS CMTSes.\n";
01164 
01165       return NULL;
01166    case CLI_GENERATE:
01167       return NULL;
01168    }
01169 
01170    ast_cli(a->fd, "%-16s %-24s %-12s %7s\n", "Name        ", "Host                ", "Status    ", "KA timer  ");
01171    ast_cli(a->fd, "%-16s %-24s %-12s %7s\n", "------------", "--------------------", "----------", "-----------");
01172    AST_LIST_LOCK(&cmts_list);
01173    AST_LIST_TRAVERSE(&cmts_list, cmts, list) {
01174       katimer = -1;
01175       if (cmts->state == 2) {
01176          ast_copy_string(statedesc, "Connected", sizeof(statedesc));
01177          katimer = (int) (time(NULL) - cmts->katimer);
01178       } else if (cmts->state == 1) {
01179          ast_copy_string(statedesc, "Connecting", sizeof(statedesc));
01180       } else {
01181          ast_copy_string(statedesc, "N/A", sizeof(statedesc));
01182       }
01183       ast_cli(a->fd, "%-16s %-15s:%-8s %-12s %-7d\n", cmts->name, cmts->host, cmts->port, statedesc, katimer);
01184    }
01185    AST_LIST_UNLOCK(&cmts_list);
01186    return CLI_SUCCESS;
01187 }

static char* pktccops_show_gates ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1189 of file res_pktccops.c.

References cops_gate::allocated, ast_cli(), ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, cops_gate::checked, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, cops_gate::cmts, ast_cli_entry::command, ast_cli_args::fd, GATE_ALLOC_FAILED, GATE_ALLOC_PROGRESS, GATE_ALLOCATED, GATE_CLOSED, GATE_CLOSED_ERR, GATE_DELETED, GATE_OPEN, cops_gate::gateid, cops_gate::in_transaction, cops_gate::mta, cops_cmts::name, cops_gate::state, and ast_cli_entry::usage.

01190 {
01191    struct cops_gate *gate;
01192    char state_desc[16];
01193 
01194    switch(cmd) {
01195    case CLI_INIT:
01196       e->command = "pktccops show gates";
01197       e->usage = 
01198          "Usage: pktccops show gates\n"
01199          "       List PacketCable COPS GATEs.\n";
01200 
01201       return NULL;
01202    case CLI_GENERATE:
01203       return NULL;
01204    }
01205 
01206    ast_cli(a->fd, "%-16s %-12s %-12s %-10s %-10s %-10s\n" ,"CMTS", "Gate-Id","MTA", "Status", "AllocTime", "CheckTime");
01207    ast_cli(a->fd, "%-16s %-12s %-12s %-10s %-10s %-10s\n" ,"--------------" ,"----------", "----------", "--------", "--------", "--------\n");
01208    AST_LIST_LOCK(&cmts_list);
01209    AST_LIST_LOCK(&gate_list);
01210    AST_LIST_TRAVERSE(&gate_list, gate, list) {
01211       if (gate->state == GATE_ALLOC_FAILED) {
01212          ast_copy_string(state_desc, "Failed", sizeof(state_desc));
01213       } else if (gate->state == GATE_ALLOC_PROGRESS) {
01214          ast_copy_string(state_desc, "In Progress", sizeof(state_desc));
01215       } else if (gate->state == GATE_ALLOCATED) {
01216          ast_copy_string(state_desc, "Allocated", sizeof(state_desc));
01217       } else if (gate->state == GATE_CLOSED) {
01218          ast_copy_string(state_desc, "Closed", sizeof(state_desc));
01219       } else if (gate->state == GATE_CLOSED_ERR) {
01220          ast_copy_string(state_desc, "ClosedErr", sizeof(state_desc));
01221       } else if (gate->state == GATE_OPEN) {
01222          ast_copy_string(state_desc, "Open", sizeof(state_desc));
01223       } else if (gate->state == GATE_DELETED) {
01224          ast_copy_string(state_desc, "Deleted", sizeof(state_desc));
01225       } else {
01226          ast_copy_string(state_desc, "N/A", sizeof(state_desc));
01227       }
01228       
01229       ast_cli(a->fd, "%-16s 0x%.8x   0x%08x   %-10s %10i %10i %u\n", (gate->cmts) ? gate->cmts->name : "null" , gate->gateid, gate->mta, 
01230          state_desc, (int) (time(NULL) - gate->allocated), (gate->checked) ? (int) (time(NULL) - gate->checked) : 0, (unsigned int) gate->in_transaction);
01231    }
01232    AST_LIST_UNLOCK(&cmts_list);
01233    AST_LIST_UNLOCK(&gate_list);
01234    return CLI_SUCCESS;
01235 }

static char* pktccops_show_pools ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1237 of file res_pktccops.c.

References ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, cops_ippool::cmts, ast_cli_entry::command, ast_cli_args::fd, cops_ippool::list, cops_cmts::name, cops_ippool::start, cops_ippool::stop, stop, and ast_cli_entry::usage.

01238 {
01239    struct cops_ippool *ippool;
01240    char start[32];
01241    char stop[32];
01242 
01243    switch(cmd) {
01244    case CLI_INIT:
01245       e->command = "pktccops show pools";
01246       e->usage = 
01247          "Usage: pktccops show pools\n"
01248          "       List PacketCable COPS ip pools of MTAs.\n";
01249 
01250       return NULL;
01251    case CLI_GENERATE:
01252       return NULL;
01253    }
01254 
01255    ast_cli(a->fd, "%-16s %-18s %-7s\n", "Start     ", "Stop      ", "CMTS    ");
01256    ast_cli(a->fd, "%-16s %-18s %-7s\n", "----------", "----------", "--------");
01257    AST_LIST_LOCK(&ippool_list);
01258    AST_LIST_TRAVERSE(&ippool_list, ippool, list) {
01259       snprintf(start, sizeof(start), "%3u.%3u.%3u.%3u", ippool->start >> 24, (ippool->start >> 16) & 0x000000ff, (ippool->start >> 8) & 0x000000ff, ippool->start & 0x000000ff);
01260 
01261       snprintf(stop, sizeof(stop), "%3u.%3u.%3u.%3u", ippool->stop >> 24, (ippool->stop >> 16) & 0x000000ff, (ippool->stop >> 8) & 0x000000ff, ippool->stop & 0x000000ff);
01262       ast_cli(a->fd, "%-16s %-18s %-16s\n", start, stop, ippool->cmts->name);
01263    }
01264    AST_LIST_UNLOCK(&ippool_list);
01265    return CLI_SUCCESS;
01266 }

static void pktccops_unregister_cmtses ( void   )  [static]

Definition at line 1436 of file res_pktccops.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, cops_gate::cmts, free, and cops_cmts::sfd.

Referenced by unload_module().

01437 {
01438    struct cops_cmts *cmts;
01439    struct cops_gate *gate;
01440    AST_LIST_LOCK(&cmts_list);
01441    while ((cmts = AST_LIST_REMOVE_HEAD(&cmts_list, list))) {
01442       if (cmts->sfd > 0) {
01443          close(cmts->sfd);
01444       }
01445       free(cmts);
01446    }
01447    AST_LIST_UNLOCK(&cmts_list);
01448 
01449    AST_LIST_LOCK(&gate_list);
01450    while ((gate = AST_LIST_REMOVE_HEAD(&gate_list, list))) {
01451       free(gate);
01452    }
01453    AST_LIST_UNLOCK(&gate_list);
01454 }

static void pktccops_unregister_ippools ( void   )  [static]

Definition at line 1456 of file res_pktccops.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, free, and cops_ippool::list.

Referenced by do_pktccops(), and unload_module().

01457 {
01458    struct cops_ippool *ippool;
01459    AST_LIST_LOCK(&ippool_list);
01460    while ((ippool = AST_LIST_REMOVE_HEAD(&ippool_list, list))) {
01461       free(ippool);
01462    }
01463    AST_LIST_UNLOCK(&ippool_list);
01464 }

static int reload_module ( void   )  [static]

Definition at line 1502 of file res_pktccops.c.

References ast_log(), LOG_NOTICE, and pktcreload.

01503 {
01504    /* Prohibit unloading */
01505    if (pktcreload) {
01506       ast_log(LOG_NOTICE, "Previous reload in progress, please wait!\n");
01507       return -1;
01508    }
01509    pktcreload = 1;
01510    return 0;
01511 }

static int restart_pktc_thread ( void   )  [static]

Definition at line 994 of file res_pktccops.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_pktccops(), LOG_ERROR, LOG_WARNING, and pktccops_lock.

Referenced by load_module().

00995 {
00996    if (pktccops_thread == AST_PTHREADT_STOP) {
00997       return 0;
00998    }
00999    if (ast_mutex_lock(&pktccops_lock)) {
01000       ast_log(LOG_WARNING, "Unable to lock pktccops\n");
01001       return -1;
01002    }
01003    if (pktccops_thread == pthread_self()) {
01004       ast_mutex_unlock(&pktccops_lock);
01005       ast_log(LOG_WARNING, "Cannot kill myself\n");
01006       return -1;
01007    }
01008    if (pktccops_thread != AST_PTHREADT_NULL) {
01009       /* Wake up the thread */
01010       pthread_kill(pktccops_thread, SIGURG);
01011    } else {
01012       /* Start a new monitor */
01013       if (ast_pthread_create_background(&pktccops_thread, NULL, do_pktccops, NULL) < 0) {
01014          ast_mutex_unlock(&pktccops_lock);
01015          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
01016          return -1;
01017       }
01018    }
01019    ast_mutex_unlock(&pktccops_lock);
01020    return 0;
01021 }

static int unload_module ( void   )  [static]

Definition at line 1480 of file res_pktccops.c.

References ast_cli_unregister_multiple(), ast_log(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, cli_pktccops, LOG_ERROR, pktccops_lock, pktccops_unregister_cmtses(), and pktccops_unregister_ippools().

01481 {
01482    if (!ast_mutex_lock(&pktccops_lock)) {
01483       if ((pktccops_thread != AST_PTHREADT_NULL) && (pktccops_thread != AST_PTHREADT_STOP)) {
01484          pthread_cancel(pktccops_thread);
01485          pthread_kill(pktccops_thread, SIGURG);
01486          pthread_join(pktccops_thread, NULL);
01487       }
01488       pktccops_thread = AST_PTHREADT_STOP;
01489       ast_mutex_unlock(&pktccops_lock);
01490    } else {
01491       ast_log(LOG_ERROR, "Unable to lock the pktccops_thread\n");
01492       return -1;
01493    }
01494 
01495    ast_cli_unregister_multiple(cli_pktccops, sizeof(cli_pktccops) / sizeof(struct ast_cli_entry));
01496    pktccops_unregister_cmtses();
01497    pktccops_unregister_ippools();
01498    pktccops_thread = AST_PTHREADT_NULL;
01499    return 0;
01500 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "PktcCOPS manager for MGCP" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload_module, } [static]

Definition at line 1517 of file res_pktccops.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1517 of file res_pktccops.c.

struct ast_cli_entry cli_pktccops[] [static]

Definition at line 1414 of file res_pktccops.c.

Referenced by load_module(), and unload_module().

uint16_t cops_trid = 0 [static]

Definition at line 91 of file res_pktccops.c.

int gateinfoperiod = 60 [static]

Definition at line 164 of file res_pktccops.c.

Referenced by do_pktccops().

int gatetimeout = 150 [static]

Definition at line 165 of file res_pktccops.c.

Referenced by do_pktccops().

uint32_t keepalive = 60 [static]

Definition at line 161 of file res_pktccops.c.

ast_mutex_t pktccops_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 89 of file res_pktccops.c.

Referenced by restart_pktc_thread(), and unload_module().

pthread_t pktccops_thread = AST_PTHREADT_NULL [static]

Definition at line 90 of file res_pktccops.c.

int pktccopsdebug = 0 [static]

Definition at line 162 of file res_pktccops.c.

Referenced by cops_gate_cmd(), and pktccops_debug().

int pktcreload = 0 [static]

Definition at line 163 of file res_pktccops.c.

Referenced by ast_pktccops_gate_alloc(), do_pktccops(), and reload_module().

uint16_t t1 = 250 [static]

Definition at line 158 of file res_pktccops.c.

Referenced by ast_udptl_bridge(), create_match_char_tree(), dahdi_bridge(), is_prefix(), and remote_bridge_loop().

uint16_t t7 = 200 [static]

Definition at line 159 of file res_pktccops.c.

uint16_t t8 = 300 [static]

Definition at line 160 of file res_pktccops.c.


Generated on Wed Apr 6 11:30:09 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7