Skip to content

Commit

Permalink
Network debugger (#391)
Browse files Browse the repository at this point in the history
Add Network debugger

Call runInGuiThread with async=true to avoid deadlocks
  • Loading branch information
zenden2k authored Jan 12, 2025
1 parent bdd035c commit d1ae0af
Show file tree
Hide file tree
Showing 32 changed files with 1,310 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Data/Scripts/directory.nut
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function _Replace(str, pattern, replace_with) {
function UploadFile(FileName, options) {
local task = options.getTask().getFileTask();
local newFilename = task.getDisplayName();
local directory = ServerParams.getParam("directory");
local directory = ServerParams.getParam("directory") + "/";
local convertUncPath = 0;
try {
convertUncPath = ServerParams.getParam("convertUncPath").tointeger();
Expand Down
291 changes: 291 additions & 0 deletions Source/3rdpart/SplitterBar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
#if !defined(AFX_SPLITTER_H__20030708_C845_A999_1D3A_0080AD509054__INCLUDED_)
#define AFX_SPLITTER_H__20030708_C845_A999_1D3A_0080AD509054__INCLUDED_

#pragma once

/////////////////////////////////////////////////////////////////////////////
// CSplitterBar - Splitter control (not a container)
//
// Written by Bjarke Viksoe ([email protected])
// Copyright (c) 2003 Bjarke Viksoe.
//
// This code may be used in compiled form in any way you desire. This
// source file may be redistributed by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage to you or your
// computer whatsoever. It's free, so don't hassle me about it.
//
// Beware of bugs.
//

#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif

#ifndef __ATLAPP_H__
#error This control requires atlapp.h to be included first
#endif

#ifndef __ATLCTRLS_H__
#error This control requires atlctrls.h to be included first
#endif


template< class T, bool t_bVertical = true, class TBase = CWindow, class TWinTraits = CControlWinTraits >
class ATL_NO_VTABLE CSplitterBarImpl :
public CWindowImpl< T, TBase, TWinTraits >
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())

typedef CSplitterBarImpl<T, t_bVertical, TBase, TWinTraits> thisClass;

CWindow m_wndTop;
CWindow m_wndBottom;
BOOL m_bFullDrag;
SIZE m_szGutter;
inline static HCURSOR s_hCursor = NULL;
RECT m_rcSplitterPos;
int m_xySplitterPos;
SIZE m_szLimits;

// Operations

BOOL SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd==NULL);
ATLASSERT(::IsWindow(hWnd));
BOOL bRet = CWindowImpl< T, TBase, TWinTraits >::SubclassWindow(hWnd);
if( bRet ) _Init();
return bRet;
}

void SetSplitterPanes(HWND hWndTop, HWND hWndBottom)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(::IsWindow(hWndTop));
ATLASSERT(::IsWindow(hWndBottom));
m_wndTop = hWndTop;
m_wndBottom = hWndBottom;
RECT rcTop;
RECT rcBottom;
m_wndTop.GetWindowRect(&rcTop);
m_wndBottom.GetWindowRect(&rcBottom);
RECT rcSplitter = { 0 };
if( t_bVertical ) ::SetRect(&rcSplitter, rcTop.right, rcTop.top, rcBottom.left, rcBottom.bottom);
else ::SetRect(&rcSplitter, rcTop.left, rcTop.bottom, rcTop.right, rcBottom.top);
::MapWindowPoints(NULL, GetParent(), (LPPOINT) &rcSplitter, 2);
MoveWindow(&rcSplitter);
}
void SetGutterSize(int cxTop, int cxBottom)
{
m_szGutter.cx = cxTop;
m_szGutter.cy = cxBottom:
}
void SetSplitterSize(int cx)
{
ATLASSERT(::IsWindow(m_hWnd));
ResizeClient(t_bVertical ? cx : -1, t_bVertical ? -1 : cx);
T* pT = static_cast<T*>(this);
pT->UpdateSplitterLayout();
}

