From 21db9c9df375452ff84c3d9cce798fc5d78eb53f Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Thu, 8 Jul 2010 18:50:14 +0200 Subject: Building rpms is now supported. On Debian based systems you need the rpm package. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 2153497..11650c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -328,7 +328,7 @@ INSTALL( PROGRAMS misc/pvs-vncsrv DESTINATION bin) INSTALL( FILES ${CMAKE_BINARY_DIR}/org.openslx.pvs.service DESTINATION share/dbus-1/services ) # add package target to our makefile -SET( CPACK_GENERATOR "DEB" ) +SET( CPACK_GENERATOR "DEB;RPM" ) SET( CPACK_SET_DESTDIR "ON" ) SET( CPACK_PACKAGE_NAME "pvs" ) SET( CPACK_PACKAGE_VERSION_MAJOR "2" ) -- cgit v1.2.3-55-g7522 From cf1ddf0b9d55b8ca8544b0ae25e8fa08738b2049 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sat, 10 Jul 2010 04:03:20 +0200 Subject: Import OpenPGM into the tree, and provide a rudimentary build script. OpenPGM will serve as the network layer for Multicast File Transfer. --- 3rdparty/CMakeLists.txt | 160 +++++++++++++++++++++++++++++++++++ 3rdparty/libpgm-5.0.63alpha1.tar.bz2 | Bin 0 -> 358887 bytes CMakeLists.txt | 10 +++ 3 files changed, 170 insertions(+) create mode 100644 3rdparty/CMakeLists.txt create mode 100644 3rdparty/libpgm-5.0.63alpha1.tar.bz2 (limited to 'CMakeLists.txt') diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt new file mode 100644 index 0000000..84f366b --- /dev/null +++ b/3rdparty/CMakeLists.txt @@ -0,0 +1,160 @@ +################################################################################ +# Build OpenPGM +################################################################################ + +# We need GLib +INCLUDE(${CMAKE_ROOT}/Modules/FindPkgConfig.cmake) + +PKG_CHECK_MODULES(GLIB glib-2.0>=2.10) +IF(NOT GLIB_FOUND) + MESSAGE(FATAL_ERROR "You don't seem to have GLib2 installed.") +ELSE(NOT GLIB_FOUND) + MESSAGE("-- GLib2 found. Libraries: ${GLIB_LIBRARIES}, CFLAGS: ${GLIB_CFLAGS}") +ENDIF(NOT GLIB_FOUND) + +# Set up build +SET(pgm_VERSION + 5.0.63alpha1 +) + +# OpenPGM will be built in the binary tree +SET(pgm + ${CMAKE_CURRENT_BINARY_DIR}/libpgm-${pgm_VERSION}/openpgm/pgm +) + +# This has been adapted from SConscript.libpgm +SET(pgm_SRCS + ${pgm}/thread.c + ${pgm}/mem.c + ${pgm}/string.c + ${pgm}/list.c + ${pgm}/slist.c + ${pgm}/queue.c + ${pgm}/hashtable.c + ${pgm}/messages.c + ${pgm}/error.c + ${pgm}/math.c + ${pgm}/packet_parse.c + ${pgm}/packet_test.c + ${pgm}/sockaddr.c + ${pgm}/time.c + ${pgm}/if.c + ${pgm}/getifaddrs.c + ${pgm}/getnodeaddr.c + ${pgm}/indextoaddr.c + ${pgm}/indextoname.c + ${pgm}/nametoindex.c + ${pgm}/inet_network.c + ${pgm}/md5.c + ${pgm}/rand.c + ${pgm}/gsi.c + ${pgm}/tsi.c + ${pgm}/txw.c + ${pgm}/rxw.c + ${pgm}/skbuff.c + ${pgm}/socket.c + ${pgm}/source.c + ${pgm}/receiver.c + ${pgm}/recv.c + ${pgm}/engine.c + ${pgm}/timer.c + ${pgm}/net.c + ${pgm}/rate_control.c + ${pgm}/checksum.c + ${pgm}/reed_solomon.c + ${pgm}/wsastrerror.c + ${pgm}/histogram.c +) + +SET(pgm_GENERATED + ${CMAKE_CURRENT_BINARY_DIR}/version.c + ${CMAKE_CURRENT_BINARY_DIR}/galois_tables.c +) + +# We need to generate galois_tables.c ... +ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/galois_tables.c + COMMAND perl ${pgm}/galois_generator.pl > ${CMAKE_CURRENT_BINARY_DIR}/galois_tables.c + DEPENDS ${pgm}/galois_generator.pl +) + +# ... and version.c ... +ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.c + COMMAND python ${pgm}/version_generator.py > ${CMAKE_CURRENT_BINARY_DIR}/version.c + DEPENDS ${pgm}/version_generator.py +) + +# ... and we need to unpack the tree. +ADD_CUSTOM_COMMAND( + OUTPUT + ${pgm_SRCS} + ${pgm}/galois_generator.pl + ${pgm}/version_generator.py + COMMAND bzip2 -dc ${CMAKE_CURRENT_SOURCE_DIR}/libpgm-${pgm_VERSION}.tar.bz2 | tar -C ${CMAKE_CURRENT_BINARY_DIR} -x +) + +INCLUDE_DIRECTORIES( + ${pgm}/include + ${GLIB_INCLUDES_DIRS} +) + +ADD_LIBRARY( + pgm + STATIC + ${pgm_SRCS} + ${pgm_GENERATED} +) + +LINK_DIRECTORIES( + ${GLIB_LIBRARY_DIRS} +) + +ADD_DEFINITIONS( + ${GLIB_CFLAGS} +) + +IF(UNIX) + IF(CMAKE_COMPILER_IS_GNUCC) + # The scripts are fine for Linux/GCC, other platforms may or may + # not work. + ADD_DEFINITIONS( + -std=gnu99 + -D_XOPEN_SOURCE=600 + -D_BSD_SOURCE + -D_REENTRANT + -DCONFIG_HAVE_GETPROTOBYNAME_R2 + -DCONFIG_HAVE_ISO_VARARGS + -DCONFIG_HAVE_ALLOCA_H + -DCONFIG_16BIT_CHECKSUM + -DCONFIG_HAVE_PROC + -DCONFIG_HAVE_BACKTRACE + -DCONFIG_HAVE_PSELECT + -DCONFIG_HAVE_RTC + -DCONFIG_HAVE_TSC + -DCONFIG_HAVE_HPET + -DCONFIG_HAVE_POLL + -DCONFIG_HAVE_EPOLL + -DCONFIG_HAVE_GETIFADDRS + -DCONFIG_HAVE_IFR_NETMASK + -DCONFIG_HAVE_MCAST_JOIN + -DCONFIG_HAVE_IP_MREQN + -DCONFIG_HAVE_SPRINTF_GROUPING + -DCONFIG_HAVE_VASPRINTF + -DCONFIG_HAVE_DSO_VISIBILITY + -DCONFIG_BIND_INADDR_ANY + -DCONFIG_GALOIS_MUL_LUT + -DCONFIG_HAVE_GETOPT + ) + + TARGET_LINK_LIBRARIES(pgm + m rt + ${GLIB_LIBRARIES}) + + SET(_SYSTEM_SPECIFICS_SET 1) + ENDIF(CMAKE_COMPILER_IS_GNUCC) +ENDIF(UNIX) + +# Complain if this is NOT Linux/GCC. +IF(NOT _SYSTEM_SPECIFICS_SET) + MESSAGE(FATAL_ERROR "Can only build libpgm on Unix with gcc.") +ENDIF(NOT _SYSTEM_SPECIFICS_SET) + diff --git a/3rdparty/libpgm-5.0.63alpha1.tar.bz2 b/3rdparty/libpgm-5.0.63alpha1.tar.bz2 new file mode 100644 index 0000000..ab4903c Binary files /dev/null and b/3rdparty/libpgm-5.0.63alpha1.tar.bz2 differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 2153497..5e63636 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,12 @@ INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ) +################################################################################ +# Build third-party libraries +################################################################################ + +ADD_SUBDIRECTORY(3rdparty) + ################################################################################ # Variables ################################################################################ @@ -299,23 +305,27 @@ TARGET_LINK_LIBRARIES( pvsmgr ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} + pgm ) TARGET_LINK_LIBRARIES( pvsmgrtouch ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} + pgm ) TARGET_LINK_LIBRARIES( pvs ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} + pgm ) TARGET_LINK_LIBRARIES( pvsgui ${QT_LIBRARIES} ${VNC_LIBRARIES} + pgm ) SET_PROPERTY(TARGET pvsmgrtouch PROPERTY COMPILE_DEFINITIONS MAINWINDOW_USE_TOUCHGUI) -- cgit v1.2.3-55-g7522 From 6940ab33b5009b79c3141dde7f98ea78a2662449 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 12 Jul 2010 04:15:13 +0200 Subject: Implement multicast transfer protocol. --- 3rdparty/CMakeLists.txt | 110 ++-- CMakeLists.txt | 10 +- OpenPGMConfig.cmake | 53 ++ src/net/mcast/CMakeLists.txt | 65 +++ src/net/mcast/McastConfiguration.cpp | 9 + src/net/mcast/McastConfiguration.h | 159 ++++++ src/net/mcast/McastConstants.h | 33 ++ src/net/mcast/McastPGMSocket.cpp | 601 +++++++++++++++++++++ src/net/mcast/McastPGMSocket.h | 74 +++ src/net/mcast/McastReceiver.cpp | 138 +++++ src/net/mcast/McastReceiver.h | 76 +++ src/net/mcast/McastSender.cpp | 96 ++++ src/net/mcast/McastSender.h | 68 +++ src/net/mcast/trial_programs/CMakeLists.txt | 38 ++ .../mcast/trial_programs/McastConfigArgParser.cpp | 151 ++++++ .../mcast/trial_programs/McastConfigArgParser.h | 26 + src/net/mcast/trial_programs/mcastreceive.cpp | 150 +++++ src/net/mcast/trial_programs/mcastreceive.h | 44 ++ src/net/mcast/trial_programs/mcastsend.cpp | 123 +++++ src/net/mcast/trial_programs/mcastsend.h | 42 ++ 20 files changed, 2008 insertions(+), 58 deletions(-) create mode 100644 OpenPGMConfig.cmake create mode 100644 src/net/mcast/CMakeLists.txt create mode 100644 src/net/mcast/McastConfiguration.cpp create mode 100644 src/net/mcast/McastConfiguration.h create mode 100644 src/net/mcast/McastConstants.h create mode 100644 src/net/mcast/McastPGMSocket.cpp create mode 100644 src/net/mcast/McastPGMSocket.h create mode 100644 src/net/mcast/McastReceiver.cpp create mode 100644 src/net/mcast/McastReceiver.h create mode 100644 src/net/mcast/McastSender.cpp create mode 100644 src/net/mcast/McastSender.h create mode 100644 src/net/mcast/trial_programs/CMakeLists.txt create mode 100644 src/net/mcast/trial_programs/McastConfigArgParser.cpp create mode 100644 src/net/mcast/trial_programs/McastConfigArgParser.h create mode 100644 src/net/mcast/trial_programs/mcastreceive.cpp create mode 100644 src/net/mcast/trial_programs/mcastreceive.h create mode 100644 src/net/mcast/trial_programs/mcastsend.cpp create mode 100644 src/net/mcast/trial_programs/mcastsend.h (limited to 'CMakeLists.txt') diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index 84f366b..8a4cea0 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -2,15 +2,9 @@ # Build OpenPGM ################################################################################ -# We need GLib -INCLUDE(${CMAKE_ROOT}/Modules/FindPkgConfig.cmake) +INCLUDE(../OpenPGMConfig.cmake) -PKG_CHECK_MODULES(GLIB glib-2.0>=2.10) -IF(NOT GLIB_FOUND) - MESSAGE(FATAL_ERROR "You don't seem to have GLib2 installed.") -ELSE(NOT GLIB_FOUND) - MESSAGE("-- GLib2 found. Libraries: ${GLIB_LIBRARIES}, CFLAGS: ${GLIB_CFLAGS}") -ENDIF(NOT GLIB_FOUND) +ADD_DEFINITIONS(${LIBPGM_CFLAGS}) # Set up build SET(pgm_VERSION @@ -19,7 +13,7 @@ SET(pgm_VERSION # OpenPGM will be built in the binary tree SET(pgm - ${CMAKE_CURRENT_BINARY_DIR}/libpgm-${pgm_VERSION}/openpgm/pgm + ${CMAKE_CURRENT_BINARY_DIR}/libpgm-src/openpgm/pgm ) # This has been adapted from SConscript.libpgm @@ -66,6 +60,35 @@ SET(pgm_SRCS ${pgm}/histogram.c ) +SET(pgm_HDRS + ${pgm}/include/pgm/atomic.h + ${pgm}/include/pgm/backtrace.h + ${pgm}/include/pgm/engine.h + ${pgm}/include/pgm/error.h + ${pgm}/include/pgm/gsi.h + ${pgm}/include/pgm/http.h + ${pgm}/include/pgm/if.h + ${pgm}/include/pgm/list.h + ${pgm}/include/pgm/log.h + ${pgm}/include/pgm/macros.h + ${pgm}/include/pgm/mem.h + ${pgm}/include/pgm/messages.h + ${pgm}/include/pgm/msgv.h + ${pgm}/include/pgm/packet.h + ${pgm}/include/pgm/pgm.h + ${pgm}/include/pgm/signal.h + ${pgm}/include/pgm/skbuff.h + ${pgm}/include/pgm/snmp.h + ${pgm}/include/pgm/socket.h + ${pgm}/include/pgm/time.h + ${pgm}/include/pgm/tsi.h + ${pgm}/include/pgm/types.h + ${pgm}/include/pgm/version.h + ${pgm}/include/pgm/winint.h + ${pgm}/include/pgm/wininttypes.h +) + + SET(pgm_GENERATED ${CMAKE_CURRENT_BINARY_DIR}/version.c ${CMAKE_CURRENT_BINARY_DIR}/galois_tables.c @@ -86,10 +109,24 @@ ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.c # ... and we need to unpack the tree. ADD_CUSTOM_COMMAND( OUTPUT - ${pgm_SRCS} + ${pgm_SRCS} + ${pgm_HDRS} ${pgm}/galois_generator.pl ${pgm}/version_generator.py - COMMAND bzip2 -dc ${CMAKE_CURRENT_SOURCE_DIR}/libpgm-${pgm_VERSION}.tar.bz2 | tar -C ${CMAKE_CURRENT_BINARY_DIR} -x + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/libpgm-${pgm_VERSION}.tar.bz2" + COMMAND rm -rf "${CMAKE_CURRENT_BINARY_DIR}/libpgm-src" + COMMAND bzip2 -dc "${CMAKE_CURRENT_SOURCE_DIR}/libpgm-${pgm_VERSION}.tar.bz2" | tar -C "${CMAKE_CURRENT_BINARY_DIR}" -x + COMMAND mv "${CMAKE_CURRENT_BINARY_DIR}/libpgm-${pgm_VERSION}" "${CMAKE_CURRENT_BINARY_DIR}/libpgm-src" +) + +ADD_CUSTOM_COMMAND(TARGET clean + COMMAND rm -rf "${CMAKE_CURRENT_BINARY_DIR}/libpgm-src" +) + +ADD_CUSTOM_TARGET( + unpack_libpgm + DEPENDS ${pgm_SRCS} ${pgm_HDRS} ) INCLUDE_DIRECTORIES( @@ -101,9 +138,14 @@ ADD_LIBRARY( pgm STATIC ${pgm_SRCS} + ${pgm_HDRS} ${pgm_GENERATED} ) +TARGET_LINK_LIBRARIES(pgm + ${LIBPGM_LIBRARIES} +) + LINK_DIRECTORIES( ${GLIB_LIBRARY_DIRS} ) @@ -112,49 +154,3 @@ ADD_DEFINITIONS( ${GLIB_CFLAGS} ) -IF(UNIX) - IF(CMAKE_COMPILER_IS_GNUCC) - # The scripts are fine for Linux/GCC, other platforms may or may - # not work. - ADD_DEFINITIONS( - -std=gnu99 - -D_XOPEN_SOURCE=600 - -D_BSD_SOURCE - -D_REENTRANT - -DCONFIG_HAVE_GETPROTOBYNAME_R2 - -DCONFIG_HAVE_ISO_VARARGS - -DCONFIG_HAVE_ALLOCA_H - -DCONFIG_16BIT_CHECKSUM - -DCONFIG_HAVE_PROC - -DCONFIG_HAVE_BACKTRACE - -DCONFIG_HAVE_PSELECT - -DCONFIG_HAVE_RTC - -DCONFIG_HAVE_TSC - -DCONFIG_HAVE_HPET - -DCONFIG_HAVE_POLL - -DCONFIG_HAVE_EPOLL - -DCONFIG_HAVE_GETIFADDRS - -DCONFIG_HAVE_IFR_NETMASK - -DCONFIG_HAVE_MCAST_JOIN - -DCONFIG_HAVE_IP_MREQN - -DCONFIG_HAVE_SPRINTF_GROUPING - -DCONFIG_HAVE_VASPRINTF - -DCONFIG_HAVE_DSO_VISIBILITY - -DCONFIG_BIND_INADDR_ANY - -DCONFIG_GALOIS_MUL_LUT - -DCONFIG_HAVE_GETOPT - ) - - TARGET_LINK_LIBRARIES(pgm - m rt - ${GLIB_LIBRARIES}) - - SET(_SYSTEM_SPECIFICS_SET 1) - ENDIF(CMAKE_COMPILER_IS_GNUCC) -ENDIF(UNIX) - -# Complain if this is NOT Linux/GCC. -IF(NOT _SYSTEM_SPECIFICS_SET) - MESSAGE(FATAL_ERROR "Can only build libpgm on Unix with gcc.") -ENDIF(NOT _SYSTEM_SPECIFICS_SET) - diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e63636..8eb1961 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,8 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.2 ) # set compiler optimizations for debug and release SET(CMAKE_BUILD_TYPE Debug) +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -Wall") +SET(CMAKE_C_FLAGS_RELEASE "-O3 -march=native") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") # -DQT_NO_DEBUG_OUTPUT") @@ -37,6 +39,12 @@ INCLUDE_DIRECTORIES( ADD_SUBDIRECTORY(3rdparty) +################################################################################ +# Common multicast transfer module +################################################################################ + +ADD_SUBDIRECTORY(src/net/mcast) + ################################################################################ # Variables ################################################################################ @@ -338,7 +346,7 @@ INSTALL( PROGRAMS misc/pvs-vncsrv DESTINATION bin) INSTALL( FILES ${CMAKE_BINARY_DIR}/org.openslx.pvs.service DESTINATION share/dbus-1/services ) # add package target to our makefile -SET( CPACK_GENERATOR "DEB" ) +SET( CPACK_GENERATOR "DEB;RPM" ) SET( CPACK_SET_DESTDIR "ON" ) SET( CPACK_PACKAGE_NAME "pvs" ) SET( CPACK_PACKAGE_VERSION_MAJOR "2" ) diff --git a/OpenPGMConfig.cmake b/OpenPGMConfig.cmake new file mode 100644 index 0000000..074e65b --- /dev/null +++ b/OpenPGMConfig.cmake @@ -0,0 +1,53 @@ +INCLUDE(${CMAKE_ROOT}/Modules/FindPkgConfig.cmake) + +PKG_CHECK_MODULES(GLIB glib-2.0>=2.10) +IF(NOT GLIB_FOUND) + MESSAGE(FATAL_ERROR "You don't seem to have GLib2 installed.") +ENDIF(NOT GLIB_FOUND) + +IF(UNIX) + IF(CMAKE_COMPILER_IS_GNUCC) + # The scripts are fine for Linux/GCC, other platforms may or may + # not work. + SET(LIBPGM_CFLAGS + -std=gnu99 + -D_XOPEN_SOURCE=600 + -D_BSD_SOURCE + -D_REENTRANT + -DCONFIG_HAVE_GETPROTOBYNAME_R2 + -DCONFIG_HAVE_ISO_VARARGS + -DCONFIG_HAVE_ALLOCA_H + -DCONFIG_16BIT_CHECKSUM + -DCONFIG_HAVE_PROC + -DCONFIG_HAVE_BACKTRACE + -DCONFIG_HAVE_PSELECT + -DCONFIG_HAVE_RTC + -DCONFIG_HAVE_TSC + -DCONFIG_HAVE_HPET + -DCONFIG_HAVE_POLL + -DCONFIG_HAVE_EPOLL + -DCONFIG_HAVE_GETIFADDRS + -DCONFIG_HAVE_IFR_NETMASK + -DCONFIG_HAVE_MCAST_JOIN + -DCONFIG_HAVE_IP_MREQN + -DCONFIG_HAVE_SPRINTF_GROUPING + -DCONFIG_HAVE_VASPRINTF + -DCONFIG_HAVE_DSO_VISIBILITY + -DCONFIG_BIND_INADDR_ANY + -DCONFIG_GALOIS_MUL_LUT + -DCONFIG_HAVE_GETOPT + ) + + SET(LIBPGM_LIBRARIES + m rt + ${GLIB_LIBRARIES}) + + SET(_SYSTEM_SPECIFICS_SET 1) + ENDIF(CMAKE_COMPILER_IS_GNUCC) +ENDIF(UNIX) + +# Complain if this is NOT Linux/GCC. +IF(NOT _SYSTEM_SPECIFICS_SET) + MESSAGE(FATAL_ERROR "Can only build libpgm on Unix with gcc.") +ENDIF(NOT _SYSTEM_SPECIFICS_SET) + diff --git a/src/net/mcast/CMakeLists.txt b/src/net/mcast/CMakeLists.txt new file mode 100644 index 0000000..e418c64 --- /dev/null +++ b/src/net/mcast/CMakeLists.txt @@ -0,0 +1,65 @@ +INCLUDE(../../../OpenPGMConfig.cmake) + +ADD_DEFINITIONS( + ${LIBPGM_CFLAGS} + -D__STDC_CONSTANT_MACROS + -D__STDC_LIMIT_MACROS +) + +# OpenPGM uses the C99 restrict keyword which g++ does not recognize: +IF(CMAKE_COMPILER_IS_GNUCXX) + ADD_DEFINITIONS(-Drestrict=__restrict__) +ENDIF(CMAKE_COMPILER_IS_GNUCXX) + +INCLUDE(${QT_USE_FILE}) + +SET(pvsmcast_MOC_HDRS + McastConfiguration.h + McastPGMSocket.h + McastReceiver.h + McastSender.h +) + +SET(pvsmcast_HDRS + McastConfiguration.h + McastPGMSocket.h + McastReceiver.h + McastSender.h +) + +SET(pvsmcast_SRCS + McastConfiguration.cpp + McastPGMSocket.cpp + McastReceiver.cpp + McastSender.cpp +) + +INCLUDE_DIRECTORIES( + ${CMAKE_BINARY_DIR}/3rdparty/libpgm-src/openpgm/pgm/include +) + +QT4_WRAP_CPP( + pvsmcast_MOC_SRCS + ${pvsmcast_MOC_HDRS} +) + +SET_SOURCE_FILES_PROPERTIES(${pvsmcast_SRCS} ${pvsmcast_MOC_SRCS} + PROPERTIES + OBJECT_DEPENDS "3rdparty/libpgm.a" # Make sure libpgm gets unpacked before building C++ files +) + +ADD_LIBRARY( + pvsmcast + STATIC + ${pvsmcast_HDRS} + ${pvsmcast_SRCS} + ${pvsmcast_MOC_SRCS} +) + +TARGET_LINK_LIBRARIES( + pvsmcast + pgm + ${QT_LIBRARIES} +) + +ADD_SUBDIRECTORY(trial_programs) diff --git a/src/net/mcast/McastConfiguration.cpp b/src/net/mcast/McastConfiguration.cpp new file mode 100644 index 0000000..1a1c0a8 --- /dev/null +++ b/src/net/mcast/McastConfiguration.cpp @@ -0,0 +1,9 @@ +/* + * McastConfiguration.cpp + * + * Created on: Jul 10, 2010 + * Author: brs + */ + +#include "McastConfiguration.h" + diff --git a/src/net/mcast/McastConfiguration.h b/src/net/mcast/McastConfiguration.h new file mode 100644 index 0000000..a609ce1 --- /dev/null +++ b/src/net/mcast/McastConfiguration.h @@ -0,0 +1,159 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastConfiguration.h +# - hold Multicast protocol configuration data +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTCONFIGURATION_H_ +#define MCASTCONFIGURATION_H_ + +#include +#include +#include + +#include "McastConstants.h" + +class McastConfiguration: public QObject +{ +Q_OBJECT +public: + McastConfiguration(QObject* parent = 0) : + QObject(parent), + _multicastAddress(DEFAULT_MULTICAST_ADDRESS), + _multicastRate(DEFAULT_MULTICAST_RATE), + _multicastSPort(DEFAULT_MULTICAST_SPORT), + _multicastDPort(DEFAULT_MULTICAST_DPORT), + _multicastWinSize(DEFAULT_MULTICAST_WSIZ), + _multicastMTU(DEFAULT_MULTICAST_MTU), + _multicastUDPPort(DEFAULT_MULTICAST_UDPPORT), + _multicastUseUDP(false) + { + } + + McastConfiguration(McastConfiguration const& other) : + QObject(), + _multicastAddress(other._multicastAddress), + _multicastRate(other._multicastRate), + _multicastSPort(other._multicastSPort), + _multicastDPort(other._multicastDPort), + _multicastWinSize(other._multicastWinSize), + _multicastMTU(other._multicastMTU), + _multicastUDPPort(other._multicastUDPPort), + _multicastUseUDP(other._multicastUseUDP) + { + } + + virtual ~McastConfiguration() + { + } + + QString multicastAddress() const + { + return _multicastAddress; + } + McastConfiguration* multicastAddress(QString const& address) + { + _multicastAddress = address; + return this; + } + + quint16 multicastSPort() const + { + return _multicastSPort; + } + McastConfiguration* multicastSPort(quint16 port) + { + _multicastSPort = port; + return this; + } + + quint16 multicastDPort() const + { + return _multicastDPort; + } + McastConfiguration* multicastDPort(quint16 port) + { + _multicastDPort = port; + return this; + } + + quint32 multicastRate() const + { + return _multicastRate; + } + McastConfiguration* multicastRate(quint32 rate) + { + _multicastRate = rate; + return this; + } + + quint16 multicastWinSize() const + { + return _multicastWinSize; + } + McastConfiguration* multicastWinSize(quint16 size) + { + _multicastWinSize = size; + return this; + } + + quint16 multicastMTU() const + { + return _multicastMTU; + } + McastConfiguration* multicastMTU(quint16 mtu) + { + _multicastMTU = mtu; + return this; + } + + bool multicastUseUDP() const + { + return _multicastUseUDP; + } + McastConfiguration* multicastUseUDP(bool useUDP) + { + _multicastUseUDP = useUDP; + return this; + } + + bool multicastUDPPort() const + { + return _multicastUDPPort; + } + McastConfiguration* multicastUDPPort(quint16 port) + { + _multicastUDPPort = port; + return this; + } + + void commit() + { + emit changed(); + } + +signals: + void changed(); + +private: + QString _multicastAddress; + quint32 _multicastRate; + quint16 _multicastSPort; + quint16 _multicastDPort; + quint16 _multicastWinSize; + quint16 _multicastMTU; + quint16 _multicastUDPPort; + bool _multicastUseUDP; +}; + +#endif /* MCASTCONFIGURATION_H_ */ diff --git a/src/net/mcast/McastConstants.h b/src/net/mcast/McastConstants.h new file mode 100644 index 0000000..712a0d5 --- /dev/null +++ b/src/net/mcast/McastConstants.h @@ -0,0 +1,33 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastMagic.h +# - Specify the magic numbers for the McastFT protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTMAGIC_H_ +#define MCASTMAGIC_H_ + +#include + +#define MCASTFT_MAGIC UINT64_C(0x6d60ad83825fb7f9) +#define DEFAULT_MULTICAST_ADDRESS ";239.255.220.207" +#define DEFAULT_MULTICAST_SPORT 6964 +#define DEFAULT_MULTICAST_DPORT 6965 +#define DEFAULT_MULTICAST_UDPPORT 6966 +#define DEFAULT_MULTICAST_RATE (100*1024) +#define DEFAULT_MULTICAST_WSIZ 3000 +#define DEFAULT_MULTICAST_MTU 1400 +#define DEFAULT_MULTICAST_APDU 1200 +#define DEFAULT_MULTICAST_CHUNK 1024 + +#endif /* MCASTMAGIC_H_ */ diff --git a/src/net/mcast/McastPGMSocket.cpp b/src/net/mcast/McastPGMSocket.cpp new file mode 100644 index 0000000..0d6b694 --- /dev/null +++ b/src/net/mcast/McastPGMSocket.cpp @@ -0,0 +1,601 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastPGMSocket.cpp +# - wrap OpenPGM Sockets in a nicer interface -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include + +#include +#include +#include +#include +#include + +#include +// #include +// #define SIZE_MAX UINT64_MAX +// #include +// pgm redefined bool to int. Undo that. +#undef bool + +#include + +#include "McastPGMSocket.h" + +class McastPGMSocket_priv +{ +public: + McastPGMSocket_priv() : + socket(0), + recv_notif(0), + repair_notif(0), + pending_notif(0), + send_notif(0) + { + } + ~McastPGMSocket_priv() + { + if (socket) + pgm_close(socket, 0); + if (recv_notif) + delete recv_notif; + if (repair_notif) + delete repair_notif; + if (pending_notif) + delete pending_notif; + if (send_notif) + delete send_notif; + } + + pgm_sock_t* socket; + McastPGMSocket::Direction direction; + QSocketNotifier* recv_notif; + QSocketNotifier* repair_notif; + QSocketNotifier* pending_notif; + QSocketNotifier* send_notif; + + QSocketNotifier* notifier_for(int fd) { + if (recv_notif && (fd == recv_notif->socket())) + { + return recv_notif; + } + else if (repair_notif && (fd == repair_notif->socket())) + { + return repair_notif; + } + else if (pending_notif && (fd == pending_notif->socket())) + { + return pending_notif; + } + return 0; + } +}; + +static void _ensurePGMInited() +{ + if (!pgm_supported()) + { + pgm_error_t* err; + int good = pgm_init(&err); + if (!good) + { + qCritical() << "Could not init OpenPGM library: PGM Error: " << (err->message ? err->message : "(null)"); + std::exit(1); + } + } +} + +McastPGMSocket::McastPGMSocket(QObject* parent) : + QObject(parent), + _priv(new McastPGMSocket_priv), + _finished(false), + _nakTimeout(new QTimer()), + _dataTimeout(new QTimer()), + _sendTimeout(new QTimer()) +{ + _ensurePGMInited(); + + _nakTimeout->setSingleShot(true); + _dataTimeout->setSingleShot(true); + _sendTimeout->setSingleShot(true); + + connect(_nakTimeout, SIGNAL(timeout()), this, SLOT(handleNakTimeout())); + connect(_dataTimeout, SIGNAL(timeout()), this, SLOT(handleDataTimeout())); + connect(_sendTimeout, SIGNAL(timeout()), this, SLOT(canSend())); +} + +McastPGMSocket::~McastPGMSocket() +{ + delete _priv; + delete _nakTimeout; + delete _dataTimeout; + delete _sendTimeout; +} + +bool McastPGMSocket::open(McastConfiguration const* config, Direction direction) +{ + _priv->direction = direction; + + pgm_error_t* err = 0; + int good; + + pgm_addrinfo_t* addrinfo; + // parse the address string + good = pgm_getaddrinfo(config->multicastAddress().toLatin1().constData(), + 0, &addrinfo, &err); + if (!good) + { + qCritical() << "Could not parse address info: PGM Error: " + << err->message; + } + + sa_family_t family = addrinfo->ai_send_addrs[0].gsr_group.ss_family; + + good + = pgm_socket(&_priv->socket, family, SOCK_SEQPACKET, IPPROTO_PGM, &err); + if (!good) + { + qCritical() << "Could not open socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + unsigned const ambient_spm = 4096 * 1000; // every four seconds (approx.) + + // set parameters + if (direction == PSOCK_WRITE) + { + // write-only socket + const int send_only = 1, + spm_heartbeat[] = + { 16 * 1000, 16 * 1000, 16 * 1000, 16 * 1000, 32 * 1000, 64 * 1000, 128 + * 1000, 256 * 1000, 512 * 1000, 1024 * 1000, 2048 * 1000, 4096 + * 1000 }, + max_rate = config->multicastRate(), + max_window = config->multicastWinSize(); + // const int max_window_sqns = 3000; + + pgm_setsockopt(_priv->socket, PGM_SEND_ONLY, &send_only, + sizeof(send_only)); + + // SPM messages + pgm_setsockopt(_priv->socket, PGM_AMBIENT_SPM, &ambient_spm, sizeof(ambient_spm)); + pgm_setsockopt(_priv->socket, PGM_HEARTBEAT_SPM, &spm_heartbeat, sizeof(spm_heartbeat)); + + // Transmit window + pgm_setsockopt(_priv->socket, PGM_TXW_MAX_RTE, &max_rate, sizeof(max_rate)); + // pgm_setsockopt(_priv->socket, PGM_TXW_SECS, &max_window, sizeof(max_window)); + pgm_setsockopt(_priv->socket, PGM_TXW_SQNS, &max_window, sizeof(max_window)); + } + else + { + // readonly + const int recv_only = 1, + passive = 0, + max_window = config->multicastWinSize(), + max_winsqns = 0, + peer_expiry = ambient_spm * 5, + spmr_expiry = 250 * 1000, + nak_bo_ivl = 500 * 1000, + nak_rpt_ivl = 500 * 1000, + nak_rdata_ivl = 2000 * 1000, + nak_data_retries = 50, + nak_ncf_retries = 50; + pgm_setsockopt(_priv->socket, PGM_RECV_ONLY, &recv_only, sizeof(recv_only)); + pgm_setsockopt(_priv->socket, PGM_PASSIVE, &passive, sizeof(passive)); + // pgm_setsockopt(_priv->socket, PGM_RXW_SECS, &max_window, sizeof(max_window)); + pgm_setsockopt(_priv->socket, PGM_RXW_SQNS, &max_window, sizeof(max_window)); + pgm_setsockopt(_priv->socket, PGM_PEER_EXPIRY, &peer_expiry, sizeof(peer_expiry)); + pgm_setsockopt(_priv->socket, PGM_SPMR_EXPIRY, &spmr_expiry, sizeof(spmr_expiry)); + pgm_setsockopt(_priv->socket, PGM_NAK_BO_IVL, &nak_bo_ivl, sizeof(nak_bo_ivl)); + pgm_setsockopt(_priv->socket, PGM_NAK_RPT_IVL, &nak_rpt_ivl, sizeof(nak_rpt_ivl)); + pgm_setsockopt(_priv->socket, PGM_NAK_RDATA_IVL, &nak_rdata_ivl, sizeof(nak_rdata_ivl)); + pgm_setsockopt(_priv->socket, PGM_NAK_DATA_RETRIES, &nak_data_retries, sizeof(nak_data_retries)); + pgm_setsockopt(_priv->socket, PGM_NAK_NCF_RETRIES, &nak_ncf_retries, sizeof(nak_ncf_retries)); + } + + // MTU + int const mtu = config->multicastMTU(); + pgm_setsockopt(_priv->socket, PGM_MTU, &mtu, sizeof(mtu)); + + pgm_sockaddr_t addr; + addr.sa_addr.sport = config->multicastSPort(); + addr.sa_port = config->multicastDPort(); + good = pgm_gsi_create_from_hostname(&addr.sa_addr.gsi, &err); + if (!good) + { + qCritical() << "Could not generate a GSI: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + good = pgm_bind3(_priv->socket, &addr, sizeof(addr), (struct group_req*)&addrinfo->ai_send_addrs[0], sizeof(struct group_req), (struct group_req*)&addrinfo->ai_recv_addrs[0], sizeof(struct group_req), &err); + if (!good) + { + qCritical() << "Could not bind socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + // qDebug() << "Max APDU is " << _priv->socket->max_apdu; + // qDebug() << "Max TPDU is " << _priv->socket->max_tpdu; + // qDebug() << "Max TSDU Fragment is " << _priv->socket->max_tsdu_fragment; + // qDebug() << "TXW_SQNS is " << _priv->socket->txw_sqns; + + // join the group + for (unsigned i = 0; i < addrinfo->ai_recv_addrs_len; i++) + { + pgm_setsockopt(_priv->socket, PGM_JOIN_GROUP, + &addrinfo->ai_recv_addrs[i], sizeof(struct group_req)); + } + + // set send address + pgm_setsockopt(_priv->socket, PGM_SEND_GROUP, &addrinfo->ai_send_addrs[0], + sizeof(struct group_req)); + + // IP parameters + const int nonblocking = 1, multicast_loop = 0, multicast_hops = 16; + pgm_setsockopt(_priv->socket, PGM_MULTICAST_LOOP, &multicast_loop, + sizeof(multicast_loop)); + pgm_setsockopt(_priv->socket, PGM_MULTICAST_HOPS, &multicast_hops, + sizeof(multicast_hops)); + pgm_setsockopt(_priv->socket, PGM_NOBLOCK, &nonblocking, + sizeof(nonblocking)); + + good = pgm_connect(_priv->socket, &err); + if (!good) + { + qCritical() << "Could not connect socket: PGM Error: " << err->message; + pgm_error_free(err); + return false; + } + + setupNotifiers(); + + pgm_freeaddrinfo(addrinfo); + + return true; +} + +void McastPGMSocket::setupNotifiers() +{ + int recv_sock, repair_sock, pending_sock; + char const* slotname = (_priv->direction == PSOCK_WRITE) ? SLOT(handleNak(int)) : SLOT(handleData(int)); + + pgm_getsockopt(_priv->socket, PGM_RECV_SOCK, &recv_sock, sizeof(recv_sock)); + _priv->recv_notif = new QSocketNotifier(recv_sock, QSocketNotifier::Read, + this); + connect(_priv->recv_notif, SIGNAL(activated(int)), this, slotname); + + pgm_getsockopt(_priv->socket, PGM_REPAIR_SOCK, &repair_sock, sizeof(repair_sock)); + _priv->repair_notif = new QSocketNotifier(repair_sock, + QSocketNotifier::Read, this); + connect(_priv->repair_notif, SIGNAL(activated(int)), this, slotname); + + pgm_getsockopt(_priv->socket, PGM_PENDING_SOCK, &pending_sock, sizeof(pending_sock)); + _priv->pending_notif = new QSocketNotifier(pending_sock, + QSocketNotifier::Read, this); + connect(_priv->pending_notif, SIGNAL(activated(int)), this, slotname); + + if(_priv->direction == PSOCK_WRITE) + { + struct pollfd pfd; + int nfds = 1; + pgm_poll_info(_priv->socket, &pfd, &nfds, POLLOUT); + _priv->send_notif = new QSocketNotifier(pfd.fd, QSocketNotifier::Write, this); + connect(_priv->send_notif, SIGNAL(activated(int)), this, SLOT(canSend())); + } +} + +void McastPGMSocket::handleNak(int fd) +{ + qDebug() << "handleNak(int)"; + + QSocketNotifier* notif = _priv->notifier_for(fd); + notif->setEnabled(false); + + handleNak(); + + notif->setEnabled(true); +} + +void McastPGMSocket::handleNak() +{ + if (_finished) + return; + + qDebug() << "handleNak()"; + + QTimer::singleShot(1000, this, SLOT(handleNakTimeout())); + + // to handle NAKs in OpenPGM, we need to pgm_recv: + char buf[4096]; + pgm_error_t* err = 0; + + int status; + // while we don't block: + do + { + status = pgm_recv(_priv->socket, buf, sizeof(buf), MSG_DONTWAIT, 0, &err); + + if(status == PGM_IO_STATUS_TIMER_PENDING) + { + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_TIME_REMAIN, &tv, sizeof(tv)); + const int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + qDebug() << " timer pending: " << msecs << "ms"; + _nakTimeout->start(msecs); + break; + } + else if(status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_RATE_REMAIN, &tv, sizeof(tv)); + const int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + qDebug() << " rate limited: " << msecs << "ms"; + _nakTimeout->start(msecs); + break; + } + else if(status == PGM_IO_STATUS_WOULD_BLOCK) + { + qDebug() << " wouldblock"; + break; + } + else + { + if(err) + { + qCritical() << "Could not handle NAKs: PGM Error: " << err->message; + pgm_error_free(err); + err = 0; + } + } + } + while (true); +} + +void McastPGMSocket::handleNakTimeout() +{ + qDebug() << "handleNakTimeout()"; + + handleNak(); +} + +void McastPGMSocket::handleData(int fd) +{ + // need to guard against destruction in finish() via signals/slots + QPointer notif(_priv->notifier_for(fd)); + notif->setEnabled(false); + + handleData(); + + if (notif) + notif->setEnabled(true); +} + +void McastPGMSocket::handleData() +{ + qDebug() << "handleData()"; + + if (_finished) { + qDebug() << " finished!"; + return; + } + + int status; + do + { + char buf[4096]; + size_t size; + pgm_error_t* err; + + status = pgm_recv(_priv->socket, buf, sizeof(buf), MSG_DONTWAIT, &size, &err); + + if (status == PGM_IO_STATUS_NORMAL) + { + qDebug() << " normally received"; + if(size > 0) + { + QByteArray bytes(buf, size); + emit receivedPacket(bytes); + } + } + else if (status == PGM_IO_STATUS_WOULD_BLOCK) + { + qDebug() << " would block"; + // nothing more to do this time + break; + } + else if (status == PGM_IO_STATUS_TIMER_PENDING) + { + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_TIME_REMAIN, &tv, sizeof(tv)); + const int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + qDebug() << " timer pending: " << msecs << "ms"; + _dataTimeout->start(msecs); + break; + } + else if (status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_RATE_REMAIN, &tv, sizeof(tv)); + const int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + qDebug() << " rate limit pending: " << msecs << "ms"; + _dataTimeout->start(msecs); + break; + } + else if (status == PGM_IO_STATUS_RESET) + { + qDebug() << " connection reset"; + emit connectionReset(); + qCritical() << "Connection Reset: PGM Error: " << (err ? err->message : "(null)"); + break; + } + else if (status == PGM_IO_STATUS_FIN) + { + qDebug() << " connection finished"; + emit connectionFinished(); + break; + } + else + { + if(err) + { + qCritical() << "Could not read packet: PGM Error: " << (err ? err->message: "(null)"); + break; + } + } + + // the socket might have been closed from under us + if (!_priv->socket) + break; + } + while (true); +} + +void McastPGMSocket::handleDataTimeout() +{ + qDebug() << "handleDataTimeout()"; + + handleData(); +} + +void McastPGMSocket::canSend() +{ + if (_finished) + return; + + qDebug() << "canSend()"; + + if (_priv->send_notif) + { + _priv->send_notif->setEnabled(false); + } + + bool reenable = true; + + while (!_q.isEmpty()) + { + int status; + QByteArray const nextPacket(_q.head()); + status = pgm_send(_priv->socket, nextPacket.constData(), nextPacket.size(), 0); + if (status == PGM_IO_STATUS_ERROR || status == PGM_IO_STATUS_RESET) + { + qCritical() << "Could not send packet: PGM Error."; + continue; + } + else if (status == PGM_IO_STATUS_WOULD_BLOCK) + { + qDebug() << " would block"; + break; + } + else if (status == PGM_IO_STATUS_RATE_LIMITED) + { + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_RATE_REMAIN, &tv, sizeof(tv)); + const int msecs = (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + qDebug() << " rate limited:" << msecs << "ms"; + _sendTimeout->start((msecs > 0) ? msecs : 1); + reenable = false; + break; + } + else if (status == PGM_IO_STATUS_NORMAL) + { + qDebug() << " sent"; + _q.dequeue(); + continue; + } + else + { + qCritical() << "Unhandled condition in McastPGMSocket::canSend()"; + } + } + + if (_priv->send_notif && reenable) + { + emit readyToSend(); + + qDebug() << " reenable notifier"; + _priv->send_notif->setEnabled(true); + } +} + +void McastPGMSocket::sendPacket(QByteArray const& bytes) +{ + if(_q.isEmpty()) + { + int status = pgm_send(_priv->socket, bytes.constData(), bytes.size(), 0); + + if (status == PGM_IO_STATUS_ERROR || status == PGM_IO_STATUS_RESET) + { + qCritical() << "Could not send packet: PGM Error."; + return; + } + else if (status == PGM_IO_STATUS_WOULD_BLOCK) + { + _q.enqueue(bytes); + } + else if (status == PGM_IO_STATUS_RATE_LIMITED) + { + _q.enqueue(bytes); + struct timeval tv; + pgm_getsockopt(_priv->socket, PGM_RATE_REMAIN, &tv, sizeof(tv)); + _dataTimeout->start((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); + } + else if (status == PGM_IO_STATUS_NORMAL) + { + return; + } + else + { + qCritical() << "Unhandled condition in McastPGMSocket::sendPacket()"; + } + } else { + _q.enqueue(bytes); + } +} + +void McastPGMSocket::finish() +{ + if(_priv->pending_notif) + { + delete _priv->pending_notif; + _priv->pending_notif = 0; + } + if(_priv->recv_notif) + { + delete _priv->recv_notif; + _priv->recv_notif = 0; + } + if(_priv->repair_notif) + { + delete _priv->repair_notif; + _priv->repair_notif = 0; + } + if(_priv->send_notif) + { + delete _priv->send_notif; + _priv->send_notif = 0; + } + + pgm_close(_priv->socket, 1); + _priv->socket = 0; + + _finished = true; +} + +bool McastPGMSocket::finished() const +{ + return _finished; +} diff --git a/src/net/mcast/McastPGMSocket.h b/src/net/mcast/McastPGMSocket.h new file mode 100644 index 0000000..b0007a7 --- /dev/null +++ b/src/net/mcast/McastPGMSocket.h @@ -0,0 +1,74 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastPGMSocket.h +# - wrap OpenPGM Sockets in a nicer interface -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTPGMSOCKET_H_ +#define MCASTPGMSOCKET_H_ + +#include +#include +#include + +#include + +class McastPGMSocket_priv; +class QTimer; + +class McastPGMSocket : public QObject +{ + Q_OBJECT +public: + enum Direction { + PSOCK_READ, + PSOCK_WRITE + }; + + McastPGMSocket(QObject* parent = 0); + virtual ~McastPGMSocket(); + + bool open(McastConfiguration const* config, Direction direction); + bool finished() const; + +signals: + void readyToSend(); + void receivedPacket(QByteArray const& bytes); + void connectionReset(); + void connectionFinished(); + +public slots: + void sendPacket(QByteArray const& bytes); + void finish(); + +private slots: + void handleNak(int fd); + void handleData(int fd); + void handleNak(); + void handleData(); + void handleNakTimeout(); + void handleDataTimeout(); + void canSend(); + +private: + McastPGMSocket_priv* _priv; + QQueue _q; + bool _finished; + QTimer* _nakTimeout; + QTimer* _dataTimeout; + QTimer* _sendTimeout; + + void setupNotifiers(); +}; + +#endif /* MCASTPGMSOCKET_H_ */ diff --git a/src/net/mcast/McastReceiver.cpp b/src/net/mcast/McastReceiver.cpp new file mode 100644 index 0000000..7480ac2 --- /dev/null +++ b/src/net/mcast/McastReceiver.cpp @@ -0,0 +1,138 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include +#include +#include + +#include +// OpenPGM #defines bool. This is bad in C++. +#undef bool + +#include "McastConstants.h" +#include "McastReceiver.h" + +McastReceiver::McastReceiver(QIODevice* iodev, McastConfiguration* config, QObject* parent) : + QObject(parent), + _config(config ? new McastConfiguration(*config) : new McastConfiguration()), + _socket(0), + _curoffs(0), + _closed(false), + _hash(QCryptographicHash::Md5), + _iodev(iodev) +{ + _config->setParent(this); +} + +McastReceiver::~McastReceiver() +{ + if (_config) + delete _config; +} + +void McastReceiver::start() +{ + _socket = new McastPGMSocket(this); + connect(_socket, SIGNAL(receivedPacket(QByteArray)), this, SLOT(receivedPacket(QByteArray))); + connect(_socket, SIGNAL(connectionReset()), this, SLOT(connectionReset())); + // connect(_socket, SIGNAL(connectionFinished()), this, SLOT(connectionFinished())); + _socket->open(_config, McastPGMSocket::PSOCK_READ); +} + +void McastReceiver::receivedPacket(QByteArray const& bytes) +{ + if(_closed) + return; + + quint16 checksum_should = qChecksum(bytes.constData(), bytes.size() - 2); + + QDataStream strm(bytes); + strm.setByteOrder(QDataStream::BigEndian); + + // read the packet + quint64 magic; + quint64 offset; + quint16 checksum; + + + strm >> magic; + if(magic != MCASTFT_MAGIC) + { + qCritical() << "Received packet whose magic number does not match. Ignoring."; + return; + } + + strm >> offset; + qDebug() << " Received packet for offset" << offset; + + if (offset == UINT64_C(0xffffffffffffffff)) + { + // this is the end of the data stream. + QByteArray md5; + strm >> md5; + + quint16 fchecksum; + strm >> fchecksum; + + // compare the hash value + if ((fchecksum != checksum_should) || (md5 != _hash.result())) + { + _close(RES_MD5_MISMATCH); + } + else + { + _close(RES_OK); + } + + return; + } + else if (offset != _curoffs) + { + qCritical() << "Packet loss or double delivery. PGM should have prevented this. Bailing out."; + _close(RES_OFFSET_MISMATCH); + return; + } + + QByteArray contents; + strm >> contents; + _curoffs += contents.size(); + + strm >> checksum; + if(checksum != checksum_should) + { + qCritical() << "Checksum does not match. Bailing out."; + _close(RES_CHECKSUM_MISMATCH); + return; + } + + _hash.addData(contents); + + _iodev->write(contents); +} + +void McastReceiver::connectionReset() +{ + _close(RES_CONNECTION_RESET); +} + +void McastReceiver::_close(Result result) +{ + _iodev->close(); + _socket->finish(); + + _closed = true; + emit finished(result); +} diff --git a/src/net/mcast/McastReceiver.h b/src/net/mcast/McastReceiver.h new file mode 100644 index 0000000..38e1219 --- /dev/null +++ b/src/net/mcast/McastReceiver.h @@ -0,0 +1,76 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTRECEIVER_H_ +#define MCASTRECEIVER_H_ + +#include +#include +#include +#include +#include + +#include +#include + +class McastReceiver : public QObject +{ + Q_OBJECT +public: + enum Result { + RES_OK, + RES_ABORTED, + RES_OFFSET_MISMATCH, + RES_CHECKSUM_MISMATCH, + RES_MD5_MISMATCH, + RES_CONNECTION_RESET + }; + + McastReceiver(QIODevice* iodev, McastConfiguration* config = 0, QObject* parent = 0); + virtual ~McastReceiver(); + + McastConfiguration* config() + { + return _config; + } + + static inline bool is_error(Result result) + { + return result != RES_OK; + } + +signals: + void finished(int result); + +public slots: + void start(); + +private: + McastConfiguration* _config; + McastPGMSocket* _socket; + quint64 _curoffs; + bool _closed; + QCryptographicHash _hash; + QIODevice* _iodev; + +private slots: + void receivedPacket(QByteArray const& bytes); + void connectionReset(); + + void _close(Result result); +}; + +#endif /* MCASTRECEIVER_H_ */ diff --git a/src/net/mcast/McastSender.cpp b/src/net/mcast/McastSender.cpp new file mode 100644 index 0000000..24a629c --- /dev/null +++ b/src/net/mcast/McastSender.cpp @@ -0,0 +1,96 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the receiver-side multicast file transfer protocol -- implementation +# ----------------------------------------------------------------------------- +*/ + +#include "McastSender.h" +#include "McastConstants.h" + +#include + +#include +// OpenPGM #defines bool. This is bad in C++. +#undef bool + +McastSender::McastSender(QIODevice* iodev, McastConfiguration const* config, QObject* parent) : + QObject(parent), + _config(config ? new McastConfiguration(*config) : new McastConfiguration()), + _socket(0), + _iodev(iodev), + _curoffs(0), + _hash(QCryptographicHash::Md5), + _finished(false) +{ +} + +McastSender::~McastSender() +{ + delete _config; +} + +void McastSender::start() +{ + _socket = new McastPGMSocket(this); + connect(_socket, SIGNAL(readyToSend()), this, SLOT(readyToSend())); + _socket->open(_config, McastPGMSocket::PSOCK_WRITE); +} + +void McastSender::readyToSend() +{ + if(_finished) + return; + + if(_iodev->atEnd()) + { + QByteArray fpdu; + QDataStream strm(&fpdu, QIODevice::WriteOnly); + strm.setByteOrder(QDataStream::BigEndian); + + strm << (quint64)MCASTFT_MAGIC << (quint64)UINT64_C(0xffffffffffffffff) << _hash.result(); + strm << qChecksum(fpdu.constData(), fpdu.size()); + + _socket->sendPacket(fpdu); + // _socket->finish(); + + _finished = true; + + emit finished(); + return; + } + + QByteArray barr(DEFAULT_MULTICAST_APDU, '\0'); + qint64 len_read; + len_read = _iodev->read(barr.data(), barr.capacity()); + barr.resize((int)len_read); + + _hash.addData(barr); + + QByteArray pdu; + QDataStream strm(&pdu, QIODevice::WriteOnly); + strm.setByteOrder(QDataStream::BigEndian); + + strm << (quint64)MCASTFT_MAGIC << _curoffs; + strm << barr; + quint16 checksum = qChecksum(pdu.constData(), pdu.size()); + strm << checksum; + + _curoffs += len_read; + + _socket->sendPacket(pdu); +} + +void McastSender::close() +{ + _socket->finish(); +} diff --git a/src/net/mcast/McastSender.h b/src/net/mcast/McastSender.h new file mode 100644 index 0000000..e713886 --- /dev/null +++ b/src/net/mcast/McastSender.h @@ -0,0 +1,68 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/McastReceiver.h +# - implement the sender-side multicast file transfer protocol -- interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTSENDER_H_ +#define MCASTSENDER_H_ + +#include +#include +#include + +#include "McastConfiguration.h" +#include "McastPGMSocket.h" + +class McastSender : public QObject +{ + Q_OBJECT +public: + McastSender(QIODevice* iodev = 0, McastConfiguration const* config = 0, QObject* parent = 0); + virtual ~McastSender(); + + McastConfiguration* config() + { + return _config; + } + + QIODevice* iodevice() const + { + return _iodev; + } + + void setIODevice(QIODevice* iodevice) + { + _iodev = iodevice; + } + +signals: + void finished(); + +public slots: + void start(); + void close(); + +private slots: + void readyToSend(); + +private: + McastConfiguration* _config; + McastPGMSocket* _socket; + QIODevice* _iodev; + quint64 _curoffs; + QCryptographicHash _hash; + bool _finished; +}; + +#endif /* MCASTSENDER_H_ */ diff --git a/src/net/mcast/trial_programs/CMakeLists.txt b/src/net/mcast/trial_programs/CMakeLists.txt new file mode 100644 index 0000000..d0f68fa --- /dev/null +++ b/src/net/mcast/trial_programs/CMakeLists.txt @@ -0,0 +1,38 @@ +INCLUDE(${QT_USE_FILE}) + +QT4_WRAP_CPP( + mcastsend_MOC + mcastsend.h +) + +QT4_WRAP_CPP( + mcastreceive_MOC + mcastreceive.h +) + +SET(argparser_SRC + McastConfigArgParser.h + McastConfigArgParser.cpp +) + +ADD_EXECUTABLE(mcastsend + mcastsend.cpp + mcastsend.h + ${argparser_SRC} + ${mcastsend_MOC} +) + +ADD_EXECUTABLE(mcastreceive + mcastreceive.cpp + mcastreceive.h + ${argparser_SRC} + ${mcastreceive_MOC} +) + +TARGET_LINK_LIBRARIES(mcastsend + pvsmcast +) + +TARGET_LINK_LIBRARIES(mcastreceive + pvsmcast +) \ No newline at end of file diff --git a/src/net/mcast/trial_programs/McastConfigArgParser.cpp b/src/net/mcast/trial_programs/McastConfigArgParser.cpp new file mode 100644 index 0000000..8849544 --- /dev/null +++ b/src/net/mcast/trial_programs/McastConfigArgParser.cpp @@ -0,0 +1,151 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/McastConfigArgParser.cpp +# - Parse common Multicast Configuration CLI arguments +# ----------------------------------------------------------------------------- +*/ + +#include + +#include + +#include "McastConfigArgParser.h" + +using namespace std; + +bool parseMcastConfigArg(QStringList::iterator& i, QStringList::iterator const& end, McastConfiguration* config) +{ + QString arg = *i; + + if (arg == "-addr") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + config->multicastAddress(*i); + } + else if (arg == "-dport") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 dport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: dport is not an integer" << endl; + return false; + } + config->multicastDPort(dport); + } + else if (arg == "-sport") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 sport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: sport is not an integer" << endl; + return false; + } + config->multicastSPort(sport); + } + else if (arg == "-mtu") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 mtu = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: MTU is not an integer" << endl; + return false; + } + config->multicastMTU(mtu); + } + else if (arg == "-rate") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint32 rate = i->toInt(&ok); + if (!ok) + { + cerr << "Error: Rate is not an integer" << endl; + return false; + } + config->multicastRate(rate); + } + else if (arg == "-winsize") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 winsize = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: Winsize is not an integer" << endl; + return false; + } + config->multicastWinSize(winsize); + } + else if (arg == "-udp") + { + config->multicastUseUDP(true); + } + else if (arg == "-udp-port") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + return false; + } + bool ok; + quint16 udpport = (quint16)i->toInt(&ok); + if (!ok) + { + cerr << "Error: UDP-Port is not an integer" << endl; + return false; + } + config->multicastUDPPort(udpport); + } + else + { + return false; + } + + return true; +} diff --git a/src/net/mcast/trial_programs/McastConfigArgParser.h b/src/net/mcast/trial_programs/McastConfigArgParser.h new file mode 100644 index 0000000..4fb18a7 --- /dev/null +++ b/src/net/mcast/trial_programs/McastConfigArgParser.h @@ -0,0 +1,26 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/McastConfigArgParser.h +# - Parse common Multicast Configuration CLI arguments +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTCONFIGARGPARSER_H_ +#define MCASTCONFIGARGPARSER_H_ + +#include + +#include "../McastConfiguration.h" + +bool parseMcastConfigArg(QStringList::iterator& i, QStringList::iterator const& end, McastConfiguration* config); + +#endif /* MCASTCONFIGARGPARSER_H_ */ diff --git a/src/net/mcast/trial_programs/mcastreceive.cpp b/src/net/mcast/trial_programs/mcastreceive.cpp new file mode 100644 index 0000000..48a0f10 --- /dev/null +++ b/src/net/mcast/trial_programs/mcastreceive.cpp @@ -0,0 +1,150 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Receive a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#include + +#include +#include +#include +#include + +#include "mcastreceive.h" +#include "McastConfigArgParser.h" +#include "../McastConfiguration.h" +#include "../McastReceiver.h" + +using namespace std; + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + McastReceive me; + + QTimer::singleShot(0, &me, SLOT(run())); + + return app.exec(); +} + +void McastReceive::run() +{ + QStringList args = QCoreApplication::arguments(); + QStringList::iterator i = args.begin(); + QStringList::iterator const end = args.end(); + + QString filename(""); + + McastConfiguration config; + + ++i; + while (i != end) + { + QString arg = *i; + + cerr << "Arg: " << arg.toLatin1().constData() << endl; + + if (arg == "-file") + { + ++i; + if (i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing its argument" << endl; + QCoreApplication::exit(1); + return; + } + filename = *i; + } + else if (arg == "-help") + { + cerr << "Options:" << endl << endl + << " -file Receive to file FILE" << endl + << " -addr Use ADDR as address specification" << endl + << " -dport Send to port PORT" << endl + << " -sport Send from port PORT" << endl + << " -mtu Set MTU to BYTES" << endl + << " -rate Send BYTES per second" << endl + << " -winsize Set Window Size to SECONDS" << endl + << " -udp Use UDP encapsulation" << endl + << " -udp-port PORT Use UDP port PORT" << endl; + QCoreApplication::quit(); + return; + } + else + { + if (!parseMcastConfigArg(i, end, &config)) + { + cerr << "Unknown argument: " << arg.toLatin1().constData() << endl; + QCoreApplication::exit(1); + return; + } + } + + ++i; + } + + if (filename == "") + { + cerr << "No Filename given" << endl; + QCoreApplication::exit(1); + return; + } + + _target = new QFile(filename, this); + _target->open(QIODevice::WriteOnly); + + McastReceiver* recv = new McastReceiver(_target, &config, this); + + connect(recv, SIGNAL(finished(int)), this, SLOT(finished(int))); + + QTimer::singleShot(0, recv, SLOT(start())); +} + +void McastReceive::finished(int state) +{ + cerr << "finished: "; + + switch(state) + { + case McastReceiver::RES_OK: + cerr << "OK." << endl; + break; + case McastReceiver::RES_ABORTED: + cerr << "Aborted." << endl; + goto failed; + case McastReceiver::RES_CHECKSUM_MISMATCH: + cerr << "Checksum mismatch." << endl; + goto failed; + case McastReceiver::RES_CONNECTION_RESET: + cerr << "Connection reset." << endl; + goto failed; + case McastReceiver::RES_MD5_MISMATCH: + cerr << "MD5 mismatch." << endl; + goto failed; + case McastReceiver::RES_OFFSET_MISMATCH: + cerr << "Offset mismatch. Undetected packet loss?" << endl; + goto failed; + default: + cerr << "Unknown error code!" << endl; + goto failed; + } + + QCoreApplication::quit(); + return; +failed: + cerr << "Deleting file." << endl; + _target->remove(); + QCoreApplication::exit(1); + return; +} diff --git a/src/net/mcast/trial_programs/mcastreceive.h b/src/net/mcast/trial_programs/mcastreceive.h new file mode 100644 index 0000000..3e72d4c --- /dev/null +++ b/src/net/mcast/trial_programs/mcastreceive.h @@ -0,0 +1,44 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Receive a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTRECEIVE_H_ +#define MCASTRECEIVE_H_ + +#include + +class QFile; +class McastReceiver; + +class McastReceive : public QObject +{ + Q_OBJECT +public: + McastReceive() : + QObject(), + _receiver(0) + { + } + +public slots: + void run(); + void finished(int state); + +private: + McastReceiver* _receiver; + QFile* _target; +}; + +#endif /* MCASTRECEIVE_H_ */ diff --git a/src/net/mcast/trial_programs/mcastsend.cpp b/src/net/mcast/trial_programs/mcastsend.cpp new file mode 100644 index 0000000..da8ecf4 --- /dev/null +++ b/src/net/mcast/trial_programs/mcastsend.cpp @@ -0,0 +1,123 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Send a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#include + +#include +#include +#include +#include + +#include +#include "mcastsend.h" +#include "McastConfigArgParser.h" +#include "../McastConstants.h" +#include "../McastConfiguration.h" + +using namespace std; + +int +main(int argc, char**argv) +{ + QCoreApplication app(argc, argv); + McastSend me; + + QTimer::singleShot(0, &me, SLOT(run())); + + return app.exec(); +} + +void McastSend::run() +{ + QStringList args = QCoreApplication::arguments(); + QStringList::iterator i = args.begin(); + QStringList::iterator const end = args.end(); + QString filename(""); + McastConfiguration config; + + ++i; + while(i != end) + { + // parse command line arguments + + QString arg = *i; + + cerr << "Arg: " << arg.toLatin1().constData() << endl; + + if (arg == "-file") + { + i++; + if(i == end) + { + cerr << "Option " << arg.toLatin1().constData() << " is missing argument" << endl; + QCoreApplication::exit(1); + return; + } + filename = *i; + } + else if (arg == "-help") + { + cerr << "Options:" << endl << endl + << " -file Send FILE to the listeners" << endl + << " -addr Use ADDR as address specification" << endl + << " -dport Send to port PORT" << endl + << " -sport Send from port PORT" << endl + << " -mtu Set MTU to BYTES" << endl + << " -rate Send BYTES per second" << endl + << " -winsize Set Window Size to SECONDS" << endl + << " -udp Use UDP encapsulation" << endl + << " -udp-port PORT Use UDP port PORT" << endl; + QCoreApplication::quit(); + return; + } + else + { + if (!parseMcastConfigArg(i, end, &config)) + { + cerr << "Unknown command line argument: " << arg.toLatin1().constData() << endl; + QCoreApplication::exit(1); + return; + } + } + + ++i; + } + + if(filename == "") + { + cerr << "No filename given" << endl; + QCoreApplication::exit(1); + return; + } + + // now, do it. + QFile* file = new QFile(filename); + file->open(QIODevice::ReadOnly); + + McastSender* sender = new McastSender(file, &config, this); + file->setParent(sender); + + connect(sender, SIGNAL(finished()), this, SLOT(finished())); + + QTimer::singleShot(0, sender, SLOT(start())); +} + +void McastSend::finished() +{ + cerr << "finished." << endl; + // QTimer::singleShot(30000, QCoreApplication::instance(), SLOT(quit())); + // QCoreApplication::quit(); +} diff --git a/src/net/mcast/trial_programs/mcastsend.h b/src/net/mcast/trial_programs/mcastsend.h new file mode 100644 index 0000000..ae15eb4 --- /dev/null +++ b/src/net/mcast/trial_programs/mcastsend.h @@ -0,0 +1,42 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/mcast/trial_programs/mcastsend.cpp +# - Send a file via the PVS Mcast protocol +# ----------------------------------------------------------------------------- +*/ + +#ifndef MCASTSEND_H_ +#define MCASTSEND_H_ + +#include + +#include "../McastSender.h" + +class McastSend : public QObject +{ + Q_OBJECT +public: + McastSend() : + QObject(), + _sender(0) + { + } + +public slots: + void run(); + void finished(); + +private: + McastSender* _sender; +}; + +#endif /* MCASTSEND_H_ */ -- cgit v1.2.3-55-g7522 From 1219e4b7f14fff9f82e58ef3b243f709e541de68 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Fri, 16 Jul 2010 17:43:52 +0200 Subject: Compiler optimizations for "Release" changed --- CMakeLists.txt | 4 ++-- i18n/pvs_ar_JO.ts | 8 ++++---- i18n/pvs_de_DE.ts | 8 ++++---- i18n/pvs_es_MX.ts | 8 ++++---- i18n/pvs_fr_FR.ts | 8 ++++---- i18n/pvs_pl_PL.ts | 11 ++++------- 6 files changed, 22 insertions(+), 25 deletions(-) (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 11650c2..9570774 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.2 ) # set compiler optimizations for debug and release SET(CMAKE_BUILD_TYPE Debug) SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") -SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") -# -DQT_NO_DEBUG_OUTPUT") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") +# -march=native -DQT_NO_DEBUG_OUTPUT") # local cmake modules SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) diff --git a/i18n/pvs_ar_JO.ts b/i18n/pvs_ar_JO.ts index 5cb6fc0..c1b19cb 100644 --- a/i18n/pvs_ar_JO.ts +++ b/i18n/pvs_ar_JO.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_de_DE.ts b/i18n/pvs_de_DE.ts index 5cb6fc0..c1b19cb 100644 --- a/i18n/pvs_de_DE.ts +++ b/i18n/pvs_de_DE.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_es_MX.ts b/i18n/pvs_es_MX.ts index 5cb6fc0..c1b19cb 100644 --- a/i18n/pvs_es_MX.ts +++ b/i18n/pvs_es_MX.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_fr_FR.ts b/i18n/pvs_fr_FR.ts index 5cb6fc0..c1b19cb 100644 --- a/i18n/pvs_fr_FR.ts +++ b/i18n/pvs_fr_FR.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_pl_PL.ts b/i18n/pvs_pl_PL.ts index e9a8251..c1b19cb 100644 --- a/i18n/pvs_pl_PL.ts +++ b/i18n/pvs_pl_PL.ts @@ -4,25 +4,22 @@ PVS - + Message - - + VNC connection - - + The host - - + requested your screen! -- cgit v1.2.3-55-g7522 From 2ad0ca683dfade47078a2aafce9921ca238a9436 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sat, 17 Jul 2010 16:43:08 +0200 Subject: Implement UI and pvsDaemon components for outgoing Multicast Transfer --- CMakeLists.txt | 7 +- src/gui/clientFileSendDialog.cpp | 201 ++++++++++++++++++++++++++--- src/gui/clientFileSendDialog.h | 21 ++++ src/gui/ui/clientFileSendDialog.ui | 15 ++- src/gui/ui/clientNicklistDialog.ui | 7 ++ src/net/mcast/McastConfiguration.cpp | 39 ++++++ src/net/mcast/McastConfiguration.h | 5 + src/net/mcast/McastPGMSocket.cpp | 12 +- src/net/mcast/McastSender.cpp | 2 +- src/net/pvsOutgoingMulticastTransfer.cpp | 209 +++++++++++++++++++++++++++++++ src/net/pvsOutgoingMulticastTransfer.h | 92 ++++++++++++++ src/net/pvsServerConnection.h | 7 +- src/pvs.cpp | 60 +++++++++ src/pvs.h | 17 +++ 14 files changed, 661 insertions(+), 33 deletions(-) create mode 100644 src/net/pvsOutgoingMulticastTransfer.cpp create mode 100644 src/net/pvsOutgoingMulticastTransfer.h (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8eb1961..93e281e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ SET( PVS_SRCS src/net/pvsDiscoveredServer.cpp src/util/TextFile.cpp src/util/serviceDiscoveryUtil.cpp + src/net/pvsOutgoingMulticastTransfer.cpp ) # pvsgui @@ -192,6 +193,7 @@ SET( PVS_MOC_HDRS src/net/pvsServerConnection.h src/net/pvsServiceDiscovery.h src/net/pvsDiscoveredServer.h + src/net/pvsOutgoingMulticastTransfer.h ) SET( PVSGUI_MOC_HDRS @@ -313,27 +315,24 @@ TARGET_LINK_LIBRARIES( pvsmgr ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} - pgm ) TARGET_LINK_LIBRARIES( pvsmgrtouch ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} - pgm ) TARGET_LINK_LIBRARIES( pvs ${QT_LIBRARIES} ${VNC_LIBRARIES} ${X11_LIBRARIES} - pgm + pvsmcast ) TARGET_LINK_LIBRARIES( pvsgui ${QT_LIBRARIES} ${VNC_LIBRARIES} - pgm ) SET_PROPERTY(TARGET pvsmgrtouch PROPERTY COMPILE_DEFINITIONS MAINWINDOW_USE_TOUCHGUI) diff --git a/src/gui/clientFileSendDialog.cpp b/src/gui/clientFileSendDialog.cpp index ccb44b3..25e3eaa 100644 --- a/src/gui/clientFileSendDialog.cpp +++ b/src/gui/clientFileSendDialog.cpp @@ -22,6 +22,10 @@ ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) : { setupUi(this); + _transferID = 0; + _error = false; + _isMulticast = false; + _file = NULL; _socket = NULL; _clientNicklistDialog = new ClientNicklistDialog(this); @@ -60,7 +64,15 @@ void ClientFileSendDialog::open() reject(); return; } - open(_clientNicklistDialog->getNick()); + + if (_clientNicklistDialog->isSendToAll()) + { + sendToAll(); + } + else + { + open(_clientNicklistDialog->getNick()); + } } void ClientFileSendDialog::open(QString nick) @@ -75,6 +87,70 @@ void ClientFileSendDialog::open(QString nick) open(nick, filename); } +void ClientFileSendDialog::sendToAll() +{ + QString filename = QFileDialog::getOpenFileName(this, tr("Send File"), QDir::homePath(), ""); + if (filename == "") + { + reject(); + return; + } + sendToAll(filename); +} + +void ClientFileSendDialog::sendToAll(QString filename) +{ + _isMulticast = true; + + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferStarted(qulonglong)), SLOT(multicastTransferStarted(qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferProgress(qulonglong,qulonglong,qulonglong)), SLOT(multicastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFinished(qulonglong)), SLOT(multicastTransferFinished(qulonglong))); + connect(_ifaceDBus, SIGNAL(outgoingMulticastTransferFailed(qulonglong, QString const&)), SLOT(multicastTransferFailed(qulonglong, QString const&))); + + filenameLabel->setText(filename); + progressBar->setRange(0, 0); + labelNick->setText(tr("all")); + labelStatus->setText(tr("Waiting to start")); + + QString errorMessage("Backend error"); + + // We need to jump through a lot of hoops because this call is prone to time out, and + // QtDBus does not support specifying timeouts in generated interfaces. + QDBusMessage call = QDBusMessage::createMethodCall("org.openslx.pvs", "/", "org.openslx.pvs", "createMulticastTransfer"); + call << filename; + + QDBusMessage reply = _ifaceDBus->connection().call(call, QDBus::Block, 5000); + if (reply.type() == QDBusMessage::ErrorMessage) + { + QMessageBox::critical(this, tr("File Send error"), tr("Error communicating with backend: %1: %2").arg(reply.errorName()).arg(reply.errorMessage())); + reject(); + return; + } + else if (reply.type() == QDBusMessage::InvalidMessage) + { + QMessageBox::critical(this, tr("File Send error"), tr("Something went wrong while communicating with backend, but I don't know what.")); + reject(); + return; + } + else if (reply.type() == QDBusMessage::ReplyMessage) + { + QList args = reply.arguments(); + bool created = args.at(0).toBool(); + _transferID = args.at(1).toULongLong(); + QString errorMessage = args.at(2).toString(); + if (!created) + { + QMessageBox::critical(this, tr("File Send error"), tr("Could not create a multicast transfer: %1").arg(errorMessage)); + reject(); + return; + } + } + + connect(cancelButton, SIGNAL(clicked()), SLOT(canceled())); + + show(); +} + void ClientFileSendDialog::open(QString nick, QString filename) { // open file @@ -129,6 +205,8 @@ void ClientFileSendDialog::receiveAck() QString ack = QString::fromUtf8(_socket->readLine()); if (ack != "ok\n") { + _error = true; + _reason = tr("Receiver declined"); qDebug("[%s] Received nack!", metaObject()->className()); close(); return; @@ -160,27 +238,30 @@ void ClientFileSendDialog::sendFile() void ClientFileSendDialog::close() { - if (_file && _file->isOpen()) - { - _file->close(); - qDebug("[%s] File closed.", metaObject()->className()); - } - - if (_socket && _socket->isOpen()) + if (!_isMulticast) { - disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); - disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); - disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close())); - disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); - disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(error(QAbstractSocket::SocketError))); - _socket->disconnectFromHost(); - qDebug("[%s] Connection closed.", metaObject()->className()); + if (_file && _file->isOpen()) + { + _file->close(); + qDebug("[%s] File closed.", metaObject()->className()); + } + + if (_socket && _socket->isOpen()) + { + disconnect(_socket, SIGNAL(readyRead()), this, SLOT(receiveAck())); + disconnect(_socket, SIGNAL(bytesWritten(qint64)), this, SLOT(sendFile())); + disconnect(_socket, SIGNAL(disconnected()), this, SLOT(close())); + disconnect(_socket, SIGNAL(connected()), this, SLOT(sendHeader())); + disconnect(_socket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(error(QAbstractSocket::SocketError))); + _socket->disconnectFromHost(); + qDebug("[%s] Connection closed.", metaObject()->className()); + } } - disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(close())); + disconnect(cancelButton, SIGNAL(clicked()), this, SLOT(canceled())); - if (_bytesToWrite == 0) + if (!_error) { accept(); QMessageBox::information(0, tr("PVS - File Transfer"), @@ -190,12 +271,26 @@ void ClientFileSendDialog::close() { reject(); QMessageBox::warning(0, tr("PVS - File Transfer"), - tr("File Transfer canceled!")); + tr("File Transfer canceled: %1").arg(_reason)); } } +void ClientFileSendDialog::canceled() +{ + if(_isMulticast) + { + _ifaceDBus->cancelOutgoingMulticastTransfer(_transferID); + } + + _error = true; + _reason = tr("You clicked 'Cancel'"); + close(); +} + void ClientFileSendDialog::error(QAbstractSocket::SocketError error) { + _error = true; + _reason = tr("Socket Error"); qDebug("[%s] Socket error: %i", metaObject()->className(), error); close(); } @@ -212,6 +307,55 @@ QString ClientFileSendDialog::formatSize(qint64 size) return QString("%1B").arg((qreal)size, 0, 'f',1); } +void ClientFileSendDialog::multicastTransferStarted(qulonglong transferID) +{ + qDebug() << "multicastTransferStarted(" << transferID << ")"; + if (transferID != _transferID) + { + return; + } + labelStatus->setText("Started"); +} + +void ClientFileSendDialog::multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of) +{ + qDebug() << "multicastTransferProgress(" << transferID << bytes << of << ")"; + if (transferID != _transferID) + { + return; + } + + if(bytes < of) + { + labelStatus->setText("Transferring"); + progressBar->setRange(0, of); + progressBar->setValue(bytes); + } + else + { + labelStatus->setText("Waiting to finish"); + progressBar->setRange(0, 0); + } + + labelA->setText(formatSize(bytes)); + labelB->setText(formatSize(of)); +} + +void ClientFileSendDialog::multicastTransferFinished(quint64 transferID) +{ + qDebug() << "multicastTransferFinished(" << transferID << ")"; + qDebug("[%s] MulticastTransfer finished", metaObject()->className()); + close(); +} + +void ClientFileSendDialog::multicastTransferFailed(quint64 transferID, QString const& reason) +{ + qDebug() << "multicastTransferFailed(" << transferID << reason << ")"; + _error = true; + _reason = reason; + close(); +} + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -235,6 +379,25 @@ ClientNicklistDialog::ClientNicklistDialog(QWidget *parent) : listWidget->addItems(nicknames); listWidget->setCurrentRow(0); + + connect(sendToAllCheckBox, SIGNAL(stateChanged(int)), SLOT(sendToAllStateChanged(int))); + + sendToAllCheckBox->setCheckState(Qt::Unchecked); + _isSendToAll = false; +} + +void ClientNicklistDialog::sendToAllStateChanged(int state) +{ + if (state) + { + listWidget->setEnabled(false); + _isSendToAll = true; + } + else + { + listWidget->setEnabled(true); + _isSendToAll = false; + } } ClientNicklistDialog::~ClientNicklistDialog() diff --git a/src/gui/clientFileSendDialog.h b/src/gui/clientFileSendDialog.h index d8afc3a..7abdcc7 100644 --- a/src/gui/clientFileSendDialog.h +++ b/src/gui/clientFileSendDialog.h @@ -30,9 +30,17 @@ public: ~ClientNicklistDialog(); QString getNick(); + bool isSendToAll() const + { + return _isSendToAll; + } + +private Q_SLOTS: + void sendToAllStateChanged(int state); private: OrgOpenslxPvsInterface *_ifaceDBus; + bool _isSendToAll; }; @@ -51,14 +59,22 @@ public: void open(); void open(QString nick); void open(QString nick, QString filename); + void sendToAll(); + void sendToAll(QString filename); private Q_SLOTS: void sendHeader(); void receiveAck(); void sendFile(); void close(); + void canceled(); void error(QAbstractSocket::SocketError error); + void multicastTransferStarted(qulonglong transferID); + void multicastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void multicastTransferFinished(qulonglong transferID); + void multicastTransferFailed(qulonglong transferID, QString const& reason); + private: QString formatSize(qint64 size); @@ -71,6 +87,11 @@ private: OrgOpenslxPvsInterface *_ifaceDBus; QString _nickname; + quint64 _transferID; + bool _error; + QString _reason; + bool _isMulticast; + }; #endif /* CLIENTFILESENDDIALOG_H_ */ diff --git a/src/gui/ui/clientFileSendDialog.ui b/src/gui/ui/clientFileSendDialog.ui index d2d9c75..85462ba 100644 --- a/src/gui/ui/clientFileSendDialog.ui +++ b/src/gui/ui/clientFileSendDialog.ui @@ -6,8 +6,8 @@ 0 0 - 186 - 108 + 528 + 144 @@ -33,7 +33,7 @@ - + @@ -61,10 +61,17 @@ + + + + + + + - + diff --git a/src/gui/ui/clientNicklistDialog.ui b/src/gui/ui/clientNicklistDialog.ui index afd84f1..3679b55 100644 --- a/src/gui/ui/clientNicklistDialog.ui +++ b/src/gui/ui/clientNicklistDialog.ui @@ -28,6 +28,13 @@ + + + + Send to &all + + + diff --git a/src/net/mcast/McastConfiguration.cpp b/src/net/mcast/McastConfiguration.cpp index 1a1c0a8..489eb3f 100644 --- a/src/net/mcast/McastConfiguration.cpp +++ b/src/net/mcast/McastConfiguration.cpp @@ -5,5 +5,44 @@ * Author: brs */ +#include + #include "McastConfiguration.h" +void McastConfiguration::loadFrom(QSettings* _settings, char const* group) +{ + if (group) + _settings->beginGroup(group); + + _multicastAddress = _settings->value("groupAddress", DEFAULT_MULTICAST_ADDRESS).toString(); + _multicastInterface = _settings->value("interface", DEFAULT_MULTICAST_INTERFACE).toString(); + _multicastMTU = _settings->value("mtu", DEFAULT_MULTICAST_MTU).value(); + _multicastRate = _settings->value("rate", DEFAULT_MULTICAST_RATE).value(); + _multicastUseUDP = _settings->value("use-udp", DEFAULT_MULTICAST_USEUDP).toBool(); + _multicastWinSize = _settings->value("winsize", DEFAULT_MULTICAST_WSIZ).value(); + _multicastUDPPortBase = _settings->value("portbase", DEFAULT_MULTICAST_UDPPORT).value(); + _multicastDPort = _settings->value("dport", DEFAULT_MULTICAST_DPORT).value(); + _multicastSPort = _settings->value("sport", DEFAULT_MULTICAST_SPORT).value(); + + if (group) + _settings->endGroup(); +} + +void McastConfiguration::writeTo(QSettings* _settings, char const* group) const +{ + if (group) + _settings->beginGroup(group); + + _settings->setValue("groupAddress", _multicastAddress); + _settings->setValue("interface", _multicastInterface); + _settings->setValue("mtu", _multicastMTU); + _settings->setValue("rate", _multicastRate); + _settings->setValue("use-udp", _multicastUseUDP); + _settings->setValue("winsize", _multicastWinSize); + _settings->setValue("portbase", _multicastUDPPortBase); + _settings->setValue("dport", _multicastDPort); + _settings->setValue("sport", _multicastSPort); + + if (group) + _settings->endGroup(); +} diff --git a/src/net/mcast/McastConfiguration.h b/src/net/mcast/McastConfiguration.h index 2e64678..b010f60 100644 --- a/src/net/mcast/McastConfiguration.h +++ b/src/net/mcast/McastConfiguration.h @@ -23,6 +23,8 @@ #include "McastConstants.h" +class QSettings; + class McastConfiguration: public QObject { Q_OBJECT @@ -164,6 +166,9 @@ public: emit changed(); } + void loadFrom(QSettings* settings, char const* group = 0); + void writeTo(QSettings* settings, char const* group = 0) const; + signals: void changed(); diff --git a/src/net/mcast/McastPGMSocket.cpp b/src/net/mcast/McastPGMSocket.cpp index 105bea9..7952f00 100644 --- a/src/net/mcast/McastPGMSocket.cpp +++ b/src/net/mcast/McastPGMSocket.cpp @@ -567,6 +567,11 @@ void McastPGMSocket::sendPacket(QByteArray const& bytes) void McastPGMSocket::finish() { + if (_finished) + { + return; + } + qDebug() << "finish()"; Q_FOREACH(QSocketNotifier* notif, _priv->_notifs) @@ -582,8 +587,11 @@ void McastPGMSocket::finish() _priv->send_notif = 0; } - pgm_close(_priv->socket, 1); - _priv->socket = 0; + if (_priv->socket) + { + pgm_close(_priv->socket, 1); + _priv->socket = 0; + } _finished = true; diff --git a/src/net/mcast/McastSender.cpp b/src/net/mcast/McastSender.cpp index 322b751..e25ec86 100644 --- a/src/net/mcast/McastSender.cpp +++ b/src/net/mcast/McastSender.cpp @@ -111,6 +111,6 @@ void McastSender::close() void McastSender::socketFinished() { - delete _socket; + _socket->deleteLater(); emit finished(); } diff --git a/src/net/pvsOutgoingMulticastTransfer.cpp b/src/net/pvsOutgoingMulticastTransfer.cpp new file mode 100644 index 0000000..2f24d49 --- /dev/null +++ b/src/net/pvsOutgoingMulticastTransfer.cpp @@ -0,0 +1,209 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/pvsOutgoingMulticastTransfer.cpp +# - wrap McastSender functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#include "pvsOutgoingMulticastTransfer.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +PVSOutgoingMulticastTransfer::PVSOutgoingMulticastTransfer(QString senderName, quint64 id, QString filename, QObject* parent) : + QObject(parent), + _file(0), + _progress(0), + _config(0), + _socket(0), + _progressTimer(0), + _prepareTimer(0), + _senderName(senderName), + _id(id), + _error(false) +{ + QFileInfo finfo(filename); + if(!finfo.exists()) + { + error("File does not exist"); + } + + if(!finfo.isReadable()) + { + error("File is not readable"); + } + + _file = new QFile(filename, this); + _length = _file->size(); +} + +PVSOutgoingMulticastTransfer::~PVSOutgoingMulticastTransfer() +{ + if(_file) + delete _file; + if(_config) + delete _config; +} + +void PVSOutgoingMulticastTransfer::prepare() +{ + if (_socket && !_socketInacceptable) + { + _prepareTimer->stop(); + delete _prepareTimer; + _prepareTimer = 0; + + QTimer::singleShot(0, this, SLOT(doStart())); + return; + } + else if (_socket) + { + delete _socket; + _socket = 0; + } + + QSettings settings; + quint16 portbase = settings.value("multicast/port-base", "6966").value(); + quint16 portlimit = settings.value("multicast/port-limit", "7966").value(); + + int tries_remaining = 5; + while(tries_remaining > 0) + { + quint16 port = portbase + (qrand() % (portlimit - portbase + 1)); + + if (!_config) + { + _config = new McastConfiguration(); + } + _config->loadFrom(&settings, "multicast"); + _config->multicastUDPPortBase(port); + + _socket = new McastPGMSocket(this); + if(_socket->open(_config, McastPGMSocket::PSOCK_WRITE)) + { + break; + } + else + { + delete _socket; + _socket = 0; + } + } + + if (!_socket) + { + emit failed(_id, "Could not open socket"); + delete _prepareTimer; + _prepareTimer = 0; + return; + } + else + { + _socketInacceptable = false; + // announce the transfer: + QFileInfo info(*_file); + QString message = QString("%1:%2:%3:%4:%5").arg(_senderName).arg(_id).arg(info.baseName()).arg(info.size()).arg(_config->multicastUDPPortBase()); + PVSMsg msg(PVSCOMMAND, "MCASTFTANNOUNCE", message); + emit announce(msg); + _prepareTimer->start(5000); + } +} + +void PVSOutgoingMulticastTransfer::doStart() +{ + ConsoleLog writeLine(QString("Starting multicast transfer %1").arg(_id)); + + _file->open(QIODevice::ReadOnly); + + _sender = new McastSender(_file, _config, this); + connect(_sender, SIGNAL(finished()), SLOT(senderFinished())); + connect(_sender, SIGNAL(progress(quint64)), SLOT(senderProgress(quint64))); + // connect(_sender, SIGNAL(allSent()), SIGNAL(allSent())); + _socket->setParent(_sender); + _sender->start(_socket); + + emit started(_id); + + _progressTimer = new QTimer(this); + connect(_progressTimer, SIGNAL(timeout()), SLOT(reportTimeout())); + _progressTimer->setInterval(333); + _progressTimer->start(); +} + +void PVSOutgoingMulticastTransfer::senderProgress(quint64 bytes) + +{ + _progress = bytes; +} + +void PVSOutgoingMulticastTransfer::senderFinished() +{ + if(_progressTimer) + { + _progressTimer->stop(); + delete _progressTimer; + _progressTimer = 0; + } + emit finished(_id); + _sender->close(); + delete _sender; +} + +void PVSOutgoingMulticastTransfer::reportTimeout() +{ + emit progress(_id, _progress, _length); +} + +void PVSOutgoingMulticastTransfer::retry() +{ + bool first = !_socketInacceptable; + _socketInacceptable = true; + + if(first) + { + _prepareTimer->setInterval(1000); + } +} + +void PVSOutgoingMulticastTransfer::start() +{ + if (!_prepareTimer) + { + _prepareTimer = new QTimer(this); + _prepareTimer->setSingleShot(true); + connect(_prepareTimer, SIGNAL(timeout()), SLOT(prepare())); + } + QTimer::singleShot(0, this, SLOT(prepare())); +} + +void PVSOutgoingMulticastTransfer::abort() +{ + if (_sender) + _sender->close(); +} + +void PVSOutgoingMulticastTransfer::error(QString const& reason) +{ + qCritical() << "Could not create an outgoing mcast transfer: " << reason; + _error = true; + _reason = reason; +} diff --git a/src/net/pvsOutgoingMulticastTransfer.h b/src/net/pvsOutgoingMulticastTransfer.h new file mode 100644 index 0000000..5fd6a3d --- /dev/null +++ b/src/net/pvsOutgoingMulticastTransfer.h @@ -0,0 +1,92 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/pvsOutgoingMulticastTransfer.h +# - wrap McastSender functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#ifndef PVSOUTGOINGMULTICASTTRANSFER_H_ +#define PVSOUTGOINGMULTICASTTRANSFER_H_ + +#include +#include +#include + +#include + +class QFile; +class QTimer; +class McastConfiguration; +class McastPGMSocket; +class McastSender; + +class PVSOutgoingMulticastTransfer : public QObject +{ + Q_OBJECT +public: + PVSOutgoingMulticastTransfer(QString senderName, quint64 id, QString filename, QObject* parent = 0); + virtual ~PVSOutgoingMulticastTransfer(); + + quint64 id() const + { + return _id; + } + + bool isError() const + { + return _error; + } + + QString reason() const + { + return _reason; + } + +signals: + void started(qulonglong id); + void progress(qulonglong id, qulonglong bytes, qulonglong of); + void allSent(qulonglong id); + void finished(qulonglong id); + void failed(qulonglong id, QString const reason); + void announce(PVSMsg announcement); + +private slots: + void senderProgress(quint64 bytes); + void senderFinished(); + void reportTimeout(); + void doStart(); + void prepare(); + +public slots: + void start(); + void abort(); + void retry(); + +private: + QFile* _file; + quint64 _length; + quint64 _progress; + McastConfiguration* _config; + McastPGMSocket* _socket; + McastSender* _sender; + QTimer* _progressTimer; + QTimer* _prepareTimer; + QString _senderName; + quint64 _id; + bool _error; + QString _reason; + bool _socketInacceptable; + + void error(QString const& reason); +}; + +#endif /* PVSOUTGOINGMULTICASTTRANSFER_H_ */ diff --git a/src/net/pvsServerConnection.h b/src/net/pvsServerConnection.h index 0669d88..c6ef015 100644 --- a/src/net/pvsServerConnection.h +++ b/src/net/pvsServerConnection.h @@ -11,9 +11,9 @@ #define _PVSSERVERCONNECTION_H_ #include "src/util/dispatcher.h" +#include "src/net/pvsMsg.h" #include -class PVSMsg; class PVS; class PVSDiscoveredServer; @@ -30,8 +30,6 @@ public: return _socket != NULL && _socket->state() == QAbstractSocket::ConnectedState; } - void sendMessage(PVSMsg newMessage); - void ping(); QString getServerName(); @@ -63,6 +61,9 @@ public: _commandDispatcher.removeListener(ident, who, func); }; +public Q_SLOTS: + void sendMessage(PVSMsg newMessage); + protected: void timerEvent(QTimerEvent *event); diff --git a/src/pvs.cpp b/src/pvs.cpp index 2069e36..c7fe5ce 100644 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -15,6 +15,8 @@ #include "src/net/pvsMsg.h" #include "src/net/pvsServiceDiscovery.h" #include "src/net/pvsDiscoveredServer.h" +#include "src/net/mcast/McastConfiguration.h" +#include "src/net/pvsOutgoingMulticastTransfer.h" // D-Bus #include "pvsadaptor.h" @@ -38,6 +40,7 @@ PVS::PVS() : loadCommands(); _blankScreen = NULL; _vncPort = -1; + _masterMcastConfig = new McastConfiguration(this); // add a notify to the allow file, so we get informed when the file is changed QString watchPath("/home/"); @@ -176,6 +179,17 @@ void PVS::onCommand(PVSMsg cmdMessage) unlock(); return; } + if (ident.compare("MCASTFTRETRY") == 0) + { + QStringList fields = message.split(':'); + if (fields[0].compare(getUserName()) == 0) + { + quint64 id = fields[0].toULongLong(); + PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(id, 0); + if (transfer) + transfer->retry(); + } + } #ifdef never // prototype @@ -627,3 +641,49 @@ void PVS::signalHandler(int signal) } +bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID, QString& errorReason) +{ + transferID = generateMcastTransferID(); + + PVSOutgoingMulticastTransfer* transfer = new PVSOutgoingMulticastTransfer(getUserName(), transferID, objectPath, this); + if (transfer->isError()) + { + errorReason = transfer->reason(); + delete transfer; + return false; + } + + _outgoingTransfers.insert(transferID, transfer); + connect(transfer, SIGNAL(started(qulonglong)), SIGNAL(outgoingMulticastTransferStarted(qulonglong))); + connect(transfer, SIGNAL(finished(qulonglong)), SIGNAL(outgoingMulticastTransferFinished(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const)), SIGNAL(outgoingMulticastTransferFailed(qulonglong, QString const))); + connect(transfer, SIGNAL(progress(qulonglong, qulonglong, qulonglong)), SIGNAL(outgoingMulticastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(transfer, SIGNAL(announce(PVSMsg)), _pvsServerConnection, SLOT(sendMessage(PVSMsg))); + QTimer::singleShot(0, transfer, SLOT(start())); + errorReason = ""; + return true; +} + +void PVS::cancelOutgoingMulticastTransfer(quint64 transferID) +{ + PVSOutgoingMulticastTransfer* transfer = _outgoingTransfers.value(transferID, 0); + + if (transfer) + { + delete transfer; + } +} + +quint64 PVS::generateMcastTransferID() +{ + static quint64 nodeID = 0; + static quint16 counter = 0; + + if (!nodeID) + { + QDataStream(QCryptographicHash::hash(getUserName().toLocal8Bit(), QCryptographicHash::Md5)) >> nodeID; + } + + return (nodeID & Q_UINT64_C(0xffffffffffff0000)) | (quint64)(++counter); +} + diff --git a/src/pvs.h b/src/pvs.h index 4b1e29e..93596d2 100644 --- a/src/pvs.h +++ b/src/pvs.h @@ -28,6 +28,8 @@ class PVSServiceDiscovery; class PVSDiscoveredServer; +class McastConfiguration; +class PVSOutgoingMulticastTransfer; /** * PVSClient @@ -80,6 +82,11 @@ public Q_SLOTS: QStringList getAvailableHosts(); QString getIpByNick(QString nick); + // Multicast File Transfer + bool createMulticastTransfer(QString const& objectPath, quint64& transferID, QString& errorReason); + void cancelOutgoingMulticastTransfer(quint64 transferID); + + Q_SIGNALS: void project(QString host, int port, QString passwd, bool fullscreen, bool smoothTransformation, int quality); @@ -93,6 +100,12 @@ Q_SIGNALS: void addHost(QString host); void delHost(QString host); + // Multicast File Transfer + void outgoingMulticastTransferStarted(qulonglong transferID); + void outgoingMulticastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void outgoingMulticastTransferFinished(qulonglong transferID); + void outgoingMulticastTransferFailed(qulonglong transferID, QString reason); + protected: void timerEvent(QTimerEvent *event); @@ -142,5 +155,9 @@ private: int _timerLockTest; int _timerLockDelay; + McastConfiguration* _masterMcastConfig; + QHash _outgoingTransfers; + + static quint64 generateMcastTransferID(); }; #endif /* PVSCLIENT_H_ */ -- cgit v1.2.3-55-g7522 From 755f07b1a25c414b0c7cbe28db4a7ecbc32975c7 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 19 Jul 2010 11:53:55 +0200 Subject: Implement initial multicast receive functionality in PVS daemon --- CMakeLists.txt | 2 + src/net/mcast/McastReceiver.cpp | 49 +++++++++-- src/net/mcast/McastReceiver.h | 5 +- src/net/pvsIncomingMulticastTransfer.cpp | 134 +++++++++++++++++++++++++++++++ src/net/pvsIncomingMulticastTransfer.h | 71 ++++++++++++++++ src/pvs.cpp | 85 ++++++++++++++++++++ src/pvs.h | 11 +++ 7 files changed, 351 insertions(+), 6 deletions(-) create mode 100644 src/net/pvsIncomingMulticastTransfer.cpp create mode 100644 src/net/pvsIncomingMulticastTransfer.h (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 93e281e..3f2089a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,7 @@ SET( PVS_SRCS src/util/TextFile.cpp src/util/serviceDiscoveryUtil.cpp src/net/pvsOutgoingMulticastTransfer.cpp + src/net/pvsIncomingMulticastTransfer.cpp ) # pvsgui @@ -194,6 +195,7 @@ SET( PVS_MOC_HDRS src/net/pvsServiceDiscovery.h src/net/pvsDiscoveredServer.h src/net/pvsOutgoingMulticastTransfer.h + src/net/pvsIncomingMulticastTransfer.h ) SET( PVSGUI_MOC_HDRS diff --git a/src/net/mcast/McastReceiver.cpp b/src/net/mcast/McastReceiver.cpp index 6070208..1f27127 100644 --- a/src/net/mcast/McastReceiver.cpp +++ b/src/net/mcast/McastReceiver.cpp @@ -27,7 +27,7 @@ McastReceiver::McastReceiver(QIODevice* iodev, McastConfiguration* config, QObject* parent) : QObject(parent), - _config(config ? new McastConfiguration(*config) : new McastConfiguration()), + _config(config ? new McastConfiguration(*config) : 0), _socket(0), _curoffs(0), _closed(false), @@ -43,13 +43,52 @@ McastReceiver::~McastReceiver() delete _config; } -void McastReceiver::start() +void McastReceiver::config(McastConfiguration const* config) { + if (_config) + delete _config; + _config = new McastConfiguration(*config, this); +} + +bool McastReceiver::start() +{ + McastConfiguration *config = _config; + if (!config) + config = new McastConfiguration(); + + if (_socket) + { + delete _socket; + } _socket = new McastPGMSocket(this); - connect(_socket, SIGNAL(receivedPacket(QByteArray)), this, SLOT(receivedPacket(QByteArray))); - connect(_socket, SIGNAL(connectionReset()), this, SLOT(connectionReset())); + + connect(_socket, SIGNAL(receivedPacket(QByteArray)), SLOT(receivedPacket(QByteArray))); + connect(_socket, SIGNAL(connectionReset()), SLOT(connectionReset())); // connect(_socket, SIGNAL(connectionFinished()), this, SLOT(connectionFinished())); - _socket->open(_config, McastPGMSocket::PSOCK_READ); + if (_socket->open(_config, McastPGMSocket::PSOCK_READ)) + { + return true; + } + else + { + disconnect(_socket, SIGNAL(receivedPacket(QByteArray)), this, SLOT(receivedPacket(QByteArray))); + disconnect(_socket, SIGNAL(connectionReset()), this, SLOT(connectionReset())); + return false; + } +} + +void McastReceiver::abort() +{ + if (_socket) + { + delete _socket; + _socket = 0; + } + + if (_iodev) + { + _iodev->close(); + } } void McastReceiver::receivedPacket(QByteArray const& bytes) diff --git a/src/net/mcast/McastReceiver.h b/src/net/mcast/McastReceiver.h index 48ff7c5..247733d 100644 --- a/src/net/mcast/McastReceiver.h +++ b/src/net/mcast/McastReceiver.h @@ -47,6 +47,8 @@ public: return _config; } + void config(McastConfiguration const* config); + static inline bool is_error(Result result) { return result != RES_OK; @@ -57,7 +59,8 @@ signals: void progress(quint64 offset); public slots: - void start(); + bool start(); + void abort(); private: McastConfiguration* _config; diff --git a/src/net/pvsIncomingMulticastTransfer.cpp b/src/net/pvsIncomingMulticastTransfer.cpp new file mode 100644 index 0000000..01507a9 --- /dev/null +++ b/src/net/pvsIncomingMulticastTransfer.cpp @@ -0,0 +1,134 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/pcsIncomingMulticastTransfer.h +# - wrap McastReceiver functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#include +#include +#include + +#include "pvsIncomingMulticastTransfer.h" +#include + +PVSIncomingMulticastTransfer::PVSIncomingMulticastTransfer(QString const& sender, qulonglong transferID, qulonglong size, + ushort port, McastConfiguration const* configTemplate, QObject* parent) : + QObject(parent), + _sender(sender), + _transferID(transferID), + _bytes(0), + _size(size), + _port(port), + _temporaryFile(new QTemporaryFile(QFileInfo(QDir::homePath(), "incoming.mcastft.XXXXXX").absolutePath(), this)), + _finalFile(0), + _receiver(0), + _config(configTemplate ? + new McastConfiguration(*configTemplate) : + new McastConfiguration()), + _progressTimer(new QTimer(this)) +{ + _config->multicastUDPPortBase(port); + _config->multicastDPort(port); + _config->multicastSPort(port); + + connect(_progressTimer, SIGNAL(timeout()), SLOT(updateProgress())); +} + +PVSIncomingMulticastTransfer::~PVSIncomingMulticastTransfer() +{ + // TODO Auto-generated destructor stub +} + +bool PVSIncomingMulticastTransfer::start() +{ + QFile *dest = _finalFile ? _finalFile : _temporaryFile; + _receiver = new McastReceiver(dest, new McastConfiguration(*_config), this); + connect(_receiver, SIGNAL(finished(int)), SLOT(receiverFinished(int))); + connect(_receiver, SIGNAL(progress(quint64)), SLOT(receiverProgress(quint64))); + + if (!_receiver->start()) + { + emit retry(_sender, _transferID); + return false; + } + else + { + _progressTimer->start(333); + return true; + } +} + +void PVSIncomingMulticastTransfer::abort() +{ + delete _receiver; + _receiver = 0; + + delete _progressTimer; + _progressTimer = 0; + + if (_temporaryFile) + { + _temporaryFile->remove(); + } + delete _temporaryFile; + + if (_finalFile) + { + _finalFile->remove(); + } + delete _finalFile; +} + +void PVSIncomingMulticastTransfer::updatePort(ushort port) +{ + _config->multicastUDPPortBase(port); + _config->multicastSPort(port); + _config->multicastDPort(port); +} + +void PVSIncomingMulticastTransfer::receiverProgressed(quint64 bytes) +{ + _bytes = bytes; +} + +void PVSIncomingMulticastTransfer::receiverFinished(int how) +{ + switch(how) + { + case McastReceiver::RES_OK: + emit finished(_transferID); + break; + case McastReceiver::RES_ABORTED: + emit failed(_transferID, tr("Aborted")); + break; + case McastReceiver::RES_MD5_MISMATCH: + case McastReceiver::RES_CHECKSUM_MISMATCH: + emit failed(_transferID, tr("Unrecoverable data corruption")); + break; + case McastReceiver::RES_CONNECTION_RESET: + emit failed(_transferID, tr("Connection was reset")); + break; + case McastReceiver::RES_OFFSET_MISMATCH: + emit failed(_transferID, tr("Unrecoverable data loss. Try a lower transfer rate")); + break; + } +} + +void PVSIncomingMulticastTransfer::updateProgress() +{ + if (!_started) + { + emit started(_transferID); + } + emit progress(_transferID, _bytes, _size); +} diff --git a/src/net/pvsIncomingMulticastTransfer.h b/src/net/pvsIncomingMulticastTransfer.h new file mode 100644 index 0000000..9a33348 --- /dev/null +++ b/src/net/pvsIncomingMulticastTransfer.h @@ -0,0 +1,71 @@ +/* +# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg +# +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING +# +# If you have any feedback please consult http://openslx.org/feedback and +# send your suggestions, praise, or complaints to feedback@openslx.org +# +# General information about OpenSLX can be found at http://openslx.org/ +# ----------------------------------------------------------------------------- +# src/net/pcsIncomingMulticastTransfer.h +# - wrap McastReceiver functionality in PVS daemon +# ----------------------------------------------------------------------------- +*/ + +#ifndef PVSINCOMINGMULTICASTTRANSFER_H_ +#define PVSINCOMINGMULTICASTTRANSFER_H_ + +#include +#include + +#include + +class McastConfiguration; +class McastReceiver; +class QFile; +class QTimer; + +class PVSIncomingMulticastTransfer : public QObject +{ + Q_OBJECT +public: + PVSIncomingMulticastTransfer(QString const& sender, qulonglong transferID, qulonglong size, ushort port, + McastConfiguration const* configTemplate, QObject* parent = 0); + virtual ~PVSIncomingMulticastTransfer(); + + void setFinalFile(QString const& filename); + +signals: + void retry(QString const& sender, qulonglong transferID); + void started(qulonglong transferID); + void progress(qulonglong transferID, qulonglong bytes, qulonglong of); + void finished(qulonglong transferID); + void failed(qulonglong transferID, QString const& reason); + +public slots: + void updatePort(ushort port); + bool start(); + void abort(); + +private slots: + void receiverProgressed(quint64 bytes); + void receiverFinished(int reason); + void updateProgress(); + +private: + QString _sender; + qulonglong _transferID; + qulonglong _bytes; + qulonglong _size; + ushort _port; + QFile* _temporaryFile; + QFile* _finalFile; + McastReceiver* _receiver; + McastConfiguration* _config; + bool _started; + QTimer* _progressTimer; +}; + +#endif /* PVSINCOMINGMULTICASTTRANSFER_H_ */ diff --git a/src/pvs.cpp b/src/pvs.cpp index af5958e..8f06f74 100644 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -17,6 +17,7 @@ #include "src/net/pvsDiscoveredServer.h" #include "src/net/mcast/McastConfiguration.h" #include "src/net/pvsOutgoingMulticastTransfer.h" +#include "src/net/pvsIncomingMulticastTransfer.h" // D-Bus #include "pvsadaptor.h" @@ -190,6 +191,45 @@ void PVS::onCommand(PVSMsg cmdMessage) transfer->retry(); } } + if (ident.compare("MCASTFTANNOUNCE") == 0) + { + QStringList fields = message.split(':'); + bool ok; + QString sender; + qulonglong transferID; + QString basename; + qulonglong size; + ushort port; + + if (!fields.size() == 5) + { + goto malformedAnnounce; + } + sender = fields[0]; + transferID = fields[1].toULongLong(&ok); + if (!ok) + { + goto malformedAnnounce; + } + basename = fields[2]; + size = fields[3].toULongLong(&ok); + if (!ok) + { + goto malformedAnnounce; + } + port = fields[4].toUShort(&ok); + if (!ok) + { + goto malformedAnnounce; + } + + onIncomingMulticastTransfer(sender, transferID, basename, size, port); + return; + + malformedAnnounce: + qDebug() << "Ignoring malformed MCASTFTANNOUNCE command: " << message; + return; + } #ifdef never // prototype @@ -676,6 +716,39 @@ void PVS::cancelOutgoingMulticastTransfer(quint64 transferID) } } +void PVS::onIncomingMulticastTransfer(QString const& sender, qulonglong transferID, + QString const& basename, qulonglong size, ushort port) +{ + PVSIncomingMulticastTransfer* transfer; + if (_incomingTransfers.value(transferID, 0)) + { + transfer->updatePort(port); + QTimer::singleShot(0, transfer, SLOT(start())); + } + else + { + transfer = new PVSIncomingMulticastTransfer(sender, transferID, size, port, _masterMcastConfig, this); + _incomingTransfers.insert(transferID, transfer); + + connect(transfer, SIGNAL(retry(QString const&, qulonglong)), SLOT(onIncomingMulticastTransferRetry(QString const&, qulonglong))); + connect(transfer, SIGNAL(started(qulonglong)), SIGNAL(incomingMulticastTransferStarted(qulonglong))); + connect(transfer, SIGNAL(progress(qulonglong, qulonglong, qulonglong)), SIGNAL(incomingMulticastTransferProgress(qulonglong, qulonglong, qulonglong))); + connect(transfer, SIGNAL(finished(qulonglong)), SIGNAL(incomingMulticastTransferFinished(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const&)), SIGNAL(incomingMulticastTransferFailed(qulonglong, QString))); + connect(transfer, SIGNAL(finished(qulonglong)), SLOT(incomingMulticastTransferDelete(qulonglong))); + connect(transfer, SIGNAL(failed(qulonglong, QString const&)), SLOT(incomingMulticastTransferDelete(qulonglong))); + + emit incomingMulticastTransferNew(transferID, sender, basename, size); + QTimer::singleShot(0, transfer, SLOT(start())); + } +} + +void PVS::onIncomingMulticastTransferRetry(QString const& sender, qulonglong transferID) +{ + PVSMsg retryMessage(PVSCOMMAND, "MCASTFTRETRY", QString("%1:%2").arg(sender).arg(transferID)); + _pvsServerConnection->sendMessage(retryMessage); +} + quint64 PVS::generateMcastTransferID() { static quint64 nodeID = 0; @@ -698,3 +771,15 @@ void PVS::outgoingMulticastTransferDelete(qulonglong transferID) _outgoingTransfers.remove(transferID); transfer->deleteLater(); } + +void PVS::incomingMulticastTransferDelete(qulonglong transferID) +{ + PVSIncomingMulticastTransfer* transfer = _incomingTransfers.value(transferID, 0); + if (!transfer) + { + return; + } + + _incomingTransfers.remove(transferID); + transfer->deleteLater(); +} diff --git a/src/pvs.h b/src/pvs.h index 4e07fd8..dc272f0 100644 --- a/src/pvs.h +++ b/src/pvs.h @@ -30,6 +30,7 @@ class PVSServiceDiscovery; class PVSDiscoveredServer; class McastConfiguration; class PVSOutgoingMulticastTransfer; +class PVSIncomingMulticastTransfer; /** * PVSClient @@ -105,6 +106,11 @@ Q_SIGNALS: void outgoingMulticastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); void outgoingMulticastTransferFinished(qulonglong transferID); void outgoingMulticastTransferFailed(qulonglong transferID, QString reason); + void incomingMulticastTransferNew(qulonglong transferID, QString sender, QString basename, qulonglong size); + void incomingMulticastTransferStarted(qulonglong transferID); + void incomingMulticastTransferProgress(qulonglong transferID, qulonglong bytes, qulonglong of); + void incomingMulticastTransferFinished(qulonglong transferID); + void incomingMulticastTransferFailed(qulonglong transferID, QString reason); protected: @@ -157,10 +163,15 @@ private: McastConfiguration* _masterMcastConfig; QHash _outgoingTransfers; + QHash _incomingTransfers; + void onIncomingMulticastTransfer(QString const& sender, qulonglong transferID, QString const& basename, qulonglong size, ushort port); + void onIncomingMulticastTransferRetry(QString const& sender, qulonglong transferID); static quint64 generateMcastTransferID(); + private Q_SLOTS: // housekeeping void outgoingMulticastTransferDelete(qulonglong transferID); + void incomingMulticastTransferDelete(qulonglong transferID); }; #endif /* PVSCLIENT_H_ */ -- cgit v1.2.3-55-g7522 From 19316e9142c5ab4a4e1603715fbbf555aac97826 Mon Sep 17 00:00:00 2001 From: Alexander Hoppe Date: Tue, 3 Aug 2010 18:23:24 +0200 Subject: Anpassungen fuer Win32-build. Aufspaltung der ClientGUIUtils in 2 Versionen Anpassungen des HomeDir Alle Aenderungen sollten unschaedlich fuer den Linux-build-Prozess sein. --- CMakeLists.txt | 100 +++++++++++++++++------ i18n/pvs_ar_JO.ts | 8 +- i18n/pvs_de_DE.ts | 8 +- i18n/pvs_es_MX.ts | 8 +- i18n/pvs_fr_FR.ts | 8 +- i18n/pvs_pl_PL.ts | 8 +- src/pvs.cpp | 27 ++++-- src/pvs.h | 11 ++- src/pvsDaemon.cpp | 22 +++-- src/pvsgui.cpp | 2 +- src/util/clientGUIUtils.h | 25 ++---- src/util/clientGUIUtils_Win32.cpp | 46 +++++++++++ src/util/clientGUIUtils_X11.cpp | 168 ++++++++++++++++++++++++++++++++++++++ src/util/consoleLogger.cpp | 2 +- src/util/util.cpp | 62 ++++++++++---- src/util/util.h | 6 +- 16 files changed, 411 insertions(+), 100 deletions(-) mode change 100644 => 100755 CMakeLists.txt mode change 100644 => 100755 src/pvs.cpp mode change 100644 => 100755 src/pvs.h mode change 100644 => 100755 src/pvsDaemon.cpp mode change 100644 => 100755 src/util/clientGUIUtils.h create mode 100755 src/util/clientGUIUtils_Win32.cpp create mode 100755 src/util/clientGUIUtils_X11.cpp mode change 100644 => 100755 src/util/consoleLogger.cpp mode change 100644 => 100755 src/util/util.cpp mode change 100644 => 100755 src/util/util.h (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index 9570774..d2eae17 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.2 ) # set compiler optimizations for debug and release SET(CMAKE_BUILD_TYPE Debug) SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") -SET(CMAKE_CXX_FLAGS_RELEASE "-O2") -# -march=native -DQT_NO_DEBUG_OUTPUT") +SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") +# -DQT_NO_DEBUG_OUTPUT") # local cmake modules SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) @@ -31,6 +31,15 @@ INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR} ) +IF(WIN32) + SET(sysdep_suffix _Win32) + INCLUDE_DIRECTORIES( + /c/KDE4/tmp/LibVNCServer-0.9.7/ + ) +ELSEIF(UNIX) + SET(sysdep_suffix _X11) +ENDIF(WIN32) + ################################################################################ # Variables ################################################################################ @@ -78,7 +87,7 @@ SET( PVS_SRCS src/net/pvsLocalhostCommunicator.cpp src/util/util.cpp src/util/consoleLogger.cpp - src/util/clientGUIUtils.cpp + src/util/clientGUIUtils${sysdep_suffix}.cpp src/util/pvsSettingsManager.cpp src/core/pvsChatClient.cpp src/net/pvsServiceDiscovery.cpp @@ -262,6 +271,7 @@ QT4_CREATE_TRANSLATION( PVSGUI_QMS ${PVSGUI_SRCS} ${PVSGUI_UI_HDRS} ${PVSGUI_TSS ################################################################################ ## here we instruct CMake to build our executable from all of the source files +if(UNIX) ADD_EXECUTABLE( pvsmgr ${PVSMGR_SRCS} ${PVSMGR_MOC_SRCS} @@ -277,6 +287,7 @@ ADD_EXECUTABLE( pvsmgrtouch ${PVSMGR_RC_SRCS} ${PVSMGR_QMS} ) +ENDIF(UNIX) ADD_EXECUTABLE( pvs ${PVS_SRCS} @@ -295,35 +306,72 @@ ADD_EXECUTABLE( pvsgui # last thing we have to do is to tell CMake what libraries our executable needs, # luckily FIND_PACKAGE prepared variables for us: -TARGET_LINK_LIBRARIES( pvsmgr - ${QT_LIBRARIES} - ${VNC_LIBRARIES} - ${X11_LIBRARIES} -) - -TARGET_LINK_LIBRARIES( pvsmgrtouch - ${QT_LIBRARIES} - ${VNC_LIBRARIES} - ${X11_LIBRARIES} -) - -TARGET_LINK_LIBRARIES( pvs - ${QT_LIBRARIES} - ${VNC_LIBRARIES} - ${X11_LIBRARIES} -) - -TARGET_LINK_LIBRARIES( pvsgui - ${QT_LIBRARIES} - ${VNC_LIBRARIES} -) +IF(WIN32) + TARGET_LINK_LIBRARIES( pvsmgr + + ) +ELSEIF(UNIX) +TARGET_LINK_LIBRARIES( pvsmgr + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + ${X11_LIBRARIES} + ) +ENDIF(WIN32) + +IF(WIN32) + TARGET_LINK_LIBRARIES( pvsmgrtouch + + ) +ELSEIF(UNIX) + TARGET_LINK_LIBRARIES( pvsmgrtouch + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + ${X11_LIBRARIES} + ) +ENDIF(WIN32) + +IF(WIN32) + TARGET_LINK_LIBRARIES( pvs + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + advapi32 + ws2_32 + ) +ELSEIF(UNIX) + TARGET_LINK_LIBRARIES( pvs + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + ${X11_LIBRARIES} + ) +ENDIF(WIN32) + +IF(WIN32) + TARGET_LINK_LIBRARIES( pvsgui + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + #advapi32 + ws2_32 + ) +ELSEIF(UNIX) + TARGET_LINK_LIBRARIES( pvsgui + ${QT_LIBRARIES} + ${VNC_LIBRARIES} + ) +ENDIF(WIN32) + +IF(UNIX) SET_PROPERTY(TARGET pvsmgrtouch PROPERTY COMPILE_DEFINITIONS MAINWINDOW_USE_TOUCHGUI) SET_PROPERTY(TARGET pvsmgr PROPERTY COMPILE_DEFINITIONS MAINWINDOW_USE_NORMALGUI) +ENDIF(UNIX) # add install target to our makefile CONFIGURE_FILE( org.openslx.pvs.service ${CMAKE_BINARY_DIR}/org.openslx.pvs.service ) -INSTALL( TARGETS pvsmgr pvs pvsgui pvsmgrtouch RUNTIME DESTINATION bin ) +IF(WIN32) + INSTALL( TARGETS pvs pvsgui RUNTIME DESTINATION bin ) +ELSEIF(UNIX) + INSTALL( TARGETS pvsmgr pvs pvsgui pvsmgrtouch RUNTIME DESTINATION bin ) +ENDIF(WIN32) INSTALL( PROGRAMS misc/pvs-vncsrv DESTINATION bin) INSTALL( FILES ${CMAKE_BINARY_DIR}/org.openslx.pvs.service DESTINATION share/dbus-1/services ) diff --git a/i18n/pvs_ar_JO.ts b/i18n/pvs_ar_JO.ts index c1b19cb..38bf578 100644 --- a/i18n/pvs_ar_JO.ts +++ b/i18n/pvs_ar_JO.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_de_DE.ts b/i18n/pvs_de_DE.ts index c1b19cb..38bf578 100644 --- a/i18n/pvs_de_DE.ts +++ b/i18n/pvs_de_DE.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_es_MX.ts b/i18n/pvs_es_MX.ts index c1b19cb..38bf578 100644 --- a/i18n/pvs_es_MX.ts +++ b/i18n/pvs_es_MX.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_fr_FR.ts b/i18n/pvs_fr_FR.ts index c1b19cb..38bf578 100644 --- a/i18n/pvs_fr_FR.ts +++ b/i18n/pvs_fr_FR.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/i18n/pvs_pl_PL.ts b/i18n/pvs_pl_PL.ts index c1b19cb..38bf578 100644 --- a/i18n/pvs_pl_PL.ts +++ b/i18n/pvs_pl_PL.ts @@ -4,22 +4,22 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! diff --git a/src/pvs.cpp b/src/pvs.cpp old mode 100644 new mode 100755 index d09d407..1c08be5 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -36,12 +36,14 @@ PVS::PVS() : _vncRequested = false; readPolicyFiles(); loadCommands(); - _blankScreen = NULL; + /*#ifndef __WIN32__*/ + _blankScreen = NULL; + /*#endif*/ _vncPort = -1; // add a notify to the allow file, so we get informed when the file is changed - QString watchPath("/home/"); - watchPath.append(getUserName().append(QString("/.pvs/.allow"))); + QString watchPath(getPolicyDir()); + watchPath.append(QString(".allow")); _notify = new QFileSystemWatcher(this); _notify->addPath(QString(watchPath.toUtf8().data())); @@ -64,6 +66,7 @@ PVS::PVS() : _timerLockTest = 0; _timerLockDelay = 0; + #ifndef __WIN32__ //add signalhandling for sigterm signals struct sigaction act; act.sa_handler = &PVS::signalHandler; @@ -75,7 +78,7 @@ PVS::PVS() : sigaction(SIGHUP, &act, 0); sigaction(SIGINT, &act, 0); sigaction(SIGQUIT, &act, 0); - + #endif /*__WIN32__*/ } PVS::~PVS() @@ -498,14 +501,19 @@ int PVS::startVNCScript(int port, QString pass, QString rwpass) commandLine.append(rwpass); if (!system(NULL)) ConsoleLog writeError("No Command processor available"); - int result = system(commandLine.toUtf8().data()); + #ifndef __WIN32__ +//TODO Win32 result = WEXITSTATUS(result); if (result != 0) ConsoleLog writeError(QString("VNC-Server is not running, code: ") + int2String(result)); else ConsoleLog writeLine("VNC-Server should be running"); return result; + #else + /*Code fuer VNC-Aufruf unter Windows einfuegen*/ + return 0; + #endif /*__WIN32__*/ } else { @@ -521,6 +529,7 @@ int PVS::stopVNCScript() { if (gotVNCScript()) { + #ifndef __WIN32__ ConsoleLog writeLine("Stopping VNC-Script"); QString commandLine(_vncScriptPath); commandLine.append(" "); @@ -532,6 +541,10 @@ int PVS::stopVNCScript() ConsoleLog writeLine("VNC-Server should be stopped"); int result = system(commandLine.toUtf8().data()); return WEXITSTATUS(result); + #else + /*Code fuer VNC-Server stoppen unter Windows einfuegen*/ + return 0; + #endif /*__WIN32__*/ } else { @@ -608,6 +621,7 @@ QString PVS::getIpByNick(QString nick) void PVS::signalHandler(int signal) { ConsoleLog writeLine(QString("Received Signal ").append (int2String(signal))); + #ifndef __WIN32__ switch (signal) { case SIGHUP: mainClient->quit(); @@ -622,6 +636,9 @@ void PVS::signalHandler(int signal) mainClient->quit(); break; } + #else + ConsoleLog writeLine("Abfang nicht definiert fuer Windows"); + #endif /*__WIN32__*/ } diff --git a/src/pvs.h b/src/pvs.h old mode 100644 new mode 100755 index ba696d8..b6b5e65 --- a/src/pvs.h +++ b/src/pvs.h @@ -13,8 +13,10 @@ #define PVSCLIENT_H_ #include -#include -#include +#ifndef __WIN32__ + #include + #include +#endif #include #include "setup.h" @@ -25,7 +27,6 @@ #include "src/util/consoleLogger.h" #include "src/util/clientGUIUtils.h" - class PVSServiceDiscovery; class PVSDiscoveredServer; @@ -116,7 +117,9 @@ private: bool _locked; ///< are we locked? QString _lockMsg; ///< message to display while we're locked bool _vncAllowed; ///< whether vncConnections to this client are allowed (dup?) - BlankScreen *_blankScreen;///< obhject to blank the screen + /*#ifndef __WIN32__*/ + BlankScreen *_blankScreen;///< object to blank the screen + /*#endif*/ QFileSystemWatcher* _notify; ///< used to get notifies about file changes //vnc-server diff --git a/src/pvsDaemon.cpp b/src/pvsDaemon.cpp old mode 100644 new mode 100755 index e87bfe7..e9479df --- a/src/pvsDaemon.cpp +++ b/src/pvsDaemon.cpp @@ -68,11 +68,17 @@ int main(int argc, char** argv) int port = -1; QFileInfo script; - script.setFile("/usr/bin/pvs-vncsrv"); - if (!script.exists()) - script.setFile("/usr/local/bin/pvs-vncsrv"); - if (!script.exists()) - script.setFile("/home/" + getUserName() + "/.pvs/pvs-vncsrv"); + #ifdef __WIN32__ + //TODO Win32 + if (!script.exists()) + script.setFile(getHomeDir() + "/.pvs/pvs-vncsrv_win32.bat"); + #else + script.setFile("/usr/bin/pvs-vncsrv"); + if (!script.exists()) + script.setFile("/usr/local/bin/pvs-vncsrv"); + if (!script.exists()) + script.setFile(getHomeDir() + "/.pvs/pvs-vncsrv"); + #endif //__WIN32__ QCoreApplication app(argc, argv); app.setOrganizationName("openslx"); @@ -293,6 +299,8 @@ int main(int argc, char** argv) #ifdef as_daemon + /*Alex: neu schreiben als pvsdaemon_win32.cpp und minimieren in Task-Leiste*/ + #ifndef __WIN32__ /* Our process ID and Session ID */ pid_t pid, sid; @@ -331,10 +339,10 @@ int main(int argc, char** argv) /* Close out the standard file descriptors */ close(STDIN_FILENO); - freopen ((QString("/home/").append(getUserName().append(QString("/.pvs/dump")))).toUtf8().data(),"w",stdout); + freopen ((QString(getHomeDir()).append(QString("/.pvs/dump"))).toUtf8().data(),"w",stdout); //close(STDOUT_FILENO); close(STDERR_FILENO); - + #endif /*__WIN32__*/ /* Daemon-specific initialization goes here */ /* The Big Loop */ diff --git a/src/pvsgui.cpp b/src/pvsgui.cpp index 6fdd673..b2f0a8f 100644 --- a/src/pvsgui.cpp +++ b/src/pvsgui.cpp @@ -107,7 +107,7 @@ PVSGUI::PVSGUI(QWidget *parent) : connect(_ifaceDBus, SIGNAL(delHost(QString)), this, SLOT(delHost(QString))); // show toolbar - setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); + setWindowFlags(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint); setAttribute(Qt::WA_AlwaysShowToolTips); updateConfig(); setVisible(true); diff --git a/src/util/clientGUIUtils.h b/src/util/clientGUIUtils.h old mode 100644 new mode 100755 index 28b05cc..b04d3fe --- a/src/util/clientGUIUtils.h +++ b/src/util/clientGUIUtils.h @@ -1,21 +1,20 @@ +#ifndef _BLANKSCREEN_H_ +#define _BLANKSCREEN_H_ + #include "src/util/consoleLogger.h" -#include // Every Xlib program must include this -#include #include #include #include - #define REFRESH_RATE 0.15 - -#ifndef _BLANKSCREEN_H_ -#define _BLANKSCREEN_H_ +class BlankScreen_Sysdep; class BlankScreen { public: BlankScreen(); + virtual ~BlankScreen(); void draw(bool force = false); bool lock(); bool unlock(); @@ -23,17 +22,7 @@ public: bool lock_inputs(); private: - Display *dpy; - Window win; - XEvent ev; - int scr; - - bool locked; - - - QString lockMsg; - int blackColor, whiteColor; - int offX, offY; + BlankScreen_Sysdep* _sysdep; }; -#endif +#endif \ No newline at end of file diff --git a/src/util/clientGUIUtils_Win32.cpp b/src/util/clientGUIUtils_Win32.cpp new file mode 100755 index 0000000..1b4d2ae --- /dev/null +++ b/src/util/clientGUIUtils_Win32.cpp @@ -0,0 +1,46 @@ + +#include "clientGUIUtils.h" +#include + +struct BlankScreen_Sysdep { + + bool locked; + QWidget* blankwin; + + QString lockMsg; + int blackColor, whiteColor; + int offX, offY; +}; + +BlankScreen::BlankScreen() +{ + _sysdep = new BlankScreen_Sysdep; + _sysdep->blankwin = new QWidget(0, Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + _sysdep->blankwin->setWindowState(Qt::WindowFullScreen); + _sysdep->blankwin->show(); +} + +BlankScreen::~BlankScreen() +{ + delete _sysdep; +} + +void BlankScreen::draw(bool force) +{ + +} + +bool BlankScreen::lock() +{ + return true; +} + +bool BlankScreen::lock_inputs() +{ + return true; +} + +bool BlankScreen::unlock() +{ + return true; +} diff --git a/src/util/clientGUIUtils_X11.cpp b/src/util/clientGUIUtils_X11.cpp new file mode 100755 index 0000000..29c96f0 --- /dev/null +++ b/src/util/clientGUIUtils_X11.cpp @@ -0,0 +1,168 @@ +#include "clientGUIUtils.h" +#include +#include + + +struct BlankScreen_Sysdep { + + Display *dpy; + Window win; + XEvent ev; + int scr; + + bool locked; + + + QString lockMsg; + int blackColor, whiteColor; + int offX, offY; +}; + +BlankScreen::BlankScreen() +{ + _sysdep = new BlankScreen_Sysdep; + _sysdep->dpy = XOpenDisplay(NULL); + _sysdep->scr = DefaultScreen(_sysdep->dpy); + assert(_sysdep->dpy); + _sysdep->blackColor = BlackPixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy)); + _sysdep->whiteColor = WhitePixel(_sysdep->dpy, DefaultScreen(_sysdep->dpy)); +// win = XCreateSimpleWindow(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), 0, 0, 200, 100, 0, blackColor, whiteColor); + _sysdep->win = XCreateSimpleWindow(_sysdep->dpy, RootWindow(_sysdep->dpy, _sysdep->scr), 10, 10, 200, 200, 1, WhitePixel(_sysdep->dpy, _sysdep->scr), BlackPixel(_sysdep->dpy, _sysdep->scr)); + + XSelectInput(_sysdep->dpy, _sysdep->win, ExposureMask | KeyPressMask); + _sysdep->locked = false; + _sysdep->offX = _sysdep->offY = 0; +} + +BlankScreen::~BlankScreen() +{ + delete _sysdep; +} + +void BlankScreen::draw(bool force) +{ + if (_sysdep->locked)// no need to draw if we're not showing the window + { + XWindowAttributes xwa; + XGetWindowAttributes(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), &xwa); + int hx = (xwa.width)>>2, hy = (xwa.height)>>2; + + if (XCheckTypedEvent(_sysdep->dpy, Expose, &_sysdep->ev) || force ) + { + hx += _sysdep->offX; + hy += _sysdep->offY; + + GC gcc = XCreateGC(_sysdep->dpy, _sysdep->win, 0, NULL); + XSetForeground(_sysdep->dpy, gcc, _sysdep->whiteColor); +// XClearArea(_sysdep->dpy, _sysdep->win, 0, 0, xwa.width, xwa.height, false); + if (_sysdep->lockMsg.size() > 0) + { + char *msg = const_cast(_sysdep->lockMsg.toUtf8().data()); + XDrawString(_sysdep->dpy, _sysdep->win, gcc/*DefaultGC(dpy, scr)*/, hx, hy, msg, strlen(msg)); + } + else + { + } + } + } +} + +bool BlankScreen::lock() +{ +#define lock_test + + if (_sysdep->locked) + return _sysdep->locked; + + // We want to get MapNotify events + XSelectInput(_sysdep->dpy, _sysdep->win, StructureNotifyMask); + + // "Map" the window (that is, make it appear on the screen) + XMapWindow(_sysdep->dpy, _sysdep->win); + + // Create a "Graphics Context" + //GC gc = XCreateGC(dpy, win, 0, NULL); + + XEvent xev; + Atom wm_state = XInternAtom(_sysdep->dpy, "_NET_WM_STATE", False); + Atom fullscreen = XInternAtom(_sysdep->dpy, "_NET_WM_STATE_FULLSCREEN", False); + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = _sysdep->win; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = fullscreen; + xev.xclient.data.l[2] = 0; + + XSendEvent(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), False, + SubstructureNotifyMask, &xev); + + + + + // Wait for the MapNotify event + for (;;) + { + XEvent e; + XNextEvent(_sysdep->dpy, &e); + if (e.type == MapNotify) + break; + } + //Flush it! + //XFlush(_sysdep->dpy); + +#ifndef lock_test + // load the locked cursor, so people dont think they can click anything + // TODO: Use some kind of invisible cursor instead of the wait-cursor + Cursor _sysdep->locked_cur = XCreateFontCursor(_sysdep->dpy, XC_watch); + XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy),_sysdep->locked_cur); +#endif + + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + + if (!_sysdep->locked) + ConsoleLog writeLine(QString("Locked")); + + // see header for more information on this switch + return _sysdep->locked = true; +} + +bool BlankScreen::lock_inputs() +{ + // grabbing of keyboard and mouse and hide the cursor + XGrabKeyboard(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, GrabModeAsync, GrabModeAsync, CurrentTime); + XGrabPointer(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), false, 0, GrabModeAsync, GrabModeAsync, None, NULL, CurrentTime); + return true; +} + +bool BlankScreen::unlock() +{ + + if (_sysdep->dpy) + { + + int retval = -1; + + //reset cursor to arrow (no *real* default here...) + Cursor normal_cur = XCreateFontCursor(_sysdep->dpy, XC_arrow); + XDefineCursor(_sysdep->dpy, DefaultRootWindow(_sysdep->dpy), normal_cur); + + // ungrabbing of keyboard and mouse + XUngrabPointer(_sysdep->dpy, CurrentTime); + XUngrabKeyboard(_sysdep->dpy, CurrentTime); + + + retval = XUnmapWindow(_sysdep->dpy,_sysdep->win); + if (retval == BadWindow) + ConsoleLog writeError(QString("Bad window while unmapping. Badwindow: ").append(int2String(retval))); + XFlush(_sysdep->dpy); + } + if (_sysdep->locked) + ConsoleLog writeLine(QString("Unlocked")); + + _sysdep->lockMsg.clear(); + return !(_sysdep->locked = false); +} diff --git a/src/util/consoleLogger.cpp b/src/util/consoleLogger.cpp old mode 100644 new mode 100755 index b523b40..ae29989 --- a/src/util/consoleLogger.cpp +++ b/src/util/consoleLogger.cpp @@ -226,7 +226,7 @@ void ConsoleLogger::_prepareLog() _logFileGood = false; _readLog(); - mkdir(getPolicyFilePath(QString()).toUtf8().data(), 0777); + createPolicyDir(); QString fullpath; fullpath.append(_logPath); //TODO: handle wether path/ or path were entered? diff --git a/src/util/util.cpp b/src/util/util.cpp old mode 100644 new mode 100755 index 946168e..7463ae0 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -6,7 +6,11 @@ #include #include #include - +#include +#ifdef __WIN32__ + #include + #include +#endif //__WIN32__ PVSServerEntry::PVSServerEntry(QString name) { @@ -45,7 +49,11 @@ int getRandom(int min, int max) if (init) { init = false; + #ifndef __WIN32__ srand ( time(NULL) + getpid() ); + #else + srand ( time(NULL) ); /*might be solved by another random factor*/ + #endif } if (min >= max) return rand(); return rand() % (max-min+1) + min; @@ -184,12 +192,29 @@ QString colonSplitter(QString line, bool first) QString getUserName() { - struct passwd* passUser = getpwuid(getuid()); QString username; - if (passUser) - { - username = QString(passUser->pw_name); - } + #ifdef __WIN32__ + WCHAR* lpszSystemInfo; // pointer to system information + DWORD cchBuff = 256; // size of user name + WCHAR tchBuffer[UNLEN + 1]; // buffer for expanded string + + lpszSystemInfo = tchBuffer; + + // Get and display the user name. + GetUserNameW(lpszSystemInfo, &cchBuff); + + //Unicode string needs to be converted + username = QString::fromWCharArray(lpszSystemInfo); + #elif defined __WIN32__ + struct passwd* passUser = getpwuid(getuid()); + + if (passwd) + username = passwd->pw_name; + if (passUser) + { + username = QString(passUser->pw_name); + } + #endif //#ifdef __WIN32__ if (username.isEmpty()) { printf("USERNAME COULDNT BE RETRIEVED!\n"); @@ -202,19 +227,21 @@ QString getUserName() QString getFullUsername() { QString fullname = getUserName(); - struct passwd *pd; + #ifndef __WIN32__ + struct passwd *pd; - if (NULL == (pd = getpwuid(getuid()))) - {ConsoleLog writeError("getpwuid() error.");} - else - { - QString tmp = pd->pw_gecos; - QStringList userData = tmp.split(","); - if(userData[0].length() > 0 ) + if (NULL == (pd = getpwuid(getuid()))) + {ConsoleLog writeError("getpwuid() error.");} + else { - fullname = userData[0]; + QString tmp = pd->pw_gecos; + QStringList userData = tmp.split(","); + if(userData[0].length() > 0 ) + { + fullname = userData[0]; + } } - } + #endif //__WIN32__ //might be completed some time to a full solution for WIN32 return fullname; } @@ -266,7 +293,8 @@ bool policyFileExists(QString fileName) void createPolicyDir() { - mkdir(getPolicyDir().toUtf8().data(), 0777); + QDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)).mkdir(".pvs"); + //assuming PolicyDir is defined like in getPolicyDir() } void createPolicyFiles() diff --git a/src/util/util.h b/src/util/util.h old mode 100644 new mode 100755 index 6ddefc6..4f2d0ee --- a/src/util/util.h +++ b/src/util/util.h @@ -4,7 +4,11 @@ #include #include #include -#include +#ifndef __WIN32__ + #include +#else + /*#include "pwd_win32.h"*/ +#endif /*__WIN32*/ #include #include -- cgit v1.2.3-55-g7522 From c544ec75d2314160f5591aab966a77ead26697d7 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Thu, 26 Aug 2010 22:58:37 +0200 Subject: Some refactoring --- CMakeLists.txt | 4 ++-- src/net/pvsServiceBroadcast.cpp | 10 +++------- src/version.h | 4 ++-- 3 files changed, 7 insertions(+), 11 deletions(-) (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index d2eae17..2ac01c9 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,8 +11,8 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.2 ) # set compiler optimizations for debug and release SET(CMAKE_BUILD_TYPE Debug) SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") -SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") -# -DQT_NO_DEBUG_OUTPUT") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2" ) +#-march=native -DQT_NO_DEBUG_OUTPUT # local cmake modules SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) diff --git a/src/net/pvsServiceBroadcast.cpp b/src/net/pvsServiceBroadcast.cpp index f68db56..46d287d 100644 --- a/src/net/pvsServiceBroadcast.cpp +++ b/src/net/pvsServiceBroadcast.cpp @@ -29,15 +29,11 @@ PVSServiceBroadcast::PVSServiceBroadcast() _timer = 0; _broadcaster.bind(SD_PORT_CONSOLE); - QList interfaces = QNetworkInterface::allInterfaces (); - foreach (QNetworkInterface interface, interfaces) - { - QList entries = interface.addressEntries(); - foreach (QNetworkAddressEntry entry, entries) { + foreach (QNetworkInterface interface, QNetworkInterface::allInterfaces()) + foreach (QNetworkAddressEntry entry, interface.addressEntries()) if (!entry.broadcast().isNull() && entry.broadcast().toString() != "127.255.255.255") _everyone.append(entry.broadcast()); - } - } + if (_everyone.isEmpty()) qDebug("ERROR: No broadcast address found"); } diff --git a/src/version.h b/src/version.h index ac24ac2..69a3bde 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ -#define VERSION_STRING "2.0.1.0" -#define VERSION_NUMBER 2010 +#define VERSION_STRING "2.0.2.0" +#define VERSION_NUMBER 2020 -- cgit v1.2.3-55-g7522 From ca61d21c6defb9553234c1fa5b0979c46542c676 Mon Sep 17 00:00:00 2001 From: Johann Latocha Date: Sat, 28 Aug 2010 03:17:08 +0200 Subject: Enhancement #587 --- CMakeLists.txt | 2 +- i18n/pvs_ar_JO.ts | 139 ++++++++++++++++++++++++++++++++++++-- i18n/pvs_de_DE.ts | 141 +++++++++++++++++++++++++++++++++++++-- i18n/pvs_es_MX.ts | 139 ++++++++++++++++++++++++++++++++++++-- i18n/pvs_fr_FR.ts | 139 ++++++++++++++++++++++++++++++++++++-- i18n/pvs_pl_PL.ts | 139 ++++++++++++++++++++++++++++++++++++-- i18n/pvsgui_ar_JO.ts | 66 +++++++++--------- i18n/pvsgui_de_DE.ts | 66 +++++++++--------- i18n/pvsgui_es_MX.ts | 66 +++++++++--------- i18n/pvsgui_fr_FR.ts | 66 +++++++++--------- i18n/pvsgui_pl_PL.ts | 66 +++++++++--------- org.openslx.pvs.service | 2 +- src/gui/clientChatDialog.cpp | 2 - src/gui/clientConfigDialog.cpp | 2 - src/gui/clientFileSendDialog.cpp | 2 - src/gui/clientVNCViewer.cpp | 2 - src/pvs.cpp | 9 ++- src/pvs.h | 2 +- src/pvsDaemon.cpp | 132 ++++++++++++++++-------------------- src/pvsgui.cpp | 34 ++++++---- src/pvsgui.h | 1 - src/version.h | 4 +- 22 files changed, 931 insertions(+), 290 deletions(-) (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ac01c9..e364528 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,7 +381,7 @@ SET( CPACK_SET_DESTDIR "ON" ) SET( CPACK_PACKAGE_NAME "pvs" ) SET( CPACK_PACKAGE_VERSION_MAJOR "2" ) SET( CPACK_PACKAGE_VERSION_MINOR "0" ) -SET( CPACK_PACKAGE_VERSION_PATCH "1" ) +SET( CPACK_PACKAGE_VERSION_PATCH "3" ) SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY "Pool Video Switch" ) SET( CPACK_PACKAGE_DESCRIPTION "") SET( CPACK_PACKAGE_CONTACT "Simon Wittenberg " ) diff --git a/i18n/pvs_ar_JO.ts b/i18n/pvs_ar_JO.ts index 38bf578..a57e4bd 100644 --- a/i18n/pvs_ar_JO.ts +++ b/i18n/pvs_ar_JO.ts @@ -4,24 +4,155 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! + + QObject + + + Version: + + + + + Usage: + + + + + <<option> <value>, ... > + + + + + Options: + + + + + -vncScriptFile <fullpath\filename> + + + + + Specifies a custom location for the vnc-start/stop-script. + + + + + If not specified, /usr/bin/pvs-vncsrv is expected. + + + + + -freq <seconds> + + + + + Specifies how long to wait until a reconnection attempt is made. + + + + + Default is 5. + + + + + -port <port> + + + + + Specifies on which port to run. + + + + + Default is + + + + + -h or --help + + + + + Shows this help text and exits. + + + + + -v or --version + + + + + Shows the current version and exits. + + + + + -d or --daemon + + + + + Start as daemon. + + + + + -c <string command>:<string value> + + + + + Sends the command and the optional value to a running PVS-Client. + + + + + Command and value may not contain spaces or colons. + + + + + The dividing colon is mandatory. + + + + + Prints out available commands to use with -c. + + + + + Use -h or --help to get a listing of all options. +-v or --version gives you the current version. + + + + + diff --git a/i18n/pvs_de_DE.ts b/i18n/pvs_de_DE.ts index 38bf578..a58199c 100644 --- a/i18n/pvs_de_DE.ts +++ b/i18n/pvs_de_DE.ts @@ -1,27 +1,158 @@ - + PVS - + Message - + VNC connection - + The host - + requested your screen! + + QObject + + + Version: + + + + + Usage: + + + + + <<option> <value>, ... > + + + + + Options: + + + + + -vncScriptFile <fullpath\filename> + + + + + Specifies a custom location for the vnc-start/stop-script. + + + + + If not specified, /usr/bin/pvs-vncsrv is expected. + + + + + -freq <seconds> + + + + + Specifies how long to wait until a reconnection attempt is made. + + + + + Default is 5. + + + + + -port <port> + + + + + Specifies on which port to run. + + + + + Default is + + + + + -h or --help + + + + + Shows this help text and exits. + + + + + -v or --version + + + + + Shows the current version and exits. + + + + + -d or --daemon + + + + + Start as daemon. + + + + + -c <string command>:<string value> + + + + + Sends the command and the optional value to a running PVS-Client. + + + + + Command and value may not contain spaces or colons. + + + + + The dividing colon is mandatory. + + + + + Prints out available commands to use with -c. + + + + + Use -h or --help to get a listing of all options. +-v or --version gives you the current version. + + + + + diff --git a/i18n/pvs_es_MX.ts b/i18n/pvs_es_MX.ts index 38bf578..a57e4bd 100644 --- a/i18n/pvs_es_MX.ts +++ b/i18n/pvs_es_MX.ts @@ -4,24 +4,155 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! + + QObject + + + Version: + + + + + Usage: + + + + + <<option> <value>, ... > + + + + + Options: + + + + + -vncScriptFile <fullpath\filename> + + + + + Specifies a custom location for the vnc-start/stop-script. + + + + + If not specified, /usr/bin/pvs-vncsrv is expected. + + + + + -freq <seconds> + + + + + Specifies how long to wait until a reconnection attempt is made. + + + + + Default is 5. + + + + + -port <port> + + + + + Specifies on which port to run. + + + + + Default is + + + + + -h or --help + + + + + Shows this help text and exits. + + + + + -v or --version + + + + + Shows the current version and exits. + + + + + -d or --daemon + + + + + Start as daemon. + + + + + -c <string command>:<string value> + + + + + Sends the command and the optional value to a running PVS-Client. + + + + + Command and value may not contain spaces or colons. + + + + + The dividing colon is mandatory. + + + + + Prints out available commands to use with -c. + + + + + Use -h or --help to get a listing of all options. +-v or --version gives you the current version. + + + + + diff --git a/i18n/pvs_fr_FR.ts b/i18n/pvs_fr_FR.ts index 38bf578..a57e4bd 100644 --- a/i18n/pvs_fr_FR.ts +++ b/i18n/pvs_fr_FR.ts @@ -4,24 +4,155 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! + + QObject + + + Version: + + + + + Usage: + + + + + <<option> <value>, ... > + + + + + Options: + + + + + -vncScriptFile <fullpath\filename> + + + + + Specifies a custom location for the vnc-start/stop-script. + + + + + If not specified, /usr/bin/pvs-vncsrv is expected. + + + + + -freq <seconds> + + + + + Specifies how long to wait until a reconnection attempt is made. + + + + + Default is 5. + + + + + -port <port> + + + + + Specifies on which port to run. + + + + + Default is + + + + + -h or --help + + + + + Shows this help text and exits. + + + + + -v or --version + + + + + Shows the current version and exits. + + + + + -d or --daemon + + + + + Start as daemon. + + + + + -c <string command>:<string value> + + + + + Sends the command and the optional value to a running PVS-Client. + + + + + Command and value may not contain spaces or colons. + + + + + The dividing colon is mandatory. + + + + + Prints out available commands to use with -c. + + + + + Use -h or --help to get a listing of all options. +-v or --version gives you the current version. + + + + + diff --git a/i18n/pvs_pl_PL.ts b/i18n/pvs_pl_PL.ts index 38bf578..a57e4bd 100644 --- a/i18n/pvs_pl_PL.ts +++ b/i18n/pvs_pl_PL.ts @@ -4,24 +4,155 @@ PVS - + Message - + VNC connection - + The host - + requested your screen! + + QObject + + + Version: + + + + + Usage: + + + + + <<option> <value>, ... > + + + + + Options: + + + + + -vncScriptFile <fullpath\filename> + + + + + Specifies a custom location for the vnc-start/stop-script. + + + + + If not specified, /usr/bin/pvs-vncsrv is expected. + + + + + -freq <seconds> + + + + + Specifies how long to wait until a reconnection attempt is made. + + + + + Default is 5. + + + + + -port <port> + + + + + Specifies on which port to run. + + + + + Default is + + + + + -h or --help + + + + + Shows this help text and exits. + + + + + -v or --version + + + + + Shows the current version and exits. + + + + + -d or --daemon + + + + + Start as daemon. + + + + + -c <string command>:<string value> + + + + + Sends the command and the optional value to a running PVS-Client. + + + + + Command and value may not contain spaces or colons. + + + + + The dividing colon is mandatory. + + + + + Prints out available commands to use with -c. + + + + + Use -h or --help to get a listing of all options. +-v or --version gives you the current version. + + + + + diff --git a/i18n/pvsgui_ar_JO.ts b/i18n/pvsgui_ar_JO.ts index 04d9717..83560ba 100644 --- a/i18n/pvsgui_ar_JO.ts +++ b/i18n/pvsgui_ar_JO.ts @@ -40,47 +40,47 @@ ClientChatDialog - + &Send File... - + has joined the chat. - + has left the chat. - + PVS File Transfer - + Send file ' - + ' to - + Connected. - + Disconnected. - + Message from < @@ -260,23 +260,23 @@ ClientFileSendDialog - + Open File - - + + PVS - File Transfer - + File Transfer complete. - + File Transfer canceled! @@ -399,77 +399,77 @@ p, li { white-space: pre-wrap; } - + &Disconnect - + C&hat - + &Send File - + &Config - + &Information - + &About - + &Quit - - - + + + PVS Connection - + Please enter password (If not needed leave blank): - + Are you sure you want to disconnect? - - + + PVS connection - - + + Connected to - - + + Disconnected - + New host available: diff --git a/i18n/pvsgui_de_DE.ts b/i18n/pvsgui_de_DE.ts index 544ebff..d49306a 100644 --- a/i18n/pvsgui_de_DE.ts +++ b/i18n/pvsgui_de_DE.ts @@ -40,47 +40,47 @@ ClientChatDialog - + &Send File... Datei &Senden... - + has joined the chat. ist dem Chat beigetreten. - + has left the chat. hat den Chat verlassen. - + PVS File Transfer PVS Dateiübertragung - + Send file ' Datei senden ' - + ' to ' an - + Connected. Verbunden. - + Disconnected. Getrennt. - + Message from < Nachricht von < @@ -260,23 +260,23 @@ ClientFileSendDialog - + Open File Datei Öffnen - - + + PVS - File Transfer PBS -Dateiübertragung - + File Transfer complete. Dateiübertragung beendet. - + File Transfer canceled! Dateiübertragung abgebrochen! @@ -407,77 +407,77 @@ p, li { white-space: pre-wrap; } Verbinden - + &Disconnect &Trennen - + C&hat - + &Send File Datei &Senden - + &Config &Konfiguration - + &Information &Information - + &About &Über - + &Quit &Beenden - - - + + + PVS Connection PVS Verbindung - + Please enter password (If not needed leave blank): Bitte geben sie ein Passwor ein (Falls nicht erforderlich einfach leer lassen): - + Are you sure you want to disconnect? Sind sie sicher dass sie die Verbindung trennen möchten? - - + + PVS connection PVS Verbindung - - + + Connected to Verbunden mit - - + + Disconnected Getrennt - + New host available: Neuer Host verfügbar: diff --git a/i18n/pvsgui_es_MX.ts b/i18n/pvsgui_es_MX.ts index 855ee9b..92db9d7 100644 --- a/i18n/pvsgui_es_MX.ts +++ b/i18n/pvsgui_es_MX.ts @@ -40,47 +40,47 @@ ClientChatDialog - + &Send File... Enviar archivo... - + has joined the chat. ha ingresado al chat. - + has left the chat. ha abandonado el chat - + PVS File Transfer PVS Transferencia de datos - + Send file ' Enviar archivo ' - + ' to ' a - + Connected. Conectado. - + Disconnected. Desconectado. - + Message from < Mensaje de < @@ -260,23 +260,23 @@ ClientFileSendDialog - + Open File Abrir archivo - - + + PVS - File Transfer PVS - Transferencia de datos - + File Transfer complete. La transferencia de datos ha sido completada. - + File Transfer canceled! La transferencia de datos ha sido cancelada! @@ -419,77 +419,77 @@ p, li { white-space: pre-wrap; } Conectar - + &Disconnect &Desconectar - + C&hat ??? - + &Send File &Enviar archivo - + &Config &Configuración - + &Information &Información - + &About &Acerca de - + &Quit &Cerrar - - - + + + PVS Connection PVS Connección - + Please enter password (If not needed leave blank): Porfavor ingrese una contraseña (Deje la seccion vacia si no lo necesita): - + Are you sure you want to disconnect? Realmente desea desconectarse? - - + + PVS connection PVS Connección - - + + Connected to Connectar a - - + + Disconnected Desconectado - + New host available: Nuevo Host disponible: diff --git a/i18n/pvsgui_fr_FR.ts b/i18n/pvsgui_fr_FR.ts index 04d9717..83560ba 100644 --- a/i18n/pvsgui_fr_FR.ts +++ b/i18n/pvsgui_fr_FR.ts @@ -40,47 +40,47 @@ ClientChatDialog - + &Send File... - + has joined the chat. - + has left the chat. - + PVS File Transfer - + Send file ' - + ' to - + Connected. - + Disconnected. - + Message from < @@ -260,23 +260,23 @@ ClientFileSendDialog - + Open File - - + + PVS - File Transfer - + File Transfer complete. - + File Transfer canceled! @@ -399,77 +399,77 @@ p, li { white-space: pre-wrap; } - + &Disconnect - + C&hat - + &Send File - + &Config - + &Information - + &About - + &Quit - - - + + + PVS Connection - + Please enter password (If not needed leave blank): - + Are you sure you want to disconnect? - - + + PVS connection - - + + Connected to - - + + Disconnected - + New host available: diff --git a/i18n/pvsgui_pl_PL.ts b/i18n/pvsgui_pl_PL.ts index 04d9717..83560ba 100644 --- a/i18n/pvsgui_pl_PL.ts +++ b/i18n/pvsgui_pl_PL.ts @@ -40,47 +40,47 @@ ClientChatDialog - + &Send File... - + has joined the chat. - + has left the chat. - + PVS File Transfer - + Send file ' - + ' to - + Connected. - + Disconnected. - + Message from < @@ -260,23 +260,23 @@ ClientFileSendDialog - + Open File - - + + PVS - File Transfer - + File Transfer complete. - + File Transfer canceled! @@ -399,77 +399,77 @@ p, li { white-space: pre-wrap; } - + &Disconnect - + C&hat - + &Send File - + &Config - + &Information - + &About - + &Quit - - - + + + PVS Connection - + Please enter password (If not needed leave blank): - + Are you sure you want to disconnect? - - + + PVS connection - - + + Connected to - - + + Disconnected - + New host available: diff --git a/org.openslx.pvs.service b/org.openslx.pvs.service index 0398081..91a3e67 100644 --- a/org.openslx.pvs.service +++ b/org.openslx.pvs.service @@ -1,4 +1,4 @@ [D-BUS Service] Name=org.openslx.pvs -Exec=@CMAKE_INSTALL_PREFIX@/bin/pvs +Exec=@CMAKE_INSTALL_PREFIX@/bin/pvs -d diff --git a/src/gui/clientChatDialog.cpp b/src/gui/clientChatDialog.cpp index 7c32790..163ac92 100644 --- a/src/gui/clientChatDialog.cpp +++ b/src/gui/clientChatDialog.cpp @@ -29,8 +29,6 @@ ClientChatDialog::ClientChatDialog(QWidget *parent) : // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/chat", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); connect(_ifaceDBus, SIGNAL(chat_receive(QString, QString, QString)), this, SLOT(receive(QString, QString, QString))); diff --git a/src/gui/clientConfigDialog.cpp b/src/gui/clientConfigDialog.cpp index 3e1ee50..0ee5908 100644 --- a/src/gui/clientConfigDialog.cpp +++ b/src/gui/clientConfigDialog.cpp @@ -28,8 +28,6 @@ ClientConfigDialog::ClientConfigDialog(QWidget *parent) : // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/config", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); } diff --git a/src/gui/clientFileSendDialog.cpp b/src/gui/clientFileSendDialog.cpp index ccb44b3..b4512c0 100644 --- a/src/gui/clientFileSendDialog.cpp +++ b/src/gui/clientFileSendDialog.cpp @@ -28,8 +28,6 @@ ClientFileSendDialog::ClientFileSendDialog(QWidget *parent) : // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/filesend", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); // get current users name from backend diff --git a/src/gui/clientVNCViewer.cpp b/src/gui/clientVNCViewer.cpp index d6a218b..d794b0b 100644 --- a/src/gui/clientVNCViewer.cpp +++ b/src/gui/clientVNCViewer.cpp @@ -22,8 +22,6 @@ ClientVNCViewer::ClientVNCViewer(QWidget *parent) : { // connect to D-Bus and get interface QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/vnc", this); - dbus.registerService("org.openslx.pvsgui"); _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); connect(_ifaceDBus, SIGNAL(project(QString, int, QString, bool, bool, int)), this, SLOT(open(QString, int, QString, bool, bool, int))); diff --git a/src/pvs.cpp b/src/pvs.cpp index 1c08be5..21b7bdf 100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -53,8 +53,10 @@ PVS::PVS() : // connect to D-Bus new PvsAdaptor(this); QDBusConnection dbus = QDBusConnection::sessionBus(); - dbus.registerObject("/", this); - dbus.registerService("org.openslx.pvs"); + if (!dbus.registerObject("/", this)) + qDebug("[ERROR] DBus: Could not register object"); + if (!dbus.registerService("org.openslx.pvs")) + qDebug("[ERROR] DBus: Could not register service"); _sdClient = new PVSServiceDiscovery(this); @@ -552,9 +554,10 @@ int PVS::stopVNCScript() } } -void PVS::start() +bool PVS::start() { _pvsServerConnection->sendMessage(PVSMsg(PVSCOMMAND, "PROJECTING", "YES")); + return true; } void PVS::onConnected(QString name) diff --git a/src/pvs.h b/src/pvs.h index b6b5e65..1bb0747 100755 --- a/src/pvs.h +++ b/src/pvs.h @@ -69,7 +69,7 @@ public: void guiDelHost(QString host); public Q_SLOTS: - void start(); + bool start(); void quit(); void chat_send(QString nick_to, QString nick_from, QString msg); QString chat_getNickname(); diff --git a/src/pvsDaemon.cpp b/src/pvsDaemon.cpp index e9479df..b23bc57 100755 --- a/src/pvsDaemon.cpp +++ b/src/pvsDaemon.cpp @@ -9,14 +9,12 @@ #include "src/core/pvsChatClient.h" PVS *mainClient = NULL; - -// This define works as a switch whether to run as deamon or regular app -#define as_daemon +QTextStream qout(stdout); /// VERSION_STRING is defined in src/version.h void printVersion(bool doExit) { - + QTextStream qout(stdout); printf("Version:\t"VERSION_STRING"\n"); if (doExit) exit(0); @@ -25,30 +23,31 @@ void printVersion(bool doExit) /// outputs the full help text void printHelp() { - printf("**************************************************************\n"); - printf("\nPool Video Switch Client\n"); - printf("**************************************************************\n"); - printVersion(false); - printf("**************************************************************\n"); - printf("Usage:\tpoolVSClient < + + + Network + + + + @@ -531,6 +538,14 @@ - + + + &Configure... + + + Configure Network Parameters + + diff --git a/src/gui/ui/mainwindowtouch.ui b/src/gui/ui/mainwindowtouch.ui index 9030b17..cf7e411 100644 --- a/src/gui/ui/mainwindowtouch.ui +++ b/src/gui/ui/mainwindowtouch.ui @@ -365,6 +365,8 @@ + + @@ -636,6 +638,15 @@ Ctrl+D + + + + :/netconf:/netconf + + + Configure Network... + + diff --git a/src/gui/ui/multicastConfigDialog.ui b/src/gui/ui/multicastConfigDialog.ui new file mode 100644 index 0000000..1ddf02c --- /dev/null +++ b/src/gui/ui/multicastConfigDialog.ui @@ -0,0 +1,156 @@ + + + MulticastConfigDialogClass + + + + 0 + 0 + 331 + 314 + + + + + 0 + 0 + + + + PVS - Multicast Configuration + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<table style="-qt-table-type: root; margin-top:4px; margin-bottom:4px; margin-left:4px; margin-right:4px;"> +<tr> +<td style="border: none;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You need to specify connection parameters for multicast messaging on your network. These parameters will automatically be distributed to client computers, so you need to assign them only once.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">You will probably want to assign an address from the <span style=" text-decoration: underline;">239.0.0.0/8</span> &quot;Administratively Scoped&quot; range.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Do not assign arbitrary numbers without checking with your network administrator!</span></p></td></tr></table></body></html> + + + true + + + + + + + + + Multicast Group Address + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 009.009.009.009; + + + ... + + + + + + + <span style=" font-weight:600; color:#008800;">OK</span> + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Data Port (1024-65535) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 00009; + + + 5 + + + + + + + <span style=" font-weight:600; color:#008800;">OK</span> + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Transmission Rate + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + KiB/s + + + 10240 + + + 10 + + + 100 + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + diff --git a/src/net/mcast/McastConfiguration.h b/src/net/mcast/McastConfiguration.h index 6884036..53f7a54 100644 --- a/src/net/mcast/McastConfiguration.h +++ b/src/net/mcast/McastConfiguration.h @@ -166,6 +166,23 @@ public: emit changed(); } + McastConfiguration& operator=(McastConfiguration const& source) + { + if(this != &source) + { + _multicastInterface = source._multicastInterface; + _multicastAddress = source._multicastAddress; + _multicastRate = source._multicastRate; + _multicastSPort = source._multicastSPort; + _multicastDPort = source._multicastDPort; + _multicastWinSize = source._multicastWinSize; + _multicastMTU = source._multicastMTU; + _multicastUDPPortBase = source._multicastUDPPortBase; + _multicastUseUDP = source._multicastUseUDP; + } + return *this; + } + void loadFrom(QSettings* settings, char const* group = 0); void writeTo(QSettings* settings, char const* group = 0) const; diff --git a/src/net/pvsListenServer.cpp b/src/net/pvsListenServer.cpp index f21303e..1c1387b 100644 --- a/src/net/pvsListenServer.cpp +++ b/src/net/pvsListenServer.cpp @@ -21,9 +21,13 @@ #include "pvsClientConnection.h" #include "src/util/consoleLogger.h" #include +#include +#include +#include #include "SslServer.h" #include //#define verbose +#include "mcast/McastConfiguration.h" // Create listener PVSListenServer::PVSListenServer(int port, int clients) @@ -36,6 +40,7 @@ PVSListenServer::PVSListenServer(int port, int clients) else _clientsMax = clients; _port = port; + _mcastConfig = 0; init(); } @@ -178,6 +183,7 @@ void PVSListenServer::onClientConnected(PVSClientConnection* connected) { connected->setServerID(_id); connected->setID(generateID()); + connected->push_back_send(mcastConfigMessage()); } void PVSListenServer::onClientDisconnected(PVSClientConnection* disconnected) @@ -227,6 +233,11 @@ PVSClientConnection* PVSListenServer::getConnectionFromID(int id) // Initialize listening socket bool PVSListenServer::init() { + if (_mcastConfig) + delete _mcastConfig; + _mcastConfig = new McastConfiguration(this); + loadMcastConfig(); + if (_listenSocket != NULL) shutdown(); @@ -306,3 +317,52 @@ bool PVSListenServer::isListening() { return _listenSocket != NULL && _listenSocket->isListening(); } + +void PVSListenServer::loadMcastConfig() +{ + QSettings settings; + _mcastConfig->loadFrom(&settings, "multicast-filetransfer"); +} + +void PVSListenServer::saveMcastConfig() +{ + QSettings settings; + _mcastConfig->writeTo(&settings, "multicast-filetransfer"); + settings.sync(); +} + +PVSMsg PVSListenServer::mcastConfigMessage() +{ + // If anything is changed here, do not forget to + // 1. assign a new version number + // 2. adapt PVS::onCommand(PVSMsg) in pvs.cpp + QByteArray ba; + QDataStream strm(&ba, QIODevice::WriteOnly); + strm << (quint16)1 // version + << _mcastConfig->multicastAddress() + << _mcastConfig->multicastUDPPortBase() + << _mcastConfig->multicastDPort() + << _mcastConfig->multicastSPort() + << _mcastConfig->multicastMTU() + << _mcastConfig->multicastWinSize() + << _mcastConfig->multicastRate() + << _mcastConfig->multicastUseUDP(); + + QByteArray b64 = ba.toBase64(); + QString message = QString::fromAscii(b64.constData(), b64.length()); + PVSMsg msg(PVSCOMMAND, "MCASTFTCONFIG", message); + return msg; +} + +void PVSListenServer::multicastReconfigure(McastConfiguration const* source) +{ + _mcastConfig->multicastAddress(source->multicastAddress()); + *_mcastConfig = *source; + saveMcastConfig(); + sendToAll(mcastConfigMessage()); +} + +McastConfiguration const* PVSListenServer::getMulticastConfiguration() +{ + return _mcastConfig; +} diff --git a/src/net/pvsListenServer.h b/src/net/pvsListenServer.h index ab021c7..90d2a77 100644 --- a/src/net/pvsListenServer.h +++ b/src/net/pvsListenServer.h @@ -10,6 +10,7 @@ class SslServer; class PVSClientConnection; class PVSMsg; +class McastConfiguration; class PVSListenServer : public QObject { @@ -40,6 +41,12 @@ private: bool init(); unsigned int generateID(); + McastConfiguration* _mcastConfig; + + void loadMcastConfig(); + void saveMcastConfig(); + PVSMsg mcastConfigMessage(); + protected: void timerEvent(QTimerEvent *event); @@ -60,6 +67,9 @@ public: bool disconnectClient(PVSClientConnection* delinquent); void onConnectionRemoved(PVSClientConnection* delinquent); + void multicastReconfigure(McastConfiguration const* source); + McastConfiguration const* getMulticastConfiguration(); + std::list* getClientListPtr() { return &_clients; diff --git a/src/pvs.cpp b/src/pvs.cpp index 9bd36d6..df21468 100644 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -45,7 +45,10 @@ PVS::PVS() : loadCommands(); _blankScreen = NULL; _vncPort = -1; + + QSettings settings; _masterMcastConfig = new McastConfiguration(this); + _masterMcastConfig->loadFrom(&settings); // add a notify to the allow file, so we get informed when the file is changed QString watchPath("/home/"); @@ -234,6 +237,11 @@ void PVS::onCommand(PVSMsg cmdMessage) qDebug() << "Ignoring malformed MCASTFTANNOUNCE command: " << message; return; } + if (ident.compare("MCASTFTCONFIG") == 0) + { + loadMcastConfig(message); + return; + } #ifdef never // prototype @@ -735,7 +743,8 @@ void PVS::cancelIncomingMulticastTransfer(qulonglong transferID) void PVS::setMulticastInterface(QString const& interfaceName) { QSettings settings; - settings.setValue("multicast/interface", interfaceName); + _masterMcastConfig->multicastInterface(interfaceName); + _masterMcastConfig->writeTo(&settings, "multicast"); settings.sync(); } @@ -814,3 +823,50 @@ void PVS::incomingMulticastTransferDelete(qulonglong transferID) _incomingTransfers.remove(transferID); transfer->deleteLater(); } + +void PVS::loadMcastConfig(QString const& message) +{ + QByteArray ba = QByteArray::fromBase64(message.toAscii()); + QDataStream d(&ba, QIODevice::ReadOnly); + quint16 ver, udpp, dp, sp, mtu, wsz; + quint32 rate; + QString addr; + bool useudp; + + d >> ver; + if(ver != 1) + { + ConsoleLog writeLine(QString("Unable to decode multicast configuration message: Unknown version %1").arg(ver)); + return; + } + + d >> addr + >> udpp + >> dp + >> sp + >> mtu + >> wsz + >> rate + >> useudp; + if(d.status() != QDataStream::Ok) + { + ConsoleLog writeLine(QString("Unable to decode multicast configuration message: There was an error reading")); + return; + } + + _masterMcastConfig->multicastUDPPortBase(udpp); + _masterMcastConfig->multicastDPort(dp); + _masterMcastConfig->multicastSPort(sp); + _masterMcastConfig->multicastMTU(mtu); + _masterMcastConfig->multicastWinSize(wsz); + _masterMcastConfig->multicastRate(rate); + _masterMcastConfig->multicastAddress(addr); + _masterMcastConfig->multicastUseUDP(useudp); + + QSettings settings; + _masterMcastConfig->writeTo(&settings, "multicast"); + settings.sync(); + + ConsoleLog writeLine(QString("Reconfigured multicast filetransfer to IP %1, UDP port base %2, destination port %3, source port %4, MTU %5, Window Size %6, rate %7, %8using UDP") + .arg(addr).arg(udpp).arg(dp).arg(sp).arg(mtu).arg(wsz).arg(rate).arg(useudp ? "" : "not ")); +} diff --git a/src/pvs.h b/src/pvs.h index 4c61ffd..3b3365c 100644 --- a/src/pvs.h +++ b/src/pvs.h @@ -88,6 +88,7 @@ public Q_SLOTS: void cancelOutgoingMulticastTransfer(quint64 transferID); void cancelIncomingMulticastTransfer(qulonglong transferID); void setMulticastInterface(QString const& interfaceName); + void loadMcastConfig(QString const& encoded); Q_SIGNALS: void project(QString host, int port, QString passwd, bool fullscreen, -- cgit v1.2.3-55-g7522 From c73f21c8a607b99c855d5cce545a305f16ac9354 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 15:43:16 +0200 Subject: Forgot to add pvsNetworkInterfaceListModel.cpp to CMakeLists.txt --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'CMakeLists.txt') diff --git a/CMakeLists.txt b/CMakeLists.txt index 0899bdf..8afb407 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,6 +116,7 @@ SET( PVSGUI_SRCS src/util/vncClientThread.cpp src/util/TextFile.cpp src/gui/aboutDialog.cpp + src/net/pvsNetworkInterfaceListModel.cpp ) @@ -212,6 +213,7 @@ SET( PVSGUI_MOC_HDRS src/gui/clientInfoDialog.h src/util/vncClientThread.h src/gui/aboutDialog.h + src/net/pvsNetworkInterfaceListModel.h ) # i18n (Qt) -- cgit v1.2.3-55-g7522