mirror of
https://github.com/glest/glest-source.git
synced 2025-08-18 06:01:17 +02:00
Updated with initial 3.4.4 codebase includes:
- network fixes for multiplayer defects found - initial code (disabled currently) for content crc checking and downloading - code compiles on Win32 using VS2008 express, project files not yet included
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
//This file is part of Glest Shared Library (www.glest.org)
|
||||
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
|
||||
|
||||
//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
|
||||
//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 "socket.h"
|
||||
@@ -28,6 +28,8 @@ using namespace Shared::Util;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
bool Socket::enableDebugText = true;
|
||||
|
||||
// =====================================================
|
||||
// class Ip
|
||||
// =====================================================
|
||||
@@ -48,7 +50,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c
|
||||
|
||||
|
||||
Ip::Ip(const string& ipString){
|
||||
int offset= 0;
|
||||
int offset= 0;
|
||||
int byteIndex= 0;
|
||||
|
||||
for(byteIndex= 0; byteIndex<4; ++byteIndex){
|
||||
@@ -71,51 +73,307 @@ Socket::Socket(int sock){
|
||||
this->sock= sock;
|
||||
}
|
||||
|
||||
Socket::Socket(){
|
||||
Socket::Socket()
|
||||
{
|
||||
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(sock<0) {
|
||||
if(sock < 0)
|
||||
{
|
||||
throwException("Error creating socket");
|
||||
}
|
||||
}
|
||||
|
||||
Socket::~Socket() {
|
||||
::close(sock);
|
||||
Socket::~Socket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
disconnectSocket();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
void Socket::disconnectSocket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] calling shutdown and close for socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
::shutdown(sock,2);
|
||||
::close(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socketTriggeredList.size() > 0)
|
||||
{
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
int imaxsocket = 0;
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if(socket > 0)
|
||||
{
|
||||
FD_SET(socket, &rfds);
|
||||
imaxsocket = max(socket,imaxsocket);
|
||||
}
|
||||
}
|
||||
|
||||
if(imaxsocket > 0)
|
||||
{
|
||||
/* Wait up to 0 seconds. */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d errno = %d [%s]",__FILE__,__FUNCTION__,retval,errno,strerror(errno));
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
}
|
||||
else if(retval)
|
||||
{
|
||||
bResult = true;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
|
||||
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
|
||||
|
||||
itermap->second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
itermap->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead()
|
||||
{
|
||||
return Socket::hasDataToRead(sock) ;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead(int socket)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socket > 0)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(socket, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval)
|
||||
{
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
int Socket::getDataToRead(){
|
||||
unsigned long size;
|
||||
unsigned long size = 0;
|
||||
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctl(sock, FIONREAD, &size);
|
||||
//fd_set rfds;
|
||||
//struct timeval tv;
|
||||
//int retval;
|
||||
|
||||
if(err < 0 && errno != EAGAIN){
|
||||
throwException("Can not get data to read");
|
||||
}
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
//FD_ZERO(&rfds);
|
||||
//FD_SET(sock, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 0;
|
||||
|
||||
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
//if(retval)
|
||||
if(sock > 0)
|
||||
{
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctl(sock, FIONREAD, &size);
|
||||
|
||||
if(err < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,err,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err == 0)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
int Socket::send(const void *data, int dataSize) {
|
||||
ssize_t bytesSent= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
if(bytesSent<0 && errno != EAGAIN) {
|
||||
throwException("error while receiving socket data");
|
||||
ssize_t bytesSent= 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesSent < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d errno = %d [%s]",__FILE__,__FUNCTION__,bytesSent,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesSent < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during send, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesSent < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isWritable(true) == true)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bytesSent <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesSent,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
|
||||
|
||||
return static_cast<int>(bytesSent);
|
||||
}
|
||||
|
||||
int Socket::receive(void *data, int dataSize) {
|
||||
ssize_t bytesReceived= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
if(bytesReceived<0 && errno != EAGAIN) {
|
||||
throwException("error while receiving socket data");
|
||||
int Socket::receive(void *data, int dataSize)
|
||||
{
|
||||
ssize_t bytesReceived = 0;
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesReceived < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesReceived < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during receive, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesReceived < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(bytesReceived <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,bytesReceived,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
return static_cast<int>(bytesReceived);
|
||||
}
|
||||
|
||||
int Socket::peek(void *data, int dataSize){
|
||||
ssize_t err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
if(err<0 && errno != EAGAIN){
|
||||
throwException("Can not receive data");
|
||||
ssize_t err = 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
}
|
||||
if(err < 0 && errno != EAGAIN)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,errno,strerror(errno));
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err < 0 && errno == EAGAIN)
|
||||
{
|
||||
printf("In [%s::%s] #1 EAGAIN during peek, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((err < 0 && errno == EAGAIN) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
|
||||
printf("In [%s::%s] #2 EAGAIN during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(err <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
return static_cast<int>(err);
|
||||
@@ -128,49 +386,114 @@ void Socket::setBlock(bool block){
|
||||
}
|
||||
}
|
||||
|
||||
bool Socket::isReadable(){
|
||||
bool Socket::isReadable()
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(sock+1, &set, NULL, NULL, &tv);
|
||||
if(i<0){
|
||||
throwException("Error selecting socket");
|
||||
if(i < 0)
|
||||
{
|
||||
//throwException("Error selecting socket");
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
return i==1;
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return (i == 1);
|
||||
}
|
||||
|
||||
bool Socket::isWritable(){
|
||||
bool Socket::isWritable(bool waitOnDelayedResponse)
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i<0){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
bool result = false;
|
||||
do
|
||||
{
|
||||
int i = select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i < 0 )
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
waitOnDelayedResponse = false;
|
||||
|
||||
//throwException("Error selecting socket");
|
||||
}
|
||||
else if(i == 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,i,errno,strerror(errno));
|
||||
printf("%s",szBuf);
|
||||
|
||||
if(waitOnDelayedResponse == false)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
} while(waitOnDelayedResponse == true && result == false);
|
||||
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::isConnected(){
|
||||
|
||||
bool Socket::isConnected()
|
||||
{
|
||||
//if the socket is not writable then it is not conencted
|
||||
if(!isWritable()){
|
||||
if(isWritable(false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if the socket is readable it is connected if we can read a byte from it
|
||||
if(isReadable()){
|
||||
if(isReadable())
|
||||
{
|
||||
char tmp;
|
||||
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
|
||||
int err = peek(&tmp, sizeof(tmp));
|
||||
return (err > 0);
|
||||
/*
|
||||
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
|
||||
|
||||
if(err <= 0 && errno != EAGAIN)
|
||||
{
|
||||
int iErr = errno;
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if(err <= 0)
|
||||
{
|
||||
int iErr = errno;
|
||||
//disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] #2 DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,err,iErr,strerror(iErr));
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//otherwise the socket is connected
|
||||
@@ -198,9 +521,9 @@ string Socket::getIp() const{
|
||||
throw runtime_error("Error getting host ip");
|
||||
}
|
||||
|
||||
return
|
||||
intToStr(address[0]) + "." +
|
||||
intToStr(address[1]) + "." +
|
||||
return
|
||||
intToStr(address[0]) + "." +
|
||||
intToStr(address[1]) + "." +
|
||||
intToStr(address[2]) + "." +
|
||||
intToStr(address[3]);
|
||||
}
|
||||
@@ -215,7 +538,8 @@ void Socket::throwException(const string &str){
|
||||
// class ClientSocket
|
||||
// ===============================================
|
||||
|
||||
void ClientSocket::connect(const Ip &ip, int port){
|
||||
void ClientSocket::connect(const Ip &ip, int port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
@@ -224,20 +548,23 @@ void ClientSocket::connect(const Ip &ip, int port){
|
||||
addr.sin_port= htons(port);
|
||||
|
||||
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
|
||||
if(err < 0) {
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]",ip.getString().c_str(),port,err,errno,strerror(errno));
|
||||
sprintf(szBuf,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d errno = %d [%s]\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,errno,strerror(errno));
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
if (errno == EINPROGRESS) {
|
||||
|
||||
if (errno == EINPROGRESS)
|
||||
{
|
||||
fd_set myset;
|
||||
struct timeval tv;
|
||||
int valopt;
|
||||
socklen_t lon;
|
||||
|
||||
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
|
||||
do {
|
||||
fprintf(stderr, "In [%s::%s] EINPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__);
|
||||
|
||||
do
|
||||
{
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
@@ -246,41 +573,57 @@ void ClientSocket::connect(const Ip &ip, int port){
|
||||
|
||||
err = select(sock+1, NULL, &myset, NULL, &tv);
|
||||
|
||||
if (err < 0 && errno != EINTR) {
|
||||
sprintf(szBuf, "Error connecting %d - %s\n", errno, strerror(errno));
|
||||
throwException(szBuf);
|
||||
if (err < 0 && errno != EINTR)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error connecting %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
else if (err > 0) {
|
||||
else if (err > 0)
|
||||
{
|
||||
// Socket selected for write
|
||||
lon = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0) {
|
||||
sprintf(szBuf, "Error in getsockopt() %d - %s\n", errno, strerror(errno));
|
||||
throwException(szBuf);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error in getsockopt() %d - [%s]\n",__FILE__,__FUNCTION__,errno, strerror(errno));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
// Check the value returned...
|
||||
if (valopt) {
|
||||
sprintf(szBuf, "Error in delayed connection() %d - %s\n", valopt, strerror(valopt));
|
||||
throwException(szBuf);
|
||||
if (valopt)
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Error in delayed connection() %d - [%s]\n",__FILE__,__FUNCTION__,valopt, strerror(valopt));
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
|
||||
fprintf(stderr, "In [%s::%s] Apparent recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
|
||||
break;
|
||||
}
|
||||
else {
|
||||
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
|
||||
throwException(szBuf);
|
||||
else
|
||||
{
|
||||
sprintf(szBuf, "In [%s::%s] Timeout in select() - Cancelling!\n",__FILE__,__FUNCTION__);
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
if(err < 0)
|
||||
{
|
||||
throwException(szBuf);
|
||||
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d [%s]\n",__FILE__,__FUNCTION__,sock,err,errno,strerror(errno));
|
||||
//throwException(szBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "In [%s::%s] Valid recovery for connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, errno = %d\n",sock,err,errno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,7 +631,8 @@ void ClientSocket::connect(const Ip &ip, int port){
|
||||
// class ServerSocket
|
||||
// ===============================================
|
||||
|
||||
void ServerSocket::bind(int port){
|
||||
void ServerSocket::bind(int port)
|
||||
{
|
||||
//sockaddr structure
|
||||
sockaddr_in addr;
|
||||
addr.sin_family= AF_INET;
|
||||
@@ -297,30 +641,45 @@ void ServerSocket::bind(int port){
|
||||
|
||||
int val = 1;
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
|
||||
|
||||
|
||||
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
if(err < 0) {
|
||||
throwException("Error binding socket");
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf, "In [%s::%s] Error binding socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
throwException(szBuf);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerSocket::listen(int connectionQueueSize){
|
||||
void ServerSocket::listen(int connectionQueueSize)
|
||||
{
|
||||
int err= ::listen(sock, connectionQueueSize);
|
||||
if(err < 0) {
|
||||
throwException("Error listening socket");
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,errno);
|
||||
throwException(szBuf);
|
||||
}
|
||||
}
|
||||
|
||||
Socket *ServerSocket::accept(){
|
||||
Socket *ServerSocket::accept()
|
||||
{
|
||||
int newSock= ::accept(sock, NULL, NULL);
|
||||
if(newSock < 0) {
|
||||
if(errno == EAGAIN)
|
||||
return NULL;
|
||||
if(newSock < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
if(Socket::enableDebugText) printf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,newSock,errno);
|
||||
|
||||
if(errno == EAGAIN)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
throwException(szBuf);
|
||||
|
||||
throwException("Error accepting socket connection");
|
||||
}
|
||||
return new Socket(newSock);
|
||||
}
|
||||
|
||||
|
||||
}}//end namespace
|
||||
|
||||
|
@@ -1,9 +1,9 @@
|
||||
//This file is part of Glest Shared Library (www.glest.org)
|
||||
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
|
||||
|
||||
//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
|
||||
//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 "platform_util.h"
|
||||
|
||||
@@ -24,6 +24,10 @@
|
||||
#include "window.h"
|
||||
#include "noimpl.h"
|
||||
|
||||
#include "checksum.h"
|
||||
#include "socket.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
@@ -38,7 +42,7 @@ int ScreenHeight;
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// PerformanceTimer
|
||||
// PerformanceTimer
|
||||
// =====================================
|
||||
|
||||
void PerformanceTimer::init(float fps, int maxTimes){
|
||||
@@ -67,7 +71,7 @@ void PerformanceTimer::reset(){
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Chrono
|
||||
// Chrono
|
||||
// =====================================
|
||||
|
||||
Chrono::Chrono() {
|
||||
@@ -111,7 +115,7 @@ int64 Chrono::queryCounter(int multiplier) const {
|
||||
}
|
||||
|
||||
// =====================================
|
||||
// Misc
|
||||
// Misc
|
||||
// =====================================
|
||||
|
||||
//finds all filenames like path and stores them in resultys
|
||||
@@ -128,7 +132,7 @@ void findAll(const string &path, vector<string> &results, bool cutExtension) {
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
@@ -160,6 +164,217 @@ void findAll(const string &path, vector<string> &results, bool cutExtension) {
|
||||
}
|
||||
}
|
||||
|
||||
int isdir(const char *path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
|
||||
}
|
||||
|
||||
bool EndsWith(const string &str, const string& key)
|
||||
{
|
||||
size_t keylen = key.length();
|
||||
size_t strlen = str.length();
|
||||
|
||||
if(keylen <= strlen)
|
||||
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets their checksum of all files combined
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
|
||||
|
||||
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
/** Stupid win32 is searching for all files without extension when *. is
|
||||
* specified as wildcard
|
||||
*/
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
checksum.addFile(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
return checksum.getSum();
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets the checksum of each file
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
|
||||
|
||||
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
/** Stupid win32 is searching for all files without extension when *. is
|
||||
* specified as wildcard
|
||||
*/
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(p);
|
||||
|
||||
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
/*
|
||||
const char* begin = p;
|
||||
for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
if(*p == '/')
|
||||
begin = p+1;
|
||||
}
|
||||
*/
|
||||
|
||||
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
return checksumFiles;
|
||||
}
|
||||
|
||||
string extractDirectoryPathFromFile(string filename)
|
||||
{
|
||||
return filename.substr( 0, filename.rfind("/")+1 );
|
||||
}
|
||||
|
||||
void createDirectoryPaths(string Path)
|
||||
{
|
||||
char DirName[256]="";
|
||||
const char *path = Path.c_str();
|
||||
char *dirName = DirName;
|
||||
while(*path)
|
||||
{
|
||||
//if (('\\' == *path) || ('/' == *path))
|
||||
if ('/' == *path)
|
||||
{
|
||||
//if (':' != *(path-1))
|
||||
{
|
||||
mkdir(DirName, S_IRWXO);
|
||||
}
|
||||
}
|
||||
*dirName++ = *path++;
|
||||
*dirName = '\0';
|
||||
}
|
||||
mkdir(DirName, S_IRWXO);
|
||||
}
|
||||
|
||||
bool changeVideoMode(int resW, int resH, int colorBits, int ) {
|
||||
Private::shouldBeFullscreen = true;
|
||||
return true;
|
||||
|
@@ -1,265 +1,480 @@
|
||||
// ==============================================================
|
||||
// This file is part of Glest Shared Library (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// 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 "platform_util.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "util.h"
|
||||
#include "conversion.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
// =====================================================
|
||||
// class PerformanceTimer
|
||||
// =====================================================
|
||||
|
||||
void PerformanceTimer::init(int fps, int maxTimes){
|
||||
int64 freq;
|
||||
|
||||
if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){
|
||||
throw runtime_error("Performance counters not supported");
|
||||
}
|
||||
|
||||
times= 0;
|
||||
this->maxTimes= maxTimes;
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks);
|
||||
|
||||
updateTicks= freq/fps;
|
||||
}
|
||||
|
||||
bool PerformanceTimer::isTime(){
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
|
||||
|
||||
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
|
||||
lastTicks+= updateTicks;
|
||||
times++;
|
||||
return true;
|
||||
}
|
||||
times= 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PerformanceTimer::reset(){
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
|
||||
lastTicks= thisTicks;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Chrono
|
||||
// =====================================================
|
||||
|
||||
Chrono::Chrono(){
|
||||
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &freq)){
|
||||
throw runtime_error("Performance counters not supported");
|
||||
}
|
||||
stopped= true;
|
||||
accumCount= 0;
|
||||
}
|
||||
|
||||
void Chrono::start(){
|
||||
stopped= false;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &startCount);
|
||||
}
|
||||
|
||||
void Chrono::stop(){
|
||||
int64 endCount;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
|
||||
accumCount+= endCount-startCount;
|
||||
stopped= true;
|
||||
}
|
||||
|
||||
int64 Chrono::getMicros() const{
|
||||
return queryCounter(1000000);
|
||||
}
|
||||
|
||||
int64 Chrono::getMillis() const{
|
||||
return queryCounter(1000);
|
||||
}
|
||||
|
||||
int64 Chrono::getSeconds() const{
|
||||
return queryCounter(1);
|
||||
}
|
||||
|
||||
int64 Chrono::queryCounter(int multiplier) const{
|
||||
if(stopped){
|
||||
return multiplier*accumCount/freq;
|
||||
}
|
||||
else{
|
||||
int64 endCount;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
|
||||
return multiplier*(accumCount+endCount-startCount)/freq;
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class PlatformExceptionHandler
|
||||
// =====================================================
|
||||
|
||||
PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL;
|
||||
|
||||
LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){
|
||||
|
||||
HANDLE hFile = CreateFile(
|
||||
thisPointer->dumpFileName.c_str(),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation;
|
||||
|
||||
lExceptionInformation.ThreadId= GetCurrentThreadId();
|
||||
lExceptionInformation.ExceptionPointers= pointers;
|
||||
lExceptionInformation.ClientPointers= false;
|
||||
|
||||
MiniDumpWriteDump(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
hFile,
|
||||
MiniDumpNormal,
|
||||
&lExceptionInformation,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
thisPointer->handle();
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void PlatformExceptionHandler::install(string dumpFileName){
|
||||
thisPointer= this;
|
||||
this->dumpFileName= dumpFileName;
|
||||
SetUnhandledExceptionFilter(handler);
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Misc
|
||||
// =====================================================
|
||||
|
||||
//finds all filenames like path and stores them in resultys
|
||||
void findAll(const string &path, vector<string> &results, bool cutExtension){
|
||||
|
||||
int i= 0;
|
||||
struct _finddata_t fi;
|
||||
intptr_t handle;
|
||||
char *cstr;
|
||||
|
||||
results.clear();
|
||||
|
||||
cstr= new char[path.length()+1];
|
||||
strcpy(cstr, path.c_str());
|
||||
|
||||
if((handle=_findfirst(cstr,&fi))!=-1){
|
||||
do{
|
||||
if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){
|
||||
i++;
|
||||
results.push_back(fi.name);
|
||||
}
|
||||
}
|
||||
while(_findnext(handle, &fi)==0);
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Error opening files: "+ path);
|
||||
}
|
||||
|
||||
if(i==0){
|
||||
throw runtime_error("No files found: "+ path);
|
||||
}
|
||||
|
||||
if(cutExtension){
|
||||
for (int i=0; i<results.size(); ++i){
|
||||
results.at(i)=cutLastExt(results.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
delete [] cstr;
|
||||
}
|
||||
|
||||
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
|
||||
DEVMODE devMode;
|
||||
|
||||
for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){
|
||||
if (devMode.dmPelsWidth== resW &&
|
||||
devMode.dmPelsHeight== resH &&
|
||||
devMode.dmBitsPerPel== colorBits){
|
||||
|
||||
devMode.dmDisplayFrequency=refreshFrequency;
|
||||
|
||||
LONG result= ChangeDisplaySettings(&devMode, 0);
|
||||
if(result == DISP_CHANGE_SUCCESSFUL){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void restoreVideoMode(){
|
||||
int dispChangeErr= ChangeDisplaySettings(NULL, 0);
|
||||
assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL);
|
||||
}
|
||||
|
||||
void message(string message){
|
||||
MessageBox(NULL, message.c_str(), "Message", MB_OK);
|
||||
}
|
||||
|
||||
bool ask(string message){
|
||||
return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES;
|
||||
}
|
||||
|
||||
void exceptionMessage(const exception &excp){
|
||||
string message, title;
|
||||
showCursor(true);
|
||||
|
||||
message+= "ERROR(S):\n\n";
|
||||
message+= excp.what();
|
||||
|
||||
title= "Error: Unhandled Exception";
|
||||
MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL);
|
||||
}
|
||||
|
||||
int getScreenW(){
|
||||
return GetSystemMetrics(SM_CXSCREEN);
|
||||
}
|
||||
|
||||
int getScreenH(){
|
||||
return GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
void sleep(int millis){
|
||||
Sleep(millis);
|
||||
}
|
||||
|
||||
void showCursor(bool b){
|
||||
ShowCursor(b);
|
||||
}
|
||||
|
||||
bool isKeyDown(int virtualKey){
|
||||
return (GetKeyState(virtualKey) & 0x8000) != 0;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
// ==============================================================
|
||||
// This file is part of Glest Shared Library (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// 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 "platform_util.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "util.h"
|
||||
#include "conversion.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <direct.h>
|
||||
|
||||
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
||||
|
||||
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
// =====================================================
|
||||
// class PerformanceTimer
|
||||
// =====================================================
|
||||
|
||||
void PerformanceTimer::init(int fps, int maxTimes){
|
||||
int64 freq;
|
||||
|
||||
if(QueryPerformanceFrequency((LARGE_INTEGER*) &freq)==0){
|
||||
throw runtime_error("Performance counters not supported");
|
||||
}
|
||||
|
||||
times= 0;
|
||||
this->maxTimes= maxTimes;
|
||||
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &lastTicks);
|
||||
|
||||
updateTicks= freq/fps;
|
||||
}
|
||||
|
||||
bool PerformanceTimer::isTime(){
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
|
||||
|
||||
if((thisTicks-lastTicks)>=updateTicks && times<maxTimes){
|
||||
lastTicks+= updateTicks;
|
||||
times++;
|
||||
return true;
|
||||
}
|
||||
times= 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void PerformanceTimer::reset(){
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &thisTicks);
|
||||
lastTicks= thisTicks;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Chrono
|
||||
// =====================================================
|
||||
|
||||
Chrono::Chrono(){
|
||||
if(!QueryPerformanceFrequency((LARGE_INTEGER*) &freq)){
|
||||
throw runtime_error("Performance counters not supported");
|
||||
}
|
||||
stopped= true;
|
||||
accumCount= 0;
|
||||
}
|
||||
|
||||
void Chrono::start(){
|
||||
stopped= false;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &startCount);
|
||||
}
|
||||
|
||||
void Chrono::stop(){
|
||||
int64 endCount;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
|
||||
accumCount+= endCount-startCount;
|
||||
stopped= true;
|
||||
}
|
||||
|
||||
int64 Chrono::getMicros() const{
|
||||
return queryCounter(1000000);
|
||||
}
|
||||
|
||||
int64 Chrono::getMillis() const{
|
||||
return queryCounter(1000);
|
||||
}
|
||||
|
||||
int64 Chrono::getSeconds() const{
|
||||
return queryCounter(1);
|
||||
}
|
||||
|
||||
int64 Chrono::queryCounter(int multiplier) const{
|
||||
if(stopped){
|
||||
return multiplier*accumCount/freq;
|
||||
}
|
||||
else{
|
||||
int64 endCount;
|
||||
QueryPerformanceCounter((LARGE_INTEGER*) &endCount);
|
||||
return multiplier*(accumCount+endCount-startCount)/freq;
|
||||
}
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class PlatformExceptionHandler
|
||||
// =====================================================
|
||||
|
||||
PlatformExceptionHandler *PlatformExceptionHandler::thisPointer= NULL;
|
||||
|
||||
LONG WINAPI PlatformExceptionHandler::handler(LPEXCEPTION_POINTERS pointers){
|
||||
|
||||
HANDLE hFile = CreateFile(
|
||||
thisPointer->dumpFileName.c_str(),
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0);
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION lExceptionInformation;
|
||||
|
||||
lExceptionInformation.ThreadId= GetCurrentThreadId();
|
||||
lExceptionInformation.ExceptionPointers= pointers;
|
||||
lExceptionInformation.ClientPointers= false;
|
||||
|
||||
MiniDumpWriteDump(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
hFile,
|
||||
MiniDumpNormal,
|
||||
&lExceptionInformation,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
thisPointer->handle();
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
void PlatformExceptionHandler::install(string dumpFileName){
|
||||
thisPointer= this;
|
||||
this->dumpFileName= dumpFileName;
|
||||
SetUnhandledExceptionFilter(handler);
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// class Misc
|
||||
// =====================================================
|
||||
|
||||
//finds all filenames like path and stores them in resultys
|
||||
void findAll(const string &path, vector<string> &results, bool cutExtension){
|
||||
|
||||
int i= 0;
|
||||
struct _finddata_t fi;
|
||||
intptr_t handle;
|
||||
char *cstr;
|
||||
|
||||
results.clear();
|
||||
|
||||
cstr= new char[path.length()+1];
|
||||
strcpy(cstr, path.c_str());
|
||||
|
||||
if((handle=_findfirst(cstr,&fi))!=-1){
|
||||
do{
|
||||
if(!(strcmp(".", fi.name)==0 || strcmp("..", fi.name)==0)){
|
||||
i++;
|
||||
results.push_back(fi.name);
|
||||
}
|
||||
}
|
||||
while(_findnext(handle, &fi)==0);
|
||||
}
|
||||
else{
|
||||
throw runtime_error("Error opening files: "+ path);
|
||||
}
|
||||
|
||||
if(i==0){
|
||||
throw runtime_error("No files found: "+ path);
|
||||
}
|
||||
|
||||
if(cutExtension){
|
||||
for (int i=0; i<results.size(); ++i){
|
||||
results.at(i)=cutLastExt(results.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
delete [] cstr;
|
||||
}
|
||||
|
||||
int isdir(const char *path)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
return stat (path, &stats) == 0 && S_ISDIR (stats.st_mode);
|
||||
}
|
||||
|
||||
bool EndsWith(const string &str, const string& key)
|
||||
{
|
||||
size_t keylen = key.length();
|
||||
size_t strlen = str.length();
|
||||
|
||||
if(keylen <= strlen)
|
||||
return string::npos != str.rfind(key.c_str(),strlen - keylen, keylen);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets their checksum of all files combined
|
||||
int32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum) {
|
||||
|
||||
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
|
||||
|
||||
/* MV - PORT THIS to win32
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// // strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
checksum.addFile(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
getFolderTreeContentsCheckSumRecursively(string(p) + "/*", filterFileExt, &checksum);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
*/
|
||||
return checksum.getSum();
|
||||
}
|
||||
|
||||
//finds all filenames like path and gets the checksum of each file
|
||||
vector<std::pair<string,int32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,int32> > *recursiveMap) {
|
||||
|
||||
vector<std::pair<string,int32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,int32> >() : *recursiveMap);
|
||||
|
||||
/* MV - PORT THIS to win32
|
||||
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
|
||||
|
||||
std::string mypath = path;
|
||||
// Stupid win32 is searching for all files without extension when *. is specified as wildcard
|
||||
if(mypath.compare(mypath.size() - 2, 2, "*.") == 0) {
|
||||
mypath = mypath.substr(0, mypath.size() - 2);
|
||||
mypath += "*";
|
||||
}
|
||||
|
||||
glob_t globbuf;
|
||||
|
||||
int res = glob(mypath.c_str(), 0, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
|
||||
if(isdir(p) == 0)
|
||||
{
|
||||
bool addFile = true;
|
||||
if(filterFileExt != "")
|
||||
{
|
||||
addFile = EndsWith(p, filterFileExt);
|
||||
}
|
||||
|
||||
if(addFile)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s::%s] adding file [%s]\n",__FILE__,__FUNCTION__,p);
|
||||
|
||||
Checksum checksum;
|
||||
checksum.addFile(p);
|
||||
|
||||
checksumFiles.push_back(std::pair<string,int32>(p,checksum.getSum()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
|
||||
// Look recursively for sub-folders
|
||||
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
|
||||
if(res < 0) {
|
||||
std::stringstream msg;
|
||||
msg << "Couldn't scan directory '" << mypath << "': " << strerror(errno);
|
||||
throw runtime_error(msg.str());
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < globbuf.gl_pathc; ++i) {
|
||||
const char* p = globbuf.gl_pathv[i];
|
||||
//
|
||||
//const char* begin = p;
|
||||
//for( ; *p != 0; ++p) {
|
||||
// strip the path component
|
||||
// if(*p == '/')
|
||||
// begin = p+1;
|
||||
//}
|
||||
|
||||
checksumFiles = getFolderTreeContentsCheckSumListRecursively(string(p) + "/*", filterFileExt, &checksumFiles);
|
||||
}
|
||||
|
||||
globfree(&globbuf);
|
||||
*/
|
||||
return checksumFiles;
|
||||
}
|
||||
|
||||
string extractDirectoryPathFromFile(string filename)
|
||||
{
|
||||
return filename.substr( 0, filename.rfind("/")+1 );
|
||||
}
|
||||
|
||||
void createDirectoryPaths(string Path)
|
||||
{
|
||||
char DirName[256]="";
|
||||
const char *path = Path.c_str();
|
||||
char *dirName = DirName;
|
||||
while(*path)
|
||||
{
|
||||
//if (('\\' == *path) || ('/' == *path))
|
||||
if ('/' == *path)
|
||||
{
|
||||
//if (':' != *(path-1))
|
||||
{
|
||||
_mkdir(DirName);
|
||||
}
|
||||
}
|
||||
*dirName++ = *path++;
|
||||
*dirName = '\0';
|
||||
}
|
||||
_mkdir(DirName);
|
||||
}
|
||||
|
||||
bool changeVideoMode(int resW, int resH, int colorBits, int refreshFrequency){
|
||||
DEVMODE devMode;
|
||||
|
||||
for (int i=0; EnumDisplaySettings(NULL, i, &devMode) ;i++){
|
||||
if (devMode.dmPelsWidth== resW &&
|
||||
devMode.dmPelsHeight== resH &&
|
||||
devMode.dmBitsPerPel== colorBits){
|
||||
|
||||
devMode.dmDisplayFrequency=refreshFrequency;
|
||||
|
||||
LONG result= ChangeDisplaySettings(&devMode, 0);
|
||||
if(result == DISP_CHANGE_SUCCESSFUL){
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void restoreVideoMode(){
|
||||
int dispChangeErr= ChangeDisplaySettings(NULL, 0);
|
||||
assert(dispChangeErr==DISP_CHANGE_SUCCESSFUL);
|
||||
}
|
||||
|
||||
void message(string message){
|
||||
MessageBox(NULL, message.c_str(), "Message", MB_OK);
|
||||
}
|
||||
|
||||
bool ask(string message){
|
||||
return MessageBox(NULL, message.c_str(), "Confirmation", MB_YESNO)==IDYES;
|
||||
}
|
||||
|
||||
void exceptionMessage(const exception &excp){
|
||||
string message, title;
|
||||
showCursor(true);
|
||||
|
||||
message+= "ERROR(S):\n\n";
|
||||
message+= excp.what();
|
||||
|
||||
title= "Error: Unhandled Exception";
|
||||
MessageBox(NULL, message.c_str(), title.c_str(), MB_ICONSTOP | MB_OK | MB_TASKMODAL);
|
||||
}
|
||||
|
||||
int getScreenW(){
|
||||
return GetSystemMetrics(SM_CXSCREEN);
|
||||
}
|
||||
|
||||
int getScreenH(){
|
||||
return GetSystemMetrics(SM_CYSCREEN);
|
||||
}
|
||||
|
||||
void sleep(int millis){
|
||||
Sleep(millis);
|
||||
}
|
||||
|
||||
void showCursor(bool b){
|
||||
ShowCursor(b);
|
||||
}
|
||||
|
||||
bool isKeyDown(int virtualKey){
|
||||
return (GetKeyState(virtualKey) & 0x8000) != 0;
|
||||
}
|
||||
|
||||
}}//end namespace
|
||||
|
@@ -3,9 +3,9 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Marti<74>o Figueroa
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
@@ -16,12 +16,17 @@
|
||||
#include "conversion.h"
|
||||
|
||||
#include "leak_dumper.h"
|
||||
#include <time.h>
|
||||
|
||||
#define socklen_t int
|
||||
|
||||
using namespace std;
|
||||
using namespace Shared::Util;
|
||||
|
||||
namespace Shared{ namespace Platform{
|
||||
|
||||
bool Socket::enableDebugText = false;
|
||||
|
||||
// =====================================================
|
||||
// class Ip
|
||||
// =====================================================
|
||||
@@ -42,7 +47,7 @@ Ip::Ip(unsigned char byte0, unsigned char byte1, unsigned char byte2, unsigned c
|
||||
|
||||
|
||||
Ip::Ip(const string& ipString){
|
||||
int offset= 0;
|
||||
int offset= 0;
|
||||
int byteIndex= 0;
|
||||
|
||||
for(byteIndex= 0; byteIndex<4; ++byteIndex){
|
||||
@@ -64,7 +69,7 @@ string Ip::getString() const{
|
||||
Socket::SocketManager Socket::socketManager;
|
||||
|
||||
Socket::SocketManager::SocketManager(){
|
||||
WSADATA wsaData;
|
||||
WSADATA wsaData;
|
||||
WORD wVersionRequested = MAKEWORD(2, 0);
|
||||
WSAStartup(wVersionRequested, &wsaData);
|
||||
//dont throw exceptions here, this is a static initializacion
|
||||
@@ -85,59 +90,300 @@ Socket::Socket(){
|
||||
}
|
||||
}
|
||||
|
||||
Socket::~Socket(){
|
||||
int err= closesocket(sock);
|
||||
if(err==INVALID_SOCKET){
|
||||
throwException("Error closing socket");
|
||||
}
|
||||
Socket::~Socket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
disconnectSocket();
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
void Socket::disconnectSocket()
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] START closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
|
||||
if(sock > 0)
|
||||
{
|
||||
::shutdown(sock,2);
|
||||
::closesocket(sock);
|
||||
sock = -1;
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] END closing socket = %d...\n",__FILE__,__FUNCTION__,sock);
|
||||
}
|
||||
|
||||
// Int lookup is socket fd while bool result is whether or not that socket was signalled for reading
|
||||
bool Socket::hasDataToRead(std::map<int,bool> &socketTriggeredList)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socketTriggeredList.size() > 0)
|
||||
{
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
|
||||
int imaxsocket = 0;
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if(socket > 0)
|
||||
{
|
||||
FD_SET(socket, &rfds);
|
||||
imaxsocket = max(socket,imaxsocket);
|
||||
}
|
||||
}
|
||||
|
||||
if(imaxsocket > 0)
|
||||
{
|
||||
/* Wait up to 0 seconds. */
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(imaxsocket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR SELECTING SOCKET DATA retval = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,retval,WSAGetLastError());
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
}
|
||||
else if(retval)
|
||||
{
|
||||
bResult = true;
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] select detected data imaxsocket = %d...\n",__FILE__,__FUNCTION__,imaxsocket);
|
||||
|
||||
for(std::map<int,bool>::iterator itermap = socketTriggeredList.begin();
|
||||
itermap != socketTriggeredList.end(); itermap++)
|
||||
{
|
||||
int socket = itermap->first;
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
if(Socket::enableDebugText) printf("In [%s] FD_ISSET true for socket %d...\n",__FUNCTION__,socket);
|
||||
|
||||
itermap->second = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
itermap->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] socketTriggeredList->size() = %d\n",__FILE__,__FUNCTION__,socketTriggeredList.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead()
|
||||
{
|
||||
return Socket::hasDataToRead(sock) ;
|
||||
}
|
||||
|
||||
bool Socket::hasDataToRead(int socket)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
if(socket > 0)
|
||||
{
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(socket, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int retval = select(socket + 1, &rfds, NULL, NULL, &tv);
|
||||
if(retval)
|
||||
{
|
||||
if (FD_ISSET(socket, &rfds))
|
||||
{
|
||||
bResult = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
int Socket::getDataToRead(){
|
||||
u_long size;
|
||||
|
||||
int err= ioctlsocket(sock, FIONREAD, &size);
|
||||
unsigned long size = 0;
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not get data to read");
|
||||
}
|
||||
}
|
||||
//fd_set rfds;
|
||||
//struct timeval tv;
|
||||
//int retval;
|
||||
|
||||
/* Watch stdin (fd 0) to see when it has input. */
|
||||
//FD_ZERO(&rfds);
|
||||
//FD_SET(sock, &rfds);
|
||||
|
||||
/* Wait up to 0 seconds. */
|
||||
//tv.tv_sec = 0;
|
||||
//tv.tv_usec = 0;
|
||||
|
||||
//retval = select(sock + 1, &rfds, NULL, NULL, &tv);
|
||||
//if(retval)
|
||||
if(sock > 0)
|
||||
{
|
||||
/* ioctl isn't posix, but the following seems to work on all modern
|
||||
* unixes */
|
||||
int err= ioctlsocket(sock, FIONREAD, &size);
|
||||
|
||||
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR PEEKING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,err,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err == 0)
|
||||
{
|
||||
//if(Socket::enableDebugText) printf("In [%s] ioctl returned = %d, size = %ld\n",__FUNCTION__,err,size);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<int>(size);
|
||||
}
|
||||
|
||||
int Socket::send(const void *data, int dataSize){
|
||||
int err= ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not send data");
|
||||
}
|
||||
int Socket::send(const void *data, int dataSize) {
|
||||
int bytesSent= 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
}
|
||||
return err;
|
||||
if(bytesSent < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"In [%s::%s] ERROR WRITING SOCKET DATA, err = %d WSAGetLastError() = %d",__FILE__,__FUNCTION__,bytesSent,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during send, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesSent < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isWritable(true) == true)
|
||||
{
|
||||
bytesSent = ::send(sock, reinterpret_cast<const char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during send, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesSent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bytesSent <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesSent,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
if(Socket::enableDebugText) printf("In [%s::%s] sock = %d, bytesSent = %d\n",__FILE__,__FUNCTION__,sock,bytesSent);
|
||||
|
||||
return static_cast<int>(bytesSent);
|
||||
}
|
||||
|
||||
int Socket::receive(void *data, int dataSize){
|
||||
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
int Socket::receive(void *data, int dataSize)
|
||||
{
|
||||
int bytesReceived = 0;
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not receive data");
|
||||
}
|
||||
if(sock > 0)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
}
|
||||
if(bytesReceived < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR READING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,WSAGetLastError());
|
||||
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during receive, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((bytesReceived < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
bytesReceived = recv(sock, reinterpret_cast<char*>(data), dataSize, 0);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during receive, trying again returned: %d\n",__FILE__,__FUNCTION__,bytesReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
if(bytesReceived <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while receiving socket data, bytesReceived = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,bytesReceived,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
return static_cast<int>(bytesReceived);
|
||||
}
|
||||
|
||||
int Socket::peek(void *data, int dataSize){
|
||||
int err= recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
int err = 0;
|
||||
if(sock > 0)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
}
|
||||
if(err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] ERROR PEEKING SOCKET DATA error while sending socket data, bytesSent = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,WSAGetLastError());
|
||||
|
||||
if(err==SOCKET_ERROR){
|
||||
if(WSAGetLastError()!=WSAEWOULDBLOCK){
|
||||
throwException("Can not receive data");
|
||||
}
|
||||
throwException(szBuf);
|
||||
}
|
||||
else if(err < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
|
||||
{
|
||||
printf("In [%s::%s] #1 WSAEWOULDBLOCK during peek, trying again...\n",__FILE__,__FUNCTION__);
|
||||
|
||||
time_t tStartTimer = time(NULL);
|
||||
while((err < 0 && WSAGetLastError() == WSAEWOULDBLOCK) && (difftime(time(NULL),tStartTimer) <= 5))
|
||||
{
|
||||
if(Socket::isReadable() == true)
|
||||
{
|
||||
err = recv(sock, reinterpret_cast<char*>(data), dataSize, MSG_PEEK);
|
||||
|
||||
printf("In [%s::%s] #2 WSAEWOULDBLOCK during peek, trying again returned: %d\n",__FILE__,__FUNCTION__,err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
if(err <= 0)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
|
||||
printf("%s",szBuf);
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
return static_cast<int>(err);
|
||||
}
|
||||
|
||||
void Socket::setBlock(bool block){
|
||||
@@ -149,49 +395,101 @@ void Socket::setBlock(bool block){
|
||||
}
|
||||
}
|
||||
|
||||
bool Socket::isReadable(){
|
||||
bool Socket::isReadable()
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
TIMEVAL tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(0, &set, NULL, NULL, &tv);
|
||||
if(i==SOCKET_ERROR){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
int i= select(sock+1, &set, NULL, NULL, &tv);
|
||||
if(i==SOCKET_ERROR)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
}
|
||||
//return (i == 1 && FD_ISSET(sock, &set));
|
||||
return (i == 1);
|
||||
}
|
||||
|
||||
bool Socket::isWritable(){
|
||||
bool Socket::isWritable(bool waitOnDelayedResponse)
|
||||
{
|
||||
if(sock <= 0) return false;
|
||||
|
||||
TIMEVAL tv;
|
||||
tv.tv_sec= 0;
|
||||
tv.tv_usec= 10;
|
||||
tv.tv_usec= 1;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int i= select(0, NULL, &set, NULL, &tv);
|
||||
if(i==SOCKET_ERROR){
|
||||
throwException("Error selecting socket");
|
||||
}
|
||||
return i==1;
|
||||
bool result = false;
|
||||
do
|
||||
{
|
||||
int i= select(sock+1, NULL, &set, NULL, &tv);
|
||||
if(i==SOCKET_ERROR)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] error while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
waitOnDelayedResponse = false;
|
||||
}
|
||||
else if(i == 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] TIMEOUT while selecting socket data, err = %d, errno = %d\n",__FILE__,__FUNCTION__,i,WSAGetLastError());
|
||||
printf("%s",szBuf);
|
||||
|
||||
if(waitOnDelayedResponse == false)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
} while(waitOnDelayedResponse == true && result == false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Socket::isConnected(){
|
||||
|
||||
//if the socket is not writable then it is not conencted
|
||||
if(!isWritable()){
|
||||
if(isWritable(false) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//if the socket is readable it is connected if we can read a byte from it
|
||||
if(isReadable()){
|
||||
char tmp;
|
||||
return recv(sock, &tmp, sizeof(tmp), MSG_PEEK) > 0;
|
||||
if(isReadable())
|
||||
{
|
||||
char tmp;
|
||||
int err = peek(&tmp, sizeof(tmp));
|
||||
return (err > 0);
|
||||
/*
|
||||
int err = recv(sock, &tmp, sizeof(tmp), MSG_PEEK);
|
||||
|
||||
if(err <= 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
int iErr = WSAGetLastError();
|
||||
disconnectSocket();
|
||||
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"[%s::%s] DISCONNECTED SOCKET error while peeking isconnected socket data, err = %d, WSAGetLastError() = %d\n",__FILE__,__FUNCTION__,err,iErr);
|
||||
printf("%s",szBuf);
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//otherwise the socket is connected
|
||||
@@ -220,9 +518,9 @@ string Socket::getIp() const{
|
||||
throwException("Error getting host ip");
|
||||
}
|
||||
|
||||
return
|
||||
intToStr(address[0]) + "." +
|
||||
intToStr(address[1]) + "." +
|
||||
return
|
||||
intToStr(address[0]) + "." +
|
||||
intToStr(address[1]) + "." +
|
||||
intToStr(address[2]) + "." +
|
||||
intToStr(address[3]);
|
||||
}
|
||||
@@ -235,20 +533,86 @@ void Socket::throwException(const string &str){
|
||||
// class ClientSocket
|
||||
// =====================================================
|
||||
|
||||
void ClientSocket::connect(const Ip &ip, int port){
|
||||
void ClientSocket::connect(const Ip &ip, int port)
|
||||
{
|
||||
sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.sin_family= AF_INET;
|
||||
addr.sin_addr.s_addr= inet_addr(ip.getString().c_str());
|
||||
addr.sin_port= htons(port);
|
||||
|
||||
int err= ::connect(sock, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr));
|
||||
if(err==SOCKET_ERROR){
|
||||
int lastError= WSAGetLastError();
|
||||
if(err < 0)
|
||||
{
|
||||
char szBuf[1024]="";
|
||||
sprintf(szBuf,"#2 Error connecting socket for IP: %s for Port: %d err = %d WSAGetLastError() = %d",ip.getString().c_str(),port,err,WSAGetLastError());
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
|
||||
if(lastError!=WSAEWOULDBLOCK && lastError!=WSAEALREADY){
|
||||
throwException("Can not connect");
|
||||
}
|
||||
if (WSAGetLastError() == WSAEINPROGRESS) {
|
||||
|
||||
fd_set myset;
|
||||
struct timeval tv;
|
||||
int valopt;
|
||||
socklen_t lon;
|
||||
|
||||
fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
|
||||
do {
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
FD_ZERO(&myset);
|
||||
FD_SET(sock, &myset);
|
||||
|
||||
err = select(sock+1, NULL, &myset, NULL, &tv);
|
||||
|
||||
if (err < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
{
|
||||
sprintf(szBuf, "Error connecting %d\n", WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
else if (err > 0) {
|
||||
// Socket selected for write
|
||||
lon = sizeof(int);
|
||||
if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (char *)(&valopt), &lon) < 0)
|
||||
{
|
||||
sprintf(szBuf, "Error in getsockopt() %d\n", WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
// Check the value returned...
|
||||
if (valopt)
|
||||
{
|
||||
sprintf(szBuf, "Error in delayed connection() %d\n", valopt);
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Apparent recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(szBuf, "Timeout in select() - Cancelling!\n");
|
||||
//throwException(szBuf);
|
||||
fprintf(stderr, "%s", szBuf);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
if(err < 0)
|
||||
{
|
||||
fprintf(stderr, "In [%s::%s] Before END sock = %d, err = %d, errno = %d\n",__FILE__,__FUNCTION__,sock,err,WSAGetLastError());
|
||||
//throwException(szBuf);
|
||||
}
|
||||
|
||||
fprintf(stderr, "Valid recovery for connection sock = %d, err = %d, WSAGetLastError() = %d\n",sock,err,WSAGetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +626,7 @@ void ServerSocket::bind(int port){
|
||||
addr.sin_family= AF_INET;
|
||||
addr.sin_addr.s_addr= INADDR_ANY;
|
||||
addr.sin_port= htons(port);
|
||||
|
||||
|
||||
int err= ::bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
|
||||
if(err==SOCKET_ERROR){
|
||||
throwException("Error binding socket");
|
||||
|
@@ -3,9 +3,9 @@
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
@@ -27,14 +27,14 @@ namespace Shared{ namespace Util{
|
||||
|
||||
Checksum::Checksum(){
|
||||
sum= 0;
|
||||
r= 55665;
|
||||
c1= 52845;
|
||||
r= 55665;
|
||||
c1= 52845;
|
||||
c2= 22719;
|
||||
}
|
||||
|
||||
void Checksum::addByte(int8 value){
|
||||
int32 cipher= (value ^ (r >> 8));
|
||||
|
||||
|
||||
r= (cipher + r) * c1 + c2;
|
||||
sum+= cipher;
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void Checksum::addString(const string &value){
|
||||
}
|
||||
|
||||
void Checksum::addFile(const string &path){
|
||||
|
||||
|
||||
FILE* file= fopen(path.c_str(), "rb");
|
||||
|
||||
if(file!=NULL){
|
||||
|
@@ -3,9 +3,9 @@
|
||||
//
|
||||
// Copyright (C) 2001-2008 Marti<74>o Figueroa
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// ==============================================================
|
||||
|
||||
@@ -61,7 +61,7 @@ XmlIo::XmlIo(){
|
||||
}
|
||||
catch(const XMLException&){
|
||||
throw runtime_error("Error initializing XML system");
|
||||
}
|
||||
}
|
||||
|
||||
try{
|
||||
XMLCh str[strSize];
|
||||
@@ -84,7 +84,7 @@ XmlIo::~XmlIo(){
|
||||
}
|
||||
|
||||
XmlNode *XmlIo::load(const string &path){
|
||||
|
||||
|
||||
try{
|
||||
ErrorHandler errorHandler;
|
||||
#if XERCES_VERSION_MAJOR < 3
|
||||
@@ -99,7 +99,7 @@ XmlNode *XmlIo::load(const string &path){
|
||||
config->setParameter(XMLUni::fgDOMValidate, true);
|
||||
#endif
|
||||
DOMDocument *document= parser->parseURI(path.c_str());
|
||||
|
||||
|
||||
if(document==NULL){
|
||||
throw runtime_error("Can not parse URL: " + path);
|
||||
}
|
||||
@@ -110,7 +110,7 @@ XmlNode *XmlIo::load(const string &path){
|
||||
}
|
||||
catch(const DOMException &e){
|
||||
throw runtime_error("Exception while loading: " + path + ": " + XMLString::transcode(e.msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlIo::save(const string &path, const XmlNode *node){
|
||||
@@ -144,7 +144,7 @@ void XmlIo::save(const string &path, const XmlNode *node){
|
||||
}
|
||||
catch(const DOMException &e){
|
||||
throw runtime_error("Exception while saving: " + path + ": " + XMLString::transcode(e.msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
// =====================================================
|
||||
// class XmlTree
|
||||
@@ -188,7 +188,7 @@ XmlNode::XmlNode(DOMNode *node){
|
||||
|
||||
//check children
|
||||
for(int i=0; i<node->getChildNodes()->getLength(); ++i){
|
||||
DOMNode *currentNode= node->getChildNodes()->item(i);
|
||||
DOMNode *currentNode= node->getChildNodes()->item(i);
|
||||
if(currentNode->getNodeType()==DOMNode::ELEMENT_NODE){
|
||||
XmlNode *xmlNode= new XmlNode(currentNode);
|
||||
children.push_back(xmlNode);
|
||||
@@ -234,7 +234,7 @@ XmlAttribute *XmlNode::getAttribute(int i) const{
|
||||
}
|
||||
return attributes[i];
|
||||
}
|
||||
|
||||
|
||||
XmlAttribute *XmlNode::getAttribute(const string &name) const{
|
||||
for(int i=0; i<attributes.size(); ++i){
|
||||
if(attributes[i]->getName()==name){
|
||||
@@ -269,6 +269,20 @@ XmlNode *XmlNode::getChild(const string &childName, int i) const{
|
||||
throw runtime_error("Node \""+getName()+"\" doesn't have "+intToStr(i+1)+" children named \""+childName+"\"\n\nTree: "+getTreeString());
|
||||
}
|
||||
|
||||
bool XmlNode::hasChild(const string &childName) const
|
||||
{
|
||||
int count= 0;
|
||||
for(int j = 0; j < children.size(); ++j)
|
||||
{
|
||||
if(children[j]->getName()==childName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
XmlNode *XmlNode::addChild(const string &name){
|
||||
XmlNode *node= new XmlNode(name);
|
||||
children.push_back(node);
|
||||
@@ -290,10 +304,10 @@ DOMElement *XmlNode::buildElement(DOMDocument *document) const{
|
||||
for(int i=0; i<attributes.size(); ++i){
|
||||
XMLString::transcode(attributes[i]->getName().c_str(), str, strSize-1);
|
||||
DOMAttr *attr= document->createAttribute(str);
|
||||
|
||||
|
||||
XMLString::transcode(attributes[i]->getValue().c_str(), str, strSize-1);
|
||||
attr->setValue(str);
|
||||
|
||||
|
||||
node->setAttributeNode(attr);
|
||||
}
|
||||
|
||||
@@ -387,7 +401,7 @@ const string &XmlAttribute::getRestrictedValue() const
|
||||
"\"\nFor portability reasons the only allowed characters in this field are: " + allowedCharacters);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user