2 * Routines for "Time Shift" window
3 * Submitted by Edwin Groothuis <wireshark@mavetju.org>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "time_shift.h"
37 #include "ui/ui_util.h"
41 #define SHIFT_SETTOZERO 1
42 #define SHIFT_KEEPOFFSET 0
44 #define CHECK_YEARS(Y) \
46 return "Years must be larger than 1970"; \
48 #define CHECK_MONTHS(M) \
49 if (*M < 1 || *M > 12) { \
50 return "Months must be between [1..12]"; \
52 #define CHECK_DAYS(D) \
53 if (*D < 1 || *D > 31) { \
54 return "Days must be between [1..31]"; \
56 #define CHECK_HOURS(h) \
57 if (*h < 0 || *h > 23) { \
58 return "Hours must be between [0..23]"; \
60 #define CHECK_HOUR(h) \
62 return "Negative hours. Have you specified more than " \
63 "one minus character?"; \
65 #define CHECK_MINUTE(m) \
66 if (*m < 0 || *m > 59) { \
67 return "Minutes must be between [0..59]"; \
69 #define CHECK_SECOND(s) \
70 if (*s < 0 || *s > 59) { \
71 return "Seconds must be between [0..59]"; \
75 modify_time_perform(frame_data
*fd
, int neg
, nstime_t
*offset
, int settozero
)
77 /* The actual shift */
78 if (settozero
== SHIFT_SETTOZERO
) {
79 nstime_subtract(&(fd
->abs_ts
), &(fd
->shift_offset
));
80 nstime_set_zero(&(fd
->shift_offset
));
83 if (neg
== SHIFT_POS
) {
84 nstime_add(&(fd
->abs_ts
), offset
);
85 nstime_add(&(fd
->shift_offset
), offset
);
86 } else if (neg
== SHIFT_NEG
) {
87 nstime_subtract(&(fd
->abs_ts
), offset
);
88 nstime_subtract(&(fd
->shift_offset
), offset
);
90 fprintf(stderr
, "Modify_time_perform: neg = %d?\n", neg
);
95 * If the line between (OT1, NT1) and (OT2, NT2) is a straight line
96 * and (OT3, NT3) is on that line,
97 * then (NT2 - NT1) / (OT2 - OT2) = (NT3 - NT1) / (OT3 - OT1) and
98 * then (OT3 - OT1) * (NT2 - NT1) / (OT2 - OT2) = (NT3 - NT1) and
99 * then NT1 + (OT3 - OT1) * (NT2 - NT1) / (OT2 - OT2) = NT3 and
100 * then NT3 = NT1 + (OT3 - OT1) * (NT2 - NT1) / (OT2 - OT2) and
101 * thus NT3 = NT1 + (OT3 - OT1) * (NT2 - NT1) / (OT2 - OT1)
102 * or NT3 = NT1 + (OT3 - OT1) * ( deltaNT12 / deltaOT12)
104 * All the things you come up when waiting for the train to come...
107 calcNT3(nstime_t
*OT1
, nstime_t
*OT3
, nstime_t
*NT1
, nstime_t
*NT3
,
108 nstime_t
*deltaOT
, nstime_t
*deltaNT
)
110 long double fnt
, fot
, f
, secs
, nsecs
;
112 fnt
= (long double)deltaNT
->secs
+ (deltaNT
->nsecs
/ 1000000000.0L);
113 fot
= (long double)deltaOT
->secs
+ (deltaOT
->nsecs
/ 1000000000.0L);
116 nstime_copy(NT3
, OT3
);
117 nstime_subtract(NT3
, OT1
);
119 secs
= f
* (long double)NT3
->secs
;
120 nsecs
= f
* (long double)NT3
->nsecs
;
121 nsecs
+= (secs
- floorl(secs
)) * 1000000000.0L;
122 while (nsecs
> 1000000000L) {
124 nsecs
-= 1000000000L;
128 nsecs
+= 1000000000L;
130 NT3
->secs
= (time_t)secs
;
131 NT3
->nsecs
= (int)nsecs
;
132 nstime_add(NT3
, NT1
);
136 time_string_parse(const gchar
*time_text
, int *year
, int *month
, int *day
, gboolean
*negative
, int *hour
, int *minute
, long double *second
) {
139 if (!time_text
|| !hour
|| !minute
|| !second
)
140 return "Unable to convert time.";
142 pts
= (gchar
*)time_text
;
144 /* strip whitespace */
145 while (isspace(pts
[0]))
148 if (year
&& month
&& day
) {
150 * The following time format is allowed:
151 * [YYYY-MM-DD] hh:mm:ss(.decimals)?
153 * Since Wireshark doesn't support regular expressions (please prove me
154 * wrong :-) we will have to figure it out ourselves in the
157 * 1. YYYY-MM-DD hh:mm:ss.decimals
158 * 2. hh:mm:ss.decimals
162 /* check for empty string */
164 return "Time is empty.";
166 if (sscanf(pts
, "%d-%d-%d %d:%d:%Lf", year
, month
, day
, hour
, minute
, second
) == 6) {
167 /* printf("%%d-%%d-%%d %%d:%%d:%%f\n"); */
172 CHECK_MINUTE(minute
);
173 CHECK_SECOND(second
);
174 } else if (sscanf(pts
, "%d:%d:%Lf", hour
, minute
, second
) == 3) {
175 /* printf("%%d:%%d:%%f\n"); */
176 *year
= *month
= *day
= 0;
178 CHECK_MINUTE(minute
);
179 CHECK_SECOND(second
);
181 return "Could not parse the time. Expected [YYYY-MM-DD] "
186 return "Unable to convert time.";
189 * The following offset types are allowed:
190 * -?((hh:)mm:)ss(.decimals)?
192 * Since Wireshark doesn't support regular expressions (please prove me
193 * wrong :-) we will have to figure it out ourselves in the
196 * 1. hh:mm:ss.decimals
202 /* check for minus sign */
209 /* check for empty string */
211 return "Time is empty.";
213 if (sscanf(pts
, "%d:%d:%Lf", hour
, minute
, second
) == 3) {
214 /* printf("%%d:%%d:%%d.%%d\n"); */
216 CHECK_MINUTE(minute
);
217 CHECK_SECOND(second
);
218 } else if (sscanf(pts
, "%d:%Lf", minute
, second
) == 2) {
219 /* printf("%%d:%%d.%%d\n"); */
220 CHECK_MINUTE(minute
);
221 CHECK_SECOND(second
);
223 } else if (sscanf(pts
, "%Lf", second
) == 1) {
224 /* printf("%%d.%%d\n"); */
225 CHECK_SECOND(second
);
228 return "Could not parse the time: Expected [[hh:]mm:]ss.[dec].";
236 time_string_to_nstime(const gchar
*time_text
, nstime_t
*packettime
, nstime_t
*nstime
)
240 struct tm tm
, *tmptm
;
242 const gchar
*err_str
;
244 if ((err_str
= time_string_parse(time_text
, &Y
, &M
, &D
, NULL
, &h
, &m
, &f
)) != NULL
)
247 /* Convert the time entered in an epoch offset */
248 tmptm
= localtime(&(packettime
->secs
));
252 memset (&tm
, 0, sizeof (tm
));
255 tm
.tm_year
= Y
- 1900;
261 tm
.tm_sec
= (int)floorl(f
);
264 return "Mktime went wrong. Is the time valid?";
269 nstime
->nsecs
= (int)(f
* 1000000000);
275 time_shift_all(capture_file
*cf
, const gchar
*offset_text
)
278 long double offset_float
= 0;
284 const gchar
*err_str
;
286 if (!cf
|| !offset_text
)
287 return "Nothing to work with.";
289 if ((err_str
= time_string_parse(offset_text
, NULL
, NULL
, NULL
, &neg
, &h
, &m
, &f
)) != NULL
)
292 offset_float
= h
* 3600 + m
* 60 + f
;
294 if (offset_float
== 0)
295 return "Offset is zero.";
297 nstime_set_zero(&offset
);
298 offset
.secs
= (time_t)floorl(offset_float
);
299 offset_float
-= offset
.secs
;
300 offset
.nsecs
= (int)(offset_float
* 1000000000);
302 if (!frame_data_sequence_find(cf
->frames
, 1))
303 return "No frames found."; /* Shouldn't happen */
305 for (i
= 1; i
<= cf
->count
; i
++) {
306 if ((fd
= frame_data_sequence_find(cf
->frames
, i
)) == NULL
)
307 continue; /* Shouldn't happen */
308 modify_time_perform(fd
, neg
? SHIFT_NEG
: SHIFT_POS
, &offset
, SHIFT_KEEPOFFSET
);
310 packet_list_queue_draw();
316 time_shift_settime(capture_file
*cf
, guint packet_num
, const gchar
*time_text
)
318 nstime_t set_time
, diff_time
, packet_time
;
319 frame_data
*fd
, *packetfd
;
321 const gchar
*err_str
;
323 if (!cf
|| !time_text
)
324 return "Nothing to work with.";
326 if (packet_num
< 1 || packet_num
> cf
->count
)
327 return "Packet out of range.";
330 * Get a copy of the real time (abs_ts - shift_offset) do we can find out the
331 * difference between the specified time and the original packet
333 if ((packetfd
= frame_data_sequence_find(cf
->frames
, packet_num
)) == NULL
)
334 return "No packets found.";
335 nstime_delta(&packet_time
, &(packetfd
->abs_ts
), &(packetfd
->shift_offset
));
337 if ((err_str
= time_string_to_nstime(time_text
, &packet_time
, &set_time
)) != NULL
)
340 /* Calculate difference between packet time and requested time */
341 nstime_delta(&diff_time
, &set_time
, &packet_time
);
343 /* Up to here nothing is changed */
345 if (!frame_data_sequence_find(cf
->frames
, 1))
346 return "No frames found."; /* Shouldn't happen */
348 /* Set everything back to the original time */
349 for (i
= 1; i
<= cf
->count
; i
++) {
350 if ((fd
= frame_data_sequence_find(cf
->frames
, i
)) == NULL
)
351 continue; /* Shouldn't happen */
352 modify_time_perform(fd
, SHIFT_POS
, &diff_time
, SHIFT_SETTOZERO
);
355 packet_list_queue_draw();
360 time_shift_adjtime(capture_file
*cf
, guint packet1_num
, const gchar
*time1_text
, guint packet2_num
, const gchar
*time2_text
)
362 nstime_t nt1
, nt2
, ot1
, ot2
, nt3
;
363 nstime_t dnt
, dot
, d3t
;
364 frame_data
*fd
, *packet1fd
, *packet2fd
;
366 const gchar
*err_str
;
368 if (!cf
|| !time1_text
|| !time2_text
)
369 return "Nothing to work with.";
371 if (packet1_num
< 1 || packet1_num
> cf
->count
|| packet2_num
< 1 || packet2_num
> cf
->count
)
372 return "Packet out of range.";
375 * The following time format is allowed:
376 * [YYYY-MM-DD] hh:mm:ss(.decimals)?
378 * Since Wireshark doesn't support regular expressions (please prove me
379 * wrong :-) we will have to figure it out ourselves in the
382 * 1. YYYY-MM-DD hh:mm:ss.decimals
383 * 2. hh:mm:ss.decimals
388 * Get a copy of the real time (abs_ts - shift_offset) do we can find out the
389 * difference between the specified time and the original packet
391 if ((packet1fd
= frame_data_sequence_find(cf
->frames
, packet1_num
)) == NULL
)
392 return "No frames found.";
393 nstime_copy(&ot1
, &(packet1fd
->abs_ts
));
394 nstime_subtract(&ot1
, &(packet1fd
->shift_offset
));
396 if ((err_str
= time_string_to_nstime(time1_text
, &ot1
, &nt1
)) != NULL
)
400 * Get a copy of the real time (abs_ts - shift_offset) do we can find out the
401 * difference between the specified time and the original packet
403 if ((packet2fd
= frame_data_sequence_find(cf
->frames
, packet2_num
)) == NULL
)
404 return "No frames found.";
405 nstime_copy(&ot2
, &(packet2fd
->abs_ts
));
406 nstime_subtract(&ot2
, &(packet2fd
->shift_offset
));
408 if ((err_str
= time_string_to_nstime(time2_text
, &ot2
, &nt2
)) != NULL
)
411 nstime_copy(&dot
, &ot2
);
412 nstime_subtract(&dot
, &ot1
);
414 nstime_copy(&dnt
, &nt2
);
415 nstime_subtract(&dnt
, &nt1
);
417 /* Up to here nothing is changed */
418 if (!frame_data_sequence_find(cf
->frames
, 1))
419 return "No frames found."; /* Shouldn't happen */
421 for (i
= 1; i
<= cf
->count
; i
++) {
422 if ((fd
= frame_data_sequence_find(cf
->frames
, i
)) == NULL
)
423 continue; /* Shouldn't happen */
425 /* Set everything back to the original time */
426 nstime_subtract(&(fd
->abs_ts
), &(fd
->shift_offset
));
427 nstime_set_zero(&(fd
->shift_offset
));
429 /* Add the difference to each packet */
430 calcNT3(&ot1
, &(fd
->abs_ts
), &nt1
, &nt3
, &dot
, &dnt
);
432 nstime_copy(&d3t
, &nt3
);
433 nstime_subtract(&d3t
, &(fd
->abs_ts
));
435 modify_time_perform(fd
, SHIFT_POS
, &d3t
, SHIFT_SETTOZERO
);
438 packet_list_queue_draw();
443 time_shift_undo(capture_file
*cf
)
450 return "Nothing to work with.";
452 nulltime
.secs
= nulltime
.nsecs
= 0;
454 if (!frame_data_sequence_find(cf
->frames
, 1))
455 return "No frames found."; /* Shouldn't happen */
457 for (i
= 1; i
<= cf
->count
; i
++) {
458 if ((fd
= frame_data_sequence_find(cf
->frames
, i
)) == NULL
)
459 continue; /* Shouldn't happen */
460 modify_time_perform(fd
, SHIFT_NEG
, &nulltime
, SHIFT_SETTOZERO
);
462 packet_list_queue_draw();
472 * indent-tabs-mode: nil
475 * ex: set shiftwidth=4 tabstop=8 expandtab:
476 * :indentSize=4:tabSize=8:noTabs=true: