nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* time_shift.c |
2 | * Routines for "Time Shift" window |
||
3 | * Submitted by Edwin Groothuis <wireshark@mavetju.org> |
||
4 | * |
||
5 | * Wireshark - Network traffic analyzer |
||
6 | * By Gerald Combs <gerald@wireshark.org> |
||
7 | * Copyright 1998 Gerald Combs |
||
8 | * |
||
9 | * This program is free software; you can redistribute it and/or |
||
10 | * modify it under the terms of the GNU General Public License |
||
11 | * as published by the Free Software Foundation; either version 2 |
||
12 | * of the License, or (at your option) any later version. |
||
13 | * |
||
14 | * This program is distributed in the hope that it will be useful, |
||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
17 | * GNU General Public License for more details. |
||
18 | * |
||
19 | * You should have received a copy of the GNU General Public License |
||
20 | * along with this program; if not, write to the Free Software |
||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
||
22 | */ |
||
23 | |||
24 | #include "config.h" |
||
25 | |||
26 | #include <stdio.h> |
||
27 | #include <string.h> |
||
28 | #include <math.h> |
||
29 | |||
30 | |||
31 | #include "time_shift.h" |
||
32 | |||
33 | #include "ui/ui_util.h" |
||
34 | |||
35 | #ifndef HAVE_FLOORL |
||
36 | #define floorl(x) floor((double)x) |
||
37 | #endif |
||
38 | |||
39 | #define SHIFT_POS 0 |
||
40 | #define SHIFT_NEG 1 |
||
41 | #define SHIFT_SETTOZERO 1 |
||
42 | #define SHIFT_KEEPOFFSET 0 |
||
43 | |||
44 | #define CHECK_YEARS(Y) \ |
||
45 | if (*Y < 1970) { \ |
||
46 | return "Years must be larger than 1970"; \ |
||
47 | } |
||
48 | #define CHECK_MONTHS(M) \ |
||
49 | if (*M < 1 || *M > 12) { \ |
||
50 | return "Months must be between [1..12]"; \ |
||
51 | } |
||
52 | #define CHECK_DAYS(D) \ |
||
53 | if (*D < 1 || *D > 31) { \ |
||
54 | return "Days must be between [1..31]"; \ |
||
55 | } |
||
56 | #define CHECK_HOURS(h) \ |
||
57 | if (*h < 0 || *h > 23) { \ |
||
58 | return "Hours must be between [0..23]"; \ |
||
59 | } |
||
60 | #define CHECK_HOUR(h) \ |
||
61 | if (*h < 0) { \ |
||
62 | return "Negative hours. Have you specified more than " \ |
||
63 | "one minus character?"; \ |
||
64 | } |
||
65 | #define CHECK_MINUTE(m) \ |
||
66 | if (*m < 0 || *m > 59) { \ |
||
67 | return "Minutes must be between [0..59]"; \ |
||
68 | } |
||
69 | #define CHECK_SECOND(s) \ |
||
70 | if (*s < 0 || *s > 59) { \ |
||
71 | return "Seconds must be between [0..59]"; \ |
||
72 | } |
||
73 | |||
74 | static void |
||
75 | modify_time_perform(frame_data *fd, int neg, nstime_t *offset, int settozero) |
||
76 | { |
||
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)); |
||
81 | } |
||
82 | |||
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); |
||
89 | } else { |
||
90 | fprintf(stderr, "Modify_time_perform: neg = %d?\n", neg); |
||
91 | } |
||
92 | } |
||
93 | |||
94 | /* |
||
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) |
||
103 | * |
||
104 | * All the things you come up when waiting for the train to come... |
||
105 | */ |
||
106 | static void |
||
107 | calcNT3(nstime_t *OT1, nstime_t *OT3, nstime_t *NT1, nstime_t *NT3, |
||
108 | nstime_t *deltaOT, nstime_t *deltaNT) |
||
109 | { |
||
110 | long double fnt, fot, f, secs, nsecs; |
||
111 | |||
112 | fnt = (long double)deltaNT->secs + (deltaNT->nsecs / 1000000000.0L); |
||
113 | fot = (long double)deltaOT->secs + (deltaOT->nsecs / 1000000000.0L); |
||
114 | f = fnt / fot; |
||
115 | |||
116 | nstime_copy(NT3, OT3); |
||
117 | nstime_subtract(NT3, OT1); |
||
118 | |||
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) { |
||
123 | secs += 1; |
||
124 | nsecs -= 1000000000L; |
||
125 | } |
||
126 | while (nsecs < 0) { |
||
127 | secs -= 1; |
||
128 | nsecs += 1000000000L; |
||
129 | } |
||
130 | NT3->secs = (time_t)secs; |
||
131 | NT3->nsecs = (int)nsecs; |
||
132 | nstime_add(NT3, NT1); |
||
133 | } |
||
134 | |||
135 | const gchar * |
||
136 | time_string_parse(const gchar *time_text, int *year, int *month, int *day, gboolean *negative, int *hour, int *minute, long double *second) { |
||
137 | const gchar *pts = time_text; |
||
138 | |||
139 | if (!time_text || !hour || !minute || !second) |
||
140 | return "Unable to convert time."; |
||
141 | |||
142 | /* strip whitespace */ |
||
143 | while (g_ascii_isspace(pts[0])) |
||
144 | ++pts; |
||
145 | |||
146 | if (year && month && day) { |
||
147 | /* |
||
148 | * The following time format is allowed: |
||
149 | * [YYYY-MM-DD] hh:mm:ss(.decimals)? |
||
150 | * |
||
151 | * Since Wireshark doesn't support regular expressions (please prove me |
||
152 | * wrong :-) we will have to figure it out ourselves in the |
||
153 | * following order: |
||
154 | * |
||
155 | * 1. YYYY-MM-DD hh:mm:ss.decimals |
||
156 | * 2. hh:mm:ss.decimals |
||
157 | * |
||
158 | */ |
||
159 | |||
160 | /* check for empty string */ |
||
161 | if (pts[0] == '\0') |
||
162 | return "Time is empty."; |
||
163 | |||
164 | if (sscanf(pts, "%d-%d-%d %d:%d:%Lf", year, month, day, hour, minute, second) == 6) { |
||
165 | /* printf("%%d-%%d-%%d %%d:%%d:%%f\n"); */ |
||
166 | CHECK_YEARS(year); |
||
167 | CHECK_MONTHS(month); |
||
168 | CHECK_DAYS(day); |
||
169 | CHECK_HOURS(hour); |
||
170 | CHECK_MINUTE(minute); |
||
171 | CHECK_SECOND(second); |
||
172 | } else if (sscanf(pts, "%d:%d:%Lf", hour, minute, second) == 3) { |
||
173 | /* printf("%%d:%%d:%%f\n"); */ |
||
174 | *year = *month = *day = 0; |
||
175 | CHECK_HOUR(hour); |
||
176 | CHECK_MINUTE(minute); |
||
177 | CHECK_SECOND(second); |
||
178 | } else { |
||
179 | return "Could not parse the time. Expected [YYYY-MM-DD] " |
||
180 | "hh:mm:ss[.dec]."; |
||
181 | } |
||
182 | } else { |
||
183 | if (!negative) |
||
184 | return "Unable to convert time."; |
||
185 | |||
186 | /* |
||
187 | * The following offset types are allowed: |
||
188 | * -?((hh:)mm:)ss(.decimals)? |
||
189 | * |
||
190 | * Since Wireshark doesn't support regular expressions (please prove me |
||
191 | * wrong :-) we will have to figure it out ourselves in the |
||
192 | * following order: |
||
193 | * |
||
194 | * 1. hh:mm:ss.decimals |
||
195 | * 2. mm:ss.decimals |
||
196 | * 3. ss.decimals |
||
197 | * |
||
198 | */ |
||
199 | |||
200 | /* check for minus sign */ |
||
201 | *negative = FALSE; |
||
202 | if (pts[0] == '-') { |
||
203 | *negative = TRUE; |
||
204 | pts++; |
||
205 | } |
||
206 | |||
207 | /* check for empty string */ |
||
208 | if (pts[0] == '\0') |
||
209 | return "Time is empty."; |
||
210 | |||
211 | if (sscanf(pts, "%d:%d:%Lf", hour, minute, second) == 3) { |
||
212 | /* printf("%%d:%%d:%%d.%%d\n"); */ |
||
213 | CHECK_HOUR(hour); |
||
214 | CHECK_MINUTE(minute); |
||
215 | CHECK_SECOND(second); |
||
216 | } else if (sscanf(pts, "%d:%Lf", minute, second) == 2) { |
||
217 | /* printf("%%d:%%d.%%d\n"); */ |
||
218 | CHECK_MINUTE(minute); |
||
219 | CHECK_SECOND(second); |
||
220 | *hour = 0; |
||
221 | } else if (sscanf(pts, "%Lf", second) == 1) { |
||
222 | /* printf("%%d.%%d\n"); */ |
||
223 | CHECK_SECOND(second); |
||
224 | *hour = *minute = 0; |
||
225 | } else { |
||
226 | return "Could not parse the time: Expected [[hh:]mm:]ss.[dec]."; |
||
227 | } |
||
228 | } |
||
229 | |||
230 | return NULL; |
||
231 | } |
||
232 | |||
233 | static const gchar * |
||
234 | time_string_to_nstime(const gchar *time_text, nstime_t *packettime, nstime_t *nstime) |
||
235 | { |
||
236 | int h, m, Y, M, D; |
||
237 | long double f; |
||
238 | struct tm tm, *tmptm; |
||
239 | time_t tt; |
||
240 | const gchar *err_str; |
||
241 | |||
242 | if ((err_str = time_string_parse(time_text, &Y, &M, &D, NULL, &h, &m, &f)) != NULL) |
||
243 | return err_str; |
||
244 | |||
245 | /* Convert the time entered in an epoch offset */ |
||
246 | tmptm = localtime(&(packettime->secs)); |
||
247 | if (tmptm) { |
||
248 | tm = *tmptm; |
||
249 | } else { |
||
250 | memset (&tm, 0, sizeof (tm)); |
||
251 | } |
||
252 | if (Y != 0) { |
||
253 | tm.tm_year = Y - 1900; |
||
254 | tm.tm_mon = M - 1; |
||
255 | tm.tm_mday = D; |
||
256 | } |
||
257 | tm.tm_hour = h; |
||
258 | tm.tm_min = m; |
||
259 | tm.tm_sec = (int)floorl(f); |
||
260 | tt = mktime(&tm); |
||
261 | if (tt == -1) { |
||
262 | return "Mktime went wrong. Is the time valid?"; |
||
263 | } |
||
264 | |||
265 | nstime->secs = tt; |
||
266 | f -= tm.tm_sec; |
||
267 | nstime->nsecs = (int)(f * 1000000000); |
||
268 | |||
269 | return NULL; |
||
270 | } |
||
271 | |||
272 | const gchar * |
||
273 | time_shift_all(capture_file *cf, const gchar *offset_text) |
||
274 | { |
||
275 | nstime_t offset; |
||
276 | long double offset_float = 0; |
||
277 | guint32 i; |
||
278 | frame_data *fd; |
||
279 | gboolean neg; |
||
280 | int h, m; |
||
281 | long double f; |
||
282 | const gchar *err_str; |
||
283 | |||
284 | if (!cf || !offset_text) |
||
285 | return "Nothing to work with."; |
||
286 | |||
287 | if ((err_str = time_string_parse(offset_text, NULL, NULL, NULL, &neg, &h, &m, &f)) != NULL) |
||
288 | return err_str; |
||
289 | |||
290 | offset_float = h * 3600 + m * 60 + f; |
||
291 | |||
292 | if (offset_float == 0) |
||
293 | return "Offset is zero."; |
||
294 | |||
295 | nstime_set_zero(&offset); |
||
296 | offset.secs = (time_t)floorl(offset_float); |
||
297 | offset_float -= offset.secs; |
||
298 | offset.nsecs = (int)(offset_float * 1000000000); |
||
299 | |||
300 | if (!frame_data_sequence_find(cf->frames, 1)) |
||
301 | return "No frames found."; /* Shouldn't happen */ |
||
302 | |||
303 | for (i = 1; i <= cf->count; i++) { |
||
304 | if ((fd = frame_data_sequence_find(cf->frames, i)) == NULL) |
||
305 | continue; /* Shouldn't happen */ |
||
306 | modify_time_perform(fd, neg ? SHIFT_NEG : SHIFT_POS, &offset, SHIFT_KEEPOFFSET); |
||
307 | } |
||
308 | packet_list_queue_draw(); |
||
309 | |||
310 | return NULL; |
||
311 | } |
||
312 | |||
313 | const gchar * |
||
314 | time_shift_settime(capture_file *cf, guint packet_num, const gchar *time_text) |
||
315 | { |
||
316 | nstime_t set_time, diff_time, packet_time; |
||
317 | frame_data *fd, *packetfd; |
||
318 | guint32 i; |
||
319 | const gchar *err_str; |
||
320 | |||
321 | if (!cf || !time_text) |
||
322 | return "Nothing to work with."; |
||
323 | |||
324 | if (packet_num < 1 || packet_num > cf->count) |
||
325 | return "Packet out of range."; |
||
326 | |||
327 | /* |
||
328 | * Get a copy of the real time (abs_ts - shift_offset) do we can find out the |
||
329 | * difference between the specified time and the original packet |
||
330 | */ |
||
331 | if ((packetfd = frame_data_sequence_find(cf->frames, packet_num)) == NULL) |
||
332 | return "No packets found."; |
||
333 | nstime_delta(&packet_time, &(packetfd->abs_ts), &(packetfd->shift_offset)); |
||
334 | |||
335 | if ((err_str = time_string_to_nstime(time_text, &packet_time, &set_time)) != NULL) |
||
336 | return err_str; |
||
337 | |||
338 | /* Calculate difference between packet time and requested time */ |
||
339 | nstime_delta(&diff_time, &set_time, &packet_time); |
||
340 | |||
341 | /* Up to here nothing is changed */ |
||
342 | |||
343 | if (!frame_data_sequence_find(cf->frames, 1)) |
||
344 | return "No frames found."; /* Shouldn't happen */ |
||
345 | |||
346 | /* Set everything back to the original time */ |
||
347 | for (i = 1; i <= cf->count; i++) { |
||
348 | if ((fd = frame_data_sequence_find(cf->frames, i)) == NULL) |
||
349 | continue; /* Shouldn't happen */ |
||
350 | modify_time_perform(fd, SHIFT_POS, &diff_time, SHIFT_SETTOZERO); |
||
351 | } |
||
352 | |||
353 | packet_list_queue_draw(); |
||
354 | return NULL; |
||
355 | } |
||
356 | |||
357 | const gchar * |
||
358 | time_shift_adjtime(capture_file *cf, guint packet1_num, const gchar *time1_text, guint packet2_num, const gchar *time2_text) |
||
359 | { |
||
360 | nstime_t nt1, nt2, ot1, ot2, nt3; |
||
361 | nstime_t dnt, dot, d3t; |
||
362 | frame_data *fd, *packet1fd, *packet2fd; |
||
363 | guint32 i; |
||
364 | const gchar *err_str; |
||
365 | |||
366 | if (!cf || !time1_text || !time2_text) |
||
367 | return "Nothing to work with."; |
||
368 | |||
369 | if (packet1_num < 1 || packet1_num > cf->count || packet2_num < 1 || packet2_num > cf->count) |
||
370 | return "Packet out of range."; |
||
371 | |||
372 | /* |
||
373 | * The following time format is allowed: |
||
374 | * [YYYY-MM-DD] hh:mm:ss(.decimals)? |
||
375 | * |
||
376 | * Since Wireshark doesn't support regular expressions (please prove me |
||
377 | * wrong :-) we will have to figure it out ourselves in the |
||
378 | * following order: |
||
379 | * |
||
380 | * 1. YYYY-MM-DD hh:mm:ss.decimals |
||
381 | * 2. hh:mm:ss.decimals |
||
382 | * |
||
383 | */ |
||
384 | |||
385 | /* |
||
386 | * Get a copy of the real time (abs_ts - shift_offset) do we can find out the |
||
387 | * difference between the specified time and the original packet |
||
388 | */ |
||
389 | if ((packet1fd = frame_data_sequence_find(cf->frames, packet1_num)) == NULL) |
||
390 | return "No frames found."; |
||
391 | nstime_copy(&ot1, &(packet1fd->abs_ts)); |
||
392 | nstime_subtract(&ot1, &(packet1fd->shift_offset)); |
||
393 | |||
394 | if ((err_str = time_string_to_nstime(time1_text, &ot1, &nt1)) != NULL) |
||
395 | return err_str; |
||
396 | |||
397 | /* |
||
398 | * Get a copy of the real time (abs_ts - shift_offset) do we can find out the |
||
399 | * difference between the specified time and the original packet |
||
400 | */ |
||
401 | if ((packet2fd = frame_data_sequence_find(cf->frames, packet2_num)) == NULL) |
||
402 | return "No frames found."; |
||
403 | nstime_copy(&ot2, &(packet2fd->abs_ts)); |
||
404 | nstime_subtract(&ot2, &(packet2fd->shift_offset)); |
||
405 | |||
406 | if ((err_str = time_string_to_nstime(time2_text, &ot2, &nt2)) != NULL) |
||
407 | return err_str; |
||
408 | |||
409 | nstime_copy(&dot, &ot2); |
||
410 | nstime_subtract(&dot, &ot1); |
||
411 | |||
412 | nstime_copy(&dnt, &nt2); |
||
413 | nstime_subtract(&dnt, &nt1); |
||
414 | |||
415 | /* Up to here nothing is changed */ |
||
416 | if (!frame_data_sequence_find(cf->frames, 1)) |
||
417 | return "No frames found."; /* Shouldn't happen */ |
||
418 | |||
419 | for (i = 1; i <= cf->count; i++) { |
||
420 | if ((fd = frame_data_sequence_find(cf->frames, i)) == NULL) |
||
421 | continue; /* Shouldn't happen */ |
||
422 | |||
423 | /* Set everything back to the original time */ |
||
424 | nstime_subtract(&(fd->abs_ts), &(fd->shift_offset)); |
||
425 | nstime_set_zero(&(fd->shift_offset)); |
||
426 | |||
427 | /* Add the difference to each packet */ |
||
428 | calcNT3(&ot1, &(fd->abs_ts), &nt1, &nt3, &dot, &dnt); |
||
429 | |||
430 | nstime_copy(&d3t, &nt3); |
||
431 | nstime_subtract(&d3t, &(fd->abs_ts)); |
||
432 | |||
433 | modify_time_perform(fd, SHIFT_POS, &d3t, SHIFT_SETTOZERO); |
||
434 | } |
||
435 | |||
436 | packet_list_queue_draw(); |
||
437 | return NULL; |
||
438 | } |
||
439 | |||
440 | const gchar * |
||
441 | time_shift_undo(capture_file *cf) |
||
442 | { |
||
443 | guint32 i; |
||
444 | frame_data *fd; |
||
445 | nstime_t nulltime; |
||
446 | |||
447 | if (!cf) |
||
448 | return "Nothing to work with."; |
||
449 | |||
450 | nulltime.secs = nulltime.nsecs = 0; |
||
451 | |||
452 | if (!frame_data_sequence_find(cf->frames, 1)) |
||
453 | return "No frames found."; /* Shouldn't happen */ |
||
454 | |||
455 | for (i = 1; i <= cf->count; i++) { |
||
456 | if ((fd = frame_data_sequence_find(cf->frames, i)) == NULL) |
||
457 | continue; /* Shouldn't happen */ |
||
458 | modify_time_perform(fd, SHIFT_NEG, &nulltime, SHIFT_SETTOZERO); |
||
459 | } |
||
460 | packet_list_queue_draw(); |
||
461 | return NULL; |
||
462 | } |
||
463 | |||
464 | /* |
||
465 | * Editor modelines |
||
466 | * |
||
467 | * Local Variables: |
||
468 | * c-basic-offset: 4 |
||
469 | * tab-width: 8 |
||
470 | * indent-tabs-mode: nil |
||
471 | * End: |
||
472 | * |
||
473 | * ex: set shiftwidth=4 tabstop=8 expandtab: |
||
474 | * :indentSize=4:tabSize=8:noTabs=true: |
||
475 | */ |