From 1b2e3c5721bdbc85bcb2e97d7ba3bccd07202543 Mon Sep 17 00:00:00 2001 From: Ulrich Kemloh <u.kemloh@fz-juelich.de> Date: Sat, 18 Jan 2014 21:40:06 +0000 Subject: [PATCH] --- src/IO/OutputHandler.cpp | 128 ++++++++++ src/IO/OutputHandler.h | 79 ++++++ src/IO/TraVisToClient.cpp | 498 ++++++++++++++++++++++++++++++++++++++ src/IO/TraVisToClient.h | 149 ++++++++++++ 4 files changed, 854 insertions(+) create mode 100644 src/IO/OutputHandler.cpp create mode 100644 src/IO/OutputHandler.h create mode 100644 src/IO/TraVisToClient.cpp create mode 100644 src/IO/TraVisToClient.h diff --git a/src/IO/OutputHandler.cpp b/src/IO/OutputHandler.cpp new file mode 100644 index 0000000..1fb1428 --- /dev/null +++ b/src/IO/OutputHandler.cpp @@ -0,0 +1,128 @@ +/** + * File: OutputHandler.cpp + * + * Created on 20. November 2010, 15:20 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim 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 JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "OutputHandler.h" + +#include <stdio.h> +#include <stdarg.h> +#include <cstdlib> + +using namespace std; + + +void OutputHandler::Write(string str) { + if (this != NULL) + cout << str << endl; +} + +void OutputHandler::Write(const char* message,...) { + char msg[CLENGTH]; + va_list ap; + va_start (ap, message); + vsprintf (msg,message ,ap); + va_end (ap); + + string str(msg); + if(str.find("ERROR")==string::npos) { + cout<<msg<<endl; + cout.flush(); + } + else { + cerr<<msg<<endl; + cerr.flush(); + } + + //cout << "\033[1;30mbold red text\033[0m\n"; + //cout << "\033[1;31"<<msg<<"\033[0m\n"; + //cout << "\033[1;31 bla bla \033[0m\n"; +} + +void STDIOHandler::Write(string str) { + if (this != NULL) + cout << str << endl; +} + +FileHandler::FileHandler(const char *fn) { + pfp.open(fn); + if (!fn) { + char tmp[CLENGTH]; + sprintf(tmp, "Error!!! File [%s] could not be opened!", fn); + cerr << tmp << endl; + exit(0); + } +} + +FileHandler::~FileHandler() { + pfp.close(); +} + +void FileHandler::Write(string str) { + if (this != NULL) { + pfp << str << endl; + pfp.flush(); + } +} + +void FileHandler::Write(const char* string,...) { + char msg[CLENGTH]; + va_list ap; + va_start (ap, string); + vsprintf (msg,string ,ap); + va_end (ap); + pfp<<msg<<endl; + pfp.flush(); +} + +TraVisToHandler::TraVisToHandler(string host, int port) { + client = new TraVisToClient(host, port); + brokentags.push_back("<trajectoriesDataset>"); + brokentags.push_back("</trajectoriesDataset>"); + brokentags.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); +} + +TraVisToHandler::~TraVisToHandler(){ + delete client; +} + +void TraVisToHandler::Write(string str) { + + vector<string>::iterator str_it; + + //There are a few broken tags which need to be checked for and removed. + for (str_it = brokentags.begin(); str_it != brokentags.end(); ++str_it) { + int tagstart = str.find(*str_it); + if (tagstart != (int) string::npos) { + str.erase(str.begin() + tagstart, str.begin() + tagstart + (*str_it).size()); + } + } + client->sendData(str.c_str()); +} + + + + + diff --git a/src/IO/OutputHandler.h b/src/IO/OutputHandler.h new file mode 100644 index 0000000..855d85a --- /dev/null +++ b/src/IO/OutputHandler.h @@ -0,0 +1,79 @@ +/** + * File: OutputHandler.h + * + * Created on 20. November 2010, 15:20 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim 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 JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef OUTPUT_HANDLER_H_ +#define OUTPUT_HANDLER_H_ + +#include <iostream> +#include <fstream> +#include <vector> + + +#include "../IO/TraVisToClient.h" +#include "../general/Macros.h" + +class OutputHandler { +public: + virtual void Write(std::string str); + virtual void Write(const char *string, ...); + virtual ~OutputHandler(){}; +}; + +class STDIOHandler : public OutputHandler { +public: + void Write(std::string str); +}; + +class FileHandler : public OutputHandler { +private: + std::ofstream pfp; + +public: + FileHandler(const char *fn); + virtual ~FileHandler(); + void Write(std::string str); + void Write(const char *string,...); +}; + +class TraVisToHandler : public OutputHandler { +private: + TraVisToClient* client; + +public: + TraVisToHandler(std::string host, int port); + virtual ~TraVisToHandler(); + void Write(std::string str); + + //Some tags are broken + std::vector<std::string> brokentags; +}; + + + + +#endif /*OUTPUT_HANDLER_H_*/ + diff --git a/src/IO/TraVisToClient.cpp b/src/IO/TraVisToClient.cpp new file mode 100644 index 0000000..d095a4b --- /dev/null +++ b/src/IO/TraVisToClient.cpp @@ -0,0 +1,498 @@ +/** + * TraVisToClient.cpp + * Copyright (C) <2009-2010> <Ulrich Kemloh> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim 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 JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + + +/********* include files ******************************************************/ + +#include <iostream> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + + +#include "TraVisToClient.h" + + +using namespace std; + +TraVisToClient::TraVisToClient(string hostname, unsigned short port) { + _hostname=hostname; + _port = port; + _isConnected = false; + createConnection(); + + +} + +TraVisToClient::~TraVisToClient() { + if (_isConnected) close(); +} + + +/// send datablock to the server + +void TraVisToClient::sendData(const char* data) { + + // first create a new connection, in the case the last one was lost/close + + if (!_isConnected) { + createConnection(); + //FIXME: queue messsage in a vector + // msgQueue.push_back(data); + return; + + } + char msgSizeStr[10]; + int msgSize = (int)strlen(data); + sprintf(msgSizeStr, "%d\n", msgSize); + + /* check if parameters are valid */ + if (NULL == data) { + fprintf(stderr, "invalid message buffer!"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + + // do until queue empty for() + + + /*send the length of the message*/ + int msgsize = strlen(msgSizeStr); + if (msgsize != send(_tcpSocket, (const char *) msgSizeStr, strlen(msgSizeStr), 0)) { + fprintf(stderr, "sending message Size failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + /* now send the message */ + if (msgSize != send(_tcpSocket, (const char *) data, msgSize, 0)) { + fprintf(stderr, "sending message failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + // end do +} + +/// close the client (end the connection) + +void TraVisToClient::close() { + if (_isConnected) { + /* all things are done, so shutdown the connection */ + if (!shutdownAndCloseSocket(_tcpSocket)) { + fprintf(stderr, "shutdown and close socket failed!"); + stopSocketSession(); + fprintf(stderr, "leaving main() with error"); + return; + } + + /* stop the socket session */ + stopSocketSession(); + } + +} + +void TraVisToClient::createConnection() { + + /* start the socket session */ + if (!startSocketSession()) { + fprintf(stderr, "startSocketSession() failed!"); + fprintf(stderr, "socket creation failed for host [%s] on port [%d]!",_hostname.c_str(),_port); + exit(EXIT_FAILURE); + } + + /* create a new socket and connect the socket to the given service */ + if (INVALID_SOCKET == (_tcpSocket = createClientSocket(_hostname.c_str(), _port))) { + fprintf(stderr, "\nsocket creation failed for host [%s] on port [%d]!\n",_hostname.c_str(),_port); + stopSocketSession(); + exit(EXIT_FAILURE); + } + _isConnected = true; +} + +/********* function definitions **************************************/ + +/** + * This function returns an integer (unsigned long) representation + * of an IP address, given as a FQN or a dotted IP address. + * + * @param hostName name of a host as FQN or dotted IP address + * + * @return The return value is an integer value of a dotted IP address if + * the hostname exists (valid DNS entry) or the hostname is given + * as a dotted IP address. Otherwise the function returns + * @c INADDR_NONE. + */ +unsigned long +TraVisToClient::lookupHostAddress(const char *hostName) { + unsigned long addr; /* inet address of hostname */ + struct hostent *host; /* host structure for DNS request */ + + dtrace("entering lookupHostAddress()"); + + if (NULL == hostName) { + derror("invalid parameter"); + dtrace("leaving lookupHostAddress()"); + return (INADDR_NONE); + } + + dtrace("looking for host %s", hostName); + + addr = inet_addr(hostName); + + if (INADDR_NONE == addr) { + /* hostName isn't a dotted IP, so resolve it through DNS */ + host = gethostbyname(hostName); + if (NULL != host) { + addr = *((unsigned long *) host->h_addr); + } + } + + dtrace("leaving lookupHostAddress()"); + return (addr); +} +/******** end of function lookupHostAddress **************************/ + +/** + * This function creates a new client internet domain socket (TCP/IP) + * and connects to a service on an internet host. + * + * @param serverName hostname of a server + * @param portNumber port number of service + * + * @return The function returns a socket handle if the socket can be created + * and connected to a service. If an error occurred, the function + * returns @c INVALID_SOCKET. + */ +socket_t +TraVisToClient::createClientSocket(const char *serverName, unsigned short portNumber) { + unsigned long ipAddress; /* internet address */ + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for client socket */ + + dtrace("entering createClientSocket()"); + + /* get the IP address of the server host */ + if (INADDR_NONE == (ipAddress = lookupHostAddress(serverName))) { + derror("lookupHostAddress() failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("trying to connect %s on port %hu", serverName, portNumber); + + /* create the client socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = ipAddress; + + /* try to connect to the server socket */ + if (SOCKET_ERROR == connect(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("connect() failed"); + //FIXME + //closesocket(tcpSocket); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("leaving createClientSocket()"); + return (sock); +} +/******** end of function createClientSocket *************************/ + +/** + * This function creates a new server internet domain socket (TCP/IP). + * + * @param portNumber port number on which to listen for incoming packets + * + * @return The function returns a socket handle if the socket can be created. + * If an error occurs, the function returns @c INVALID_SOCKET. + */ +socket_t +TraVisToClient::createServerSocket(unsigned short portNumber) { + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for server socket */ + + dtrace("entering createServerSocket()"); + + /* create the server socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + /* first of all, zero srvAddr, so that we have a defined status */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + /* try to bind socket to the specified server port */ + if (SOCKET_ERROR == bind(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("bind() failed!"); + //FIXME: + //closesocket(tcpSocket); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + if (SOCKET_ERROR == listen(sock, QUEUE_LENGTH)) { + derror("listen() failed!"); + shutdownAndCloseSocket(sock); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("server started at port %hu", portNumber); + + dtrace("leaving createServerSocket()"); + return (sock); +} +/******** end of function createServerSocket *************************/ + +/** + * This function sends a message of a given size to a communication + * partner via a connected socket. + * + * @param sock socket for sending the message + * @param msg pointer to the message buffer which should be sent + * @param msgSize size of the message buffer + * + * @return The function returns @c true if the message was sent to the server, + * otherwise the function returns @c false. + */ +bool +TraVisToClient::sendMessage(socket_t sock, const void *msg, int msgSize) { + dtrace("entering sendMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving sendMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size %d", msgSize); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("sending message of size %d", msgSize); + + /* now send the message */ + if (msgSize != send(sock, (const char *) msg, msgSize, 0)) { + derror("sending message failed"); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("leaving sendMessage()"); + return (true); +} +/******** end of function sendMessage ********************************/ + +/** + * This functions receives a message from a communication partner and + * stores it into a given message buffer. + * The function blocks until all bytes have been successfully received, + * or an error occurred. + * + * @param sock socket for receiving the message + * @param[out] msg message buffer for receiving the message + * @param msgSize size of the buffer to contain the message + * + * @return The function returns @c true if all things went well. Otherwise + * the function returns @c false. + */ +bool +TraVisToClient::receiveMessage(socket_t sock, void *msg, int msgSize) { + char *msgPart; /* pointer to the memory for receiving the message */ + int toReceive; /* number of bytes to receive */ + int received; /* number of bytes totally received */ + int nBytes; /* number of bytes currently received */ + + dtrace("entering receiveMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + msgPart = (char *) msg; + received = 0; + + dtrace("trying to receive a message of size %d", msgSize); + + /* start receiving bytes from server until complete message is received */ + do { + toReceive = msgSize - received; + nBytes = recv(sock, msgPart, toReceive, 0); + switch (nBytes) { + case SOCKET_ERROR: /* error occurred */ + derror("error during message receipt"); + dtrace("leaving receiveMessage()"); + return (false); + case 0: /* connection has been closed */ + derror("remote host has closed the connection"); + dtrace("leaving receiveMessage()"); + return (false); + default: /* some bytes have been received */ + dtrace("received %d bytes of message", nBytes); + received += nBytes; + msgPart += nBytes; + break; + } + } while (received != msgSize); + + dtrace("received message of size %d", received); + + dtrace("leaving receiveMessage()"); + return (true); +} +/******** end of function receiveMessage *****************************/ + +/** + * This function shuts down and closes a given socket. + * + * @param sock socket to be closed + * + * @return if all things went ok, this function returns @c true, otherwise + * @c false + */ +bool +TraVisToClient::shutdownAndCloseSocket(socket_t sock) { + bool status = true; + + dtrace("entering shutdownAndCloseSocket()"); + + if (SOCKET_ERROR == shutdown(sock, SHUT_RDWR)) { + derror("shutdown() failed"); + status = false; + } + + //FIXME: + //if (SOCKET_ERROR == closesocket(tcpSocket)) { + // derror("closesocket() failed"); + // status = false; + //} + + dtrace("leaving shutdownAndCloseSocket()"); + return (status); +} + +/******** end of function shutdownAndCloseSocket *********************/ + +void +TraVisToClient::_printErrorMessage(void) { +} + + +#ifdef _WIN32 + +/** + * This function initializes the Win32 Socket API. + * + * @return if all things went ok, this function returns @c true, otherwise + * @c false + */ +bool +TraVisToClient::_startWin32SocketSession(void) { + WORD requestedVersion; + WSADATA wsaData; + + dtrace("entering _startWin32SocketSession()"); + + requestedVersion = MAKEWORD(WS_MAJOR_VERSION, WS_MINOR_VERSION); + + if (0 != WSAStartup(requestedVersion, &wsaData)) { + derror("WSAStartup() failed"); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + /* Confirm that the Windows Socket DLL supports 1.1. */ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if (WS_MINOR_VERSION != LOBYTE(wsaData.wVersion) + || WS_MAJOR_VERSION != HIBYTE(wsaData.wVersion)) { + derror("Windows Socket DLL does not support the requested version"); + _stopWin32SocketSession(); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + WSASetLastError(0); /* reset the error code */ + + dtrace("leaving _startWin32SocketSession()"); + return (true); +} +/******** end of function _startWin32SocketSession *******************/ + +/** + * This function terminates the Win32 Socket API. + * No future API calls are allowed. + */ +void +TraVisToClient::_stopWin32SocketSession(void) { + dtrace("entering _stopWin32SocketSession()"); + + if (SOCKET_ERROR == WSACleanup()) { + derror("WSACleanup() failed"); + } + + dtrace("leaving _stopWin32SocketSession()"); + return; +} +/******** end of function _stopWin32SocketSession ********************/ + +#endif /* _WIN32 */ + diff --git a/src/IO/TraVisToClient.h b/src/IO/TraVisToClient.h new file mode 100644 index 0000000..01eea90 --- /dev/null +++ b/src/IO/TraVisToClient.h @@ -0,0 +1,149 @@ +/** + * + * Copyright (C) <2009-2010> <Ulrich Kemloh> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim 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 JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef TRAVISTOCLIENT_H_ +#define TRAVISTOCLIENT_H_ + +#include <iostream> +#include <vector> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#ifdef _WIN32 + +#endif + +#define QUEUE_LENGTH 5 ///< max queue length of pending connections + +/******** macro definitions ******************************************/ + +#ifdef TRACE_LOGGING + +#define dtrace(...) _printDebugLine(__FILE__, __LINE__, false, __VA_ARGS__) +#define derror(...) _printDebugLine(__FILE__, __LINE__, true, __VA_ARGS__) + +#else + +#define dtrace(...) ((void) 0) +#define derror(...) (fprintf(stderr, __VA_ARGS__), _printErrorMessage()) + +#endif /* TRACE_LOGGING */ + + +#ifdef _WIN32 +#include <winsock.h> +#define WS_MAJOR_VERSION 1 ///< major version of Winsock API +#define WS_MINOR_VERSION 1 ///< minor version of Winsock API +#define SHUT_RDWR SD_BOTH ///< @c SHUT_RDWR is POSIX standard +typedef SOCKET socket_t; +typedef int socklen_t; +#define startSocketSession() _startWin32SocketSession() +#define stopSocketSession() _stopWin32SocketSession() + + +#else +#include <unistd.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <sys/socket.h> +typedef int socket_t; +#define u_int_32_t unsigned int +#define startSocketSession() (true) +#define stopSocketSession() ((void) 0) +//#define closesocket close +#define INVALID_SOCKET (-1) +#define SOCKET_ERROR (-1) +#endif + + +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED (5000) ///< up to this number, ports are reserved and should not be used +#endif + + + +#define PORT 8989 +#define HOST "localhost" + +class TraVisToClient { +public: + + /// create a client with specific parameters + TraVisToClient(std::string hostname = HOST, unsigned short port = PORT); + + /// Destructor + virtual ~TraVisToClient(); + + /// send datablock to the server + /// this functions is still blocking unfortunately, so it may + /// influence the execution time of your program + void sendData(const char* data); + + /// close the client (end the connection) + void close(); + + /// send a datagram using the unreliable + /// udp protokoll + void sendDatagram(char *datagram); + +private: + void createConnection(); + + unsigned long lookupHostAddress(const char *hostName); + + socket_t createClientSocket(const char *serverName, unsigned short portNumber); + + socket_t createServerSocket(unsigned short portNumber); + + bool shutdownAndCloseSocket(socket_t sock); + + bool sendMessage(socket_t sock, const void *msg, int msgSize); + + bool receiveMessage(socket_t sock, void *msg, int msgSize); + + void _printErrorMessage(void); + +#ifdef _WIN32 + bool _startWin32SocketSession(void); + void _stopWin32SocketSession(void); +#else + #define closesocket close +#endif + + + +private: + bool _isConnected; + socket_t _tcpSocket; + std::string _hostname; + unsigned short _port; + std::vector<const char *> _msgQueue; + +}; + +#endif /* TRAVISTOCLIENT_H_ */ -- GitLab