Thread: [Gcblue-commits] gcb_wx/src/network tcConnectionData.cpp,NONE,1.1 tcMessage.cpp,NONE,1.1 tcMultiplay
Status: Alpha
Brought to you by:
ddcforge
|
From: <ddc...@us...> - 2004-02-29 23:02:10
|
Update of /cvsroot/gcblue/gcb_wx/src/network In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13290/src/network Modified Files: tcNetworkInterface.cpp Added Files: tcConnectionData.cpp tcMessage.cpp tcMultiplayerInterface.cpp Log Message: --- NEW FILE: tcConnectionData.cpp --- /** @file tcConnectionData.cpp */ /* ** ** Copyright (C) 2003-2004 Dewitt "Cole" Colclough (de...@tw...) ** All rights reserved. ** This file is part of the Global Conflict Blue (GCB) program. ** GCB is free software; you can redistribute it and/or modify ** it under the terms of version 2 of the GNU General Public License as ** published by the Free Software Foundation. ** GCB is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with GCB; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdwx.h" // precompiled header file #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "network/tcConnectionData.h" #include "network/tcNetworkInterface.h" #include "tcTime.h" #include <iostream> BEGIN_NAMESPACE(network) tcNetworkInterface* tcConnectionData::networkInterface = NULL; /** * Attempts to read next whole message. If message is incomplete, the partial * message is returned to the socket read buffer. This method does not block. * Uses tempMessage for temporary storage. If return message is to be stored, * the message must be COPIED. Do not store the pointer. * @return pointer to new message if entire message is ready, otherwise NULL */ tcMessage* tcConnectionData::ReadNextMessage() { wxASSERT(socket); // attempt to read header if header needs to be read if (tempMessage.id == -1) { const unsigned headerSize = sizeof(tempMessage.messageSize) + sizeof(tempMessage.id); // verify the message header and at least one byte of data are available socket->Read(tempMessage.buffer + tempMessage.bufferIdx, headerSize - tempMessage.bufferIdx); tempMessage.bufferIdx += socket->LastCount(); if (tempMessage.bufferIdx >= headerSize) { memcpy(&tempMessage.messageSize, tempMessage.buffer, sizeof(tempMessage.messageSize)); memcpy(&tempMessage.id, tempMessage.buffer + sizeof(tempMessage.messageSize), sizeof(tempMessage.id)); tempMessage.bufferIdx = 0; } } if (tempMessage.id == -1) return NULL; // Read message socket->Read(tempMessage.buffer + tempMessage.bufferIdx, tempMessage.messageSize - tempMessage.bufferIdx); tempMessage.bufferIdx += socket->LastCount(); if (tempMessage.bufferIdx >= tempMessage.messageSize) { tempMessage.bufferIdx = 0; // reset bufferIdx } else { fprintf(stdout, "Read %d bytes of data\n", tempMessage.bufferIdx); return NULL; } //socket->SetFlags(wxSOCKET_NOWAIT); tempMessage.buffer[256] = 0; std::string testString; testString = (char*)tempMessage.buffer; fprintf(stdout, "Received message, size: %d, id:%d, data:%s\n", tempMessage.messageSize, tempMessage.id, testString.c_str()); wxMessageBox(testString.c_str(),"Message",wxOK); tempMessage.Reset(); return &tempMessage; } /** * Adds message idx to back of TCP send queue */ void tcConnectionData::SendTCP(unsigned int idx) { writeQueueTCP.push(idx); } /** * */ void tcConnectionData::Update() { wxASSERT(networkInterface); //ReadNextMessage(); WriteQueuedMessage(); } /** * Writes next queued message to socket. If capacity of write buffer * is exceeded, writes part of the message only. */ void tcConnectionData::WriteQueuedMessage() { if (writeQueueTCP.empty()) return; int bufferId = writeQueueTCP.front(); tcMessage *message = networkInterface->GetMessage(bufferId); if (message == NULL) { std::cerr << "Error - bad message buffer idx." << std::endl; writeQueueTCP.pop(); return; } // socket->SetFlags(wxSOCKET_WAITALL); const unsigned idx1 = sizeof(message->messageSize); const unsigned idx2 = sizeof(message->messageSize) + sizeof(message->id); if (message->bufferIdx < idx1) { // write message size field socket->Write(&message->messageSize + message->bufferIdx, idx1 - message->bufferIdx); message->bufferIdx += socket->LastCount(); if (message->bufferIdx < idx1) return; } if (socket->Error()) { int gg = 4; wxSocketError err = socket->LastError(); } if (message->bufferIdx < idx2) { // write message id field socket->Write(&message->id + message->bufferIdx - idx1, idx2 - message->bufferIdx); message->bufferIdx += socket->LastCount(); if (message->bufferIdx < idx2) return; } if (socket->Error()) { int gg = 4; wxSocketError err = socket->LastError(); } // write data socket->Write(&message->buffer[message->bufferIdx - idx2], message->messageSize - message->bufferIdx + idx2); message->bufferIdx += socket->LastCount(); // pop message from queue and return message buffer if entire // message has been written if (message->bufferIdx >= (message->messageSize + idx2)) { writeQueueTCP.pop(); networkInterface->ReturnMessage(bufferId); } if (socket->Error()) { int gg = 4; wxSocketError err = socket->LastError(); } // socket->SetFlags(wxSOCKET_NOWAIT); } /** * tcConnectionData default constructor */ tcConnectionData::tcConnectionData() { socket = NULL; idString = "Err"; id = -1; } END_NAMESPACE --- NEW FILE: tcMessage.cpp --- /** @file tcMessage.cpp */ /* ** ** Copyright (C) 2003-2004 Dewitt "Cole" Colclough (de...@tw...) ** All rights reserved. ** This file is part of the Global Conflict Blue (GCB) program. ** GCB is free software; you can redistribute it and/or modify ** it under the terms of version 2 of the GNU General Public License as ** published by the Free Software Foundation. ** GCB is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with GCB; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdwx.h" // precompiled header file #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "network/tcMessage.h" #include <iostream> BEGIN_NAMESPACE(network) /** * Reset message state to default / uninitialized */ void tcMessage::Reset() { id = -1; sourceId = -1; timestamp = 0; bufferIdx = 0; messageSize = 0; } /** * tcMessage default constructor */ tcMessage::tcMessage() { Reset(); } /** * copy constructor */ tcMessage::tcMessage(const tcMessage& source) { id = source.id;; timestamp = source.timestamp; sourceId = source.sourceId; bufferIdx = source.bufferIdx; messageSize = source.messageSize; wxASSERT(messageSize <= BUFFER_SIZE); if (messageSize > BUFFER_SIZE) messageSize = BUFFER_SIZE; memcpy(buffer, source.buffer, messageSize); } END_NAMESPACE --- NEW FILE: tcMultiplayerInterface.cpp --- /** @file tcNetworkInterface.cpp */ /** tcMultiplayerInterface.cpp */ /* ** Copyright (C) 2003 Dewitt "Cole" Colclough (de...@tw...) ** All rights reserved. ** This file is part of the Global Conflict Blue (GCB) program. ** GCB is free software; you can redistribute it and/or modify ** it under the terms of version 2 of the GNU General Public License as ** published by the Free Software Foundation. ** GCB is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with GCB; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "stdwx.h" // precompiled header file #ifndef WX_PRECOMP #include "wx/wx.h" #endif #include "network/tcNetworkInterface.h" #include "network/tcMultiplayerInterface.h" BEGIN_NAMESPACE(network) /** * @return singleton instance */ tcMultiplayerInterface& tcMultiplayerInterface::Get() { static tcMultiplayerInterface instance; return instance; } int tcMultiplayerInterface::GetConnectionId(unsigned connectionIdx) { return networkInterface->GetConnectionId(connectionIdx); } std::string tcMultiplayerInterface::GetConnectionStatus(unsigned connectionIdx) { return networkInterface->GetConnectionStatus(connectionIdx); } unsigned tcMultiplayerInterface::GetNumConnections() { return networkInterface->GetNumConnections(); } void tcMultiplayerInterface::MakeClient() { networkInterface->MakeClient(); } void tcMultiplayerInterface::MakeServer() { networkInterface->MakeServer(); } void tcMultiplayerInterface::OpenConnection(std::string hostName) { networkInterface->OpenConnection(hostName.c_str()); } /** * Sends a test message of text to destination */ void tcMultiplayerInterface::SendTestMessage(int destination, std::string message) { char buff[256]; size_t messageLength = message.length(); if (messageLength > 255) messageLength = 255; strncpy(buff, message.c_str(), messageLength); buff[messageLength] = 0; networkInterface->SendMessage(destination, 1, (unsigned)(messageLength+1), (unsigned char*)buff); } /** * This must be called regularly to perform network functions. * (avoids need for multithreadeding) */ void tcMultiplayerInterface::Update() { networkInterface->Update(); } tcMultiplayerInterface::tcMultiplayerInterface() { networkInterface = new tcNetworkInterface(); wxASSERT(networkInterface); } /** * Copy constructor not allowed for this singleton class */ tcMultiplayerInterface::tcMultiplayerInterface(const tcMultiplayerInterface& source) { wxASSERT(false); } tcMultiplayerInterface::~tcMultiplayerInterface() { if (networkInterface) delete networkInterface; } END_NAMESPACE Index: tcNetworkInterface.cpp =================================================================== RCS file: /cvsroot/gcblue/gcb_wx/src/network/tcNetworkInterface.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** tcNetworkInterface.cpp 27 Feb 2004 00:07:59 -0000 1.3 --- tcNetworkInterface.cpp 29 Feb 2004 22:51:36 -0000 1.4 *************** *** 23,27 **** #ifndef WX_PRECOMP #include "wx/wx.h" - //#include "wx/msw/private.h" // for MS Windows specific definitions #endif --- 23,26 ---- *************** *** 32,77 **** BEGIN_NAMESPACE(network) ! /** ! * Reset message state to default / uninitialized ! */ ! void tcNetworkInterface::tcMessage::Reset() ! { ! id = -1; ! timestamp = 0; ! messageId = -1; ! messageSize = 0; ! } - /** - * tcMessage default constructor - */ - tcNetworkInterface::tcMessage::tcMessage() - { - Reset(); - } - /** - * copy constructor - */ - tcNetworkInterface::tcMessage::tcMessage(const tcNetworkInterface::tcMessage& source) - { - id = source.id;; - timestamp = source.timestamp; - messageId = source.messageId; - messageSize = source.messageSize; - wxASSERT(messageSize <= BUFFER_SIZE); - if (messageSize > BUFFER_SIZE) messageSize = BUFFER_SIZE; - memcpy(buffer, source.buffer, messageSize); - } - - /** - * tcConnectionData default constructor - */ - tcNetworkInterface::tcConnectionData::tcConnectionData() - { - socket = NULL; - idString = "Err"; - id = -1; - } void tcNetworkInterface::AddConnection(wxSocketBase *socket) --- 31,39 ---- BEGIN_NAMESPACE(network) ! BEGIN_EVENT_TABLE(tcNetworkInterface, wxEvtHandler) ! EVT_SOCKET(-1, tcNetworkInterface::OnSocketEvent) ! END_EVENT_TABLE() void tcNetworkInterface::AddConnection(wxSocketBase *socket) *************** *** 95,104 **** cdata.id = connectionIndex++; - connectionLookup[cdata.id] = (int)connectionData.size(); ! socket->Notify(FALSE); connectionData.push_back(cdata); fprintf(stdout, "New connection: %s : %d\n", addr.Hostname().c_str(), addr.Service()); --- 57,69 ---- cdata.id = connectionIndex++; ! socket->SetEventHandler(*this, cdata.id); ! socket->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_CONNECTION_FLAG); ! socket->Notify(TRUE); ! socket->SetFlags(wxSOCKET_NOWAIT); connectionData.push_back(cdata); + UpdateConnectionLookup(); fprintf(stdout, "New connection: %s : %d\n", addr.Hostname().c_str(), addr.Service()); *************** *** 216,228 **** /** * Obtains message buffer if available. ! * @param idx index of new message buffer ! * @return true if message buffer is available */ ! bool tcNetworkInterface::GetMessage(unsigned int& idx) { ! if (available.empty()) return false; ! idx = available.front(); available.pop(); ! return true; } --- 181,208 ---- /** * Obtains message buffer if available. ! * @return valid id if message buffer is available, -1 otherwise */ ! int tcNetworkInterface::CheckoutMessage() { ! if (available.empty()) return -1; ! int idx = (int)available.front(); available.pop(); ! return idx; ! } ! ! /** ! * @return NULL if idx is invalid, pointer to connection data otherwise ! */ ! tcConnectionData* tcNetworkInterface::GetConnection(int idx) ! { ! if (idx < 0) return NULL; ! if (idx >= (int)connectionData.size()) return NULL; ! return &connectionData[idx]; ! } ! ! tcMessage* tcNetworkInterface::GetMessage(int id) ! { ! if ((id < 0)||(id >= (int)messageBuffer.size())) return NULL; ! return &messageBuffer[id]; } *************** *** 307,311 **** } ! serverSock->Notify(FALSE); } --- 287,326 ---- } ! serverSock->SetEventHandler(*this, 27); ! serverSock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_CONNECTION_FLAG); ! serverSock->Notify(TRUE); ! //serverSock->Notify(FALSE); ! serverSock->SetFlags(wxSOCKET_NOWAIT); ! } ! ! void tcNetworkInterface::OnSocketEvent(wxSocketEvent& event) ! { ! std::cout << "Socket event: "; ! ! switch(event.GetSocketEvent()) ! { ! case wxSOCKET_INPUT: ! { ! std::cout << "wxSOCKET_INPUT"; ! int connectionIdx = LookupConnectionIndex(event.m_id); ! tcConnectionData *conn = GetConnection(connectionIdx); ! if (conn) ! { ! conn->ReadNextMessage(); ! } ! ! } ! break; ! case wxSOCKET_LOST: ! std::cout << "wxSOCKET_LOST"; ! break; ! case wxSOCKET_CONNECTION: ! std::cout << "wxSOCKET_CONNECTION"; ! break; ! default: ! std::cout << "Unexpected event!"; ! break; ! } ! std::cout << std::endl; } *************** *** 356,359 **** --- 371,376 ---- void tcNetworkInterface::RemoveDeadConnections() { + bool erasedAny = false; + // update connections, remove dead connections int nConnections = (int)connectionData.size(); *************** *** 366,371 **** if (!connectionData[n].socket->IsConnected()) { - connectionLookup[connectionData[n].id] = -1; // invalidate lookup entry connectionData.erase(connectionData.begin()+n); } } --- 383,388 ---- if (!connectionData[n].socket->IsConnected()) { connectionData.erase(connectionData.begin()+n); + erasedAny = true; } } *************** *** 375,378 **** --- 392,400 ---- connectState = NOT_CONNECTED; } + + if (erasedAny) + { + UpdateConnectionLookup(); + } } *************** *** 386,391 **** size_t nConnections = connectionData.size(); - // iterate in reverse to allow safe removal - // (should substitute iterator for this) for(size_t n=0;n<nConnections;n++) { --- 408,411 ---- *************** *** 424,428 **** ! unsigned char* tcNetworkInterface::GetMessage(int connectionId, int& messageId, unsigned& messageSize, int protocol) { --- 444,448 ---- ! unsigned char* tcNetworkInterface::ReceiveMessage(int connectionId, int& messageId, unsigned& messageSize, int protocol) { *************** *** 436,440 **** { if (protocol != TCP) return false; // only TCP supported right now ! return false; } --- 456,489 ---- { if (protocol != TCP) return false; // only TCP supported right now ! ! int connectionIdx = LookupConnectionIndex(connectionId); ! if (connectionIdx == -1) ! { ! std::cerr << "Error - Connection id not found." << std::endl; ! return false; ! } ! ! if (messageSize > tcMessage::BUFFER_SIZE) ! { ! std::cerr << "Error - Attempted to send oversized message." << std::endl; ! return false; ! } ! ! // checkout new message ! int bufferIdx = CheckoutMessage(); ! tcMessage *message = GetMessage(bufferIdx); ! if (message == NULL) return false; ! ! // populate message ! message->id = messageId; ! message->messageSize = messageSize; ! message->sourceId = connectionId; ! message->timestamp = tcTime::Get30HzCount(); ! ! memcpy(message->buffer, data, messageSize); ! ! connectionData[connectionIdx].SendTCP(bufferIdx); ! ! return true; } *************** *** 447,450 **** --- 496,503 ---- void tcNetworkInterface::Update() { + static unsigned lastUpdate = tcTime::Get30HzCount(); + + if ((tcTime::Get30HzCount() - lastUpdate) < 15) return; + lastUpdate = tcTime::Get30HzCount(); if (isServer) { *************** *** 471,474 **** --- 524,529 ---- RemoveDeadConnections(); + UpdateConnections(); + } *************** *** 500,503 **** --- 555,583 ---- } + void tcNetworkInterface::UpdateConnections() + { + size_t nConnections = connectionData.size(); + + for(size_t n=0;n<nConnections;n++) + { + connectionData[n].Update(); + } + } + + /** + * Update connectionLookup map (by clearing and rebuilding) + * This should be called after adding or deleting a connection. + */ + void tcNetworkInterface::UpdateConnectionLookup() + { + connectionLookup.clear(); + size_t nConnections = connectionData.size(); + + for(size_t n=0;n<nConnections;n++) + { + connectionLookup[connectionData[n].id] = (int)n; + } + } + void tcNetworkInterface::UpdateServer() { *************** *** 512,515 **** --- 592,596 ---- } + UpdateConnections(); } *************** *** 522,526 **** serverSock(NULL) { ! connectState = NOT_CONNECTED; ResetMessageBuffer(); --- 603,607 ---- serverSock(NULL) { ! tcConnectionData::networkInterface = this; connectState = NOT_CONNECTED; ResetMessageBuffer(); |