/* ** L2 - OSSP Logging Library ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP L2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/l2/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** l2_channel.c: channel handling ** */ #include "l2.h" #include "l2_p.h" #include l2_channel_t *l2_channel_create(l2_handler_t *h) { l2_channel_t *ch; if (h == NULL) return NULL; if ((ch = (l2_channel_t *)malloc(sizeof(l2_channel_t))) == NULL) return NULL; ch->state = L2_CHSTATE_CREATED; ch->downstream = NULL; memset(&ch->context, 0, sizeof(l2_context_t)); memcpy(&ch->handler, h, sizeof(l2_handler_t)); if (ch->handler.create(&ch->context, ch) == L2_ERROR) { free(ch); return NULL; } return ch; } l2_result_t l2_channel_configure(l2_channel_t *ch, const char *fmt, ...) { l2_result_t rv; va_list ap; if (ch == NULL || fmt == NULL) return L2_ERROR; if (ch->state != L2_CHSTATE_CREATED) return L2_ERROR; va_start(ap, fmt); rv = ch->handler.configure(&ch->context, ch, fmt, ap); va_end(ap); return rv; } l2_result_t l2_channel_open(l2_channel_t *ch) { l2_result_t rv; if (ch == NULL) return L2_ERROR; if (ch->state != L2_CHSTATE_CREATED) return L2_ERROR; while (ch != NULL && ch->handler.open == NULL) { ch->state = L2_CHSTATE_OPENED; ch = ch->downstream; } if (ch == NULL) return L2_ERROR; rv = ch->handler.open(&ch->context, ch); if (rv == L2_OK) ch->state = L2_CHSTATE_OPENED; return rv; } l2_result_t l2_channel_write(l2_channel_t *ch, const char *buf, size_t bufsize) { l2_result_t rv; if (ch == NULL) return L2_ERROR; if (ch->state != L2_CHSTATE_OPENED) return L2_ERROR; if (buf == NULL) return L2_ERROR; if (bufsize == 0) return L2_OK; while (ch != NULL && ch->handler.write == NULL) ch = ch->downstream; if (ch == NULL) return L2_ERROR; rv = ch->handler.write(&ch->context, ch, buf, bufsize); return rv; } l2_result_t l2_channel_flush(l2_channel_t *ch) { l2_result_t rv; if (ch == NULL) return L2_ERROR; if (ch->state != L2_CHSTATE_OPENED) return L2_ERROR; while (ch != NULL && ch->handler.flush == NULL) ch = ch->downstream; if (ch == NULL) return L2_ERROR; rv = ch->handler.flush(&ch->context, ch); return rv; } l2_result_t l2_channel_close(l2_channel_t *ch) { l2_result_t rv; if (ch == NULL) return L2_ERROR; if (ch->state != L2_CHSTATE_OPENED) return L2_ERROR; while (ch != NULL && ch->handler.close == NULL) { ch->state = L2_CHSTATE_CREATED; ch = ch->downstream; } if (ch == NULL) return L2_ERROR; rv = ch->handler.close(&ch->context, ch); if (rv == L2_OK) ch->state = L2_CHSTATE_CREATED; return rv; } l2_result_t l2_channel_destroy(l2_channel_t *ch) { l2_result_t rv; if (ch == NULL) return L2_ERROR; if (ch->state == L2_CHSTATE_OPENED) if ((rv = l2_channel_close(ch)) != L2_OK) return rv; while (ch != NULL && ch->handler.destroy == NULL) ch = ch->downstream; if (ch != NULL) rv = ch->handler.destroy(&ch->context, ch); else rv = L2_OK; free(ch); return rv; } l2_result_t l2_channel_stack(l2_channel_t *ch, l2_channel_t *chTop) { if (ch == NULL || chTop == NULL) return L2_ERROR; if ( ch->state != L2_CHSTATE_CREATED || chTop->state != L2_CHSTATE_CREATED) return L2_ERROR; if (chTop->handler.type != L2_CHANNEL_FILTER) return L2_ERROR; chTop->downstream = ch; return L2_OK; } l2_channel_t *l2_channel_downstream(l2_channel_t *ch) { if (ch == NULL) return NULL; return ch->downstream; } l2_chtype_t l2_channel_type(l2_channel_t *ch) { if (ch == NULL) return NULL; return ch->handler.type; }