nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
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 */