1 /* Calf DSP Library
2  * Open Sound Control primitives
3  *
4  * Copyright (C) 2007 Krzysztof Foltman
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this program; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #ifndef __CALF_OSCTL_H
23 #define __CALF_OSCTL_H
24 
25 #include <string>
26 #include <vector>
27 #include <string.h>
28 #include <errno.h>
29 #include <iostream>
30 #ifndef _MSC_VER
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #endif
34 
35 namespace osctl
36 {
37 
38 enum osc_type
39 {
40     osc_i32 = 'i',
41     osc_f32 = 'f',
42     osc_string = 's',
43     osc_blob = 'b',
44 
45     // unsupported
46     osc_i64 = 'h',
47     osc_ts = 't',
48     osc_f64 = 'd',
49     osc_string_alt = 'S',
50     osc_char = 'c',
51     osc_rgba = 'r',
52     osc_midi = 'm',
53     osc_true = 'T',
54     osc_false = 'F',
55     osc_nil = 'N',
56     osc_inf = 'I',
57     osc_start_array = '[',
58     osc_end_array = ']'
59 };
60 
61 extern const char *osc_type_name(osc_type type);
62 
63 struct osc_exception: public std::exception
64 {
whatosc_exception65     virtual const char *what() const throw() { return "OSC parsing error"; }
66 };
67 
68 struct osc_read_exception: public std::exception
69 {
whatosc_read_exception70     virtual const char *what() const throw() { return "OSC buffer underflow"; }
71 };
72 
73 struct osc_write_exception: public std::exception
74 {
whatosc_write_exception75     virtual const char *what() const throw() { return "OSC buffer overflow"; }
76 };
77 
78 struct null_buffer
79 {
readnull_buffer80     static bool read(uint8_t *dest, uint32_t bytes)
81     {
82         return false;
83     }
writenull_buffer84     static bool write(uint8_t *dest, uint32_t bytes)
85     {
86         return true;
87     }
clearnull_buffer88     static void clear()
89     {
90     }
91 };
92 
93 struct raw_buffer
94 {
95     uint8_t *ptr;
96     uint32_t pos, count, size;
97 
raw_bufferraw_buffer98     raw_buffer()
99     {
100         ptr = NULL;
101         pos = count = size = 0;
102     }
raw_bufferraw_buffer103     raw_buffer(uint8_t *_ptr, uint32_t _count, uint32_t _size)
104     {
105         set(_ptr, _count, _size);
106     }
setraw_buffer107     inline void set(uint8_t *_ptr, uint32_t _count, uint32_t _size)
108     {
109         ptr = _ptr;
110         pos = 0;
111         count = _count;
112         size = _size;
113     }
readraw_buffer114     bool read(uint8_t *dest, uint32_t bytes)
115     {
116         if (pos + bytes > count)
117             return false;
118         memcpy(dest, ptr + pos, bytes);
119         pos += bytes;
120         return true;
121     }
writeraw_buffer122     bool write(const uint8_t *src, uint32_t bytes)
123     {
124         if (count + bytes > size)
125             return false;
126         memcpy(ptr + count, src, bytes);
127         count += bytes;
128         return true;
129     }
read_leftraw_buffer130     int read_left()
131     {
132         return count - pos;
133     }
write_leftraw_buffer134     int write_left()
135     {
136         return size - count;
137     }
write_misalignmentraw_buffer138     inline int write_misalignment()
139     {
140         return 4 - (count & 3);
141     }
clearraw_buffer142     void clear()
143     {
144         pos = 0;
145         count = 0;
146     }
tellraw_buffer147     int tell()
148     {
149         return pos;
150     }
seekraw_buffer151     void seek(int _pos)
152     {
153         pos = _pos;
154     }
155 };
156 
157 struct string_buffer
158 {
159     std::string data;
160     uint32_t pos, size;
161 
string_bufferstring_buffer162     string_buffer()
163     {
164         pos = 0;
165         size = 1048576;
166     }
167     string_buffer(std::string _data, int _size = 1048576)
168     {
169         data = _data;
170         pos = 0;
171         size = _size;
172     }
readstring_buffer173     bool read(uint8_t *dest, uint32_t bytes)
174     {
175         if (pos + bytes > data.length())
176             return false;
177         memcpy(dest, &data[pos], bytes);
178         pos += bytes;
179         return true;
180     }
writestring_buffer181     bool write(const uint8_t *src, uint32_t bytes)
182     {
183         if (data.length() + bytes > size)
184             return false;
185         uint32_t wpos = data.length();
186         data.resize(wpos + bytes);
187         memcpy(&data[wpos], src, bytes);
188         return true;
189     }
read_leftstring_buffer190     inline int read_left()
191     {
192         return data.length() - pos;
193     }
write_leftstring_buffer194     inline int write_left()
195     {
196         return size - data.length();
197     }
write_misalignmentstring_buffer198     inline int write_misalignment()
199     {
200         return 4 - (data.length() & 3);
201     }
clearstring_buffer202     void clear()
203     {
204         data.clear();
205         pos = 0;
206     }
tellstring_buffer207     int tell()
208     {
209         return pos;
210     }
seekstring_buffer211     void seek(int _pos)
212     {
213         pos = _pos;
214     }
215 };
216 
217 template<class Buffer, class TypeBuffer = null_buffer, bool Throw = true>
218 struct osc_stream
219 {
220     Buffer &buffer;
221     TypeBuffer *type_buffer;
222     bool error;
223 
osc_streamosc_stream224     osc_stream(Buffer &_buffer) : buffer(_buffer), type_buffer(NULL), error(false) {}
osc_streamosc_stream225     osc_stream(Buffer &_buffer, TypeBuffer &_type_buffer) : buffer(_buffer), type_buffer(&_type_buffer), error(false) {}
padosc_stream226     inline void pad()
227     {
228         uint32_t zero = 0;
229         write(&zero, buffer.write_misalignment());
230     }
readosc_stream231     inline void read(void *dest, uint32_t bytes)
232     {
233         if (!buffer.read((uint8_t *)dest, bytes))
234         {
235             if (Throw)
236                 throw osc_read_exception();
237             else
238             {
239                 error = true;
240                 memset(dest, 0, bytes);
241             }
242         }
243     }
writeosc_stream244     inline void write(const void *src, uint32_t bytes)
245     {
246         if (!buffer.write((const uint8_t *)src, bytes))
247         {
248             if (Throw)
249                 throw osc_write_exception();
250             else
251                 error = true;
252         }
253     }
clearosc_stream254     inline void clear()
255     {
256         buffer.clear();
257         if (type_buffer)
258             type_buffer->clear();
259     }
write_typeosc_stream260     inline void write_type(char ch)
261     {
262         if (type_buffer)
263             type_buffer->write((uint8_t *)&ch, 1);
264     }
265 };
266 
267 typedef osc_stream<string_buffer> osc_strstream;
268 typedef osc_stream<string_buffer, string_buffer> osc_typed_strstream;
269 
270 struct osc_inline_strstream: public string_buffer, public osc_strstream
271 {
osc_inline_strstreamosc_inline_strstream272     osc_inline_strstream()
273     : string_buffer(), osc_strstream(static_cast<string_buffer &>(*this))
274     {
275     }
276 };
277 
278 struct osc_str_typed_buffer_pair
279 {
280     string_buffer buf_data, buf_types;
281 };
282 
283 struct osc_inline_typed_strstream: public osc_str_typed_buffer_pair, public osc_typed_strstream
284 {
osc_inline_typed_strstreamosc_inline_typed_strstream285     osc_inline_typed_strstream()
286     : osc_str_typed_buffer_pair(), osc_typed_strstream(buf_data, buf_types)
287     {
288     }
289 };
290 
291 template<class Buffer, class TypeBuffer>
292 inline osc_stream<Buffer, TypeBuffer> &
293 operator <<(osc_stream<Buffer, TypeBuffer> &s, uint32_t val)
294 {
295     val = htonl(val);
296     s.write(&val, 4);
297     s.write_type(osc_i32);
298     return s;
299 }
300 
301 template<class Buffer, class TypeBuffer>
302 inline osc_stream<Buffer, TypeBuffer> &
303 operator >>(osc_stream<Buffer, TypeBuffer> &s, uint32_t &val)
304 {
305     s.read(&val, 4);
306     val = htonl(val);
307     return s;
308 }
309 
310 template<class Buffer, class TypeBuffer>
311 inline osc_stream<Buffer, TypeBuffer> &
312 operator >>(osc_stream<Buffer, TypeBuffer> &s, int32_t &val)
313 {
314     s.read(&val, 4);
315     val = htonl(val);
316     return s;
317 }
318 
319 template<class Buffer, class TypeBuffer>
320 inline osc_stream<Buffer, TypeBuffer> &
321 operator <<(osc_stream<Buffer, TypeBuffer> &s, float val)
322 {
323     union { float v; uint32_t i; } val2;
324     val2.v = val;
325     val2.i = htonl(val2.i);
326     s.write(&val2.i, 4);
327     s.write_type(osc_f32);
328     return s;
329 }
330 
331 template<class Buffer, class TypeBuffer>
332 inline osc_stream<Buffer, TypeBuffer> &
333 operator >>(osc_stream<Buffer, TypeBuffer> &s, float &val)
334 {
335     union { float v; uint32_t i; } val2;
336     s.read(&val2.i, 4);
337     val2.i = htonl(val2.i);
338     val = val2.v;
339     return s;
340 }
341 
342 template<class Buffer, class TypeBuffer>
343 inline osc_stream<Buffer, TypeBuffer> &
344 operator <<(osc_stream<Buffer, TypeBuffer> &s, const std::string &str)
345 {
346     s.write(&str[0], str.length());
347     s.pad();
348     s.write_type(osc_string);
349     return s;
350 }
351 
352 template<class Buffer, class TypeBuffer>
353 inline osc_stream<Buffer, TypeBuffer> &
354 operator >>(osc_stream<Buffer, TypeBuffer> &s, std::string &str)
355 {
356     // inefficient...
357     char five[5];
358     five[4] = '\0';
359     str.resize(0);
360     while(1)
361     {
362         s.read(five, 4);
363         if (five[0] == '\0')
364             break;
365         str += five;
366         if (!five[1] || !five[2] || !five[3])
367             break;
368     }
369     return s;
370 }
371 
372 template<class Buffer, class TypeBuffer, class DestBuffer>
373 inline osc_stream<Buffer, TypeBuffer> &
read_buffer_from_osc_stream(osc_stream<Buffer,TypeBuffer> & s,DestBuffer & buf)374 read_buffer_from_osc_stream(osc_stream<Buffer, TypeBuffer> &s, DestBuffer &buf)
375 {
376     uint32_t nlen = 0;
377     s.read(&nlen, 4);
378     uint32_t len = htonl(nlen);
379     // write length in network order
380     for (uint32_t i = 0; i < len; i += 1024)
381     {
382         uint8_t tmp[1024];
383         uint32_t part = std::min((uint32_t)1024, len - i);
384         s.read(tmp, part);
385         buf.write(tmp, part);
386     }
387     // pad
388     s.read(&nlen, 4 - (len & 3));
389     return s;
390 }
391 
392 template<class Buffer, class TypeBuffer, class SrcBuffer>
393 inline osc_stream<Buffer, TypeBuffer> &
write_buffer_to_osc_stream(osc_stream<Buffer,TypeBuffer> & s,SrcBuffer & buf)394 write_buffer_to_osc_stream(osc_stream<Buffer, TypeBuffer> &s, SrcBuffer &buf)
395 {
396     uint32_t len = buf.read_left();
397     uint32_t nlen = ntohl(len);
398     s.write(&nlen, 4);
399     // write length in network order
400     for (uint32_t i = 0; i < len; i += 1024)
401     {
402         uint8_t tmp[1024];
403         uint32_t part = std::min((uint32_t)1024, len - i);
404         buf.read(tmp, part);
405         s.write(tmp, part);
406     }
407     s.pad();
408     s.write_type(osc_blob);
409     return s;
410 }
411 
412 template<class Buffer, class TypeBuffer>
413 inline osc_stream<Buffer, TypeBuffer> &
414 operator >>(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
415 {
416     return read_buffer_from_osc_stream(s, str);
417 }
418 
419 template<class Buffer, class TypeBuffer>
420 inline osc_stream<Buffer, TypeBuffer> &
421 operator >>(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
422 {
423     return read_buffer_from_osc_stream(s, str);
424 }
425 
426 template<class Buffer, class TypeBuffer>
427 inline osc_stream<Buffer, TypeBuffer> &
428 operator <<(osc_stream<Buffer, TypeBuffer> &s, raw_buffer &str)
429 {
430     return write_buffer_to_osc_stream(s, str);
431 }
432 
433 template<class Buffer, class TypeBuffer>
434 inline osc_stream<Buffer, TypeBuffer> &
435 operator <<(osc_stream<Buffer, TypeBuffer> &s, string_buffer &str)
436 {
437     return write_buffer_to_osc_stream(s, str);
438 }
439 
440 // XXXKF: I don't support reading binary blobs yet
441 
442 struct osc_net_bad_address: public std::exception
443 {
444     std::string addr, error_msg;
osc_net_bad_addressosc_net_bad_address445     osc_net_bad_address(const char *_addr)
446     {
447         addr = _addr;
448         error_msg = "Incorrect OSC URI: " + addr;
449     }
whatosc_net_bad_address450     virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_bad_addressosc_net_bad_address451     virtual ~osc_net_bad_address() throw () {}
452 };
453 
454 struct osc_net_exception: public std::exception
455 {
456     int net_errno;
457     std::string command, error_msg;
458     osc_net_exception(const char *cmd, int _errno = errno)
459     {
460         command = cmd;
461         net_errno = _errno;
462         error_msg = "OSC error in "+command+": "+strerror(_errno);
463     }
whatosc_net_exception464     virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_exceptionosc_net_exception465     virtual ~osc_net_exception() throw () {}
466 };
467 #ifdef _MSC_VER
468 //TODO: add replacement for osc_net_dns_exception
469 #else
470 struct osc_net_dns_exception: public std::exception
471 {
472     int net_errno;
473     std::string command, error_msg;
474     osc_net_dns_exception(const char *cmd, int _errno = h_errno)
475     {
476         command = cmd;
477         net_errno = _errno;
478         error_msg = "OSC error in "+command+": "+hstrerror(_errno);
479     }
whatosc_net_dns_exception480     virtual const char *what() const throw() { return error_msg.c_str(); }
~osc_net_dns_exceptionosc_net_dns_exception481     virtual ~osc_net_dns_exception() throw () {}
482 };
483 #endif
484 template<class OscStream>
485 struct osc_message_sink
486 {
487     virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)=0;
~osc_message_sinkosc_message_sink488     virtual ~osc_message_sink() {}
489 };
490 
491 template<class OscStream, class DumpStream>
492 struct osc_message_dump: public osc_message_sink<OscStream>
493 {
494     DumpStream &stream;
osc_message_dumposc_message_dump495     osc_message_dump(DumpStream &_stream) : stream(_stream) {}
496 
receive_osc_messageosc_message_dump497     virtual void receive_osc_message(std::string address, std::string type_tag, OscStream &buffer)
498     {
499         int pos = buffer.buffer.tell();
500         stream << "address: " << address << ", type tag: " << type_tag << std::endl;
501         for (unsigned int i = 0; i < type_tag.size(); i++)
502         {
503             stream << "Argument " << i << " is ";
504             switch(type_tag[i])
505             {
506                 case 'i':
507                 {
508                     uint32_t val;
509                     buffer >> val;
510                     stream << val;
511                     break;
512                 }
513                 case 'f':
514                 {
515                     float val;
516                     buffer >> val;
517                     stream << val;
518                     break;
519                 }
520                 case 's':
521                 {
522                     std::string val;
523                     buffer >> val;
524                     stream << val;
525                     break;
526                 }
527                 case 'b':
528                 {
529                     osctl::string_buffer val;
530                     buffer >> val;
531                     stream << "blob (" << val.data.length() << " bytes)";
532                     break;
533                 }
534                 default:
535                 {
536                     stream << "unknown - cannot parse more arguments" << std::endl;
537                     i = type_tag.size();
538                     break;
539                 }
540             }
541             stream << std::endl;
542         }
543         stream << std::flush;
544         buffer.buffer.seek(pos);
545     }
546 };
547 
548 };
549 
550 #endif
551