Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:52 2007

Asterisk developer's documentation :: Codename Pineapple


sip3_sdprtp.c File Reference


Detailed Description

Various SIP SDP and RTP handling functions Version 3 of chan_sip.

Author:
Mark Spencer <markster@digium.com>

Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)

See Also:

Definition in file sip3_sdprtp.c.

#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"

Include dependency graph for sip3_sdprtp.c:

Go to the source code of this file.

Functions

static void add_codec_to_sdp (const struct sip_dialog *p, int codec, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug, int *min_packet_size)
 Add codec offer to SDP offer/answer body in INVITE or 200 OK.
static void add_noncodec_to_sdp (const struct sip_dialog *p, int format, int sample_rate, char **m_buf, size_t *m_size, char **a_buf, size_t *a_size, int debug)
 Add RFC 2833 DTMF offer to SDP.
int add_sdp (struct sip_request *resp, struct sip_dialog *p)
 Add Session Description Protocol message.
int find_sdp (struct sip_request *req)
 Determine whether a SIP message contains an SDP in its body.
char * get_body (struct sip_request *req, char *name)
 Get the message body part identified by name=.
static char * get_body_by_line (const char *line, const char *name, int nameLen)
 Reads one line of SIP message body.
static void get_our_media_address (struct sip_dialog *p, int needvideo, struct sockaddr_in *sin, struct sockaddr_in *vsin, struct sockaddr_in *dest, struct sockaddr_in *vdest)
 Set all IP media addresses for this call.
static const char * get_sdp (struct sip_request *req, const char *name)
 Get a line from an SDP message body.
static const char * get_sdp_iterate (int *start, struct sip_request *req, const char *name)
 Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number.
int process_sdp (struct sip_dialog *p, struct sip_request *req)
 Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call.
void register_rtp_and_udptl (void)
 Register RTP and UDPTL to the subsystems.
static int sip_get_codec (struct ast_channel *chan)
 Return SIP UA's codec (part of the RTP interface).
enum ast_rtp_get_result sip_get_rtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
 Returns null if we can't reinvite audio (part of RTP interface).
static struct ast_udptlsip_get_udptl_peer (struct ast_channel *chan)
 Get UDPTL peer address (part of UDPTL interface).
enum ast_rtp_get_result sip_get_vrtp_peer (struct ast_channel *chan, struct ast_rtp **rtp)
 Returns null if we can't reinvite video (part of RTP interface).
GNURK struct ast_framesip_read (struct ast_channel *ast)
 Read SIP RTP from channel.
static struct ast_framesip_rtp_read (struct ast_channel *ast, struct sip_dialog *p, int *faxdetect)
 Read RTP from network.
int sip_set_rtp_peer (struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
 Set the RTP peer for this call.
static int sip_set_udptl_peer (struct ast_channel *chan, struct ast_udptl *udptl)
 Determine UDPTL peer address for re-invite (part of UDPTL interface).
void stop_media_flows (struct sip_dialog *dialog)
 Immediately stop RTP, VRTP and UDPTL as applicable.
void unregister_rtp_and_udptl (void)
 UNRegister RTP and UDPTL to the subsystems.

Variables

static struct ast_rtp_protocol sip_rtp
 Interface structure with callbacks used to connect to RTP module.
static struct ast_udptl_protocol sip_udptl
 Interface structure with callbacks used to connect to UDPTL module.


Function Documentation

static void add_codec_to_sdp const struct sip_dialog p,
int  codec,
int  sample_rate,
char **  m_buf,
size_t *  m_size,
char **  a_buf,
size_t *  a_size,
int  debug,
int *  min_packet_size
[static]
 

Add codec offer to SDP offer/answer body in INVITE or 200 OK.

Definition at line 957 of file sip3_sdprtp.c.

References ast_build_string(), ast_codec_pref_getsize(), AST_FORMAT_G729A, AST_FORMAT_ILBC, ast_getformatname(), ast_rtp_codec_getpref(), ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), AST_RTP_OPT_G726_NONSTANDARD, ast_test_flag, ast_verbose(), sip_dialog::flags, fmt, sip_dialog::rtp, and SIP_G726_NONSTANDARD.

00960 {
00961    int rtp_code;
00962    struct ast_format_list fmt;
00963 
00964 
00965    if (debug)
00966       ast_verbose("Adding codec 0x%x (%s) to SDP\n", codec, ast_getformatname(codec));
00967    if ((rtp_code = ast_rtp_lookup_code(p->rtp, 1, codec)) == -1)
00968       return;
00969 
00970    if (p->rtp) {
00971       struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
00972       fmt = ast_codec_pref_getsize(pref, codec);
00973    } else /* I dont see how you couldn't have p->rtp, but good to check for and error out if not there like earlier code */
00974       return;
00975    ast_build_string(m_buf, m_size, " %d", rtp_code);
00976    ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
00977           ast_rtp_lookup_mime_subtype(1, codec,
00978                        ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0),
00979           sample_rate);
00980    if (codec == AST_FORMAT_G729A) {
00981       /* Indicate that we don't support VAD (G.729 annex B) */
00982       ast_build_string(a_buf, a_size, "a=fmtp:%d annexb=no\r\n", rtp_code);
00983    } else if (codec == AST_FORMAT_ILBC) {
00984       /* Add information about us using only 20/30 ms packetization */
00985       ast_build_string(a_buf, a_size, "a=fmtp:%d mode=%d\r\n", rtp_code, fmt.cur_ms);
00986    }
00987 
00988    if (fmt.cur_ms && (fmt.cur_ms < *min_packet_size))
00989       *min_packet_size = fmt.cur_ms;
00990 
00991    /* Our first codec packetization processed cannot be zero */
00992    if ((*min_packet_size)==0 && fmt.cur_ms)
00993       *min_packet_size = fmt.cur_ms;
00994 }

static void add_noncodec_to_sdp const struct sip_dialog p,
int  format,
int  sample_rate,
char **  m_buf,
size_t *  m_size,
char **  a_buf,
size_t *  a_size,
int  debug
[static]
 

Add RFC 2833 DTMF offer to SDP.

Definition at line 936 of file sip3_sdprtp.c.

References ast_build_string(), AST_RTP_DTMF, ast_rtp_lookup_code(), ast_rtp_lookup_mime_subtype(), ast_verbose(), and sip_dialog::rtp.

00939 {
00940    int rtp_code;
00941 
00942    if (debug)
00943       ast_verbose("Adding non-codec 0x%x (%s) to SDP\n", format, ast_rtp_lookup_mime_subtype(0, format, 0));
00944    if ((rtp_code = ast_rtp_lookup_code(p->rtp, 0, format)) == -1)
00945       return;
00946 
00947    ast_build_string(m_buf, m_size, " %d", rtp_code);
00948    ast_build_string(a_buf, a_size, "a=rtpmap:%d %s/%d\r\n", rtp_code,
00949           ast_rtp_lookup_mime_subtype(0, format, 0),
00950           sample_rate);
00951    if (format == AST_RTP_DTMF)
00952       /* Indicate we support DTMF and FLASH... */
00953       ast_build_string(a_buf, a_size, "a=fmtp:%d 0-16\r\n", rtp_code);
00954 }

int add_sdp struct sip_request resp,
struct sip_dialog p
 

Add Session Description Protocol message.

Todo:
XXX We need to select one codec, not many, since there's no transcoding

Definition at line 1029 of file sip3_sdprtp.c.

