From bbeb99056aa8fbbf54c29abf2baee680f1d0dbbd Mon Sep 17 00:00:00 2001 From: brunoherbelin Date: Tue, 20 Oct 2020 18:27:26 +0200 Subject: [PATCH] Update to OSCPack v1.1 --- ext/OSCPack/LICENSE | 66 ++-- ext/OSCPack/README | 300 +++++++++--------- ext/OSCPack/ip/IpEndpointName.cpp | 35 +- ext/OSCPack/ip/IpEndpointName.h | 29 +- ext/OSCPack/ip/NetworkingUtils.h | 27 +- ext/OSCPack/ip/PacketListener.h | 27 +- ext/OSCPack/ip/TimerListener.h | 27 +- ext/OSCPack/ip/UdpSocket.h | 62 ++-- ext/OSCPack/ip/posix/NetworkingUtils.cpp | 27 +- ext/OSCPack/ip/posix/UdpSocket.cpp | 272 +++++++++------- ext/OSCPack/ip/win32/NetworkingUtils.cpp | 27 +- ext/OSCPack/ip/win32/UdpSocket.cpp | 108 +++++-- .../osc/MessageMappingOscPacketListener.h | 31 +- ext/OSCPack/osc/OscException.h | 30 +- ext/OSCPack/osc/OscOutboundPacketStream.cpp | 142 ++++++--- ext/OSCPack/osc/OscOutboundPacketStream.h | 42 ++- ext/OSCPack/osc/OscPacketListener.h | 27 +- ext/OSCPack/osc/OscPrintReceivedElements.cpp | 66 ++-- ext/OSCPack/osc/OscPrintReceivedElements.h | 29 +- ext/OSCPack/osc/OscReceivedElements.cpp | 286 ++++++++++------- ext/OSCPack/osc/OscReceivedElements.h | 166 +++++++--- ext/OSCPack/osc/OscTypes.cpp | 28 +- ext/OSCPack/osc/OscTypes.h | 92 +++++- 23 files changed, 1217 insertions(+), 729 deletions(-) diff --git a/ext/OSCPack/LICENSE b/ext/OSCPack/LICENSE index ebaaac1..7b11e28 100644 --- a/ext/OSCPack/LICENSE +++ b/ext/OSCPack/LICENSE @@ -1,34 +1,34 @@ -oscpack -- Open Sound Control (OSC) packet manipulation library -http://www.rossbencina.com/code/oscpack - -Copyright (c) 2004-2013 Ross Bencina - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files -(the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF -CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -### - -The text above constitutes the entire oscpack license; however, -the oscpack developer(s) also make the following non-binding requests: - -Any person wishing to distribute modifications to the Software is -requested to send the modifications to the original developer so that -they can be incorporated into the canonical version. It is also -requested that these non-binding requests be included whenever the +oscpack -- Open Sound Control (OSC) packet manipulation library +http://www.rossbencina.com/code/oscpack + +Copyright (c) 2004-2013 Ross Bencina + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files +(the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF +CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +### + +The text above constitutes the entire oscpack license; however, +the oscpack developer(s) also make the following non-binding requests: + +Any person wishing to distribute modifications to the Software is +requested to send the modifications to the original developer so that +they can be incorporated into the canonical version. It is also +requested that these non-binding requests be included whenever the above license is reproduced. \ No newline at end of file diff --git a/ext/OSCPack/README b/ext/OSCPack/README index 5d1d5c1..4382775 100644 --- a/ext/OSCPack/README +++ b/ext/OSCPack/README @@ -1,150 +1,150 @@ -oscpack -- Open Sound Control packet manipulation library -A simple C++ library for packing and unpacking OSC packets. -http://www.rossbencina.com/code/oscpack - -Copyright (c) 2004-2013 Ross Bencina - - -Oscpack is simply a set of C++ classes for packing and unpacking OSC packets. -Oscpack includes a minimal set of UDP networking classes for Windows and POSIX. -The networking classes are sufficient for writing many OSC applications and servers, -but you are encouraged to use another networking framework if it better suits your needs. -Oscpack is not an OSC application framework. It doesn't include infrastructure for -constructing or routing OSC namespaces, just classes for easily constructing, -sending, receiving and parsing OSC packets. The library should also be easy to use -for other transport methods (e.g. serial). - -The key goals of the oscpack library are: - - - Be a simple and complete implementation of OSC - - Be portable to a wide variety of platforms - - Allow easy development of robust OSC applications - (for example it should be impossible to crash a server - by sending it malformed packets, and difficult to create - malformed packets.) - -Here's a quick run down of the key files: - -osc/OscReceivedElements -- classes for parsing a packet -osc/OscPrintRecievedElements -- iostream << operators for printing packet elements -osc/OscOutboundPacketStream -- a class for packing messages into a packet -osc/OscPacketListener -- base class for listening to OSC packets on a UdpSocket -ip/IpEndpointName -- class that represents an IP address and port number -ip/UdpSocket -- classes for UDP transmission and listening sockets -tests/OscUnitTests -- unit test program for the OSC modules -tests/OscSendTests -- examples of how to send messages -tests/OscReceiveTest -- example of how to receive the messages sent by OSCSendTests -examples/OscDump -- a program that prints received OSC packets -examples/SimpleSend -- a minimal program to send an OSC message -examples/SimpleReceive -- a minimal program to receive an OSC message - -osc/ contains all of the OSC related classes -ip/ contains the networking classes - -ip/windows contains the Windows implementation of the networking classes -ip/posix contains the POSIX implementation of the networking classes - - -Building --------- - -The idea is that you will embed this source code in your projects as you -see fit. The Makefile has an install rule for building a shared library and -installing headers in usr/local. It can also build a static library. -There is a CMakeLists.txt for building with cmake. - -Makefile builds -............... - -The Makefile works for Linux and Max OS X. It should also work on other platforms -that have make. Just run: - -$ make - -You can run "make install" if you like. - - -Cmake builds -............ - -There is a CMakeLists.txt file which has been tested with cmake on -Windows and Linux. It should work on other platforms too. -For example, to generate a Visual Studio 10 project, run cmake -like this: - -> cmake -G "Visual Studio 10" - -Run cmake without any parameters to get a list of available generators. - - -Mingw build batch file -...................... - -For Windows there is a batch file for doing a simple test build with -MinGW gcc called make.MinGW32.bat. This will build the test executables -and oscdump in ./bin and run the unit tests. - - -Note: - -In some rare instances you may need to edit the Makefile or -osc/OscHostEndianness.h to configure oscpack for the endianness of your -processor (see the comments at the top of the Makefile for details). - - - -Verification test ------------------ - -To run the unit tests: - -$ ./bin/OscUnitTests - -To run the send and receive tests. Open two terminals. In one run: - -$ ./bin/OscReceiveTest - -Then in the other terminal run: - -$./bin/OscSendTests - - -You should see an indication that the messages were received -in the first terminal. - -Note that OscSendTests intentionally sends some unexpected -message parameters to test exception handling in the receiver. -You will see some "error while parsing message" messages printed. - -You can use ./bin/OscDump to print out OSC messages received -from any program, including the test programs. - - --- - - -If you fix anything or write a set of TCP send/receive classes -please consider sending me a patch. My email address is -rossb@audiomulch.com. Thanks :) - -For more information about Open Sound Control, see: -http://opensoundcontrol.org/ - -Thanks to Till Bovermann for helping with POSIX networking code and -Mac compatibility, and to Martin Kaltenbrunner and the rest of the -reacTable team for giving me a reason to finish this library. Thanks -to Merlijn Blaauw for reviewing the interfaces. Thanks to Xavier Oliver -for additional help with Linux builds and POSIX implementation details. - -Portions developed at the Music Technology Group, Audiovisual Institute, -University Pompeu Fabra, Barcelona, during my stay as a visiting -researcher, November 2004 - September 2005. - -Thanks to Syneme at the University of Calgary for providing financial -support for the 1.1.0 update, December 2012 - March 2013. - -See the file CHANGES for information about recent updates. - -See the file LICENSE for information about distributing and using this code. - -### +oscpack -- Open Sound Control packet manipulation library +A simple C++ library for packing and unpacking OSC packets. +http://www.rossbencina.com/code/oscpack + +Copyright (c) 2004-2013 Ross Bencina + + +Oscpack is simply a set of C++ classes for packing and unpacking OSC packets. +Oscpack includes a minimal set of UDP networking classes for Windows and POSIX. +The networking classes are sufficient for writing many OSC applications and servers, +but you are encouraged to use another networking framework if it better suits your needs. +Oscpack is not an OSC application framework. It doesn't include infrastructure for +constructing or routing OSC namespaces, just classes for easily constructing, +sending, receiving and parsing OSC packets. The library should also be easy to use +for other transport methods (e.g. serial). + +The key goals of the oscpack library are: + + - Be a simple and complete implementation of OSC + - Be portable to a wide variety of platforms + - Allow easy development of robust OSC applications + (for example it should be impossible to crash a server + by sending it malformed packets, and difficult to create + malformed packets.) + +Here's a quick run down of the key files: + +osc/OscReceivedElements -- classes for parsing a packet +osc/OscPrintRecievedElements -- iostream << operators for printing packet elements +osc/OscOutboundPacketStream -- a class for packing messages into a packet +osc/OscPacketListener -- base class for listening to OSC packets on a UdpSocket +ip/IpEndpointName -- class that represents an IP address and port number +ip/UdpSocket -- classes for UDP transmission and listening sockets +tests/OscUnitTests -- unit test program for the OSC modules +tests/OscSendTests -- examples of how to send messages +tests/OscReceiveTest -- example of how to receive the messages sent by OSCSendTests +examples/OscDump -- a program that prints received OSC packets +examples/SimpleSend -- a minimal program to send an OSC message +examples/SimpleReceive -- a minimal program to receive an OSC message + +osc/ contains all of the OSC related classes +ip/ contains the networking classes + +ip/windows contains the Windows implementation of the networking classes +ip/posix contains the POSIX implementation of the networking classes + + +Building +-------- + +The idea is that you will embed this source code in your projects as you +see fit. The Makefile has an install rule for building a shared library and +installing headers in usr/local. It can also build a static library. +There is a CMakeLists.txt for building with cmake. + +Makefile builds +............... + +The Makefile works for Linux and Max OS X. It should also work on other platforms +that have make. Just run: + +$ make + +You can run "make install" if you like. + + +Cmake builds +............ + +There is a CMakeLists.txt file which has been tested with cmake on +Windows and Linux. It should work on other platforms too. +For example, to generate a Visual Studio 10 project, run cmake +like this: + +> cmake -G "Visual Studio 10" + +Run cmake without any parameters to get a list of available generators. + + +Mingw build batch file +...................... + +For Windows there is a batch file for doing a simple test build with +MinGW gcc called make.MinGW32.bat. This will build the test executables +and oscdump in ./bin and run the unit tests. + + +Note: + +In some rare instances you may need to edit the Makefile or +osc/OscHostEndianness.h to configure oscpack for the endianness of your +processor (see the comments at the top of the Makefile for details). + + + +Verification test +----------------- + +To run the unit tests: + +$ ./bin/OscUnitTests + +To run the send and receive tests. Open two terminals. In one run: + +$ ./bin/OscReceiveTest + +Then in the other terminal run: + +$./bin/OscSendTests + + +You should see an indication that the messages were received +in the first terminal. + +Note that OscSendTests intentionally sends some unexpected +message parameters to test exception handling in the receiver. +You will see some "error while parsing message" messages printed. + +You can use ./bin/OscDump to print out OSC messages received +from any program, including the test programs. + + +-- + + +If you fix anything or write a set of TCP send/receive classes +please consider sending me a patch. My email address is +rossb@audiomulch.com. Thanks :) + +For more information about Open Sound Control, see: +http://opensoundcontrol.org/ + +Thanks to Till Bovermann for helping with POSIX networking code and +Mac compatibility, and to Martin Kaltenbrunner and the rest of the +reacTable team for giving me a reason to finish this library. Thanks +to Merlijn Blaauw for reviewing the interfaces. Thanks to Xavier Oliver +for additional help with Linux builds and POSIX implementation details. + +Portions developed at the Music Technology Group, Audiovisual Institute, +University Pompeu Fabra, Barcelona, during my stay as a visiting +researcher, November 2004 - September 2005. + +Thanks to Syneme at the University of Calgary for providing financial +support for the 1.1.0 update, December 2012 - March 2013. + +See the file CHANGES for information about recent updates. + +See the file LICENSE for information about distributing and using this code. + +### diff --git a/ext/OSCPack/ip/IpEndpointName.cpp b/ext/OSCPack/ip/IpEndpointName.cpp index 33fdd98..556da3a 100644 --- a/ext/OSCPack/ip/IpEndpointName.cpp +++ b/ext/OSCPack/ip/IpEndpointName.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,9 +23,20 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "IpEndpointName.h" -#include +#include #include "NetworkingUtils.h" @@ -43,9 +50,9 @@ unsigned long IpEndpointName::GetHostByName( const char *s ) void IpEndpointName::AddressAsString( char *s ) const { if( address == ANY_ADDRESS ){ - sprintf( s, "" ); + std::sprintf( s, "" ); }else{ - sprintf( s, "%d.%d.%d.%d", + std::sprintf( s, "%d.%d.%d.%d", (int)((address >> 24) & 0xFF), (int)((address >> 16) & 0xFF), (int)((address >> 8) & 0xFF), @@ -58,9 +65,9 @@ void IpEndpointName::AddressAndPortAsString( char *s ) const { if( port == ANY_PORT ){ if( address == ANY_ADDRESS ){ - sprintf( s, ":" ); + std::sprintf( s, ":" ); }else{ - sprintf( s, "%d.%d.%d.%d:", + std::sprintf( s, "%d.%d.%d.%d:", (int)((address >> 24) & 0xFF), (int)((address >> 16) & 0xFF), (int)((address >> 8) & 0xFF), @@ -68,9 +75,9 @@ void IpEndpointName::AddressAndPortAsString( char *s ) const } }else{ if( address == ANY_ADDRESS ){ - sprintf( s, ":%d", port ); + std::sprintf( s, ":%d", port ); }else{ - sprintf( s, "%d.%d.%d.%d:%d", + std::sprintf( s, "%d.%d.%d.%d:%d", (int)((address >> 24) & 0xFF), (int)((address >> 16) & 0xFF), (int)((address >> 8) & 0xFF), diff --git a/ext/OSCPack/ip/IpEndpointName.h b/ext/OSCPack/ip/IpEndpointName.h index c7b078e..4b3159a 100644 --- a/ext/OSCPack/ip/IpEndpointName.h +++ b/ext/OSCPack/ip/IpEndpointName.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_IPENDPOINTNAME_H -#define INCLUDED_IPENDPOINTNAME_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_IPENDPOINTNAME_H +#define INCLUDED_OSCPACK_IPENDPOINTNAME_H class IpEndpointName{ @@ -54,6 +61,8 @@ public: unsigned long address; int port; + bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; } + enum { ADDRESS_STRING_LENGTH=17 }; void AddressAsString( char *s ) const; @@ -71,4 +80,4 @@ inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs ) return !(lhs == rhs); } -#endif /* INCLUDED_IPENDPOINTNAME_H */ +#endif /* INCLUDED_OSCPACK_IPENDPOINTNAME_H */ diff --git a/ext/OSCPack/ip/NetworkingUtils.h b/ext/OSCPack/ip/NetworkingUtils.h index 0d6901c..516e9d2 100644 --- a/ext/OSCPack/ip/NetworkingUtils.h +++ b/ext/OSCPack/ip/NetworkingUtils.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_NETWORKINGUTILS_H -#define INCLUDED_NETWORKINGUTILS_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_NETWORKINGUTILS_H +#define INCLUDED_OSCPACK_NETWORKINGUTILS_H // in general NetworkInitializer is only used internally, but if you're @@ -46,4 +53,4 @@ public: unsigned long GetHostByName( const char *name ); -#endif /* INCLUDED_NETWORKINGUTILS_H */ +#endif /* INCLUDED_OSCPACK_NETWORKINGUTILS_H */ diff --git a/ext/OSCPack/ip/PacketListener.h b/ext/OSCPack/ip/PacketListener.h index 6647209..2a8cf63 100644 --- a/ext/OSCPack/ip/PacketListener.h +++ b/ext/OSCPack/ip/PacketListener.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_PACKETLISTENER_H -#define INCLUDED_PACKETLISTENER_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_PACKETLISTENER_H +#define INCLUDED_OSCPACK_PACKETLISTENER_H class IpEndpointName; @@ -40,4 +47,4 @@ public: const IpEndpointName& remoteEndpoint ) = 0; }; -#endif /* INCLUDED_PACKETLISTENER_H */ +#endif /* INCLUDED_OSCPACK_PACKETLISTENER_H */ diff --git a/ext/OSCPack/ip/TimerListener.h b/ext/OSCPack/ip/TimerListener.h index 82b1181..61e262b 100644 --- a/ext/OSCPack/ip/TimerListener.h +++ b/ext/OSCPack/ip/TimerListener.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_TIMERLISTENER_H -#define INCLUDED_TIMERLISTENER_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_TIMERLISTENER_H +#define INCLUDED_OSCPACK_TIMERLISTENER_H class TimerListener{ @@ -37,4 +44,4 @@ public: virtual void TimerExpired() = 0; }; -#endif /* INCLUDED_TIMERLISTENER_H */ +#endif /* INCLUDED_OSCPACK_TIMERLISTENER_H */ diff --git a/ext/OSCPack/ip/UdpSocket.h b/ext/OSCPack/ip/UdpSocket.h index 6d9c26d..8bebb27 100644 --- a/ext/OSCPack/ip/UdpSocket.h +++ b/ext/OSCPack/ip/UdpSocket.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,16 +23,24 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_UDPSOCKET_H -#define INCLUDED_UDPSOCKET_H -#ifndef INCLUDED_NETWORKINGUTILITIES_H +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_UDPSOCKET_H +#define INCLUDED_OSCPACK_UDPSOCKET_H + +#include // size_t + #include "NetworkingUtils.h" -#endif /* INCLUDED_NETWORKINGUTILITIES_H */ - -#ifndef INCLUDED_IPENDPOINTNAME_H #include "IpEndpointName.h" -#endif /* INCLUDED_IPENDPOINTNAME_H */ class PacketListener; @@ -80,26 +84,40 @@ class UdpSocket{ public: - // ctor throws std::runtime_error if there's a problem + // Ctor throws std::runtime_error if there's a problem // initializing the socket. UdpSocket(); virtual ~UdpSocket(); - // the socket is created in an unbound, unconnected state + // Enable broadcast addresses (e.g. x.x.x.255) + // Sets SO_BROADCAST socket option. + void SetEnableBroadcast( bool enableBroadcast ); + + // Enable multiple listeners for a single port on same + // network interface* + // Sets SO_REUSEADDR (also SO_REUSEPORT on OS X). + // [*] The exact behavior of SO_REUSEADDR and + // SO_REUSEPORT is undefined for some common cases + // and may have drastically different behavior on different + // operating systems. + void SetAllowReuse( bool allowReuse ); + + + // The socket is created in an unbound, unconnected state // such a socket can only be used to send to an arbitrary // address using SendTo(). To use Send() you need to first // connect to a remote endpoint using Connect(). To use // ReceiveFrom you need to first bind to a local endpoint // using Bind(). - // retrieve the local endpoint name when sending to 'to' - IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const; + // Retrieve the local endpoint name when sending to 'to' + IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const; // Connect to a remote endpoint which is used as the target // for calls to Send() void Connect( const IpEndpointName& remoteEndpoint ); - void Send( const char *data, int size ); - void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ); + void Send( const char *data, std::size_t size ); + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ); // Bind a local endpoint to receive incoming data. Endpoint @@ -107,7 +125,7 @@ public: void Bind( const IpEndpointName& localEndpoint ); bool IsBound() const; - int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ); + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ); }; @@ -155,4 +173,4 @@ public: }; -#endif /* INCLUDED_UDPSOCKET_H */ +#endif /* INCLUDED_OSCPACK_UDPSOCKET_H */ diff --git a/ext/OSCPack/ip/posix/NetworkingUtils.cpp b/ext/OSCPack/ip/posix/NetworkingUtils.cpp index 3b1da79..51daca3 100644 --- a/ext/OSCPack/ip/posix/NetworkingUtils.cpp +++ b/ext/OSCPack/ip/posix/NetworkingUtils.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,13 +23,24 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "ip/NetworkingUtils.h" #include #include #include -#include -#include + +#include @@ -49,7 +56,7 @@ unsigned long GetHostByName( const char *name ) struct hostent *h = gethostbyname( name ); if( h ){ struct in_addr a; - memcpy( &a, h->h_addr_list[0], h->h_length ); + std::memcpy( &a, h->h_addr_list[0], h->h_length ); result = ntohl(a.s_addr); } diff --git a/ext/OSCPack/ip/posix/UdpSocket.cpp b/ext/OSCPack/ip/posix/UdpSocket.cpp index 735169b..4fa6204 100644 --- a/ext/OSCPack/ip/posix/UdpSocket.cpp +++ b/ext/OSCPack/ip/posix/UdpSocket.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,16 +23,18 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "ip/UdpSocket.h" -#include -#include -#include -#include -#include -#include -#include -#include // for memset +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "ip/UdpSocket.h" #include #include @@ -48,19 +46,30 @@ #include #include // for sockaddr_in +#include +#include +#include +#include + +#include +#include +#include // for memset +#include +#include + #include "ip/PacketListener.h" #include "ip/TimerListener.h" #if defined(__APPLE__) && !defined(_SOCKLEN_T) -// pre system 10.3 didn have socklen_t +// pre system 10.3 didn't have socklen_t typedef ssize_t socklen_t; #endif static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) { - memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); + std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = @@ -107,7 +116,7 @@ public: throw std::runtime_error("unable to create udp socket\n"); } - memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); + std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); sendToAddr_.sin_family = AF_INET; } @@ -116,6 +125,24 @@ public: if (socket_ != -1) close(socket_); } + void SetEnableBroadcast( bool enableBroadcast ) + { + int broadcast = (enableBroadcast) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); + } + + void SetAllowReuse( bool allowReuse ) + { + int reuseAddr = (allowReuse) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)); + +#ifdef __APPLE__ + // needed also for OS X - enable multiple listeners for a single port on same network interface + int reusePort = (allowReuse) ? 1 : 0; // int on posix + setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &reusePort, sizeof(reusePort)); +#endif + } + IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const { assert( isBound_ ); @@ -132,7 +159,7 @@ public: // get the address struct sockaddr_in sockAddr; - memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); + std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); socklen_t length = sizeof(sockAddr); if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) { throw std::runtime_error("unable to getsockname\n"); @@ -149,7 +176,7 @@ public: // unconnect from the remote address struct sockaddr_in unconnectSockAddr; - memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) ); + std::memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) ); unconnectSockAddr.sin_family = AF_UNSPEC; // address fields are zero int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)); @@ -172,14 +199,14 @@ public: isConnected_ = true; } - void Send( const char *data, int size ) + void Send( const char *data, std::size_t size ) { assert( isConnected_ ); send( socket_, data, size, 0 ); } - void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ) + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) { sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address ); sendToAddr_.sin_port = htons( remoteEndpoint.port ); @@ -201,14 +228,14 @@ public: bool IsBound() const { return isBound_; } - int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ) + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) { assert( isBound_ ); struct sockaddr_in fromAddr; socklen_t fromAddrLen = sizeof(fromAddr); - int result = recvfrom(socket_, data, size, 0, + ssize_t result = recvfrom(socket_, data, size, 0, (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen); if( result < 0 ) return 0; @@ -216,7 +243,7 @@ public: remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr); remoteEndpoint.port = ntohs(fromAddr.sin_port); - return result; + return (std::size_t)result; } int Socket() { return socket_; } @@ -232,6 +259,16 @@ UdpSocket::~UdpSocket() delete impl_; } +void UdpSocket::SetEnableBroadcast( bool enableBroadcast ) +{ + impl_->SetEnableBroadcast( enableBroadcast ); +} + +void UdpSocket::SetAllowReuse( bool allowReuse ) +{ + impl_->SetAllowReuse( allowReuse ); +} + IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const { return impl_->LocalEndpointFor( remoteEndpoint ); @@ -242,12 +279,12 @@ void UdpSocket::Connect( const IpEndpointName& remoteEndpoint ) impl_->Connect( remoteEndpoint ); } -void UdpSocket::Send( const char *data, int size ) +void UdpSocket::Send( const char *data, std::size_t size ) { impl_->Send( data, size ); } -void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ) +void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) { impl_->SendTo( remoteEndpoint, data, size ); } @@ -262,7 +299,7 @@ bool UdpSocket::IsBound() const return impl_->IsBound(); } -int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ) +std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) { return impl_->ReceiveFrom( remoteEndpoint, data, size ); } @@ -368,104 +405,123 @@ public: void Run() { break_ = false; + char *data = 0; + + try{ + + // configure the master fd_set for select() - // configure the master fd_set for select() + fd_set masterfds, tempfds; + FD_ZERO( &masterfds ); + FD_ZERO( &tempfds ); + + // in addition to listening to the inbound sockets we + // also listen to the asynchronous break pipe, so that AsynchronousBreak() + // can break us out of select() from another thread. + FD_SET( breakPipe_[0], &masterfds ); + int fdmax = breakPipe_[0]; - fd_set masterfds, tempfds; - FD_ZERO( &masterfds ); - FD_ZERO( &tempfds ); - - // in addition to listening to the inbound sockets we - // also listen to the asynchronous break pipe, so that AsynchronousBreak() - // can break us out of select() from another thread. - FD_SET( breakPipe_[0], &masterfds ); - int fdmax = breakPipe_[0]; + for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); + i != socketListeners_.end(); ++i ){ - for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); - i != socketListeners_.end(); ++i ){ - - if( fdmax < i->second->impl_->Socket() ) - fdmax = i->second->impl_->Socket(); - FD_SET( i->second->impl_->Socket(), &masterfds ); - } + if( fdmax < i->second->impl_->Socket() ) + fdmax = i->second->impl_->Socket(); + FD_SET( i->second->impl_->Socket(), &masterfds ); + } - // configure the timer queue - double currentTimeMs = GetCurrentTimeMs(); + // configure the timer queue + double currentTimeMs = GetCurrentTimeMs(); - // expiry time ms, listener - std::vector< std::pair< double, AttachedTimerListener > > timerQueue_; - for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin(); - i != timerListeners_.end(); ++i ) - timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) ); - std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); + // expiry time ms, listener + std::vector< std::pair< double, AttachedTimerListener > > timerQueue_; + for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin(); + i != timerListeners_.end(); ++i ) + timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) ); + std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); - const int MAX_BUFFER_SIZE = 4098; - char *data = new char[ MAX_BUFFER_SIZE ]; - IpEndpointName remoteEndpoint; + const int MAX_BUFFER_SIZE = 4098; + data = new char[ MAX_BUFFER_SIZE ]; + IpEndpointName remoteEndpoint; - struct timeval timeout; + struct timeval timeout; - while( !break_ ){ - tempfds = masterfds; + while( !break_ ){ + tempfds = masterfds; - struct timeval *timeoutPtr = 0; - if( !timerQueue_.empty() ){ - double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs(); - if( timeoutMs < 0 ) - timeoutMs = 0; - - // 1000000 microseconds in a second - timeout.tv_sec = (long)(timeoutMs * .001); - timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000); - timeoutPtr = &timeout; - } + struct timeval *timeoutPtr = 0; + if( !timerQueue_.empty() ){ + double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs(); + if( timeoutMs < 0 ) + timeoutMs = 0; + + long timoutSecondsPart = (long)(timeoutMs * .001); + timeout.tv_sec = (time_t)timoutSecondsPart; + // 1000000 microseconds in a second + timeout.tv_usec = (suseconds_t)((timeoutMs - (timoutSecondsPart * 1000)) * 1000); + timeoutPtr = &timeout; + } - if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){ - throw std::runtime_error("select failed\n"); - } + if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 ){ + if( break_ ){ + break; + }else if( errno == EINTR ){ + // on returning an error, select() doesn't clear tempfds. + // so tempfds would remain all set, which would cause read( breakPipe_[0]... + // below to block indefinitely. therefore if select returns EINTR we restart + // the while() loop instead of continuing on to below. + continue; + }else{ + throw std::runtime_error("select failed\n"); + } + } - if ( FD_ISSET( breakPipe_[0], &tempfds ) ){ - // clear pending data from the asynchronous break pipe - char c; - read( breakPipe_[0], &c, 1 ); - } - - if( break_ ) - break; + if( FD_ISSET( breakPipe_[0], &tempfds ) ){ + // clear pending data from the asynchronous break pipe + char c; + read( breakPipe_[0], &c, 1 ); + } + + if( break_ ) + break; - for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); - i != socketListeners_.end(); ++i ){ + for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); + i != socketListeners_.end(); ++i ){ - if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){ + if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){ - int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); - if( size > 0 ){ - i->first->ProcessPacket( data, size, remoteEndpoint ); - if( break_ ) - break; - } - } - } + std::size_t size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); + if( size > 0 ){ + i->first->ProcessPacket( data, (int)size, remoteEndpoint ); + if( break_ ) + break; + } + } + } - // execute any expired timers - currentTimeMs = GetCurrentTimeMs(); - bool resort = false; - for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin(); - i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){ + // execute any expired timers + currentTimeMs = GetCurrentTimeMs(); + bool resort = false; + for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin(); + i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){ - i->second.listener->TimerExpired(); - if( break_ ) - break; + i->second.listener->TimerExpired(); + if( break_ ) + break; - i->first += i->second.periodMs; - resort = true; - } - if( resort ) - std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); - } + i->first += i->second.periodMs; + resort = true; + } + if( resort ) + std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); + } - delete [] data; + delete [] data; + }catch(...){ + if( data ) + delete [] data; + throw; + } } void Break() diff --git a/ext/OSCPack/ip/win32/NetworkingUtils.cpp b/ext/OSCPack/ip/win32/NetworkingUtils.cpp index 071a758..ded5305 100644 --- a/ext/OSCPack/ip/win32/NetworkingUtils.cpp +++ b/ext/OSCPack/ip/win32/NetworkingUtils.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,12 +23,23 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "ip/NetworkingUtils.h" #include // this must come first to prevent errors with MSVC7 #include -#include -#include + +#include static LONG initCount_ = 0; @@ -80,7 +87,7 @@ unsigned long GetHostByName( const char *name ) struct hostent *h = gethostbyname( name ); if( h ){ struct in_addr a; - memcpy( &a, h->h_addr_list[0], h->h_length ); + std::memcpy( &a, h->h_addr_list[0], h->h_length ); result = ntohl(a.s_addr); } diff --git a/ext/OSCPack/ip/win32/UdpSocket.cpp b/ext/OSCPack/ip/win32/UdpSocket.cpp index 8e64749..f4543fb 100644 --- a/ext/OSCPack/ip/win32/UdpSocket.cpp +++ b/ext/OSCPack/ip/win32/UdpSocket.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,17 +23,35 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "ip/UdpSocket.h" + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include // this must come first to prevent errors with MSVC7 #include #include // for timeGetTime() -#include -#include -#include -#include +#ifndef WINCE #include +#endif + +#include +#include +#include // for memset +#include +#include + +#include "ip/UdpSocket.h" // usually I'd include the module header first + // but this is causing conflicts with BCB4 due to + // std::size_t usage. #include "ip/NetworkingUtils.h" #include "ip/PacketListener.h" @@ -49,7 +63,7 @@ typedef int socklen_t; static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) { - memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); + std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = @@ -98,7 +112,7 @@ public: throw std::runtime_error("unable to create udp socket\n"); } - memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); + std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) ); sendToAddr_.sin_family = AF_INET; } @@ -107,6 +121,22 @@ public: if (socket_ != INVALID_SOCKET) closesocket(socket_); } + void SetEnableBroadcast( bool enableBroadcast ) + { + char broadcast = (char)((enableBroadcast) ? 1 : 0); // char on win32 + setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); + } + + void SetAllowReuse( bool allowReuse ) + { + // Note: SO_REUSEADDR is non-deterministic for listening sockets on Win32. See MSDN article: + // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE" + // http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx + + char reuseAddr = (char)((allowReuse) ? 1 : 0); // char on win32 + setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)); + } + IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const { assert( isBound_ ); @@ -123,7 +153,7 @@ public: // get the address struct sockaddr_in sockAddr; - memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); + std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); socklen_t length = sizeof(sockAddr); if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) { throw std::runtime_error("unable to getsockname\n"); @@ -162,19 +192,19 @@ public: isConnected_ = true; } - void Send( const char *data, int size ) + void Send( const char *data, std::size_t size ) { assert( isConnected_ ); - send( socket_, data, size, 0 ); + send( socket_, data, (int)size, 0 ); } - void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ) + void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) { sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address ); sendToAddr_.sin_port = htons( (short)remoteEndpoint.port ); - sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) ); + sendto( socket_, data, (int)size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) ); } void Bind( const IpEndpointName& localEndpoint ) @@ -191,14 +221,14 @@ public: bool IsBound() const { return isBound_; } - int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ) + std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) { assert( isBound_ ); struct sockaddr_in fromAddr; socklen_t fromAddrLen = sizeof(fromAddr); - int result = recvfrom(socket_, data, size, 0, + int result = recvfrom(socket_, data, (int)size, 0, (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen); if( result < 0 ) return 0; @@ -222,6 +252,16 @@ UdpSocket::~UdpSocket() delete impl_; } +void UdpSocket::SetEnableBroadcast( bool enableBroadcast ) +{ + impl_->SetEnableBroadcast( enableBroadcast ); +} + +void UdpSocket::SetAllowReuse( bool allowReuse ) +{ + impl_->SetAllowReuse( allowReuse ); +} + IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const { return impl_->LocalEndpointFor( remoteEndpoint ); @@ -232,12 +272,12 @@ void UdpSocket::Connect( const IpEndpointName& remoteEndpoint ) impl_->Connect( remoteEndpoint ); } -void UdpSocket::Send( const char *data, int size ) +void UdpSocket::Send( const char *data, std::size_t size ) { impl_->Send( data, size ); } -void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ) +void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size ) { impl_->SendTo( remoteEndpoint, data, size ); } @@ -252,7 +292,7 @@ bool UdpSocket::IsBound() const return impl_->IsBound(); } -int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size ) +std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size ) { return impl_->ReceiveFrom( remoteEndpoint, data, size ); } @@ -282,7 +322,9 @@ extern "C" /*static*/ void InterruptSignalHandler( int ); /*static*/ void InterruptSignalHandler( int ) { multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak(); - signal( SIGINT, SIG_DFL ); +#ifndef WINCE + signal( SIGINT, SIG_DFL ); +#endif } @@ -297,8 +339,12 @@ class SocketReceiveMultiplexer::Implementation{ double GetCurrentTimeMs() const { +#ifndef WINCE return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days - } +#else + return 0; +#endif + } public: Implementation() @@ -405,9 +451,9 @@ public: if( waitResult != WAIT_TIMEOUT ){ for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){ - int size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); + std::size_t size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE ); if( size > 0 ){ - socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint ); + socketListeners_[i].first->ProcessPacket( data, (int)size, remoteEndpoint ); if( break_ ) break; } @@ -503,9 +549,13 @@ void SocketReceiveMultiplexer::RunUntilSigInt() { assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */ multiplexerInstanceToAbortWithSigInt_ = this; - signal( SIGINT, InterruptSignalHandler ); +#ifndef WINCE + signal( SIGINT, InterruptSignalHandler ); +#endif impl_->Run(); +#ifndef WINCE signal( SIGINT, SIG_DFL ); +#endif multiplexerInstanceToAbortWithSigInt_ = 0; } diff --git a/ext/OSCPack/osc/MessageMappingOscPacketListener.h b/ext/OSCPack/osc/MessageMappingOscPacketListener.h index 017bf05..fc7f75a 100644 --- a/ext/OSCPack/osc/MessageMappingOscPacketListener.h +++ b/ext/OSCPack/osc/MessageMappingOscPacketListener.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,10 +23,21 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H -#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H -#include +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H +#define INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H + +#include #include #include "OscPacketListener.h" @@ -61,7 +68,7 @@ protected: private: struct cstr_compare{ bool operator()( const char *lhs, const char *rhs ) const - { return strcmp( lhs, rhs ) < 0; } + { return std::strcmp( lhs, rhs ) < 0; } }; typedef std::map function_map_type; @@ -70,4 +77,4 @@ private: } // namespace osc -#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */ \ No newline at end of file +#endif /* INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H */ \ No newline at end of file diff --git a/ext/OSCPack/osc/OscException.h b/ext/OSCPack/osc/OscException.h index cd8d567..5742762 100644 --- a/ext/OSCPack/osc/OscException.h +++ b/ext/OSCPack/osc/OscException.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSC_EXCEPTION_H -#define INCLUDED_OSC_EXCEPTION_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCEXCEPTION_H +#define INCLUDED_OSCPACK_OSCEXCEPTION_H #include @@ -40,7 +47,8 @@ class Exception : public std::exception { public: Exception() throw() {} Exception( const Exception& src ) throw() - : what_( src.what_ ) {} + : std::exception( src ) + , what_( src.what_ ) {} Exception( const char *w ) throw() : what_( w ) {} Exception& operator=( const Exception& src ) throw() @@ -51,4 +59,4 @@ public: } // namespace osc -#endif /* INCLUDED_OSC_EXCEPTION_H */ +#endif /* INCLUDED_OSCPACK_OSCEXCEPTION_H */ diff --git a/ext/OSCPack/osc/OscOutboundPacketStream.cpp b/ext/OSCPack/osc/OscOutboundPacketStream.cpp index 75b1800..e54cbd3 100644 --- a/ext/OSCPack/osc/OscOutboundPacketStream.cpp +++ b/ext/OSCPack/osc/OscOutboundPacketStream.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,18 +23,37 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "OscOutboundPacketStream.h" -#include -#include -#include - -#if defined(__WIN32__) || defined(WIN32) +#if defined(__WIN32__) || defined(WIN32) || defined(_WIN32) #include // for alloca +#else +//#include // alloca on Linux (also OSX) +#include // alloca on OSX and FreeBSD (and Linux?) #endif +#include +#include // memcpy, memmove, strcpy, strlen +#include // ptrdiff_t + #include "OscHostEndianness.h" +#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug +namespace std { +using ::__strcpy__; // avoid error: E2316 '__strcpy__' is not a member of 'std'. +} +#endif namespace osc{ @@ -130,13 +145,14 @@ static void FromUInt64( char *p, uint64 x ) } -static inline long RoundUp4( long x ) +// round up to the next highest multiple of 4. unless x is already a multiple of 4 +static inline std::size_t RoundUp4( std::size_t x ) { - return ((x-1) & (~0x03L)) + 4; + return (x + 3) & ~((std::size_t)0x03); } -OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity ) +OutboundPacketStream::OutboundPacketStream( char *buffer, std::size_t capacity ) : data_( buffer ) , end_( data_ + capacity ) , typeTagsCurrent_( end_ ) @@ -145,7 +161,12 @@ OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity , elementSizePtr_( 0 ) , messageIsInProgress_( false ) { - + // sanity check integer types declared in OscTypes.h + // you'll need to fix OscTypes.h if any of these asserts fail + assert( sizeof(osc::int32) == 4 ); + assert( sizeof(osc::uint32) == 4 ); + assert( sizeof(osc::int64) == 8 ); + assert( sizeof(osc::uint64) == 8 ); } @@ -189,12 +210,15 @@ void OutboundPacketStream::EndElement( char *endPtr ) // size slot is stored in the elements size slot (or a ptr to data_ // if there is no containing element). We retrieve that here uint32 *previousElementSizePtr = - (uint32*)(data_ + *reinterpret_cast(elementSizePtr_)); + reinterpret_cast(data_ + *elementSizePtr_); - // then we store the element size in the slot, note that the element + // then we store the element size in the slot. note that the element // size does not include the size slot, hence the - 4 below. - uint32 elementSize = - (endPtr - reinterpret_cast(elementSizePtr_)) - 4; + + std::ptrdiff_t d = endPtr - reinterpret_cast(elementSizePtr_); + // assert( d >= 4 && d <= 0x7FFFFFFF ); // assume packets smaller than 2Gb + + uint32 elementSize = static_cast(d - 4); FromUInt32( reinterpret_cast(elementSizePtr_), elementSize ); // finally, we reset the element size ptr to the containing element @@ -211,7 +235,7 @@ bool OutboundPacketStream::ElementSizeSlotRequired() const void OutboundPacketStream::CheckForAvailableBundleSpace() { - unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16; + std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + 16; if( required > Capacity() ) throw OutOfBufferMemoryException(); @@ -221,18 +245,18 @@ void OutboundPacketStream::CheckForAvailableBundleSpace() void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) { // plus 4 for at least four bytes of type tag - unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) - + RoundUp4(strlen(addressPattern) + 1) + 4; + std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + + RoundUp4(std::strlen(addressPattern) + 1) + 4; if( required > Capacity() ) throw OutOfBufferMemoryException(); } -void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength ) +void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength ) { // plus three for extra type tag, comma and null terminator - unsigned long required = (argumentCurrent_ - data_) + argumentLength + std::size_t required = (argumentCurrent_ - data_) + argumentLength + RoundUp4( (end_ - typeTagsCurrent_) + 3 ); if( required > Capacity() ) @@ -250,15 +274,15 @@ void OutboundPacketStream::Clear() } -unsigned int OutboundPacketStream::Capacity() const +std::size_t OutboundPacketStream::Capacity() const { return end_ - data_; } -unsigned int OutboundPacketStream::Size() const +std::size_t OutboundPacketStream::Size() const { - unsigned int result = argumentCurrent_ - data_; + std::size_t result = argumentCurrent_ - data_; if( IsMessageInProgress() ){ // account for the length of the type tag string. the total type tag // includes an initial comma, plus at least one terminating \0 @@ -302,7 +326,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& r messageCursor_ = BeginElement( messageCursor_ ); - memcpy( messageCursor_, "#bundle\0", 8 ); + std::memcpy( messageCursor_, "#bundle\0", 8 ); FromUInt64( messageCursor_ + 8, rhs.timeTag ); messageCursor_ += 16; @@ -336,12 +360,12 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs messageCursor_ = BeginElement( messageCursor_ ); - strcpy( messageCursor_, rhs.addressPattern ); - unsigned long rhsLength = strlen(rhs.addressPattern); + std::strcpy( messageCursor_, rhs.addressPattern ); + std::size_t rhsLength = std::strlen(rhs.addressPattern); messageCursor_ += rhsLength + 1; // zero pad to 4-byte boundary - unsigned long i = rhsLength + 1; + std::size_t i = rhsLength + 1; while( i & 0x3 ){ *messageCursor_++ = '\0'; ++i; @@ -363,27 +387,27 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& if( !IsMessageInProgress() ) throw MessageNotInProgressException(); - int typeTagsCount = end_ - typeTagsCurrent_; + std::size_t typeTagsCount = end_ - typeTagsCurrent_; if( typeTagsCount ){ char *tempTypeTags = (char*)alloca(typeTagsCount); - memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount ); + std::memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount ); // slot size includes comma and null terminator - int typeTagSlotSize = RoundUp4( typeTagsCount + 2 ); + std::size_t typeTagSlotSize = RoundUp4( typeTagsCount + 2 ); - uint32 argumentsSize = argumentCurrent_ - messageCursor_; + std::size_t argumentsSize = argumentCurrent_ - messageCursor_; - memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize ); + std::memmove( messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize ); messageCursor_[0] = ','; // copy type tags in reverse (really forward) order - for( int i=0; i < typeTagsCount; ++i ) + for( std::size_t i=0; i < typeTagsCount; ++i ) messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ]; char *p = messageCursor_ + 1 + typeTagsCount; - for( int i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i ) + for( std::size_t i=0; i < (typeTagSlotSize - (typeTagsCount + 1)); ++i ) *p++ = '\0'; typeTagsCurrent_ = end_; @@ -393,7 +417,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator& }else{ // send an empty type tags string - memcpy( messageCursor_, ",\0\0\0", 4 ); + std::memcpy( messageCursor_, ",\0\0\0", 4 ); // advance messageCursor_ for next message messageCursor_ += 4; @@ -575,15 +599,15 @@ OutboundPacketStream& OutboundPacketStream::operator<<( double rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) { - CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); + CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); *(--typeTagsCurrent_) = STRING_TYPE_TAG; - strcpy( argumentCurrent_, rhs ); - unsigned long rhsLength = strlen(rhs); + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary - unsigned long i = rhsLength + 1; + std::size_t i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; @@ -595,15 +619,15 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) { - CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); + CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) ); *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; - strcpy( argumentCurrent_, rhs ); - unsigned long rhsLength = strlen(rhs); + std::strcpy( argumentCurrent_, rhs ); + std::size_t rhsLength = std::strlen(rhs); argumentCurrent_ += rhsLength + 1; // zero pad to 4-byte boundary - unsigned long i = rhsLength + 1; + std::size_t i = rhsLength + 1; while( i & 0x3 ){ *argumentCurrent_++ = '\0'; ++i; @@ -621,7 +645,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) FromUInt32( argumentCurrent_, rhs.size ); argumentCurrent_ += 4; - memcpy( argumentCurrent_, rhs.data, rhs.size ); + std::memcpy( argumentCurrent_, rhs.data, rhs.size ); argumentCurrent_ += rhs.size; // zero pad to 4-byte boundary @@ -634,6 +658,26 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs ) return *this; } +OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayInitiator& rhs ) +{ + (void) rhs; + CheckForAvailableArgumentSpace(0); + + *(--typeTagsCurrent_) = ARRAY_BEGIN_TYPE_TAG; + + return *this; +} + +OutboundPacketStream& OutboundPacketStream::operator<<( const ArrayTerminator& rhs ) +{ + (void) rhs; + CheckForAvailableArgumentSpace(0); + + *(--typeTagsCurrent_) = ARRAY_END_TYPE_TAG; + + return *this; +} + } // namespace osc diff --git a/ext/OSCPack/osc/OscOutboundPacketStream.h b/ext/OSCPack/osc/OscOutboundPacketStream.h index 317e4b2..26f3e58 100644 --- a/ext/OSCPack/osc/OscOutboundPacketStream.h +++ b/ext/OSCPack/osc/OscOutboundPacketStream.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,21 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSCOUTBOUNDPACKET_H -#define INCLUDED_OSCOUTBOUNDPACKET_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H +#define INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H + +#include // size_t #include "OscTypes.h" #include "OscException.h" @@ -66,15 +75,15 @@ public: class OutboundPacketStream{ public: - OutboundPacketStream( char *buffer, unsigned long capacity ); + OutboundPacketStream( char *buffer, std::size_t capacity ); ~OutboundPacketStream(); void Clear(); - unsigned int Capacity() const; + std::size_t Capacity() const; // invariant: size() is valid even while building a message. - unsigned int Size() const; + std::size_t Size() const; const char *Data() const; @@ -96,7 +105,7 @@ public: OutboundPacketStream& operator<<( const InfinitumType& rhs ); OutboundPacketStream& operator<<( int32 rhs ); -#ifndef x86_64 +#if !(defined(__x86_64__) || defined(_M_X64)) OutboundPacketStream& operator<<( int rhs ) { *this << (int32)rhs; return *this; } #endif @@ -112,6 +121,9 @@ public: OutboundPacketStream& operator<<( const Symbol& rhs ); OutboundPacketStream& operator<<( const Blob& rhs ); + OutboundPacketStream& operator<<( const ArrayInitiator& rhs ); + OutboundPacketStream& operator<<( const ArrayTerminator& rhs ); + private: char *BeginElement( char *beginPtr ); @@ -120,7 +132,7 @@ private: bool ElementSizeSlotRequired() const; void CheckForAvailableBundleSpace(); void CheckForAvailableMessageSpace( const char *addressPattern ); - void CheckForAvailableArgumentSpace( long argumentLength ); + void CheckForAvailableArgumentSpace( std::size_t argumentLength ); char *data_; char *end_; @@ -139,4 +151,4 @@ private: } // namespace osc -#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */ +#endif /* INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H */ diff --git a/ext/OSCPack/osc/OscPacketListener.h b/ext/OSCPack/osc/OscPacketListener.h index bc322b7..c77e924 100644 --- a/ext/OSCPack/osc/OscPacketListener.h +++ b/ext/OSCPack/osc/OscPacketListener.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSCPACKETLISTENER_H -#define INCLUDED_OSCPACKETLISTENER_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCPACKETLISTENER_H +#define INCLUDED_OSCPACK_OSCPACKETLISTENER_H #include "OscReceivedElements.h" #include "../ip/PacketListener.h" @@ -69,4 +76,4 @@ public: } // namespace osc -#endif /* INCLUDED_OSCPACKETLISTENER_H */ +#endif /* INCLUDED_OSCPACK_OSCPACKETLISTENER_H */ diff --git a/ext/OSCPack/osc/OscPrintReceivedElements.cpp b/ext/OSCPack/osc/OscPrintReceivedElements.cpp index 91bfe4f..72e0bc5 100644 --- a/ext/OSCPack/osc/OscPrintReceivedElements.cpp +++ b/ext/OSCPack/osc/OscPrintReceivedElements.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,13 +23,29 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "OscPrintReceivedElements.h" -#include #include -#include #include +#include +#include +#if defined(__BORLANDC__) // workaround for BCB4 release build intrinsics bug +namespace std { +using ::__strcpy__; // avoid error: E2316 '__strcpy__' is not a member of 'std'. +} +#endif namespace osc{ @@ -109,20 +121,17 @@ std::ostream& operator<<( std::ostream & os, case TIME_TAG_TYPE_TAG: { - os << "OSC-timetag:" << arg.AsTimeTagUnchecked(); + os << "OSC-timetag:" << arg.AsTimeTagUnchecked() << " "; std::time_t t = (unsigned long)( arg.AsTimeTagUnchecked() >> 32 ); - // strip trailing newline from string returned by ctime const char *timeString = std::ctime( &t ); - size_t len = strlen( timeString ); - char *s = new char[ len + 1 ]; - strcpy( s, timeString ); - if( len ) - s[ len - 1 ] = '\0'; - - os << " " << s; + size_t len = std::strlen( timeString ); + + // -1 to omit trailing newline from string returned by ctime() + if( len > 1 ) + os.write( timeString, len - 1 ); } break; @@ -140,12 +149,12 @@ std::ostream& operator<<( std::ostream & os, case BLOB_TYPE_TAG: { - unsigned long size; const void *data; + osc_bundle_element_size_t size; arg.AsBlobUnchecked( data, size ); os << "OSC-blob:<<" << std::hex << std::setfill('0'); unsigned char *p = (unsigned char*)data; - for( unsigned long i = 0; i < size; ++i ){ + for( osc_bundle_element_size_t i = 0; i < size; ++i ){ os << "0x" << std::setw(2) << int(p[i]); if( i != size-1 ) os << ' '; @@ -155,6 +164,14 @@ std::ostream& operator<<( std::ostream & os, } break; + case ARRAY_BEGIN_TYPE_TAG: + os << "["; + break; + + case ARRAY_END_TYPE_TAG: + os << "]"; + break; + default: os << "unknown"; } @@ -165,10 +182,13 @@ std::ostream& operator<<( std::ostream & os, std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m ) { - - os << "[" << m.AddressPattern(); + os << "["; + if( m.AddressPatternIsUInt32() ) + os << m.AddressPatternAsUInt32(); + else + os << m.AddressPattern(); + bool first = true; - for( ReceivedMessage::const_iterator i = m.ArgumentsBegin(); i != m.ArgumentsEnd(); ++i ){ if( first ){ diff --git a/ext/OSCPack/osc/OscPrintReceivedElements.h b/ext/OSCPack/osc/OscPrintReceivedElements.h index c42cfa5..7561c01 100644 --- a/ext/OSCPack/osc/OscPrintReceivedElements.h +++ b/ext/OSCPack/osc/OscPrintReceivedElements.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,14 +23,23 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSCPRINTRECEIVEDELEMENTS_H -#define INCLUDED_OSCPRINTRECEIVEDELEMENTS_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H +#define INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H #include -#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H #include "OscReceivedElements.h" -#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ namespace osc{ @@ -46,4 +51,4 @@ std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b ); } // namespace osc -#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */ +#endif /* INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H */ diff --git a/ext/OSCPack/osc/OscReceivedElements.cpp b/ext/OSCPack/osc/OscReceivedElements.cpp index 326fd62..3b38bfc 100644 --- a/ext/OSCPack/osc/OscReceivedElements.cpp +++ b/ext/OSCPack/osc/OscReceivedElements.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,12 +23,22 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "OscReceivedElements.h" -#include +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#include "OscReceivedElements.h" #include "OscHostEndianness.h" +#include // ptrdiff_t namespace osc{ @@ -77,13 +83,10 @@ static inline const char* FindStr4End( const char *p, const char *end ) } -static inline unsigned long RoundUp4( unsigned long x ) +// round up to the next highest multiple of 4. unless x is already a multiple of 4 +static inline uint32 RoundUp4( uint32 x ) { - unsigned long remainder = x & 0x3UL; - if( remainder ) - return x + (4 - remainder); - else - return x; + return (x + 3) & ~((uint32)0x03); } @@ -127,12 +130,12 @@ static inline uint32 ToUInt32( const char *p ) } -int64 ToInt64( const char *p ) +static inline int64 ToInt64( const char *p ) { #ifdef OSC_HOST_LITTLE_ENDIAN union{ osc::int64 i; - char c[4]; + char c[8]; } u; u.c[0] = p[7]; @@ -151,12 +154,12 @@ int64 ToInt64( const char *p ) } -uint64 ToUInt64( const char *p ) +static inline uint64 ToUInt64( const char *p ) { #ifdef OSC_HOST_LITTLE_ENDIAN union{ osc::uint64 i; - char c[4]; + char c[8]; } u; u.c[0] = p[7]; @@ -189,20 +192,20 @@ bool ReceivedBundleElement::IsBundle() const } -int32 ReceivedBundleElement::Size() const +osc_bundle_element_size_t ReceivedBundleElement::Size() const { - return ToUInt32( size_ ); + return ToInt32( sizePtr_ ); } //------------------------------------------------------------------------------ bool ReceivedMessageArgument::AsBool() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == TRUE_TYPE_TAG ) + else if( *typeTagPtr_ == TRUE_TYPE_TAG ) return true; - else if( *typeTag_ == FALSE_TYPE_TAG ) + else if( *typeTagPtr_ == FALSE_TYPE_TAG ) return false; else throw WrongArgumentTypeException(); @@ -211,9 +214,9 @@ bool ReceivedMessageArgument::AsBool() const bool ReceivedMessageArgument::AsBoolUnchecked() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == TRUE_TYPE_TAG ) + else if( *typeTagPtr_ == TRUE_TYPE_TAG ) return true; else return false; @@ -222,9 +225,9 @@ bool ReceivedMessageArgument::AsBoolUnchecked() const int32 ReceivedMessageArgument::AsInt32() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == INT32_TYPE_TAG ) + else if( *typeTagPtr_ == INT32_TYPE_TAG ) return AsInt32Unchecked(); else throw WrongArgumentTypeException(); @@ -239,10 +242,10 @@ int32 ReceivedMessageArgument::AsInt32Unchecked() const char c[4]; } u; - u.c[0] = argument_[3]; - u.c[1] = argument_[2]; - u.c[2] = argument_[1]; - u.c[3] = argument_[0]; + u.c[0] = argumentPtr_[3]; + u.c[1] = argumentPtr_[2]; + u.c[2] = argumentPtr_[1]; + u.c[3] = argumentPtr_[0]; return u.i; #else @@ -253,9 +256,9 @@ int32 ReceivedMessageArgument::AsInt32Unchecked() const float ReceivedMessageArgument::AsFloat() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == FLOAT_TYPE_TAG ) + else if( *typeTagPtr_ == FLOAT_TYPE_TAG ) return AsFloatUnchecked(); else throw WrongArgumentTypeException(); @@ -270,10 +273,10 @@ float ReceivedMessageArgument::AsFloatUnchecked() const char c[4]; } u; - u.c[0] = argument_[3]; - u.c[1] = argument_[2]; - u.c[2] = argument_[1]; - u.c[3] = argument_[0]; + u.c[0] = argumentPtr_[3]; + u.c[1] = argumentPtr_[2]; + u.c[2] = argumentPtr_[1]; + u.c[3] = argumentPtr_[0]; return u.f; #else @@ -284,9 +287,9 @@ float ReceivedMessageArgument::AsFloatUnchecked() const char ReceivedMessageArgument::AsChar() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == CHAR_TYPE_TAG ) + else if( *typeTagPtr_ == CHAR_TYPE_TAG ) return AsCharUnchecked(); else throw WrongArgumentTypeException(); @@ -295,15 +298,15 @@ char ReceivedMessageArgument::AsChar() const char ReceivedMessageArgument::AsCharUnchecked() const { - return (char)ToInt32( argument_ ); + return (char)ToInt32( argumentPtr_ ); } uint32 ReceivedMessageArgument::AsRgbaColor() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == RGBA_COLOR_TYPE_TAG ) + else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG ) return AsRgbaColorUnchecked(); else throw WrongArgumentTypeException(); @@ -312,15 +315,15 @@ uint32 ReceivedMessageArgument::AsRgbaColor() const uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const { - return ToUInt32( argument_ ); + return ToUInt32( argumentPtr_ ); } uint32 ReceivedMessageArgument::AsMidiMessage() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG ) + else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG ) return AsMidiMessageUnchecked(); else throw WrongArgumentTypeException(); @@ -329,15 +332,15 @@ uint32 ReceivedMessageArgument::AsMidiMessage() const uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const { - return ToUInt32( argument_ ); + return ToUInt32( argumentPtr_ ); } int64 ReceivedMessageArgument::AsInt64() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == INT64_TYPE_TAG ) + else if( *typeTagPtr_ == INT64_TYPE_TAG ) return AsInt64Unchecked(); else throw WrongArgumentTypeException(); @@ -346,15 +349,15 @@ int64 ReceivedMessageArgument::AsInt64() const int64 ReceivedMessageArgument::AsInt64Unchecked() const { - return ToInt64( argument_ ); + return ToInt64( argumentPtr_ ); } uint64 ReceivedMessageArgument::AsTimeTag() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == TIME_TAG_TYPE_TAG ) + else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG ) return AsTimeTagUnchecked(); else throw WrongArgumentTypeException(); @@ -363,15 +366,15 @@ uint64 ReceivedMessageArgument::AsTimeTag() const uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const { - return ToUInt64( argument_ ); + return ToUInt64( argumentPtr_ ); } double ReceivedMessageArgument::AsDouble() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == DOUBLE_TYPE_TAG ) + else if( *typeTagPtr_ == DOUBLE_TYPE_TAG ) return AsDoubleUnchecked(); else throw WrongArgumentTypeException(); @@ -386,14 +389,14 @@ double ReceivedMessageArgument::AsDoubleUnchecked() const char c[8]; } u; - u.c[0] = argument_[7]; - u.c[1] = argument_[6]; - u.c[2] = argument_[5]; - u.c[3] = argument_[4]; - u.c[4] = argument_[3]; - u.c[5] = argument_[2]; - u.c[6] = argument_[1]; - u.c[7] = argument_[0]; + u.c[0] = argumentPtr_[7]; + u.c[1] = argumentPtr_[6]; + u.c[2] = argumentPtr_[5]; + u.c[3] = argumentPtr_[4]; + u.c[4] = argumentPtr_[3]; + u.c[5] = argumentPtr_[2]; + u.c[6] = argumentPtr_[1]; + u.c[7] = argumentPtr_[0]; return u.d; #else @@ -404,10 +407,10 @@ double ReceivedMessageArgument::AsDoubleUnchecked() const const char* ReceivedMessageArgument::AsString() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == STRING_TYPE_TAG ) - return argument_; + else if( *typeTagPtr_ == STRING_TYPE_TAG ) + return argumentPtr_; else throw WrongArgumentTypeException(); } @@ -415,50 +418,88 @@ const char* ReceivedMessageArgument::AsString() const const char* ReceivedMessageArgument::AsSymbol() const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == SYMBOL_TYPE_TAG ) - return argument_; + else if( *typeTagPtr_ == SYMBOL_TYPE_TAG ) + return argumentPtr_; else throw WrongArgumentTypeException(); } -void ReceivedMessageArgument::AsBlob( const void*& data, unsigned long& size ) const +void ReceivedMessageArgument::AsBlob( const void*& data, osc_bundle_element_size_t& size ) const { - if( !typeTag_ ) + if( !typeTagPtr_ ) throw MissingArgumentException(); - else if( *typeTag_ == BLOB_TYPE_TAG ) + else if( *typeTagPtr_ == BLOB_TYPE_TAG ) AsBlobUnchecked( data, size ); else throw WrongArgumentTypeException(); } -void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, unsigned long& size ) const +void ReceivedMessageArgument::AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const { - size = ToUInt32( argument_ ); - data = (void*)(argument_+4); + // read blob size as an unsigned int then validate + osc_bundle_element_size_t sizeResult = (osc_bundle_element_size_t)ToUInt32( argumentPtr_ ); + if( !IsValidElementSizeValue(sizeResult) ) + throw MalformedMessageException("invalid blob size"); + + size = sizeResult; + data = (void*)(argumentPtr_+ osc::OSC_SIZEOF_INT32); +} + +std::size_t ReceivedMessageArgument::ComputeArrayItemCount() const +{ + // it is only valid to call ComputeArrayItemCount when the argument is the array start marker + if( !IsArrayBegin() ) + throw WrongArgumentTypeException(); + + std::size_t result = 0; + unsigned int level = 0; + const char *typeTag = typeTagPtr_ + 1; + + // iterate through all type tags. note that ReceivedMessage::Init + // has already checked that the message is well formed. + while( *typeTag ) { + switch( *typeTag++ ) { + case ARRAY_BEGIN_TYPE_TAG: + level += 1; + break; + + case ARRAY_END_TYPE_TAG: + if(level == 0) + return result; + level -= 1; + break; + + default: + if( level == 0 ) // only count items at level 0 + ++result; + } + } + + return result; } //------------------------------------------------------------------------------ void ReceivedMessageArgumentIterator::Advance() { - if( !value_.typeTag_ ) + if( !value_.typeTagPtr_ ) return; - switch( *value_.typeTag_++ ){ + switch( *value_.typeTagPtr_++ ){ case '\0': // don't advance past end - --value_.typeTag_; + --value_.typeTagPtr_; break; case TRUE_TYPE_TAG: case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: - + // zero length break; @@ -468,14 +509,14 @@ void ReceivedMessageArgumentIterator::Advance() case RGBA_COLOR_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG: - value_.argument_ += 4; + value_.argumentPtr_ += 4; break; case INT64_TYPE_TAG: case TIME_TAG_TYPE_TAG: case DOUBLE_TYPE_TAG: - value_.argument_ += 8; + value_.argumentPtr_ += 8; break; case STRING_TYPE_TAG: @@ -485,26 +526,31 @@ void ReceivedMessageArgumentIterator::Advance() // the arguments have already been validated in // ReceivedMessage::Init() below. - value_.argument_ = FindStr4End( value_.argument_ ); + value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ ); break; case BLOB_TYPE_TAG: { - uint32 blobSize = ToUInt32( value_.argument_ ); - value_.argument_ = value_.argument_ + 4 + RoundUp4( blobSize ); + // treat blob size as an unsigned int for the purposes of this calculation + uint32 blobSize = ToUInt32( value_.argumentPtr_ ); + value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); } break; + case ARRAY_BEGIN_TYPE_TAG: + case ARRAY_END_TYPE_TAG: + + // [ Indicates the beginning of an array. The tags following are for + // data in the Array until a close brace tag is reached. + // ] Indicates the end of an array. + + // zero length, don't advance argument ptr + break; + default: // unknown type tag // don't advance - --value_.typeTag_; + --value_.typeTagPtr_; break; - - - // not handled: - // [ Indicates the beginning of an array. The tags following are for - // data in the Array until a close brace tag is reached. - // ] Indicates the end of an array. } } @@ -536,12 +582,15 @@ uint32 ReceivedMessage::AddressPatternAsUInt32() const } -void ReceivedMessage::Init( const char *message, unsigned long size ) +void ReceivedMessage::Init( const char *message, osc_bundle_element_size_t size ) { + if( !IsValidElementSizeValue(size) ) + throw MalformedMessageException( "invalid message size" ); + if( size == 0 ) throw MalformedMessageException( "zero length messages not permitted" ); - if( (size & 0x03L) != 0 ) + if( !IsMultipleOf4(size) ) throw MalformedMessageException( "message size must be multiple of four" ); const char *end = message + size; @@ -580,6 +629,7 @@ void ReceivedMessage::Init( const char *message, unsigned long size ) const char *typeTag = typeTagsBegin_; const char *argument = arguments_; + unsigned int arrayLevel = 0; do{ switch( *typeTag ){ @@ -587,10 +637,22 @@ void ReceivedMessage::Init( const char *message, unsigned long size ) case FALSE_TYPE_TAG: case NIL_TYPE_TAG: case INFINITUM_TYPE_TAG: - // zero length break; + // [ Indicates the beginning of an array. The tags following are for + // data in the Array until a close brace tag is reached. + // ] Indicates the end of an array. + case ARRAY_BEGIN_TYPE_TAG: + ++arrayLevel; + // (zero length argument data) + break; + + case ARRAY_END_TYPE_TAG: + --arrayLevel; + // (zero length argument data) + break; + case INT32_TYPE_TAG: case FLOAT_TYPE_TAG: case CHAR_TYPE_TAG: @@ -627,11 +689,12 @@ void ReceivedMessage::Init( const char *message, unsigned long size ) case BLOB_TYPE_TAG: { - if( argument + 4 > end ) + if( argument + osc::OSC_SIZEOF_INT32 > end ) MalformedMessageException( "arguments exceed message size" ); + // treat blob size as an unsigned int for the purposes of this calculation uint32 blobSize = ToUInt32( argument ); - argument = argument + 4 + RoundUp4( blobSize ); + argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize ); if( argument > end ) MalformedMessageException( "arguments exceed message size" ); } @@ -639,16 +702,22 @@ void ReceivedMessage::Init( const char *message, unsigned long size ) default: throw MalformedMessageException( "unknown type tag" ); - - // not handled: - // [ Indicates the beginning of an array. The tags following are for - // data in the Array until a close brace tag is reached. - // ] Indicates the end of an array. } }while( *++typeTag != '\0' ); typeTagsEnd_ = typeTag; + + if( arrayLevel != 0 ) + throw MalformedMessageException( "array was not terminated before end of message (expected ']' end of array tag)" ); } + + // These invariants should be guaranteed by the above code. + // we depend on them in the implementation of ArgumentCount() +#ifndef NDEBUG + std::ptrdiff_t argumentCount = typeTagsEnd_ - typeTagsBegin_; + assert( argumentCount >= 0 ); + assert( argumentCount <= OSC_INT32_MAX ); +#endif } } @@ -668,12 +737,16 @@ ReceivedBundle::ReceivedBundle( const ReceivedBundleElement& bundleElement ) } -void ReceivedBundle::Init( const char *bundle, unsigned long size ) +void ReceivedBundle::Init( const char *bundle, osc_bundle_element_size_t size ) { + + if( !IsValidElementSizeValue(size) ) + throw MalformedBundleException( "invalid bundle size" ); + if( size < 16 ) throw MalformedBundleException( "packet too short for bundle" ); - if( (size & 0x03L) != 0 ) + if( !IsMultipleOf4(size) ) throw MalformedBundleException( "bundle size must be multiple of four" ); if( bundle[0] != '#' @@ -693,14 +766,15 @@ void ReceivedBundle::Init( const char *bundle, unsigned long size ) const char *p = timeTag_ + 8; while( p < end_ ){ - if( p + 4 > end_ ) + if( p + osc::OSC_SIZEOF_INT32 > end_ ) throw MalformedBundleException( "packet too short for elementSize" ); + // treat element size as an unsigned int for the purposes of this calculation uint32 elementSize = ToUInt32( p ); - if( (elementSize & 0x03L) != 0 ) + if( (elementSize & ((uint32)0x03)) != 0 ) throw MalformedBundleException( "bundle element size must be multiple of four" ); - p += 4 + elementSize; + p += osc::OSC_SIZEOF_INT32 + elementSize; if( p > end_ ) throw MalformedBundleException( "packet too short for bundle element" ); diff --git a/ext/OSCPack/osc/OscReceivedElements.h b/ext/OSCPack/osc/OscReceivedElements.h index f438757..729938e 100644 --- a/ext/OSCPack/osc/OscReceivedElements.h +++ b/ext/OSCPack/osc/OscReceivedElements.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,23 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H -#define INCLUDED_OSCRECEIVEDELEMENTS_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H +#define INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H + +#include +#include +#include // size_t #include "OscTypes.h" #include "OscException.h" @@ -37,6 +48,12 @@ namespace osc{ +class MalformedPacketException : public Exception{ +public: + MalformedPacketException( const char *w="malformed packet" ) + : Exception( w ) {} +}; + class MalformedMessageException : public Exception{ public: MalformedMessageException( const char *w="malformed message" ) @@ -70,37 +87,73 @@ public: class ReceivedPacket{ public: - ReceivedPacket( const char *contents, int32 size ) + // Although the OSC spec is not entirely clear on this, we only support + // packets up to 0x7FFFFFFC bytes long (the maximum 4-byte aligned value + // representable by an int32). An exception will be raised if you pass a + // larger value to the ReceivedPacket() constructor. + + ReceivedPacket( const char *contents, osc_bundle_element_size_t size ) : contents_( contents ) - , size_( size ) {} + , size_( ValidateSize(size) ) {} + + ReceivedPacket( const char *contents, std::size_t size ) + : contents_( contents ) + , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} + +#if !(defined(__x86_64__) || defined(_M_X64)) + ReceivedPacket( const char *contents, int size ) + : contents_( contents ) + , size_( ValidateSize( (osc_bundle_element_size_t)size ) ) {} +#endif bool IsMessage() const { return !IsBundle(); } bool IsBundle() const; - int32 Size() const { return size_; } + osc_bundle_element_size_t Size() const { return size_; } const char *Contents() const { return contents_; } private: const char *contents_; - int32 size_; + osc_bundle_element_size_t size_; + + static osc_bundle_element_size_t ValidateSize( osc_bundle_element_size_t size ) + { + // sanity check integer types declared in OscTypes.h + // you'll need to fix OscTypes.h if any of these asserts fail + assert( sizeof(osc::int32) == 4 ); + assert( sizeof(osc::uint32) == 4 ); + assert( sizeof(osc::int64) == 8 ); + assert( sizeof(osc::uint64) == 8 ); + + if( !IsValidElementSizeValue(size) ) + throw MalformedPacketException( "invalid packet size" ); + + if( size == 0 ) + throw MalformedPacketException( "zero length elements not permitted" ); + + if( !IsMultipleOf4(size) ) + throw MalformedPacketException( "element size must be multiple of four" ); + + return size; + } }; class ReceivedBundleElement{ public: - ReceivedBundleElement( const char *size ) - : size_( size ) {} + ReceivedBundleElement( const char *sizePtr ) + : sizePtr_( sizePtr ) {} friend class ReceivedBundleElementIterator; bool IsMessage() const { return !IsBundle(); } bool IsBundle() const; - int32 Size() const; - const char *Contents() const { return size_ + 4; } + osc_bundle_element_size_t Size() const; + const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; } private: - const char *size_; + const char *sizePtr_; }; @@ -132,11 +185,11 @@ public: private: ReceivedBundleElement value_; - void Advance() { value_.size_ = value_.Contents() + value_.Size(); } + void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); } bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const { - return value_.size_ == rhs.value_.size_; + return value_.sizePtr_ == rhs.value_.sizePtr_; } }; @@ -155,73 +208,79 @@ inline bool operator!=(const ReceivedBundleElementIterator& lhs, class ReceivedMessageArgument{ public: - ReceivedMessageArgument( const char *typeTag, const char *argument ) - : typeTag_( typeTag ) - , argument_( argument ) {} + ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr ) + : typeTagPtr_( typeTagPtr ) + , argumentPtr_( argumentPtr ) {} friend class ReceivedMessageArgumentIterator; - const char TypeTag() const { return *typeTag_; } + char TypeTag() const { return *typeTagPtr_; } // the unchecked methods below don't check whether the argument actually // is of the specified type. they should only be used if you've already // checked the type tag or the associated IsType() method. bool IsBool() const - { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; } + { return *typeTagPtr_ == TRUE_TYPE_TAG || *typeTagPtr_ == FALSE_TYPE_TAG; } bool AsBool() const; bool AsBoolUnchecked() const; - bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; } - bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; } + bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; } + bool IsInfinitum() const { return *typeTagPtr_ == INFINITUM_TYPE_TAG; } - bool IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; } + bool IsInt32() const { return *typeTagPtr_ == INT32_TYPE_TAG; } int32 AsInt32() const; int32 AsInt32Unchecked() const; - bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; } + bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; } float AsFloat() const; float AsFloatUnchecked() const; - bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; } + bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; } char AsChar() const; char AsCharUnchecked() const; - bool IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; } + bool IsRgbaColor() const { return *typeTagPtr_ == RGBA_COLOR_TYPE_TAG; } uint32 AsRgbaColor() const; uint32 AsRgbaColorUnchecked() const; - bool IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; } + bool IsMidiMessage() const { return *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG; } uint32 AsMidiMessage() const; uint32 AsMidiMessageUnchecked() const; - bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; } + bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; } int64 AsInt64() const; int64 AsInt64Unchecked() const; - bool IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; } + bool IsTimeTag() const { return *typeTagPtr_ == TIME_TAG_TYPE_TAG; } uint64 AsTimeTag() const; uint64 AsTimeTagUnchecked() const; - bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; } + bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; } double AsDouble() const; double AsDoubleUnchecked() const; - bool IsString() const { return *typeTag_ == STRING_TYPE_TAG; } + bool IsString() const { return *typeTagPtr_ == STRING_TYPE_TAG; } const char* AsString() const; - const char* AsStringUnchecked() const { return argument_; } + const char* AsStringUnchecked() const { return argumentPtr_; } - bool IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; } + bool IsSymbol() const { return *typeTagPtr_ == SYMBOL_TYPE_TAG; } const char* AsSymbol() const; - const char* AsSymbolUnchecked() const { return argument_; } + const char* AsSymbolUnchecked() const { return argumentPtr_; } - bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; } - void AsBlob( const void*& data, unsigned long& size ) const; - void AsBlobUnchecked( const void*& data, unsigned long& size ) const; + bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; } + void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const; + void AsBlobUnchecked( const void*& data, osc_bundle_element_size_t& size ) const; + bool IsArrayBegin() const { return *typeTagPtr_ == ARRAY_BEGIN_TYPE_TAG; } + bool IsArrayEnd() const { return *typeTagPtr_ == ARRAY_END_TYPE_TAG; } + // Calculate the number of top-level items in the array. Nested arrays count as one item. + // Only valid at array start. Will throw an exception if IsArrayStart() == false. + std::size_t ComputeArrayItemCount() const; + private: - const char *typeTag_; - const char *argument_; + const char *typeTagPtr_; + const char *argumentPtr_; }; @@ -257,7 +316,7 @@ private: bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const { - return value_.typeTag_ == rhs.value_.typeTag_; + return value_.typeTagPtr_ == rhs.value_.typeTagPtr_; } }; @@ -299,6 +358,7 @@ public: // not sure if it would be useful to stream Nil and Infinitum // for now it's not possible + // same goes for array boundaries ReceivedMessageArgumentStream& operator>>( int32& rhs ) { @@ -401,6 +461,8 @@ public: ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs ) { + (void) rhs; // suppress unused parameter warning + if( !Eos() ) throw ExcessArgumentException(); @@ -410,18 +472,18 @@ public: class ReceivedMessage{ - void Init( const char *bundle, unsigned long size ); + void Init( const char *bundle, osc_bundle_element_size_t size ); public: explicit ReceivedMessage( const ReceivedPacket& packet ); explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); const char *AddressPattern() const { return addressPattern_; } - // Support for non-standad SuperCollider integer address patterns: + // Support for non-standard SuperCollider integer address patterns: bool AddressPatternIsUInt32() const; uint32 AddressPatternAsUInt32() const; - unsigned long ArgumentCount() const { return static_cast(typeTagsEnd_ - typeTagsBegin_); } + uint32 ArgumentCount() const { return static_cast(typeTagsEnd_ - typeTagsBegin_); } const char *TypeTags() const { return typeTagsBegin_; } @@ -452,14 +514,14 @@ private: class ReceivedBundle{ - void Init( const char *message, unsigned long size ); + void Init( const char *message, osc_bundle_element_size_t size ); public: explicit ReceivedBundle( const ReceivedPacket& packet ); explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); uint64 TimeTag() const; - unsigned long ElementCount() const { return elementCount_; } + uint32 ElementCount() const { return elementCount_; } typedef ReceivedBundleElementIterator const_iterator; @@ -476,11 +538,11 @@ public: private: const char *timeTag_; const char *end_; - unsigned long elementCount_; + uint32 elementCount_; }; } // namespace osc -#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ +#endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */ diff --git a/ext/OSCPack/osc/OscTypes.cpp b/ext/OSCPack/osc/OscTypes.cpp index 889ab43..51616d5 100644 --- a/ext/OSCPack/osc/OscTypes.cpp +++ b/ext/OSCPack/osc/OscTypes.cpp @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,6 +23,17 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ #include "OscTypes.h" namespace osc{ @@ -34,7 +41,12 @@ namespace osc{ BundleInitiator BeginBundleImmediate(1); BundleTerminator EndBundle; MessageTerminator EndMessage; -NilType Nil; +NilType OscNil; +#ifndef _OBJC_OBJC_H_ +NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead +#endif InfinitumType Infinitum; +ArrayInitiator BeginArray; +ArrayTerminator EndArray; } // namespace osc diff --git a/ext/OSCPack/osc/OscTypes.h b/ext/OSCPack/osc/OscTypes.h index 81549b5..005524f 100644 --- a/ext/OSCPack/osc/OscTypes.h +++ b/ext/OSCPack/osc/OscTypes.h @@ -1,8 +1,8 @@ /* - oscpack -- Open Sound Control packet manipulation library - http://www.audiomulch.com/~rossb/oscpack + oscpack -- Open Sound Control (OSC) packet manipulation library + http://www.rossbencina.com/code/oscpack - Copyright (c) 2004-2005 Ross Bencina + Copyright (c) 2004-2013 Ross Bencina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -15,10 +15,6 @@ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - Any person wishing to distribute modifications to the Software is - requested to send the modifications to the original developer so that - they can be incorporated into the canonical version. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,8 +23,19 @@ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef INCLUDED_OSCTYPES_H -#define INCLUDED_OSCTYPES_H + +/* + The text above constitutes the entire oscpack license; however, + the oscpack developer(s) also make the following non-binding requests: + + Any person wishing to distribute modifications to the Software is + requested to send the modifications to the original developer so that + they can be incorporated into the canonical version. It is also + requested that these non-binding requests be included whenever the + above license is reproduced. +*/ +#ifndef INCLUDED_OSCPACK_OSCTYPES_H +#define INCLUDED_OSCPACK_OSCTYPES_H namespace osc{ @@ -40,6 +47,11 @@ namespace osc{ typedef __int64 int64; typedef unsigned __int64 uint64; +#elif defined(__x86_64__) || defined(_M_X64) + +typedef long int64; +typedef unsigned long uint64; + #else typedef long long int64; @@ -49,7 +61,7 @@ typedef unsigned long long uint64; -#ifdef x86_64 +#if defined(__x86_64__) || defined(_M_X64) typedef signed int int32; typedef unsigned int uint32; @@ -62,6 +74,41 @@ typedef unsigned long uint32; #endif +enum ValueTypeSizes{ + OSC_SIZEOF_INT32 = 4, + OSC_SIZEOF_UINT32 = 4, + OSC_SIZEOF_INT64 = 8, + OSC_SIZEOF_UINT64 = 8, +}; + + +// osc_bundle_element_size_t is used for the size of bundle elements and blobs +// the OSC spec specifies these as int32 (signed) but we ensure that they +// are always positive since negative field sizes make no sense. + +typedef int32 osc_bundle_element_size_t; + +enum { + OSC_INT32_MAX = 0x7FFFFFFF, + + // Element sizes are specified to be int32, and are always rounded up to nearest + // multiple of 4. Therefore their values can't be greater than 0x7FFFFFFC. + OSC_BUNDLE_ELEMENT_SIZE_MAX = 0x7FFFFFFC +}; + + +inline bool IsValidElementSizeValue( osc_bundle_element_size_t x ) +{ + // sizes may not be negative or exceed OSC_BUNDLE_ELEMENT_SIZE_MAX + return x >= 0 && x <= OSC_BUNDLE_ELEMENT_SIZE_MAX; +} + + +inline bool IsMultipleOf4( osc_bundle_element_size_t x ) +{ + return (x & ((osc_bundle_element_size_t)0x03)) == 0; +} + enum TypeTagValues { TRUE_TYPE_TAG = 'T', @@ -78,7 +125,9 @@ enum TypeTagValues { DOUBLE_TYPE_TAG = 'd', STRING_TYPE_TAG = 's', SYMBOL_TYPE_TAG = 'S', - BLOB_TYPE_TAG = 'b' + BLOB_TYPE_TAG = 'b', + ARRAY_BEGIN_TYPE_TAG = '[', + ARRAY_END_TYPE_TAG = ']' }; @@ -120,8 +169,11 @@ extern MessageTerminator EndMessage; struct NilType{ }; -extern NilType Nil; +extern NilType OscNil; +#ifndef _OBJC_OBJC_H_ +extern NilType Nil; // Objective-C defines Nil. so our Nil is deprecated. use OscNil instead +#endif struct InfinitumType{ }; @@ -166,13 +218,23 @@ struct Symbol{ struct Blob{ Blob() {} - explicit Blob( const void* data_, unsigned long size_ ) + explicit Blob( const void* data_, osc_bundle_element_size_t size_ ) : data( data_ ), size( size_ ) {} const void* data; - unsigned long size; + osc_bundle_element_size_t size; }; +struct ArrayInitiator{ +}; + +extern ArrayInitiator BeginArray; + +struct ArrayTerminator{ +}; + +extern ArrayTerminator EndArray; + } // namespace osc -#endif /* INCLUDED_OSCTYPES_H */ +#endif /* INCLUDED_OSCPACK_OSCTYPES_H */