2010-03-17 07:25:19 +01:00
|
|
|
|
// ==============================================================
|
|
|
|
|
// This file is part of Glest (www.glest.org)
|
|
|
|
|
//
|
2010-03-17 14:22:08 +01:00
|
|
|
|
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
2010-03-17 07:25:19 +01:00
|
|
|
|
//
|
|
|
|
|
// You can redistribute this code and/or modify it under
|
|
|
|
|
// the terms of the GNU General Public License as published
|
|
|
|
|
// by the Free Software Foundation; either version 2 of the
|
|
|
|
|
// License, or (at your option) any later version
|
|
|
|
|
// ==============================================================
|
|
|
|
|
|
|
|
|
|
#include "network_interface.h"
|
|
|
|
|
|
|
|
|
|
#include <exception>
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
#include "conversion.h"
|
|
|
|
|
#include "platform_util.h"
|
2010-03-20 00:26:00 +01:00
|
|
|
|
#include <fstream>
|
|
|
|
|
#include "util.h"
|
2010-03-17 07:25:19 +01:00
|
|
|
|
|
|
|
|
|
#include "leak_dumper.h"
|
|
|
|
|
|
|
|
|
|
using namespace Shared::Platform;
|
|
|
|
|
using namespace Shared::Util;
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
namespace Glest{ namespace Game{
|
|
|
|
|
|
|
|
|
|
// =====================================================
|
|
|
|
|
// class NetworkInterface
|
|
|
|
|
// =====================================================
|
|
|
|
|
|
|
|
|
|
const int NetworkInterface::readyWaitTimeout= 60000; //1 minute
|
|
|
|
|
|
|
|
|
|
bool NetworkInterface::allowGameDataSynchCheck = false;
|
|
|
|
|
bool NetworkInterface::allowDownloadDataSynch = false;
|
|
|
|
|
DisplayMessageFunction NetworkInterface::pCB_DisplayMessage = NULL;
|
|
|
|
|
|
|
|
|
|
void NetworkInterface::sendMessage(const NetworkMessage* networkMessage){
|
|
|
|
|
Socket* socket= getSocket();
|
|
|
|
|
|
|
|
|
|
networkMessage->send(socket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetworkMessageType NetworkInterface::getNextMessageType(bool checkHasDataFirst)
|
|
|
|
|
{
|
|
|
|
|
Socket* socket= getSocket();
|
|
|
|
|
int8 messageType= nmtInvalid;
|
|
|
|
|
|
|
|
|
|
if(checkHasDataFirst == false ||
|
|
|
|
|
(checkHasDataFirst == true &&
|
|
|
|
|
socket != NULL &&
|
|
|
|
|
socket->hasDataToRead() == true))
|
|
|
|
|
{
|
|
|
|
|
//peek message type
|
|
|
|
|
int dataSize = socket->getDataToRead();
|
|
|
|
|
if(dataSize >= sizeof(messageType)){
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socket->getDataToRead() dataSize = %d\n",__FILE__,__FUNCTION__,dataSize);
|
2010-03-17 07:25:19 +01:00
|
|
|
|
|
|
|
|
|
int iPeek = socket->peek(&messageType, sizeof(messageType));
|
|
|
|
|
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] socket->getDataToRead() iPeek = %d, messageType = %d\n",__FILE__,__FUNCTION__,iPeek,messageType);
|
2010-03-17 07:25:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//sanity check new message type
|
|
|
|
|
if(messageType<0 || messageType>=nmtCount){
|
|
|
|
|
throw runtime_error("Invalid message type: " + intToStr(messageType));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return static_cast<NetworkMessageType>(messageType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetworkInterface::receiveMessage(NetworkMessage* networkMessage){
|
|
|
|
|
|
2010-03-20 00:26:00 +01:00
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s]\n",__FILE__,__FUNCTION__);
|
2010-03-17 07:25:19 +01:00
|
|
|
|
|
|
|
|
|
Socket* socket= getSocket();
|
|
|
|
|
|
|
|
|
|
return networkMessage->receive(socket);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool NetworkInterface::isConnected(){
|
|
|
|
|
bool result = (getSocket()!=NULL && getSocket()->isConnected());
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void NetworkInterface::DisplayErrorMessage(string sErr, bool closeSocket) {
|
2010-03-17 14:22:08 +01:00
|
|
|
|
|
|
|
|
|
if(closeSocket == true && getSocket() != NULL)
|
|
|
|
|
{
|
|
|
|
|
close();
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-17 07:25:19 +01:00
|
|
|
|
if(pCB_DisplayMessage != NULL) {
|
|
|
|
|
pCB_DisplayMessage(sErr.c_str(), false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
throw runtime_error(sErr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =====================================================
|
|
|
|
|
// class GameNetworkInterface
|
|
|
|
|
// =====================================================
|
|
|
|
|
|
|
|
|
|
GameNetworkInterface::GameNetworkInterface(){
|
|
|
|
|
quit= false;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-18 22:26:40 +01:00
|
|
|
|
void GameNetworkInterface::requestCommand(const NetworkCommand *networkCommand, bool insertAtStart) {
|
|
|
|
|
if(insertAtStart == false) {
|
|
|
|
|
requestedCommands.push_back(*networkCommand);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
requestedCommands.insert(requestedCommands.begin(),*networkCommand);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-17 07:25:19 +01:00
|
|
|
|
// =====================================================
|
|
|
|
|
// class FileTransferSocketThread
|
|
|
|
|
// =====================================================
|
|
|
|
|
|
|
|
|
|
const int32 SEND_FILE = 0x20;
|
|
|
|
|
const int32 ACK = 0x47;
|
|
|
|
|
|
|
|
|
|
FileTransferSocketThread::FileTransferSocketThread(FileTransferInfo fileInfo)
|
|
|
|
|
{
|
|
|
|
|
this->info = fileInfo;
|
|
|
|
|
this->info.serverPort += 100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileTransferSocketThread::execute()
|
|
|
|
|
{
|
|
|
|
|
if(info.hostType == eServer)
|
|
|
|
|
{
|
|
|
|
|
ServerSocket serverSocket;
|
|
|
|
|
//serverSocket.setBlock(false);
|
|
|
|
|
serverSocket.bind(this->info.serverPort);
|
|
|
|
|
serverSocket.listen(1);
|
|
|
|
|
Socket *clientSocket = serverSocket.accept();
|
|
|
|
|
|
|
|
|
|
char data[513]="";
|
|
|
|
|
memset(data, 0, 256);
|
|
|
|
|
|
|
|
|
|
clientSocket->receive(data,256);
|
|
|
|
|
if(*data == SEND_FILE)
|
|
|
|
|
{
|
|
|
|
|
FileInfo file;
|
|
|
|
|
|
|
|
|
|
memcpy(&file, data+1, sizeof(file));
|
|
|
|
|
|
|
|
|
|
*data=ACK;
|
|
|
|
|
clientSocket->send(data,256);
|
|
|
|
|
|
|
|
|
|
Checksum checksum;
|
|
|
|
|
checksum.addFile(file.fileName);
|
|
|
|
|
file.filecrc = checksum.getSum();
|
|
|
|
|
|
|
|
|
|
ifstream infile(file.fileName.c_str(), ios::in | ios::binary | ios::ate);
|
|
|
|
|
if(infile.is_open() == true)
|
|
|
|
|
{
|
|
|
|
|
file.filesize = infile.tellg();
|
|
|
|
|
infile.seekg (0, ios::beg);
|
|
|
|
|
|
|
|
|
|
memset(data, 0, 256);
|
|
|
|
|
*data=SEND_FILE;
|
|
|
|
|
memcpy(data+1,&file,sizeof(file));
|
|
|
|
|
|
|
|
|
|
clientSocket->send(data,256);
|
|
|
|
|
clientSocket->receive(data,256);
|
|
|
|
|
if(*data != ACK)
|
|
|
|
|
;//transfer error
|
|
|
|
|
|
|
|
|
|
int remain=file.filesize % 512 ;
|
|
|
|
|
int packs=(file.filesize-remain)/512;
|
|
|
|
|
|
|
|
|
|
while(packs--)
|
|
|
|
|
{
|
|
|
|
|
infile.read(data,512);
|
|
|
|
|
//if(!ReadFile(file,data,512,&read,NULL))
|
|
|
|
|
// ; //read error
|
|
|
|
|
//if(written!=pack)
|
|
|
|
|
// ; //read error
|
|
|
|
|
clientSocket->send(data,512);
|
|
|
|
|
clientSocket->receive(data,256);
|
|
|
|
|
if(*data!=ACK)
|
|
|
|
|
;//transfer error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
infile.read(data,remain);
|
|
|
|
|
//if(!ReadFile(file,data,remain,&read,NULL))
|
|
|
|
|
// ; //read error
|
|
|
|
|
//if(written!=pack)
|
|
|
|
|
// ; //read error
|
|
|
|
|
|
|
|
|
|
clientSocket->send(data,remain);
|
|
|
|
|
clientSocket->receive(data,256);
|
|
|
|
|
if(*data!=ACK)
|
|
|
|
|
;//transfer error
|
|
|
|
|
|
|
|
|
|
infile.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete clientSocket;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Ip ip(this->info.serverIP);
|
|
|
|
|
ClientSocket clientSocket;
|
|
|
|
|
//clientSocket.setBlock(false);
|
|
|
|
|
clientSocket.connect(this->info.serverIP, this->info.serverPort);
|
|
|
|
|
|
|
|
|
|
if(clientSocket.isConnected() == true)
|
|
|
|
|
{
|
|
|
|
|
FileInfo file;
|
|
|
|
|
file.fileName = this->info.fileName;
|
|
|
|
|
//file.filesize =
|
|
|
|
|
//file.filecrc = this->info.
|
|
|
|
|
|
|
|
|
|
string path = extractDirectoryPathFromFile(file.fileName);
|
|
|
|
|
createDirectoryPaths(path);
|
|
|
|
|
ofstream outFile(file.fileName.c_str(), ios_base::binary | ios_base::out);
|
|
|
|
|
if(outFile.is_open() == true)
|
|
|
|
|
{
|
|
|
|
|
char data[513]="";
|
|
|
|
|
memset(data, 0, 256);
|
|
|
|
|
*data=SEND_FILE;
|
|
|
|
|
memcpy(data+1,&file,sizeof(file));
|
|
|
|
|
|
|
|
|
|
clientSocket.send(data,256);
|
|
|
|
|
clientSocket.receive(data,256);
|
|
|
|
|
if(*data!=ACK)
|
|
|
|
|
;//transfer error
|
|
|
|
|
|
|
|
|
|
clientSocket.receive(data,256);
|
|
|
|
|
if(*data == SEND_FILE)
|
|
|
|
|
{
|
|
|
|
|
memcpy(&file, data+1, sizeof(file));
|
|
|
|
|
*data=ACK;
|
|
|
|
|
clientSocket.send(data,256);
|
|
|
|
|
|
|
|
|
|
int remain = file.filesize % 512 ;
|
|
|
|
|
int packs = (file.filesize-remain) / 512;
|
|
|
|
|
|
|
|
|
|
while(packs--)
|
|
|
|
|
{
|
|
|
|
|
clientSocket.receive(data,512);
|
|
|
|
|
|
|
|
|
|
outFile.write(data, 512);
|
|
|
|
|
if(outFile.bad())
|
|
|
|
|
{
|
|
|
|
|
int ii = 0;
|
|
|
|
|
}
|
|
|
|
|
//if(!WriteFile(file,data,512,&written,NULL))
|
|
|
|
|
// ; //write error
|
|
|
|
|
//if(written != pack)
|
|
|
|
|
// ; //write error
|
|
|
|
|
*data=ACK;
|
|
|
|
|
clientSocket.send(data,256);
|
|
|
|
|
}
|
|
|
|
|
clientSocket.receive(data,remain);
|
|
|
|
|
|
|
|
|
|
outFile.write(data, remain);
|
|
|
|
|
if(outFile.bad())
|
|
|
|
|
{
|
|
|
|
|
int ii = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if(!WriteFile(file,data,remain,&written,NULL))
|
|
|
|
|
// ; //write error
|
|
|
|
|
//if(written!=pack)
|
|
|
|
|
// ; //write error
|
|
|
|
|
*data=ACK;
|
|
|
|
|
clientSocket.send(data,256);
|
|
|
|
|
|
|
|
|
|
Checksum checksum;
|
|
|
|
|
checksum.addFile(file.fileName);
|
|
|
|
|
int32 crc = checksum.getSum();
|
|
|
|
|
if(file.filecrc != crc)
|
|
|
|
|
{
|
|
|
|
|
int ii = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if(calc_crc(file)!=info.crc)
|
|
|
|
|
// ; //transfeer error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outFile.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}}//end namespace
|