References add_codec_to_sdp(), ast_build_string(), ast_codec_pref_index(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, ast_getformatname_multiple(), ast_inet_ntoa(), ast_log(), ast_test_flag, ast_verbose(), capability, FALSE, sip_dialog::flags, get_our_media_address(), sip_dialog::jointcapability, len, LOG_WARNING, sip_dialog::maxcallbitrate, option_debug, sip_dialog::ourip, sip_dialog::prefcodec, sip_dialog::prefs, sip_dialog::rtp, sip_dialog::sessionid, sip_dialog::sessionversion, sip_debug_test_pvt(), SIP_NOVIDEO, SIP_PAGE2_CALL_ONHOLD_INACTIVE, SIP_PAGE2_CALL_ONHOLD_ONEDIR, SIP_PAGE2_T38SUPPORT_RTP, sip_dialog::t38, t38properties::t38support, TRUE, and sip_dialog::vrtp.

01030 {
01031    int len = 0;
01032    int alreadysent = 0;
01033 
01034    struct sockaddr_in sin;
01035    struct sockaddr_in vsin;
01036    struct sockaddr_in dest;
01037    struct sockaddr_in vdest = { 0, };
01038 
01039    /* SDP fields */
01040    char *version =   "v=0\r\n";     /* Protocol version */
01041    char *subject =   "s=session\r\n";  /* Subject of the session */
01042    char owner[256];           /* Session owner/creator */
01043    char connection[256];            /* Connection data */
01044    char *stime = "t=0 0\r\n";          /* Time the session is active */
01045    char bandwidth[256] = "";        /* Max bitrate */
01046    char *hold;
01047    char m_audio[256];            /* Media declaration line for audio */
01048    char m_video[256];            /* Media declaration line for video */
01049    char a_audio[1024];           /* Attributes for audio */
01050    char a_video[1024];           /* Attributes for video */
01051    char *m_audio_next = m_audio;
01052    char *m_video_next = m_video;
01053    size_t m_audio_left = sizeof(m_audio);
01054    size_t m_video_left = sizeof(m_video);
01055    char *a_audio_next = a_audio;
01056    char *a_video_next = a_video;
01057    size_t a_audio_left = sizeof(a_audio);
01058    size_t a_video_left = sizeof(a_video);
01059 
01060    int x;
01061    int capability;
01062    int needvideo = FALSE;
01063    int debug = sip_debug_test_pvt(p);
01064    int min_audio_packet_size = 0;
01065    int min_video_packet_size = 0;
01066 
01067    m_video[0] = '\0';   /* Reset the video media string if it's not needed */
01068 
01069    if (!p->rtp) {
01070       ast_log(LOG_WARNING, "No way to add SDP without an RTP structure\n");
01071       return -1;
01072    }
01073 
01074    /* Set RTP Session ID and version */
01075    if (!p->sessionid) {
01076       p->sessionid = getpid();
01077       p->sessionversion = p->sessionid;
01078    } else
01079       p->sessionversion++;
01080 
01081    /* Ok, let's start working with codec selection here */
01082    capability = p->jointcapability;
01083 
01084    if (option_debug > 1) {
01085       char codecbuf[BUFSIZ];
01086       ast_log(LOG_DEBUG, "** Our capability: %s Video flag: %s\n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), capability), ast_test_flag(&p->flags[0], SIP_NOVIDEO) ? "True" : "False");
01087       ast_log(LOG_DEBUG, "** Our prefcodec: %s \n", ast_getformatname_multiple(codecbuf, sizeof(codecbuf), p->prefcodec));
01088    }
01089    
01090 #ifdef WHEN_WE_HAVE_T38_FOR_OTHER_TRANSPORTS
01091    if ((ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_RTP))) {
01092       ast_build_string(&m_audio_next, &m_audio_left, " %d", 191);
01093       ast_build_string(&a_audio_next, &a_audio_left, "a=rtpmap:%d %s/%d\r\n", 191, "t38", 8000);
01094    }
01095 #endif
01096 
01097    /* Check if we need video in this call */
01098    if((capability & AST_FORMAT_VIDEO_MASK) && !ast_test_flag(&p->flags[0], SIP_NOVIDEO)) {
01099       if (p->vrtp) {
01100          needvideo = TRUE;
01101          if (option_debug > 1)
01102             ast_log(LOG_DEBUG, "This call needs video offers! \n");
01103       } else if (option_debug > 1)
01104          ast_log(LOG_DEBUG, "This call needs video offers, but there's no video support enabled ! \n");
01105    }
01106 
01107    /* Get our media IP addresses for RTP */
01108    get_our_media_address(p, needvideo, &sin, &vsin, &dest, &vdest);
01109 
01110    /* Ok, we need video. Let's add what we need for video and set codecs.
01111       Video is handled differently than audio since we can not transcode. */
01112    if (needvideo) {
01113       ast_build_string(&m_video_next, &m_video_left, "m=video %d RTP/AVP", ntohs(vdest.sin_port));
01114 
01115       /* Build max bitrate string */
01116       if (p->maxcallbitrate)
01117          snprintf(bandwidth, sizeof(bandwidth), "b=CT:%d\r\n", p->maxcallbitrate);
01118       if (debug) 
01119          ast_verbose("Video is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(vsin.sin_port));   
01120 
01121       /*! \todo XXX We need to select one codec, not many, since there's no transcoding */
01122    }
01123    if (debug) 
01124       ast_verbose("Audio is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(sin.sin_port)); 
01125 
01126    /* Start building generic SDP headers */
01127 
01128    /* We break with the "recommendation" and send our IP, in order that our
01129       peer doesn't have to ast_gethostbyname() us */
01130 
01131    snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
01132    snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
01133    ast_build_string(&m_audio_next, &m_audio_left, "m=audio %d RTP/AVP", ntohs(dest.sin_port));
01134 
01135    if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR))
01136       hold = "a=recvonly\r\n";
01137    else if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE))
01138       hold = "a=inactive\r\n";
01139    else
01140       hold = "a=sendrecv\r\n";
01141 
01142    /* Now, start adding audio codecs. These are added in this order:
01143       - First what was requested by the calling channel
01144       - Then preferences in order from sip.conf device config for this peer/user
01145       - Then other codecs in capabilities, including video
01146    */
01147 
01148    /* Prefer the audio codec we were requested to use, first, no matter what 
01149       Note that p->prefcodec can include video codecs, so mask them out
01150     */
01151    if (capability & p->prefcodec) {
01152       add_codec_to_sdp(p, p->prefcodec & AST_FORMAT_AUDIO_MASK, 8000,
01153              &m_audio_next, &m_audio_left,
01154              &a_audio_next, &a_audio_left,
01155              debug, &min_audio_packet_size);
01156       alreadysent |= p->prefcodec & AST_FORMAT_AUDIO_MASK;
01157    }
01158 
01159 
01160    /* Start by sending our preferred audio codecs */
01161    for (x = 0; x < 32; x++) {
01162       int pref_codec;
01163 
01164       if (!(pref_codec = ast_codec_pref_index(&p->prefs, x)))
01165          break; 
01166 
01167       if (!(capability & pref_codec))
01168          continue;
01169 
01170       if (alreadysent & pref_codec)
01171          continue;
01172 
01173       add_codec_to_sdp(p, pref_codec, 8000,
01174              &m_audio_next, &m_audio_left,
01175              &a_audio_next, &a_audio_left,
01176              debug, &min_audio_packet_size);
01177       alreadysent |= pref_codec;
01178    }
01179 
01180    /* Now send any other common audio and video codecs, and non-codec formats: */
01181    for (x = 1; x <= (needvideo ? AST_FORMAT_MAX_VIDEO : AST_FORMAT_MAX_AUDIO); x <<= 1) {
01182       if (!(capability & x))  /* Codec not requested */
01183          continue;
01184 
01185       if (alreadysent & x) /* Already added to SDP */
01186          continue;
01187 
01188       if (x <= AST_FORMAT_MAX_AUDIO)
01189          add_codec_to_sdp(p, x, 8000,
01190                 &m_audio_next, &m_audio_left,
01191                 &a_audio_next, &a_audio_left,
01192                 debug, &min_audio_packet_size);
01193       else 
01194          add_codec_to_sdp(p, x, 90000,
01195                 &m_video_next, &m_video_left,
01196                 &a_video_next, &a_video_left,
01197                 debug, &min_video_packet_size);
01198    }
01199 
01200    /* Now add DTMF RFC2833 telephony-event as a codec */
01201    for (x = 1; x <= AST_RTP_MAX; x <<= 1) {
01202       if (!(p->jointnoncodeccapability & x))
01203          continue;
01204 
01205       add_noncodec_to_sdp(p, x, 8000,
01206                 &m_audio_next, &m_audio_left,
01207                 &a_audio_next, &a_audio_left,
01208                 debug);
01209    }
01210 
01211    if (option_debug > 2)
01212       ast_log(LOG_DEBUG, "-- Done with adding codecs to SDP\n");
01213 
01214    if(!p->owner || !ast_internal_timing_enabled(p->owner))
01215       ast_build_string(&a_audio_next, &a_audio_left, "a=silenceSupp:off - - - -\r\n");
01216    if (min_audio_packet_size)
01217       ast_build_string(&a_audio_next, &a_audio_left, "a=ptime:%d\r\n", min_audio_packet_size);
01218 
01219    if (min_video_packet_size)
01220       ast_build_string(&a_video_next, &a_video_left, "a=ptime:%d\r\n", min_video_packet_size);
01221 
01222 
01223    if ((m_audio_left < 2) || (m_video_left < 2) || (a_audio_left == 0) || (a_video_left == 0))
01224       ast_log(LOG_WARNING, "SIP SDP may be truncated due to undersized buffer!!\n");
01225 
01226    ast_build_string(&m_audio_next, &m_audio_left, "\r\n");
01227    if (needvideo)
01228       ast_build_string(&m_video_next, &m_video_left, "\r\n");
01229 
01230    len = strlen(version) + strlen(subject) + strlen(owner) + strlen(connection) + strlen(stime) + strlen(m_audio) + strlen(a_audio) + strlen(hold);
01231    if (needvideo) /* only if video response is appropriate */
01232       len += strlen(m_video) + strlen(a_video) + strlen(bandwidth) + strlen(hold);
01233 
01234    add_header(resp, "Content-Type", "application/sdp");
01235    add_header_contentLength(resp, len);
01236    add_line(resp, version);
01237    add_line(resp, owner);
01238    add_line(resp, subject);
01239    add_line(resp, connection);
01240    if (needvideo)    /* only if video response is appropriate */
01241       add_line(resp, bandwidth);
01242    add_line(resp, stime);
01243    add_line(resp, m_audio);
01244    add_line(resp, a_audio);
01245    add_line(resp, hold);
01246    if (needvideo) { /* only if video response is appropriate */
01247       add_line(resp, m_video);
01248       add_line(resp, a_video);
01249       add_line(resp, hold);   /* Repeat hold for the video stream */
01250    }
01251 
01252    /* Update lastrtprx when we send our SDP */
01253    p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
01254 
01255    if (option_debug > 2) {
01256       char buf[BUFSIZ];
01257       ast_log(LOG_DEBUG, "Done building SDP. Settling with this capability: %s\n", ast_getformatname_multiple(buf, BUFSIZ, capability));
01258    }
01259 
01260    return 0;
01261 }

