Compare commits

...

11 Commits

Author SHA1 Message Date
JesseQu 53614275d0 added into our own repository. 2025-07-28 11:43:03 +08:00
Emiel Bruijntjes 839f74f2e7
Merge pull request #544 from DHP86/decode-type-x
Add type 'x' in Field::decode.
2025-06-30 15:26:09 +02:00
DHP86 71abd6d1d1 Add type 'x' in Field::decode.
type 'x' means byte array (array of unsigned chars) so it is strictly not correct to return a LongString (array of signed chars). But with this change the library can continue going after receiving type 'x'. The original code crashes or starts doing undefined things when receiving a nonempty byte array from a client.
2025-06-23 14:58:32 +02:00
Emiel Bruijntjes ca49382bfc prepare for next release 4.3.27 2024-10-25 07:51:18 +02:00
Emiel Bruijntjes 6a68d56660 added support for std::string_view for tables and fields 2024-10-24 18:41:00 +02:00
Emiel Bruijntjes ba4b8d3685 Disable heartbeats for libevent because no timers have been implemented (fixes #533) 2024-07-08 20:15:11 +02:00
Emiel Bruijntjes 32faf9526a small fix to AMQP::Tagger in case it gets destructed before the close-callbacks are called 2024-04-21 08:29:37 +02:00
Emiel Bruijntjes 8fea64cdec
Merge pull request #515 from SpaceIm/fix-windows-install-dll
CMake: few fixes for windows shared
2023-10-10 11:20:25 +02:00
SpaceIm bd1b3e5d46 few fixes for windows shared
- install DLL in bin folder instead of lib folder
- export symbols if msvc for shared lib, otherwise import lib of DLL is empty. Visual Studio hides symbols by default. WINDOWS_EXPORT_ALL_SYMBOLS is a workaround, the proper way would be to hide all symbols irrespective of compiler, and carefully export symbols of AMQP-CPP interface.
2023-10-10 11:16:52 +02:00
Emiel Bruijntjes 2448a2ad93
Merge pull request #514 from SpaceIm/fix-mingw-link-ws2_32
CMake: explicit link to ws2_32 if targeting Windows
2023-10-10 11:15:07 +02:00
SpaceIm 2b17473cd6 explicit link to ws2_32 if targeting Windows
#pragma comment(lib,"Ws2_32.lib") in endian.h is a hack and is not portable. It only works for Visual Studio, not gcc or clang on Windows.
2023-10-10 11:03:53 +02:00
8 changed files with 72 additions and 31 deletions

View File

@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
project(amqpcpp) project(amqpcpp)
set (VERSION_MAJOR 4) set (VERSION_MAJOR 4)
set (VERSION_MINOR 3) set (VERSION_MINOR 3)
set (VERSION_PATCH 26) set (VERSION_PATCH 27)
set (SO_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}) set (SO_VERSION ${VERSION_MAJOR}.${VERSION_MINOR})
# build options # build options
@ -84,35 +84,36 @@ if(AMQP-CPP_BUILD_SHARED)
# create shared lib # create shared lib
#add_library(${PROJECT_NAME} SHARED ${SRCS}) #add_library(${PROJECT_NAME} SHARED ${SRCS})
add_library(${PROJECT_NAME} SHARED ${src_MAIN} ${src_LINUX_TCP}) add_library(${PROJECT_NAME} SHARED ${src_MAIN} ${src_LINUX_TCP})
set_target_properties(${PROJECT_NAME} PROPERTIES
# set shared lib version # set shared lib version
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${SO_VERSION}) SOVERSION ${SO_VERSION}
# export symbols for Visual Studio as a workaround
WINDOWS_EXPORT_ALL_SYMBOLS ON
)
else() else()
# create static lib # create static lib
#add_library(${PROJECT_NAME} STATIC ${SRCS}) #add_library(${PROJECT_NAME} STATIC ${SRCS})
add_library(${PROJECT_NAME} STATIC ${src_MAIN} ${src_LINUX_TCP}) add_library(${PROJECT_NAME} STATIC ${src_MAIN} ${src_LINUX_TCP})
endif() endif()
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC ws2_32)
endif()
# install rules # install rules
# ------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------
if(AMQP-CPP_BUILD_SHARED) include(GNUInstallDirs)
# copy shared lib and its static counter part
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config
ARCHIVE DESTINATION lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION lib RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) )
else()
# copy static lib
install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config
ARCHIVE DESTINATION lib
)
endif()
# copy header files # copy header files
install(DIRECTORY include/amqpcpp/ DESTINATION include/amqpcpp install(DIRECTORY include/amqpcpp/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amqpcpp
FILES_MATCHING PATTERN "*.h") FILES_MATCHING PATTERN "*.h")
install(FILES include/amqpcpp.h DESTINATION include) install(FILES include/amqpcpp.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(EXPORT ${PROJECT_NAME}Config DESTINATION cmake) install(EXPORT ${PROJECT_NAME}Config DESTINATION cmake)
export(TARGETS ${PROJECT_NAME} FILE ${PROJECT_NAME}Config.cmake) export(TARGETS ${PROJECT_NAME} FILE ${PROJECT_NAME}Config.cmake)
@ -121,7 +122,7 @@ set(DEST_DIR "${CMAKE_INSTALL_PREFIX}")
set(PRIVATE_LIBS "-llibamqpcc") set(PRIVATE_LIBS "-llibamqpcc")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/amqpcpp.pc.in" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/amqpcpp.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/amqpcpp.pc" @ONLY) "${CMAKE_CURRENT_BINARY_DIR}/amqpcpp.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/amqpcpp.pc" DESTINATION lib/pkgconfig) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/amqpcpp.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
# submodule support # submodule support
# ------------------------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------------------------

