Benny Prijono wrote: > On Fri, Aug 8, 2008 at 6:39 PM, Pedro Gon?alves > <pedro.pandre at gmail.com <mailto:pedro.pandre at gmail.com>> wrote: > > > The check->tdata is set to NULL once that particular > connectivity check completes (i.e. on_stun_request_complete() > has been called for that check). > > The assertion is put there to make sure that > on_stun_request_complete() is not called more than once for > the same check. > > -benny > > OK. So basically if for some reason we receive 2 Binding Responses > to the same Binding Request, we'll get an assert error. > > > No, that's a wrong conclusion. > > > Is this desirable? Should'nt the subsequent Binding Responses to > an already completed transaction be simply ignored? > > > It will. Subsequent responses will be (or should be) treated as > retransmission by the transaction layer, and it will not call the > callback. > > > However, what about in the case where neither tdata nor > check->tdata are null, and they are simply different from each other? > What can cause this? > > > Frankly, I don't know. That's what we're trying to find out, aren't we. :) > > > I am including the application log and the capture I made when > this exception happened. > > In the last lines of the log we can see that a Binding success > response was received. > I've also added some debug in functions pj_stun_session_on_rx_pkt > (), on_incoming_response(), pj_stun_client_tsx_on_rx_msg(), > stun_tsx_on_complete(), in which we can see that > tdata and check->tdata were already different, thus causing the > assertion error. > > > How can you print the tdata and check->tdata in > pj_stun_session_on_rx_pkt()? Where did you get the pointers from? I had some work tracing back the variables, but here is how I am gettting them: on *stun_tsx_on_complete*, *tdata* is ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx)) and *check->tdata* is (((pj_ice_msg_data*) ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx))->token))->data.req.clist->checks[((pj_ice_msg_data*) ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx))->token)->data.req.ckid].tdata on *pj_stun_client_tsx_on_rx_msg*, *tdata* is ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx)) and *check->tdata* is (((pj_ice_msg_data*) ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx))->token))->data.req.clist->checks[((pj_ice_msg_data*) ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx))->token)->data.req.ckid].tdata on *on_incoming_response*, *tdata* is ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tdata->client_tsx)) and *check->tdata* can be got making pj_stun_tx_data *stun_tx_data = ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tdata->client_tsx)); pj_ice_msg_data *ice_msg_data = (((pj_ice_msg_data*) stun_tx_data->token)); this way, check->tdata is ice_msg_data->data.req.clist->checks[ice_msg_data->data.req.ckid].tdata on *pj_stun_session_on_rx_pkt*, *tdata* is ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx_lookup(sess, msg)->client_tsx)) and *check->tdata* can be got making pj_stun_tx_data *stun_tx_data = ((pj_stun_tx_data*) pj_stun_client_tsx_get_data(tsx_lookup(sess, msg)->client_tsx)); pj_ice_msg_data *ice_msg_data = (((pj_ice_msg_data*) stun_tx_data->token)); this way, check->tdata is ice_msg_data->data.req.clist->checks[ice_msg_data->data.req.ckid].tdata Cheers Pedro Gon?alves