From cd6bee6d7e290d61911eb9efbceaacd1efdcde52 Mon Sep 17 00:00:00 2001 From: Peter Slattery Date: Sat, 30 Jan 2021 14:01:04 -0800 Subject: [PATCH] Finished preliminary socket layer and win32 implementation. --- src/app/blumen_lumen.cpp | 62 ++++++++++++++++--- src/app/blumen_lumen.h | 14 +++++ .../foldhaus_panel_animation_timeline.h | 8 +-- src/app/foldhaus_app.cpp | 19 +++--- src/app/interface.h | 2 +- src/app/platform_win32/win32_foldhaus.cpp | 5 +- .../platform_win32/win32_foldhaus_socket.h | 41 +++++++++++- src/app/platform_win32/win32_test_code.cpp | 10 ++- src/gs_libs/gs_types.cpp | 28 ++++++++- src/gs_libs/gs_types.h | 4 ++ 10 files changed, 163 insertions(+), 30 deletions(-) diff --git a/src/app/blumen_lumen.cpp b/src/app/blumen_lumen.cpp index 0467e8a..667b997 100644 --- a/src/app/blumen_lumen.cpp +++ b/src/app/blumen_lumen.cpp @@ -10,9 +10,13 @@ BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData) { mic_listen_job_data* Data = (mic_listen_job_data*)UserData; + gs_data Msg = {}; + while (true) { - gs_data Msg = SocketRecieve(Data->SocketManager, Data->ListenSocket, Ctx->Transient); +#if 0 + // TODO(pjs): Make this a peek operation + Msg = SocketRecieve(Data->SocketManager, Data->ListenSocket, Ctx->Transient); if (Msg.Size > 0) { OutputDebugStringA("Listened"); @@ -22,6 +26,23 @@ BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData) Data->MicPacketBuffer->WriteHead = 0; } } +#endif + + while (Data->OutgoingMsgQueue->ReadHead != Data->OutgoingMsgQueue->WriteHead) + { + u32 ReadIndex = Data->OutgoingMsgQueue->ReadHead++; + if (Data->OutgoingMsgQueue->ReadHead >= BLUMEN_MESSAGE_QUEUE_COUNT) + { + Data->OutgoingMsgQueue->ReadHead = 0; + } + + Msg = Data->OutgoingMsgQueue->Buffers[ReadIndex]; + u32 Address = 0; + u32 Port = 0; + s32 Flags = 0; + SocketSend(Data->SocketManager, Data->ListenSocket, Address, Port, Msg, Flags); + OutputDebugStringA("Wrote\n"); + } } CloseSocket(Data->SocketManager, Data->ListenSocket); @@ -41,15 +62,13 @@ BlumenLumen_CustomInit(app_state* State, context Context) blumen_lumen_state* BLState = (blumen_lumen_state*)Result.Memory; BLState->MicListenJobData.SocketManager = Context.SocketManager; BLState->MicListenJobData.MicPacketBuffer = &BLState->MicPacketBuffer; + BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue; BLState->MicListenJobData.ListenSocket = CreateSocket(Context.SocketManager, "127.0.0.1", "20185"); BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData); - -#if 1 gs_const_string SculpturePath = ConstString("data/test_blumen.fold"); LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog); -#endif { // Animation PLAYGROUND animation Anim0 = {0}; @@ -122,17 +141,40 @@ BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context) State->AnimationSystem.ActiveAnimationIndex = 2; } - gs_string TempString = PushStringF(State->Transient, 256, "%.*s", 32, Packet.AnimationFileName); - NullTerminate(&TempString); - - OutputDebugStringA("Received\n"); - OutputDebugStringA(TempString.Str); - if (BLState->MicPacketBuffer.ReadHead >= PACKETS_MAX) { BLState->MicPacketBuffer.ReadHead = 0; } } + + if ((BLState->OutgoingMsgQueue.WriteHead >= BLState->OutgoingMsgQueue.ReadHead) || + (BLState->OutgoingMsgQueue.WriteHead < BLState->OutgoingMsgQueue.ReadHead)) + { + u32 WriteIndex = BLState->OutgoingMsgQueue.WriteHead; + if (BLState->OutgoingMsgQueue.WriteHead >= BLUMEN_MESSAGE_QUEUE_COUNT) + { + BLState->OutgoingMsgQueue.WriteHead = 0; + } + + gs_data* Msg = BLState->OutgoingMsgQueue.Buffers + WriteIndex; + if (Msg->Size == 0) + { + *Msg = PushSizeToData(&State->Permanent, sizeof(motor_packet)); + } + motor_packet* Packet = (motor_packet*)Msg->Memory; + Packet->FlowerPositions[0] = 5; + Packet->FlowerPositions[0] = 4; + Packet->FlowerPositions[0] = 9; + + // NOTE(pjs): We increment the write head AFTER we've written so that + // the network thread doesn't think the buffer is ready to send before + // the data is set. We want to avoid the case of: + // 1. Main Thread increments write head to 1 + // 2. Network Thread thinks theres a new message to send at 0 + // 3. Network Thread sends the message at 0 + // 4. Main Thread sets the message at 0 + BLState->OutgoingMsgQueue.WriteHead += 1; + } } diff --git a/src/app/blumen_lumen.h b/src/app/blumen_lumen.h index a59f26d..d5ce452 100644 --- a/src/app/blumen_lumen.h +++ b/src/app/blumen_lumen.h @@ -24,18 +24,32 @@ struct microphone_packet }; #pragma pack(pop) +#define BLUMEN_MESSAGE_QUEUE_COUNT 32 +typedef struct blumen_network_msg_queue +{ + gs_data Buffers[BLUMEN_MESSAGE_QUEUE_COUNT]; + u32 WriteHead; + u32 ReadHead; +} blumen_network_msg_queue; + +// TODO(pjs): Refactor this -> blumen_network_job_state struct mic_listen_job_data { platform_socket_manager* SocketManager; packet_ringbuffer* MicPacketBuffer; platform_socket_handle_ ListenSocket; + + blumen_network_msg_queue* OutgoingMsgQueue; }; struct blumen_lumen_state { packet_ringbuffer MicPacketBuffer; + blumen_network_msg_queue OutgoingMsgQueue; + temp_job_req JobReq; + platform_thread_handle MicListenThread; mic_listen_job_data MicListenJobData; }; diff --git a/src/app/editor/panels/foldhaus_panel_animation_timeline.h b/src/app/editor/panels/foldhaus_panel_animation_timeline.h index 1fb550a..92ee12c 100644 --- a/src/app/editor/panels/foldhaus_panel_animation_timeline.h +++ b/src/app/editor/panels/foldhaus_panel_animation_timeline.h @@ -610,7 +610,7 @@ PlayBar_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* Pan ui_interface* Interface = &State->Interface; ui_PushLayout(Interface, Bounds, LayoutDirection_TopDown, MakeString("PlayBar Layout")); - ui_FillRect(Interface, Bounds, Interface->Style.PanelBGColors[0]); + ui_FillRect(Interface, Bounds, Interface->Style.PanelBG); ui_BeginRow(&State->Interface, 4); { if (ui_Button(Interface, MakeString("Pause"))) @@ -645,7 +645,7 @@ FrameCount_Render(animation_timeline_state* TimelineState, rect2 Bounds, render_ s32 VisibleFrameCount = VisibleFrames.Max - VisibleFrames.Min; - ui_FillRect(Interface, Bounds, Interface->Style.PanelBGColors[0]); + ui_FillRect(Interface, Bounds, Interface->Style.PanelBG); // Frame Ticks u32 TickCount = 10; @@ -692,7 +692,7 @@ LayerList_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel* P ui_interface* Interface = &State->Interface; animation ActiveAnim = *AnimationSystem_GetActiveAnimation(&State->AnimationSystem); - ui_FillRect(Interface, Bounds, Interface->Style.PanelBGColors[0]); + ui_FillRect(Interface, Bounds, Interface->Style.PanelBG); v2 LayerDim = { Rect2Width(Bounds), LAYER_HEIGHT }; rect2 LayerBounds = {0}; @@ -801,7 +801,7 @@ AnimInfoView_Render(animation_timeline_state* TimelineState, rect2 Bounds, panel ui_interface* Interface = &State->Interface; ui_PushLayout(Interface, Bounds, LayoutDirection_TopDown, MakeString("AnimInfo Layout")); - ui_FillRect(&State->Interface, Bounds, Interface->Style.PanelBGColors[0]); + ui_FillRect(&State->Interface, Bounds, Interface->Style.PanelBG); if (ui_BeginLabeledDropdown(Interface, MakeString("Active Animation"), ActiveAnim->Name)) { diff --git a/src/app/foldhaus_app.cpp b/src/app/foldhaus_app.cpp index 12d5bfd..f53a27c 100644 --- a/src/app/foldhaus_app.cpp +++ b/src/app/foldhaus_app.cpp @@ -58,18 +58,15 @@ INITIALIZE_APPLICATION(InitializeApplication) interface_config IConfig = {0}; IConfig.FontSize = 14; - IConfig.PanelBGColors[0] = v4{.3f, .3f, .3f, 1}; - IConfig.PanelBGColors[1] = v4{.4f, .4f, .4f, 1}; - IConfig.PanelBGColors[2] = v4{.5f, .5f, .5f, 1}; - IConfig.PanelBGColors[3] = v4{.6f, .6f, .6f, 1}; + IConfig.PanelBG = v4{ .3f, .3f, .3f, 1.f }; IConfig.ButtonColor_Inactive = BlackV4; - IConfig.ButtonColor_Active = v4{.1f, .1f, .1f, 1}; - IConfig.ButtonColor_Selected = v4{.3f, .3f, .3f, 1}; - IConfig.TextColor = WhiteV4; - IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; - IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; - IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; - IConfig.ListBGSelected = v4{.44f, .44f, .44f, 1.f }; + IConfig.ButtonColor_Active = v4{ .1f, .1f, .1f, 1.f }; + IConfig.ButtonColor_Selected = v4{ .3f, .3f, .3f, 1.f }; + IConfig.TextColor = WhiteV4; + IConfig.ListBGColors[0] = v4{ .16f, .16f, .16f, 1.f }; + IConfig.ListBGColors[1] = v4{ .18f, .18f, .18f, 1.f }; + IConfig.ListBGHover = v4{ .22f, .22f, .22f, 1.f }; + IConfig.ListBGSelected = v4{ .44f, .44f, .44f, 1.f }; IConfig.Margin = v2{5, 5}; State->Interface = ui_InterfaceCreate(Context, IConfig, &State->Permanent); diff --git a/src/app/interface.h b/src/app/interface.h index ee846c1..34cf505 100644 --- a/src/app/interface.h +++ b/src/app/interface.h @@ -315,7 +315,7 @@ struct ui_eval_result struct interface_config { - v4 PanelBGColors[4]; + v4 PanelBG; // TODO(pjs): Turn these into _Default, _Hot, _Active v4 ButtonColor_Inactive, ButtonColor_Active, ButtonColor_Selected; diff --git a/src/app/platform_win32/win32_foldhaus.cpp b/src/app/platform_win32/win32_foldhaus.cpp index 4b4a612..9877fa3 100644 --- a/src/app/platform_win32/win32_foldhaus.cpp +++ b/src/app/platform_win32/win32_foldhaus.cpp @@ -497,7 +497,7 @@ WinMain ( *Context.ThreadManager = CreatePlatformThreadManager(Win32CreateThread, Win32KillThread); Context.SocketManager = PushStruct(&PlatformPermanent, platform_socket_manager); - *Context.SocketManager = CreatePlatformSocketManager(Win32CreateSocket, Win32CloseSocket, Win32SocketReceive); + *Context.SocketManager = CreatePlatformSocketManager(Win32CreateSocket, Win32CloseSocket, Win32SocketReceive, Win32SocketSend); win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true)) { return -1; } @@ -512,6 +512,8 @@ WinMain ( addressed_data_buffer_list OutputData = AddressedDataBufferList_Create(ThreadContext); + Context.InitializeApplication(Context); + Running = true; Context.WindowIsVisible = true; while (Running) @@ -588,6 +590,7 @@ WinMain ( Win32SocketSystem_Cleanup(); Win32WorkQueue_Cleanup(); + Win32_TestCode_SocketReading_Cleanup(); return 0; } diff --git a/src/app/platform_win32/win32_foldhaus_socket.h b/src/app/platform_win32/win32_foldhaus_socket.h index 43d5dbc..adce909 100644 --- a/src/app/platform_win32/win32_foldhaus_socket.h +++ b/src/app/platform_win32/win32_foldhaus_socket.h @@ -226,6 +226,34 @@ Win32SocketReceive(platform_socket* Socket, gs_memory_arena* Storage) #endif } +internal s32 +Win32SocketSend(platform_socket* Socket, u32 Address, u32 Port, gs_data Data, s32 Flags) +{ + SOCKET* Win32Sock = (SOCKET*)Socket->PlatformHandle; + + sockaddr_in SockAddress = {}; + SockAddress.sin_family = AF_INET; + SockAddress.sin_port = HostToNetU16(Port); + SockAddress.sin_addr.s_addr = HostToNetU32(Address); + + s32 LengthSent = sendto(*Win32Sock, (char*)Data.Memory, Data.Size, Flags, (sockaddr*)&SockAddress, sizeof(sockaddr_in)); + + if (LengthSent == SOCKET_ERROR) + { + s32 Error = WSAGetLastError(); + if (Error == 10051) + { + } + else + { + // TODO(Peter): :ErrorLogging + InvalidCodePath; + } + } + + return LengthSent; +} + internal s32 Win32Socket_SetOption(win32_socket* Socket, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength) { @@ -323,7 +351,18 @@ Win32Socket_Receive(win32_socket* Socket, gs_memory_arena* Storage) { // TODO(pjs): Error logging s32 Error = WSAGetLastError(); - InvalidCodePath; + if (Error == 10053) + { + // WSAECONNABORTED - aborted by the software + } + else if (Error == 10093) + { + // WSANOTINITIALISED + } + else + { + InvalidCodePath; + } } Result.Size = BytesReceived; return Result; diff --git a/src/app/platform_win32/win32_test_code.cpp b/src/app/platform_win32/win32_test_code.cpp index 8173e73..8c23153 100644 --- a/src/app/platform_win32/win32_test_code.cpp +++ b/src/app/platform_win32/win32_test_code.cpp @@ -35,6 +35,7 @@ Win32_TestCode_UART(gs_thread_context ThreadContext) #endif win32_socket ListenSocket; +HANDLE ListenThread; DWORD WINAPI Win32_TestCode_ListenThreadProc(LPVOID ThreadData) @@ -54,7 +55,7 @@ Win32_TestCode_SocketReading(gs_thread_context ThreadContext, temp_job_req* Req) { ListenSocket = Win32Socket_ConnectToAddress("127.0.0.1", "20185"); u8* Arg = (u8*)Req; - HANDLE Handle = CreateThread(0, 0, &Win32_TestCode_ListenThreadProc, Arg, 0, 0); + ListenThread = CreateThread(0, 0, &Win32_TestCode_ListenThreadProc, Arg, 0, 0); } internal void @@ -74,5 +75,12 @@ BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData) } } +internal void +Win32_TestCode_SocketReading_Cleanup() +{ + TerminateThread(ListenThread, 0); + Win32Socket_Close(&ListenSocket); +} + #define WIN32_TEST_CODE_CPP #endif // WIN32_TEST_CODE_CPP \ No newline at end of file diff --git a/src/gs_libs/gs_types.cpp b/src/gs_libs/gs_types.cpp index 91f2b03..cff4d8c 100644 --- a/src/gs_libs/gs_types.cpp +++ b/src/gs_libs/gs_types.cpp @@ -3364,16 +3364,22 @@ SOCKET_RECEIVE(PlatformSocketRecieve_Stub) return {}; } +SOCKET_SEND(PlatformSocketSend_Stub) +{ + return false; +} internal platform_socket_manager CreatePlatformSocketManager(platform_create_socket* CreateSocketProc, platform_close_socket* CloseSocketProc, - platform_socket_receive* SocketRecieveProc) + platform_socket_receive* SocketRecieveProc, + platform_socket_send* SocketSendProc) { platform_socket_manager Result = {}; Result.CreateSocketProc = CreateSocketProc; Result.CloseSocketProc = CloseSocketProc; Result.SocketRecieveProc = SocketRecieveProc; + Result.SocketSendProc = SocketSendProc; if (!CreateSocketProc) { @@ -3387,6 +3393,10 @@ CreatePlatformSocketManager(platform_create_socket* CreateSocketProc, { Result.SocketRecieveProc = PlatformSocketRecieve_Stub; } + if (!SocketSendProc) + { + Result.SocketSendProc = PlatformSocketSend_Stub; + } return Result; } @@ -3440,6 +3450,22 @@ SocketRecieve(platform_socket_manager* Manager, platform_socket_handle_ SocketHa return Result; } +internal bool +SocketSend(platform_socket_manager* Manager, platform_socket_handle_ SocketHandle, u32 Address, u32 Port, gs_data Data, s32 Flags) +{ + bool Result = false; + if (Manager->SocketsUsed[SocketHandle.Index]) + { + platform_socket* Socket = &Manager->Sockets[SocketHandle.Index]; + if (Socket->PlatformHandle != 0) + { + s32 SizeSent = Manager->SocketSendProc(Socket, Address, Port, Data, Flags); + Result = (SizeSent == Data.Size); + } + } + return Result; +} + /////////////////////////// // // Hashes diff --git a/src/gs_libs/gs_types.h b/src/gs_libs/gs_types.h index 2cdd56b..3b29abe 100644 --- a/src/gs_libs/gs_types.h +++ b/src/gs_libs/gs_types.h @@ -1107,6 +1107,9 @@ typedef CLOSE_SOCKET(platform_close_socket); #define SOCKET_RECEIVE(name) gs_data name(platform_socket* Socket, gs_memory_arena* Storage) typedef SOCKET_RECEIVE(platform_socket_receive); +#define SOCKET_SEND(name) s32 name(platform_socket* Socket, u32 Address, u32 Port, gs_data Data, s32 Flags) +typedef SOCKET_SEND(platform_socket_send); + #define SOCKETS_COUNT_MAX 32 typedef struct platform_socket_manager { @@ -1116,6 +1119,7 @@ typedef struct platform_socket_manager platform_create_socket* CreateSocketProc; platform_close_socket* CloseSocketProc; platform_socket_receive* SocketRecieveProc; + platform_socket_send* SocketSendProc; } platform_socket_manager; #define GS_TYPES_H #endif // GS_TYPES_H \ No newline at end of file