浏览代码

tm: don't reply if the reply dest. is not yet set

- relay_reply() doesn't attempt to send the reply if the reply
 destination is not yet fully set. This can happen for example
 if reply_to_via is set, Via contains a host name (and not an ip)
 and before having a chance to resolve the name a reply must be
 sent (reply for a message that hasn't been sent yet: very
 unlikely, but possible).

- use a membar_write() in init_rb(), before setting the reply send
  socket (the reply send socket is also used as a flag for a fully
  initialized reply destination and the membar_write() makes sure
  that everything else was written before the send socket and no
  re-ordering will take place).
Andrei Pelinescu-Onciul 15 年之前
父节点
当前提交
96e1bc629b
共有 2 个文件被更改,包括 7 次插入18 次删除
  1. 2 15
      modules/tm/t_lookup.c
  2. 5 3
      modules/tm/t_reply.c

+ 2 - 15
modules/tm/t_lookup.c

@@ -1196,7 +1196,6 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
 	/*struct socket_info* send_sock;*/
 	struct via_body* via;
 	int proto;
-	int backup_mhomed;
 
 	/* rb. timers are init. init_t()/new_cell() */
 	via=msg->via1;
@@ -1220,20 +1219,8 @@ int init_rb( struct retr_buf *rb, struct sip_msg *msg)
 	rb->dst.comp=via->comp_no;
 #endif
 	rb->dst.send_flags=msg->rpl_send_flags;
-	/* turn off mhomed for generating replies -- they are ideally sent to where
-	   request came from to make life with NATs and other beasts easier
-	*/
-	backup_mhomed=mhomed;
-	mhomed=0;
-	mhomed=backup_mhomed;
-	/* use for sending replies the incoming interface of the request -bogdan */
-	/*send_sock=get_send_socket(msg, &rb->dst.to, proto);
-	if (send_sock==0) {
-		LOG(L_ERR, "ERROR: init_rb: cannot fwd to af %d, proto %d "
-			"no socket\n", rb->dst.to.s.sa_family, proto);
-		ser_error=E_BAD_VIA;
-		return 0;
-	}*/
+	
+	membar_write();
 	rb->dst.send_sock=msg->rcv.bind_address;
 	return 1;
 }

+ 5 - 3
modules/tm/t_reply.c

@@ -637,7 +637,7 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
 	   If reply_to_via is set and via contains a host name (and not an ip)
 	   the chances for this increase a lot.
 	 */
-	if (!trans->uas.response.dst.send_sock) {
+	if (unlikely(!trans->uas.response.dst.send_sock)) {
 		LOG(L_ERR, "ERROR: _reply_light: no resolved dst to send reply to\n");
 	} else {
 		if (likely(SEND_PR_BUFFER( rb, buf, len )>=0)){
@@ -1786,7 +1786,8 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 		if (reply_status == RPS_COMPLETED) {
 			start_final_repl_retr(t);
 		}
-		if (SEND_PR_BUFFER( uas_rb, buf, res_len )>=0){
+		if (likely(uas_rb->dst.send_sock &&
+					SEND_PR_BUFFER( uas_rb, buf, res_len ) >= 0)){
 			if (unlikely(!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT))){
 				run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request,
 					relayed_msg, relayed_code);
@@ -1801,7 +1802,8 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 				run_onsend_callbacks2(TMCB_RESPONSE_SENT, t, &onsend_params);
 			}
 #endif
-		}
+		} else if (unlikely(uas_rb->dst.send_sock == 0))
+			ERR("no resolved dst to send reply to\n");
 		/* Call put_on_wait() only if we really send out
 		* the reply. It can happen that the reply has been already sent from
 		* failure_route  or from a callback and the timer has been already