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:
Ryan Fleury
2026-06-08 11:10:14 -07:00
parent 1ef94cb759
commit 5c664261a3
38 changed files with 1347 additions and 81 deletions
+1 -1
View File
@@ -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, },
+3 -3
View File
@@ -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);
{ {
+5 -5
View File
@@ -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
+9
View File
@@ -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
+1 -1
View File
@@ -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;
} }
} }
+1
View File
@@ -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"
+1
View File
@@ -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"
-1
View File
@@ -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;
}; };
+135
View File
@@ -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;
}
+56
View File
@@ -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
+11 -29
View File
@@ -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;
} }
-2
View File
@@ -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;
}; };
+33
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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
+14
View File
@@ -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
+22
View File
@@ -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;
}
+7
View File
@@ -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
+8 -8
View File
@@ -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);
+4 -2
View File
@@ -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 }},
+3 -1
View File
@@ -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 }
+87 -4
View File
@@ -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;
+5
View File
@@ -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;
+9 -4
View File
@@ -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)
+2 -2
View File
@@ -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);
+2
View File
@@ -0,0 +1,2 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
+10
View File
@@ -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
+9
View File
@@ -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
+14
View File
@@ -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
+13
View File
@@ -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("");
}
+7
View File
@@ -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
+4
View File
@@ -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);
-18
View File
@@ -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
+501
View File
@@ -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, &params.id);
off += str8_deserial_read_struct(request_data, off, &params.method);
off += str8_deserial_read_struct(request_data, off, &params.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, &params.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, &params.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, &params.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, &params.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(&params->id));
str8_list_push(scratch.arena, &pieces, str8_struct(&params->method));
str8_list_push(scratch.arena, &pieces, str8_struct(&params->url.size));
str8_list_push(scratch.arena, &pieces, params->url);
str8_list_push(scratch.arena, &pieces, str8_struct(&params->body.size));
str8_list_push(scratch.arena, &pieces, params->body);
str8_list_push(scratch.arena, &pieces, str8_struct(&params->user_agent.size));
str8_list_push(scratch.arena, &pieces, params->user_agent);
str8_list_push(scratch.arena, &pieces, str8_struct(&params->authorization.size));
str8_list_push(scratch.arena, &pieces, params->authorization);
str8_list_push(scratch.arena, &pieces, str8_struct(&params->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;
}
+58
View File
@@ -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
+2
View File
@@ -0,0 +1,2 @@
// raddbg 0.9.27 project file