#include "PassiveSocket.h" // Include header for active socket object definition #include #include "../../CommonInterfaces/CommonGUIHelperInterface.h" #include "Bullet3Common/b3CommandLineArgs.h" #ifdef NO_SHARED_MEMORY #include "PhysicsServerCommandProcessor.h" typedef PhysicsServerCommandProcessor MyCommandProcessor; #else #include "SharedMemoryCommandProcessor.h" typedef SharedMemoryCommandProcessor MyCommandProcessor; #endif //NO_SHARED_MEMORY #include "SharedMemoryCommands.h" #include "Bullet3Common/b3AlignedObjectArray.h" #include "PhysicsServerCommandProcessor.h" #include "../Utils/b3Clock.h" bool gVerboseNetworkMessagesServer = true; void MySerializeInt(unsigned int sz, unsigned char* output) { unsigned int tmp = sz; output[0] = tmp & 255; tmp = tmp >> 8; output[1] = tmp & 255; tmp = tmp >> 8; output[2] = tmp & 255; tmp = tmp >> 8; output[3] = tmp & 255; } int main(int argc, char* argv[]) { b3CommandLineArgs parseArgs(argc, argv); b3Clock clock; double timeOutInSeconds = 10; DummyGUIHelper guiHelper; MyCommandProcessor* sm = new MyCommandProcessor; sm->setGuiHelper(&guiHelper); int port = 6667; parseArgs.GetCmdLineArgument("port", port); gVerboseNetworkMessagesServer = parseArgs.CheckCmdLineFlag("verbose"); #ifndef NO_SHARED_MEMORY int key = 0; if (parseArgs.GetCmdLineArgument("sharedMemoryKey", key)) { sm->setSharedMemoryKey(key); } #endif //NO_SHARED_MEMORY bool isPhysicsClientConnected = sm->connect(); bool exitRequested = false; if (isPhysicsClientConnected) { printf("Starting TCP server using port %d\n", port); CPassiveSocket socket; CActiveSocket* pClient = NULL; //-------------------------------------------------------------------------- // Initialize our socket object //-------------------------------------------------------------------------- socket.Initialize(); socket.Listen("localhost", port); //socket.SetBlocking(); int curNumErr = 0; while (!exitRequested) { b3Clock::usleep(0); if ((pClient = socket.Accept()) != NULL) { b3AlignedObjectArray bytesReceived; int clientPort = socket.GetClientPort(); printf("connected from %s:%d\n", socket.GetClientAddr(), clientPort); if (pClient->Receive(4)) { int clientKey = *(int*)pClient->GetData(); if (clientKey == SHARED_MEMORY_MAGIC_NUMBER) { printf("Client version OK %d\n", clientKey); } else { printf("Server version (%d) mismatches Client Version (%d)\n", SHARED_MEMORY_MAGIC_NUMBER, clientKey); continue; } } //---------------------------------------------------------------------- // Receive request from the client. //---------------------------------------------------------------------- while (1) { //printf("try receive\n"); bool receivedData = false; int maxLen = 4 + sizeof(SharedMemoryStatus) + SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE; if (pClient->Receive(maxLen)) { //heuristic to detect disconnected clients CSimpleSocket::CSocketError err = pClient->GetSocketError(); if (err != CSimpleSocket::SocketSuccess || !pClient->IsSocketValid()) { b3Clock::usleep(100); curNumErr++; if (curNumErr > 100) { printf("TCP Connection error = %d, curNumErr = %d\n", (int)err, curNumErr); break; } } curNumErr = 0; char* msg2 = (char*)pClient->GetData(); int numBytesRec2 = pClient->GetBytesReceived(); int curSize = bytesReceived.size(); bytesReceived.resize(bytesReceived.size() + numBytesRec2); for (int i = 0; i < numBytesRec2; i++) { bytesReceived[curSize + i] = msg2[i]; } if (bytesReceived.size() >= 4) { int numBytesRec = bytesReceived.size(); if (numBytesRec >= 10) { if (strncmp(&bytesReceived[0], "disconnect", 10) == 0) { printf("Disconnect request received\n"); bytesReceived.clear(); break; } if (strncmp(&bytesReceived[0], "terminateserver", 10) == 0) { printf("Terminate server request received\n"); exitRequested = true; bytesReceived.clear(); break; } } if (gVerboseNetworkMessagesServer) { printf("received message length [%d]\n", numBytesRec); } receivedData = true; SharedMemoryCommand cmd; SharedMemoryCommand* cmdPtr = 0; int type = *(int*)&bytesReceived[0]; //performance test if (numBytesRec == sizeof(int)) { cmdPtr = &cmd; cmd.m_type = *(int*)&bytesReceived[0]; } else { if (numBytesRec == sizeof(SharedMemoryCommand)) { cmdPtr = (SharedMemoryCommand*)&bytesReceived[0]; } else { if (numBytesRec == 36) { cmdPtr = &cmd; memcpy(&cmd, &bytesReceived[0], numBytesRec); } } } if (cmdPtr) { SharedMemoryStatus serverStatus; b3AlignedObjectArray buffer; buffer.resize(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE); bool hasStatus = sm->processCommand(*cmdPtr, serverStatus, &buffer[0], buffer.size()); double startTimeSeconds = clock.getTimeInSeconds(); double curTimeSeconds = clock.getTimeInSeconds(); while ((!hasStatus) && ((curTimeSeconds - startTimeSeconds) < timeOutInSeconds)) { hasStatus = sm->receiveStatus(serverStatus, &buffer[0], buffer.size()); curTimeSeconds = clock.getTimeInSeconds(); } if (gVerboseNetworkMessagesServer) { //printf("buffer.size = %d\n", buffer.size()); printf("serverStatus.m_numDataStreamBytes = %d\n", serverStatus.m_numDataStreamBytes); } if (hasStatus) { b3AlignedObjectArray packetData; unsigned char* statBytes = (unsigned char*)&serverStatus; if (cmdPtr->m_type == CMD_STEP_FORWARD_SIMULATION) { packetData.resize(4 + sizeof(int)); int sz = packetData.size(); int curPos = 0; MySerializeInt(sz, &packetData[curPos]); curPos += 4; for (int i = 0; i < sizeof(int); i++) { packetData[i + curPos] = statBytes[i]; } curPos += sizeof(int); pClient->Send(&packetData[0], packetData.size()); } else { if (cmdPtr->m_type == CMD_REQUEST_VR_EVENTS_DATA) { int headerSize = 16 + 5 * sizeof(int) + sizeof(smUint64_t) + sizeof(char*) + sizeof(b3VRControllerEvent) * serverStatus.m_sendVREvents.m_numVRControllerEvents; packetData.resize(4 + headerSize); int sz = packetData.size(); int curPos = 0; MySerializeInt(sz, &packetData[curPos]); curPos += 4; for (int i = 0; i < headerSize; i++) { packetData[i + curPos] = statBytes[i]; } curPos += headerSize; pClient->Send(&packetData[0], packetData.size()); } else { //create packetData with [int packetSizeInBytes, status, streamBytes) packetData.resize(4 + sizeof(SharedMemoryStatus) + serverStatus.m_numDataStreamBytes); int sz = packetData.size(); int curPos = 0; if (gVerboseNetworkMessagesServer) { //printf("buffer.size = %d\n", buffer.size()); printf("serverStatus packed size = %d\n", sz); } MySerializeInt(sz, &packetData[curPos]); curPos += 4; for (int i = 0; i < sizeof(SharedMemoryStatus); i++) { packetData[i + curPos] = statBytes[i]; } curPos += sizeof(SharedMemoryStatus); for (int i = 0; i < serverStatus.m_numDataStreamBytes; i++) { packetData[i + curPos] = buffer[i]; } pClient->Send(&packetData[0], packetData.size()); } } } bytesReceived.clear(); } else { //likely an incomplete packet, let's append more bytes //printf("received packet with unknown contents\n"); } } } if (!receivedData) { //printf("Didn't receive data.\n"); } } printf("Disconnecting client.\n"); pClient->Close(); delete pClient; } } socket.Close(); socket.Shutdown(CSimpleSocket::Both); } else { printf("Error: cannot connect to shared memory physics server."); } delete sm; return 0; }