int find_sdp struct sip_request req  ) 
 

Determine whether a SIP message contains an SDP in its body.

Parameters:
req the SIP request to process
Returns:
TRUE if SDP found, FALSE if not found
Also updates req->sdp_start and req->sdp_end to indicate where the SDP lives in the message body.

Definition at line 880 of file sip3_sdprtp.c.

References ast_strdupa, ast_strlen_zero(), FALSE, get_header(), sip_request::line, sip_request::lines, sip_request::sdp_end, sip_request::sdp_start, strcasestr(), and TRUE.

00881 {
00882    const char *content_type;
00883    const char *search;
00884    char *boundary;
00885    unsigned int x;
00886 
00887    content_type = get_header(req, "Content-Type");
00888 
00889    /* if the body contains only SDP, this is easy */
00890    if (!strcasecmp(content_type, "application/sdp")) {
00891       req->sdp_start = 0;
00892       req->sdp_end = req->lines;
00893       return TRUE;
00894    }
00895 
00896    /* if it's not multipart/mixed, there cannot be an SDP */
00897    if (strncasecmp(content_type, "multipart/mixed", 15))
00898       return FALSE;
00899 
00900    /* if there is no boundary marker, it's invalid */
00901    if (!(search = strcasestr(content_type, ";boundary=")))
00902       return FALSE;
00903 
00904    search += 10;
00905 
00906    if (ast_strlen_zero(search))
00907       return FALSE;
00908 
00909    /* make a duplicate of the string, with two extra characters
00910       at the beginning */
00911    boundary = ast_strdupa(search - 2);
00912    boundary[0] = boundary[1] = '-';
00913 
00914    /* search for the boundary marker, but stop when there are not enough
00915       lines left for it, the Content-Type header and at least one line of
00916       body */
00917    for (x = 0; x < (req->lines - 2); x++) {
00918       if (!strncasecmp(req->line[x], boundary, strlen(boundary)) &&
00919           !strcasecmp(req->line[x + 1], "Content-Type: application/sdp")) {
00920          x += 2;
00921          req->sdp_start = x;
00922          /* search for the end of the body part */
00923          for ( ; x < req->lines; x++) {
00924             if (!strncasecmp(req->line[x], boundary, strlen(boundary)))
00925                break;
00926          }
00927          req->sdp_end = x;
00928          return TRUE;
00929       }
00930    }
00931 
00932    return FALSE;
00933 }

GNURK char * get_body struct sip_request req,
char *  name
 

Get the message body part identified by name=.

Definition at line 166 of file sip3_sdprtp.c.

References get_body_by_line(), len, sip_request::line, and sip_request::lines.

00167 {
00168    int x;
00169    int len = strlen(name);
00170    char *r;
00171 
00172    for (x = 0; x < req->lines; x++) {
00173       r = get_body_by_line(req->line[x], name, len);
00174       if (r[0] != '\0')
00175          return r;
00176    }
00177 
00178    return "";
00179 }

static char* get_body_by_line const char *  line,
const char *  name,
int  nameLen
[static]
 

Reads one line of SIP message body.

Definition at line 132 of file sip3_sdprtp.c.

00133 {
00134    if (strncasecmp(line, name, nameLen) == 0 && line[nameLen] == '=')
00135       return ast_skip_blanks(line + nameLen + 1);
00136 
00137    return "";
00138 }

static void get_our_media_address struct sip_dialog p,
int  needvideo,
struct sockaddr_in *  sin,
struct sockaddr_in *  vsin,
struct sockaddr_in *  dest,
struct sockaddr_in *  vdest
[static]
 

Set all IP media addresses for this call.

Note:
called from add_sdp()

Definition at line 999 of file sip3_sdprtp.c.

References ast_rtp_get_us(), sip_dialog::ourip, sip_dialog::redirip, sip_dialog::rtp, sip_dialog::vredirip, and sip_dialog::vrtp.

01000 {
01001        /* First, get our address */
01002        ast_rtp_get_us(p->rtp, sin);
01003        if (p->vrtp)
01004                ast_rtp_get_us(p->vrtp, vsin);
01005 
01006        /* Now, try to figure out where we want them to send data */
01007        /* Is this a re-invite to move the media out, then use the original offer from caller  */
01008        if (p->redirip.sin_addr.s_addr) {       /* If we have a redirection IP, use it */
01009                dest->sin_port = p->redirip.sin_port;
01010                dest->sin_addr = p->redirip.sin_addr;
01011        } else {
01012                dest->sin_addr = p->ourip;
01013                dest->sin_port = sin->sin_port;
01014        }
01015        if (needvideo) {
01016                /* Determine video destination */
01017                if (p->vredirip.sin_addr.s_addr) {
01018                        vdest->sin_addr = p->vredirip.sin_addr;
01019                        vdest->sin_port = p->vredirip.sin_port;
01020                } else {
01021                        vdest->sin_addr = p->ourip;
01022                        vdest->sin_port = vsin->sin_port;
01023                }
01024        }
01025 
01026 }

static const char* get_sdp struct sip_request req,
const char *  name
[static]
 

Get a line from an SDP message body.

Definition at line 158 of file sip3_sdprtp.c.

References get_sdp_iterate().

00159 {
00160    int dummy = 0;
00161 
00162    return get_sdp_iterate(&dummy, req, name);
00163 }

static const char* get_sdp_iterate int *  start,
struct sip_request req,
const char *  name
[static]
 

Lookup 'name' in the SDP starting at the 'start' line. Returns the matching line, and 'start' is updated with the next line number.

Definition at line 144 of file sip3_sdprtp.c.

References get_body_by_line(), len, and sip_request::line.

00145 {
00146    int len = strlen(name);
00147 
00148    while (*start < req->sdp_end) {
00149       const char *r = get_body_by_line(req->line[(*start)++], name, len);
00150       if (r[0] != '\0')
00151          return r;
00152    }
00153 
00154    return "";
00155 }

int process_sdp struct sip_dialog p,
struct sip_request req
 

Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call.

The SDP contains

  • a session description
  • one or multiple media descriptions that starts with m=

< RTP Audio port number

< RTP Video port number

< media socket address

< Video socket address

< RTP Audio host IP

< RTP video host IP

Definition at line 189 of file sip3_sdprtp.c.

References ast_clear_flag, ast_gethostbyname(), ast_log(), ast_rtp_alloc_size(), ast_rtp_new_init(), ast_rtp_pt_clear(), ast_rtp_set_m_type(), ast_set_flag, ast_strlen_zero(), ast_verbose(), debug(), FALSE, sip_dialog::flags, get_sdp(), get_sdp_iterate(), hp, sip_dialog::lastrtprx, sip_dialog::lastrtptx, len, LOG_ERROR, LOG_WARNING, sip_dialog::rtp, s, sip_request::sdp_start, sip_debug_test_pvt(), SIP_NOVIDEO, and TRUE.

00190 {
00191    const char *m;    /* SDP media offer */
00192    const char *c;
00193    const char *a;
00194    char host[258];
00195    int len = -1;
00196    int portno = -1;     /*!< RTP Audio port number */
00197    int vportno = -1;    /*!< RTP Video port number */
00198    int udptlportno = -1;
00199    int peert38capability = 0;
00200    char s[256];
00201    int old = 0;
00202 
00203    /* Peer capability is the capability in the SDP, non codec is RFC2833 DTMF (101) */ 
00204    int peercapability = 0, peernoncodeccapability = 0;
00205    int vpeercapability = 0, vpeernoncodeccapability = 0;
00206    struct sockaddr_in sin;    /*!< media socket address */
00207    struct sockaddr_in vsin;   /*!< Video socket address */
00208 
00209    const char *codecs;
00210    struct hostent *hp;     /*!< RTP Audio host IP */
00211    struct hostent *vhp = NULL;   /*!< RTP video host IP */
00212    struct ast_hostent audiohp;
00213    struct ast_hostent videohp;
00214    int codec;
00215    int destiterator = 0;
00216    int iterator;
00217    int sendonly = 0;
00218    int numberofports;
00219    struct ast_channel *bridgepeer = NULL;
00220    struct ast_rtp *newaudiortp, *newvideortp;   /* Buffers for codec handling */
00221    int newjointcapability;          /* Negotiated capability */
00222    int newpeercapability;
00223    int newnoncodeccapability;
00224    int numberofmediastreams = 0;
00225    int debug = sip_debug_test_pvt(p);
00226       
00227    int found_rtpmap_codecs[32];
00228    int last_rtpmap_codec=0;
00229 
00230    if (!p->rtp) {
00231       ast_log(LOG_ERROR, "Got SDP but have no RTP session allocated.\n");
00232       return -1;
00233    }
00234 
00235    /* Initialize the temporary RTP structures we use to evaluate the offer from the peer */
00236    newaudiortp = alloca(ast_rtp_alloc_size());
00237    memset(newaudiortp, 0, ast_rtp_alloc_size());
00238    ast_rtp_new_init(newaudiortp);
00239    ast_rtp_pt_clear(newaudiortp);
00240 
00241    newvideortp = alloca(ast_rtp_alloc_size());
00242    memset(newvideortp, 0, ast_rtp_alloc_size());
00243    ast_rtp_new_init(newvideortp);
00244    ast_rtp_pt_clear(newvideortp);
00245 
00246    /* Update our last rtprx when we receive an SDP, too */
00247    p->lastrtprx = p->lastrtptx = time(NULL); /* XXX why both ? */
00248 
00249 
00250    /* Try to find first media stream */
00251    m = get_sdp(req, "m");
00252    destiterator = req->sdp_start;
00253    c = get_sdp_iterate(&destiterator, req, "c");
00254    if (ast_strlen_zero(m) || ast_strlen_zero(c)) {
00255       ast_log(LOG_WARNING, "Insufficient information for SDP (m = '%s', c = '%s')\n", m, c);
00256       return -1;
00257    }
00258 
00259    /* Check for IPv4 address (not IPv6 yet) */
00260    if (sscanf(c, "IN IP4 %256s", host) != 1) {
00261       ast_log(LOG_WARNING, "Invalid host in c= line, '%s'\n", c);
00262       return -1;
00263    }
00264 
00265    /* XXX This could block for a long time, and block the main thread! XXX */
00266    hp = ast_gethostbyname(host, &audiohp);
00267    if (!hp) {
00268       ast_log(LOG_WARNING, "Unable to lookup host in c= line, '%s'\n", c);
00269       return -1;
00270    }
00271    vhp = hp;   /* Copy to video address as default too */
00272    
00273    iterator = req->sdp_start;
00274    ast_set_flag(&p->flags[0], SIP_NOVIDEO);  
00275 
00276 
00277    /* Find media streams in this SDP offer */
00278    while ((m = get_sdp_iterate(&iterator, req, "m"))[0] != '\0') {
00279       int x;
00280       int audio = FALSE;
00281 
00282       numberofports = 1;
00283       if ((sscanf(m, "audio %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) ||
00284           (sscanf(m, "audio %d RTP/AVP %n", &x, &len) == 1)) {
00285          audio = TRUE;
00286          numberofmediastreams++;
00287          /* Found audio stream in this media definition */
00288          portno = x;
00289          /* Scan through the RTP payload types specified in a "m=" line: */
00290          for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
00291             if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
00292                ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
00293                return -1;
00294             }
00295             if (debug)
00296                ast_verbose("Found RTP audio format %d\n", codec);
00297             ast_rtp_set_m_type(newaudiortp, codec);
00298          }
00299       } else if ((sscanf(m, "video %d/%d RTP/AVP %n", &x, &numberofports, &len) == 2) ||
00300           (sscanf(m, "video %d RTP/AVP %n", &x, &len) == 1)) {
00301          /* If it is not audio - is it video ? */
00302          ast_clear_flag(&p->flags[0], SIP_NOVIDEO);   
00303          numberofmediastreams++;
00304          vportno = x;
00305          /* Scan through the RTP payload types specified in a "m=" line: */
00306          for (codecs = m + len; !ast_strlen_zero(codecs); codecs = ast_skip_blanks(codecs + len)) {
00307             if (sscanf(codecs, "%d%n", &codec, &len) != 1) {
00308                ast_log(LOG_WARNING, "Error in codec string '%s'\n", codecs);
00309                return -1;
00310             }
00311             if (debug)
00312                ast_verbose("Found RTP video format %d\n", codec);
00313             ast_rtp_set_m_type(newvideortp, codec);
00314          }
00315       } else if (p->udptl && ((sscanf(m, "image %d udptl t38%n", &x, &len) == 1))) {
00316          if (debug)
00317             ast_verbose("Got T.38 offer in SDP in dialog %s\n", p->callid);
00318          udptlportno = x;
00319          numberofmediastreams++;
00320          
00321          if (p->owner && p->lastinvite) {
00322             p->t38.state = T38_PEER_REINVITE; /* T38 Offered in re-invite from remote party */
00323             if (option_debug > 1)
00324                ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>" );
00325          } else {
00326             p->t38.state = T38_PEER_DIRECT; /* T38 Offered directly from peer in first invite */
00327             if (option_debug > 1)
00328                ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
00329          }
00330       } else 
00331          ast_log(LOG_WARNING, "Unsupported SDP media type in offer: %s\n", m);
00332       if (numberofports > 1)
00333          ast_log(LOG_WARNING, "SDP offered %d ports for media, not supported by Asterisk. Will try anyway...\n", numberofports);
00334       
00335 
00336       /* Check for Media-description-level-address for audio */
00337       c = get_sdp_iterate(&destiterator, req, "c");
00338       if (!ast_strlen_zero(c)) {
00339          if (sscanf(c, "IN IP4 %256s", host) != 1) {
00340             ast_log(LOG_WARNING, "Invalid secondary host in c= line, '%s'\n", c);
00341          } else {
00342             /* XXX This could block for a long time, and block the main thread! XXX */
00343             if (audio) {
00344                if ( !(hp = ast_gethostbyname(host, &audiohp)))
00345                   ast_log(LOG_WARNING, "Unable to lookup RTP Audio host in secondary c= line, '%s'\n", c);
00346             } else if (!(vhp = ast_gethostbyname(host, &videohp)))
00347                ast_log(LOG_WARNING, "Unable to lookup RTP video host in secondary c= line, '%s'\n", c);
00348          }
00349 
00350       }
00351    }
00352    if (portno == -1 && vportno == -1 && udptlportno == -1)
00353       /* No acceptable offer found in SDP  - we have no ports */
00354       /* Do not change RTP or VRTP if this is a re-invite */
00355       return -2;
00356 
00357    if (numberofmediastreams > 2)
00358       /* We have too many fax, audio and/or video media streams, fail this offer */
00359       return -3;
00360 
00361    /* RTP addresses and ports for audio and video */
00362    sin.sin_family = AF_INET;
00363    vsin.sin_family = AF_INET;
00364    memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00365    if (vhp)
00366       memcpy(&vsin.sin_addr, vhp->h_addr, sizeof(vsin.sin_addr));
00367       
00368    /* Setup UDPTL port number */
00369    if (p->udptl) {
00370       if (udptlportno > 0) {
00371          sin.sin_port = htons(udptlportno);
00372          ast_udptl_set_peer(p->udptl, &sin);
00373          if (debug)
00374             ast_log(LOG_DEBUG,"Peer T.38 UDPTL is at port %s:%d\n",ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00375       } else {
00376          ast_udptl_stop(p->udptl);
00377          if (debug)
00378             ast_log(LOG_DEBUG, "Peer doesn't provide T.38 UDPTL\n");
00379       }
00380    }
00381    if (p->rtp) {
00382       if (portno > 0) {
00383          sin.sin_port = htons(portno);
00384          if (!sin.sin_port) 
00385             ast_log(LOG_WARNING, "No SIN structure here, will crash\n");
00386          ast_rtp_set_peer(p->rtp, &sin);
00387          if (debug)
00388             ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00389       } else {
00390          if (udptlportno > 0) {
00391             if (debug)
00392                ast_log(LOG_DEBUG, "Got T.38 re-invite without audio. Keeping RTP active during T.38 session. Call-Id %s\n", p->callid);
00393          } else 
00394             ast_rtp_stop(p->rtp);
00395          if (debug)
00396             ast_verbose("Peer doesn't provide audio: Call-Id: %s\n", p->callid);
00397       }
00398    }
00399    /* Setup video port number */
00400    if (vportno != -1)
00401       vsin.sin_port = htons(vportno);
00402 
00403 
00404    /* Next, scan through each "a=rtpmap:" line, noting each
00405     * specified RTP payload type (with corresponding MIME subtype):
00406     */
00407    /* XXX This needs to be done per media stream, since it's media stream specific */
00408    iterator = req->sdp_start;
00409    while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
00410       char* mimeSubtype = ast_strdupa(a); /* ensures we have enough space */
00411       if (option_debug > 1) {
00412          int breakout = FALSE;
00413       
00414          /* If we're debugging, check for unsupported sdp options */
00415          if (!strncasecmp(a, "rtcp:", (size_t) 5)) {
00416             if (debug)
00417                ast_verbose("Got unsupported a:rtcp in SDP offer \n");
00418             breakout = TRUE;
00419          } else if (!strncasecmp(a, "fmtp:", (size_t) 5)) {
00420             /* Format parameters:  Not supported */
00421             /* Note: This is used for codec parameters, like bitrate for
00422                G722 and video formats for H263 and H264 
00423                See RFC2327 for an example */
00424             if (debug)
00425                ast_verbose("Got unsupported a:fmtp in SDP offer \n");
00426             breakout = TRUE;
00427          } else if (!strncasecmp(a, "framerate:", (size_t) 10)) {
00428             /* Video stuff:  Not supported */
00429             if (debug)
00430                ast_verbose("Got unsupported a:framerate in SDP offer \n");
00431             breakout = TRUE;
00432          } else if (!strncasecmp(a, "maxprate:", (size_t) 9)) {
00433             /* Video stuff:  Not supported */
00434             if (debug)
00435                ast_verbose("Got unsupported a:maxprate in SDP offer \n");
00436             breakout = TRUE;
00437          } else if (!strncasecmp(a, "crypto:", (size_t) 7)) {
00438             /* SRTP stuff, not yet supported */
00439             if (debug)
00440                ast_verbose("Got unsupported a:crypto in SDP offer \n");
00441             breakout = TRUE;
00442          }
00443          if (breakout)  /* We have a match, skip to next header */
00444             continue;
00445       }
00446       if (!strcasecmp(a, "sendonly")) {
00447          sendonly = 1;
00448          continue;
00449       } else if (!strcasecmp(a, "inactive")) {
00450          sendonly = 2;
00451          continue;
00452       }  else if (!strcasecmp(a, "sendrecv")) {
00453          sendonly = 0;
00454          continue;
00455       } else if (strlen(a) > 5 && !strncasecmp(a, "ptime", 5)) {
00456          char *tmp = strrchr(a, ':');
00457          long int framing = 0;
00458          if (tmp) {
00459             tmp++;
00460             framing = strtol(tmp, NULL, 10);
00461             if (framing == LONG_MIN || framing == LONG_MAX) {
00462                framing = 0;
00463                if (option_debug)
00464                   ast_log(LOG_DEBUG, "Can't read framing from SDP: %s\n", a);
00465             }
00466          }
00467          if (framing && last_rtpmap_codec) {
00468             if (p->autoframing || global.autoframing) {
00469                struct ast_codec_pref *pref = ast_rtp_codec_getpref(p->rtp);
00470                int codec_n;
00471                int format = 0;
00472                for (codec_n = 0; codec_n < last_rtpmap_codec; codec_n++) {
00473                   format = ast_rtp_codec_getformat(found_rtpmap_codecs[codec_n]);
00474                   if (!format)   /* non-codec or not found */
00475                      continue;
00476                   if (option_debug)
00477                      ast_log(LOG_DEBUG, "Setting framing for %d to %ld\n", format, framing);
00478                   ast_codec_pref_setsize(pref, format, framing);
00479                }
00480                ast_rtp_codec_setpref(p->rtp, pref);
00481             }
00482          }
00483          memset(&found_rtpmap_codecs, 0, sizeof(found_rtpmap_codecs));
00484          last_rtpmap_codec = 0;
00485          continue;
00486       } else if (sscanf(a, "rtpmap: %u %[^/]/", &codec, mimeSubtype) == 2) {
00487          /* We have a rtpmap to handle */
00488          if (debug)
00489             ast_verbose("Found description format %s for ID %d\n", mimeSubtype, codec);
00490          found_rtpmap_codecs[last_rtpmap_codec] = codec;
00491          last_rtpmap_codec++;
00492 
00493          /* Note: should really look at the 'freq' and '#chans' params too */
00494          ast_rtp_set_rtpmap_type(newaudiortp, codec, "audio", mimeSubtype,
00495                ast_test_flag(&p->flags[0], SIP_G726_NONSTANDARD) ? AST_RTP_OPT_G726_NONSTANDARD : 0);
00496          if (p->vrtp)
00497             ast_rtp_set_rtpmap_type(newvideortp, codec, "video", mimeSubtype, 0);
00498       }
00499    }
00500    
00501    if (udptlportno != -1) {
00502       int found = 0, x;
00503       
00504       old = 0;
00505       
00506       /* Scan trough the a= lines for T38 attributes and set apropriate fileds */
00507       iterator = req->sdp_start;
00508       while ((a = get_sdp_iterate(&iterator, req, "a"))[0] != '\0') {
00509          if ((sscanf(a, "T38FaxMaxBuffer:%d", &x) == 1)) {
00510             found = 1;
00511             if (option_debug > 2)
00512                ast_log(LOG_DEBUG, "MaxBufferSize:%d\n",x);
00513          } else if ((sscanf(a, "T38MaxBitRate:%d", &x) == 1)) {
00514             found = 1;
00515             if (option_debug > 2)
00516                ast_log(LOG_DEBUG,"T38MaxBitRate: %d\n",x);
00517             switch (x) {
00518             case 14400:
00519                peert38capability |= T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
00520                break;
00521             case 12000:
00522                peert38capability |= T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
00523                break;
00524             case 9600:
00525                peert38capability |= T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
00526                break;
00527             case 7200:
00528                peert38capability |= T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400;
00529                break;
00530             case 4800:
00531                peert38capability |= T38FAX_RATE_4800 | T38FAX_RATE_2400;
00532                break;
00533             case 2400:
00534                peert38capability |= T38FAX_RATE_2400;
00535                break;
00536             }
00537          } else if ((sscanf(a, "T38FaxVersion:%d", &x) == 1)) {
00538             found = 1;
00539             if (option_debug > 2)
00540                ast_log(LOG_DEBUG, "FaxVersion: %d\n",x);
00541             if (x == 0)
00542                peert38capability |= T38FAX_VERSION_0;
00543             else if (x == 1)
00544                peert38capability |= T38FAX_VERSION_1;
00545          } else if ((sscanf(a, "T38FaxMaxDatagram:%d", &x) == 1)) {
00546             found = 1;
00547             if (option_debug > 2)
00548                ast_log(LOG_DEBUG, "FaxMaxDatagram: %d\n",x);
00549             ast_udptl_set_far_max_datagram(p->udptl, x);
00550             ast_udptl_set_local_max_datagram(p->udptl, x);
00551          } else if ((sscanf(a, "T38FaxFillBitRemoval:%d", &x) == 1)) {
00552             found = 1;
00553             if (option_debug > 2)
00554                ast_log(LOG_DEBUG, "FillBitRemoval: %d\n",x);
00555             if (x == 1)
00556                peert38capability |= T38FAX_FILL_BIT_REMOVAL;
00557          } else if ((sscanf(a, "T38FaxTranscodingMMR:%d", &x) == 1)) {
00558             found = 1;
00559             if (option_debug > 2)
00560                ast_log(LOG_DEBUG, "Transcoding MMR: %d\n",x);
00561             if (x == 1)
00562                peert38capability |= T38FAX_TRANSCODING_MMR;
00563          }
00564          if ((sscanf(a, "T38FaxTranscodingJBIG:%d", &x) == 1)) {
00565             found = 1;
00566             if (option_debug > 2)
00567                ast_log(LOG_DEBUG, "Transcoding JBIG: %d\n",x);
00568             if (x == 1)
00569                peert38capability |= T38FAX_TRANSCODING_JBIG;
00570          } else if ((sscanf(a, "T38FaxRateManagement:%s", s) == 1)) {
00571             found = 1;
00572             if (option_debug > 2)
00573                ast_log(LOG_DEBUG, "RateMangement: %s\n", s);
00574             if (!strcasecmp(s, "localTCF"))
00575                peert38capability |= T38FAX_RATE_MANAGEMENT_LOCAL_TCF;
00576             else if (!strcasecmp(s, "transferredTCF"))
00577                peert38capability |= T38FAX_RATE_MANAGEMENT_TRANSFERED_TCF;
00578          } else if ((sscanf(a, "T38FaxUdpEC:%s", s) == 1)) {
00579             found = 1;
00580             if (option_debug > 2)
00581                ast_log(LOG_DEBUG, "UDP EC: %s\n", s);
00582             if (!strcasecmp(s, "t38UDPRedundancy")) {
00583                peert38capability |= T38FAX_UDP_EC_REDUNDANCY;
00584                ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_REDUNDANCY);
00585             } else if (!strcasecmp(s, "t38UDPFEC")) {
00586                peert38capability |= T38FAX_UDP_EC_FEC;
00587                ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_FEC);
00588             } else {
00589                peert38capability |= T38FAX_UDP_EC_NONE;
00590                ast_udptl_set_error_correction_scheme(p->udptl, UDPTL_ERROR_CORRECTION_NONE);
00591             }
00592          }
00593       }
00594       if (found) { /* Some cisco equipment returns nothing beside c= and m= lines in 200 OK T38 SDP */
00595          p->t38.peercapability = peert38capability;
00596          p->t38.jointcapability = (peert38capability & 255); /* Put everything beside supported speeds settings */
00597          peert38capability &= (T38FAX_RATE_14400 | T38FAX_RATE_12000 | T38FAX_RATE_9600 | T38FAX_RATE_7200 | T38FAX_RATE_4800 | T38FAX_RATE_2400);
00598          p->t38.jointcapability |= (peert38capability & p->t38.capability); /* Put the lower of our's and peer's speed */
00599       }
00600       if (debug)
00601          ast_log(LOG_DEBUG, "Our T38 capability = (%d), peer T38 capability (%d), joint T38 capability (%d)\n",
00602             p->t38.capability,
00603             p->t38.peercapability,
00604             p->t38.jointcapability);
00605    } else {
00606       p->t38.state = T38_DISABLED;
00607       if (option_debug > 2)
00608          ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
00609    }
00610 
00611    /* Now gather all of the codecs that we are asked for: */
00612    ast_rtp_get_current_formats(newaudiortp, &peercapability, &peernoncodeccapability);
00613    ast_rtp_get_current_formats(newvideortp, &vpeercapability, &vpeernoncodeccapability);
00614 
00615    newjointcapability = p->capability & (peercapability | vpeercapability);
00616    newpeercapability = (peercapability | vpeercapability);
00617    newnoncodeccapability = p->noncodeccapability & peernoncodeccapability;
00618       
00619       
00620    if (debug) {
00621       /* shame on whoever coded this.... */
00622       char s1[BUFSIZ], s2[BUFSIZ], s3[BUFSIZ], s4[BUFSIZ];
00623 
00624       ast_verbose("Capabilities: us - %s, peer - audio=%s/video=%s, combined - %s\n",
00625              ast_getformatname_multiple(s1, BUFSIZ, p->capability),
00626              ast_getformatname_multiple(s2, BUFSIZ, newpeercapability),
00627              ast_getformatname_multiple(s3, BUFSIZ, vpeercapability),
00628              ast_getformatname_multiple(s4, BUFSIZ, newjointcapability));
00629 
00630       ast_verbose("Non-codec capabilities (dtmf): us - %s, peer - %s, combined - %s\n",
00631              ast_rtp_lookup_mime_multiple(s1, BUFSIZ, p->noncodeccapability, 0, 0),
00632              ast_rtp_lookup_mime_multiple(s2, BUFSIZ, peernoncodeccapability, 0, 0),
00633              ast_rtp_lookup_mime_multiple(s3, BUFSIZ, newnoncodeccapability, 0, 0));
00634    }
00635    if (!newjointcapability) {
00636       /* If T.38 was not negotiated either, totally bail out... */
00637       if (!p->t38.jointcapability) {
00638          ast_log(LOG_NOTICE, "No compatible codecs, not accepting this offer!\n");
00639          /* Do NOT Change current setting */
00640          return -1;
00641       } else {
00642          if (option_debug > 2)
00643             ast_log(LOG_DEBUG, "Have T.38 but no audio codecs, accepting offer anyway\n");
00644          return 0;
00645       }
00646    }
00647 
00648    /* We are now ready to change the sip session and p->rtp and p->vrtp with the offered codecs, since
00649       they are acceptable */
00650    p->jointcapability = newjointcapability;  /* Our joint codec profile for this call */
00651    p->peercapability = newpeercapability;    /* The other sides capability in latest offer */
00652    p->jointnoncodeccapability = newnoncodeccapability;   /* DTMF capabilities */
00653 
00654    ast_rtp_pt_copy(p->rtp, newaudiortp);
00655    if (p->vrtp)
00656       ast_rtp_pt_copy(p->vrtp, newvideortp);
00657 
00658    if (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO) {
00659       ast_clear_flag(&p->flags[0], SIP_DTMF);
00660       if (newnoncodeccapability & AST_RTP_DTMF) {
00661          /* XXX Would it be reasonable to drop the DSP at this point? XXX */
00662          ast_set_flag(&p->flags[0], SIP_DTMF_RFC2833);
00663       } else {
00664          ast_set_flag(&p->flags[0], SIP_DTMF_INBAND);
00665       }
00666    }
00667 
00668    /* Setup audio port number */
00669    if (p->rtp && sin.sin_port) {
00670       ast_rtp_set_peer(p->rtp, &sin);
00671       if (debug)
00672          ast_verbose("Peer audio RTP is at port %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
00673    }
00674 
00675    /* Setup video port number */
00676    if (p->vrtp && vsin.sin_port) {
00677       ast_rtp_set_peer(p->vrtp, &vsin);
00678       if (debug) 
00679          ast_verbose("Peer video RTP is at port %s:%d\n", ast_inet_ntoa(vsin.sin_addr), ntohs(vsin.sin_port));
00680    }
00681 
00682    /* Ok, we're going with this offer */
00683    if (option_debug > 1) {
00684       char buf[BUFSIZ];
00685       ast_log(LOG_DEBUG, "We're settling with these formats: %s\n", ast_getformatname_multiple(buf, BUFSIZ, p->jointcapability));
00686    }
00687 
00688    if (!p->owner)    /* There's no open channel owning us so we can return here. For a re-invite or so, we proceed */
00689       return 0;
00690 
00691    if (option_debug > 3)
00692       ast_log(LOG_DEBUG, "We have an owner, now see if we need to change this call\n");
00693 
00694    if (!(p->owner->nativeformats & p->jointcapability & AST_FORMAT_AUDIO_MASK) && (p->jointcapability & AST_FORMAT_AUDIO_MASK)) {
00695       if (debug) {
00696          char s1[BUFSIZ], s2[BUFSIZ];
00697          ast_log(LOG_DEBUG, "Oooh, we need to change our audio formats since our peer supports only %s and not %s\n", 
00698             ast_getformatname_multiple(s1, BUFSIZ, p->jointcapability),
00699             ast_getformatname_multiple(s2, BUFSIZ, p->owner->nativeformats));
00700       }
00701       p->owner->nativeformats = ast_codec_choose(&p->prefs, p->jointcapability, 1) | (p->capability & vpeercapability);
00702       ast_set_read_format(p->owner, p->owner->readformat);
00703       ast_set_write_format(p->owner, p->owner->writeformat);
00704    }
00705    
00706    /* Turn on/off music on hold if we are holding/unholding */
00707    if ((bridgepeer = ast_bridged_channel(p->owner))) {
00708       if (sin.sin_addr.s_addr && !sendonly) {
00709          ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
00710          /* Activate a re-invite */
00711          ast_queue_frame(p->owner, &ast_null_frame);
00712       } else if (!sin.sin_addr.s_addr || sendonly) {
00713          ast_queue_control_data(p->owner, AST_CONTROL_HOLD, 
00714                       S_OR(p->mohsuggest, NULL),
00715                       !ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
00716          if (sendonly)
00717             ast_rtp_stop(p->rtp);
00718          /* RTCP needs to go ahead, even if we're on hold!!! */
00719          /* Activate a re-invite */
00720          ast_queue_frame(p->owner, &ast_null_frame);
00721       }
00722    }
00723 
00724    /* Manager Hold and Unhold events must be generated, if necessary */
00725    if (sin.sin_addr.s_addr && !sendonly) {
00726       if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
00727          append_history(p, "Unhold", "%s", req->data);
00728          if (global.callevents)
00729             manager_event(EVENT_FLAG_CALL, "Unhold",
00730                "Channel: %s\r\n"
00731                "Uniqueid: %s\r\n",
00732                p->owner->name, 
00733                p->owner->uniqueid);
00734          sip_peer_hold(p, 0);
00735       } 
00736       ast_clear_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD);  /* Clear both flags */
00737    } else if (!sin.sin_addr.s_addr || sendonly ) {
00738       /* No address for RTP, we're on hold */
00739       append_history(p, "Hold", "%s", req->data);
00740 
00741       if (global.callevents && !ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD)) {
00742          manager_event(EVENT_FLAG_CALL, "Hold",
00743             "Channel: %s\r\n"
00744             "Uniqueid: %s\r\n",
00745             p->owner->name, 
00746             p->owner->uniqueid);
00747       }
00748       if (sendonly == 1)   /* One directional hold (sendonly/recvonly) */
00749          ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_ONEDIR);
00750       else if (sendonly == 2) /* Inactive stream */
00751          ast_set_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD_INACTIVE);
00752       sip_peer_hold(p, 1);
00753    }
00754    
00755    return 0;
00756 }

