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 shared lib version set_target_properties(${PROJECT_NAME} PROPERTIES
set_target_properties(${PROJECT_NAME} PROPERTIES SOVERSION ${SO_VERSION}) # set shared lib 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 ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION lib RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
RUNTIME DESTINATION lib )
)
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

@ -10,7 +10,7 @@ The library can be used to parse incoming data from, and generate frames to, a R
OVERVIEW OVERVIEW
======== ========
**Are you upgrading from AMQP-CPP 3 to AMQP-CPP 4?** [Please read the upgrade instructions](#upgrading) ** Are you upgrading from AMQP-CPP 3 to AMQP-CPP 4?** [Please read the upgrade instructions](#upgrading)
**Note for the reader:** This readme file has a peculiar structure. We start **Note for the reader:** This readme file has a peculiar structure. We start
explaining the pure and hard core low level interface in which you have to explaining the pure and hard core low level interface in which you have to

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;