~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.2.1/pjlib/src/pj/errno.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-01-07 14:51:16 UTC
  • mfrom: (4.3.5 sid)
  • Revision ID: package-import@ubuntu.com-20150107145116-yxnafinf4lrdvrmx
Tags: 1.4.1-0.1ubuntu1
* Merge with Debian, remaining changes:
 - Drop soprano, nepomuk build-dep
* Drop ubuntu patches, now upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: errno.c 4761 2014-02-24 09:02:44Z nanang $ */
 
2
/* 
 
3
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 
4
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (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
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 
19
 */
 
20
#include <pj/errno.h>
 
21
#include <pj/log.h>
 
22
#include <pj/string.h>
 
23
#include <pj/compat/string.h>
 
24
#include <pj/compat/stdarg.h>
 
25
#include <pj/assert.h>
 
26
 
 
27
/* Prototype for platform specific error message, which will be defined 
 
28
 * in separate file.
 
29
 */
 
30
PJ_BEGIN_DECL
 
31
 
 
32
    PJ_DECL(int) platform_strerror(pj_os_err_type code, 
 
33
                                   char *buf, pj_size_t bufsize );
 
34
PJ_END_DECL
 
35
 
 
36
#ifndef PJLIB_MAX_ERR_MSG_HANDLER
 
37
#       define PJLIB_MAX_ERR_MSG_HANDLER   10
 
38
#endif
 
39
 
 
40
/* Error message handler. */
 
41
static unsigned err_msg_hnd_cnt;
 
42
static struct err_msg_hnd
 
43
{
 
44
    pj_status_t     begin;
 
45
    pj_status_t     end;
 
46
    pj_str_t      (*strerror)(pj_status_t, char*, pj_size_t);
 
47
 
 
48
} err_msg_hnd[PJLIB_MAX_ERR_MSG_HANDLER];
 
49
 
 
50
/* PJLIB's own error codes/messages */
 
51
#if defined(PJ_HAS_ERROR_STRING) && PJ_HAS_ERROR_STRING!=0
 
52
 
 
53
static const struct 
 
54
{
 
55
    int code;
 
56
    const char *msg;
 
57
} err_str[] = 
 
58
{
 
59
    PJ_BUILD_ERR(PJ_EUNKNOWN,      "Unknown Error" ),
 
60
    PJ_BUILD_ERR(PJ_EPENDING,      "Pending operation" ),
 
61
    PJ_BUILD_ERR(PJ_ETOOMANYCONN,  "Too many connecting sockets" ),
 
62
    PJ_BUILD_ERR(PJ_EINVAL,        "Invalid value or argument" ),
 
63
    PJ_BUILD_ERR(PJ_ENAMETOOLONG,  "Name too long" ),
 
64
    PJ_BUILD_ERR(PJ_ENOTFOUND,     "Not found" ),
 
65
    PJ_BUILD_ERR(PJ_ENOMEM,        "Not enough memory" ),
 
66
    PJ_BUILD_ERR(PJ_EBUG,          "BUG DETECTED!" ),
 
67
    PJ_BUILD_ERR(PJ_ETIMEDOUT,     "Operation timed out" ),
 
68
    PJ_BUILD_ERR(PJ_ETOOMANY,      "Too many objects of the specified type"),
 
69
    PJ_BUILD_ERR(PJ_EBUSY,         "Object is busy"),
 
70
    PJ_BUILD_ERR(PJ_ENOTSUP,       "Option/operation is not supported"),
 
71
    PJ_BUILD_ERR(PJ_EINVALIDOP,    "Invalid operation"),
 
72
    PJ_BUILD_ERR(PJ_ECANCELLED,    "Operation cancelled"),
 
73
    PJ_BUILD_ERR(PJ_EEXISTS,       "Object already exists" ),
 
74
    PJ_BUILD_ERR(PJ_EEOF,          "End of file" ),
 
75
    PJ_BUILD_ERR(PJ_ETOOBIG,       "Size is too big"),
 
76
    PJ_BUILD_ERR(PJ_ERESOLVE,      "gethostbyname() has returned error"),
 
77
    PJ_BUILD_ERR(PJ_ETOOSMALL,     "Size is too short"),
 
78
    PJ_BUILD_ERR(PJ_EIGNORED,      "Ignored"),
 
79
    PJ_BUILD_ERR(PJ_EIPV6NOTSUP,   "IPv6 is not supported"),
 
80
    PJ_BUILD_ERR(PJ_EAFNOTSUP,     "Unsupported address family"),
 
81
    PJ_BUILD_ERR(PJ_EGONE,         "Object no longer exists"),
 
82
    PJ_BUILD_ERR(PJ_ESOCKETSTOP,   "Socket is in bad state")
 
83
};
 
84
#endif  /* PJ_HAS_ERROR_STRING */
 
85
 
 
86
 
 
87
/*
 
88
 * pjlib_error()
 
89
 *
 
90
 * Retrieve message string for PJLIB's own error code.
 
91
 */
 
92
static int pjlib_error(pj_status_t code, char *buf, pj_size_t size)
 
93
{
 
94
    int len;
 
95
 
 
96
#if defined(PJ_HAS_ERROR_STRING) && PJ_HAS_ERROR_STRING!=0
 
97
    unsigned i;
 
98
 
 
99
    for (i=0; i<sizeof(err_str)/sizeof(err_str[0]); ++i) {
 
100
        if (err_str[i].code == code) {
 
101
            pj_size_t len = strlen(err_str[i].msg);
 
102
            if (len >= size) len = size-1;
 
103
            pj_memcpy(buf, err_str[i].msg, len);
 
104
            buf[len] = '\0';
 
105
            return (int)len;
 
106
        }
 
107
    }
 
108
#endif
 
109
 
 
110
    len = pj_ansi_snprintf( buf, size, "Unknown pjlib error %d", code);
 
111
    if (len < 1 || len >= (int)size)
 
112
        len = (int)(size - 1);
 
113
    return len;
 
114
}
 
115
 
 
116
#define IN_RANGE(val,start,end)     ((val)>=(start) && (val)<(end))
 
117
 
 
118
/* Register strerror handle. */
 
119
PJ_DEF(pj_status_t) pj_register_strerror( pj_status_t start,
 
120
                                          pj_status_t space,
 
121
                                          pj_error_callback f)
 
122
{
 
123
    unsigned i;
 
124
 
 
125
    /* Check arguments. */
 
126
    PJ_ASSERT_RETURN(start && space && f, PJ_EINVAL);
 
127
 
 
128
    /* Check if there aren't too many handlers registered. */
 
129
    PJ_ASSERT_RETURN(err_msg_hnd_cnt < PJ_ARRAY_SIZE(err_msg_hnd),
 
130
                     PJ_ETOOMANY);
 
131
 
 
132
    /* Start error must be greater than PJ_ERRNO_START_USER */
 
133
    PJ_ASSERT_RETURN(start >= PJ_ERRNO_START_USER, PJ_EEXISTS);
 
134
 
 
135
    /* Check that no existing handler has covered the specified range. */
 
136
    for (i=0; i<err_msg_hnd_cnt; ++i) {
 
137
        if (IN_RANGE(start, err_msg_hnd[i].begin, err_msg_hnd[i].end) ||
 
138
            IN_RANGE(start+space-1, err_msg_hnd[i].begin, err_msg_hnd[i].end))
 
139
        {
 
140
            if (err_msg_hnd[i].begin == start && 
 
141
                err_msg_hnd[i].end == (start+space) &&
 
142
                err_msg_hnd[i].strerror == f)
 
143
            {
 
144
                /* The same range and handler has already been registered */
 
145
                return PJ_SUCCESS;
 
146
            }
 
147
 
 
148
            return PJ_EEXISTS;
 
149
        }
 
150
    }
 
151
 
 
152
    /* Register the handler. */
 
153
    err_msg_hnd[err_msg_hnd_cnt].begin = start;
 
154
    err_msg_hnd[err_msg_hnd_cnt].end = start + space;
 
155
    err_msg_hnd[err_msg_hnd_cnt].strerror = f;
 
156
 
 
157
    ++err_msg_hnd_cnt;
 
158
 
 
159
    return PJ_SUCCESS;
 
160
}
 
161
 
 
162
/* Internal PJLIB function called by pj_shutdown() to clear error handlers */
 
163
void pj_errno_clear_handlers(void)
 
164
{
 
165
    err_msg_hnd_cnt = 0;
 
166
    pj_bzero(err_msg_hnd, sizeof(err_msg_hnd));
 
167
}
 
168
 
 
169
 
 
170
/*
 
171
 * pj_strerror()
 
172
 */
 
173
PJ_DEF(pj_str_t) pj_strerror( pj_status_t statcode, 
 
174
                              char *buf, pj_size_t bufsize )
 
175
{
 
176
    int len = -1;
 
177
    pj_str_t errstr;
 
178
 
 
179
    pj_assert(buf && bufsize);
 
180
 
 
181
    if (statcode == PJ_SUCCESS) {
 
182
        len = pj_ansi_snprintf( buf, bufsize, "Success");
 
183
 
 
184
    } else if (statcode < PJ_ERRNO_START + PJ_ERRNO_SPACE_SIZE) {
 
185
        len = pj_ansi_snprintf( buf, bufsize, "Unknown error %d", statcode);
 
186
 
 
187
    } else if (statcode < PJ_ERRNO_START_STATUS + PJ_ERRNO_SPACE_SIZE) {
 
188
        len = pjlib_error(statcode, buf, bufsize);
 
189
 
 
190
    } else if (statcode < PJ_ERRNO_START_SYS + PJ_ERRNO_SPACE_SIZE) {
 
191
        len = platform_strerror(PJ_STATUS_TO_OS(statcode), buf, bufsize);
 
192
 
 
193
    } else {
 
194
        unsigned i;
 
195
 
 
196
        /* Find user handler to get the error message. */
 
197
        for (i=0; i<err_msg_hnd_cnt; ++i) {
 
198
            if (IN_RANGE(statcode, err_msg_hnd[i].begin, err_msg_hnd[i].end)) {
 
199
                return (*err_msg_hnd[i].strerror)(statcode, buf, bufsize);
 
200
            }
 
201
        }
 
202
 
 
203
        /* Handler not found! */
 
204
        len = pj_ansi_snprintf( buf, bufsize, "Unknown error %d", statcode);
 
205
    }
 
206
 
 
207
    if (len < 1 || len >= (int)bufsize) {
 
208
        len = (int)(bufsize - 1);
 
209
        buf[len] = '\0';
 
210
    }
 
211
 
 
212
    errstr.ptr = buf;
 
213
    errstr.slen = len;
 
214
 
 
215
    return errstr;
 
216
}
 
217
 
 
218
#if PJ_LOG_MAX_LEVEL >= 1
 
219
static void invoke_log(const char *sender, int level, const char *format, ...)
 
220
{
 
221
    va_list arg;
 
222
    va_start(arg, format);
 
223
    pj_log(sender, level, format, arg);
 
224
    va_end(arg);
 
225
}
 
226
 
 
227
static void pj_perror_imp(int log_level, const char *sender, 
 
228
                          pj_status_t status,
 
229
                          const char *title_fmt, va_list marker)
 
