O2 2.0
A communication protocol for interactive music and media applications.
o2internal.h
1/* o2internal.h - o2.h + declarations needed for implementation */
2
3/* Roger B. Dannenberg
4 * April 2020
5 */
6
8
9#ifndef O2INTERNAL_H
10#define O2INTERNAL_H
11
12/* gcc doesn't know _Thread_local from C11 yet */
13#ifdef __GNUC__
14# define thread_local __thread
15#elif __STDC_VERSION__ >= 201112L
16# define thread_local _Thread_local
17#elif defined(_MSC_VER)
18// now thread_local seems to be a keyword in Visual Studio
19// # define thread_local __declspec(thread)
20#else
21# error Cannot define thread_local
22#endif
23
27#include <stdio.h>
28#include <string.h>
29#include <stdarg.h>
30#include <math.h>
31#include <assert.h>
32
33#include "o2.h"
34
35#include "o2obj.h"
36#include "debug.h"
37#include "vec.h"
38
39// Now, we need o2_ctx before including processes.h, and we need some
40// classes before that:
41
42// hash keys are processed in 32-bit chunks so we declare a special
43// string type. These are used in messages as well.
44typedef const char *O2string; // string padded to 4-byte boundary
45
46#include "o2network.h"
47#include "o2node.h"
48
49class Proc_info;
50class Bridge_info;
51
52class O2_context {
53public:
54 // msg_types is used to hold type codes as message args are accumulated
55 Vec<char> msg_types;
56 // msg_data is used to hold data as message args are accumulated
57 Vec<char> msg_data;
58 O2arg_ptr *argv; // arg vector extracted by calls to o2_get_next()
59
60 int argc; // length of argv
61
62 // O2argv_data is used to create the argv for handlers. It is expanded as
63 // needed to handle the largest message and is reused.
64 Vec<O2arg_ptr> argv_data;
65
66 // O2arg_data holds parameters that are coerced from message data
67 // It is referenced by O2argv_data and expanded as needed.
68 Vec<char> arg_data;
69
70 Hash_node full_path_table;
71 Hash_node path_tree;
72
73 // support for o2mem:
74 char *chunk; // where to allocate bytes when freelist is empty
75 size_t chunk_remaining; // how many bytes left in chunk
76
77 // one and only one of the following 2 addresses should be NULL:
78 Proc_info *proc;
79
80 Bridge_info *binst;
82
83 // This is a stack of messages we are delivering implemented using
84 // the next fields to make a list. If the user receiving a message
85 // decides to exit(), we will find un-freed messages here and free
86 // them, avoiding a(n apparent) memory leak. When a message is not
87 // in a data structure (e.g. pending queue, schedule, network send
88 // queue, the message should be on this list).
89 O2message_ptr msgs;
90
91 // warning callback for dropped messages
92 void (*warning)(const char *warn, o2_msg_data_ptr msg);
93
94 O2_context() {
95 argv = NULL;
96 argc = 0;
97 chunk = NULL;
98 chunk_remaining = 0;
99 proc = NULL;
100 binst = NULL;
101 msgs = NULL;
102 warning = &o2_message_drop_warning;
103 }
104
105 // deallocate everything that may have been allocated and attached
106 // to o2_ctx:
107 void finish() {
108 O2_DBG(printf("before o2_hash_node_finish of path_tree:\n"); \
109 show_tree());
110 path_tree.finish();
111 full_path_table.finish();
112 argv_data.finish();
113 arg_data.finish();
114 msg_types.finish();
115 msg_data.finish();
116 }
117#ifndef O2_NO_DEBUG
118 void show_tree() {
119 printf("%s -------- PATH TREE --------\n", o2_debug_prefix);
120 path_tree.show(2);
121 }
122#endif
123};
124
125/* O2 should not be called from multiple threads. One exception
126 * is the shared memory bridged processes call functions designed
127 * to run in a high-priority thread
128 * (such as an audio callback) that exchanges messages with a full O2
129 * process. There is a small problem that O2 message construction and
130 * decoding functions use some static, preallocated storage, so sharing
131 * across threads is not allowed. To avoid this, we put shared storage
132 * in an O2_context structure. One structure must be allocated per
133 * thread, and we use a thread-local variable o2_ctx to locate
134 * the context.
135 */
136extern thread_local O2_context *o2_ctx;
137
138
139#include "clock.h"
140#include "processes.h"
141#include "stun.h"
142#include "mqtt.h"
143#include "mqttcomm.h"
144#include "bridge.h"
145
146void o2_mem_finish(void); // implemented by o2mem.c, called to free
147// any memory managed by o2mem module.
148
149
151#ifdef _MSC_VER
152
153#ifndef USE_ANSI_C
154#define USE_ANSI_C
155#endif
156
157#ifndef _CRT_SECURE_NO_WARNINGS
158// Preclude warnings for string functions
159#define _CRT_SECURE_NO_WARNINGS
160#endif
161
162// OS X and Linux call it "snprintf":
163// snprintf seems to be defined Visual Studio now,
164// Visual Studio 2015 is the first version which defined snprintf,
165// and its _MSC_VER is 1900:
166#if _MSC_VER < 1900
167#define snprintf _snprintf
168#endif
169
170#else // Linux or OS X
171
172#define ioctlsocket ioctl
173#define closesocket close
174
175#endif // _MSC_VER
176
177
178#define RETURN_IF_ERROR(expr) { O2err err = (expr); \
179 if (err != O2_SUCCESS) return err; }
180
181// define IS_BIG_ENDIAN, IS_LITTLE_ENDIAN, and swap64(i),
182// swap32(i), and swap16(i)
183#if WIN32
184// WIN32 requires predefinition of IS_BIG_ENDIAN=1 or IS_BIG_ENDIAN=0
185#else
186 #ifdef __APPLE__
187 // OS X endian.h is in MacOSX10.8.sdk/usr/include/machine/endian.h:
188 #include "machine/endian.h"
189 #define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
190 #else
191 #include <endian.h>
192 #define LITTLE_ENDIAN __LITTLE_ENDIAN
193 #define BYTE_ORDER __BYTE_ORDER
194 #endif
195 #define IS_BIG_ENDIAN (BYTE_ORDER != LITTLE_ENDIAN)
196#endif
197#define IS_LITTLE_ENDIAN (!(IS_BIG_ENDIAN))
198#define swap16(i) ((((i) >> 8) & 0xff) | (((i) & 0xff) << 8))
199#define swap32(i) ((((i) >> 24) & 0xff) | (((i) & 0xff0000) >> 8) | \
200 (((i) & 0xff00) << 8) | (((i) & 0xff) << 24))
201#define swap64(i) ((((uint64_t) swap32(i)) << 32) | swap32((i) >> 32))
202#define O2_DEF_TYPE_SIZE 8
203#define O2_DEF_DATA_SIZE 8
204
205#define ROUNDUP_TO_32BIT(i) ((((size_t) i) + 3) & ~3)
206
207
208// o2_strcpy is like strlcpy but it does not return length.
209// precisely, o2_strcpy() copies up to n characters (including EOS) from
210// s to d. String s is truncated to a maximum length of n - 1 and terminated
211// with a zero EOS byte. (Any remainder of d may or may not be filled with
212// zeros, unlike strlcpy, which zero fills.)
213#ifdef __APPLE__
214#define o2_strcpy(d, s, n) ((void) strlcpy(d, s, n))
215#else
216void o2_strcpy(char *__restrict dst, const char *__restrict src,
217 size_t dstsize);
218#endif
219
220extern O2time o2_local_now;
221extern O2time o2_global_now;
222extern O2time o2_global_offset; // o2_global_now - o2_local_now
223extern int o2_gtsched_started;
224
225#define O2_ARGS_END O2_MARKER_A, O2_MARKER_B
227#define MAX_BUFFER 1024
228
231#define O2_MAX_NODE_NAME_LEN 1020
232#define NAME_BUF_LEN ((O2_MAX_NODE_NAME_LEN) + 4)
233
234/* \brief Maximum length of UDP messages in bytes
235 */
236#define O2_MAX_MSG_SIZE 32768
237
238
239// shared internal functions
240void o2_notify_others(const char *service_name, bool added, const char *tappee,
241 const char *properties, int send_mode);
242
243
244O2err o2_tap_new(O2string tappee, Proxy_info *process,
245 const char *tapper, O2tap_send_mode send_mode);
246
247O2err o2_tap_remove(O2string tappee, Proxy_info *process,
248 const char *tapper);
249
250void o2_init_phase2();
251
252int o2_parse_version(const char *vers, int vers_len);
253
254#endif /* O2INTERNAL_H */
Definition: bridge.h:146
Definition: o2node.h:164
Definition: processes.h:20
Definition: o2node.h:291
Definition: vec.h:6
void o2_message_drop_warning(const char *warn, o2_msg_data_ptr msg)
Default dropped message alert.
Definition: o2.cpp:1242
double O2time
O2 timestamps are doubles representing seconds since the approximate start time of the ensemble.
Definition: o2.h:625
O2err
return values used generally by O2 functions
Definition: o2.h:329
an O2 message container
Definition: o2.h:690
data part of an O2 message
Definition: o2.h:638
union of all O2 parameter types
Definition: o2.h:764