Update to OSCPack v1.1

This commit is contained in:
brunoherbelin
2020-10-20 18:27:26 +02:00
parent 65aefc9fb8
commit bbeb99056a
23 changed files with 1217 additions and 729 deletions

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,9 +23,20 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "IpEndpointName.h"
#include <stdio.h> #include <cstdio>
#include "NetworkingUtils.h" #include "NetworkingUtils.h"
@@ -43,9 +50,9 @@ unsigned long IpEndpointName::GetHostByName( const char *s )
void IpEndpointName::AddressAsString( char *s ) const void IpEndpointName::AddressAsString( char *s ) const
{ {
if( address == ANY_ADDRESS ){ if( address == ANY_ADDRESS ){
sprintf( s, "<any>" ); std::sprintf( s, "<any>" );
}else{ }else{
sprintf( s, "%d.%d.%d.%d", std::sprintf( s, "%d.%d.%d.%d",
(int)((address >> 24) & 0xFF), (int)((address >> 24) & 0xFF),
(int)((address >> 16) & 0xFF), (int)((address >> 16) & 0xFF),
(int)((address >> 8) & 0xFF), (int)((address >> 8) & 0xFF),
@@ -58,9 +65,9 @@ void IpEndpointName::AddressAndPortAsString( char *s ) const
{ {
if( port == ANY_PORT ){ if( port == ANY_PORT ){
if( address == ANY_ADDRESS ){ if( address == ANY_ADDRESS ){
sprintf( s, "<any>:<any>" ); std::sprintf( s, "<any>:<any>" );
}else{ }else{
sprintf( s, "%d.%d.%d.%d:<any>", std::sprintf( s, "%d.%d.%d.%d:<any>",
(int)((address >> 24) & 0xFF), (int)((address >> 24) & 0xFF),
(int)((address >> 16) & 0xFF), (int)((address >> 16) & 0xFF),
(int)((address >> 8) & 0xFF), (int)((address >> 8) & 0xFF),
@@ -68,9 +75,9 @@ void IpEndpointName::AddressAndPortAsString( char *s ) const
} }
}else{ }else{
if( address == ANY_ADDRESS ){ if( address == ANY_ADDRESS ){
sprintf( s, "<any>:%d", port ); std::sprintf( s, "<any>:%d", port );
}else{ }else{
sprintf( s, "%d.%d.%d.%d:%d", std::sprintf( s, "%d.%d.%d.%d:%d",
(int)((address >> 24) & 0xFF), (int)((address >> 24) & 0xFF),
(int)((address >> 16) & 0xFF), (int)((address >> 16) & 0xFF),
(int)((address >> 8) & 0xFF), (int)((address >> 8) & 0xFF),

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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{ class IpEndpointName{
@@ -54,6 +61,8 @@ public:
unsigned long address; unsigned long address;
int port; int port;
bool IsMulticastAddress() const { return ((address >> 24) & 0xFF) >= 224 && ((address >> 24) & 0xFF) <= 239; }
enum { ADDRESS_STRING_LENGTH=17 }; enum { ADDRESS_STRING_LENGTH=17 };
void AddressAsString( char *s ) const; void AddressAsString( char *s ) const;
@@ -71,4 +80,4 @@ inline bool operator!=( const IpEndpointName& lhs, const IpEndpointName& rhs )
return !(lhs == rhs); return !(lhs == rhs);
} }
#endif /* INCLUDED_IPENDPOINTNAME_H */ #endif /* INCLUDED_OSCPACK_IPENDPOINTNAME_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 // in general NetworkInitializer is only used internally, but if you're
@@ -46,4 +53,4 @@ public:
unsigned long GetHostByName( const char *name ); unsigned long GetHostByName( const char *name );
#endif /* INCLUDED_NETWORKINGUTILS_H */ #endif /* INCLUDED_OSCPACK_NETWORKINGUTILS_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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; class IpEndpointName;
@@ -40,4 +47,4 @@ public:
const IpEndpointName& remoteEndpoint ) = 0; const IpEndpointName& remoteEndpoint ) = 0;
}; };
#endif /* INCLUDED_PACKETLISTENER_H */ #endif /* INCLUDED_OSCPACK_PACKETLISTENER_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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{ class TimerListener{
@@ -37,4 +44,4 @@ public:
virtual void TimerExpired() = 0; virtual void TimerExpired() = 0;
}; };
#endif /* INCLUDED_TIMERLISTENER_H */ #endif /* INCLUDED_OSCPACK_TIMERLISTENER_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,16 +23,24 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <cstring> // size_t
#include "NetworkingUtils.h" #include "NetworkingUtils.h"
#endif /* INCLUDED_NETWORKINGUTILITIES_H */
#ifndef INCLUDED_IPENDPOINTNAME_H
#include "IpEndpointName.h" #include "IpEndpointName.h"
#endif /* INCLUDED_IPENDPOINTNAME_H */
class PacketListener; class PacketListener;
@@ -80,26 +84,40 @@ class UdpSocket{
public: public:
// ctor throws std::runtime_error if there's a problem // Ctor throws std::runtime_error if there's a problem
// initializing the socket. // initializing the socket.
UdpSocket(); UdpSocket();
virtual ~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 // such a socket can only be used to send to an arbitrary
// address using SendTo(). To use Send() you need to first // address using SendTo(). To use Send() you need to first
// connect to a remote endpoint using Connect(). To use // connect to a remote endpoint using Connect(). To use
// ReceiveFrom you need to first bind to a local endpoint // ReceiveFrom you need to first bind to a local endpoint
// using Bind(). // using Bind().
// retrieve the local endpoint name when sending to 'to' // Retrieve the local endpoint name when sending to 'to'
IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const; IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const;
// Connect to a remote endpoint which is used as the target // Connect to a remote endpoint which is used as the target
// for calls to Send() // for calls to Send()
void Connect( const IpEndpointName& remoteEndpoint ); void Connect( const IpEndpointName& remoteEndpoint );
void Send( const char *data, int size ); void Send( const char *data, std::size_t size );
void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size ); void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size );
// Bind a local endpoint to receive incoming data. Endpoint // Bind a local endpoint to receive incoming data. Endpoint
@@ -107,7 +125,7 @@ public:
void Bind( const IpEndpointName& localEndpoint ); void Bind( const IpEndpointName& localEndpoint );
bool IsBound() const; 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 */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,13 +23,24 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "ip/NetworkingUtils.h"
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <string.h>
#include <stdio.h> #include <cstring>
@@ -49,7 +56,7 @@ unsigned long GetHostByName( const char *name )
struct hostent *h = gethostbyname( name ); struct hostent *h = gethostbyname( name );
if( h ){ if( h ){
struct in_addr a; 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); result = ntohl(a.s_addr);
} }

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,16 +23,18 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "ip/UdpSocket.h"
#include <vector> /*
#include <algorithm> The text above constitutes the entire oscpack license; however,
#include <stdexcept> the oscpack developer(s) also make the following non-binding requests:
#include <assert.h>
#include <signal.h> Any person wishing to distribute modifications to the Software is
#include <math.h> requested to send the modifications to the original developer so that
#include <errno.h> they can be incorporated into the canonical version. It is also
#include <string.h> // for memset requested that these non-binding requests be included whenever the
above license is reproduced.
*/
#include "ip/UdpSocket.h"
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
@@ -48,19 +46,30 @@
#include <sys/time.h> #include <sys/time.h>
#include <netinet/in.h> // for sockaddr_in #include <netinet/in.h> // for sockaddr_in
#include <signal.h>
#include <math.h>
#include <errno.h>
#include <string.h>
#include <algorithm>
#include <cassert>
#include <cstring> // for memset
#include <stdexcept>
#include <vector>
#include "ip/PacketListener.h" #include "ip/PacketListener.h"
#include "ip/TimerListener.h" #include "ip/TimerListener.h"
#if defined(__APPLE__) && !defined(_SOCKLEN_T) #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; typedef ssize_t socklen_t;
#endif #endif
static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) 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_family = AF_INET;
sockAddr.sin_addr.s_addr = sockAddr.sin_addr.s_addr =
@@ -107,7 +116,7 @@ public:
throw std::runtime_error("unable to create udp socket\n"); 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; sendToAddr_.sin_family = AF_INET;
} }
@@ -116,6 +125,24 @@ public:
if (socket_ != -1) close(socket_); 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 IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{ {
assert( isBound_ ); assert( isBound_ );
@@ -132,7 +159,7 @@ public:
// get the address // get the address
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
socklen_t length = sizeof(sockAddr); socklen_t length = sizeof(sockAddr);
if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) { if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
throw std::runtime_error("unable to getsockname\n"); throw std::runtime_error("unable to getsockname\n");
@@ -149,7 +176,7 @@ public:
// unconnect from the remote address // unconnect from the remote address
struct sockaddr_in unconnectSockAddr; struct sockaddr_in unconnectSockAddr;
memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) ); std::memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
unconnectSockAddr.sin_family = AF_UNSPEC; unconnectSockAddr.sin_family = AF_UNSPEC;
// address fields are zero // address fields are zero
int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)); int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
@@ -172,14 +199,14 @@ public:
isConnected_ = true; isConnected_ = true;
} }
void Send( const char *data, int size ) void Send( const char *data, std::size_t size )
{ {
assert( isConnected_ ); assert( isConnected_ );
send( socket_, data, size, 0 ); 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_addr.s_addr = htonl( remoteEndpoint.address );
sendToAddr_.sin_port = htons( remoteEndpoint.port ); sendToAddr_.sin_port = htons( remoteEndpoint.port );
@@ -201,14 +228,14 @@ public:
bool IsBound() const { return isBound_; } 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_ ); assert( isBound_ );
struct sockaddr_in fromAddr; struct sockaddr_in fromAddr;
socklen_t fromAddrLen = sizeof(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); (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
if( result < 0 ) if( result < 0 )
return 0; return 0;
@@ -216,7 +243,7 @@ public:
remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr); remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
remoteEndpoint.port = ntohs(fromAddr.sin_port); remoteEndpoint.port = ntohs(fromAddr.sin_port);
return result; return (std::size_t)result;
} }
int Socket() { return socket_; } int Socket() { return socket_; }
@@ -232,6 +259,16 @@ UdpSocket::~UdpSocket()
delete impl_; 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 IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{ {
return impl_->LocalEndpointFor( remoteEndpoint ); return impl_->LocalEndpointFor( remoteEndpoint );
@@ -242,12 +279,12 @@ void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
impl_->Connect( 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 ); 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 ); impl_->SendTo( remoteEndpoint, data, size );
} }
@@ -262,7 +299,7 @@ bool UdpSocket::IsBound() const
return impl_->IsBound(); 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 ); return impl_->ReceiveFrom( remoteEndpoint, data, size );
} }
@@ -368,104 +405,123 @@ public:
void Run() void Run()
{ {
break_ = false; break_ = false;
char *data = 0;
// configure the master fd_set for select() try{
fd_set masterfds, tempfds; // configure the master fd_set for select()
FD_ZERO( &masterfds );
FD_ZERO( &tempfds );
// in addition to listening to the inbound sockets we fd_set masterfds, tempfds;
// also listen to the asynchronous break pipe, so that AsynchronousBreak() FD_ZERO( &masterfds );
// can break us out of select() from another thread. FD_ZERO( &tempfds );
FD_SET( breakPipe_[0], &masterfds );
int fdmax = breakPipe_[0];
for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); // in addition to listening to the inbound sockets we
i != socketListeners_.end(); ++i ){ // 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];
if( fdmax < i->second->impl_->Socket() ) for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
fdmax = i->second->impl_->Socket(); i != socketListeners_.end(); ++i ){
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 // configure the timer queue
double currentTimeMs = GetCurrentTimeMs(); double currentTimeMs = GetCurrentTimeMs();
// expiry time ms, listener // expiry time ms, listener
std::vector< std::pair< double, AttachedTimerListener > > timerQueue_; std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin(); for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
i != timerListeners_.end(); ++i ) i != timerListeners_.end(); ++i )
timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) ); timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
const int MAX_BUFFER_SIZE = 4098; const int MAX_BUFFER_SIZE = 4098;
char *data = new char[ MAX_BUFFER_SIZE ]; data = new char[ MAX_BUFFER_SIZE ];
IpEndpointName remoteEndpoint; IpEndpointName remoteEndpoint;
struct timeval timeout; struct timeval timeout;
while( !break_ ){ while( !break_ ){
tempfds = masterfds; tempfds = masterfds;
struct timeval *timeoutPtr = 0; struct timeval *timeoutPtr = 0;
if( !timerQueue_.empty() ){ if( !timerQueue_.empty() ){
double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs(); double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
if( timeoutMs < 0 ) if( timeoutMs < 0 )
timeoutMs = 0; timeoutMs = 0;
// 1000000 microseconds in a second long timoutSecondsPart = (long)(timeoutMs * .001);
timeout.tv_sec = (long)(timeoutMs * .001); timeout.tv_sec = (time_t)timoutSecondsPart;
timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000); // 1000000 microseconds in a second
timeoutPtr = &timeout; timeout.tv_usec = (suseconds_t)((timeoutMs - (timoutSecondsPart * 1000)) * 1000);
} timeoutPtr = &timeout;
}
if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){ if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 ){
throw std::runtime_error("select failed\n"); 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 ) ){ if( FD_ISSET( breakPipe_[0], &tempfds ) ){
// clear pending data from the asynchronous break pipe // clear pending data from the asynchronous break pipe
char c; char c;
read( breakPipe_[0], &c, 1 ); read( breakPipe_[0], &c, 1 );
} }
if( break_ ) if( break_ )
break; break;
for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin(); for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
i != socketListeners_.end(); ++i ){ 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 ); std::size_t size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
if( size > 0 ){ if( size > 0 ){
i->first->ProcessPacket( data, size, remoteEndpoint ); i->first->ProcessPacket( data, (int)size, remoteEndpoint );
if( break_ ) if( break_ )
break; break;
} }
} }
} }
// execute any expired timers // execute any expired timers
currentTimeMs = GetCurrentTimeMs(); currentTimeMs = GetCurrentTimeMs();
bool resort = false; bool resort = false;
for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin(); for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){ i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
i->second.listener->TimerExpired(); i->second.listener->TimerExpired();
if( break_ ) if( break_ )
break; break;
i->first += i->second.periodMs; i->first += i->second.periodMs;
resort = true; resort = true;
} }
if( resort ) if( resort )
std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls ); std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
} }
delete [] data; delete [] data;
}catch(...){
if( data )
delete [] data;
throw;
}
} }
void Break() void Break()

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,12 +23,23 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "ip/NetworkingUtils.h"
#include <winsock2.h> // this must come first to prevent errors with MSVC7 #include <winsock2.h> // this must come first to prevent errors with MSVC7
#include <windows.h> #include <windows.h>
#include <stdlib.h>
#include <stdio.h> #include <cstring>
static LONG initCount_ = 0; static LONG initCount_ = 0;
@@ -80,7 +87,7 @@ unsigned long GetHostByName( const char *name )
struct hostent *h = gethostbyname( name ); struct hostent *h = gethostbyname( name );
if( h ){ if( h ){
struct in_addr a; 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); result = ntohl(a.s_addr);
} }

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,17 +23,35 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <winsock2.h> // this must come first to prevent errors with MSVC7 #include <winsock2.h> // this must come first to prevent errors with MSVC7
#include <windows.h> #include <windows.h>
#include <mmsystem.h> // for timeGetTime() #include <mmsystem.h> // for timeGetTime()
#include <vector> #ifndef WINCE
#include <algorithm>
#include <stdexcept>
#include <assert.h>
#include <signal.h> #include <signal.h>
#endif
#include <algorithm>
#include <cassert>
#include <cstring> // for memset
#include <stdexcept>
#include <vector>
#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/NetworkingUtils.h"
#include "ip/PacketListener.h" #include "ip/PacketListener.h"
@@ -49,7 +63,7 @@ typedef int socklen_t;
static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint ) 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_family = AF_INET;
sockAddr.sin_addr.s_addr = sockAddr.sin_addr.s_addr =
@@ -98,7 +112,7 @@ public:
throw std::runtime_error("unable to create udp socket\n"); 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; sendToAddr_.sin_family = AF_INET;
} }
@@ -107,6 +121,22 @@ public:
if (socket_ != INVALID_SOCKET) closesocket(socket_); 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 IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{ {
assert( isBound_ ); assert( isBound_ );
@@ -123,7 +153,7 @@ public:
// get the address // get the address
struct sockaddr_in sockAddr; struct sockaddr_in sockAddr;
memset( (char *)&sockAddr, 0, sizeof(sockAddr ) ); std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
socklen_t length = sizeof(sockAddr); socklen_t length = sizeof(sockAddr);
if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) { if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
throw std::runtime_error("unable to getsockname\n"); throw std::runtime_error("unable to getsockname\n");
@@ -162,19 +192,19 @@ public:
isConnected_ = true; isConnected_ = true;
} }
void Send( const char *data, int size ) void Send( const char *data, std::size_t size )
{ {
assert( isConnected_ ); 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_addr.s_addr = htonl( remoteEndpoint.address );
sendToAddr_.sin_port = htons( (short)remoteEndpoint.port ); 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 ) void Bind( const IpEndpointName& localEndpoint )
@@ -191,14 +221,14 @@ public:
bool IsBound() const { return isBound_; } 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_ ); assert( isBound_ );
struct sockaddr_in fromAddr; struct sockaddr_in fromAddr;
socklen_t fromAddrLen = sizeof(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); (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
if( result < 0 ) if( result < 0 )
return 0; return 0;
@@ -222,6 +252,16 @@ UdpSocket::~UdpSocket()
delete impl_; 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 IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
{ {
return impl_->LocalEndpointFor( remoteEndpoint ); return impl_->LocalEndpointFor( remoteEndpoint );
@@ -232,12 +272,12 @@ void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
impl_->Connect( 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 ); 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 ); impl_->SendTo( remoteEndpoint, data, size );
} }
@@ -252,7 +292,7 @@ bool UdpSocket::IsBound() const
return impl_->IsBound(); 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 ); return impl_->ReceiveFrom( remoteEndpoint, data, size );
} }
@@ -282,7 +322,9 @@ extern "C" /*static*/ void InterruptSignalHandler( int );
/*static*/ void InterruptSignalHandler( int ) /*static*/ void InterruptSignalHandler( int )
{ {
multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak(); multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
signal( SIGINT, SIG_DFL ); #ifndef WINCE
signal( SIGINT, SIG_DFL );
#endif
} }
@@ -297,8 +339,12 @@ class SocketReceiveMultiplexer::Implementation{
double GetCurrentTimeMs() const double GetCurrentTimeMs() const
{ {
#ifndef WINCE
return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
} #else
return 0;
#endif
}
public: public:
Implementation() Implementation()
@@ -405,9 +451,9 @@ public:
if( waitResult != WAIT_TIMEOUT ){ if( waitResult != WAIT_TIMEOUT ){
for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){ 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 ){ if( size > 0 ){
socketListeners_[i].first->ProcessPacket( data, size, remoteEndpoint ); socketListeners_[i].first->ProcessPacket( data, (int)size, remoteEndpoint );
if( break_ ) if( break_ )
break; break;
} }
@@ -503,9 +549,13 @@ void SocketReceiveMultiplexer::RunUntilSigInt()
{ {
assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */ assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
multiplexerInstanceToAbortWithSigInt_ = this; multiplexerInstanceToAbortWithSigInt_ = this;
signal( SIGINT, InterruptSignalHandler ); #ifndef WINCE
signal( SIGINT, InterruptSignalHandler );
#endif
impl_->Run(); impl_->Run();
#ifndef WINCE
signal( SIGINT, SIG_DFL ); signal( SIGINT, SIG_DFL );
#endif
multiplexerInstanceToAbortWithSigInt_ = 0; multiplexerInstanceToAbortWithSigInt_ = 0;
} }

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,10 +23,21 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H
#include <string.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_MESSAGEMAPPINGOSCPACKETLISTENER_H
#define INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H
#include <cstring>
#include <map> #include <map>
#include "OscPacketListener.h" #include "OscPacketListener.h"
@@ -61,7 +68,7 @@ protected:
private: private:
struct cstr_compare{ struct cstr_compare{
bool operator()( const char *lhs, const char *rhs ) const bool operator()( const char *lhs, const char *rhs ) const
{ return strcmp( lhs, rhs ) < 0; } { return std::strcmp( lhs, rhs ) < 0; }
}; };
typedef std::map<const char*, function_type, cstr_compare> function_map_type; typedef std::map<const char*, function_type, cstr_compare> function_map_type;
@@ -70,4 +77,4 @@ private:
} // namespace osc } // namespace osc
#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */ #endif /* INCLUDED_OSCPACK_MESSAGEMAPPINGOSCPACKETLISTENER_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <exception> #include <exception>
@@ -40,7 +47,8 @@ class Exception : public std::exception {
public: public:
Exception() throw() {} Exception() throw() {}
Exception( const Exception& src ) throw() Exception( const Exception& src ) throw()
: what_( src.what_ ) {} : std::exception( src )
, what_( src.what_ ) {}
Exception( const char *w ) throw() Exception( const char *w ) throw()
: what_( w ) {} : what_( w ) {}
Exception& operator=( const Exception& src ) throw() Exception& operator=( const Exception& src ) throw()
@@ -51,4 +59,4 @@ public:
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSC_EXCEPTION_H */ #endif /* INCLUDED_OSCPACK_OSCEXCEPTION_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,18 +23,37 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "OscOutboundPacketStream.h"
#include <string.h> #if defined(__WIN32__) || defined(WIN32) || defined(_WIN32)
#include <stdlib.h>
#include <assert.h>
#if defined(__WIN32__) || defined(WIN32)
#include <malloc.h> // for alloca #include <malloc.h> // for alloca
#else
//#include <alloca.h> // alloca on Linux (also OSX)
#include <stdlib.h> // alloca on OSX and FreeBSD (and Linux?)
#endif #endif
#include <cassert>
#include <cstring> // memcpy, memmove, strcpy, strlen
#include <cstddef> // ptrdiff_t
#include "OscHostEndianness.h" #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{ 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 ) : data_( buffer )
, end_( data_ + capacity ) , end_( data_ + capacity )
, typeTagsCurrent_( end_ ) , typeTagsCurrent_( end_ )
@@ -145,7 +161,12 @@ OutboundPacketStream::OutboundPacketStream( char *buffer, unsigned long capacity
, elementSizePtr_( 0 ) , elementSizePtr_( 0 )
, messageIsInProgress_( false ) , 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_ // size slot is stored in the elements size slot (or a ptr to data_
// if there is no containing element). We retrieve that here // if there is no containing element). We retrieve that here
uint32 *previousElementSizePtr = uint32 *previousElementSizePtr =
(uint32*)(data_ + *reinterpret_cast<uint32*>(elementSizePtr_)); reinterpret_cast<uint32*>(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. // size does not include the size slot, hence the - 4 below.
uint32 elementSize =
(endPtr - reinterpret_cast<char*>(elementSizePtr_)) - 4; std::ptrdiff_t d = endPtr - reinterpret_cast<char*>(elementSizePtr_);
// assert( d >= 4 && d <= 0x7FFFFFFF ); // assume packets smaller than 2Gb
uint32 elementSize = static_cast<uint32>(d - 4);
FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize ); FromUInt32( reinterpret_cast<char*>(elementSizePtr_), elementSize );
// finally, we reset the element size ptr to the containing element // finally, we reset the element size ptr to the containing element
@@ -211,7 +235,7 @@ bool OutboundPacketStream::ElementSizeSlotRequired() const
void OutboundPacketStream::CheckForAvailableBundleSpace() void OutboundPacketStream::CheckForAvailableBundleSpace()
{ {
unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) + 16; std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0) + 16;
if( required > Capacity() ) if( required > Capacity() )
throw OutOfBufferMemoryException(); throw OutOfBufferMemoryException();
@@ -221,18 +245,18 @@ void OutboundPacketStream::CheckForAvailableBundleSpace()
void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern ) void OutboundPacketStream::CheckForAvailableMessageSpace( const char *addressPattern )
{ {
// plus 4 for at least four bytes of type tag // plus 4 for at least four bytes of type tag
unsigned long required = Size() + ((ElementSizeSlotRequired())?4:0) std::size_t required = Size() + ((ElementSizeSlotRequired())?4:0)
+ RoundUp4(strlen(addressPattern) + 1) + 4; + RoundUp4(std::strlen(addressPattern) + 1) + 4;
if( required > Capacity() ) if( required > Capacity() )
throw OutOfBufferMemoryException(); throw OutOfBufferMemoryException();
} }
void OutboundPacketStream::CheckForAvailableArgumentSpace( long argumentLength ) void OutboundPacketStream::CheckForAvailableArgumentSpace( std::size_t argumentLength )
{ {
// plus three for extra type tag, comma and null terminator // 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 ); + RoundUp4( (end_ - typeTagsCurrent_) + 3 );
if( required > Capacity() ) if( required > Capacity() )
@@ -250,15 +274,15 @@ void OutboundPacketStream::Clear()
} }
unsigned int OutboundPacketStream::Capacity() const std::size_t OutboundPacketStream::Capacity() const
{ {
return end_ - data_; 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() ){ if( IsMessageInProgress() ){
// account for the length of the type tag string. the total type tag // account for the length of the type tag string. the total type tag
// includes an initial comma, plus at least one terminating \0 // includes an initial comma, plus at least one terminating \0
@@ -302,7 +326,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BundleInitiator& r
messageCursor_ = BeginElement( messageCursor_ ); messageCursor_ = BeginElement( messageCursor_ );
memcpy( messageCursor_, "#bundle\0", 8 ); std::memcpy( messageCursor_, "#bundle\0", 8 );
FromUInt64( messageCursor_ + 8, rhs.timeTag ); FromUInt64( messageCursor_ + 8, rhs.timeTag );
messageCursor_ += 16; messageCursor_ += 16;
@@ -336,12 +360,12 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const BeginMessage& rhs
messageCursor_ = BeginElement( messageCursor_ ); messageCursor_ = BeginElement( messageCursor_ );
strcpy( messageCursor_, rhs.addressPattern ); std::strcpy( messageCursor_, rhs.addressPattern );
unsigned long rhsLength = strlen(rhs.addressPattern); std::size_t rhsLength = std::strlen(rhs.addressPattern);
messageCursor_ += rhsLength + 1; messageCursor_ += rhsLength + 1;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
unsigned long i = rhsLength + 1; std::size_t i = rhsLength + 1;
while( i & 0x3 ){ while( i & 0x3 ){
*messageCursor_++ = '\0'; *messageCursor_++ = '\0';
++i; ++i;
@@ -363,27 +387,27 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
if( !IsMessageInProgress() ) if( !IsMessageInProgress() )
throw MessageNotInProgressException(); throw MessageNotInProgressException();
int typeTagsCount = end_ - typeTagsCurrent_; std::size_t typeTagsCount = end_ - typeTagsCurrent_;
if( typeTagsCount ){ if( typeTagsCount ){
char *tempTypeTags = (char*)alloca(typeTagsCount); char *tempTypeTags = (char*)alloca(typeTagsCount);
memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount ); std::memcpy( tempTypeTags, typeTagsCurrent_, typeTagsCount );
// slot size includes comma and null terminator // 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] = ','; messageCursor_[0] = ',';
// copy type tags in reverse (really forward) order // 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 ]; messageCursor_[i+1] = tempTypeTags[ (typeTagsCount-1) - i ];
char *p = messageCursor_ + 1 + typeTagsCount; 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'; *p++ = '\0';
typeTagsCurrent_ = end_; typeTagsCurrent_ = end_;
@@ -393,7 +417,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const MessageTerminator&
}else{ }else{
// send an empty type tags string // send an empty type tags string
memcpy( messageCursor_, ",\0\0\0", 4 ); std::memcpy( messageCursor_, ",\0\0\0", 4 );
// advance messageCursor_ for next message // advance messageCursor_ for next message
messageCursor_ += 4; messageCursor_ += 4;
@@ -575,15 +599,15 @@ OutboundPacketStream& OutboundPacketStream::operator<<( double rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
{ {
CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
*(--typeTagsCurrent_) = STRING_TYPE_TAG; *(--typeTagsCurrent_) = STRING_TYPE_TAG;
strcpy( argumentCurrent_, rhs ); std::strcpy( argumentCurrent_, rhs );
unsigned long rhsLength = strlen(rhs); std::size_t rhsLength = std::strlen(rhs);
argumentCurrent_ += rhsLength + 1; argumentCurrent_ += rhsLength + 1;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
unsigned long i = rhsLength + 1; std::size_t i = rhsLength + 1;
while( i & 0x3 ){ while( i & 0x3 ){
*argumentCurrent_++ = '\0'; *argumentCurrent_++ = '\0';
++i; ++i;
@@ -595,15 +619,15 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const char *rhs )
OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs ) OutboundPacketStream& OutboundPacketStream::operator<<( const Symbol& rhs )
{ {
CheckForAvailableArgumentSpace( RoundUp4(strlen(rhs) + 1) ); CheckForAvailableArgumentSpace( RoundUp4(std::strlen(rhs) + 1) );
*(--typeTagsCurrent_) = SYMBOL_TYPE_TAG; *(--typeTagsCurrent_) = SYMBOL_TYPE_TAG;
strcpy( argumentCurrent_, rhs ); std::strcpy( argumentCurrent_, rhs );
unsigned long rhsLength = strlen(rhs); std::size_t rhsLength = std::strlen(rhs);
argumentCurrent_ += rhsLength + 1; argumentCurrent_ += rhsLength + 1;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
unsigned long i = rhsLength + 1; std::size_t i = rhsLength + 1;
while( i & 0x3 ){ while( i & 0x3 ){
*argumentCurrent_++ = '\0'; *argumentCurrent_++ = '\0';
++i; ++i;
@@ -621,7 +645,7 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
FromUInt32( argumentCurrent_, rhs.size ); FromUInt32( argumentCurrent_, rhs.size );
argumentCurrent_ += 4; argumentCurrent_ += 4;
memcpy( argumentCurrent_, rhs.data, rhs.size ); std::memcpy( argumentCurrent_, rhs.data, rhs.size );
argumentCurrent_ += rhs.size; argumentCurrent_ += rhs.size;
// zero pad to 4-byte boundary // zero pad to 4-byte boundary
@@ -634,6 +658,26 @@ OutboundPacketStream& OutboundPacketStream::operator<<( const Blob& rhs )
return *this; 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 } // namespace osc

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,21 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <cstring> // size_t
#include "OscTypes.h" #include "OscTypes.h"
#include "OscException.h" #include "OscException.h"
@@ -66,15 +75,15 @@ public:
class OutboundPacketStream{ class OutboundPacketStream{
public: public:
OutboundPacketStream( char *buffer, unsigned long capacity ); OutboundPacketStream( char *buffer, std::size_t capacity );
~OutboundPacketStream(); ~OutboundPacketStream();
void Clear(); void Clear();
unsigned int Capacity() const; std::size_t Capacity() const;
// invariant: size() is valid even while building a message. // invariant: size() is valid even while building a message.
unsigned int Size() const; std::size_t Size() const;
const char *Data() const; const char *Data() const;
@@ -96,7 +105,7 @@ public:
OutboundPacketStream& operator<<( const InfinitumType& rhs ); OutboundPacketStream& operator<<( const InfinitumType& rhs );
OutboundPacketStream& operator<<( int32 rhs ); OutboundPacketStream& operator<<( int32 rhs );
#ifndef x86_64 #if !(defined(__x86_64__) || defined(_M_X64))
OutboundPacketStream& operator<<( int rhs ) OutboundPacketStream& operator<<( int rhs )
{ *this << (int32)rhs; return *this; } { *this << (int32)rhs; return *this; }
#endif #endif
@@ -112,6 +121,9 @@ public:
OutboundPacketStream& operator<<( const Symbol& rhs ); OutboundPacketStream& operator<<( const Symbol& rhs );
OutboundPacketStream& operator<<( const Blob& rhs ); OutboundPacketStream& operator<<( const Blob& rhs );
OutboundPacketStream& operator<<( const ArrayInitiator& rhs );
OutboundPacketStream& operator<<( const ArrayTerminator& rhs );
private: private:
char *BeginElement( char *beginPtr ); char *BeginElement( char *beginPtr );
@@ -120,7 +132,7 @@ private:
bool ElementSizeSlotRequired() const; bool ElementSizeSlotRequired() const;
void CheckForAvailableBundleSpace(); void CheckForAvailableBundleSpace();
void CheckForAvailableMessageSpace( const char *addressPattern ); void CheckForAvailableMessageSpace( const char *addressPattern );
void CheckForAvailableArgumentSpace( long argumentLength ); void CheckForAvailableArgumentSpace( std::size_t argumentLength );
char *data_; char *data_;
char *end_; char *end_;
@@ -139,4 +151,4 @@ private:
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */ #endif /* INCLUDED_OSCPACK_OSCOUTBOUNDPACKETSTREAM_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "OscReceivedElements.h"
#include "../ip/PacketListener.h" #include "../ip/PacketListener.h"
@@ -69,4 +76,4 @@ public:
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSCPACKETLISTENER_H */ #endif /* INCLUDED_OSCPACK_OSCPACKETLISTENER_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,13 +23,29 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 "OscPrintReceivedElements.h"
#include <iostream>
#include <cstring> #include <cstring>
#include <iomanip>
#include <ctime> #include <ctime>
#include <iostream>
#include <iomanip>
#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{ namespace osc{
@@ -109,20 +121,17 @@ std::ostream& operator<<( std::ostream & os,
case TIME_TAG_TYPE_TAG: case TIME_TAG_TYPE_TAG:
{ {
os << "OSC-timetag:" << arg.AsTimeTagUnchecked(); os << "OSC-timetag:" << arg.AsTimeTagUnchecked() << " ";
std::time_t t = std::time_t t =
(unsigned long)( arg.AsTimeTagUnchecked() >> 32 ); (unsigned long)( arg.AsTimeTagUnchecked() >> 32 );
// strip trailing newline from string returned by ctime
const char *timeString = std::ctime( &t ); const char *timeString = std::ctime( &t );
size_t len = strlen( timeString ); size_t len = std::strlen( timeString );
char *s = new char[ len + 1 ];
strcpy( s, timeString );
if( len )
s[ len - 1 ] = '\0';
os << " " << s; // -1 to omit trailing newline from string returned by ctime()
if( len > 1 )
os.write( timeString, len - 1 );
} }
break; break;
@@ -140,12 +149,12 @@ std::ostream& operator<<( std::ostream & os,
case BLOB_TYPE_TAG: case BLOB_TYPE_TAG:
{ {
unsigned long size;
const void *data; const void *data;
osc_bundle_element_size_t size;
arg.AsBlobUnchecked( data, size ); arg.AsBlobUnchecked( data, size );
os << "OSC-blob:<<" << std::hex << std::setfill('0'); os << "OSC-blob:<<" << std::hex << std::setfill('0');
unsigned char *p = (unsigned char*)data; 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]); os << "0x" << std::setw(2) << int(p[i]);
if( i != size-1 ) if( i != size-1 )
os << ' '; os << ' ';
@@ -155,6 +164,14 @@ std::ostream& operator<<( std::ostream & os,
} }
break; break;
case ARRAY_BEGIN_TYPE_TAG:
os << "[";
break;
case ARRAY_END_TYPE_TAG:
os << "]";
break;
default: default:
os << "unknown"; os << "unknown";
} }
@@ -165,10 +182,13 @@ std::ostream& operator<<( std::ostream & os,
std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m ) std::ostream& operator<<( std::ostream & os, const ReceivedMessage& m )
{ {
os << "[";
if( m.AddressPatternIsUInt32() )
os << m.AddressPatternAsUInt32();
else
os << m.AddressPattern();
os << "[" << m.AddressPattern();
bool first = true; bool first = true;
for( ReceivedMessage::const_iterator i = m.ArgumentsBegin(); for( ReceivedMessage::const_iterator i = m.ArgumentsBegin();
i != m.ArgumentsEnd(); ++i ){ i != m.ArgumentsEnd(); ++i ){
if( first ){ if( first ){

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,14 +23,23 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <iosfwd> #include <iosfwd>
#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H
#include "OscReceivedElements.h" #include "OscReceivedElements.h"
#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */
namespace osc{ namespace osc{
@@ -46,4 +51,4 @@ std::ostream& operator<<( std::ostream & os, const ReceivedBundle& b );
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */ #endif /* INCLUDED_OSCPACK_OSCPRINTRECEIVEDELEMENTS_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,12 +23,22 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "OscReceivedElements.h"
#include <cassert> /*
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 "OscHostEndianness.h"
#include <cstddef> // ptrdiff_t
namespace osc{ 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; return (x + 3) & ~((uint32)0x03);
if( remainder )
return x + (4 - remainder);
else
return x;
} }
@@ -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 #ifdef OSC_HOST_LITTLE_ENDIAN
union{ union{
osc::int64 i; osc::int64 i;
char c[4]; char c[8];
} u; } u;
u.c[0] = p[7]; 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 #ifdef OSC_HOST_LITTLE_ENDIAN
union{ union{
osc::uint64 i; osc::uint64 i;
char c[4]; char c[8];
} u; } u;
u.c[0] = p[7]; 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 bool ReceivedMessageArgument::AsBool() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == TRUE_TYPE_TAG ) else if( *typeTagPtr_ == TRUE_TYPE_TAG )
return true; return true;
else if( *typeTag_ == FALSE_TYPE_TAG ) else if( *typeTagPtr_ == FALSE_TYPE_TAG )
return false; return false;
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -211,9 +214,9 @@ bool ReceivedMessageArgument::AsBool() const
bool ReceivedMessageArgument::AsBoolUnchecked() const bool ReceivedMessageArgument::AsBoolUnchecked() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == TRUE_TYPE_TAG ) else if( *typeTagPtr_ == TRUE_TYPE_TAG )
return true; return true;
else else
return false; return false;
@@ -222,9 +225,9 @@ bool ReceivedMessageArgument::AsBoolUnchecked() const
int32 ReceivedMessageArgument::AsInt32() const int32 ReceivedMessageArgument::AsInt32() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == INT32_TYPE_TAG ) else if( *typeTagPtr_ == INT32_TYPE_TAG )
return AsInt32Unchecked(); return AsInt32Unchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -239,10 +242,10 @@ int32 ReceivedMessageArgument::AsInt32Unchecked() const
char c[4]; char c[4];
} u; } u;
u.c[0] = argument_[3]; u.c[0] = argumentPtr_[3];
u.c[1] = argument_[2]; u.c[1] = argumentPtr_[2];
u.c[2] = argument_[1]; u.c[2] = argumentPtr_[1];
u.c[3] = argument_[0]; u.c[3] = argumentPtr_[0];
return u.i; return u.i;
#else #else
@@ -253,9 +256,9 @@ int32 ReceivedMessageArgument::AsInt32Unchecked() const
float ReceivedMessageArgument::AsFloat() const float ReceivedMessageArgument::AsFloat() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == FLOAT_TYPE_TAG ) else if( *typeTagPtr_ == FLOAT_TYPE_TAG )
return AsFloatUnchecked(); return AsFloatUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -270,10 +273,10 @@ float ReceivedMessageArgument::AsFloatUnchecked() const
char c[4]; char c[4];
} u; } u;
u.c[0] = argument_[3]; u.c[0] = argumentPtr_[3];
u.c[1] = argument_[2]; u.c[1] = argumentPtr_[2];
u.c[2] = argument_[1]; u.c[2] = argumentPtr_[1];
u.c[3] = argument_[0]; u.c[3] = argumentPtr_[0];
return u.f; return u.f;
#else #else
@@ -284,9 +287,9 @@ float ReceivedMessageArgument::AsFloatUnchecked() const
char ReceivedMessageArgument::AsChar() const char ReceivedMessageArgument::AsChar() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == CHAR_TYPE_TAG ) else if( *typeTagPtr_ == CHAR_TYPE_TAG )
return AsCharUnchecked(); return AsCharUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -295,15 +298,15 @@ char ReceivedMessageArgument::AsChar() const
char ReceivedMessageArgument::AsCharUnchecked() const char ReceivedMessageArgument::AsCharUnchecked() const
{ {
return (char)ToInt32( argument_ ); return (char)ToInt32( argumentPtr_ );
} }
uint32 ReceivedMessageArgument::AsRgbaColor() const uint32 ReceivedMessageArgument::AsRgbaColor() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == RGBA_COLOR_TYPE_TAG ) else if( *typeTagPtr_ == RGBA_COLOR_TYPE_TAG )
return AsRgbaColorUnchecked(); return AsRgbaColorUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -312,15 +315,15 @@ uint32 ReceivedMessageArgument::AsRgbaColor() const
uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const uint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const
{ {
return ToUInt32( argument_ ); return ToUInt32( argumentPtr_ );
} }
uint32 ReceivedMessageArgument::AsMidiMessage() const uint32 ReceivedMessageArgument::AsMidiMessage() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == MIDI_MESSAGE_TYPE_TAG ) else if( *typeTagPtr_ == MIDI_MESSAGE_TYPE_TAG )
return AsMidiMessageUnchecked(); return AsMidiMessageUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -329,15 +332,15 @@ uint32 ReceivedMessageArgument::AsMidiMessage() const
uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const uint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const
{ {
return ToUInt32( argument_ ); return ToUInt32( argumentPtr_ );
} }
int64 ReceivedMessageArgument::AsInt64() const int64 ReceivedMessageArgument::AsInt64() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == INT64_TYPE_TAG ) else if( *typeTagPtr_ == INT64_TYPE_TAG )
return AsInt64Unchecked(); return AsInt64Unchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -346,15 +349,15 @@ int64 ReceivedMessageArgument::AsInt64() const
int64 ReceivedMessageArgument::AsInt64Unchecked() const int64 ReceivedMessageArgument::AsInt64Unchecked() const
{ {
return ToInt64( argument_ ); return ToInt64( argumentPtr_ );
} }
uint64 ReceivedMessageArgument::AsTimeTag() const uint64 ReceivedMessageArgument::AsTimeTag() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == TIME_TAG_TYPE_TAG ) else if( *typeTagPtr_ == TIME_TAG_TYPE_TAG )
return AsTimeTagUnchecked(); return AsTimeTagUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -363,15 +366,15 @@ uint64 ReceivedMessageArgument::AsTimeTag() const
uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const uint64 ReceivedMessageArgument::AsTimeTagUnchecked() const
{ {
return ToUInt64( argument_ ); return ToUInt64( argumentPtr_ );
} }
double ReceivedMessageArgument::AsDouble() const double ReceivedMessageArgument::AsDouble() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == DOUBLE_TYPE_TAG ) else if( *typeTagPtr_ == DOUBLE_TYPE_TAG )
return AsDoubleUnchecked(); return AsDoubleUnchecked();
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
@@ -386,14 +389,14 @@ double ReceivedMessageArgument::AsDoubleUnchecked() const
char c[8]; char c[8];
} u; } u;
u.c[0] = argument_[7]; u.c[0] = argumentPtr_[7];
u.c[1] = argument_[6]; u.c[1] = argumentPtr_[6];
u.c[2] = argument_[5]; u.c[2] = argumentPtr_[5];
u.c[3] = argument_[4]; u.c[3] = argumentPtr_[4];
u.c[4] = argument_[3]; u.c[4] = argumentPtr_[3];
u.c[5] = argument_[2]; u.c[5] = argumentPtr_[2];
u.c[6] = argument_[1]; u.c[6] = argumentPtr_[1];
u.c[7] = argument_[0]; u.c[7] = argumentPtr_[0];
return u.d; return u.d;
#else #else
@@ -404,10 +407,10 @@ double ReceivedMessageArgument::AsDoubleUnchecked() const
const char* ReceivedMessageArgument::AsString() const const char* ReceivedMessageArgument::AsString() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == STRING_TYPE_TAG ) else if( *typeTagPtr_ == STRING_TYPE_TAG )
return argument_; return argumentPtr_;
else else
throw WrongArgumentTypeException(); throw WrongArgumentTypeException();
} }
@@ -415,43 +418,81 @@ const char* ReceivedMessageArgument::AsString() const
const char* ReceivedMessageArgument::AsSymbol() const const char* ReceivedMessageArgument::AsSymbol() const
{ {
if( !typeTag_ ) if( !typeTagPtr_ )
throw MissingArgumentException(); throw MissingArgumentException();
else if( *typeTag_ == SYMBOL_TYPE_TAG ) else if( *typeTagPtr_ == SYMBOL_TYPE_TAG )
return argument_; return argumentPtr_;
else else
throw WrongArgumentTypeException(); 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(); throw MissingArgumentException();
else if( *typeTag_ == BLOB_TYPE_TAG ) else if( *typeTagPtr_ == BLOB_TYPE_TAG )
AsBlobUnchecked( data, size ); AsBlobUnchecked( data, size );
else else
throw WrongArgumentTypeException(); 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_ ); // read blob size as an unsigned int then validate
data = (void*)(argument_+4); 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() void ReceivedMessageArgumentIterator::Advance()
{ {
if( !value_.typeTag_ ) if( !value_.typeTagPtr_ )
return; return;
switch( *value_.typeTag_++ ){ switch( *value_.typeTagPtr_++ ){
case '\0': case '\0':
// don't advance past end // don't advance past end
--value_.typeTag_; --value_.typeTagPtr_;
break; break;
case TRUE_TYPE_TAG: case TRUE_TYPE_TAG:
@@ -468,14 +509,14 @@ void ReceivedMessageArgumentIterator::Advance()
case RGBA_COLOR_TYPE_TAG: case RGBA_COLOR_TYPE_TAG:
case MIDI_MESSAGE_TYPE_TAG: case MIDI_MESSAGE_TYPE_TAG:
value_.argument_ += 4; value_.argumentPtr_ += 4;
break; break;
case INT64_TYPE_TAG: case INT64_TYPE_TAG:
case TIME_TAG_TYPE_TAG: case TIME_TAG_TYPE_TAG:
case DOUBLE_TYPE_TAG: case DOUBLE_TYPE_TAG:
value_.argument_ += 8; value_.argumentPtr_ += 8;
break; break;
case STRING_TYPE_TAG: case STRING_TYPE_TAG:
@@ -485,26 +526,31 @@ void ReceivedMessageArgumentIterator::Advance()
// the arguments have already been validated in // the arguments have already been validated in
// ReceivedMessage::Init() below. // ReceivedMessage::Init() below.
value_.argument_ = FindStr4End( value_.argument_ ); value_.argumentPtr_ = FindStr4End( value_.argumentPtr_ );
break; break;
case BLOB_TYPE_TAG: case BLOB_TYPE_TAG:
{ {
uint32 blobSize = ToUInt32( value_.argument_ ); // treat blob size as an unsigned int for the purposes of this calculation
value_.argument_ = value_.argument_ + 4 + RoundUp4( blobSize ); uint32 blobSize = ToUInt32( value_.argumentPtr_ );
value_.argumentPtr_ = value_.argumentPtr_ + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
} }
break; 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 default: // unknown type tag
// don't advance // don't advance
--value_.typeTag_; --value_.typeTagPtr_;
break; 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 ) if( size == 0 )
throw MalformedMessageException( "zero length messages not permitted" ); throw MalformedMessageException( "zero length messages not permitted" );
if( (size & 0x03L) != 0 ) if( !IsMultipleOf4(size) )
throw MalformedMessageException( "message size must be multiple of four" ); throw MalformedMessageException( "message size must be multiple of four" );
const char *end = message + size; const char *end = message + size;
@@ -580,6 +629,7 @@ void ReceivedMessage::Init( const char *message, unsigned long size )
const char *typeTag = typeTagsBegin_; const char *typeTag = typeTagsBegin_;
const char *argument = arguments_; const char *argument = arguments_;
unsigned int arrayLevel = 0;
do{ do{
switch( *typeTag ){ switch( *typeTag ){
@@ -587,10 +637,22 @@ void ReceivedMessage::Init( const char *message, unsigned long size )
case FALSE_TYPE_TAG: case FALSE_TYPE_TAG:
case NIL_TYPE_TAG: case NIL_TYPE_TAG:
case INFINITUM_TYPE_TAG: case INFINITUM_TYPE_TAG:
// zero length // zero length
break; 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 INT32_TYPE_TAG:
case FLOAT_TYPE_TAG: case FLOAT_TYPE_TAG:
case CHAR_TYPE_TAG: case CHAR_TYPE_TAG:
@@ -627,11 +689,12 @@ void ReceivedMessage::Init( const char *message, unsigned long size )
case BLOB_TYPE_TAG: case BLOB_TYPE_TAG:
{ {
if( argument + 4 > end ) if( argument + osc::OSC_SIZEOF_INT32 > end )
MalformedMessageException( "arguments exceed message size" ); MalformedMessageException( "arguments exceed message size" );
// treat blob size as an unsigned int for the purposes of this calculation
uint32 blobSize = ToUInt32( argument ); uint32 blobSize = ToUInt32( argument );
argument = argument + 4 + RoundUp4( blobSize ); argument = argument + osc::OSC_SIZEOF_INT32 + RoundUp4( blobSize );
if( argument > end ) if( argument > end )
MalformedMessageException( "arguments exceed message size" ); MalformedMessageException( "arguments exceed message size" );
} }
@@ -639,16 +702,22 @@ void ReceivedMessage::Init( const char *message, unsigned long size )
default: default:
throw MalformedMessageException( "unknown type tag" ); 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' ); }while( *++typeTag != '\0' );
typeTagsEnd_ = typeTag; 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 ) if( size < 16 )
throw MalformedBundleException( "packet too short for bundle" ); throw MalformedBundleException( "packet too short for bundle" );
if( (size & 0x03L) != 0 ) if( !IsMultipleOf4(size) )
throw MalformedBundleException( "bundle size must be multiple of four" ); throw MalformedBundleException( "bundle size must be multiple of four" );
if( bundle[0] != '#' if( bundle[0] != '#'
@@ -693,14 +766,15 @@ void ReceivedBundle::Init( const char *bundle, unsigned long size )
const char *p = timeTag_ + 8; const char *p = timeTag_ + 8;
while( p < end_ ){ while( p < end_ ){
if( p + 4 > end_ ) if( p + osc::OSC_SIZEOF_INT32 > end_ )
throw MalformedBundleException( "packet too short for elementSize" ); throw MalformedBundleException( "packet too short for elementSize" );
// treat element size as an unsigned int for the purposes of this calculation
uint32 elementSize = ToUInt32( p ); uint32 elementSize = ToUInt32( p );
if( (elementSize & 0x03L) != 0 ) if( (elementSize & ((uint32)0x03)) != 0 )
throw MalformedBundleException( "bundle element size must be multiple of four" ); throw MalformedBundleException( "bundle element size must be multiple of four" );
p += 4 + elementSize; p += osc::OSC_SIZEOF_INT32 + elementSize;
if( p > end_ ) if( p > end_ )
throw MalformedBundleException( "packet too short for bundle element" ); throw MalformedBundleException( "packet too short for bundle element" );

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,23 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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 <cassert>
#include <cstddef>
#include <cstring> // size_t
#include "OscTypes.h" #include "OscTypes.h"
#include "OscException.h" #include "OscException.h"
@@ -37,6 +48,12 @@
namespace osc{ namespace osc{
class MalformedPacketException : public Exception{
public:
MalformedPacketException( const char *w="malformed packet" )
: Exception( w ) {}
};
class MalformedMessageException : public Exception{ class MalformedMessageException : public Exception{
public: public:
MalformedMessageException( const char *w="malformed message" ) MalformedMessageException( const char *w="malformed message" )
@@ -70,37 +87,73 @@ public:
class ReceivedPacket{ class ReceivedPacket{
public: 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 ) : 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 IsMessage() const { return !IsBundle(); }
bool IsBundle() const; bool IsBundle() const;
int32 Size() const { return size_; } osc_bundle_element_size_t Size() const { return size_; }
const char *Contents() const { return contents_; } const char *Contents() const { return contents_; }
private: private:
const char *contents_; 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{ class ReceivedBundleElement{
public: public:
ReceivedBundleElement( const char *size ) ReceivedBundleElement( const char *sizePtr )
: size_( size ) {} : sizePtr_( sizePtr ) {}
friend class ReceivedBundleElementIterator; friend class ReceivedBundleElementIterator;
bool IsMessage() const { return !IsBundle(); } bool IsMessage() const { return !IsBundle(); }
bool IsBundle() const; bool IsBundle() const;
int32 Size() const; osc_bundle_element_size_t Size() const;
const char *Contents() const { return size_ + 4; } const char *Contents() const { return sizePtr_ + osc::OSC_SIZEOF_INT32; }
private: private:
const char *size_; const char *sizePtr_;
}; };
@@ -132,11 +185,11 @@ public:
private: private:
ReceivedBundleElement value_; ReceivedBundleElement value_;
void Advance() { value_.size_ = value_.Contents() + value_.Size(); } void Advance() { value_.sizePtr_ = value_.Contents() + value_.Size(); }
bool IsEqualTo( const ReceivedBundleElementIterator& rhs ) const 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{ class ReceivedMessageArgument{
public: public:
ReceivedMessageArgument( const char *typeTag, const char *argument ) ReceivedMessageArgument( const char *typeTagPtr, const char *argumentPtr )
: typeTag_( typeTag ) : typeTagPtr_( typeTagPtr )
, argument_( argument ) {} , argumentPtr_( argumentPtr ) {}
friend class ReceivedMessageArgumentIterator; 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 // 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 // is of the specified type. they should only be used if you've already
// checked the type tag or the associated IsType() method. // checked the type tag or the associated IsType() method.
bool IsBool() const 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 AsBool() const;
bool AsBoolUnchecked() const; bool AsBoolUnchecked() const;
bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; } bool IsNil() const { return *typeTagPtr_ == NIL_TYPE_TAG; }
bool IsInfinitum() const { return *typeTag_ == INFINITUM_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 AsInt32() const;
int32 AsInt32Unchecked() const; int32 AsInt32Unchecked() const;
bool IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; } bool IsFloat() const { return *typeTagPtr_ == FLOAT_TYPE_TAG; }
float AsFloat() const; float AsFloat() const;
float AsFloatUnchecked() const; float AsFloatUnchecked() const;
bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; } bool IsChar() const { return *typeTagPtr_ == CHAR_TYPE_TAG; }
char AsChar() const; char AsChar() const;
char AsCharUnchecked() 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 AsRgbaColor() const;
uint32 AsRgbaColorUnchecked() 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 AsMidiMessage() const;
uint32 AsMidiMessageUnchecked() const; uint32 AsMidiMessageUnchecked() const;
bool IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; } bool IsInt64() const { return *typeTagPtr_ == INT64_TYPE_TAG; }
int64 AsInt64() const; int64 AsInt64() const;
int64 AsInt64Unchecked() 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 AsTimeTag() const;
uint64 AsTimeTagUnchecked() const; uint64 AsTimeTagUnchecked() const;
bool IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; } bool IsDouble() const { return *typeTagPtr_ == DOUBLE_TYPE_TAG; }
double AsDouble() const; double AsDouble() const;
double AsDoubleUnchecked() 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* 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* AsSymbol() const;
const char* AsSymbolUnchecked() const { return argument_; } const char* AsSymbolUnchecked() const { return argumentPtr_; }
bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; } bool IsBlob() const { return *typeTagPtr_ == BLOB_TYPE_TAG; }
void AsBlob( const void*& data, unsigned long& size ) const; void AsBlob( const void*& data, osc_bundle_element_size_t& size ) const;
void AsBlobUnchecked( const void*& data, unsigned long& 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: private:
const char *typeTag_; const char *typeTagPtr_;
const char *argument_; const char *argumentPtr_;
}; };
@@ -257,7 +316,7 @@ private:
bool IsEqualTo( const ReceivedMessageArgumentIterator& rhs ) const 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 // not sure if it would be useful to stream Nil and Infinitum
// for now it's not possible // for now it's not possible
// same goes for array boundaries
ReceivedMessageArgumentStream& operator>>( int32& rhs ) ReceivedMessageArgumentStream& operator>>( int32& rhs )
{ {
@@ -401,6 +461,8 @@ public:
ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs ) ReceivedMessageArgumentStream& operator>>( MessageTerminator& rhs )
{ {
(void) rhs; // suppress unused parameter warning
if( !Eos() ) if( !Eos() )
throw ExcessArgumentException(); throw ExcessArgumentException();
@@ -410,18 +472,18 @@ public:
class ReceivedMessage{ class ReceivedMessage{
void Init( const char *bundle, unsigned long size ); void Init( const char *bundle, osc_bundle_element_size_t size );
public: public:
explicit ReceivedMessage( const ReceivedPacket& packet ); explicit ReceivedMessage( const ReceivedPacket& packet );
explicit ReceivedMessage( const ReceivedBundleElement& bundleElement ); explicit ReceivedMessage( const ReceivedBundleElement& bundleElement );
const char *AddressPattern() const { return addressPattern_; } 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; bool AddressPatternIsUInt32() const;
uint32 AddressPatternAsUInt32() const; uint32 AddressPatternAsUInt32() const;
unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); } uint32 ArgumentCount() const { return static_cast<uint32>(typeTagsEnd_ - typeTagsBegin_); }
const char *TypeTags() const { return typeTagsBegin_; } const char *TypeTags() const { return typeTagsBegin_; }
@@ -452,14 +514,14 @@ private:
class ReceivedBundle{ class ReceivedBundle{
void Init( const char *message, unsigned long size ); void Init( const char *message, osc_bundle_element_size_t size );
public: public:
explicit ReceivedBundle( const ReceivedPacket& packet ); explicit ReceivedBundle( const ReceivedPacket& packet );
explicit ReceivedBundle( const ReceivedBundleElement& bundleElement ); explicit ReceivedBundle( const ReceivedBundleElement& bundleElement );
uint64 TimeTag() const; uint64 TimeTag() const;
unsigned long ElementCount() const { return elementCount_; } uint32 ElementCount() const { return elementCount_; }
typedef ReceivedBundleElementIterator const_iterator; typedef ReceivedBundleElementIterator const_iterator;
@@ -476,11 +538,11 @@ public:
private: private:
const char *timeTag_; const char *timeTag_;
const char *end_; const char *end_;
unsigned long elementCount_; uint32 elementCount_;
}; };
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */ #endif /* INCLUDED_OSCPACK_OSCRECEIVEDELEMENTS_H */

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,6 +23,17 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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" #include "OscTypes.h"
namespace osc{ namespace osc{
@@ -34,7 +41,12 @@ namespace osc{
BundleInitiator BeginBundleImmediate(1); BundleInitiator BeginBundleImmediate(1);
BundleTerminator EndBundle; BundleTerminator EndBundle;
MessageTerminator EndMessage; 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; InfinitumType Infinitum;
ArrayInitiator BeginArray;
ArrayTerminator EndArray;
} // namespace osc } // namespace osc

View File

@@ -1,8 +1,8 @@
/* /*
oscpack -- Open Sound Control packet manipulation library oscpack -- Open Sound Control (OSC) packet manipulation library
http://www.audiomulch.com/~rossb/oscpack http://www.rossbencina.com/code/oscpack
Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com> Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files a copy of this software and associated documentation files
@@ -15,10 +15,6 @@
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. 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, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
@@ -27,8 +23,19 @@
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 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{ namespace osc{
@@ -40,6 +47,11 @@ namespace osc{
typedef __int64 int64; typedef __int64 int64;
typedef unsigned __int64 uint64; typedef unsigned __int64 uint64;
#elif defined(__x86_64__) || defined(_M_X64)
typedef long int64;
typedef unsigned long uint64;
#else #else
typedef long long int64; 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 signed int int32;
typedef unsigned int uint32; typedef unsigned int uint32;
@@ -62,6 +74,41 @@ typedef unsigned long uint32;
#endif #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 { enum TypeTagValues {
TRUE_TYPE_TAG = 'T', TRUE_TYPE_TAG = 'T',
@@ -78,7 +125,9 @@ enum TypeTagValues {
DOUBLE_TYPE_TAG = 'd', DOUBLE_TYPE_TAG = 'd',
STRING_TYPE_TAG = 's', STRING_TYPE_TAG = 's',
SYMBOL_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{ 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{ struct InfinitumType{
}; };
@@ -166,13 +218,23 @@ struct Symbol{
struct Blob{ struct Blob{
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_ ) {} : data( data_ ), size( size_ ) {}
const void* data; const void* data;
unsigned long size; osc_bundle_element_size_t size;
}; };
struct ArrayInitiator{
};
extern ArrayInitiator BeginArray;
struct ArrayTerminator{
};
extern ArrayTerminator EndArray;
} // namespace osc } // namespace osc
#endif /* INCLUDED_OSCTYPES_H */ #endif /* INCLUDED_OSCPACK_OSCTYPES_H */