1 /* capture_file.cpp 2 * 3 * Wireshark - Network traffic analyzer 4 * By Gerald Combs <gerald@wireshark.org> 5 * Copyright 1998 Gerald Combs 6 * 7 * SPDX-License-Identifier: GPL-2.0-or-later 8 */ 9 10 #include "capture_file.h" 11 12 /* 13 * @file Capture file class 14 * 15 * Wraps the capture_file struct, cfile global, and callbacks. 16 */ 17 18 #include "globals.h" 19 capture_file cfile; 20 21 #include "file.h" 22 23 #include "epan/epan_dissect.h" 24 25 #include "ui/capture.h" 26 27 #include <QFileInfo> 28 #include <QTimer> 29 #include <QDebug> 30 31 CaptureEvent::CaptureEvent(Context ctx, EventType evt) : 32 _ctx(ctx), 33 _evt(evt), 34 _session(Q_NULLPTR) 35 { 36 } 37 38 CaptureEvent::CaptureEvent(Context ctx, EventType evt, QString file) : 39 _ctx(ctx), 40 _evt(evt), 41 _filePath(file), 42 _session(Q_NULLPTR) 43 { 44 } 45 46 CaptureEvent::CaptureEvent(Context ctx, EventType evt, capture_session * session) : 47 _ctx(ctx), 48 _evt(evt), 49 _session(session) 50 { 51 } 52 53 CaptureEvent::CaptureEvent(const CaptureEvent &ce) : 54 _ctx(ce._ctx), 55 _evt(ce._evt), 56 _filePath(ce._filePath), 57 _session(ce._session) 58 { 59 } 60 61 CaptureEvent::Context CaptureEvent::captureContext() const 62 { return _ctx; } 63 64 CaptureEvent::EventType CaptureEvent::eventType() const 65 { return _evt; } 66 67 QString CaptureEvent::filePath() const 68 { return _filePath; } 69 70 capture_session * CaptureEvent::capSession() const 71 { return _session; } 72 73 // To do: 74 // - Add getters and (if needed) setters: 75 // - Full filename 76 // - Capture state (stopped, prepared, running). 77 // - Call common_create_progress_dlg. This would let us manage the stop 78 // flag here as well as emit progress signals. 79 80 QString CaptureFile::no_capture_file_ = QObject::tr("[no capture file]"); 81 82 CaptureFile::CaptureFile(QObject *parent, capture_file *cap_file) : 83 QObject(parent), 84 cap_file_(cap_file), 85 file_state_(QString()) 86 { 87 #ifdef HAVE_LIBPCAP 88 capture_callback_add(captureCallback, (gpointer) this); 89 #endif 90 cf_callback_add(captureFileCallback, (gpointer) this); 91 } 92 93 CaptureFile::~CaptureFile() 94 { 95 cf_callback_remove(captureFileCallback, this); 96 } 97 98 bool CaptureFile::isValid() const 99 { 100 if (cap_file_ && cap_file_->state != FILE_CLOSED) { // XXX FILE_READ_IN_PROGRESS as well? 101 return true; 102 } 103 return false; 104 } 105 106 int CaptureFile::currentRow() 107 { 108 if (isValid()) 109 return cap_file_->current_row; 110 return -1; 111 } 112 113 const QString CaptureFile::filePath() 114 { 115 QString path; 116 117 if (isValid()) { 118 // 119 // Sadly, some UN*Xes don't necessarily use UTF-8 120 // for their file names, so we have to map the 121 // file path to UTF-8. If that fails, we're somewhat 122 // stuck. 123 // 124 char *utf8_filename = g_filename_to_utf8(cap_file_->filename, 125 -1, 126 NULL, 127 NULL, 128 NULL); 129 if (utf8_filename) { 130 path = QString::fromUtf8(utf8_filename); 131 g_free(utf8_filename); 132 } else { 133 // So what the heck else can we do here? 134 path = QString(); 135 } 136 } else { 137 path = QString(); 138 } 139 return path; 140 } 141 142 const QString CaptureFile::fileName() 143 { 144 QString path, name; 145 146 path = filePath(); 147 if (!path.isEmpty()) { 148 QFileInfo cfi(path); 149 name = cfi.fileName(); 150 } else { 151 name = QString(); 152 } 153 154 return name; 155 } 156 157 const QString CaptureFile::fileBaseName() 158 { 159 QString baseName; 160 161 if (isValid()) { 162 char *basename = cf_get_basename(cap_file_); 163 baseName = basename; 164 g_free(basename); 165 } else { 166 baseName = QString(); 167 } 168 return baseName; 169 } 170 171 const QString CaptureFile::fileDisplayName() 172 { 173 QString displayName; 174 175 if (isValid()) { 176 char *display_name = cf_get_display_name(cap_file_); 177 displayName = display_name; 178 g_free(display_name); 179 } else { 180 displayName = QString(); 181 } 182 return displayName; 183 } 184 185 const QString CaptureFile::fileTitle() 186 { 187 QString title; 188 189 if (isValid()) { 190 title = fileDisplayName() + file_state_; 191 } else { 192 title = no_capture_file_; 193 } 194 return title; 195 } 196 197 struct _packet_info *CaptureFile::packetInfo() 198 { 199 if (capFile() && capFile()->edt) { 200 return &(capFile()->edt->pi); 201 } 202 return NULL; 203 } 204 205 int CaptureFile::timestampPrecision() 206 { 207 if (capFile() && capFile()->provider.wth) { 208 return wtap_file_tsprec(capFile()->provider.wth); 209 } 210 return WTAP_TSPREC_UNKNOWN; 211 } 212 213 void CaptureFile::retapPackets() 214 { 215 if (cap_file_) { 216 cf_retap_packets(cap_file_); 217 } 218 } 219 220 void CaptureFile::delayedRetapPackets() 221 { 222 QTimer::singleShot(0, this, SLOT(retapPackets())); 223 } 224 225 void CaptureFile::reload() 226 { 227 if (cap_file_ && cap_file_->state == FILE_READ_DONE) { 228 cf_reload(cap_file_); 229 } 230 } 231 232 void CaptureFile::stopLoading() 233 { 234 setCaptureStopFlag(true); 235 } 236 237 capture_file *CaptureFile::globalCapFile() 238 { 239 return &cfile; 240 } 241 242 gpointer CaptureFile::window() 243 { 244 if (cap_file_) return cap_file_->window; 245 return NULL; 246 } 247 248 void CaptureFile::setCaptureStopFlag(bool stop_flag) 249 { 250 if (cap_file_) cap_file_->stop_flag = stop_flag; 251 } 252 253 void CaptureFile::captureFileCallback(gint event, gpointer data, gpointer user_data) 254 { 255 CaptureFile *capture_file = static_cast<CaptureFile *>(user_data); 256 if (!capture_file) return; 257 258 capture_file->captureFileEvent(event, data); 259 } 260 261 #ifdef HAVE_LIBPCAP 262 void CaptureFile::captureCallback(gint event, capture_session *cap_session, gpointer user_data) 263 { 264 CaptureFile *capture_file = static_cast<CaptureFile *>(user_data); 265 if (!capture_file) return; 266 267 capture_file->captureSessionEvent(event, cap_session); 268 } 269 #endif 270 271 void CaptureFile::captureFileEvent(int event, gpointer data) 272 { 273 switch(event) { 274 case(cf_cb_file_opened): 275 cap_file_ = (capture_file *) data; 276 emit captureEvent(CaptureEvent(CaptureEvent::File, CaptureEvent::Opened)); 277 break; 278 case(cf_cb_file_closing): 279 file_state_ = tr(" [closing]"); 280 emit captureEvent(CaptureEvent(CaptureEvent::File, CaptureEvent::Closing)); 281 break; 282 case(cf_cb_file_closed): 283 file_state_ = tr(" [closed]"); 284 emit captureEvent(CaptureEvent(CaptureEvent::File, CaptureEvent::Closed)); 285 cap_file_ = NULL; 286 file_state_ = QString(); 287 break; 288 case(cf_cb_file_read_started): 289 emit captureEvent(CaptureEvent(CaptureEvent::File, CaptureEvent::Started)); 290 break; 291 case(cf_cb_file_read_finished): 292 emit captureEvent(CaptureEvent(CaptureEvent::File, CaptureEvent::Finished)); 293 break; 294 case(cf_cb_file_reload_started): 295 emit captureEvent(CaptureEvent(CaptureEvent::Reload, CaptureEvent::Started)); 296 break; 297 case(cf_cb_file_reload_finished): 298 emit captureEvent(CaptureEvent(CaptureEvent::Reload, CaptureEvent::Finished)); 299 break; 300 case(cf_cb_file_rescan_started): 301 emit captureEvent(CaptureEvent(CaptureEvent::Rescan, CaptureEvent::Started)); 302 break; 303 case(cf_cb_file_rescan_finished): 304 emit captureEvent(CaptureEvent(CaptureEvent::Rescan, CaptureEvent::Finished)); 305 break; 306 case(cf_cb_file_retap_started): 307 emit captureEvent(CaptureEvent(CaptureEvent::Retap, CaptureEvent::Started)); 308 break; 309 case(cf_cb_file_retap_finished): 310 /* Flush any pending tapped packet before emitting captureFileRetapFinished() */ 311 emit captureEvent(CaptureEvent(CaptureEvent::Retap, CaptureEvent::Finished)); 312 emit captureEvent(CaptureEvent(CaptureEvent::Retap, CaptureEvent::Flushed)); 313 break; 314 case(cf_cb_file_merge_started): 315 emit captureEvent(CaptureEvent(CaptureEvent::Merge, CaptureEvent::Started)); 316 break; 317 case(cf_cb_file_merge_finished): 318 emit captureEvent(CaptureEvent(CaptureEvent::Merge, CaptureEvent::Finished)); 319 break; 320 321 case(cf_cb_file_fast_save_finished): 322 // gtk/main.c calls main_cf_cb_file_rescan_finished. Should we do 323 // the equivalent? 324 break; 325 326 case(cf_cb_file_save_started): 327 { 328 emit captureEvent(CaptureEvent(CaptureEvent::Save, CaptureEvent::Started, QString((const char *)data))); 329 break; 330 } 331 case(cf_cb_file_save_finished): 332 emit captureEvent(CaptureEvent(CaptureEvent::Save, CaptureEvent::Finished)); 333 break; 334 case(cf_cb_file_save_failed): 335 emit captureEvent(CaptureEvent(CaptureEvent::Save, CaptureEvent::Failed)); 336 break; 337 case(cf_cb_file_save_stopped): 338 emit captureEvent(CaptureEvent(CaptureEvent::Save, CaptureEvent::Stopped)); 339 break; 340 341 default: 342 qWarning() << "CaptureFile::captureFileCallback: event " << event << " unknown"; 343 Q_ASSERT(false); 344 break; 345 } 346 } 347 348 #ifdef HAVE_LIBPCAP 349 void CaptureFile::captureSessionEvent(int event, capture_session *cap_session) 350 { 351 switch(event) { 352 case(capture_cb_capture_prepared): 353 emit captureEvent(CaptureEvent(CaptureEvent::Capture, CaptureEvent::Prepared, cap_session)); 354 cap_file_ = cap_session->cf; 355 break; 356 case(capture_cb_capture_update_started): 357 emit captureEvent(CaptureEvent(CaptureEvent::Update, CaptureEvent::Started, cap_session)); 358 break; 359 case(capture_cb_capture_update_continue): 360 emit captureEvent(CaptureEvent(CaptureEvent::Update, CaptureEvent::Continued, cap_session)); 361 break; 362 case(capture_cb_capture_update_finished): 363 emit captureEvent(CaptureEvent(CaptureEvent::Update, CaptureEvent::Finished, cap_session)); 364 break; 365 case(capture_cb_capture_fixed_started): 366 emit captureEvent(CaptureEvent(CaptureEvent::Fixed, CaptureEvent::Started, cap_session)); 367 break; 368 case(capture_cb_capture_fixed_continue): 369 emit captureEvent(CaptureEvent(CaptureEvent::Fixed, CaptureEvent::Continued, cap_session)); 370 break; 371 case(capture_cb_capture_fixed_finished): 372 emit captureEvent(CaptureEvent(CaptureEvent::Fixed, CaptureEvent::Finished, cap_session)); 373 break; 374 case(capture_cb_capture_stopping): 375 /* Beware: this state won't be called, if the capture child 376 * closes the capturing on it's own! */ 377 emit captureEvent(CaptureEvent(CaptureEvent::Capture, CaptureEvent::Stopping, cap_session)); 378 break; 379 case(capture_cb_capture_failed): 380 emit captureEvent(CaptureEvent(CaptureEvent::Capture, CaptureEvent::Failed, cap_session)); 381 break; 382 default: 383 qWarning() << "main_capture_callback: event " << event << " unknown"; 384 } 385 } 386 #endif // HAVE_LIBPCAP 387