📄 chan_gtalk.c
字号:
iq = iks_new("iq"); gtalk = iks_new("session"); dcodecs = iks_new("description"); transport = iks_new("transport"); payload_telephone = iks_new("payload-type"); if (!(iq && gtalk && dcodecs && transport && payload_telephone)){ if(iq) iks_delete(iq); if(gtalk) iks_delete(gtalk); if(dcodecs) iks_delete(dcodecs); if(transport) iks_delete(transport); if(payload_telephone) iks_delete(payload_telephone); ast_log(LOG_ERROR, "Could not allocate iksemel nodes\n"); return 0; } iks_insert_attrib(dcodecs, "xmlns", "http://www.google.com/session/phone"); iks_insert_attrib(dcodecs, "xml:lang", "en"); for (x = 0; x < 32; x++) { if (!(pref_codec = ast_codec_pref_index(&client->prefs, x))) break; if (!(client->capability & pref_codec)) continue; if (alreadysent & pref_codec) continue; codecs_num = add_codec_to_answer(p, pref_codec, dcodecs); alreadysent |= pref_codec; } if (codecs_num) { /* only propose DTMF within an audio session */ iks_insert_attrib(payload_telephone, "id", "106"); iks_insert_attrib(payload_telephone, "name", "telephone-event"); iks_insert_attrib(payload_telephone, "clockrate", "8000"); } iks_insert_attrib(transport,"xmlns","http://www.google.com/transport/p2p"); iks_insert_attrib(iq, "type", "set"); iks_insert_attrib(iq, "to", to); iks_insert_attrib(iq, "from", from); iks_insert_attrib(iq, "id", client->connection->mid); ast_aji_increment_mid(client->connection->mid); iks_insert_attrib(gtalk, "xmlns", "http://www.google.com/session"); iks_insert_attrib(gtalk, "type",initiator ? "initiate": "accept"); iks_insert_attrib(gtalk, "initiator", initiator ? from : to); iks_insert_attrib(gtalk, "id", sid); iks_insert_node(iq, gtalk); iks_insert_node(gtalk, dcodecs); iks_insert_node(gtalk, transport); iks_insert_node(dcodecs, payload_telephone); iks_send(client->connection->p, iq); iks_delete(payload_telephone); iks_delete(transport); iks_delete(dcodecs); iks_delete(gtalk); iks_delete(iq); return 1;}static int gtalk_invite_response(struct gtalk_pvt *p, char *to , char *from, char *sid, int initiator){ iks *iq, *session, *transport; iq = iks_new("iq"); session = iks_new("session"); transport = iks_new("transport"); if(!(iq && session && transport)) { if(iq) iks_delete(iq); if(session) iks_delete(session); if(transport) iks_delete(transport); ast_log(LOG_ERROR, " Unable to allocate IKS node\n"); return -1; } iks_insert_attrib(iq, "from", from); iks_insert_attrib(iq, "to", to); iks_insert_attrib(iq, "type", "set"); iks_insert_attrib(iq, "id",p->parent->connection->mid); ast_aji_increment_mid(p->parent->connection->mid); iks_insert_attrib(session, "type", "transport-accept"); iks_insert_attrib(session, "id", sid); iks_insert_attrib(session, "initiator", initiator ? from : to); iks_insert_attrib(session, "xmlns", "http://www.google.com/session"); iks_insert_attrib(transport, "xmlns", "http://www.google.com/transport/p2p"); iks_insert_node(iq,session); iks_insert_node(session,transport); iks_send(p->parent->connection->p, iq); iks_delete(transport); iks_delete(session); iks_delete(iq); return 1;}static int gtalk_ringing_ack(void *data, ikspak *pak){ struct gtalk_pvt *p = data; if (p->ringrule) iks_filter_remove_rule(p->parent->connection->f, p->ringrule); p->ringrule = NULL; if (p->owner) ast_queue_control(p->owner, AST_CONTROL_RINGING); return IKS_FILTER_EAT;}static int gtalk_answer(struct ast_channel *ast){ struct gtalk_pvt *p = ast->tech_pvt; int res = 0; if (option_debug) ast_log(LOG_DEBUG, "Answer!\n"); ast_mutex_lock(&p->lock); gtalk_invite(p, p->them, p->us,p->sid, 0); ast_mutex_unlock(&p->lock); return res;}static enum ast_rtp_get_result gtalk_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp){ struct gtalk_pvt *p = chan->tech_pvt; enum ast_rtp_get_result res = AST_RTP_GET_FAILED; if (!p) return res; ast_mutex_lock(&p->lock); if (p->rtp){ *rtp = p->rtp; res = AST_RTP_TRY_PARTIAL; } ast_mutex_unlock(&p->lock); return res;}static int gtalk_get_codec(struct ast_channel *chan){ struct gtalk_pvt *p = chan->tech_pvt; return p->peercapability;}static int gtalk_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active){ struct gtalk_pvt *p; p = chan->tech_pvt; if (!p) return -1; ast_mutex_lock(&p->lock);/* if (rtp) ast_rtp_get_peer(rtp, &p->redirip); else memset(&p->redirip, 0, sizeof(p->redirip)); p->redircodecs = codecs; */ /* Reset lastrtprx timer */ ast_mutex_unlock(&p->lock); return 0;}static int gtalk_response(struct gtalk *client, char *from, ikspak *pak, const char *reasonstr, const char *reasonstr2){ iks *response = NULL, *error = NULL, *reason = NULL; int res = -1; response = iks_new("iq"); if (response) { iks_insert_attrib(response, "type", "result"); iks_insert_attrib(response, "from", from); iks_insert_attrib(response, "to", iks_find_attrib(pak->x, "from")); iks_insert_attrib(response, "id", iks_find_attrib(pak->x, "id")); if (reasonstr) { error = iks_new("error"); if (error) { iks_insert_attrib(error, "type", "cancel"); reason = iks_new(reasonstr); if (reason) iks_insert_node(error, reason); iks_insert_node(response, error); } } iks_send(client->connection->p, response); if (reason) iks_delete(reason); if (error) iks_delete(error); iks_delete(response); res = 0; } return res;}static int gtalk_is_answered(struct gtalk *client, ikspak *pak){ struct gtalk_pvt *tmp; char *from; iks *codec; char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ]; int peernoncodeccapability; ast_log(LOG_DEBUG, "The client is %s\n", client->name); /* Make sure our new call doesn't exist yet */ for (tmp = client->p; tmp; tmp = tmp->next) { if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) break; } /* codec points to the first <payload-type/> tag */ codec = iks_child(iks_child(iks_child(pak->x))); while (codec) { ast_rtp_set_m_type(tmp->rtp, atoi(iks_find_attrib(codec, "id"))); ast_rtp_set_rtpmap_type(tmp->rtp, atoi(iks_find_attrib(codec, "id")), "audio", iks_find_attrib(codec, "name"), 0); codec = iks_next(codec); } /* Now gather all of the codecs that we are asked for */ ast_rtp_get_current_formats(tmp->rtp, &tmp->peercapability, &peernoncodeccapability); /* at this point, we received an awser from the remote Gtalk client, which allows us to compare capabilities */ tmp->jointcapability = tmp->capability & tmp->peercapability; if (!tmp->jointcapability) { ast_log(LOG_WARNING, "Capabilities don't match : us - %s, peer - %s, combined - %s \n", ast_getformatname_multiple(s1, BUFSIZ, tmp->capability), ast_getformatname_multiple(s2, BUFSIZ, tmp->peercapability), ast_getformatname_multiple(s3, BUFSIZ, tmp->jointcapability)); /* close session if capabilities don't match */ ast_queue_hangup(tmp->owner); return -1; } from = iks_find_attrib(pak->x, "to"); if(!from) from = client->connection->jid->full; if (tmp) { if (tmp->owner) ast_queue_control(tmp->owner, AST_CONTROL_ANSWER); } else ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); gtalk_response(client, from, pak, NULL, NULL); return 1;}static int gtalk_is_accepted(struct gtalk *client, ikspak *pak){ struct gtalk_pvt *tmp; char *from; ast_log(LOG_DEBUG, "The client is %s\n", client->name); /* find corresponding call */ for (tmp = client->p; tmp; tmp = tmp->next) { if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) break; } from = iks_find_attrib(pak->x, "to"); if(!from) from = client->connection->jid->full; if (!tmp) ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); /* answer 'iq' packet to let the remote peer know that we're alive */ gtalk_response(client, from, pak, NULL, NULL); return 1;}static int gtalk_handle_dtmf(struct gtalk *client, ikspak *pak){ struct gtalk_pvt *tmp; iks *dtmfnode = NULL, *dtmfchild = NULL; char *dtmf; char *from; /* Make sure our new call doesn't exist yet */ for (tmp = client->p; tmp; tmp = tmp->next) { if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid) || iks_find_with_attrib(pak->x, "gtalk", "sid", tmp->sid)) break; } from = iks_find_attrib(pak->x, "to"); if(!from) from = client->connection->jid->full; if (tmp) { if(iks_find_with_attrib(pak->x, "dtmf-method", "method", "rtp")) { gtalk_response(client, from, pak, "feature-not-implemented xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'", "unsupported-dtmf-method xmlns='http://jabber.org/protocol/gtalk/info/dtmf#errors'"); return -1; } if ((dtmfnode = iks_find(pak->x, "dtmf"))) { if((dtmf = iks_find_attrib(dtmfnode, "code"))) { if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-up")) { struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; f.subclass = dtmf[0]; ast_queue_frame(tmp->owner, &f); ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); } else if(iks_find_with_attrib(pak->x, "dtmf", "action", "button-down")) { struct ast_frame f = {AST_FRAME_DTMF_END, }; f.subclass = dtmf[0]; ast_queue_frame(tmp->owner, &f); ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); } else if(iks_find_attrib(pak->x, "dtmf")) { /* 250 millasecond default */ struct ast_frame f = {AST_FRAME_DTMF, }; f.subclass = dtmf[0]; ast_queue_frame(tmp->owner, &f); ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); } } } else if ((dtmfnode = iks_find_with_attrib(pak->x, "gtalk", "action", "session-info"))) { if((dtmfchild = iks_find(dtmfnode, "dtmf"))) { if((dtmf = iks_find_attrib(dtmfchild, "code"))) { if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-up")) { struct ast_frame f = {AST_FRAME_DTMF_END, }; f.subclass = dtmf[0]; ast_queue_frame(tmp->owner, &f); ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); } else if(iks_find_with_attrib(dtmfnode, "dtmf", "action", "button-down")) { struct ast_frame f = {AST_FRAME_DTMF_BEGIN, }; f.subclass = dtmf[0]; ast_queue_frame(tmp->owner, &f); ast_verbose("GOOGLE! DTMF-relay event received: %c\n", f.subclass); } } } } gtalk_response(client, from, pak, NULL, NULL); return 1; } else ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); gtalk_response(client, from, pak, NULL, NULL); return 1;}static int gtalk_hangup_farend(struct gtalk *client, ikspak *pak){ struct gtalk_pvt *tmp; char *from; ast_log(LOG_DEBUG, "The client is %s\n", client->name); /* Make sure our new call doesn't exist yet */ for (tmp = client->p; tmp; tmp = tmp->next) { if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) break; } from = iks_find_attrib(pak->x, "to"); if(!from) from = client->connection->jid->full; if (tmp) { tmp->alreadygone = 1; if (tmp->owner) ast_queue_hangup(tmp->owner); } else ast_log(LOG_NOTICE, "Whoa, didn't find call!\n"); gtalk_response(client, from, pak, NULL, NULL); return 1;}static int gtalk_create_candidates(struct gtalk *client, struct gtalk_pvt *p, char *sid, char *from, char *to){ struct gtalk_candidate *tmp; struct aji_client *c = client->connection; struct gtalk_candidate *ours1 = NULL, *ours2 = NULL; struct sockaddr_in sin; struct sockaddr_in dest; struct in_addr us; iks *iq, *gtalk, *candidate, *transport; char user[17], pass[17], preference[5], port[7]; iq = iks_new("iq"); gtalk = iks_new("session"); candidate = iks_new("candidate"); transport = iks_new("transport"); if (!iq || !gtalk || !candidate || !transport) { ast_log(LOG_ERROR, "Memory allocation error\n"); goto safeout; } ours1 = ast_calloc(1, sizeof(*ours1)); ours2 = ast_calloc(1, sizeof(*ours2)); if (!ours1 || !ours2) goto safeout; iks_insert_attrib(transport, "xmlns","http://www.google.com/transport/p2p"); iks_insert_node(iq, gtalk); iks_insert_node(gtalk,transport); iks_insert_node(transport, candidate); for (; p; p = p->next) { if (!strcasecmp(p->sid, sid)) break; } if (!p) { ast_log(LOG_NOTICE, "No matching gtalk session - SID %s!\n", sid); goto safeout; } ast_rtp_get_us(p->rtp, &sin);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -