Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
dist
VCamdroid
VCamdroid
*.log
*.dmp
8 changes: 0 additions & 8 deletions windows/app.log

This file was deleted.

49 changes: 29 additions & 20 deletions windows/src/application.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "application.h"
#include "crashhandler.h"

#include "gui/imgadjdlg.h"
#include "gui/streamconfigdlg.h"
Expand All @@ -21,6 +22,8 @@ Application::Application()

bool Application::OnInit()
{
CrashHandler::Install();

if (!wxApp::OnInit())
return false;

Expand Down Expand Up @@ -162,36 +165,42 @@ void Application::BindEventListeners()

void Application::OnDeviceConnected(DeviceDescriptor& descriptor) const
{
mainWindow->GetTaskbarIcon()->ShowBalloon("New stream available", "Streaming device " + descriptor.name() + " available!", 10, wxICON_INFORMATION);
rtspManager->AddDescriptor(descriptor);
UpdateAvailableDevices();
mainWindow->GetEventHandler()->CallAfter([this, descriptor]() mutable {
mainWindow->GetTaskbarIcon()->ShowBalloon("New stream available", "Streaming device " + descriptor.name() + " available!", 10, wxICON_INFORMATION);
rtspManager->AddDescriptor(descriptor);
UpdateAvailableDevices();
});
}

void Application::OnDeviceDisconnected(DeviceDescriptor& descriptor) const
{
mainWindow->GetTaskbarIcon()->ShowBalloon("Stream ended", "Streaming device " + descriptor.name() + " disconnected!", 10, wxICON_INFORMATION);

// Check if the device that just disconnected was the active streaming device
// If it was reset the canvas to blank
int streamingDeviceId = rtspManager->GetStreamingDevice();
if (streamingDeviceId >= 0)
{
const auto& streamingDescriptor = rtspManager->GetDescriptors()[streamingDeviceId];
if (streamingDescriptor == descriptor)
mainWindow->GetCanvas()->Clear();
}
mainWindow->GetEventHandler()->CallAfter([this, descriptor]() mutable {
mainWindow->GetTaskbarIcon()->ShowBalloon("Stream ended", "Streaming device " + descriptor.name() + " disconnected!", 10, wxICON_INFORMATION);

// Remove from manager
rtspManager->RemoveDescriptor(descriptor);
// Check if the device that just disconnected was the active streaming device
// If it was reset the canvas to blank
int streamingDeviceId = rtspManager->GetStreamingDevice();
if (streamingDeviceId >= 0)
{
const auto& streamingDescriptor = rtspManager->GetDescriptors()[streamingDeviceId];
if (streamingDescriptor == descriptor)
mainWindow->GetCanvas()->Clear();
}

// Remove from manager
rtspManager->RemoveDescriptor(descriptor);

// Update UI list
UpdateAvailableDevices();
// Update UI list
UpdateAvailableDevices();
});
}

void Application::OnDeviceErrorReported(DeviceDescriptor& descriptor, const Connection::ErrorReport& error) const
{
auto icon = error.severity == Connection::ErrorReport::SEVERITY_WARNING ? wxICON_WARNING : wxICON_ERROR;
mainWindow->GetTaskbarIcon()->ShowBalloon(descriptor.name() + " " + error.error, error.description, 1000, icon);
mainWindow->GetEventHandler()->CallAfter([this, descriptor, error]() {
auto icon = error.severity == Connection::ErrorReport::SEVERITY_WARNING ? wxICON_WARNING : wxICON_ERROR;
mainWindow->GetTaskbarIcon()->ShowBalloon(descriptor.name() + " " + error.error, error.description, 1000, icon);
});
}

void Application::UpdateAvailableDevices() const
Expand Down
81 changes: 81 additions & 0 deletions windows/src/crashhandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#pragma once

#include <windows.h>
#include <dbghelp.h>
#include <ctime>
#include <exception>
#include <string>

#pragma comment(lib, "dbghelp.lib")

#include "logger.h"

extern Logger logger;

namespace CrashHandler
{
static std::string TimestampedDumpPath()
{
time_t now = time(nullptr);
char buf[64];
struct tm tm_info;
localtime_s(&tm_info, &now);
strftime(buf, sizeof(buf), "vcamdroid_crash_%Y%m%d_%H%M%S.dmp", &tm_info);
return buf;
}

static void WriteDump(EXCEPTION_POINTERS* exceptionInfo = nullptr)
{
std::string path = TimestampedDumpPath();

HANDLE hFile = CreateFileA(path.c_str(), GENERIC_WRITE, 0, nullptr,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);

if (hFile == INVALID_HANDLE_VALUE)
{
logger << "[CRASH] Failed to create dump file: " << path << "\n";
return;
}

MINIDUMP_EXCEPTION_INFORMATION info{};
MINIDUMP_EXCEPTION_INFORMATION* pInfo = nullptr;
if (exceptionInfo)
{
info.ThreadId = GetCurrentThreadId();
info.ExceptionPointers = exceptionInfo;
info.ClientPointers = TRUE;
pInfo = &info;
}

MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile,
MiniDumpWithThreadInfo, pInfo, nullptr, nullptr);
CloseHandle(hFile);

logger << "[CRASH] Minidump written: " << path << "\n";
}

static LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo)
{
DWORD code = exceptionInfo->ExceptionRecord->ExceptionCode;
auto addr = reinterpret_cast<uintptr_t>(exceptionInfo->ExceptionRecord->ExceptionAddress);

logger << "[CRASH] Unhandled exception - code: 0x" << std::hex << code
<< " address: 0x" << addr << std::dec << "\n";

WriteDump(exceptionInfo);

return EXCEPTION_EXECUTE_HANDLER;
}

static void TerminateHandler()
{
logger << "[CRASH] std::terminate() called - unhandled C++ exception\n";
WriteDump();
}

static void Install()
{
SetUnhandledExceptionFilter(ExceptionFilter);
std::set_terminate(TerminateHandler);
}
}
14 changes: 10 additions & 4 deletions windows/src/net/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,17 @@ void Server::TCPDoAccept()
// We need to read this here because the connection listener
// needs all the data sent by the client (trough GetConnectedDevicesInfo)
// otherwise the connection would need to be passed to the connection
std::array<char, 512> buffer;
size_t size = socket.read_some(asio::buffer(buffer, 512));

std::vector<uint8_t> buffer;
std::array<uint8_t, 1024> chunk;
asio::error_code readEc;
size_t n;
do {
n = socket.read_some(asio::buffer(chunk), readEc);
if (n > 0) buffer.insert(buffer.end(), chunk.begin(), chunk.begin() + n);
} while (n == chunk.size() && !readEc);

// auto ipaddress = socket.remote_endpoint().address().to_string();
auto descriptor = Serializer::DeserializeDeviceDescriptor((const uint8_t*)buffer.data(), size);
auto descriptor = Serializer::DeserializeDeviceDescriptor(buffer.data(), buffer.size());

auto conn = std::make_shared<Connection>(
std::move(socket),
Expand Down