📄 chan_h323.c
字号:
struct ast_ha *oldha; int found = 0; int format; user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&userl, name, name, 0, 0, strcmp); if (user) found++; else { if (!(user = (struct oh323_user *)calloc(1, sizeof(*user)))) return NULL; ASTOBJ_INIT(user); } oldha = user->ha; user->ha = (struct ast_ha *)NULL; memcpy(&user->options, &global_options, sizeof(user->options)); /* Set default context */ ast_copy_string(user->context, default_context, sizeof(user->context)); if (user && !found) ast_copy_string(user->name, name, sizeof(user->name));#if 0 /* XXX Port channel variables functionality from chan_sip XXX */ if (user->chanvars) { ast_variables_destroy(user->chanvars); user->chanvars = NULL; }#endif for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { if (!update_common_options(v, &user->options)) continue; if (!strcasecmp(v->name, "context")) { ast_copy_string(user->context, v->value, sizeof(user->context)); } else if (!strcasecmp(v->name, "secret")) { ast_copy_string(user->secret, v->value, sizeof(user->secret)); } else if (!strcasecmp(v->name, "accountcode")) { ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode)); } else if (!strcasecmp(v->name, "host")) { if (!strcasecmp(v->value, "dynamic")) { ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n"); ASTOBJ_UNREF(user, oh323_destroy_user); return NULL; } else if (ast_get_ip(&user->addr, v->value)) { ASTOBJ_UNREF(user, oh323_destroy_user); return NULL; } /* Let us know we need to use ip authentication */ user->host = 1; } else if (!strcasecmp(v->name, "amaflags")) { format = ast_cdr_amaflags2int(v->value); if (format < 0) { ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno); } else { user->amaflags = format; } } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { user->ha = ast_append_ha(v->name, v->value, user->ha); } } ASTOBJ_UNMARK(user); ast_free_ha(oldha); return user;}static struct oh323_user *realtime_user(const call_details_t *cd){ struct ast_variable *var, *tmp; struct oh323_user *user; char *username; if (userbyalias) var = ast_load_realtime("h323", "name", username = cd->call_source_aliases, NULL); else { username = (char *)NULL; var = ast_load_realtime("h323", "host", cd->sourceIp, NULL); } if (!var) return NULL; for (tmp = var; tmp; tmp = tmp->next) { if (!strcasecmp(tmp->name, "type") && !(!strcasecmp(tmp->value, "user") || !strcasecmp(tmp->value, "friend"))) { ast_variables_destroy(var); return NULL; } else if (!username && !strcasecmp(tmp->name, "name")) username = tmp->value; } if (!username) { ast_log(LOG_WARNING, "Cannot determine user name for IP address %s\n", cd->sourceIp); ast_variables_destroy(var); return NULL; } user = build_user(username, var, NULL, 1); ast_variables_destroy(var); return user;}static struct oh323_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime){ struct oh323_peer *peer; struct ast_ha *oldha; int found = 0; peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL(&peerl, name, name, 0, 0, strcmp); if (peer) found++; else { if (!(peer = (struct oh323_peer*)calloc(1, sizeof(*peer)))) return NULL; ASTOBJ_INIT(peer); } oldha = peer->ha; peer->ha = NULL; memcpy(&peer->options, &global_options, sizeof(peer->options)); peer->addr.sin_port = htons(h323_signalling_port); peer->addr.sin_family = AF_INET; if (!found && name) ast_copy_string(peer->name, name, sizeof(peer->name));#if 0 /* XXX Port channel variables functionality from chan_sip XXX */ if (peer->chanvars) { ast_variables_destroy(peer->chanvars); peer->chanvars = NULL; }#endif /* Default settings for mailbox */ peer->mailbox[0] = '\0'; for (; v || ((v = alt) && !(alt = NULL)); v = v->next) { if (!update_common_options(v, &peer->options)) continue; if (!strcasecmp(v->name, "host")) { if (!strcasecmp(v->value, "dynamic")) { ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n"); ASTOBJ_UNREF(peer, oh323_destroy_peer); return NULL; } if (ast_get_ip(&peer->addr, v->value)) { ast_log(LOG_ERROR, "Could not determine IP for %s\n", v->value); ASTOBJ_UNREF(peer, oh323_destroy_peer); return NULL; } } else if (!strcasecmp(v->name, "port")) { peer->addr.sin_port = htons(atoi(v->value)); } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) { peer->ha = ast_append_ha(v->name, v->value, peer->ha); } else if (!strcasecmp(v->name, "mailbox")) { ast_copy_string(peer->mailbox, v->value, sizeof(peer->mailbox)); } else if (!strcasecmp(v->name, "hasvoicemail")) { if (ast_true(v->value) && ast_strlen_zero(peer->mailbox)) { ast_copy_string(peer->mailbox, name, sizeof(peer->mailbox)); } } } ASTOBJ_UNMARK(peer); ast_free_ha(oldha); return peer;}static struct oh323_peer *realtime_peer(const char *peername, struct sockaddr_in *sin){ struct oh323_peer *peer; struct ast_variable *var; struct ast_variable *tmp; const char *addr; /* First check on peer name */ if (peername) var = ast_load_realtime("h323", "name", peername, addr = NULL); else if (sin) /* Then check on IP address for dynamic peers */ var = ast_load_realtime("h323", "host", addr = ast_inet_ntoa(sin->sin_addr), NULL); else return NULL; if (!var) return NULL; for (tmp = var; tmp; tmp = tmp->next) { /* If this is type=user, then skip this object. */ if (!strcasecmp(tmp->name, "type") && !(!strcasecmp(tmp->value, "peer") || !strcasecmp(tmp->value, "friend"))) { ast_variables_destroy(var); return NULL; } else if (!peername && !strcasecmp(tmp->name, "name")) { peername = tmp->value; } } if (!peername) { /* Did not find peer in realtime */ ast_log(LOG_WARNING, "Cannot determine peer name for IP address %s\n", addr); ast_variables_destroy(var); return NULL; } /* Peer found in realtime, now build it in memory */ peer = build_peer(peername, var, NULL, 1); ast_variables_destroy(var); return peer;}static int oh323_addrcmp_str(struct in_addr inaddr, char *addr){ return strcmp(ast_inet_ntoa(inaddr), addr);}static struct oh323_user *find_user(const call_details_t *cd, int realtime){ struct oh323_user *u; if (userbyalias) u = ASTOBJ_CONTAINER_FIND(&userl, cd->call_source_aliases); else u = ASTOBJ_CONTAINER_FIND_FULL(&userl, cd->sourceIp, addr.sin_addr, 0, 0, oh323_addrcmp_str); if (!u && realtime) u = realtime_user(cd); if (!u && h323debug) ast_log(LOG_DEBUG, "Could not find user by name %s or address %s\n", cd->call_source_aliases, cd->sourceIp); return u;}static int oh323_addrcmp(struct sockaddr_in addr, struct sockaddr_in *sin){ int res; if (!sin) res = -1; else res = inaddrcmp(&addr , sin); return res;}static struct oh323_peer *find_peer(const char *peer, struct sockaddr_in *sin, int realtime){ struct oh323_peer *p; if (peer) p = ASTOBJ_CONTAINER_FIND(&peerl, peer); else p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, addr, 0, 0, oh323_addrcmp); if (!p && realtime) p = realtime_peer(peer, sin); if (!p && h323debug) ast_log(LOG_DEBUG, "Could not find peer by name %s or address %s\n", (peer ? peer : "<NONE>"), (sin ? ast_inet_ntoa(sin->sin_addr) : "<NONE>")); return p;}static int create_addr(struct oh323_pvt *pvt, char *opeer){ struct hostent *hp; struct ast_hostent ahp; struct oh323_peer *p; int portno; int found = 0; char *port; char *hostn; char peer[256] = ""; ast_copy_string(peer, opeer, sizeof(peer)); port = strchr(peer, ':'); if (port) { *port = '\0'; port++; } pvt->sa.sin_family = AF_INET; p = find_peer(peer, NULL, 1); if (p) { found++; memcpy(&pvt->options, &p->options, sizeof(pvt->options)); pvt->jointcapability = pvt->options.capability; if (pvt->options.dtmfmode) { if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { pvt->nonCodecCapability |= AST_RTP_DTMF; } else { pvt->nonCodecCapability &= ~AST_RTP_DTMF; } } if (p->addr.sin_addr.s_addr) { pvt->sa.sin_addr = p->addr.sin_addr; pvt->sa.sin_port = p->addr.sin_port; } ASTOBJ_UNREF(p, oh323_destroy_peer); } if (!p && !found) { hostn = peer; if (port) { portno = atoi(port); } else { portno = h323_signalling_port; } hp = ast_gethostbyname(hostn, &ahp); if (hp) { memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr)); pvt->sa.sin_port = htons(portno); /* Look peer by address */ p = find_peer(NULL, &pvt->sa, 1); memcpy(&pvt->options, (p ? &p->options : &global_options), sizeof(pvt->options)); pvt->jointcapability = pvt->options.capability; if (p) { ASTOBJ_UNREF(p, oh323_destroy_peer); } if (pvt->options.dtmfmode) { if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { pvt->nonCodecCapability |= AST_RTP_DTMF; } else { pvt->nonCodecCapability &= ~AST_RTP_DTMF; } } return 0; } else { ast_log(LOG_WARNING, "No such host: %s\n", peer); return -1; } } else if (!found) { return -1; } else { return 0; }}static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause){ int oldformat; struct oh323_pvt *pvt; struct ast_channel *tmpc = NULL; char *dest = (char *)data; char *ext, *host; char *h323id = NULL; char tmp[256], tmp1[256]; if (h323debug) ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data); pvt = oh323_alloc(0); if (!pvt) { ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data); return NULL; } oldformat = format; format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1); if (!format) { ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); oh323_destroy(pvt); if (cause) *cause = AST_CAUSE_INCOMPATIBLE_DESTINATION; return NULL; } ast_copy_string(tmp, dest, sizeof(tmp)); host = strchr(tmp, '@'); if (host) { *host = '\0'; host++; ext = tmp; } else { ext = strrchr(tmp, '/'); if (ext) *ext++ = '\0'; host = tmp; } strtok_r(host, "/", &(h323id)); if (!ast_strlen_zero(h323id)) { h323_set_id(h323id); } if (ext) { ast_copy_string(pvt->exten, ext, sizeof(pvt->exten)); } if (h323debug) ast_log(LOG_DEBUG, "Extension: %s Host: %s\n", pvt->exten, host); if (gatekeeper_disable) { if (create_addr(pvt, host)) { oh323_destroy(pvt); if (cause) *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; return NULL; } } else { memcpy(&pvt->options, &global_options, sizeof(pvt->options)); pvt->jointcapability = pvt->options.capability; if (pvt->options.dtmfmode) { if (pvt->options.dtmfmode & H323_DTMF_RFC2833) { pvt->nonCodecCapability |= AST_RTP_DTMF; } else { pvt->nonCodecCapability &= ~AST_RTP_DTMF; } } } ast_mutex_lock(&caplock); /* Generate unique channel identifier */ snprintf(tmp1, sizeof(tmp1)-1, "%s-%u", host, ++unique); tmp1[sizeof(tmp1)-1] = '\0'; ast_mutex_unlock(&caplock); ast_mutex_lock(&pvt->lock); tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1); ast_mutex_unlock(&pvt->lock); if (!tmpc) { oh323_destroy(pvt); if (cause) *cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE; } ast_update_use_count(); restart_monitor(); return tmpc;}/** Find a call by alias */static struct oh323_alias *find_alias(const char *source_aliases, int realtime){ struct oh323_alias *a; a = ASTOBJ_CONTAINER_FIND(&aliasl, source_aliases); if (!a && realtime) a = realtime_alias(source_aliases); return a;}/** * Callback for sending digits from H.323 up to asterisk * */static int receive_digit(unsigned call_reference, char digit, const char *token, int duration){ struct oh323_pvt *pvt; int res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -