-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathosc_error.c
More file actions
202 lines (188 loc) · 5.64 KB
/
osc_error.c
File metadata and controls
202 lines (188 loc) · 5.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
Written by John MacCallum, The Center for New Music and Audio Technologies,
University of California, Berkeley. Copyright (c) 2009-12, The Regents of
the University of California (Regents).
Permission to use, copy, modify, distribute, and distribute modified versions
of this software and its documentation without fee and without a signed
licensing agreement, is hereby granted, provided that the above copyright
notice, this paragraph and the following two paragraphs appear in all copies,
modifications, and distributions.
IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
#include "osc_error.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "osc.h"
#include "osc_mem.h"
#include "osc_bundle_s.h"
#include "osc_byteorder.h"
int osc_error_defaultHandler(void *context, const char * const errorstr)
{
return fprintf(stderr, "%s\n", errorstr);
}
static t_osc_error_handler _osc_error_handler = osc_error_defaultHandler;
int osc_error_handler(void *context,
const char * const filename,
const char * const functionname,
int linenum,
t_osc_err errorcode,
const char * const moreinfo_fmt,
...)
{
if(_osc_error_handler){
// printf("%s context %p \n\tfilename %s \n\tfunctionname %s \n\tlinenum %d \n\terrorcode %d \n\tmoreinfo_fmt %s \n", __func__, context, filename, functionname, linenum, (int)errorcode, moreinfo_fmt );
int buflen = MAX_ERR_STRING_LEN;
char buf[buflen];
char *pos = buf;
if(filename){
pos += snprintf(pos, buflen, "%s:\n", filename);
}
if(functionname){
pos += snprintf(pos, (buflen - (pos - buf)), "%s(): ", functionname);
}
if(linenum > 0){
pos += snprintf(pos, (buflen - (pos - buf)), "%d: ", linenum);
}
if(errorcode){
pos += snprintf(pos, (buflen - (pos - buf)), "%s: \n", osc_error_string(errorcode));
}
if(moreinfo_fmt){
pos += snprintf(pos, (buflen - (pos - buf)), "%s", moreinfo_fmt);
}
va_list ap;
va_start(ap, moreinfo_fmt);
char newbuf[buflen];
pos = newbuf;
pos += vsnprintf(newbuf, (buflen - (pos - newbuf)), buf, ap);
va_end(ap);
return _osc_error_handler(context, newbuf);
}
return 0;
}
void osc_error_setHandler(t_osc_error_handler eh)
{
_osc_error_handler = eh;
}
char *osc_error_string(t_osc_err err)
{
switch(err){
case OSC_ERR_NONE:
return "no error";
case OSC_ERR_BUNDLETOOSMALL:
#define xstr(s) str(s)
#define str(s) #s
return "OSC bundle was too small (< "xstr(OSC_HEADER_SIZE)" bytes)";
#undef xstr
#undef str
case OSC_ERR_NOBUNDLEID:
return "no bundle id ("OSC_IDENTIFIER") found at beginning of bundle";
case OSC_ERR_MSGTOOSMALL:
return "OSC message was too small (< 4 bytes)";
case OSC_ERR_MSGTOOLARGE:
return "OSC message size is incorrect; message extends beyond the end of the bundle";
case OSC_ERR_MALFORMEDADDRESS:
return "malformed OSC address (probably missing an initial '/')";
case OSC_ERR_NOBUNDLE:
return "received a NULL pointer where a bundle was expected";
case OSC_ERR_OUTOFMEM:
return "out of memory";
case OSC_ERR_NULLPTR:
return "got a NULL pointer unexpectedly";
case OSC_ERR_BADTYPETAG:
return "encountered a discrepancy between a typetag and a piece of data";
case OSC_ERR_MALFORMEDMSG:
return "malformed message";
case OSC_ERR_INVAL:
return "invalid address";
case OSC_ERR_EXPR_FUNCTIONNOTFOUND:
case OSC_ERR_PARSER_FUNCTIONNOTFOUND:
return "function not found";
case OSC_ERR_EXPR_ADDRESSUNBOUND:
return "address is unbound";
case OSC_ERR_EXPPARSE:
return "error parsing expression";
case OSC_ERR_PARSER:
return "error parsing OSC bundle";
case OSC_ERR_EXPR_ARGCHK:
return "invalid arguments for function";
case OSC_ERR_EXPR_EVAL:
return "error evaluating expression";
case OSC_ERR_INVALIDCHARINADDRESS:
return "invalid character found in address";
default:
return "unrecognized error code";
}
}
t_osc_err osc_error_bundleSanityCheck(int len, char *bundle)
{
if(!bundle){
return OSC_ERR_NOBUNDLE;
}
if(len < OSC_HEADER_SIZE){
return OSC_ERR_BUNDLETOOSMALL;
}
if(osc_bundle_s_strcmpID(bundle)){
return OSC_ERR_NOBUNDLEID;
}
char *ptr = bundle + OSC_HEADER_SIZE;
int cumsize = OSC_HEADER_SIZE;
while((ptr - bundle) < len){
cumsize += 4; // msg size
int size = ntoh32(*((uint32_t *)ptr));
cumsize += size;
if(cumsize > len){
return OSC_ERR_MSGTOOLARGE;
}
int ret;
if((ret = osc_error_msgSanityCheck(ptr))){
return ret;
}
ptr += size + 4;
}
return OSC_ERR_NONE;
}
t_osc_err osc_error_msgSanityCheck(char *msg)
{
int size = ntoh32(*((uint32_t *)msg));
if(size < 4){
return OSC_ERR_MSGTOOSMALL;
}
if(*(msg + 4) != '/'){
return OSC_ERR_MALFORMEDADDRESS;
}
return OSC_ERR_NONE;
}
t_osc_err osc_error_validateAddress(char *address){
// this should be done with a proper grammar
if(!address){
return OSC_ERR_NULLPTR;
}
if(*address != '/'){
return OSC_ERR_MALFORMEDADDRESS;
}
if(strlen(address) < 2){
return OSC_ERR_MALFORMEDADDRESS;
}
int len = strlen(address);
for(int i = 0; i < len; i++){
switch(address[i]){
case '\0':
return OSC_ERR_NONE;
case '#':
case ' ':
return OSC_ERR_INVALIDCHARINADDRESS;
default:
;
}
}
return OSC_ERR_NONE;
}