void register_rtp_and_udptl void   ) 
 

Register RTP and UDPTL to the subsystems.

Definition at line 111 of file sip3_sdprtp.c.

References ast_rtp_proto_register(), ast_udptl_proto_register(), sip_rtp, and sip_udptl.

Referenced by load_module().

00112 {
00113    /* Tell the RTP subdriver that we're here */
00114    ast_rtp_proto_register(&sip_rtp);
00115 
00116    /* Tell the UDPTL subdriver that we're here */
00117    ast_udptl_proto_register(&sip_udptl);
00118 }

static int sip_get_codec struct ast_channel chan  )  [static]
 

Return SIP UA's codec (part of the RTP interface).

Definition at line 1264 of file sip3_sdprtp.c.

References sip_dialog::peercapability, and ast_channel::tech_pvt.

01265 {
01266    struct sip_dialog *p = chan->tech_pvt;
01267    return p->peercapability;  
01268 }

enum ast_rtp_get_result sip_get_rtp_peer struct ast_channel chan,
struct ast_rtp **  rtp
 

Returns null if we can't reinvite audio (part of RTP interface).

Definition at line 825 of file sip3_sdprtp.c.

References AST_JB_FORCED, AST_RTP_GET_FAILED, ast_rtp_getnat(), AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, dialog_lock(), FALSE, sip_dialog::flags, global, sip_globals::jbconf, sip_dialog::rtp, SIP_CAN_REINVITE, SIP_CAN_REINVITE_NAT, ast_channel::tech_pvt, and TRUE.