View File

@ -3,7 +3,7 @@ INCLUDE_DIR = ${PREFIX}/include
LIBRARY_DIR = ${PREFIX}/lib LIBRARY_DIR = ${PREFIX}/lib
export LIBRARY_NAME = amqpcpp export LIBRARY_NAME = amqpcpp
export SONAME = 4.3 export SONAME = 4.3
export VERSION = 4.3.26 export VERSION = 4.3.27
all: all:
$(MAKE) VERSION=${VERSION} -C src all $(MAKE) VERSION=${VERSION} -C src all

View File

@ -2,7 +2,7 @@
* Field proxy. Returned by the table. Can be casted to the * Field proxy. Returned by the table. Can be casted to the
* relevant native type (std::string or numeric) * relevant native type (std::string or numeric)
* *
* @copyright 2014 Copernica BV * @copyright 2014 - 2024 Copernica BV
*/ */
/** /**
@ -207,6 +207,22 @@ public:
return *this; return *this;
} }
/**
* Assign a string value
*
* @param value
* @return FieldProxy
*/
FieldProxy &operator=(const std::string_view &value)
{
// in theory we should make a distinction between short and long string,
// but in practive only long strings are accepted
_source->set(_index, LongString(value));
// allow chaining
return *this;
}
/** /**
* Assign a string value * Assign a string value
* *

View File

@ -140,6 +140,22 @@ private:
std::map<int,std::unique_ptr<Watcher>> _watchers; std::map<int,std::unique_ptr<Watcher>> _watchers;
/**
* Method that is called when the heartbeat frequency is negotiated
* @param connection The connection that suggested a heartbeat interval
* @param interval The suggested interval from the server
* @return uint16_t The interval to use
*/
virtual uint16_t onNegotiate(TcpConnection *connection, uint16_t interval) override
{
// call base (in the highly theoretical case that the base class does something meaningful)
auto response = TcpHandler::onNegotiate(connection, interval);
// because the LibEvHandler has not yet implemented timers for ensuring that we send
// some data every couple of seconds, we disabled timeouts
return 0;
}
/** /**
* Method that is called by AMQP-CPP to register a filedescriptor for readability or writability * Method that is called by AMQP-CPP to register a filedescriptor for readability or writability
* @param connection The TCP connection object that is reporting * @param connection The TCP connection object that is reporting

View File

@ -138,6 +138,7 @@ public:
Table &set(const std::string &name, uint64_t value) { return set(name, ULongLong(value)); } Table &set(const std::string &name, uint64_t value) { return set(name, ULongLong(value)); }
Table &set(const std::string &name, int64_t value) { return set(name, LongLong(value)); } Table &set(const std::string &name, int64_t value) { return set(name, LongLong(value)); }
Table &set(const std::string &name, const std::string &value) { return set(name, LongString(value)); } Table &set(const std::string &name, const std::string &value) { return set(name, LongString(value)); }
Table &set(const std::string &name, const std::string_view &value) { return set(name, LongString(value)); }
Table &set(const std::string &name, const char *value) { return set(name, LongString(std::string(value))); } Table &set(const std::string &name, const char *value) { return set(name, LongString(std::string(value))); }
Table &set(const std::string &name, std::nullptr_t) { return set(name, VoidField()); } Table &set(const std::string &name, std::nullptr_t) { return set(name, VoidField()); }

View File

@ -43,6 +43,7 @@ std::unique_ptr<Field> Field::decode(InBuffer &frame)
case 'T': return std::unique_ptr<Field>(new Timestamp(frame)); case 'T': return std::unique_ptr<Field>(new Timestamp(frame));
case 'F': return std::unique_ptr<Field>(new Table(frame)); case 'F': return std::unique_ptr<Field>(new Table(frame));
case 'V': return std::unique_ptr<Field>(new VoidField(frame)); case 'V': return std::unique_ptr<Field>(new VoidField(frame));
case 'x': return std::unique_ptr<Field>(new LongString(frame));
default: return nullptr; default: return nullptr;
} }
} }

View File

@ -4,7 +4,7 @@
* Implementation for Tagger class. * Implementation for Tagger class.
* *
* @author Michael van der Werve <michael.vanderwerve@mailerq.com> * @author Michael van der Werve <michael.vanderwerve@mailerq.com>
* @copyright 2020 - 2023 Copernica BV * @copyright 2020 - 2024 Copernica BV
*/ */
/** /**
@ -80,12 +80,15 @@ void Tagger::onAck(uint64_t deliveryTag, bool multiple)
// leap out if there are still messages or we shouldn't close yet // leap out if there are still messages or we shouldn't close yet
if (!_close || unacknowledged()) return; if (!_close || unacknowledged()) return;
// we make a local copy to keep the object in scope even when 'this' is deleted
auto close = _close;
// close the channel, and forward the callbacks to the installed handler // close the channel, and forward the callbacks to the installed handler
// we need to be sure the the deffered object stays alive even if the callback // we need to be sure the the deffered object stays alive even if the callback
// decides to remove us. // decides to remove us.
_implementation->close() _implementation->close()
.onSuccess([this]() { auto close = _close; close->reportSuccess(); }) .onSuccess([close]() { close->reportSuccess(); })
.onError([this](const char *message) { auto close = _close; close->reportError(message); }); .onError([close](const char *message) { close->reportError(message); });
} }
/** /**
@ -98,12 +101,15 @@ void Tagger::onNack(uint64_t deliveryTag, bool multiple)
// leap out if there are still messages or we shouldn't close yet // leap out if there are still messages or we shouldn't close yet
if (!_close || unacknowledged()) return; if (!_close || unacknowledged()) return;
// we make a local copy to keep the object in scope even when 'this' is deleted
auto close = _close;
// close the channel, and forward the callbacks to the installed handler // close the channel, and forward the callbacks to the installed handler
// we need to be sure the the deffered object stays alive even if the callback // we need to be sure the the deffered object stays alive even if the callback
// decides to remove us. // decides to remove us.
_implementation->close() _implementation->close()
.onSuccess([this]() { auto close = _close; close->reportSuccess(); }) .onSuccess([close]() { close->reportSuccess(); })
.onError([this](const char *message) { auto close = _close; close->reportError(message); }); .onError([close](const char *message) { close->reportError(message); });
} }
/** /**
@ -182,8 +188,8 @@ Deferred &Tagger::close()
// if this was already set to be closed, return that // if this was already set to be closed, return that
if (_close) return *_close; if (_close) return *_close;
// create the deferred // create the deferred (we make a local copy to keep the object in scope even when 'this is deleted)
_close = std::make_shared<Deferred>(!_implementation->usable()); auto close = _close = std::make_shared<Deferred>(!_implementation->usable());
// if there are open messages or there is a queue, they will still get acked and we will then forward it // if there are open messages or there is a queue, they will still get acked and we will then forward it
if (unacknowledged()) return *_close; if (unacknowledged()) return *_close;
@ -192,8 +198,8 @@ Deferred &Tagger::close()
// we need to be sure the the deffered object stays alive even if the callback // we need to be sure the the deffered object stays alive even if the callback
// decides to remove us. // decides to remove us.
_implementation->close() _implementation->close()
.onSuccess([this]() { auto close = _close; close->reportSuccess(); }) .onSuccess([close]() { close->reportSuccess(); })
.onError([this](const char *message) { auto close = _close; close->reportError(message); }); .onError([close](const char *message) { close->reportError(message); });
// return the created deferred // return the created deferred
return *_close; return *_close;