mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 09:18:09 +00:00
symbol server abstraction layer; http layer; fix to 'prefer_disasm' rule when no disassembly tabs are open; small fixes / cleanup
This commit is contained in:
+1
-1
@@ -49,7 +49,7 @@ commands =
|
|||||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
// .f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg debug telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
// .f1 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
|
|
||||||
//- rjf: [raddbg wsl]
|
//- rjf: [raddbg wsl]
|
||||||
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
// .f1 = { .win = "wsl ./build.sh raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||||
|
|||||||
@@ -623,10 +623,10 @@ date_time_from_unix_time(U64 unix_time)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
//~ rjf: Wrapped Ring Buffer Reads/Writes
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size)
|
wrapped_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size)
|
||||||
{
|
{
|
||||||
Assert(src_data_size <= ring_size);
|
Assert(src_data_size <= ring_size);
|
||||||
{
|
{
|
||||||
@@ -643,7 +643,7 @@ ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size)
|
wrapped_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size)
|
||||||
{
|
{
|
||||||
Assert(read_size <= ring_size);
|
Assert(read_size <= ring_size);
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1107,12 +1107,12 @@ internal void sleep_ms(U32 ms);
|
|||||||
internal Guid make_guid(void);
|
internal Guid make_guid(void);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Non-Fancy Ring Buffer Reads/Writes
|
//~ rjf: Wrapped Ring Buffer Reads/Writes
|
||||||
|
|
||||||
internal U64 ring_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size);
|
internal U64 wrapped_write(U8 *ring_base, U64 ring_size, U64 ring_pos, void *src_data, U64 src_data_size);
|
||||||
internal U64 ring_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size);
|
internal U64 wrapped_read(U8 *ring_base, U64 ring_size, U64 ring_pos, void *dst_data, U64 read_size);
|
||||||
#define ring_write_struct(ring_base, ring_size, ring_pos, ptr) ring_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
#define wrapped_write_struct(ring_base, ring_size, ring_pos, ptr) wrapped_write((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||||
#define ring_read_struct(ring_base, ring_size, ring_pos, ptr) ring_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
#define wrapped_read_struct(ring_base, ring_size, ring_pos, ptr) wrapped_read((ring_base), (ring_size), (ring_pos), (ptr), sizeof(*(ptr)))
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Sorts
|
//~ rjf: Sorts
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: initialize all included layers
|
//- rjf: initialize all included layers
|
||||||
|
#if defined(HTTP_H) && !defined(HTTP_INIT_MANUAL)
|
||||||
|
http_init();
|
||||||
|
#endif
|
||||||
|
#if defined(SYMBOL_SERVER_H) && !defined(SMSV_INIT_MANUAL)
|
||||||
|
smsv_init();
|
||||||
|
#endif
|
||||||
#if defined(ARTIFACT_CACHE_H) && !defined(AC_INIT_MANUAL)
|
#if defined(ARTIFACT_CACHE_H) && !defined(AC_INIT_MANUAL)
|
||||||
ac_init();
|
ac_init();
|
||||||
#endif
|
#endif
|
||||||
@@ -215,6 +221,9 @@ async_thread_entry_point(void *params)
|
|||||||
#if defined(FILE_STREAM_H)
|
#if defined(FILE_STREAM_H)
|
||||||
fs_async_tick();
|
fs_async_tick();
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HTTP_H)
|
||||||
|
http_async_tick();
|
||||||
|
#endif
|
||||||
#if defined(DBG_INFO_H)
|
#if defined(DBG_INFO_H)
|
||||||
di_async_tick();
|
di_async_tick();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ write_data_list_to_file_path(String8 path, String8List list)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off);
|
U64 bytes_to_copy = Min(write_buffer_available_size, n->string.size - n_off);
|
||||||
write_buffer_write_pos += ring_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy);
|
write_buffer_write_pos += wrapped_write(write_buffer, write_buffer_size, write_buffer_write_pos, n->string.str + n_off, bytes_to_copy);
|
||||||
n_off += bytes_to_copy;
|
n_off += bytes_to_copy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "base_hash.c"
|
#include "base_hash.c"
|
||||||
#include "base_system.c"
|
#include "base_system.c"
|
||||||
#include "base_threads.c"
|
#include "base_threads.c"
|
||||||
|
#include "base_ring.c"
|
||||||
#include "base_thread_context.c"
|
#include "base_thread_context.c"
|
||||||
#include "base_files.c"
|
#include "base_files.c"
|
||||||
#include "base_shared_memory.c"
|
#include "base_shared_memory.c"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "base_hash.h"
|
#include "base_hash.h"
|
||||||
#include "base_system.h"
|
#include "base_system.h"
|
||||||
#include "base_threads.h"
|
#include "base_threads.h"
|
||||||
|
#include "base_ring.h"
|
||||||
#include "base_thread_context.h"
|
#include "base_thread_context.h"
|
||||||
#include "base_files.h"
|
#include "base_files.h"
|
||||||
#include "base_shared_memory.h"
|
#include "base_shared_memory.h"
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ struct ProcessInfo
|
|||||||
String8 user_program_config_data_path;
|
String8 user_program_config_data_path;
|
||||||
String8 user_program_cache_data_path;
|
String8 user_program_cache_data_path;
|
||||||
String8 user_program_logs_data_path;
|
String8 user_program_logs_data_path;
|
||||||
String8 symbol_cache_path;
|
|
||||||
String8List module_load_paths;
|
String8List module_load_paths;
|
||||||
String8List environment;
|
String8List environment;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Ring Functions
|
||||||
|
|
||||||
|
internal Ring *
|
||||||
|
make_ring(Arena *arena, U64 size)
|
||||||
|
{
|
||||||
|
Ring *ring = push_array(arena, Ring, 1);
|
||||||
|
ring->size = size;
|
||||||
|
ring->base = push_array(arena, U8, ring->size);
|
||||||
|
return ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
ring_try_write(Ring *ring, U64 size, void *ptr)
|
||||||
|
{
|
||||||
|
U64 bytes_unconsumed = (ring->write_pos - ring->read_pos);
|
||||||
|
U64 bytes_available = ring->size - bytes_unconsumed;
|
||||||
|
B32 result = 0;
|
||||||
|
if(bytes_available >= size)
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
ring->write_pos += wrapped_write(ring->base, ring->size, ring->write_pos, ptr, size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
ring_try_read(Ring *ring, U64 size, void *ptr)
|
||||||
|
{
|
||||||
|
U64 bytes_unconsumed = (ring->write_pos - ring->read_pos);
|
||||||
|
B32 result = 0;
|
||||||
|
if(bytes_unconsumed >= size)
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
ring->read_pos += wrapped_read(ring->base, ring->size, ring->read_pos, ptr, size);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Guarded Ring Functions
|
||||||
|
|
||||||
|
internal GuardedRing *
|
||||||
|
guarded_ring_alloc(Arena *arena, U64 size)
|
||||||
|
{
|
||||||
|
GuardedRing *gr = push_array(arena, GuardedRing, 1);
|
||||||
|
gr->ring = make_ring(arena, size);
|
||||||
|
gr->mutex = mutex_alloc();
|
||||||
|
gr->cv = cond_var_alloc();
|
||||||
|
return gr;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
guarded_ring_release(GuardedRing *ring)
|
||||||
|
{
|
||||||
|
mutex_release(ring->mutex);
|
||||||
|
cond_var_release(ring->cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RingGuard
|
||||||
|
guarded_ring_open(GuardedRing *ring)
|
||||||
|
{
|
||||||
|
RingGuard guard = {ring};
|
||||||
|
mutex_take(ring->mutex);
|
||||||
|
return guard;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
guarded_ring_close(RingGuard *guard)
|
||||||
|
{
|
||||||
|
mutex_drop(guard->r->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
guarded_ring_try_write(RingGuard *guard, U64 size, void *ptr)
|
||||||
|
{
|
||||||
|
B32 result = ring_try_write(guard->r->ring, size, ptr);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
cond_var_broadcast(guard->r->cv);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
guarded_ring_try_read(RingGuard *guard, U64 size, void *ptr)
|
||||||
|
{
|
||||||
|
B32 result = ring_try_read(guard->r->ring, size, ptr);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
cond_var_broadcast(guard->r->cv);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
guarded_ring_write_or_wait(RingGuard *guard, U64 size, void *ptr, U64 endt_us)
|
||||||
|
{
|
||||||
|
B32 write_good = 0;
|
||||||
|
for(;!write_good;)
|
||||||
|
{
|
||||||
|
write_good = guarded_ring_try_write(guard, size, ptr);
|
||||||
|
if(now_time_us() >= endt_us)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!write_good)
|
||||||
|
{
|
||||||
|
cond_var_wait(guard->r->cv, guard->r->mutex, endt_us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return write_good;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
guarded_ring_read_or_wait(RingGuard *guard, U64 size, void *ptr, U64 endt_us)
|
||||||
|
{
|
||||||
|
B32 read_good = 0;
|
||||||
|
for(;!read_good;)
|
||||||
|
{
|
||||||
|
read_good = guarded_ring_try_read(guard, size, ptr);
|
||||||
|
if(now_time_us() >= endt_us)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!read_good)
|
||||||
|
{
|
||||||
|
cond_var_wait(guard->r->cv, guard->r->mutex, endt_us);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return read_good;
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef BASE_RING_H
|
||||||
|
#define BASE_RING_H
|
||||||
|
|
||||||
|
typedef struct Ring Ring;
|
||||||
|
struct Ring
|
||||||
|
{
|
||||||
|
U8 *base;
|
||||||
|
U64 size;
|
||||||
|
U64 write_pos;
|
||||||
|
U64 read_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct GuardedRing GuardedRing;
|
||||||
|
struct GuardedRing
|
||||||
|
{
|
||||||
|
Ring *ring;
|
||||||
|
Mutex mutex;
|
||||||
|
CondVar cv;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RingGuard RingGuard;
|
||||||
|
struct RingGuard
|
||||||
|
{
|
||||||
|
GuardedRing *r;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Ring Functions
|
||||||
|
|
||||||
|
internal Ring *make_ring(Arena *arena, U64 size);
|
||||||
|
internal B32 ring_try_write(Ring *ring, U64 size, void *ptr);
|
||||||
|
internal B32 ring_try_read(Ring *ring, U64 size, void *ptr);
|
||||||
|
#define ring_try_write_struct(ring, ptr) ring_try_write((ring), sizeof(*(ptr)), (ptr))
|
||||||
|
#define ring_try_read_struct(ring, ptr) ring_try_read((ring), sizeof(*(ptr)), (ptr))
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Guarded Ring Functions
|
||||||
|
|
||||||
|
internal GuardedRing *guarded_ring_alloc(Arena *arena, U64 size);
|
||||||
|
internal void guarded_ring_release(GuardedRing *ring);
|
||||||
|
internal RingGuard guarded_ring_open(GuardedRing *ring);
|
||||||
|
internal void guarded_ring_close(RingGuard *guard);
|
||||||
|
internal B32 guarded_ring_try_write(RingGuard *guard, U64 size, void *ptr);
|
||||||
|
internal B32 guarded_ring_try_read(RingGuard *guard, U64 size, void *ptr);
|
||||||
|
#define guarded_ring_try_write_struct(ring, ptr) guarded_ring_try_write((ring), sizeof(*(ptr)), (ptr))
|
||||||
|
#define guarded_ring_try_read_struct(ring, ptr) guarded_ring_try_read((ring), sizeof(*(ptr)), (ptr))
|
||||||
|
internal B32 guarded_ring_write_or_wait(RingGuard *guard, U64 size, void *ptr, U64 endt_us);
|
||||||
|
internal B32 guarded_ring_read_or_wait(RingGuard *guard, U64 size, void *ptr, U64 endt_us);
|
||||||
|
#define guarded_ring_write_struct_or_wait(ring, ptr, endt_us) guarded_ring_write_or_wait((ring), sizeof(*(ptr)), (ptr), (endt_us))
|
||||||
|
#define guarded_ring_read_struct_or_wait(ring, ptr, endt_us) guarded_ring_read_or_wait((ring), sizeof(*(ptr)), (ptr), (endt_us))
|
||||||
|
#define guarded_ring_write_string_or_wait(ring, string, endt_us) guarded_ring_write_or_wait((ring), (string).size, (string).str, (endt_us))
|
||||||
|
|
||||||
|
#endif // BASE_RING_H
|
||||||
@@ -2144,8 +2144,8 @@ d_u2c_push_msgs(D_MsgList *msgs, U64 endt_us)
|
|||||||
U64 needed_size = sizeof(msgs_srlzed_baked.size) + msgs_srlzed_baked.size;
|
U64 needed_size = sizeof(msgs_srlzed_baked.size) + msgs_srlzed_baked.size;
|
||||||
if(available_size >= needed_size)
|
if(available_size >= needed_size)
|
||||||
{
|
{
|
||||||
d_ctrl_state->u2c_ring_write_pos += ring_write_struct(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_write_pos, &msgs_srlzed_baked.size);
|
d_ctrl_state->u2c_ring_write_pos += wrapped_write_struct(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_write_pos, &msgs_srlzed_baked.size);
|
||||||
d_ctrl_state->u2c_ring_write_pos += ring_write(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_write_pos, msgs_srlzed_baked.str, msgs_srlzed_baked.size);
|
d_ctrl_state->u2c_ring_write_pos += wrapped_write(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_write_pos, msgs_srlzed_baked.str, msgs_srlzed_baked.size);
|
||||||
good = 1;
|
good = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2174,10 +2174,10 @@ d_u2c_pop_msgs(Arena *arena)
|
|||||||
if(unconsumed_size >= sizeof(U64))
|
if(unconsumed_size >= sizeof(U64))
|
||||||
{
|
{
|
||||||
U64 size_to_decode = 0;
|
U64 size_to_decode = 0;
|
||||||
d_ctrl_state->u2c_ring_read_pos += ring_read_struct(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_read_pos, &size_to_decode);
|
d_ctrl_state->u2c_ring_read_pos += wrapped_read_struct(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_read_pos, &size_to_decode);
|
||||||
msgs_srlzed_baked.size = size_to_decode;
|
msgs_srlzed_baked.size = size_to_decode;
|
||||||
msgs_srlzed_baked.str = push_array_no_zero(scratch.arena, U8, msgs_srlzed_baked.size);
|
msgs_srlzed_baked.str = push_array_no_zero(scratch.arena, U8, msgs_srlzed_baked.size);
|
||||||
d_ctrl_state->u2c_ring_read_pos += ring_read(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_read_pos, msgs_srlzed_baked.str, size_to_decode);
|
d_ctrl_state->u2c_ring_read_pos += wrapped_read(d_ctrl_state->u2c_ring_base, d_ctrl_state->u2c_ring_size, d_ctrl_state->u2c_ring_read_pos, msgs_srlzed_baked.str, size_to_decode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cond_var_wait(d_ctrl_state->u2c_ring_cv, d_ctrl_state->u2c_ring_mutex, max_U64);
|
cond_var_wait(d_ctrl_state->u2c_ring_cv, d_ctrl_state->u2c_ring_mutex, max_U64);
|
||||||
@@ -2210,8 +2210,8 @@ d_c2u_push_events(D_EventList *events)
|
|||||||
U64 needed_size = sizeof(event_srlzed.size) + event_srlzed.size;
|
U64 needed_size = sizeof(event_srlzed.size) + event_srlzed.size;
|
||||||
if(available_size >= needed_size)
|
if(available_size >= needed_size)
|
||||||
{
|
{
|
||||||
d_ctrl_state->c2u_ring_write_pos += ring_write_struct(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_write_pos, &event_srlzed.size);
|
d_ctrl_state->c2u_ring_write_pos += wrapped_write_struct(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_write_pos, &event_srlzed.size);
|
||||||
d_ctrl_state->c2u_ring_write_pos += ring_write(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_write_pos, event_srlzed.str, event_srlzed.size);
|
d_ctrl_state->c2u_ring_write_pos += wrapped_write(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_write_pos, event_srlzed.str, event_srlzed.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cond_var_wait(d_ctrl_state->c2u_ring_cv, d_ctrl_state->c2u_ring_mutex, now_time_us()+100);
|
cond_var_wait(d_ctrl_state->c2u_ring_cv, d_ctrl_state->c2u_ring_mutex, now_time_us()+100);
|
||||||
@@ -2238,11 +2238,11 @@ d_c2u_pop_events(Arena *arena)
|
|||||||
if(unconsumed_size >= sizeof(U64))
|
if(unconsumed_size >= sizeof(U64))
|
||||||
{
|
{
|
||||||
U64 size_to_decode = 0;
|
U64 size_to_decode = 0;
|
||||||
d_ctrl_state->c2u_ring_read_pos += ring_read_struct(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_read_pos, &size_to_decode);
|
d_ctrl_state->c2u_ring_read_pos += wrapped_read_struct(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_read_pos, &size_to_decode);
|
||||||
String8 event_srlzed = {0};
|
String8 event_srlzed = {0};
|
||||||
event_srlzed.size = size_to_decode;
|
event_srlzed.size = size_to_decode;
|
||||||
event_srlzed.str = push_array_no_zero(scratch.arena, U8, event_srlzed.size);
|
event_srlzed.str = push_array_no_zero(scratch.arena, U8, event_srlzed.size);
|
||||||
d_ctrl_state->c2u_ring_read_pos += ring_read(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_read_pos, event_srlzed.str, event_srlzed.size);
|
d_ctrl_state->c2u_ring_read_pos += wrapped_read(d_ctrl_state->c2u_ring_base, d_ctrl_state->c2u_ring_size, d_ctrl_state->c2u_ring_read_pos, event_srlzed.str, event_srlzed.size);
|
||||||
D_Event *new_event = d_event_list_push(arena, &events);
|
D_Event *new_event = d_event_list_push(arena, &events);
|
||||||
*new_event = d_event_from_serialized_string(arena, event_srlzed);
|
*new_event = d_event_from_serialized_string(arena, event_srlzed);
|
||||||
}
|
}
|
||||||
@@ -2683,28 +2683,11 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, U64 base_vaddr, DM
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: determine debug info unique identifier
|
//- rjf: no found debug info path -> try to fall back on symbol server
|
||||||
//
|
//
|
||||||
String8 debug_info_unique_identifier = {0};
|
if(initial_debug_info_path.size == 0)
|
||||||
if(module_info->debug_info_path.size != 0)
|
|
||||||
{
|
{
|
||||||
Guid guid = module_info->debug_info_guid;
|
initial_debug_info_path = smsv_local_path_from_key(arena, str8_skip_last_slash(module_info->module_path), str8_skip_last_slash(module_info->debug_info_path), module_info->debug_info_guid, module_info->debug_info_age);
|
||||||
debug_info_unique_identifier = str8f(scratch.arena, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
|
|
||||||
guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7], module_info->debug_info_age);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- rjf: build local server cache debug info path
|
|
||||||
//
|
|
||||||
String8 local_server_cache_debug_info_path = {0};
|
|
||||||
if(debug_info_unique_identifier.size != 0 && module_info->debug_info_path.size != 0)
|
|
||||||
{
|
|
||||||
// TODO(rjf): this is not complete - assuming stripped etc. - just following pattern from ntdll.dll for now
|
|
||||||
String8 symbol_cache_path = get_process_info()->symbol_cache_path;
|
|
||||||
String8 module_name = str8_skip_last_slash(module_info->module_path);
|
|
||||||
String8 dbg_name = str8_skip_last_slash(module_info->debug_info_path);
|
|
||||||
String8 path = str8f(scratch.arena, "%S/%S/%S/stripped/%S", symbol_cache_path, module_name, debug_info_unique_identifier, dbg_name);
|
|
||||||
local_server_cache_debug_info_path = path_normalized_from_string(arena, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -2725,7 +2708,6 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, U64 base_vaddr, DM
|
|||||||
info.unwinder = unwinder;
|
info.unwinder = unwinder;
|
||||||
info.unwind_info = unwind_info_opaque;
|
info.unwind_info = unwind_info_opaque;
|
||||||
info.local_debug_info_path = initial_debug_info_path;
|
info.local_debug_info_path = initial_debug_info_path;
|
||||||
info.debug_info_unique_identifier = debug_info_unique_identifier;
|
|
||||||
info.raddbg_attached_marker_voff = module_info->raddbg_is_attached_marker_voff;
|
info.raddbg_attached_marker_voff = module_info->raddbg_is_attached_marker_voff;
|
||||||
info.raddbg_data = raddbg_data;
|
info.raddbg_data = raddbg_data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,8 +169,6 @@ struct D_ModuleInfo
|
|||||||
UWND_Unwinder unwinder;
|
UWND_Unwinder unwinder;
|
||||||
void *unwind_info;
|
void *unwind_info;
|
||||||
String8 local_debug_info_path;
|
String8 local_debug_info_path;
|
||||||
String8 local_server_cache_debug_info_path;
|
|
||||||
String8 debug_info_unique_identifier;
|
|
||||||
U64 raddbg_attached_marker_voff;
|
U64 raddbg_attached_marker_voff;
|
||||||
String8 raddbg_data;
|
String8 raddbg_data;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Basic Type Functions
|
||||||
|
|
||||||
|
internal HTTP_StatusKind
|
||||||
|
http_status_kind_from_code(HTTP_StatusCode code)
|
||||||
|
{
|
||||||
|
HTTP_StatusKind kind = HTTP_StatusKind_Null;
|
||||||
|
if(0){}
|
||||||
|
else if(HTTP_StatusCode_FirstInformational <= code && code <= HTTP_StatusCode_LastInformational)
|
||||||
|
{
|
||||||
|
kind = HTTP_StatusKind_Informational;
|
||||||
|
}
|
||||||
|
else if(HTTP_StatusCode_FirstSuccessful <= code && code <= HTTP_StatusCode_LastSuccessful)
|
||||||
|
{
|
||||||
|
kind = HTTP_StatusKind_Successful;
|
||||||
|
}
|
||||||
|
else if(HTTP_StatusCode_FirstRedirection <= code && code <= HTTP_StatusCode_LastRedirection)
|
||||||
|
{
|
||||||
|
kind = HTTP_StatusKind_Redirection;
|
||||||
|
}
|
||||||
|
else if(HTTP_StatusCode_FirstClientError <= code && code <= HTTP_StatusCode_LastClientError)
|
||||||
|
{
|
||||||
|
kind = HTTP_StatusKind_ClientError;
|
||||||
|
}
|
||||||
|
else if(HTTP_StatusCode_FirstServerError <= code && code <= HTTP_StatusCode_LastServerError)
|
||||||
|
{
|
||||||
|
kind = HTTP_StatusKind_ServerError;
|
||||||
|
}
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
+170
@@ -0,0 +1,170 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef HTTP_H
|
||||||
|
#define HTTP_H
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Status Codes
|
||||||
|
|
||||||
|
typedef enum HTTP_StatusKind
|
||||||
|
{
|
||||||
|
HTTP_StatusKind_Null,
|
||||||
|
HTTP_StatusKind_Informational,
|
||||||
|
HTTP_StatusKind_Successful,
|
||||||
|
HTTP_StatusKind_Redirection,
|
||||||
|
HTTP_StatusKind_ClientError,
|
||||||
|
HTTP_StatusKind_ServerError,
|
||||||
|
HTTP_StatusKind_COUNT
|
||||||
|
}
|
||||||
|
HTTP_StatusKind;
|
||||||
|
|
||||||
|
typedef U32 HTTP_StatusCode;
|
||||||
|
typedef enum HTTP_StatusCodeEnum
|
||||||
|
{
|
||||||
|
//- rjf: informational messages
|
||||||
|
HTTP_StatusCode_FirstInformational = 100,
|
||||||
|
HTTP_StatusCode_LastInformational = 199,
|
||||||
|
HTTP_StatusCode_Continue = 100,
|
||||||
|
HTTP_StatusCode_SwitchingProtocols = 101,
|
||||||
|
HTTP_StatusCode_Processing = 102,
|
||||||
|
HTTP_StatusCode_EarlyHints = 103,
|
||||||
|
|
||||||
|
//- rjf: successful messages
|
||||||
|
HTTP_StatusCode_FirstSuccessful = 200,
|
||||||
|
HTTP_StatusCode_LastSuccessful = 299,
|
||||||
|
HTTP_StatusCode_OK = 200,
|
||||||
|
HTTP_StatusCode_Created = 201,
|
||||||
|
HTTP_StatusCode_Accepted = 202,
|
||||||
|
HTTP_StatusCode_NonAuthoritativeInformation = 203,
|
||||||
|
HTTP_StatusCode_NoContent = 204,
|
||||||
|
HTTP_StatusCode_ResetContent = 205,
|
||||||
|
HTTP_StatusCode_PartialContent = 206,
|
||||||
|
HTTP_StatusCode_MultiStatus = 207,
|
||||||
|
HTTP_StatusCode_AlreadyReported = 208,
|
||||||
|
HTTP_StatusCode_IMUsed = 226,
|
||||||
|
|
||||||
|
//- rjf: redirection messages
|
||||||
|
HTTP_StatusCode_FirstRedirection = 300,
|
||||||
|
HTTP_StatusCode_LastRedirection = 399,
|
||||||
|
HTTP_StatusCode_MultipleChoices = 300,
|
||||||
|
HTTP_StatusCode_MovedPermanently = 301,
|
||||||
|
HTTP_StatusCode_Found = 302,
|
||||||
|
HTTP_StatusCode_SeeOther = 303,
|
||||||
|
HTTP_StatusCode_NotModified = 304,
|
||||||
|
HTTP_StatusCode_UseProxy = 305,
|
||||||
|
HTTP_StatusCode_TemporaryRedirect = 307,
|
||||||
|
HTTP_StatusCode_PermanentRedirect = 308,
|
||||||
|
|
||||||
|
//- rjf: client error responses
|
||||||
|
HTTP_StatusCode_FirstClientError = 400,
|
||||||
|
HTTP_StatusCode_LastClientError = 499,
|
||||||
|
HTTP_StatusCode_BadRequest = 400,
|
||||||
|
HTTP_StatusCode_Unauthorized = 401,
|
||||||
|
HTTP_StatusCode_PaymentRequired = 402,
|
||||||
|
HTTP_StatusCode_Forbidden = 403,
|
||||||
|
HTTP_StatusCode_NotFound = 404,
|
||||||
|
HTTP_StatusCode_MethodNotAllowed = 405,
|
||||||
|
HTTP_StatusCode_NotAcceptable = 406,
|
||||||
|
HTTP_StatusCode_ProxyAuthenticationRequired = 407,
|
||||||
|
HTTP_StatusCode_RequestTimeout = 408,
|
||||||
|
HTTP_StatusCode_Conflict = 409,
|
||||||
|
HTTP_StatusCode_Gone = 410,
|
||||||
|
HTTP_StatusCode_LengthRequired = 411,
|
||||||
|
HTTP_StatusCode_PreconditionFailed = 412,
|
||||||
|
HTTP_StatusCode_PayloadTooLarge = 413,
|
||||||
|
HTTP_StatusCode_URITooLong = 414,
|
||||||
|
HTTP_StatusCode_UnsupportedMediaType = 415,
|
||||||
|
HTTP_StatusCode_RangeNotSatisfiable = 416,
|
||||||
|
HTTP_StatusCode_ExpectationFailed = 417,
|
||||||
|
HTTP_StatusCode_ImATeapot = 418,
|
||||||
|
HTTP_StatusCode_MisdirectedRequest = 421,
|
||||||
|
HTTP_StatusCode_UnprocessableContent = 422,
|
||||||
|
HTTP_StatusCode_Locked = 423,
|
||||||
|
HTTP_StatusCode_FailedDependency = 424,
|
||||||
|
HTTP_StatusCode_TooEarly = 425,
|
||||||
|
HTTP_StatusCode_UpgradeRequired = 426,
|
||||||
|
HTTP_StatusCode_PreconditionRequired = 428,
|
||||||
|
HTTP_StatusCode_TooManyRequests = 429,
|
||||||
|
HTTP_StatusCode_RequestHeaderFieldsTooLarge = 431,
|
||||||
|
HTTP_StatusCode_UnavailableForLegalReasons = 451,
|
||||||
|
|
||||||
|
//- rjf: servor error responses
|
||||||
|
HTTP_StatusCode_FirstServerError = 500,
|
||||||
|
HTTP_StatusCode_LastServerError = 599,
|
||||||
|
HTTP_StatusCode_InternalServerError = 500,
|
||||||
|
HTTP_StatusCode_NotImplemented = 501,
|
||||||
|
HTTP_StatusCode_BadGateway = 502,
|
||||||
|
HTTP_StatusCode_ServiceUnavailable = 503,
|
||||||
|
HTTP_StatusCode_GatewayTimeout = 504,
|
||||||
|
HTTP_StatusCode_HTTPVersionNotSupported = 505,
|
||||||
|
HTTP_StatusCode_VariantAlsoNegotiates = 506,
|
||||||
|
HTTP_StatusCode_InsufficientStorage = 507,
|
||||||
|
HTTP_StatusCode_LoopDetected = 508,
|
||||||
|
HTTP_StatusCode_NotExtended = 510,
|
||||||
|
HTTP_StatusCode_NetworkAuthenticationRequired = 511,
|
||||||
|
}
|
||||||
|
HTTP_StatusCodeEnum;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Method Kinds
|
||||||
|
|
||||||
|
typedef enum HTTP_Method
|
||||||
|
{
|
||||||
|
HTTP_Method_Get,
|
||||||
|
HTTP_Method_Head,
|
||||||
|
HTTP_Method_Post,
|
||||||
|
HTTP_Method_Put,
|
||||||
|
HTTP_Method_Delete,
|
||||||
|
HTTP_Method_Connect,
|
||||||
|
HTTP_Method_Options,
|
||||||
|
HTTP_Method_Trace,
|
||||||
|
HTTP_Method_Patch,
|
||||||
|
HTTP_Method_COUNT
|
||||||
|
}
|
||||||
|
HTTP_Method;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Request Parameters Bundle
|
||||||
|
|
||||||
|
typedef struct HTTP_RequestParams HTTP_RequestParams;
|
||||||
|
struct HTTP_RequestParams
|
||||||
|
{
|
||||||
|
U64 id;
|
||||||
|
HTTP_Method method;
|
||||||
|
String8 url;
|
||||||
|
String8 body;
|
||||||
|
String8 user_agent;
|
||||||
|
String8 authorization;
|
||||||
|
String8 content_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Response
|
||||||
|
|
||||||
|
typedef struct HTTP_Response HTTP_Response;
|
||||||
|
struct HTTP_Response
|
||||||
|
{
|
||||||
|
U64 id;
|
||||||
|
HTTP_StatusCode code;
|
||||||
|
String8 body;
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: Basic Type Functions
|
||||||
|
|
||||||
|
internal HTTP_StatusKind http_status_kind_from_code(HTTP_StatusCode code);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl Top-Level Layer Calls
|
||||||
|
|
||||||
|
internal void http_init(void);
|
||||||
|
internal void http_async_tick(void);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl I/O Ring Functions
|
||||||
|
|
||||||
|
internal B32 http_push_request(GuardedRing *out_ring, HTTP_RequestParams *params, U64 endt_us);
|
||||||
|
internal B32 http_pop_response(Arena *arena, GuardedRing *out_ring, HTTP_Response *response_out, U64 endt_us);
|
||||||
|
|
||||||
|
#endif // HTTP_H
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#include "http.c"
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/http/win32_http.c"
|
||||||
|
#else
|
||||||
|
# include "http_stub.c"
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef HTTP_INC_H
|
||||||
|
#define HTTP_INC_H
|
||||||
|
|
||||||
|
#include "http.h"
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/http/win32_http.h"
|
||||||
|
#else
|
||||||
|
# include "http_stub.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HTTP_INC_H
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl Top-Level Layer Calls
|
||||||
|
|
||||||
|
internal void http_init(void){}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl I/O Ring Functions
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
http_push_request(GuardedRing *out_ring, HTTP_RequestParams *params, U64 endt_us)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
http_pop_response(Arena *arena, GuardedRing *out_ring, HTTP_Response *response_out, U64 endt_us)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef HTTP_STUB_H
|
||||||
|
#define HTTP_STUB_H
|
||||||
|
|
||||||
|
#endif // HTTP_STUB_H
|
||||||
@@ -59,10 +59,10 @@ mtx_enqueue_op(MTX_MutThread *thread, C_Key buffer_key, MTX_Op op)
|
|||||||
U64 needed_size = sizeof(buffer_key) + sizeof(op.range) + sizeof(op.replace.size) + op.replace.size;
|
U64 needed_size = sizeof(buffer_key) + sizeof(op.range) + sizeof(op.replace.size) + op.replace.size;
|
||||||
if(available_size >= needed_size)
|
if(available_size >= needed_size)
|
||||||
{
|
{
|
||||||
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &buffer_key);
|
thread->ring_write_pos += wrapped_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &buffer_key);
|
||||||
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.range);
|
thread->ring_write_pos += wrapped_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.range);
|
||||||
thread->ring_write_pos += ring_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.replace.size);
|
thread->ring_write_pos += wrapped_write_struct(thread->ring_base, thread->ring_size, thread->ring_write_pos, &op.replace.size);
|
||||||
thread->ring_write_pos += ring_write(thread->ring_base, thread->ring_size, thread->ring_write_pos, op.replace.str, op.replace.size);
|
thread->ring_write_pos += wrapped_write(thread->ring_base, thread->ring_size, thread->ring_write_pos, op.replace.str, op.replace.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cond_var_wait(thread->cv, thread->mutex, max_U64);
|
cond_var_wait(thread->cv, thread->mutex, max_U64);
|
||||||
@@ -78,11 +78,11 @@ mtx_dequeue_op(Arena *arena, MTX_MutThread *thread, C_Key *buffer_key_out, MTX_O
|
|||||||
U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos;
|
U64 unconsumed_size = thread->ring_write_pos - thread->ring_read_pos;
|
||||||
if(unconsumed_size >= sizeof(*buffer_key_out) + sizeof(op_out->range) + sizeof(op_out->replace.size))
|
if(unconsumed_size >= sizeof(*buffer_key_out) + sizeof(op_out->range) + sizeof(op_out->replace.size))
|
||||||
{
|
{
|
||||||
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, buffer_key_out);
|
thread->ring_read_pos += wrapped_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, buffer_key_out);
|
||||||
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->range);
|
thread->ring_read_pos += wrapped_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->range);
|
||||||
thread->ring_read_pos += ring_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->replace.size);
|
thread->ring_read_pos += wrapped_read_struct(thread->ring_base, thread->ring_size, thread->ring_read_pos, &op_out->replace.size);
|
||||||
op_out->replace.str = push_array_no_zero(arena, U8, op_out->replace.size);
|
op_out->replace.str = push_array_no_zero(arena, U8, op_out->replace.size);
|
||||||
thread->ring_read_pos += ring_read(thread->ring_base, thread->ring_size, thread->ring_read_pos, op_out->replace.str, op_out->replace.size);
|
thread->ring_read_pos += wrapped_read(thread->ring_base, thread->ring_size, thread->ring_read_pos, op_out->replace.str, op_out->replace.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cond_var_wait(thread->cv, thread->mutex, max_U64);
|
cond_var_wait(thread->cv, thread->mutex, max_U64);
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[255] =
|
|||||||
{ str8_lit_comp("open_crash_dump"), str8_lit_comp("Opens a crash dump file and recreates debuggee state at the time of the crash."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("open_crash_dump"), str8_lit_comp("Opens a crash dump file and recreates debuggee state at the time of the crash."), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_FilePath, str8_lit_comp("folder:\"$input\""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("exit"), str8_lit_comp("Exits the debugger."), str8_lit_comp("quit,close,abort"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("open_palette"), str8_lit_comp("Opens the palette."), str8_lit_comp("help,cmd,lister"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("open_palette"), str8_lit_comp("Opens the palette."), str8_lit_comp("help,cmd,lister"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*1)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:commands"), str8_lit_comp("commands"), D_EntityKind_Null}},
|
{ str8_lit_comp("run_command"), str8_lit_comp("Runs a command from the command palette."), str8_lit_comp("help,cmd"), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*1)|(RD_QueryFlag_Required*1), RD_RegSlot_CmdName, str8_lit_comp("query:commands"), str8_lit_comp("commands"), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("run_ext_driver_text_command"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*0)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("state"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("state"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Null, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
{ str8_lit_comp("eval"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
{ str8_lit_comp("eval"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), (RD_CmdKindFlag_ListInUI*0)|(RD_CmdKindFlag_ListInIPCDocs*1)|(RD_CmdKindFlag_ListInTextPt*0)|(RD_CmdKindFlag_ListInTextRng*0)|(RD_CmdKindFlag_ListInEval*0)|(RD_CmdKindFlag_ListInMemory*0), {(RD_QueryFlag_AllowFiles*0)|(RD_QueryFlag_AllowFolders*0)|(RD_QueryFlag_CodeInput*0)|(RD_QueryFlag_KeepOldInput*0)|(RD_QueryFlag_SelectOldInput*0)|(RD_QueryFlag_Floating*0)|(RD_QueryFlag_Required*0), RD_RegSlot_Expr, str8_lit_comp(""), str8_lit_comp(""), D_EntityKind_Null}},
|
||||||
@@ -845,7 +845,7 @@ RD_CmdKindInfo rd_cmd_kind_info_table[255] =
|
|||||||
{ str8_lit_comp("geo3d"), str8_lit_comp("Opens a Geometry (3D) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab},
|
{ str8_lit_comp("geo3d"), str8_lit_comp("Opens a Geometry (3D) tab."), {0}, {0}, RD_CmdKindFlag_ListInUI|RD_CmdKindFlag_ListInIPCDocs|RD_CmdKindFlag_ListInTab},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct {String8 string; CFG_Binding binding;} rd_default_binding_table[114] =
|
struct {String8 string; CFG_Binding binding;} rd_default_binding_table[116] =
|
||||||
{
|
{
|
||||||
{str8_lit_comp("kill_all"), {WM_Key_F5, 0 |WM_Modifier_Shift }},
|
{str8_lit_comp("kill_all"), {WM_Key_F5, 0 |WM_Modifier_Shift }},
|
||||||
{str8_lit_comp("step_into_inst"), {WM_Key_F11, 0 |WM_Modifier_Alt}},
|
{str8_lit_comp("step_into_inst"), {WM_Key_F11, 0 |WM_Modifier_Alt}},
|
||||||
@@ -944,7 +944,9 @@ struct {String8 string; CFG_Binding binding;} rd_default_binding_table[114] =
|
|||||||
{str8_lit_comp("goto_line"), {WM_Key_G, 0 |WM_Modifier_Ctrl }},
|
{str8_lit_comp("goto_line"), {WM_Key_G, 0 |WM_Modifier_Ctrl }},
|
||||||
{str8_lit_comp("goto_address"), {WM_Key_G, 0 |WM_Modifier_Alt}},
|
{str8_lit_comp("goto_address"), {WM_Key_G, 0 |WM_Modifier_Alt}},
|
||||||
{str8_lit_comp("search"), {WM_Key_F, 0 |WM_Modifier_Ctrl }},
|
{str8_lit_comp("search"), {WM_Key_F, 0 |WM_Modifier_Ctrl }},
|
||||||
|
{str8_lit_comp("search"), {WM_Key_Slash, 0 }},
|
||||||
{str8_lit_comp("search_backwards"), {WM_Key_R, 0 |WM_Modifier_Ctrl }},
|
{str8_lit_comp("search_backwards"), {WM_Key_R, 0 |WM_Modifier_Ctrl }},
|
||||||
|
{str8_lit_comp("search_backwards"), {WM_Key_Slash, 0 |WM_Modifier_Ctrl }},
|
||||||
{str8_lit_comp("find_next"), {WM_Key_F3, 0 }},
|
{str8_lit_comp("find_next"), {WM_Key_F3, 0 }},
|
||||||
{str8_lit_comp("find_prev"), {WM_Key_F3, 0 |WM_Modifier_Ctrl }},
|
{str8_lit_comp("find_prev"), {WM_Key_F3, 0 |WM_Modifier_Ctrl }},
|
||||||
{str8_lit_comp("find_selected_thread"), {WM_Key_F4, 0 }},
|
{str8_lit_comp("find_selected_thread"), {WM_Key_F4, 0 }},
|
||||||
|
|||||||
@@ -949,7 +949,7 @@ RD_CmdTable: // | | | |
|
|||||||
{OpenPalette 1 1 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 List "open_palette" "Open Palette" "Opens the palette." "help,cmd,lister" "" }
|
{OpenPalette 1 1 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 List "open_palette" "Open Palette" "Opens the palette." "help,cmd,lister" "" }
|
||||||
|
|
||||||
//- rjf: command fast-path
|
//- rjf: command fast-path
|
||||||
{RunCommand 1 1 0 0 0 0 "query:commands" CmdName commands Nil Null 0 0 0 0 0 1 1 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" "" }
|
{RunCommand 0 0 0 0 0 0 "query:commands" CmdName commands Nil Null 0 0 0 0 0 1 1 Null "run_command" "Run Command" "Runs a command from the command palette." "help,cmd" "" }
|
||||||
|
|
||||||
//- rjf: external drivers
|
//- rjf: external drivers
|
||||||
{RunExternalDriverTextCommand 0 0 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "run_ext_driver_text_command" "Run External Driver Text Command" "" "" "" }
|
{RunExternalDriverTextCommand 0 0 0 0 0 0 "" Null null Nil Null 0 0 0 0 0 0 0 Null "run_ext_driver_text_command" "Run External Driver Text Command" "" "" "" }
|
||||||
@@ -1415,7 +1415,9 @@ RD_DefaultBindingTable:
|
|||||||
{ "goto_line" G ctrl 0 0 }
|
{ "goto_line" G ctrl 0 0 }
|
||||||
{ "goto_address" G 0 0 alt }
|
{ "goto_address" G 0 0 alt }
|
||||||
{ "search" F ctrl 0 0 }
|
{ "search" F ctrl 0 0 }
|
||||||
|
{ "search" Slash 0 0 0 }
|
||||||
{ "search_backwards" R ctrl 0 0 }
|
{ "search_backwards" R ctrl 0 0 }
|
||||||
|
{ "search_backwards" Slash ctrl 0 0 }
|
||||||
{ "find_next" F3 0 0 0 }
|
{ "find_next" F3 0 0 0 }
|
||||||
{ "find_prev" F3 shift 0 0 }
|
{ "find_prev" F3 shift 0 0 }
|
||||||
|
|
||||||
|
|||||||
@@ -1685,7 +1685,7 @@ rd_view_ui(Rng2F32 rect)
|
|||||||
|
|
||||||
//- rjf: build container
|
//- rjf: build container
|
||||||
UI_Box *search_row = &ui_nil_box;
|
UI_Box *search_row = &ui_nil_box;
|
||||||
UI_PrefHeight(ui_px(search_row_height, 1.f)) UI_TagF("focus")
|
UI_PrefHeight(ui_px(search_row_height, 1.f)) // UI_TagF("focus")
|
||||||
{
|
{
|
||||||
if(!vs->contents_are_focused)
|
if(!vs->contents_are_focused)
|
||||||
{
|
{
|
||||||
@@ -6633,12 +6633,19 @@ rd_window_frame(void)
|
|||||||
UI_PermissionFlag_KeyboardSecondary|UI_PermissionFlag_Clicks|UI_PermissionFlag_ScrollX|UI_PermissionFlag_ScrollY :
|
UI_PermissionFlag_KeyboardSecondary|UI_PermissionFlag_Clicks|UI_PermissionFlag_ScrollX|UI_PermissionFlag_ScrollY :
|
||||||
UI_PermissionFlag_All)
|
UI_PermissionFlag_All)
|
||||||
{
|
{
|
||||||
|
B32 has_footer = (is_lister && !is_anchored);
|
||||||
|
F32 container_corner_top_radius_px = is_lister ? ui_top_font_size()*1.f : ui_top_font_size()*0.15f;
|
||||||
|
F32 container_corner_bottom_radius_px = has_footer ? ui_top_font_size()*1.f : ui_top_font_size()*0.15f;
|
||||||
|
|
||||||
// rjf: build top-level container box
|
// rjf: build top-level container box
|
||||||
UI_Box *container = &ui_nil_box;
|
UI_Box *container = &ui_nil_box;
|
||||||
UI_Rect(rect) UI_ChildLayoutAxis(Axis2_Y)
|
UI_Rect(rect) UI_ChildLayoutAxis(Axis2_Y)
|
||||||
UI_Squish(0.1f-0.1f*open_t)
|
UI_Squish(0.1f-0.1f*open_t)
|
||||||
UI_Transparency(1.f-open_t)
|
UI_Transparency(1.f-open_t)
|
||||||
UI_CornerRadius(ui_top_font_size()*0.25f)
|
UI_CornerRadius00(container_corner_top_radius_px)
|
||||||
|
UI_CornerRadius10(container_corner_top_radius_px)
|
||||||
|
UI_CornerRadius01(container_corner_bottom_radius_px)
|
||||||
|
UI_CornerRadius11(container_corner_bottom_radius_px)
|
||||||
{
|
{
|
||||||
container = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
|
container = ui_build_box_from_stringf(UI_BoxFlag_Clickable|
|
||||||
UI_BoxFlag_DrawBorder|
|
UI_BoxFlag_DrawBorder|
|
||||||
@@ -6680,7 +6687,7 @@ rd_window_frame(void)
|
|||||||
// rjf: build contents
|
// rjf: build contents
|
||||||
F32 total_height_px = dim_2f32(rect).y;
|
F32 total_height_px = dim_2f32(rect).y;
|
||||||
F32 footer_height_px = 0;
|
F32 footer_height_px = 0;
|
||||||
if(is_lister && !is_anchored)
|
if(has_footer)
|
||||||
{
|
{
|
||||||
footer_height_px = ui_top_font_size()*4.f;
|
footer_height_px = ui_top_font_size()*4.f;
|
||||||
}
|
}
|
||||||
@@ -7573,6 +7580,29 @@ rd_window_frame(void)
|
|||||||
ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL));
|
ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rjf: update available?
|
||||||
|
if(rd_state->newer_update_available)
|
||||||
|
UI_FontSize(ui_top_font_size()*0.85f)
|
||||||
|
UI_PrefWidth(ui_text_dim(10, 1))
|
||||||
|
UI_TextAlignment(UI_TextAlign_Center)
|
||||||
|
{
|
||||||
|
DR_FStrList fstrs = {0};
|
||||||
|
ui_set_next_hover_cursor(WM_Cursor_HandPoint);
|
||||||
|
UI_Box *label = ui_build_box_from_stringf(UI_BoxFlag_Clickable|UI_BoxFlag_DrawText, "##update");
|
||||||
|
UI_Signal sig = ui_signal_from_box(label);
|
||||||
|
DR_FStrParams p = {ui_top_font(), ui_top_text_raster_flags(), ui_color_from_name(s("text")), ui_top_font_size()};
|
||||||
|
if(ui_key_match(ui_hot_key(), label->key))
|
||||||
|
{
|
||||||
|
p.underline_thickness = ui_top_font_size()*0.2f;
|
||||||
|
}
|
||||||
|
dr_fstrs_push_new(scratch.arena, &fstrs, &p, s("Update Available"));
|
||||||
|
ui_box_equip_display_fstrs(label, &fstrs);
|
||||||
|
if(ui_clicked(sig))
|
||||||
|
{
|
||||||
|
wm_open_in_browser(s("https://github.com/EpicGamesExt/raddebugger/releases/latest"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7910,6 +7940,7 @@ rd_window_frame(void)
|
|||||||
//
|
//
|
||||||
if(content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0)
|
if(content_rect.x1 > content_rect.x0 && content_rect.y1 > content_rect.y0)
|
||||||
{
|
{
|
||||||
|
B32 any_disasm_open = 0;
|
||||||
ProfScope("leaf panel UI")
|
ProfScope("leaf panel UI")
|
||||||
for(CFG_PanelNode *panel = panel_tree.root;
|
for(CFG_PanelNode *panel = panel_tree.root;
|
||||||
panel != &cfg_nil_panel_node;
|
panel != &cfg_nil_panel_node;
|
||||||
@@ -7924,6 +7955,10 @@ rd_window_frame(void)
|
|||||||
panel_tree.focused == panel);
|
panel_tree.focused == panel);
|
||||||
CFG_Node *selected_tab = panel->selected_tab;
|
CFG_Node *selected_tab = panel->selected_tab;
|
||||||
RD_ViewState *selected_tab_view_state = rd_view_state_from_cfg(selected_tab);
|
RD_ViewState *selected_tab_view_state = rd_view_state_from_cfg(selected_tab);
|
||||||
|
if(str8_match(selected_tab->string, s("disasm"), 0))
|
||||||
|
{
|
||||||
|
any_disasm_open = 1;
|
||||||
|
}
|
||||||
ProfScope("leaf panel UI work - %.*s: %.*s", str8_varg(selected_tab->string), str8_varg(rd_expr_from_cfg(selected_tab)))
|
ProfScope("leaf panel UI work - %.*s: %.*s", str8_varg(selected_tab->string), str8_varg(rd_expr_from_cfg(selected_tab)))
|
||||||
UI_Focus(panel_is_focused ? UI_FocusKind_Null : UI_FocusKind_Off)
|
UI_Focus(panel_is_focused ? UI_FocusKind_Null : UI_FocusKind_Off)
|
||||||
{
|
{
|
||||||
@@ -8752,6 +8787,10 @@ rd_window_frame(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!any_disasm_open && rd_regs()->prefer_disasm)
|
||||||
|
{
|
||||||
|
rd_regs()->prefer_disasm = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
@@ -9342,6 +9381,8 @@ rd_window_frame(void)
|
|||||||
FNT_Tag font = rd_font_from_slot(RD_FontSlot_Code);
|
FNT_Tag font = rd_font_from_slot(RD_FontSlot_Code);
|
||||||
Vec2F32 p = ui_mouse();
|
Vec2F32 p = ui_mouse();
|
||||||
dr_rect(hover_debug_box->rect, v4f32(1, 1, 1, 0.2f), 0, 0, 0);
|
dr_rect(hover_debug_box->rect, v4f32(1, 1, 1, 0.2f), 0, 0, 0);
|
||||||
|
R_Rect2DInst *border = dr_rect(hover_debug_box->rect, v4f32(1, 0, 0, 1.f), 0, 0, 0);
|
||||||
|
MemoryCopyArray(border->corner_radii, hover_debug_box->corner_radii);
|
||||||
dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "key: 0x%I64x", hover_debug_box->key.u64[0]));
|
dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "key: 0x%I64x", hover_debug_box->key.u64[0]));
|
||||||
p.y += 20.f;
|
p.y += 20.f;
|
||||||
dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "string: '%S'", hover_debug_box->string));
|
dr_text(font, 12.f, 0, 0, FNT_RasterFlag_Hinted, p, v4f32(1, 1, 1, 1), push_str8f(scratch.arena, "string: '%S'", hover_debug_box->string));
|
||||||
@@ -10641,6 +10682,19 @@ rd_init(CmdLine *cmdln)
|
|||||||
rd_state->drag_drop_regs = push_array(rd_state->drag_drop_arena, RD_Regs, 1);
|
rd_state->drag_drop_regs = push_array(rd_state->drag_drop_arena, RD_Regs, 1);
|
||||||
rd_state->top_regs = &rd_state->base_regs;
|
rd_state->top_regs = &rd_state->base_regs;
|
||||||
|
|
||||||
|
// rjf: set up update check http ring & send request
|
||||||
|
{
|
||||||
|
rd_state->update_check_http_ring = guarded_ring_alloc(arena, KB(8));
|
||||||
|
HTTP_RequestParams p =
|
||||||
|
{
|
||||||
|
.id = 1,
|
||||||
|
.method = HTTP_Method_Get,
|
||||||
|
.url = s("https://api.github.com/repos/EpicGamesExt/raddebugger/releases/latest"),
|
||||||
|
.user_agent = s("raddebugger"),
|
||||||
|
};
|
||||||
|
http_push_request(rd_state->update_check_http_ring, &p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
// rjf: set up schemas
|
// rjf: set up schemas
|
||||||
{
|
{
|
||||||
rd_state->cfg_schema_table = push_array(rd_state->arena, CFG_SchemaTable, 1);
|
rd_state->cfg_schema_table = push_array(rd_state->arena, CFG_SchemaTable, 1);
|
||||||
@@ -11043,6 +11097,33 @@ rd_frame(void)
|
|||||||
MemoryZeroStruct(&rd_state->cmd_outputs);
|
MemoryZeroStruct(&rd_state->cmd_outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- rjf: check for updates
|
||||||
|
//
|
||||||
|
if(!rd_state->got_update_check)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
HTTP_Response response = {0};
|
||||||
|
if(http_pop_response(scratch.arena, rd_state->update_check_http_ring, &response, 0))
|
||||||
|
{
|
||||||
|
rd_state->got_update_check = 1;
|
||||||
|
MD_Node *root = md_tree_from_string(scratch.arena, response.body)->first;
|
||||||
|
MD_Node *html_url = md_child_from_string(root, s("html_url"), 0);
|
||||||
|
String8 newest_release_url = html_url->first->string;
|
||||||
|
U64 tag_pos = str8_find_needle(newest_release_url, 0, s("tag/v"), 0);
|
||||||
|
String8 tag_name = str8_skip(newest_release_url, tag_pos);
|
||||||
|
U64 suffix_pos = str8_find_needle(tag_name, 0, s("-"), 0);
|
||||||
|
String8 version_name = str8_prefix(tag_name, suffix_pos);
|
||||||
|
U64 release_version = version_from_str8(version_name);
|
||||||
|
U64 current_version = Version(BUILD_VERSION_MAJOR, BUILD_VERSION_MINOR, BUILD_VERSION_PATCH);
|
||||||
|
if(current_version < release_version)
|
||||||
|
{
|
||||||
|
rd_state->newer_update_available = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: iterate all tabs, touch their view-states
|
//- rjf: iterate all tabs, touch their view-states
|
||||||
//
|
//
|
||||||
@@ -11082,6 +11163,7 @@ rd_frame(void)
|
|||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: apply debug info config trees -> loaded debug info cache
|
//- rjf: apply debug info config trees -> loaded debug info cache
|
||||||
//
|
//
|
||||||
|
ProfScope("apply debug info config trees -> loaded debug info cache")
|
||||||
{
|
{
|
||||||
U64 current_update_tick_idx = update_tick_idx();
|
U64 current_update_tick_idx = update_tick_idx();
|
||||||
|
|
||||||
@@ -12883,7 +12965,8 @@ rd_frame(void)
|
|||||||
{
|
{
|
||||||
rd_cmd(RD_CmdKind_PushQuery,
|
rd_cmd(RD_CmdKind_PushQuery,
|
||||||
.do_implicit_root = 1,
|
.do_implicit_root = 1,
|
||||||
.do_lister = info->query.expr.size != 0);
|
.do_lister = (info->query.expr.size != 0),
|
||||||
|
.expr = info->query.expr);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
|||||||
@@ -394,6 +394,11 @@ struct RD_State
|
|||||||
S32 frame_depth;
|
S32 frame_depth;
|
||||||
U64 frame_eval_memread_endt_us;
|
U64 frame_eval_memread_endt_us;
|
||||||
|
|
||||||
|
// rjf: update checker
|
||||||
|
B32 got_update_check;
|
||||||
|
B32 newer_update_available;
|
||||||
|
GuardedRing *update_check_http_ring;
|
||||||
|
|
||||||
// rjf: config bucket paths
|
// rjf: config bucket paths
|
||||||
Arena *user_path_arena;
|
Arena *user_path_arena;
|
||||||
String8 user_path;
|
String8 user_path;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: post-0.9.26 TODO notes
|
//~ rjf: post-0.9.26 TODO notes
|
||||||
//
|
//
|
||||||
|
// [ ] unwinding crash - f5 on bp in w32_http_status_callback to repro
|
||||||
// [ ] jeff stepping bug
|
// [ ] jeff stepping bug
|
||||||
// [ ] wassim memory bug
|
// [ ] wassim memory bug
|
||||||
// [ ] switch off spoofs for step-over
|
// [ ] switch off spoofs for step-over
|
||||||
@@ -309,6 +310,8 @@
|
|||||||
#include "minidump/minidump_parse.h"
|
#include "minidump/minidump_parse.h"
|
||||||
#include "mdesk/mdesk.h"
|
#include "mdesk/mdesk.h"
|
||||||
#include "window_manager/window_manager_inc.h"
|
#include "window_manager/window_manager_inc.h"
|
||||||
|
#include "http/http_inc.h"
|
||||||
|
#include "symbol_server/symbol_server_inc.h"
|
||||||
#include "config/config_inc.h"
|
#include "config/config_inc.h"
|
||||||
#include "content/content.h"
|
#include "content/content.h"
|
||||||
#include "file_stream/file_stream.h"
|
#include "file_stream/file_stream.h"
|
||||||
@@ -366,6 +369,8 @@
|
|||||||
#include "minidump/minidump_parse.c"
|
#include "minidump/minidump_parse.c"
|
||||||
#include "mdesk/mdesk.c"
|
#include "mdesk/mdesk.c"
|
||||||
#include "window_manager/window_manager_inc.c"
|
#include "window_manager/window_manager_inc.c"
|
||||||
|
#include "http/http_inc.c"
|
||||||
|
#include "symbol_server/symbol_server_inc.c"
|
||||||
#include "config/config_inc.c"
|
#include "config/config_inc.c"
|
||||||
#include "content/content.c"
|
#include "content/content.c"
|
||||||
#include "file_stream/file_stream.c"
|
#include "file_stream/file_stream.c"
|
||||||
@@ -468,8 +473,8 @@ ipc_signaler_thread__entry_point(void *p)
|
|||||||
U64 available_size = (sizeof(ipc_s2m_ring_buffer) - unconsumed_size);
|
U64 available_size = (sizeof(ipc_s2m_ring_buffer) - unconsumed_size);
|
||||||
if(available_size >= sizeof(U64)+sizeof(msg.size))
|
if(available_size >= sizeof(U64)+sizeof(msg.size))
|
||||||
{
|
{
|
||||||
ipc_s2m_ring_write_pos += ring_write_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, &msg.size);
|
ipc_s2m_ring_write_pos += wrapped_write_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, &msg.size);
|
||||||
ipc_s2m_ring_write_pos += ring_write(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, msg.str, msg.size);
|
ipc_s2m_ring_write_pos += wrapped_write(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_write_pos, msg.str, msg.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cond_var_wait(ipc_s2m_ring_cv, ipc_s2m_ring_mutex, max_U64);
|
cond_var_wait(ipc_s2m_ring_cv, ipc_s2m_ring_mutex, max_U64);
|
||||||
@@ -659,10 +664,10 @@ entry_point(CmdLine *cmd_line)
|
|||||||
{
|
{
|
||||||
consumed = 1;
|
consumed = 1;
|
||||||
ipc_command_frame = 1;
|
ipc_command_frame = 1;
|
||||||
ipc_s2m_ring_read_pos += ring_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size);
|
ipc_s2m_ring_read_pos += wrapped_read_struct(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, &msg.size);
|
||||||
msg.size = Min(msg.size, unconsumed_size);
|
msg.size = Min(msg.size, unconsumed_size);
|
||||||
msg.str = push_array(scratch.arena, U8, msg.size);
|
msg.str = push_array(scratch.arena, U8, msg.size);
|
||||||
ipc_s2m_ring_read_pos += ring_read(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, msg.str, msg.size);
|
ipc_s2m_ring_read_pos += wrapped_read(ipc_s2m_ring_buffer, sizeof(ipc_s2m_ring_buffer), ipc_s2m_ring_read_pos, msg.str, msg.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(consumed)
|
if(consumed)
|
||||||
|
|||||||
@@ -2543,12 +2543,12 @@ RD_VIEW_UI_FUNCTION_DEF(disasm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: unpack cursor info
|
//- rjf: unpack cursor info / fill regs
|
||||||
//
|
//
|
||||||
|
rd_regs()->prefer_disasm = 1;
|
||||||
if(!is_loading && has_disasm)
|
if(!is_loading && has_disasm)
|
||||||
{
|
{
|
||||||
U64 off = dasm_line_array_code_off_from_idx(&dasm_info.lines, rd_regs()->cursor.line-1);
|
U64 off = dasm_line_array_code_off_from_idx(&dasm_info.lines, rd_regs()->cursor.line-1);
|
||||||
rd_regs()->prefer_disasm = 1;
|
|
||||||
rd_regs()->vaddr = range.min+off;
|
rd_regs()->vaddr = range.min+off;
|
||||||
rd_regs()->vaddr_range = r1u64(range.min+off, range.min+off);
|
rd_regs()->vaddr_range = r1u64(range.min+off, range.min+off);
|
||||||
rd_regs()->voff_range = d_voff_range_from_vaddr_range(dasm_module, rd_regs()->vaddr_range);
|
rd_regs()->voff_range = d_voff_range_from_vaddr_range(dasm_module, rd_regs()->vaddr_range);
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef SYMBOL_SERVER_H
|
||||||
|
#define SYMBOL_SERVER_H
|
||||||
|
|
||||||
|
internal void smsv_init(void);
|
||||||
|
internal String8 smsv_local_path_from_key(Arena *arena, String8 module_name, String8 dbg_name, Guid guid, U64 age);
|
||||||
|
|
||||||
|
#endif // SYMBOL_SERVER_H
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#include "symbol_server.c"
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/symbol_server/win32_symbol_server.c"
|
||||||
|
#else
|
||||||
|
# include "symbol_server_stub.c"
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef SYMBOL_SERVER_INC_H
|
||||||
|
#define SYMBOL_SERVER_INC_H
|
||||||
|
|
||||||
|
#include "symbol_server.h"
|
||||||
|
#if OS_WINDOWS
|
||||||
|
# include "win32/symbol_server/win32_symbol_server.h"
|
||||||
|
#else
|
||||||
|
# include "symbol_server_stub.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SYMBOL_SERVER_INC_H
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal void
|
||||||
|
smsv_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
smsv_local_path_from_key(Arena *arena, String8 module_name, String8 dbg_name, Guid guid, U64 age)
|
||||||
|
{
|
||||||
|
return s("");
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef SYMBOL_SERVER_STUB_H
|
||||||
|
#define SYMBOL_SERVER_STUB_H
|
||||||
|
|
||||||
|
#endif // SYMBOL_SERVER_STUB_H
|
||||||
@@ -1289,6 +1289,8 @@ ui_scroll_bar(Axis2 axis, UI_Size off_axis_size, UI_ScrollPt pt, Rng1S64 idx_ran
|
|||||||
UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags)
|
UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags)
|
||||||
UI_TextAlignment(UI_TextAlign_Center)
|
UI_TextAlignment(UI_TextAlign_Center)
|
||||||
UI_Font(ui_icon_font())
|
UI_Font(ui_icon_font())
|
||||||
|
UI_TextRasterFlags(FNT_RasterFlag_Smooth)
|
||||||
|
UI_TagF("weak")
|
||||||
{
|
{
|
||||||
String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_LeftArrow : UI_IconKind_UpArrow);
|
String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_LeftArrow : UI_IconKind_UpArrow);
|
||||||
min_scroll_sig = ui_buttonf("%S##_min_scroll_%i", arrow_string, axis);
|
min_scroll_sig = ui_buttonf("%S##_min_scroll_%i", arrow_string, axis);
|
||||||
@@ -1339,6 +1341,8 @@ ui_scroll_bar(Axis2 axis, UI_Size off_axis_size, UI_ScrollPt pt, Rng1S64 idx_ran
|
|||||||
UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags)
|
UI_Flags(UI_BoxFlag_DrawBorder|disabled_flags)
|
||||||
UI_TextAlignment(UI_TextAlign_Center)
|
UI_TextAlignment(UI_TextAlign_Center)
|
||||||
UI_Font(ui_icon_font())
|
UI_Font(ui_icon_font())
|
||||||
|
UI_TextRasterFlags(FNT_RasterFlag_Smooth)
|
||||||
|
UI_TagF("weak")
|
||||||
{
|
{
|
||||||
String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_RightArrow : UI_IconKind_DownArrow);
|
String8 arrow_string = ui_icon_string_from_kind(axis == Axis2_X ? UI_IconKind_RightArrow : UI_IconKind_DownArrow);
|
||||||
max_scroll_sig = ui_buttonf("%S##_max_scroll_%i", arrow_string, axis);
|
max_scroll_sig = ui_buttonf("%S##_max_scroll_%i", arrow_string, axis);
|
||||||
|
|||||||
@@ -1942,30 +1942,12 @@ w32_entry_point_caller(int argc, WCHAR **wargv)
|
|||||||
{
|
{
|
||||||
String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx);
|
String16 string16 = str16((U16 *)this_proc_env + start_idx, idx - start_idx);
|
||||||
String8 string = str8_from_16(arena, string16);
|
String8 string = str8_from_16(arena, string16);
|
||||||
if(str8_match(string, s("_NT_SYMBOL_PATH="), StringMatchFlag_RightSideSloppy))
|
|
||||||
{
|
|
||||||
info->symbol_cache_path = str8_skip(string, 16);
|
|
||||||
info->symbol_cache_path = str8_skip_chop_whitespace(info->symbol_cache_path);
|
|
||||||
}
|
|
||||||
str8_list_push(arena, &info->environment, string);
|
str8_list_push(arena, &info->environment, string);
|
||||||
start_idx = idx+1;
|
start_idx = idx+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(info->symbol_cache_path.size == 0)
|
|
||||||
{
|
|
||||||
Temp scratch = scratch_begin(0, 0);
|
|
||||||
U64 size = KB(32);
|
|
||||||
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
|
|
||||||
if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA, 0, 0, (WCHAR*)buffer)))
|
|
||||||
{
|
|
||||||
String8 local_appdata = str8_from_16(scratch.arena, str16_cstring(buffer));
|
|
||||||
info->symbol_cache_path = str8f(arena, "%S\\Temp\\SymbolCache", local_appdata);
|
|
||||||
|
|
||||||
}
|
|
||||||
scratch_end(scratch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: set up entity storage
|
//- rjf: set up entity storage
|
||||||
|
|||||||
@@ -0,0 +1,501 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Status Callback
|
||||||
|
|
||||||
|
internal void
|
||||||
|
w32_http_status_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, void *lpvStatusInformation, DWORD dwStatusInformationLength)
|
||||||
|
{
|
||||||
|
W32_HTTP_Request *req = (W32_HTTP_Request *)dwContext;
|
||||||
|
B32 reloop = 1;
|
||||||
|
switch(dwInternetStatus)
|
||||||
|
{
|
||||||
|
default:{reloop = 0;}break;
|
||||||
|
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_Failed);
|
||||||
|
}break;
|
||||||
|
case WINHTTP_CALLBACK_STATUS_REQUEST_SENT:
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_cond_assign(&req->status, W32_HTTP_RequestStatus_Sent, W32_HTTP_RequestStatus_PendingSend);
|
||||||
|
}break;
|
||||||
|
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
|
||||||
|
{
|
||||||
|
req->next_body_piece = 0;
|
||||||
|
req->next_body_piece_size = 0;
|
||||||
|
ins_atomic_u32_eval_cond_assign(&req->status, W32_HTTP_RequestStatus_Recvd, W32_HTTP_RequestStatus_PendingRecv);
|
||||||
|
}break;
|
||||||
|
case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
|
||||||
|
{
|
||||||
|
DWORD *size_ptr = (DWORD *)lpvStatusInformation;
|
||||||
|
req->next_body_piece_size = size_ptr[0];
|
||||||
|
if(size_ptr[0] != 0)
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_DataSized);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_Done);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case WINHTTP_CALLBACK_STATUS_READ_COMPLETE:
|
||||||
|
{
|
||||||
|
req->next_body_piece_size = dwStatusInformationLength;
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_Recvd);
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
if(reloop)
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_assign(&async_loop_again, 1);
|
||||||
|
cond_var_broadcast(async_tick_start_cond_var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl Top-Level Layer Calls
|
||||||
|
|
||||||
|
internal void
|
||||||
|
http_init(void)
|
||||||
|
{
|
||||||
|
Arena *arena = arena_alloc();
|
||||||
|
w32_http_state = push_array(arena, W32_HTTP_State, 1);
|
||||||
|
w32_http_state->arena = arena;
|
||||||
|
w32_http_state->request_ring = guarded_ring_alloc(arena, MB(1));
|
||||||
|
for EachElement(idx, w32_http_state->active_requests)
|
||||||
|
{
|
||||||
|
w32_http_state->active_requests[idx].arena = arena_alloc();
|
||||||
|
}
|
||||||
|
w32_http_state->hSession = WinHttpOpen(0, WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
|
||||||
|
WinHttpSetStatusCallback(w32_http_state->hSession, w32_http_status_callback, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
http_async_tick(void)
|
||||||
|
{
|
||||||
|
//- rjf: pop requests, fill active request slots
|
||||||
|
if(lane_idx() == 0)
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
|
||||||
|
//- rjf: find a free active request slot
|
||||||
|
U64 free_slot_num = 0;
|
||||||
|
for EachElement(idx, w32_http_state->active_requests)
|
||||||
|
{
|
||||||
|
if(!w32_http_state->active_requests[idx].active)
|
||||||
|
{
|
||||||
|
free_slot_num = idx+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: if we got one -> pop request data
|
||||||
|
String8 request_data = {0};
|
||||||
|
if(free_slot_num != 0)
|
||||||
|
{
|
||||||
|
RingGuard guard = guarded_ring_open(w32_http_state->request_ring);
|
||||||
|
guarded_ring_try_read_struct(&guard, &request_data.size);
|
||||||
|
if(request_data.size != 0)
|
||||||
|
{
|
||||||
|
request_data.str = push_array(scratch.arena, U8, request_data.size);
|
||||||
|
guarded_ring_read_or_wait(&guard, request_data.size, request_data.str, max_U64);
|
||||||
|
}
|
||||||
|
guarded_ring_close(&guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: deserialize
|
||||||
|
GuardedRing *out_ring = 0;
|
||||||
|
HTTP_RequestParams params = {0};
|
||||||
|
if(request_data.size != 0)
|
||||||
|
{
|
||||||
|
U64 off = 0;
|
||||||
|
off += str8_deserial_read_struct(request_data, off, &out_ring);
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.id);
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.method);
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.url.size);
|
||||||
|
params.url = str8_substr(request_data, r1u64(off, off+params.url.size));
|
||||||
|
off += params.url.size;
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.body.size);
|
||||||
|
params.body = str8_substr(request_data, r1u64(off, off+params.body.size));
|
||||||
|
off += params.body.size;
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.user_agent.size);
|
||||||
|
params.user_agent = str8_substr(request_data, r1u64(off, off+params.user_agent.size));
|
||||||
|
off += params.user_agent.size;
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.authorization.size);
|
||||||
|
params.authorization = str8_substr(request_data, r1u64(off, off+params.authorization.size));
|
||||||
|
off += params.authorization.size;
|
||||||
|
off += str8_deserial_read_struct(request_data, off, ¶ms.content_type.size);
|
||||||
|
params.content_type = str8_substr(request_data, r1u64(off, off+params.content_type.size));
|
||||||
|
off += params.content_type.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: fill active request slot
|
||||||
|
W32_HTTP_Request *req = 0;
|
||||||
|
if(free_slot_num != 0 && request_data.size != 0)
|
||||||
|
{
|
||||||
|
req = &w32_http_state->active_requests[free_slot_num-1];
|
||||||
|
req->active = 1;
|
||||||
|
arena_clear(req->arena);
|
||||||
|
req->out_ring = out_ring;
|
||||||
|
req->id = params.id;
|
||||||
|
req->status = W32_HTTP_RequestStatus_Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: kick off request
|
||||||
|
if(req != 0)
|
||||||
|
{
|
||||||
|
B32 good = 0;
|
||||||
|
|
||||||
|
//- rjf: unpack
|
||||||
|
HTTP_Method method = params.method;
|
||||||
|
String8 url = params.url;
|
||||||
|
String8 body = params.body;
|
||||||
|
String8 user_agent = params.user_agent;
|
||||||
|
String8 authorization = params.authorization;
|
||||||
|
String8 content_type = params.content_type;
|
||||||
|
|
||||||
|
//- rjf: extract URL info
|
||||||
|
String8 url_protocol_part = {0};
|
||||||
|
String8 url_port_part = {0};
|
||||||
|
String8 url_hostname_part = {0};
|
||||||
|
String8 url_path_part = {0};
|
||||||
|
{
|
||||||
|
U64 protocol_delimiter_pos = str8_find_needle(url, 0, s("://"), 0);
|
||||||
|
U64 post_protocol_pos = 0;
|
||||||
|
if(protocol_delimiter_pos < url.size)
|
||||||
|
{
|
||||||
|
post_protocol_pos = protocol_delimiter_pos+3;
|
||||||
|
url_protocol_part = str8_prefix(url, post_protocol_pos);
|
||||||
|
}
|
||||||
|
U64 last_colon_pos = str8_find_needle(url, post_protocol_pos, s(":"), 0);
|
||||||
|
if(last_colon_pos < url.size)
|
||||||
|
{
|
||||||
|
url_port_part = str8_skip(url, last_colon_pos+1);
|
||||||
|
}
|
||||||
|
U64 first_non_protocol_slash_pos = str8_find_needle(url, post_protocol_pos, s("/"), 0);
|
||||||
|
if(first_non_protocol_slash_pos < url.size)
|
||||||
|
{
|
||||||
|
url_hostname_part = str8_prefix(url, first_non_protocol_slash_pos);
|
||||||
|
url_hostname_part = str8_skip(url_hostname_part, post_protocol_pos);
|
||||||
|
url_path_part = str8_skip(url, first_non_protocol_slash_pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url_hostname_part = str8_skip(url, post_protocol_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert url parts to connection parameters
|
||||||
|
U16 port = INTERNET_DEFAULT_HTTPS_PORT;
|
||||||
|
String16 hostname16 = {0};
|
||||||
|
{
|
||||||
|
if(url_port_part.size != 0)
|
||||||
|
{
|
||||||
|
port = (U16)u64_from_str8(url_port_part, 10);
|
||||||
|
}
|
||||||
|
else if(str8_match(url_protocol_part, s("https://"), StringMatchFlag_CaseInsensitive))
|
||||||
|
{
|
||||||
|
port = INTERNET_DEFAULT_HTTPS_PORT;
|
||||||
|
}
|
||||||
|
else if(str8_match(url_protocol_part, s("http://"), StringMatchFlag_CaseInsensitive))
|
||||||
|
{
|
||||||
|
port = INTERNET_DEFAULT_HTTP_PORT;
|
||||||
|
}
|
||||||
|
else if(str8_match(url_protocol_part, s("ftp://"), StringMatchFlag_CaseInsensitive))
|
||||||
|
{
|
||||||
|
port = 21;
|
||||||
|
}
|
||||||
|
else if(str8_match(url_protocol_part, s("ssh://"), StringMatchFlag_CaseInsensitive))
|
||||||
|
{
|
||||||
|
port = 22;
|
||||||
|
}
|
||||||
|
hostname16 = str16_from_8(scratch.arena, url_hostname_part);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert method to verb wchar
|
||||||
|
WCHAR *verb = L"GET";
|
||||||
|
switch(method)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case HTTP_Method_Get: {verb = L"GET";}break;
|
||||||
|
case HTTP_Method_Head: {verb = L"HEAD";}break;
|
||||||
|
case HTTP_Method_Post: {verb = L"POST";}break;
|
||||||
|
case HTTP_Method_Put: {verb = L"PUT";}break;
|
||||||
|
case HTTP_Method_Delete: {verb = L"DELETE";}break;
|
||||||
|
case HTTP_Method_Connect: {verb = L"CONNECT";}break;
|
||||||
|
case HTTP_Method_Options: {verb = L"OPTIONS";}break;
|
||||||
|
case HTTP_Method_Trace: {verb = L"TRACE";}break;
|
||||||
|
case HTTP_Method_Patch: {verb = L"PATCH";}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert url parts to request parameters
|
||||||
|
WCHAR *path_name = L"";
|
||||||
|
if(url_path_part.size != 0)
|
||||||
|
{
|
||||||
|
String16 url_path_part16 = str16_from_8(scratch.arena, url_path_part);
|
||||||
|
path_name = (WCHAR *)url_path_part16.str;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: unpack body params
|
||||||
|
String16 header16 = {0};
|
||||||
|
{
|
||||||
|
String8List header_strings = {0};
|
||||||
|
if(user_agent.size != 0) { str8_list_pushf(scratch.arena, &header_strings, "User-Agent: %S\n", user_agent); }
|
||||||
|
if(authorization.size != 0) { str8_list_pushf(scratch.arena, &header_strings, "Authorization: %S\n", authorization); }
|
||||||
|
if(content_type.size != 0) { str8_list_pushf(scratch.arena, &header_strings, "Content-Type: %S\n", content_type); }
|
||||||
|
String8 header = str8_list_join(scratch.arena, &header_strings, 0);
|
||||||
|
header16 = str16_from_8(scratch.arena, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert body/header info to winhttp expected params
|
||||||
|
WCHAR *header = WINHTTP_NO_ADDITIONAL_HEADERS;
|
||||||
|
U64 header_size = 0;
|
||||||
|
void *optional = WINHTTP_NO_REQUEST_DATA;
|
||||||
|
U64 optional_size = 0;
|
||||||
|
if(header16.size != 0)
|
||||||
|
{
|
||||||
|
header = (WCHAR *)header16.str;
|
||||||
|
header_size = header16.size;
|
||||||
|
}
|
||||||
|
if(body.size != 0)
|
||||||
|
{
|
||||||
|
String8 body_copy = str8_copy(req->arena, body);
|
||||||
|
optional = body_copy.str;
|
||||||
|
optional_size = body_copy.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: open connection
|
||||||
|
HINTERNET hConnect = 0;
|
||||||
|
if(w32_http_state->hSession != 0)
|
||||||
|
{
|
||||||
|
hConnect = WinHttpConnect(w32_http_state->hSession, (WCHAR *)hostname16.str, port, 0);
|
||||||
|
good = (hConnect != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: open request
|
||||||
|
HINTERNET hRequest = 0;
|
||||||
|
if(good)
|
||||||
|
{
|
||||||
|
hRequest = WinHttpOpenRequest(hConnect, verb, path_name, 0, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
|
||||||
|
good = (hRequest != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: fill info
|
||||||
|
if(good)
|
||||||
|
{
|
||||||
|
req->status = W32_HTTP_RequestStatus_PendingSend;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req->status = W32_HTTP_RequestStatus_Failed;
|
||||||
|
}
|
||||||
|
req->hConnect = hConnect;
|
||||||
|
req->hRequest = hRequest;
|
||||||
|
|
||||||
|
//- rjf: send request
|
||||||
|
if(good)
|
||||||
|
{
|
||||||
|
WinHttpSendRequest(hRequest, header, header_size, optional, optional_size, optional_size, (DWORD_PTR)req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
if(free_slot_num == 0 || request_data.size == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lane_sync();
|
||||||
|
|
||||||
|
//- rjf: kick off receives
|
||||||
|
{
|
||||||
|
Rng1U64 range = lane_range(ArrayCount(w32_http_state->active_requests));
|
||||||
|
for EachInRange(idx, range)
|
||||||
|
{
|
||||||
|
W32_HTTP_Request *req = &w32_http_state->active_requests[idx];
|
||||||
|
if(req->active && ins_atomic_u32_eval(&req->status) == W32_HTTP_RequestStatus_Sent)
|
||||||
|
{
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_PendingRecv);
|
||||||
|
WinHttpReceiveResponse(req->hRequest, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: kick off body size queries
|
||||||
|
{
|
||||||
|
Rng1U64 range = lane_range(ArrayCount(w32_http_state->active_requests));
|
||||||
|
for EachInRange(idx, range)
|
||||||
|
{
|
||||||
|
W32_HTTP_Request *req = &w32_http_state->active_requests[idx];
|
||||||
|
if(req->active && ins_atomic_u32_eval(&req->status) == W32_HTTP_RequestStatus_Recvd)
|
||||||
|
{
|
||||||
|
if(req->next_body_piece_size != 0)
|
||||||
|
{
|
||||||
|
str8_list_push(req->arena, &req->finished_body_pieces, str8((U8 *)req->next_body_piece, req->next_body_piece_size));
|
||||||
|
}
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_PendingDataSize);
|
||||||
|
WinHttpQueryDataAvailable(req->hRequest, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: kick off body reads
|
||||||
|
{
|
||||||
|
Rng1U64 range = lane_range(ArrayCount(w32_http_state->active_requests));
|
||||||
|
for EachInRange(idx, range)
|
||||||
|
{
|
||||||
|
W32_HTTP_Request *req = &w32_http_state->active_requests[idx];
|
||||||
|
if(req->active && ins_atomic_u32_eval(&req->status) == W32_HTTP_RequestStatus_DataSized)
|
||||||
|
{
|
||||||
|
req->next_body_piece = push_array(req->arena, U8, req->next_body_piece_size);
|
||||||
|
ins_atomic_u32_eval_assign(&req->status, W32_HTTP_RequestStatus_PendingRead);
|
||||||
|
WinHttpReadData(req->hRequest, req->next_body_piece, req->next_body_piece_size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: complete requests
|
||||||
|
{
|
||||||
|
Rng1U64 range = lane_range(ArrayCount(w32_http_state->active_requests));
|
||||||
|
for EachInRange(idx, range)
|
||||||
|
{
|
||||||
|
W32_HTTP_Request *req = &w32_http_state->active_requests[idx];
|
||||||
|
W32_HTTP_RequestStatus status = ins_atomic_u32_eval(&req->status);
|
||||||
|
if(req->active &&
|
||||||
|
(status == W32_HTTP_RequestStatus_Done ||
|
||||||
|
status == W32_HTTP_RequestStatus_Failed))
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
B32 good = (status == W32_HTTP_RequestStatus_Done);
|
||||||
|
|
||||||
|
//- rjf: unpack
|
||||||
|
HINTERNET hRequest = req->hRequest;
|
||||||
|
|
||||||
|
//- rjf: read response code
|
||||||
|
HTTP_StatusCode code = 0;
|
||||||
|
if(good)
|
||||||
|
{
|
||||||
|
DWORD status_code = 0;
|
||||||
|
DWORD status_code_size = sizeof(status_code);
|
||||||
|
WinHttpQueryHeaders(hRequest,
|
||||||
|
WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
|
||||||
|
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||||
|
&status_code, &status_code_size, WINHTTP_NO_HEADER_INDEX);
|
||||||
|
code = status_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: serialize response
|
||||||
|
String8 response_data = {0};
|
||||||
|
U64 response_data_min_size = sizeof(U64) + sizeof(U64) + sizeof(HTTP_StatusCode) + sizeof(U64);
|
||||||
|
U64 response_data_max_size = req->out_ring->ring->size;
|
||||||
|
B32 response_is_possible = (response_data_min_size < response_data_max_size);
|
||||||
|
if(response_is_possible)
|
||||||
|
{
|
||||||
|
U64 body_size = req->finished_body_pieces.total_size;
|
||||||
|
String8List pieces = {0};
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(&req->id));
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(&code));
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(&body_size));
|
||||||
|
str8_list_concat_in_place(&pieces, &req->finished_body_pieces);
|
||||||
|
U64 data_size = pieces.total_size;
|
||||||
|
str8_list_push_front(scratch.arena, &pieces, str8_struct(&data_size));
|
||||||
|
if(data_size + sizeof(U64) > response_data_max_size)
|
||||||
|
{
|
||||||
|
U64 overkill = data_size + sizeof(U64) - response_data_max_size;
|
||||||
|
data_size -= overkill;
|
||||||
|
}
|
||||||
|
response_data = str8_list_join(scratch.arena, &pieces, 0);
|
||||||
|
response_data.size = data_size + sizeof(U64);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: write response
|
||||||
|
if(response_is_possible)
|
||||||
|
{
|
||||||
|
RingGuard g = guarded_ring_open(req->out_ring);
|
||||||
|
guarded_ring_write_string_or_wait(&g, response_data, max_U64);
|
||||||
|
guarded_ring_close(&g);
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: free this request slot
|
||||||
|
req->active = 0;
|
||||||
|
arena_clear(req->arena);
|
||||||
|
MemoryZeroStruct(&req->finished_body_pieces);
|
||||||
|
req->next_body_piece = 0;
|
||||||
|
req->next_body_piece_size = 0;
|
||||||
|
WinHttpCloseHandle(req->hConnect);
|
||||||
|
WinHttpCloseHandle(req->hRequest);
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: @per_os_impl I/O Ring Functions
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
http_push_request(GuardedRing *out_ring, HTTP_RequestParams *params, U64 endt_us)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
B32 result = 0;
|
||||||
|
|
||||||
|
// rjf: serialize
|
||||||
|
String8 data = {0};
|
||||||
|
{
|
||||||
|
String8List pieces = {0};
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(&out_ring));
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->id));
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->method));
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->url.size));
|
||||||
|
str8_list_push(scratch.arena, &pieces, params->url);
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->body.size));
|
||||||
|
str8_list_push(scratch.arena, &pieces, params->body);
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->user_agent.size));
|
||||||
|
str8_list_push(scratch.arena, &pieces, params->user_agent);
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->authorization.size));
|
||||||
|
str8_list_push(scratch.arena, &pieces, params->authorization);
|
||||||
|
str8_list_push(scratch.arena, &pieces, str8_struct(¶ms->content_type.size));
|
||||||
|
str8_list_push(scratch.arena, &pieces, params->content_type);
|
||||||
|
U64 data_size = pieces.total_size;
|
||||||
|
str8_list_push_front(scratch.arena, &pieces, str8_struct(&data_size));
|
||||||
|
data = str8_list_join(scratch.arena, &pieces, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: write
|
||||||
|
if(data.size < w32_http_state->request_ring->ring->size)
|
||||||
|
{
|
||||||
|
RingGuard g = guarded_ring_open(w32_http_state->request_ring);
|
||||||
|
result = guarded_ring_write_string_or_wait(&g, data, endt_us);
|
||||||
|
guarded_ring_close(&g);
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
http_pop_response(Arena *arena, GuardedRing *out_ring, HTTP_Response *response_out, U64 endt_us)
|
||||||
|
{
|
||||||
|
U64 data_size = 0;
|
||||||
|
RingGuard g = guarded_ring_open(out_ring);
|
||||||
|
B32 result = guarded_ring_read_struct_or_wait(&g, &data_size, endt_us);
|
||||||
|
if(result)
|
||||||
|
{
|
||||||
|
String8 data = {0};
|
||||||
|
data.size = data_size;
|
||||||
|
data.str = push_array(arena, U8, data.size);
|
||||||
|
guarded_ring_read_or_wait(&g, data.size, data.str, max_U64);
|
||||||
|
U64 off = 0;
|
||||||
|
off += str8_deserial_read_struct(data, off, &response_out->id);
|
||||||
|
off += str8_deserial_read_struct(data, off, &response_out->code);
|
||||||
|
off += str8_deserial_read_struct(data, off, &response_out->body.size);
|
||||||
|
response_out->body.str = push_array(arena, U8, response_out->body.size);
|
||||||
|
off += str8_deserial_read(data, off, response_out->body.str, response_out->body.size, 1);
|
||||||
|
}
|
||||||
|
guarded_ring_close(&g);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef WIN32_HTTP_H
|
||||||
|
#define WIN32_HTTP_H
|
||||||
|
|
||||||
|
#include <winhttp.h>
|
||||||
|
#pragma comment(lib, "winhttp")
|
||||||
|
|
||||||
|
typedef enum W32_HTTP_RequestStatus
|
||||||
|
{
|
||||||
|
W32_HTTP_RequestStatus_Null,
|
||||||
|
W32_HTTP_RequestStatus_PendingSend,
|
||||||
|
W32_HTTP_RequestStatus_Sent,
|
||||||
|
W32_HTTP_RequestStatus_PendingRecv,
|
||||||
|
W32_HTTP_RequestStatus_Recvd,
|
||||||
|
W32_HTTP_RequestStatus_PendingDataSize,
|
||||||
|
W32_HTTP_RequestStatus_DataSized,
|
||||||
|
W32_HTTP_RequestStatus_PendingRead,
|
||||||
|
W32_HTTP_RequestStatus_Done,
|
||||||
|
W32_HTTP_RequestStatus_Failed,
|
||||||
|
}
|
||||||
|
W32_HTTP_RequestStatus;
|
||||||
|
|
||||||
|
typedef struct W32_HTTP_Request W32_HTTP_Request;
|
||||||
|
struct W32_HTTP_Request
|
||||||
|
{
|
||||||
|
B32 active;
|
||||||
|
Arena *arena;
|
||||||
|
GuardedRing *out_ring;
|
||||||
|
U64 id;
|
||||||
|
W32_HTTP_RequestStatus status;
|
||||||
|
HINTERNET hConnect;
|
||||||
|
HINTERNET hRequest;
|
||||||
|
void *optional; // NOTE(rjf): must persist with in-flight requests
|
||||||
|
U64 optional_size;
|
||||||
|
String8List finished_body_pieces;
|
||||||
|
void *next_body_piece;
|
||||||
|
U64 next_body_piece_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct W32_HTTP_State W32_HTTP_State;
|
||||||
|
struct W32_HTTP_State
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
HINTERNET hSession;
|
||||||
|
GuardedRing *request_ring;
|
||||||
|
W32_HTTP_Request active_requests[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
global W32_HTTP_State *w32_http_state = 0;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: Status Callback
|
||||||
|
|
||||||
|
internal void w32_http_status_callback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, void *lpvStatusInformation, DWORD dwStatusInformationLength);
|
||||||
|
|
||||||
|
#endif // WIN32_HTTP_H
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal void
|
||||||
|
smsv_init(void)
|
||||||
|
{
|
||||||
|
Arena *arena = arena_alloc();
|
||||||
|
w32_smsv_state = push_array(arena, W32_SMSV_State, 1);
|
||||||
|
w32_smsv_state->arena = arena;
|
||||||
|
{
|
||||||
|
// rjf: extract parameterizations from _NT_SYMBOL_PATH
|
||||||
|
{
|
||||||
|
// rjf: get rules string from environment
|
||||||
|
String8 rules = {0};
|
||||||
|
for EachNode(n, String8Node, get_process_info()->environment.first)
|
||||||
|
{
|
||||||
|
String8 string = n->string;
|
||||||
|
if(str8_match(string, s("_NT_SYMBOL_PATH="), StringMatchFlag_RightSideSloppy))
|
||||||
|
{
|
||||||
|
rules = str8_skip(string, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: parse rules string
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
if(str8_match(rules, s("srv*"), StringMatchFlag_RightSideSloppy))
|
||||||
|
{
|
||||||
|
String8List parts = str8_split(scratch.arena, rules, (U8 *)"*", 1, 0);
|
||||||
|
for EachNode(n, String8Node, parts.first)
|
||||||
|
{
|
||||||
|
PathStyle style = path_style_from_str8(n->string);
|
||||||
|
if(w32_smsv_state->symbol_cache_path.size != 0 && style == PathStyle_WindowsAbsolute)
|
||||||
|
{
|
||||||
|
w32_smsv_state->symbol_cache_path = n->string;
|
||||||
|
}
|
||||||
|
else if(str8_match(n->string, s("https://"), StringMatchFlag_RightSideSloppy) ||
|
||||||
|
str8_match(n->string, s("http://"), StringMatchFlag_RightSideSloppy))
|
||||||
|
{
|
||||||
|
str8_list_push(arena, &w32_smsv_state->symbol_server_urls, n->string);
|
||||||
|
}
|
||||||
|
else if(str8_match(n->string, s("\\\\"), StringMatchFlag_RightSideSloppy))
|
||||||
|
{
|
||||||
|
// TODO(rjf): network share; currently unsupported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
w32_smsv_state->symbol_cache_path = str8_skip_chop_whitespace(rules);
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: always fall back to public MS server
|
||||||
|
{
|
||||||
|
String8 public_ms_server = s("https://msdl.microsoft.com/download/symbols");
|
||||||
|
B32 public_ms_server_already_present = 0;
|
||||||
|
for EachNode(n, String8Node, w32_smsv_state->symbol_server_urls.first)
|
||||||
|
{
|
||||||
|
if(str8_match(public_ms_server, n->string, 0))
|
||||||
|
{
|
||||||
|
public_ms_server_already_present = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!public_ms_server_already_present)
|
||||||
|
{
|
||||||
|
str8_list_push(arena, &w32_smsv_state->symbol_server_urls, public_ms_server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf fall back to using local appdata temp symbol cache folder
|
||||||
|
if(w32_smsv_state->symbol_cache_path.size == 0)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
U64 size = KB(32);
|
||||||
|
U16 *buffer = push_array_no_zero(scratch.arena, U16, size);
|
||||||
|
if(SUCCEEDED(SHGetFolderPathW(0, CSIDL_LOCAL_APPDATA, 0, 0, (WCHAR*)buffer)))
|
||||||
|
{
|
||||||
|
String8 local_appdata = str8_from_16(scratch.arena, str16_cstring(buffer));
|
||||||
|
w32_smsv_state->symbol_cache_path = str8f(arena, "%S\\Temp\\SymbolCache", local_appdata);
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
smsv_local_path_from_key(Arena *arena, String8 module_name, String8 dbg_name, Guid guid, U64 age)
|
||||||
|
{
|
||||||
|
String8 result = {0};
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
{
|
||||||
|
// rjf: form unique identifier based on guid
|
||||||
|
String8 debug_info_unique_identifier = {0};
|
||||||
|
{
|
||||||
|
debug_info_unique_identifier = str8f(scratch.arena, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x",
|
||||||
|
guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7], age);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rjf: form full path
|
||||||
|
if(debug_info_unique_identifier.size != 0)
|
||||||
|
{
|
||||||
|
// TODO(rjf): assuming 'stripped' for now
|
||||||
|
String8 symbol_cache_path = w32_smsv_state->symbol_cache_path;
|
||||||
|
String8 path = str8f(scratch.arena, "%S/%S/%S/stripped/%S", symbol_cache_path, module_name, debug_info_unique_identifier, dbg_name);
|
||||||
|
result = path_normalized_from_string(arena, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef WIN32_SYMBOL_SERVER_H
|
||||||
|
#define WIN32_SYMBOL_SERVER_H
|
||||||
|
|
||||||
|
typedef struct W32_SMSV_State W32_SMSV_State;
|
||||||
|
struct W32_SMSV_State
|
||||||
|
{
|
||||||
|
Arena *arena;
|
||||||
|
String8 symbol_cache_path;
|
||||||
|
String8List symbol_server_urls;
|
||||||
|
};
|
||||||
|
|
||||||
|
global W32_SMSV_State *w32_smsv_state = 0;
|
||||||
|
|
||||||
|
#endif // WIN32_SYMBOL_SERVER_H
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
// raddbg 0.9.27 project file
|
||||||
|
|
||||||
Reference in New Issue
Block a user