void UpdateSplitterLayout()
{
ATLASSERT(::IsWindow(m_hWnd));
RECT rcClient;
RECT rcTop;
RECT rcBottom;
GetWindowRect(&rcClient);
m_wndTop.GetWindowRect(&rcTop);
m_wndBottom.GetWindowRect(&rcBottom);
if( t_bVertical ) {
rcTop.right = rcClient.left;
rcBottom.left = rcClient.right;
}
else {
rcTop.bottom = rcClient.top;
rcBottom.top = rcClient.bottom;
}
::MapWindowPoints(NULL, GetParent(), (LPPOINT) &rcTop, 2);
::MapWindowPoints(NULL, GetParent(), (LPPOINT) &rcBottom, 2);
m_wndTop.SetWindowPos(NULL, &rcTop, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
m_wndBottom.SetWindowPos(NULL, &rcBottom, SWP_NOACTIVATE | SWP_NOZORDER);
::UpdateWindow(GetParent());
}

// Implementation

void _Init()
{
ATLASSERT(::IsWindow(m_hWnd));

if( s_hCursor == NULL ) {
::EnterCriticalSection(&_Module.m_csStaticDataInit);
if( s_hCursor == NULL ) s_hCursor = ::LoadCursor(NULL, t_bVertical ? IDC_SIZEWE : IDC_SIZENS);
::LeaveCriticalSection(&_Module.m_csStaticDataInit);
}

// HACK: If subclassed as label, we need mouse notifications!
ModifyStyle(0, SS_NOTIFY);

::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &m_bFullDrag, 0);

m_szGutter.cx = 14;
m_szGutter.cy = 14;
}

void _DrawGhostBar()
{
if( m_bFullDrag ) return;
RECT rect;
GetClientRect(&rect);
// Invert the brush pattern (looks just like frame window sizing)
T* pT = static_cast<T*>(this);
CWindowDC dc(pT->m_hWnd);
CBrush brush = CDCHandle::GetHalftoneBrush();
if( !brush.IsNull() ) {
CBrushHandle brushOld = dc.SelectBrush(brush);
dc.PatBlt(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, PATINVERT);
dc.SelectBrush(brushOld);
}
}

// Message map and handlers

BEGIN_MSG_MAP( thisClass )
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
END_MSG_MAP()

LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
_Init();
return lRes;
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
CPaintDC dc(pT->m_hWnd);
RECT rcClient;
GetClientRect(&rcClient);
if( (GetStyle() & SS_TYPEMASK) == SS_OWNERDRAW ) {
DRAWITEMSTRUCT dis = { 0 };
dis.CtlID = GetDlgCtrlID();
dis.CtlType = ODT_STATIC;
dis.itemAction = ODA_DRAWENTIRE;
dis.hwndItem = m_hWnd;
dis.hDC = dc;
dis.itemID = 0;
dis.itemState = 0;
if( GetCapture() == m_hWnd ) dis.itemState |= ODS_SELECTED;
dis.rcItem = rcClient;
::SendMessage(GetParent(), WM_DRAWITEM, (WPARAM) dis.CtlID, (LPARAM) &dis);
}
else
{
dc.FillRect(&rcClient, ::GetSysColorBrush(COLOR_3DFACE));
}
return 0;
}
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
if( (HWND) wParam == pT->m_hWnd && LOWORD(lParam) == HTCLIENT ) return 1;
bHandled = FALSE;
return 0;
}
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
if( (wParam & MK_LBUTTON) != 0 && ::GetCapture() == pT->m_hWnd ) {
lParam = ::GetMessagePos();
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
int xyNewSplitPos = t_bVertical ? xPos : yPos;
int cxySplitter = t_bVertical ? (m_rcSplitterPos.right - m_rcSplitterPos.left) : (m_rcSplitterPos.bottom - m_rcSplitterPos.top);
xyNewSplitPos = std::max<int>(xyNewSplitPos, m_szLimits.cx);
xyNewSplitPos = std::min<int>(xyNewSplitPos, m_szLimits.cy - cxySplitter);
if( m_xySplitterPos != xyNewSplitPos ) {
_DrawGhostBar();
int iDiff = xyNewSplitPos - m_xySplitterPos;
RECT rcClient = m_rcSplitterPos;
::OffsetRect(&rcClient, t_bVertical ? iDiff : 0, t_bVertical ? 0 : iDiff);
::MapWindowPoints(NULL, GetParent(), (LPPOINT) &rcClient, 2);
Invalidate();
SetWindowPos(HWND_TOP, &rcClient, SWP_NOACTIVATE);
Invalidate();
if( m_bFullDrag ) pT->UpdateSplitterLayout();
_DrawGhostBar();
}
}
::SetCursor(s_hCursor);
bHandled = FALSE;
return 1;
}
LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetCapture();
::SetCursor(s_hCursor);
_DrawGhostBar();
lParam = ::GetMessagePos();
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
GetWindowRect(&m_rcSplitterPos);
m_xySplitterPos = t_bVertical ? xPos : yPos;
RECT rcTop;
RECT rcBottom;
m_wndTop.GetWindowRect(&rcTop);
m_wndBottom.GetWindowRect(&rcBottom);
if( t_bVertical ) {
m_szLimits.cx = rcTop.left + m_szGutter.cx;
m_szLimits.cy = rcBottom.right - m_szGutter.cy;
}
else {
m_szLimits.cx = rcTop.top + m_szGutter.cx;
m_szLimits.cy = rcBottom.bottom - m_szGutter.cy;
}
bHandled = FALSE;
return 1;
}
LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
_DrawGhostBar();
if( !m_bFullDrag ) {
T* pT = static_cast<T*>(this);
pT->UpdateSplitterLayout();
::UpdateWindow(GetParent());
}
::ReleaseCapture();
bHandled = FALSE;
return 1;
}
};

