@@ -1383,13 +1383,13 @@ static struct iax_frame *iaxfrdup2(struct iax_frame *fr)
13831383#define NEW_ALLOW 1
13841384#define NEW_FORCE 2
13851385
1386- static int match (struct sockaddr_in * sin , unsigned short callno , unsigned short dcallno , const struct chan_iax2_pvt * cur )
1386+ static int match (struct sockaddr_in * sin , unsigned short callno , unsigned short dcallno , const struct chan_iax2_pvt * cur , int full_frame )
13871387{
13881388 if ((cur -> addr .sin_addr .s_addr == sin -> sin_addr .s_addr ) &&
13891389 (cur -> addr .sin_port == sin -> sin_port )) {
13901390 /* This is the main host */
1391- if ((cur -> peercallno == callno ) ||
1392- (( dcallno == cur -> callno ) && ! cur -> peercallno ) ) {
1391+ if ( (cur -> peercallno == 0 || cur -> peercallno == callno ) &&
1392+ ( full_frame ? dcallno == cur -> callno : 1 ) ) {
13931393 /* That's us. Be sure we keep track of the peer call number */
13941394 return 1 ;
13951395 }
@@ -1491,7 +1491,7 @@ static int make_trunk(unsigned short callno, int locked)
14911491 *
14921492 * \note Calling this function while holding another pvt lock can cause a deadlock.
14931493 */
1494- static int __find_callno (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd , int return_locked )
1494+ static int __find_callno (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd , int return_locked , int full_frame )
14951495{
14961496 int res = 0 ;
14971497 int x ;
@@ -1503,7 +1503,7 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
15031503 ast_mutex_lock (& iaxsl [x ]);
15041504 if (iaxs [x ]) {
15051505 /* Look for an exact match */
1506- if (match (sin , callno , dcallno , iaxs [x ])) {
1506+ if (match (sin , callno , dcallno , iaxs [x ], full_frame )) {
15071507 res = x ;
15081508 }
15091509 }
@@ -1513,14 +1513,16 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
15131513 ast_mutex_lock (& iaxsl [x ]);
15141514 if (iaxs [x ]) {
15151515 /* Look for an exact match */
1516- if (match (sin , callno , dcallno , iaxs [x ])) {
1516+ if (match (sin , callno , dcallno , iaxs [x ], full_frame )) {
15171517 res = x ;
15181518 }
15191519 }
15201520 ast_mutex_unlock (& iaxsl [x ]);
15211521 }
15221522 }
15231523 if ((res < 1 ) && (new >= NEW_ALLOW )) {
1524+ int start , found = 0 ;
1525+
15241526 /* It may seem odd that we look through the peer list for a name for
15251527 * this *incoming* call. Well, it is weird. However, users don't
15261528 * have an IP address/port number that we can match against. So,
@@ -1529,15 +1531,29 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
15291531 * correct, but it will be changed if needed after authentication. */
15301532 if (!iax2_getpeername (* sin , host , sizeof (host )))
15311533 snprintf (host , sizeof (host ), "%s:%d" , ast_inet_ntoa (sin -> sin_addr ), ntohs (sin -> sin_port ));
1534+
15321535 now = ast_tvnow ();
1533- for (x = 1 ;x < TRUNK_CALL_START ;x ++ ) {
1536+ start = 1 + (ast_random () % (TRUNK_CALL_START - 1 ));
1537+ for (x = start ; 1 ; x ++ ) {
1538+ if (x == TRUNK_CALL_START ) {
1539+ x = 0 ;
1540+ continue ;
1541+ }
1542+
15341543 /* Find first unused call number that hasn't been used in a while */
15351544 ast_mutex_lock (& iaxsl [x ]);
1536- if (!iaxs [x ] && ((now .tv_sec - lastused [x ].tv_sec ) > MIN_REUSE_TIME )) break ;
1545+ if (!iaxs [x ] && ((now .tv_sec - lastused [x ].tv_sec ) > MIN_REUSE_TIME )) {
1546+ found = 1 ;
1547+ break ;
1548+ }
15371549 ast_mutex_unlock (& iaxsl [x ]);
1550+
1551+ if (x == start - 1 ) {
1552+ break ;
1553+ }
15381554 }
15391555 /* We've still got lock held if we found a spot */
1540- if (x >= TRUNK_CALL_START ) {
1556+ if (x == start - 1 && ! found ) {
15411557 ast_log (LOG_WARNING , "No more space\n" );
15421558 return 0 ;
15431559 }
@@ -1575,14 +1591,14 @@ static int __find_callno(unsigned short callno, unsigned short dcallno, struct s
15751591 return res ;
15761592}
15771593
1578- static int find_callno (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd ) {
1594+ static int find_callno (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd , int full_frame ) {
15791595
1580- return __find_callno (callno , dcallno , sin , new , sockfd , 0 );
1596+ return __find_callno (callno , dcallno , sin , new , sockfd , 0 , full_frame );
15811597}
15821598
1583- static int find_callno_locked (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd ) {
1599+ static int find_callno_locked (unsigned short callno , unsigned short dcallno , struct sockaddr_in * sin , int new , int sockfd , int full_frame ) {
15841600
1585- return __find_callno (callno , dcallno , sin , new , sockfd , 1 );
1601+ return __find_callno (callno , dcallno , sin , new , sockfd , 1 , full_frame );
15861602}
15871603
15881604static void iax2_frame_free (struct iax_frame * fr )
@@ -7624,7 +7640,7 @@ static int socket_process_meta(int packet_len, struct ast_iax2_meta_hdr *meta, s
76247640 /* Stop if we don't have enough data */
76257641 if (len > packet_len )
76267642 break ;
7627- fr -> callno = find_callno_locked (callno & ~IAX_FLAG_FULL , 0 , sin , NEW_PREVENT , sockfd );
7643+ fr -> callno = find_callno_locked (callno & ~IAX_FLAG_FULL , 0 , sin , NEW_PREVENT , sockfd , 0 );
76287644 if (!fr -> callno )
76297645 continue ;
76307646
@@ -7807,7 +7823,7 @@ static int socket_process(struct iax2_thread *thread)
78077823 }
78087824
78097825 /* This is a video frame, get call number */
7810- fr -> callno = find_callno (ntohs (vh -> callno ) & ~0x8000 , dcallno , & sin , new , fd );
7826+ fr -> callno = find_callno (ntohs (vh -> callno ) & ~0x8000 , dcallno , & sin , new , fd , 0 );
78117827 minivid = 1 ;
78127828 } else if ((meta -> zeros == 0 ) && !(ntohs (meta -> metacmd ) & 0x8000 ))
78137829 return socket_process_meta (res , meta , & sin , fd , fr );
@@ -7842,7 +7858,7 @@ static int socket_process(struct iax2_thread *thread)
78427858 }
78437859
78447860 if (!fr -> callno )
7845- fr -> callno = find_callno (ntohs (mh -> callno ) & ~IAX_FLAG_FULL , dcallno , & sin , new , fd );
7861+ fr -> callno = find_callno (ntohs (mh -> callno ) & ~IAX_FLAG_FULL , dcallno , & sin , new , fd , ntohs ( mh -> callno ) & IAX_FLAG_FULL );
78467862
78477863 if (fr -> callno > 0 )
78487864 ast_mutex_lock (& iaxsl [fr -> callno ]);
@@ -9424,7 +9440,7 @@ static int iax2_do_register(struct iax2_registry *reg)
94249440
94259441 if (!reg -> callno ) {
94269442 ast_debug (1 , "Allocate call number\n" );
9427- reg -> callno = find_callno_locked (0 , 0 , & reg -> addr , NEW_FORCE , defaultsockfd );
9443+ reg -> callno = find_callno_locked (0 , 0 , & reg -> addr , NEW_FORCE , defaultsockfd , 0 );
94289444 if (reg -> callno < 1 ) {
94299445 ast_log (LOG_WARNING , "Unable to create call for registration\n" );
94309446 return -1 ;
@@ -9475,7 +9491,7 @@ static int iax2_provision(struct sockaddr_in *end, int sockfd, char *dest, const
94759491 memset (& ied , 0 , sizeof (ied ));
94769492 iax_ie_append_raw (& ied , IAX_IE_PROVISIONING , provdata .buf , provdata .pos );
94779493
9478- callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd );
9494+ callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd , 0 );
94799495 if (!callno )
94809496 return -1 ;
94819497
@@ -9631,7 +9647,7 @@ static int iax2_poke_peer(struct iax2_peer *peer, int heldcall)
96319647 }
96329648 if (heldcall )
96339649 ast_mutex_unlock (& iaxsl [heldcall ]);
9634- peer -> callno = find_callno (0 , 0 , & peer -> addr , NEW_FORCE , peer -> sockfd );
9650+ peer -> callno = find_callno (0 , 0 , & peer -> addr , NEW_FORCE , peer -> sockfd , 0 );
96359651 if (heldcall )
96369652 ast_mutex_lock (& iaxsl [heldcall ]);
96379653 if (peer -> callno < 1 ) {
@@ -9710,7 +9726,7 @@ static struct ast_channel *iax2_request(const char *type, int format, void *data
97109726 if (pds .port )
97119727 sin .sin_port = htons (atoi (pds .port ));
97129728
9713- callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd );
9729+ callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd , 0 );
97149730 if (callno < 1 ) {
97159731 ast_log (LOG_WARNING , "Unable to create call\n" );
97169732 * cause = AST_CAUSE_CONGESTION ;
@@ -11083,7 +11099,7 @@ static int cache_get_callno_locked(const char *data)
1108311099 ast_debug (1 , "peer: %s, username: %s, password: %s, context: %s\n" ,
1108411100 pds .peer , pds .username , pds .password , pds .context );
1108511101
11086- callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd );
11102+ callno = find_callno_locked (0 , 0 , & sin , NEW_FORCE , cai .sockfd , 0 );
1108711103 if (callno < 1 ) {
1108811104 ast_log (LOG_WARNING , "Unable to create call\n" );
1108911105 return -1 ;
0 commit comments