00826 {
00827    struct sip_dialog *p = NULL;
00828    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
00829 
00830    if (!(p = chan->tech_pvt) || !(p->rtp))
00831       return AST_RTP_GET_FAILED;
00832 
00833    dialog_lock(p, TRUE);
00834 
00835    *rtp = p->rtp;
00836 
00837    if (ast_rtp_getnat(*rtp) && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT))
00838       res = AST_RTP_TRY_PARTIAL;
00839    else if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
00840       res = AST_RTP_TRY_NATIVE;
00841    else if (ast_test_flag(&global.jbconf, AST_JB_FORCED))
00842       res = AST_RTP_GET_FAILED;
00843 
00844    dialog_lock(p, FALSE);
00845 
00846    return res;
00847 }

static struct ast_udptl * sip_get_udptl_peer struct ast_channel chan  )  [static]
 

Get UDPTL peer address (part of UDPTL interface).

Definition at line 1370 of file sip3_sdprtp.c.

References dialog_lock(), FALSE, ast_channel::tech_pvt, TRUE, and sip_dialog::udptl.

01371 {
01372    struct sip_dialog *p;
01373    struct ast_udptl *udptl = NULL;
01374    
01375    p = chan->tech_pvt;
01376    if (!p || !(p->udptl))
01377       return NULL;
01378    
01379    dialog_lock(p, TRUE);
01380    /*  T38 reinvites is something very different from media re-invites to optimize
01381       the media stream. They should not rely on the CAN_REINVITE setting
01382       if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE)) */
01383    udptl = p->udptl;
01384    dialog_lock(p, FALSE);
01385    return udptl;
01386 }

