diff --git a/apps/app_controlplayback.c b/apps/app_controlplayback.c index 089a7f4d8bf3dd965d8448eeeb8ce085c40cebee..850ebed9ccf470b2ea23928f13394781b2d1dc67 100755 --- a/apps/app_controlplayback.c +++ b/apps/app_controlplayback.c @@ -31,14 +31,13 @@ static char *app = "ControlPlayback"; static char *synopsis = "Play a file with fast forward and rewind"; static char *descrip = -"ControlPlayback(filename[|skipms]|[ffchar]|[rewchar]|[stopchar]]):\n" +"ControlPlayback(filename[|skipms[|ffchar[|rewchar[|stopchar[|pausechr]]]]]):\n" " Plays back a given filename (do not put extension). Options may also\n" " be included following a pipe symbol. You can use * and # to rewind and\n" " fast forward the playback specified. If 'stopchar' is added the file will\n" " terminate playback when 'stopchar' is pressed. Returns -1 if the channel\n" " was hung up, or if the file does not exist. Returns 0 otherwise.\n\n" -" Example: exten => 1234,1,ControlPlayback(file|4000|*|#|1)\n\n"; - +" Example: exten => 1234,1,ControlPlayback(file|4000|*|#|1|0)\n\n"; STANDARD_LOCAL_USER; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a9b75da33b34fc011effb6ddf3aa0b70444a9503..15c3f811b9da0074462733e8774ed44a9eb60c9a 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -265,6 +265,7 @@ static struct sip_pvt { struct sockaddr_in sa; /* Our peer */ struct sockaddr_in redirip; /* Where our RTP should be going if not to us */ struct sockaddr_in vredirip; /* Where our Video RTP should be going if not to us */ + int redircodecs; /* Redirect codecs */ struct sockaddr_in recv; /* Received as */ struct in_addr ourip; /* Our IP */ struct ast_channel *owner; /* Who owns us */ @@ -305,6 +306,7 @@ static struct sip_pvt { char lastmsg[256]; /* Last Message sent/received */ int amaflags; /* AMA Flags */ int pendinginvite; /* Any pending invite */ + int needreinvite; /* Do we need to send another reinvite? */ int pendingbye; /* Need to send bye after we ack? */ int gotrefer; /* Got a refer? */ struct sip_request initreq; /* Initial request */ @@ -493,7 +495,7 @@ static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_ static int transmit_request(struct sip_pvt *p, char *msg, int inc, int reliable, int newbranch); static int transmit_request_with_auth(struct sip_pvt *p, char *msg, int inc, int reliable, int newbranch); static int transmit_invite(struct sip_pvt *p, char *msg, int sendsdp, char *auth, char *authheader, char *vxml_url,char *distinctive_ring, int init); -static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codec); +static int transmit_reinvite_with_sdp(struct sip_pvt *p); static int transmit_info_with_digit(struct sip_pvt *p, char digit); static int transmit_message_with_text(struct sip_pvt *p, char *text); static int transmit_refer(struct sip_pvt *p, char *dest); @@ -1552,6 +1554,7 @@ static int sip_hangup(struct ast_channel *ast) /* Note we will need a BYE when this all settles out but we can't send one while we have "INVITE" outstanding. */ p->pendingbye = 1; + p->needreinvite = 0; } } } @@ -3003,7 +3006,7 @@ static int add_digit(struct sip_request *req, char digit) } /*--- add_sdp: Add Session Description Protocol message ---*/ -static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs) +static int add_sdp(struct sip_request *resp, struct sip_pvt *p) { int len; int codec; @@ -3033,8 +3036,6 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp * return -1; } capability = p->jointcapability; - if (codecs) - capability = codecs & p->jointcapability; if (!p->sessionid) { p->sessionid = getpid(); @@ -3048,8 +3049,8 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp * if (p->redirip.sin_addr.s_addr) { dest.sin_port = p->redirip.sin_port; dest.sin_addr = p->redirip.sin_addr; - } else if (rtp) { - ast_rtp_get_peer(rtp, &dest); + if (p->redircodecs) + capability = p->redircodecs; } else { dest.sin_addr = p->ourip; dest.sin_port = sin.sin_port; @@ -3060,8 +3061,6 @@ static int add_sdp(struct sip_request *resp, struct sip_pvt *p, struct ast_rtp * if (p->vredirip.sin_addr.s_addr) { vdest.sin_port = p->vredirip.sin_port; vdest.sin_addr = p->vredirip.sin_addr; - } else if (vrtp) { - ast_rtp_get_peer(vrtp, &vdest); } else { vdest.sin_addr = p->ourip; vdest.sin_port = vsin.sin_port; @@ -3210,7 +3209,7 @@ static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_r return -1; } respprep(&resp, p, msg, req); - add_sdp(&resp, p, NULL, NULL, 0); + add_sdp(&resp, p); return send_response(p, &resp, retrans, seqno); } @@ -3277,7 +3276,7 @@ static int determine_firstline_parts( struct sip_request *req ) { /* transmit_reinvite_with_sdp: Transmit reinvite with SDP :-) ---*/ /* A re-invite is basically a new INVITE with the same CALL-ID and TAG as the INVITE that opened the SIP dialogue */ -static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codec) +static int transmit_reinvite_with_sdp(struct sip_pvt *p) { struct sip_request req; if (p->canreinvite == REINVITE_UPDATE) @@ -3286,7 +3285,7 @@ static int transmit_reinvite_with_sdp(struct sip_pvt *p, struct ast_rtp *rtp, st reqprep(&req, p, "INVITE", 0, 1); add_header(&req, "Allow", ALLOWED_METHODS); - add_sdp(&req, p, rtp, vrtp, codec); + add_sdp(&req, p); /* Use this as the basis */ copy_request(&p->initreq, &req); parse(&p->initreq); @@ -3433,7 +3432,7 @@ static int transmit_invite(struct sip_pvt *p, char *cmd, int sdp, char *auth, ch } add_header(&req, "Allow", ALLOWED_METHODS); if (sdp) { - add_sdp(&req, p, NULL, NULL, 0); + add_sdp(&req, p); } else { add_header(&req, "Content-Length", "0"); add_blank_header(&req); @@ -5846,6 +5845,21 @@ static void parse_moved_contact(struct sip_pvt *p, struct sip_request *req) strncpy(p->owner->call_forward, s, sizeof(p->owner->call_forward) - 1); } +static void check_pendings(struct sip_pvt *p) +{ + /* Go ahead and send bye at this point */ + if (p->pendingbye) { + transmit_request_with_auth(p, "BYE", 0, 1, 1); + p->needdestroy = 1; + p->needreinvite = 0; + } else if (p->needreinvite) { + ast_log(LOG_DEBUG, "Sending pending reinvite on '%s'\n", p->callid); + /* Didn't get to reinvite yet, so do it now */ + transmit_reinvite_with_sdp(p); + p->needreinvite = 0; + } +} + /*--- handle_response: Handle SIP response in dialogue ---*/ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore) { @@ -5984,11 +5998,7 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ p->authtries = 0; /* If I understand this right, the branch is different for a non-200 ACK only */ transmit_request(p, "ACK", seqno, 0, 1); - /* Go ahead and send bye at this point */ - if (p->pendingbye) { - transmit_request_with_auth(p, "BYE", 0, 1, 1); - p->needdestroy = 1; - } + check_pendings(p); } else if (!strcasecmp(msg, "REGISTER")) { /* char *exp; */ int expires, expires_ms; @@ -6342,6 +6352,8 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc sip_cancel_destroy(p); /* This call is no longer outgoing if it ever was */ p->outgoing = 0; + /* This also counts as a pending invite */ + p->pendinginvite = 1; copy_request(&p->initreq, req); check_via(p, req); if (!ast_strlen_zero(get_header(req, "Content-Type"))) { @@ -6681,11 +6693,13 @@ static int handle_request(struct sip_pvt *p, struct sip_request *req, struct soc /* Uhm, I haven't figured out the point of the ACK yet. Are we supposed to retransmit responses until we get an ack? Make sure this is on a valid call */ + p->pendinginvite = 0; __sip_ack(p, seqno, FLAG_RESPONSE); if (!ast_strlen_zero(get_header(req, "Content-Type"))) { if (process_sdp(p, req)) return -1; } + check_pendings(p); if (!p->lastinvite && ast_strlen_zero(p->randdata)) p->needdestroy = 1; } else if (!strcasecmp(cmd, "SIP/2.0")) { @@ -7730,7 +7744,7 @@ static struct ast_rtp *sip_get_vrtp_peer(struct ast_channel *chan) return NULL; } -static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codec) +static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs) { struct sip_pvt *p; p = chan->pvt->pvt; @@ -7743,8 +7757,14 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struc ast_rtp_get_peer(vrtp, &p->vredirip); else memset(&p->vredirip, 0, sizeof(p->vredirip)); + p->redircodecs = codecs; if (!p->gotrefer) { - transmit_reinvite_with_sdp(p, rtp, vrtp, codec); + if (!p->pendinginvite) + transmit_reinvite_with_sdp(p); + else if (!p->pendingbye) { + ast_log(LOG_DEBUG, "Deferring reinvite on '%s'\n", p->callid); + p->needreinvite = 1; + } p->outgoing = 1; } return 0; diff --git a/rtp.c b/rtp.c index 12658cfe8468396f99fe9562c33353cc03abb29b..90c7d602236d75d2ffec32e5501797049c35146b 100755 --- a/rtp.c +++ b/rtp.c @@ -1264,14 +1264,6 @@ int ast_rtp_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, st memset(&vac0, 0, sizeof(vac0)); memset(&vac1, 0, sizeof(vac1)); - /* XXX Wait a half a second for things to settle up - this really should be fixed XXX */ - ast_autoservice_start(c0); - ast_autoservice_start(c1); - usleep(500000); - ast_autoservice_stop(c0); - ast_autoservice_stop(c1); - /* if need DTMF, cant native bridge */ if (flags & (AST_BRIDGE_DTMF_CHANNEL_0 | AST_BRIDGE_DTMF_CHANNEL_1)) return -2;