source: lib/format_helper.c @ d5a27e8

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since d5a27e8 was d5a27e8, checked in by Perry Lorier <perry@…>, 14 years ago

Update the copyright information
Fix libpcap issue
Remove all swig/python builds

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#include "config.h"
32#include <sys/types.h>
33#include <fcntl.h> /* for O_LARGEFILE */
34#include <math.h>
35#include "libtrace.h"
36#include "libtrace_int.h"
37
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
41#include <errno.h>
42#include "format_helper.h"
43
44#include <assert.h>
45#include <stdarg.h>
46
47#ifdef WIN32
48#  include <io.h>
49#  include <share.h>
50#  include <sys/timeb.h>
51
52struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
53    struct libtrace_eventobj_t event = {0,0,0.0,0};
54
55    trace_set_err(trace,TRACE_ERR_OPTION_UNAVAIL, "trace_event() is not "
56            "supported on devices under windows in this version");
57
58    event.type = TRACE_EVENT_TERMINATE;
59    return event;
60}
61#else
62#  include <sys/ioctl.h>
63
64struct libtrace_eventobj_t trace_event_device(struct libtrace_t *trace, 
65                                        struct libtrace_packet_t *packet) {
66        struct libtrace_eventobj_t event = {0,0,0.0,0};
67        int data;
68
69        assert(trace != NULL);
70        assert(packet != NULL);
71       
72        if (trace->format->get_fd) {
73                event.fd = trace->format->get_fd(trace);
74        } else {
75                event.fd = 0;
76        }
77        if (ioctl(event.fd,FIONREAD,&data)==-1) {
78                event.type = TRACE_EVENT_TERMINATE;
79                return event;
80        } 
81               
82        if (data>0) {
83                event.size = trace_read_packet(trace,packet);
84                event.type = TRACE_EVENT_PACKET;
85                return event;
86        }
87        event.type= TRACE_EVENT_IOWAIT;
88        return event;
89}
90#endif
91
92struct libtrace_eventobj_t trace_event_trace(struct libtrace_t *trace, struct libtrace_packet_t *packet) {
93        struct libtrace_eventobj_t event = {0,0,0.0,0};
94        double ts;
95        double now;
96#ifdef WIN32
97        struct __timeb64 tstruct;
98#else
99        struct timeval stv;
100#endif
101
102        if (!trace->event.packet) {
103                trace->event.packet = trace_create_packet();
104                trace->event.psize=
105                        trace_read_packet(trace,trace->event.packet);
106                if (trace->event.psize<1) {
107                        /* return here, the test for
108                         * event.size will sort out the error
109                         */
110                        if (trace_is_err(trace)) {
111                                trace_perror(trace, "read packet");
112                        }
113                        event.type = TRACE_EVENT_TERMINATE;
114                        return event;
115                }
116        }
117
118        ts=trace_get_seconds(trace->event.packet);
119
120        /* Get the adjusted current time */
121#ifdef WIN32
122        _ftime64(&tstruct);
123        now = tstruct.time + 
124                ((double)tstruct.millitm / 1000.0);
125#else
126        gettimeofday(&stv, NULL);
127        now = stv.tv_sec + 
128                ((double)stv.tv_usec / 1000000.0);
129#endif
130
131        if (fabs(trace->event.tdelta)<1e-9) {
132                /* adjust for trace delta */
133                now -= trace->event.tdelta; 
134
135                /* if the trace timestamp is still in the
136                 * future, return a SLEEP event,
137                 * otherwise fire the packet
138                 */
139                if (ts > now) {
140                        event.seconds = ts - 
141                                trace->event.trace_last_ts;
142                        event.type = TRACE_EVENT_SLEEP;
143                        return event;
144                }
145        } else {
146                /* work out the difference between the
147                 * start of trace replay, and the first
148                 * packet in the trace
149                 */
150                trace->event.tdelta = now - ts;
151        }
152
153        /* This is the first packet, so just fire away. */
154        /* TODO: finalise packet */
155       
156        /* XXX: Could we do this more efficiently? */
157        /* We do a lot of freeing and creating of packet buffers with this
158         * method, but at least it works unlike what was here previously */
159        if (packet->buf_control == TRACE_CTRL_PACKET) {
160                free(packet->buffer);
161        }
162               
163        packet->type = trace->event.packet->type;
164        packet->trace = trace->event.packet->trace;
165        packet->header = trace->event.packet->header;
166        packet->payload = trace->event.packet->payload;
167       
168        packet->buffer = trace->event.packet->buffer;
169        packet->buf_control = trace->event.packet->buf_control;
170
171        trace->event.packet->buf_control = TRACE_CTRL_EXTERNAL;
172       
173        trace_destroy_packet(trace->event.packet);
174        trace->event.packet = NULL;
175
176        event.type = TRACE_EVENT_PACKET;
177
178        trace->event.trace_last_ts = ts;
179
180        return event;
181}
182
183/* Catch undefined O_LARGEFILE on *BSD etc */
184#ifndef O_LARGEFILE
185#  define O_LARGEFILE 0
186#endif
187
188/* Catching O_BINARY on all sane OS's */
189#ifndef O_BINARY
190#  define O_BINARY 0
191#endif
192
193/* open a file or stdin using gzip compression if necessary (and supported)
194 * @internal
195 */
196libtrace_io_t *trace_open_file(libtrace_t *trace)
197{
198        int fd;
199        libtrace_io_t *ret;
200
201
202        if (strcmp(trace->uridata,"-")==0) {
203                ret=libtrace_io_fdopen(fileno(stdin),"rb");
204                return ret;
205        }
206
207        /* We open the file with open(2), so we can provide O_LARGEFILE
208         * as zlib doesn't always do it itself
209         */
210        fd=open(trace->uridata,O_LARGEFILE|O_RDONLY|O_BINARY);
211        if (fd==-1) {
212                trace_set_err(trace,errno,"Unable to open %s",trace->uridata);
213                return 0;
214        }
215        ret=libtrace_io_fdopen(fd,"rb");
216        return ret;
217}
218
219/* Create a file or write to stdout using compression if requested
220 * @internal
221 */
222libtrace_io_t *trace_open_file_out(libtrace_out_t *trace,int level, int fileflag)
223{
224        int fd;
225        libtrace_io_t *ret;
226        char filemode[4]; /* wb9\0 */
227        assert(level<10);
228        assert(level>=0);
229#ifdef HAVE_LIBZ
230        snprintf(filemode,sizeof(filemode),"wb%d",level);
231#else
232        snprintf(filemode,sizeof(filemode),"wb");
233#endif
234
235        if (strcmp(trace->uridata,"-")==0) {
236                ret=libtrace_io_fdopen(fileno(stdout),filemode);
237                return ret;
238        }
239
240        /* We open the file with open(2), so we can provide O_LARGEFILE
241         * as zlib doesn't always do it itself
242         */
243        fd=open(trace->uridata,fileflag|O_LARGEFILE|O_BINARY,0666);
244        if (fd==-1) {
245                trace_set_err_out(trace,
246                                errno,"Unable to open %s",trace->uridata);
247                return 0;
248        }
249        ret=libtrace_io_fdopen(fd,filemode);
250        if (!ret) {
251                printf("%s\n",filemode);
252                trace_set_err_out(trace,
253                                TRACE_ERR_INIT_FAILED,"gz out of memory");
254        }
255        return ret;
256}
257
258
259/** Update the libtrace error
260 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
261 * @param msg a plaintext error message
262 * @internal
263 */
264void trace_set_err(libtrace_t *trace,int errcode,const char *msg,...)
265{
266        char buf[256];
267        va_list va;
268        va_start(va,msg);
269        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
270        trace->err.err_num=errcode;
271        if (errcode>0) {
272                vsnprintf(buf,sizeof(buf),msg,va);
273                snprintf(trace->err.problem,sizeof(trace->err.problem),
274                                "%s: %s",buf,strerror(errcode));
275        } else {
276                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
277                                msg,va);
278        }
279        va_end(va);
280}
281
282/** Update the libtrace for output traces error
283 * @param errcode either an Econstant from libc, or a LIBTRACE_ERROR
284 * @param msg a plaintext error message
285 * @internal
286 */
287void trace_set_err_out(libtrace_out_t *trace,int errcode,const char *msg,...)
288{
289        char buf[256];
290        va_list va;
291        va_start(va,msg);
292        assert(errcode != 0 && "An error occurred, but it is unknown what it is");
293        trace->err.err_num=errcode;
294        if (errcode>0) {
295                vsnprintf(buf,sizeof(buf),msg,va);
296                snprintf(trace->err.problem,sizeof(trace->err.problem),
297                                "%s: %s",buf,strerror(errno));
298        } else {
299                vsnprintf(trace->err.problem,sizeof(trace->err.problem),
300                                msg,va);
301        }
302        va_end(va);
303}
304
305uint64_t byteswap64(uint64_t num)
306{
307        return (byteswap32((num&0xFFFFFFFF00000000ULL)>>32))
308              |((uint64_t)byteswap32(num&0x00000000FFFFFFFFULL)<<32);
309}
310
311uint32_t byteswap32(uint32_t num)
312{
313        return ((num&0x000000FFU)<<24)
314                | ((num&0x0000FF00U)<<8)
315                | ((num&0x00FF0000U)>>8)
316                | ((num&0xFF000000U)>>24);
317}
318
319uint16_t byteswap16(uint16_t num)
320{
321        return ((num<<8)&0xFF00)|((num>>8)&0x00FF);
322}
323
Note: See TracBrowser for help on using the repository browser.