Thu Sep 7 01:03:37 2017

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)
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(*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 = "ac1f6a56484a8820659555499174e588" , .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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 64 of file res_pktccops.c.

#define COPS_HEADER_SIZE   8

Definition at line 69 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 70 of file res_pktccops.c.

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

#define DEFAULT_COPS_PORT   "2126"

Definition at line 67 of file res_pktccops.c.

Referenced by load_pktccops_config().

#define GATE_INFO_OBJ_SIZE   24

Definition at line 73 of file res_pktccops.c.

Referenced by cops_gate_cmd().

#define GATE_SET_OBJ_SIZE   144

Definition at line 71 of file res_pktccops.c.

Referenced by cops_gate_cmd().

#define GATEID_OBJ_SIZE   8

Definition at line 72 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 695 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_ALLOC   1

Definition at line 75 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ACK   2

Definition at line 76 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_ALLOC_ERR   3

Definition at line 77 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_CLOSE   14

Definition at line 88 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_DELETE   10

Definition at line 84 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_DELETE_ACK   11

Definition at line 85 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_DELETE_ERR   12

Definition at line 86 of file res_pktccops.c.

#define PKTCCOPS_SCOMMAND_GATE_INFO   7

Definition at line 81 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_INFO_ACK   8

Definition at line 82 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_INFO_ERR   9

Definition at line 83 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_OPEN   13

Definition at line 87 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_SET   4

Definition at line 78 of file res_pktccops.c.

Referenced by cops_construct_gate().

#define PKTCCOPS_SCOMMAND_GATE_SET_ACK   5

Definition at line 79 of file res_pktccops.c.

Referenced by do_pktccops().

#define PKTCCOPS_SCOMMAND_GATE_SET_ERR   6

Definition at line 80 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 
) [read]

Definition at line 470 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().

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

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

Definition at line 651 of file res_pktccops.c.

References ast_debug, ast_log(), and LOG_WARNING.

Referenced by do_pktccops().

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

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 223 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().

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

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

Definition at line 184 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().

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

static void cops_freemsg ( struct copsmsg p  )  [static]

Definition at line 455 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().

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

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, read]

Definition at line 497 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_ippool::cmts, cops_gate::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, 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().

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

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

Definition at line 325 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().

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

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

Definition at line 390 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().

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

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

Definition at line 702 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, 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().

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

static uint32_t ftoieeef ( float  n  )  [static]

Definition at line 177 of file res_pktccops.c.

Referenced by cops_construct_gate().

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

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, 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 1025 of file res_pktccops.c.

References ast_calloc, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), AST_LIST_INSERT_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_variable_browse(), cops_ippool::cmts, config, DEFAULT_COPS_PORT, f, gateinfoperiod, gatetimeout, cops_cmts::host, cops_cmts::keepalive, LOG_WARNING, cops_cmts::name, ast_variable::name, cops_cmts::need_delete, ast_variable::next, pktccops_add_ippool(), cops_cmts::port, cops_cmts::sfd, cops_ippool::start, cops_cmts::state, cops_ippool::stop, cops_cmts::t1, cops_cmts::t7, cops_cmts::t8, update(), and ast_variable::value.

Referenced by do_pktccops(), and load_module().

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

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(), and LOG_WARNING.

Referenced by load_pktccops_config().

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 1269 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::name, and ast_cli_entry::usage.

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

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

Definition at line 1329 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, ast_cli_entry::command, cops_gate_cmd(), ast_cli_args::fd, GATE_SET, cops_cmts::name, and ast_cli_entry::usage.

01330 {
01331    int foundcmts = 0;
01332    int trid;
01333    unsigned int an,bn,cn,dn;
01334    uint32_t mta, ssip;
01335    struct cops_cmts *cmts;
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 (!strcmp(a->argv[2], "null")) {
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    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 1153 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::name, cops_cmts::port, cops_cmts::state, and ast_cli_entry::usage.

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

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

Definition at line 1190 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.

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

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

Definition at line 1238 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_cmts::name, cops_ippool::start, cops_ippool::stop, stop, and ast_cli_entry::usage.

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

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, 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, and free.

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 996 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().

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

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, 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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload_module, } [static]

Definition at line 1517 of file res_pktccops.c.

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.

uint16_t cops_trid = 0 [static]

Definition at line 92 of file res_pktccops.c.

int gateinfoperiod = 60 [static]

Definition at line 165 of file res_pktccops.c.

Referenced by do_pktccops(), and load_pktccops_config().

int gatetimeout = 150 [static]

Definition at line 166 of file res_pktccops.c.

Referenced by do_pktccops(), and load_pktccops_config().

uint32_t keepalive = 60 [static]

Definition at line 162 of file res_pktccops.c.

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

Definition at line 90 of file res_pktccops.c.

Referenced by restart_pktc_thread(), and unload_module().

pthread_t pktccops_thread = AST_PTHREADT_NULL [static]

Definition at line 91 of file res_pktccops.c.

int pktccopsdebug = 0 [static]

Definition at line 163 of file res_pktccops.c.

Referenced by cops_gate_cmd(), and pktccops_debug().

int pktcreload = 0 [static]

Definition at line 164 of file res_pktccops.c.

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

uint16_t t1 = 250 [static]

Definition at line 159 of file res_pktccops.c.

Referenced by dahdi_bridge(), and is_prefix().

uint16_t t7 = 200 [static]

Definition at line 160 of file res_pktccops.c.

uint16_t t8 = 300 [static]

Definition at line 161 of file res_pktccops.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1