230
{
 
231
    char titlebuf[PJ_PERROR_TITLE_BUF_SIZE];
 
232
    char errmsg[PJ_ERR_MSG_SIZE];
 
233
    int len;
 
234
 
 
235
    /* Build the title */
 
236
    len = pj_ansi_vsnprintf(titlebuf, sizeof(titlebuf), title_fmt, marker);
 
237
    if (len < 0 || len >= (int)sizeof(titlebuf))
 
238
        pj_ansi_strcpy(titlebuf, "Error");
 
239
 
 
240
    /* Get the error */
 
241
    pj_strerror(status, errmsg, sizeof(errmsg));
 
242
 
 
243
    /* Send to log */
 
244
    invoke_log(sender, log_level, "%s: %s", titlebuf, errmsg);
 
245
}
 
246
 
 
247
PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
 
248
                       const char *title_fmt, ...)
 
249
{
 
250
    va_list marker;
 
251
    va_start(marker, title_fmt);
 
252
    pj_perror_imp(log_level, sender, status, title_fmt, marker);
 
253
    va_end(marker);
 
254
}
 
255
 
 
256
PJ_DEF(void) pj_perror_1(const char *sender, pj_status_t status,
 
257
                         const char *title_fmt, ...)
 
258
{
 
259
    va_list marker;
 
260
    va_start(marker, title_fmt);
 
261
    pj_perror_imp(1, sender, status, title_fmt, marker);
 
262
    va_end(marker);
 
263
}
 
264
 
 
265
#else /* #if PJ_LOG_MAX_LEVEL >= 1 */
 
266
PJ_DEF(void) pj_perror(int log_level, const char *sender, pj_status_t status,
 
267
                       const char *title_fmt, ...)
 
268
{
 
269
}
 
270
#endif  /* #if PJ_LOG_MAX_LEVEL >= 1 */
 
271
 
 
272
 
 
273
#if PJ_LOG_MAX_LEVEL >= 2
 
274
PJ_DEF(void) pj_perror_2(const char *sender, pj_status_t status,
 
275
                         const char *title_fmt, ...)
 
276
{
 
277
    va_list marker;
 
278
    va_start(marker, title_fmt);
 
279
    pj_perror_imp(2, sender, status, title_fmt, marker);
 
280
    va_end(marker);
 
281
}
 
282
#endif
 
283
 
 
284
#if PJ_LOG_MAX_LEVEL >= 3
 
285
PJ_DEF(void) pj_perror_3(const char *sender, pj_status_t status,
 
286
                         const char *title_fmt, ...)
 
287
{
 
288
    va_list marker;
 
289
    va_start(marker, title_fmt);
 
290
    pj_perror_imp(3, sender, status, title_fmt, marker);
 
291
    va_end(marker);
 
292
}
 
293
#endif
 
294
 
 
295
#if PJ_LOG_MAX_LEVEL >= 4
 
296
PJ_DEF(void) pj_perror_4(const char *sender, pj_status_t status,
 
297
                         const char *title_fmt, ...)
 
298
{
 
299
    va_list marker;
 
300
    va_start(marker, title_fmt);
 
301
    pj_perror_imp(4, sender, status, title_fmt, marker);
 
302
    va_end(marker);
 
303
}
 
304
#endif
 
305
 
 
306
#if PJ_LOG_MAX_LEVEL >= 5
 
307
PJ_DEF(void) pj_perror_5(const char *sender, pj_status_t status,
 
308
                         const char *title_fmt, ...)
 
309
{
 
310
    va_list marker;
 
311
    va_start(marker, title_fmt);
 
312
    pj_perror_imp(5, sender, status, title_fmt, marker);
 
313
    va_end(marker);
 
314
}
 
315
#endif
 
316
 
 
317
#if PJ_LOG_MAX_LEVEL >= 6
 
318
PJ_DEF(void) pj_perror_6(const char *sender, pj_status_t status,
 
319
                         const char *title_fmt, ...)
 
320
{
 
321
    va_list marker;
 
322
    va_start(marker, title_fmt);
 
323
    pj_perror_imp(6, sender, status, title_fmt, marker);
 
324
    va_end(marker);
 
325
}
 
326
#endif
 
327