enum ast_rtp_get_result sip_get_vrtp_peer struct ast_channel chan,
struct ast_rtp **  rtp
 

Returns null if we can't reinvite video (part of RTP interface).

Definition at line 850 of file sip3_sdprtp.c.

References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_test_flag, sip_dialog::flags, sip_dialog::lock, sip_dialog::rtp, SIP_CAN_REINVITE, ast_channel::tech_pvt, and sip_dialog::vrtp.

00851 {
00852    struct sip_dialog *p = NULL;
00853    enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
00854    
00855    if (!(p = chan->tech_pvt) || !(p->vrtp))
00856       return AST_RTP_GET_FAILED;
00857 
00858    ast_mutex_lock(&p->lock);
00859 
00860    *rtp = p->vrtp;
00861 
00862    if (ast_test_flag(&p->flags[0], SIP_CAN_REINVITE))
00863       res = AST_RTP_TRY_NATIVE;
00864 
00865    /* The jitterbuffer is not implemented for video */
00866 
00867    ast_mutex_unlock(&p->lock);
00868 
00869    return res;
00870 }

GNURK struct ast_frame * sip_read struct ast_channel ast  ) 
 

Read SIP RTP from channel.

Definition at line 1333 of file sip3_sdprtp.c.

References ast_bridged_channel(), ast_log(), ast_set_flag, ast_test_flag, dialog_lock(), FALSE, sip_dialog::flags, sip_dialog::lastrtprx, option_debug, sip_dialog::pendinginvite, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_PAGE2_T38SUPPORT_UDPTL, SIP_PENDINGBYE, sip_rtp_read(), t38properties::state, sip_dialog::t38, T38_DISABLED, T38_LOCAL_REINVITE, t38properties::t38support, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), and TRUE.

01334 {
01335    struct ast_frame *fr;
01336    struct sip_dialog *p = ast->tech_pvt;
01337    int faxdetected = FALSE;
01338 
01339    dialog_lock(p, TRUE);
01340    fr = sip_rtp_read(ast, p, &faxdetected);
01341    p->lastrtprx = time(NULL);
01342 
01343    /* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */
01344    /* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */
01345    if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
01346       if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
01347          if (!p->pendinginvite) {
01348             if (option_debug > 2)
01349                ast_log(LOG_DEBUG, "Sending reinvite on SIP (%s) for T.38 negotiation.\n",ast->name);
01350             p->t38.state = T38_LOCAL_REINVITE;
01351             transmit_reinvite_with_sdp(p, TRUE);
01352             if (option_debug > 1)
01353                ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, ast->name);
01354          } 
01355       } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
01356          if (option_debug > 2)
01357             ast_log(LOG_DEBUG, "Deferring reinvite on SIP (%s) - it will be re-negotiated for T.38\n", ast->name);
01358          ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
01359       }  else if (option_debug > 3) {
01360          ast_log(LOG_DEBUG, "Fax deteced but discarded because another transaction is already in progress.\n");
01361          /* \note Should we turn on a flag and send re-invite for fax at a later stage? */
01362       }
01363    }
01364    dialog_lock(p, FALSE);
01365 
01366    return fr;
01367 }

static struct ast_frame* sip_rtp_read struct ast_channel ast,
struct sip_dialog p,
int *  faxdetect
[static]
 

Read RTP from network.

Definition at line 1271 of file sip3_sdprtp.c.

References ast_dsp_process(), AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_log(), ast_null_frame, ast_rtcp_read(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), ast_test_flag, ast_udptl_read(), ast_channel::fdno, sip_dialog::flags, ast_frame::frametype, ast_channel::nativeformats, option_debug, sip_dialog::owner, ast_channel::readformat, sip_dialog::rtp, SIP_DTMF, SIP_DTMF_INBAND, SIP_DTMF_RFC2833, SIP_PAGE2_T38SUPPORT_UDPTL, ast_frame::subclass, sip_dialog::t38, t38properties::t38support, sip_dialog::udptl, sip_dialog::vad, sip_dialog::vrtp, and ast_channel::writeformat.