//template< class T, bool t_bVertical, class TBase, class TWinTraits > HCURSOR CSplitterBarImpl< T, t_bVertical>::s_hCursor = NULL;

class CVertSplitterCtrl : public CSplitterBarImpl<CVertSplitterCtrl, true>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_VertSplitterBar"), GetWndClassName())
};

class CHorSplitterCtrl : public CSplitterBarImpl<CHorSplitterCtrl, false>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_HorSplitterBar"), GetWndClassName())
};


#endif // !defined(AFX_SPLITTER_H__20030708_C845_A999_1D3A_0080AD509054__INCLUDED_)

61 changes: 61 additions & 0 deletions Source/Core/3rdpart/Hexdump.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef HEXDUMP_HPP
#define HEXDUMP_HPP

#include <cctype>
#include <iomanip>
#include <ostream>

template <unsigned RowSize, bool ShowAscii>
struct CustomHexdump
{
CustomHexdump(const void* data, unsigned length) :
mData(static_cast<const unsigned char*>(data)), mLength(length) { }
const unsigned char* mData;
const unsigned mLength;
};

template <unsigned RowSize, bool ShowAscii>
std::ostream& operator<<(std::ostream& out, const CustomHexdump<RowSize, ShowAscii>& dump)
{
out.fill('0');
for (int i = 0; i < dump.mLength; i += RowSize)
{
out << "0x" << std::setw(6) << std::hex << i << ": ";
for (int j = 0; j < RowSize; ++j)
{
if (i + j < dump.mLength)
{
out << std::hex << std::setw(2) << static_cast<int>(dump.mData[i + j]) << " ";
}
else
{
out << " ";
}
}

out << " ";
if (ShowAscii)
{
for (int j = 0; j < RowSize; ++j)
{
if (i + j < dump.mLength)
{
if (std::isprint(dump.mData[i + j]))
{
out << static_cast<char>(dump.mData[i + j]);
}
else
{
out << ".";
}
}
}
}
out << /* std::endl*/ "\r\n";
}
return out;
}

typedef CustomHexdump<16, true> Hexdump;

#endif // HEXDUMP_HPP
2 changes: 2 additions & 0 deletions Source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

set(SRC_LIST Network/NetworkClient.cpp
Network/NetworkClientFactory.cpp
Network/NetworkDebugger.cpp
Upload/DefaultUploadEngine.cpp
Upload/FileUploadTask.cpp
Upload/ScriptUploadEngine.cpp
Expand Down Expand Up @@ -105,6 +106,7 @@ set(SRC_LIST Network/NetworkClient.cpp

set(HEADER_LIST Network/NetworkClient.h
Network/NetworkClientFactory.h
Network/NetworkDebugger.h
Upload/DefaultUploadEngine.h
Upload/FileUploadTask.h
Upload/ScriptUploadEngine.h
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/CoreFunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
#ifdef _WIN32
#include "DefaultProxyProvider.h"
#endif
#include "Core/Network/NetworkDebugger.h"

namespace CoreFunctions {

void ConfigureProxy(INetworkClient* nm)
{
auto debugger = ServiceLocator::instance()->networkDebugger();
nm->setDebugger(debugger);
BasicSettings& Settings = *ServiceLocator::instance()->basicSettings();
#ifdef _WIN32
if (Settings.ConnectionSettings.UseProxy == ConnectionSettingsStruct::kSystemProxy) {
Expand Down
Loading

0 comments on commit d1ae0af

Please sign in to comment.