TargetControl(Network::Socket *sock, string clientName, bool forceConnection, bool localhost) : m_Socket(sock), m_Local(localhost) { PacketType type; vector<byte> payload; m_PID = 0; { Serialiser ser("", Serialiser::WRITING, false); ser.SerialiseString("", clientName); ser.Serialise("", forceConnection); if(!SendPacket(m_Socket, ePacket_Handshake, ser)) { SAFE_DELETE(m_Socket); return; } } Serialiser *ser = NULL; GetPacket(type, ser); // failed handshaking if(m_Socket == NULL || ser == NULL) return; RDCASSERT(type == ePacket_Handshake || type == ePacket_Busy); if(type == ePacket_Handshake) { ser->Serialise("", m_Target); ser->Serialise("", m_API); ser->Serialise("", m_PID); RDCLOG("Got remote handshake: %s (%s) [%u]", m_Target.c_str(), m_API.c_str(), m_PID); } else if(type == ePacket_Busy) { ser->Serialise("", m_Target); ser->Serialise("", m_API); ser->Serialise("", m_BusyClient); RDCLOG("Got remote busy signal: %s (%s) owned by %s", m_Target.c_str(), m_API.c_str(), m_BusyClient.c_str()); } SAFE_DELETE(ser); }
RemoteRenderer(Network::Socket *sock) : m_Socket(sock) { map<RDCDriver,wstring> m = RenderDoc::Inst().GetReplayDrivers(); m_Proxies.reserve(m.size()); for(auto it=m.begin(); it != m.end(); ++it) m_Proxies.push_back(*it); { PacketType type; Serialiser *ser = NULL; GetPacket(type, &ser); m.clear(); if(ser) { uint32_t count = 0; ser->Serialise("", count); for(uint32_t i=0; i < count; i++) { RDCDriver driver = RDC_Unknown; wstring name = L""; ser->Serialise("", driver); ser->Serialise("", name); m[driver] = name; } delete ser; } } m_RemoteDrivers.reserve(m.size()); for(auto it=m.begin(); it != m.end(); ++it) m_RemoteDrivers.push_back(*it); m_ProxyDriver = NULL; m_ProxySerialiser = NULL; }
ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const char *logfile, float *progress, ReplayRenderer **rend) { if(rend == NULL) return eReplayCreate_InternalError; if(proxyid >= m_Proxies.size()) { RDCERR("Invalid proxy driver id %d specified for remote renderer", proxyid); return eReplayCreate_InternalError; } float dummy = 0.0f; if(progress == NULL) progress = &dummy; RDCDriver proxydrivertype = m_Proxies[proxyid].first; Serialiser ser("", Serialiser::WRITING, false); if(!SendChunkedFile(m_Socket, ePacket_CopyCapture, logfile, ser, progress)) { SAFE_DELETE(m_Socket); return eReplayCreate_NetworkIOFailed; } RDCLOG("Sent file to replay host. Loading..."); PacketType type = ePacket_Noop; while(m_Socket) { Serialiser *progressSer; GetPacket(type, &progressSer); if(!m_Socket || type != ePacket_LogOpenProgress) break; progressSer->Serialise("", *progress); RDCLOG("% 3.0f%%...", (*progress)*100.0f); } if(!m_Socket || type != ePacket_LogReady) return eReplayCreate_NetworkIOFailed; *progress = 1.0f; RDCLOG("Log ready on replay host"); IReplayDriver *proxyDriver = NULL; auto status = RenderDoc::Inst().CreateReplayDriver(proxydrivertype, NULL, &proxyDriver); if(status != eReplayCreate_Success || !proxyDriver) { if(proxyDriver) proxyDriver->Shutdown(); return status; } ReplayRenderer *ret = new ReplayRenderer(); ProxySerialiser *proxy = new ProxySerialiser(m_Socket, proxyDriver); status = ret->SetDevice(proxy); if(status != eReplayCreate_Success) { SAFE_DELETE(ret); return status; } // ReplayRenderer takes ownership of the ProxySerialiser (as IReplayDriver) // and it cleans itself up in Shutdown. *rend = ret; return eReplayCreate_Success; }
void ReceiveMessage(RemoteMessage *msg) { if(m_Socket == NULL) { msg->Type = eRemoteMsg_Disconnected; return; } if(!m_Socket->IsRecvDataWaiting()) { if(!m_Socket->Connected()) { SAFE_DELETE(m_Socket); msg->Type = eRemoteMsg_Disconnected; } else { Threading::Sleep(2); msg->Type = eRemoteMsg_Noop; } return; } PacketType type; Serialiser *ser = NULL; GetPacket(type, ser); if(m_Socket == NULL) { SAFE_DELETE(ser); msg->Type = eRemoteMsg_Disconnected; return; } else { if(type == ePacket_Noop) { SAFE_DELETE(ser); msg->Type = eRemoteMsg_Noop; return; } else if(type == ePacket_Busy) { string existingClient; ser->Serialise("", existingClient); SAFE_DELETE(ser); SAFE_DELETE(m_Socket); RDCLOG("Got busy signal: '%s", existingClient.c_str()); msg->Type = eRemoteMsg_Busy; msg->Busy.ClientName = existingClient; return; } else if(type == ePacket_CopyCapture) { msg->Type = eRemoteMsg_CaptureCopied; ser->Serialise("", msg->NewCapture.ID); SAFE_DELETE(ser); msg->NewCapture.localpath = m_CaptureCopies[msg->NewCapture.ID]; if(!RecvChunkedFile(m_Socket, ePacket_CopyCapture, msg->NewCapture.localpath.elems, ser, NULL)) { SAFE_DELETE(ser); SAFE_DELETE(m_Socket); msg->Type = eRemoteMsg_Disconnected; return; } m_CaptureCopies.erase(msg->NewCapture.ID); SAFE_DELETE(ser); return; } else if(type == ePacket_NewChild) { msg->Type = eRemoteMsg_NewChild; ser->Serialise("", msg->NewChild.PID); ser->Serialise("", msg->NewChild.ident); RDCLOG("Got a new child process: %u %u", msg->NewChild.PID, msg->NewChild.ident); SAFE_DELETE(ser); return; } else if(type == ePacket_NewCapture) { msg->Type = eRemoteMsg_NewCapture; ser->Serialise("", msg->NewCapture.ID); ser->Serialise("", msg->NewCapture.timestamp); string path; ser->Serialise("", path); msg->NewCapture.localpath = path; if(!m_Local) msg->NewCapture.localpath = ""; uint32_t thumblen = 0; ser->Serialise("", thumblen); create_array_uninit(msg->NewCapture.thumbnail, thumblen); size_t l = 0; byte *buf = &msg->NewCapture.thumbnail[0]; ser->SerialiseBuffer("", buf, l); RDCLOG("Got a new capture: %d (time %llu) %d byte thumbnail", msg->NewCapture.ID, msg->NewCapture.timestamp, thumblen); SAFE_DELETE(ser); return; } else if(type == ePacket_RegisterAPI) { msg->Type = eRemoteMsg_RegisterAPI; ser->Serialise("", m_API); msg->RegisterAPI.APIName = m_API; RDCLOG("Used API: %s", m_API.c_str()); SAFE_DELETE(ser); return; } } SAFE_DELETE(ser); msg->Type = eRemoteMsg_Noop; }
void RenderDoc::RemoteAccessClientThread(void *s) { Threading::KeepModuleAlive(); Network::Socket *client = (Network::Socket *)s; Serialiser ser("", Serialiser::WRITING, false); string api = ""; RDCDriver driver; RenderDoc::Inst().GetCurrentDriver(driver, api); ser.Rewind(); string target = RenderDoc::Inst().GetCurrentTarget(); ser.Serialise("", target); ser.Serialise("", api); uint32_t mypid = Process::GetCurrentPID(); ser.Serialise("", mypid); if(!SendPacket(client, ePacket_Handshake, ser)) { SAFE_DELETE(client); { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = ""; } Threading::ReleaseModuleExitThread(); return; } const int pingtime = 1000; // ping every 1000ms const int ticktime = 10; // tick every 10ms int curtime = 0; vector<CaptureData> captures; vector<pair<uint32_t, uint32_t> > children; while(client) { if(RenderDoc::Inst().m_RemoteClientThreadShutdown || (client && !client->Connected())) { SAFE_DELETE(client); break; } ser.Rewind(); Threading::Sleep(ticktime); curtime += ticktime; PacketType packetType = ePacket_Noop; string curapi; RenderDoc::Inst().GetCurrentDriver(driver, curapi); vector<CaptureData> caps = RenderDoc::Inst().GetCaptures(); vector<pair<uint32_t, uint32_t> > childprocs = RenderDoc::Inst().GetChildProcesses(); if(curapi != api) { api = curapi; ser.Serialise("", api); packetType = ePacket_RegisterAPI; } else if(caps.size() != captures.size()) { uint32_t idx = (uint32_t)captures.size(); captures.push_back(caps[idx]); packetType = ePacket_NewCapture; std::string path = FileIO::GetFullPathname(captures.back().path); ser.Serialise("", idx); ser.Serialise("", captures.back().timestamp); ser.Serialise("", path); uint32_t len = 0; RENDERDOC_GetThumbnail(captures.back().path.c_str(), NULL, len); byte *thumb = new byte[len]; RENDERDOC_GetThumbnail(captures.back().path.c_str(), thumb, len); size_t l = len; ser.Serialise("", len); ser.SerialiseBuffer("", thumb, l); delete[] thumb; } else if(childprocs.size() != children.size()) { uint32_t idx = (uint32_t)children.size(); children.push_back(childprocs[idx]); packetType = ePacket_NewChild; ser.Serialise("", children.back().first); ser.Serialise("", children.back().second); } if(curtime < pingtime && packetType == ePacket_Noop) { if(client->IsRecvDataWaiting()) { PacketType type; Serialiser *recvser = NULL; if(!RecvPacket(client, type, &recvser)) SAFE_DELETE(client); if(client == NULL) { SAFE_DELETE(recvser); continue; } else if(type == ePacket_TriggerCapture) { RenderDoc::Inst().TriggerCapture(); } else if(type == ePacket_QueueCapture) { uint32_t frameNum = 0; recvser->Serialise("", frameNum); RenderDoc::Inst().QueueCapture(frameNum); } else if(type == ePacket_CopyCapture) { caps = RenderDoc::Inst().GetCaptures(); uint32_t id = 0; recvser->Serialise("", id); if(id < caps.size()) { ser.Serialise("", id); if(!SendPacket(client, ePacket_CopyCapture, ser)) { SAFE_DELETE(client); continue; } ser.Rewind(); if(!SendChunkedFile(client, ePacket_CopyCapture, caps[id].path.c_str(), ser, NULL)) { SAFE_DELETE(client); continue; } RenderDoc::Inst().MarkCaptureRetrieved(id); } } SAFE_DELETE(recvser); } continue; } curtime = 0; if(!SendPacket(client, packetType, ser)) { SAFE_DELETE(client); continue; } } // give up our connection { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = ""; } Threading::ReleaseModuleExitThread(); }
void RenderDoc::RemoteAccessServerThread(void *s) { Threading::KeepModuleAlive(); Network::Socket *sock = (Network::Socket *)s; RenderDoc::Inst().m_SingleClientName = ""; Threading::ThreadHandle clientThread = 0; RenderDoc::Inst().m_RemoteClientThreadShutdown = false; while(!RenderDoc::Inst().m_RemoteServerThreadShutdown) { Network::Socket *client = sock->AcceptClient(false); if(client == NULL) { if(!sock->Connected()) { RDCERR("Error in accept - shutting down server"); SAFE_DELETE(sock); Threading::ReleaseModuleExitThread(); return; } Threading::Sleep(5); continue; } string existingClient; string newClient; bool kick = false; // receive handshake from client and get its name { PacketType type; Serialiser *ser = NULL; if(!RecvPacket(client, type, &ser)) { SAFE_DELETE(ser); SAFE_DELETE(client); continue; } if(type != ePacket_Handshake) { SAFE_DELETE(ser); SAFE_DELETE(client); continue; } ser->SerialiseString("", newClient); ser->Serialise("", kick); SAFE_DELETE(ser); if(newClient.empty()) { SAFE_DELETE(client); continue; } } // see if we have a client { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); existingClient = RenderDoc::Inst().m_SingleClientName; } if(!existingClient.empty() && kick) { // forcibly close communication thread which will kill the connection RenderDoc::Inst().m_RemoteClientThreadShutdown = true; Threading::JoinThread(clientThread); Threading::CloseThread(clientThread); clientThread = 0; RenderDoc::Inst().m_RemoteClientThreadShutdown = false; existingClient = ""; } if(existingClient.empty()) { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = newClient; } // if we've claimed client status, spawn a thread to communicate if(existingClient.empty() || kick) { clientThread = Threading::CreateThread(RemoteAccessClientThread, client); continue; } else { // if we've been asked to kick the existing connection off // reject this connection and tell them who is busy Serialiser ser("", Serialiser::WRITING, false); string api = ""; RDCDriver driver; RenderDoc::Inst().GetCurrentDriver(driver, api); string target = RenderDoc::Inst().GetCurrentTarget(); ser.Serialise("", target); ser.Serialise("", api); ser.SerialiseString("", RenderDoc::Inst().m_SingleClientName); // don't care about errors, we're going to close the connection either way SendPacket(client, ePacket_Busy, ser); SAFE_DELETE(client); } } RenderDoc::Inst().m_RemoteClientThreadShutdown = true; // don't join, just close the thread, as we can't wait while in the middle of module unloading Threading::CloseThread(clientThread); clientThread = 0; Threading::ReleaseModuleExitThread(); }
void RenderDoc::RemoteAccessClientThread(void *s) { Network::Socket *client = (Network::Socket *)s; Serialiser ser(L"", Serialiser::WRITING, false); wstring api = L""; RDCDriver driver; RenderDoc::Inst().GetCurrentDriver(driver, api); ser.Rewind(); wstring target = RenderDoc::Inst().GetCurrentTarget(); ser.Serialise("", target); ser.Serialise("", api); if(!SendPacket(client, ePacket_Handshake, ser)) { SAFE_DELETE(client); { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = L""; } return; } const int pingtime = 1000; // ping every 1000ms const int ticktime = 10; // tick every 10ms int curtime = 0; vector<wstring> captures; while(client) { if(RenderDoc::Inst().m_RemoteClientThreadShutdown || (client && !client->Connected())) { SAFE_DELETE(client); break; } ser.Rewind(); Threading::Sleep(ticktime); curtime += ticktime; PacketType packetType = ePacket_Noop; wstring curapi; RenderDoc::Inst().GetCurrentDriver(driver, curapi); if(curapi != api) { api = curapi; ser.Serialise("", api); packetType = ePacket_RegisterAPI; } else { vector<wstring> caps = RenderDoc::Inst().GetCaptures(); if(caps.size() != captures.size()) { uint32_t idx = (uint32_t)captures.size(); captures.push_back(caps[idx]); packetType = ePacket_NewCapture; uint64_t timestamp = FileIO::GetModifiedTimestamp(captures.back().c_str()); ser.Serialise("", idx); ser.Serialise("", timestamp); ser.Serialise("", captures.back()); uint32_t len = 128*1024; byte *thumb = new byte[len]; RENDERDOC_GetThumbnail(captures.back().c_str(), thumb, len); size_t l = len; ser.Serialise("", len); ser.SerialiseBuffer("", thumb, l); delete[] thumb; } } if(curtime < pingtime && packetType == ePacket_Noop) { if(client->IsRecvDataWaiting()) { PacketType type; Serialiser *recvser = NULL; if(!RecvPacket(client, type, &recvser)) SAFE_DELETE(client); if(client == NULL) { SAFE_DELETE(recvser); continue; } else if(type == ePacket_TriggerCapture) { RenderDoc::Inst().TriggerCapture(); } else if(type == ePacket_QueueCapture) { uint32_t frameNum = 0; recvser->Serialise("", frameNum); RenderDoc::Inst().QueueCapture(frameNum); } else if(type == ePacket_CopyCapture) { vector<wstring> caps = RenderDoc::Inst().GetCaptures(); uint32_t id = 0; recvser->Serialise("", id); if(id < caps.size()) { ser.Serialise("", id); if(!SendPacket(client, ePacket_CopyCapture, ser)) { SAFE_DELETE(client); continue; } ser.Rewind(); if(!SendChunkedFile(client, ePacket_CopyCapture, caps[id].c_str(), ser, NULL)) { SAFE_DELETE(client); continue; } RenderDoc::Inst().MarkCaptureRetrieved(id); } } SAFE_DELETE(recvser); } continue; } curtime = 0; if(!SendPacket(client, packetType, ser)) { SAFE_DELETE(client); continue; } } // give up our connection { SCOPED_LOCK(RenderDoc::Inst().m_SingleClientLock); RenderDoc::Inst().m_SingleClientName = L""; } }