01272 {
01273    /* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
01274    struct ast_frame *f;
01275    
01276    if (!p->rtp) {
01277       /* We have no RTP allocated for this channel */
01278       return &ast_null_frame;
01279    }
01280 
01281    switch(ast->fdno) {
01282    case 0:
01283       f = ast_rtp_read(p->rtp);  /* RTP Audio */
01284       break;
01285    case 1:
01286       f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
01287       break;
01288    case 2:
01289       f = ast_rtp_read(p->vrtp); /* RTP Video */
01290       break;
01291    case 3:
01292       f = ast_rtcp_read(p->vrtp);   /* RTCP Control Channel for video */
01293       break;
01294    case 5:
01295       f = ast_udptl_read(p->udptl); /* UDPTL for T.38 */
01296       break;
01297    default:
01298       f = &ast_null_frame;
01299    }
01300    /* Don't forward RFC2833 if we're not supposed to */
01301    if (f && (f->frametype == AST_FRAME_DTMF) &&
01302        (ast_test_flag(&p->flags[0], SIP_DTMF) != SIP_DTMF_RFC2833))
01303       return &ast_null_frame;
01304 
01305    if (p->owner) {
01306       /* We already hold the channel lock */
01307       if (f->frametype == AST_FRAME_VOICE) {
01308          if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {
01309             if (option_debug)
01310                ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
01311             p->owner->nativeformats = (p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;
01312             ast_set_read_format(p->owner, p->owner->readformat);
01313             ast_set_write_format(p->owner, p->owner->writeformat);
01314          }
01315          if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {
01316             f = ast_dsp_process(p->owner, p->vad, f);
01317             if (f && f->frametype == AST_FRAME_DTMF) {
01318                if (ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && f->subclass == 'f') {
01319                   if (option_debug)
01320                      ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", ast->name);
01321                   *faxdetect = 1;
01322                } else if (option_debug) {
01323                   ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass);
01324                }
01325             }
01326          }
01327       }
01328    }
01329    return f;
01330 }

int sip_set_rtp_peer struct ast_channel chan,
struct ast_rtp rtp,
struct ast_rtp vrtp,
int  codecs,
int  nat_active
 

Set the RTP peer for this call.

Definition at line 760 of file sip3_sdprtp.c.

References ast_channel::_state, append_history, ast_inet_ntoa(), ast_log(), ast_rtp_get_peer(), ast_set_flag, AST_STATE_UP, ast_test_flag, dialog_lock(), FALSE, sip_dialog::flags, sip_dialog::lastrtprx, sip_dialog::lastrtptx, option_debug, sip_dialog::ourip, sip_dialog::pendinginvite, sip_dialog::redircodecs, sip_dialog::redirip, sip_dialog::rtp, SIP_ALREADYGONE, SIP_CAN_REINVITE_NAT, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_NO_HISTORY, SIP_PENDINGBYE, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), TRUE, sip_dialog::vredirip, and sip_dialog::vrtp.

00761 {
00762    struct sip_dialog *p;
00763    int changed = 0;
00764 
00765    p = chan->tech_pvt;
00766    if (!p) 
00767       return -1;
00768    dialog_lock(p, TRUE);
00769    if (ast_test_flag(&p->flags[0], SIP_ALREADYGONE)) {
00770       /* If we're destroyed, don't bother */
00771       dialog_lock(p, FALSE);
00772       return 0;
00773    }
00774 
00775    /* if this peer cannot handle reinvites of the media stream to devices
00776       that are known to be behind a NAT, then stop the process now
00777    */
00778    if (nat_active && !ast_test_flag(&p->flags[0], SIP_CAN_REINVITE_NAT)) {
00779       dialog_lock(p, FALSE);
00780       return 0;
00781    }
00782 
00783    if (rtp) {
00784       changed |= ast_rtp_get_peer(rtp, &p->redirip);
00785    } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) {
00786       memset(&p->redirip, 0, sizeof(p->redirip));
00787       changed = 1;
00788    }
00789    if (vrtp) {
00790       changed |= ast_rtp_get_peer(vrtp, &p->vredirip);
00791    } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) {
00792       memset(&p->vredirip, 0, sizeof(p->vredirip));
00793       changed = 1;
00794    }
00795    if (codecs && (p->redircodecs != codecs)) {
00796       p->redircodecs = codecs;
00797       changed = 1;
00798    }
00799    if (changed && !ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
00800       if (chan->_state != AST_STATE_UP) { /* We are in early state */
00801          if (!ast_test_flag(&p->flags[0], SIP_NO_HISTORY))
00802             append_history(p, "ExtInv", "Initial invite sent with remote bridge proposal.");
00803          if (option_debug)
00804             ast_log(LOG_DEBUG, "Early remote bridge setting SIP '%s' - Sending media to %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
00805       } else if (!p->pendinginvite) {     /* We are up, and have no outstanding invite */
00806          if (option_debug > 2) {
00807             ast_log(LOG_DEBUG, "Sending reinvite on SIP '%s' - It's audio soon redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
00808          }
00809          transmit_reinvite_with_sdp(p, FALSE);
00810       } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
00811          if (option_debug > 2) {
00812             ast_log(LOG_DEBUG, "Deferring reinvite on SIP '%s' - It's audio will be redirected to IP %s\n", p->callid, ast_inet_ntoa(rtp ? p->redirip.sin_addr : p->ourip));
00813          }
00814          /* We have a pending Invite. Send re-invite when we're done with the invite */
00815          ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);   
00816       }
00817    }
00818    /* Reset lastrtprx timer */
00819    p->lastrtprx = p->lastrtptx = time(NULL);
00820    dialog_lock(p, FALSE);
00821    return 0;
00822 }

static int sip_set_udptl_peer struct ast_channel chan,
struct ast_udptl udptl
[static]
 

Determine UDPTL peer address for re-invite (part of UDPTL interface).

Definition at line 1389 of file sip3_sdprtp.c.

References ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_test_flag, ast_udptl_get_peer(), sip_dialog::flags, sip_dialog::lastrtprx, sip_dialog::lastrtptx, sip_dialog::lock, option_debug, sip_dialog::ourip, sip_dialog::pendinginvite, SIP_GOTREFER, SIP_NEEDREINVITE, SIP_PENDINGBYE, ast_channel::tech_pvt, transmit_reinvite_with_sdp(), TRUE, sip_dialog::udptl, and sip_dialog::udptlredirip.

01390 {
01391    struct sip_dialog *p;
01392    
01393    p = chan->tech_pvt;
01394    if (!p)
01395       return -1;
01396    ast_mutex_lock(&p->lock);
01397    if (udptl)
01398       ast_udptl_get_peer(udptl, &p->udptlredirip);
01399    else
01400       memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
01401    if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
01402       if (!p->pendinginvite) {
01403          if (option_debug > 2) 
01404             ast_log(LOG_DEBUG, "Sending T38 reinvite on SIP '%s' - It's UDPTL soon redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
01405          transmit_reinvite_with_sdp(p, TRUE);
01406       } else if (!ast_test_flag(&p->flags[0], SIP_PENDINGBYE)) {
01407          if (option_debug > 2) {
01408             ast_log(LOG_DEBUG, "Deferring reinvite on SIP '%s' - It's UDPTL will be redirected to IP %s:%d\n", p->callid, ast_inet_ntoa(udptl ? p->udptlredirip.sin_addr : p->ourip), udptl ? ntohs(p->udptlredirip.sin_port) : 0);
01409          }
01410          ast_set_flag(&p->flags[0], SIP_NEEDREINVITE);
01411       }
01412    }
01413    /* Reset lastrtprx timer */
01414    p->lastrtprx = p->lastrtptx = time(NULL);
01415    ast_mutex_unlock(&p->lock);
01416    return 0;
01417 }

void stop_media_flows struct sip_dialog dialog  ) 
 

Immediately stop RTP, VRTP and UDPTL as applicable.

Definition at line 1421 of file sip3_sdprtp.c.

References ast_log(), ast_rtp_stop(), ast_udptl_stop(), option_debug, sip_dialog::rtp, sipdebug, sip_dialog::udptl, and sip_dialog::vrtp.

01422 {
01423    if (option_debug > 4 && sipdebug)
01424       ast_log(LOG_DEBUG, "Stopping media flow for %s\n", dialog->callid);
01425    /* Immediately stop RTP, VRTP and UDPTL as applicable */
01426    if (dialog->rtp)
01427       ast_rtp_stop(dialog->rtp);
01428    if (dialog->vrtp)
01429       ast_rtp_stop(dialog->vrtp);
01430    if (dialog->udptl)
01431       ast_udptl_stop(dialog->udptl);
01432 }

void unregister_rtp_and_udptl void   ) 
 

UNRegister RTP and UDPTL to the subsystems.

Definition at line 121 of file sip3_sdprtp.c.

References ast_rtp_proto_unregister(), ast_udptl_proto_unregister(), sip_rtp, and sip_udptl.

Referenced by unload_module().

00122 {
00123    /* Tell the RTP subdriver that we're gone */
00124    ast_rtp_proto_unregister(&sip_rtp);
00125 
00126    /* Tell the UDPTL subdriver that we're gone */
00127    ast_udptl_proto_unregister(&sip_udptl);
00128 }


Variable Documentation

struct ast_rtp_protocol sip_rtp [static]
 

Interface structure with callbacks used to connect to RTP module.

Definition at line 95 of file sip3_sdprtp.c.

struct ast_udptl_protocol sip_udptl [static]
 

Initial value:

 {
   type: "SIP",
   get_udptl_info: sip_get_udptl_peer,
   set_udptl_peer: sip_set_udptl_peer,
}
Interface structure with callbacks used to connect to UDPTL module.

Definition at line 104 of file sip3_sdprtp.c.


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen