forked from osmocom/wireshark
Mkae the handling of non-full-frame time stamps match RFC 5456.
At least as I read RFC 5456: 1) non-full-frame time stamps should have high-order bits from the time stamp of the last full frame ORed into it; 2) "mini voice packets" have a 16-bit time stamp and "mini video packets" have a 15-bit time stamp; so adjust the non-full-frame time stamps in that fashion rather than by adding 32768 until the value looks OK - and don't adjust full-frame time stamps at all. Change-Id: I20873a633a99415ac73a7e6baf087e5ec62a4905 Reviewed-on: https://code.wireshark.org/review/28555 Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
parent
17a39db773
commit
5c6f2e8882
1 changed files with 91 additions and 34 deletions
|
@ -177,7 +177,6 @@ static expert_field ei_iax_too_many_transfers = EI_INIT;
|
|||
static expert_field ei_iax_circuit_id_conflict = EI_INIT;
|
||||
static expert_field ei_iax_peer_address_unsupported = EI_INIT;
|
||||
static expert_field ei_iax_invalid_len = EI_INIT;
|
||||
static expert_field ei_iax_invalid_ts = EI_INIT;
|
||||
|
||||
static dissector_handle_t iax2_handle;
|
||||
|
||||
|
@ -726,6 +725,9 @@ typedef struct iax_call_data {
|
|||
/* the absolute start time of the call */
|
||||
nstime_t start_time;
|
||||
|
||||
/* time stamp from last full frame, in the first pass */
|
||||
guint32 last_full_frame_ts;
|
||||
|
||||
iax_call_dirdata dirdata[2];
|
||||
} iax_call_data;
|
||||
|
||||
|
@ -1014,6 +1016,7 @@ static iax_call_data *iax_new_call( packet_info *pinfo,
|
|||
call -> n_reverse_circuit_ids = 0;
|
||||
call -> subdissector = NULL;
|
||||
call -> start_time = pinfo->abs_ts;
|
||||
call -> last_full_frame_ts = 0;
|
||||
nstime_delta(&call -> start_time, &call -> start_time, &millisecond);
|
||||
init_dir_data(&call->dirdata[0]);
|
||||
init_dir_data(&call->dirdata[1]);
|
||||
|
@ -1551,11 +1554,10 @@ static guint32 dissect_iax2_command(tvbuff_t *tvb, guint32 offset,
|
|||
return offset;
|
||||
}
|
||||
|
||||
#define MAX_SECS_DIFF 60 /* Arbitrary. Needs to be within loop bounds below. */
|
||||
static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, tvbuff_t *tvb, iax_packet_data *iax_packet, guint16 shortts)
|
||||
static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, tvbuff_t *tvb, iax_packet_data *iax_packet, packet_type type, guint32 relts)
|
||||
{
|
||||
guint longts =shortts;
|
||||
nstime_t ts;
|
||||
guint32 full_relts = relts;
|
||||
nstime_t lateness;
|
||||
proto_item *item;
|
||||
|
||||
if (iax_packet->call_data == NULL) {
|
||||
|
@ -1564,38 +1566,94 @@ static void iax2_add_ts_fields(packet_info *pinfo, proto_tree *iax2_tree, tvbuff
|
|||
}
|
||||
|
||||
if (iax_packet->abstime.secs == -1) {
|
||||
time_t start_secs = iax_packet->call_data->start_time.secs;
|
||||
time_t abs_secs = start_secs + longts/1000;
|
||||
nstime_t rel;
|
||||
|
||||
if (pinfo->abs_ts.secs - abs_secs > MAX_SECS_DIFF) {
|
||||
proto_tree_add_expert(iax2_tree, pinfo, &ei_iax_invalid_ts, tvb, 0, 0);
|
||||
} else {
|
||||
/* deal with short timestamps by assuming that packets are never more than
|
||||
* 16 seconds late */
|
||||
/* XXX Use arithmetic here instead of a loop? */
|
||||
while(abs_secs < pinfo->abs_ts.secs - 16) {
|
||||
longts += 32768;
|
||||
abs_secs = start_secs + longts/1000;
|
||||
}
|
||||
switch (type) {
|
||||
case IAX2_MINI_VOICE_PACKET:
|
||||
/* RFC 5456 says
|
||||
*
|
||||
* Abbreviated 'Mini Frames' are normally used for audio and
|
||||
* video; however, each time the time-stamp is a multiple of
|
||||
* 32,768 (0x8000 hex), a standard or 'Full Frame' MUST be sent.
|
||||
*
|
||||
* and, for what it later calls "Mini Frames", by which it means
|
||||
* what we're calling "mini voice packets", it says:
|
||||
*
|
||||
* Mini frames carry a 16-bit time-stamp, which is the lower 16 bits
|
||||
* of the transmitting peer's full 32-bit time-stamp for the call.
|
||||
* The time-stamp allows synchronization of incoming frames so that
|
||||
* they MAY be processed in chronological order instead of the
|
||||
* (possibly different) order in which they are received. The 16-bit
|
||||
* time-stamp wraps after 65.536 seconds, at which point a full frame
|
||||
* SHOULD be sent to notify the remote peer that its time-stamp has
|
||||
* been reset. A call MUST continue to send mini frames starting
|
||||
* with time-stamp 0 even if acknowledgment of the resynchronization
|
||||
* is not received.
|
||||
*
|
||||
* *If* we see all the full frames, that means we *should* be able
|
||||
* to convert the 16-bit time stamp to a full 32-bit time stamp by
|
||||
* ORing the upper 16 bits of the last full frame time stamp we saw
|
||||
* in above the 16-bit time stamp.
|
||||
*
|
||||
* XXX - what, if anything, should we do about full frames we've
|
||||
* missed? */
|
||||
full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF0000) | relts;
|
||||
break;
|
||||
|
||||
case IAX2_FULL_PACKET:
|
||||
case IAX2_TRUNK_PACKET:
|
||||
/* Timestamps have the full 32 bits of the timestamp.
|
||||
* Save it, to add to the mini-packet time stamps.
|
||||
*
|
||||
* XXX - that's a maximum of 4294967296 milliseconds
|
||||
* or about 4294967 seconds or about 49 days.
|
||||
* Do we need to worry about that overflowing? */
|
||||
full_relts = relts;
|
||||
iax_packet->call_data->last_full_frame_ts = full_relts;
|
||||
break;
|
||||
|
||||
case IAX2_MINI_VIDEO_PACKET:
|
||||
/* See the comment above in the IAX2_MINI_VOICE_PACKET case.
|
||||
* Note also that RFC 5456 says, in section 8.1.3.1 "Meta Video
|
||||
* Frames", which covers what we're calling "mini video packets":
|
||||
*
|
||||
* Meta video frames carry a 16-bit time-stamp, which is the lower 16
|
||||
* bits of the transmitting peer's full 32-bit time-stamp for the
|
||||
* call. When this time-stamp wraps, a Full Frame SHOULD be sent to
|
||||
* notify the remote peer that the time-stamp has been reset to 0.
|
||||
*
|
||||
* *but* it also shows the uppermost bit of that time stamp as "?",
|
||||
* with a 15-bit time stamp, in the ASCII-art packet diagram after
|
||||
* it. dissect_minivideopacket() says "bit 15 of the ts is used to
|
||||
* represent the rtp 'marker' bit"; presumably that's what's going
|
||||
* on, but the RFC doesn't say that.
|
||||
*
|
||||
* So we assume that the time stamp is only 15 bits, and that the
|
||||
* upper *17* bits of the last full frame's time stamp need to be
|
||||
* ORed in above the 15 bits of time stamp.
|
||||
*
|
||||
* XXX - do we need to worry about overflows or missed packets
|
||||
* with full timestamps? */
|
||||
full_relts = (iax_packet->call_data->last_full_frame_ts & 0xFFFF8000) | relts;
|
||||
break;
|
||||
}
|
||||
|
||||
iax_packet->abstime.secs=abs_secs;
|
||||
iax_packet->abstime.nsecs=iax_packet->call_data->start_time.nsecs + (longts % 1000) * 1000000;
|
||||
if (iax_packet->abstime.nsecs >= 1000000000) {
|
||||
iax_packet->abstime.nsecs -= 1000000000;
|
||||
iax_packet->abstime.secs ++;
|
||||
}
|
||||
/* Convert the full relative time stamp to an nstime_t */
|
||||
rel.secs = full_relts / 1000;
|
||||
rel.nsecs = (full_relts % 1000) * 1000000;
|
||||
|
||||
/* Add it to the start time to get the absolute time. */
|
||||
nstime_sum(&iax_packet->abstime, &iax_packet->call_data->start_time, &rel);
|
||||
}
|
||||
iax2_info->timestamp = longts;
|
||||
iax2_info->timestamp = relts; /* raw time stamp; nobody uses it */
|
||||
|
||||
if (iax2_tree) {
|
||||
item = proto_tree_add_time(iax2_tree, hf_iax2_absts, tvb, 0, 0, &iax_packet->abstime);
|
||||
PROTO_ITEM_SET_GENERATED(item);
|
||||
|
||||
ts = pinfo->abs_ts;
|
||||
nstime_delta(&ts, &ts, &iax_packet->abstime);
|
||||
nstime_delta(&lateness, &pinfo->abs_ts, &iax_packet->abstime);
|
||||
|
||||
item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, tvb, 0, 0, &ts);
|
||||
item = proto_tree_add_time(iax2_tree, hf_iax2_lateness, tvb, 0, 0, &lateness);
|
||||
PROTO_ITEM_SET_GENERATED(item);
|
||||
}
|
||||
}
|
||||
|
@ -1669,7 +1727,7 @@ dissect_fullpacket(tvbuff_t *tvb, guint32 offset,
|
|||
}
|
||||
|
||||
proto_tree_add_uint(iax2_tree, hf_iax2_ts, tvb, offset+2, 4, ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts);
|
||||
|
||||
proto_tree_add_item(iax2_tree, hf_iax2_oseqno, tvb, offset+6, 1,
|
||||
ENC_BIG_ENDIAN);
|
||||
|
@ -1682,7 +1740,7 @@ dissect_fullpacket(tvbuff_t *tvb, guint32 offset,
|
|||
/* add the type-specific subtree */
|
||||
packet_type_tree = proto_item_add_subtree(packet_type_base, ett_iax2_type);
|
||||
} else {
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_FULL_PACKET, ts);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1886,10 +1944,10 @@ static guint32 dissect_minivideopacket(tvbuff_t *tvb, guint32 offset,
|
|||
}
|
||||
|
||||
proto_tree_add_item(iax2_tree, hf_iax2_minividts, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts);
|
||||
proto_tree_add_item(iax2_tree, hf_iax2_minividmarker, tvb, offset, 2, ENC_BIG_ENDIAN);
|
||||
} else {
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VIDEO_PACKET, ts);
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
|
@ -1928,9 +1986,9 @@ static guint32 dissect_minipacket(tvbuff_t *tvb, guint32 offset, guint16 scallno
|
|||
}
|
||||
|
||||
proto_tree_add_uint(iax2_tree, hf_iax2_minits, tvb, offset, 2, ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts);
|
||||
} else {
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, (guint16)ts);
|
||||
iax2_add_ts_fields(pinfo, iax2_tree, tvb, iax_packet, IAX2_MINI_VOICE_PACKET, ts);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3173,7 +3231,6 @@ proto_register_iax2(void)
|
|||
{ &ei_iax_circuit_id_conflict, { "iax2.circuit_id_conflict", PI_PROTOCOL, PI_WARN, "Circuit ID conflict", EXPFILL }},
|
||||
{ &ei_iax_peer_address_unsupported, { "iax2.peer_address_unsupported", PI_PROTOCOL, PI_WARN, "Peer address unsupported", EXPFILL }},
|
||||
{ &ei_iax_invalid_len, { "iax2.invalid_len", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
|
||||
{ &ei_iax_invalid_ts, { "iax2.invalid_ts", PI_PROTOCOL, PI_WARN, "Invalid timestamp", EXPFILL }}
|
||||
};
|
||||
|
||||
expert_module_t* expert_iax;
|
||||
|
|
Loading…
Reference in a new issue