head 1.40; access; symbols L2_0_9_13:1.40 FSL_1_7_0:1.40 L2_0_9_12:1.40 LMTP2NNTP_1_4_1:1.40 LMTP2NNTP_1_4_0:1.40 FSL_1_6_1:1.40 L2_0_9_11:1.40 FSL_1_6_0:1.39 FSL_1_6b2:1.39 L2_0_9_10:1.39 FSL_1_6b1:1.39 L2_0_9_9:1.39 LMTP2NNTP_1_3_0:1.38 LMTP2NNTP_1_3b2:1.38 LMTP2NNTP_1_3b1:1.38 LMTP2NNTP_1_3a3:1.38 FSL_1_5_0:1.38 LMTP2NNTP_1_3a2:1.38 FSL_1_5a3:1.38 LMTP2NNTP_1_3a1:1.38 FSL_1_5a2:1.38 L2_0_9_8:1.38 FSL_1_5a1:1.38 L2_0_9_7:1.38 L2_0_9_6:1.38 FSL_1_4_0:1.38 FSL_1_4b1:1.38 L2_0_9_5:1.38 FSL_1_4a1:1.38 FSL_1_3_0:1.38 FSL_1_3b1:1.38 L2_0_9_4:1.38 FSL_1_2_1:1.38 L2_0_9_3:1.38 FSL_1_2_0:1.38 L2_0_9_2:1.38 FSL_1_1_0:1.38 FSL_1_1b1:1.38 WORKOFF:1.38.0.2 WORKOFF_BP:1.38 FSL_1_0_8:1.38 LMTP2NNTP_1_2_0:1.38 LMTP2NNTP_1_2b4:1.38 LMTP2NNTP_1_2b3:1.38 LMTP2NNTP_1_2b2:1.38 LMTP2NNTP_1_2b1:1.38 LMTP2NNTP_1_2a8:1.38 LMTP2NNTP_1_2a7:1.38 FSL_1_0_7:1.38 FSL_1_0_6:1.37 FSL_1_0_5:1.36 FSL_1_0_4:1.36 L2_0_9_1:1.36 FSL_1_0_3:1.36 LMTP2NNTP_1_2a6:1.36 FSL_1_0_2:1.36 FSL_1_0_1:1.36 FSL_1_0_0:1.36 FSL_0_9_0:1.36 L2_0_9_0:1.36 FSL_0_1_12:1.35 FSL_0_1_11:1.35 FSL_0_1_10:1.35 FSL_0_1_9:1.35 FSL_0_1_8:1.35 FSL_0_1_7:1.35 FSL_0_1_6:1.35 FSL_0_1_5:1.35 FSL_0_1_1:1.35 LMTP2NNTP_1_2a5:1.35 LMTP2NNTP_1_2a4:1.35 LMTP2NNTP_1_2a3:1.35 LMTP2NNTP_1_2a1:1.34 LMTP2NNTP_1_1_1:1.30 LMTP2NNTP_1_1_0:1.30 LMTP2NNTP_1_1b4:1.30 LMTP2NNTP_1_1b3:1.30 L2_CHANNEL_ONLY_REVAMPING_BEFORE:1.32 LMTP2NNTP_1_1b2:1.30 LMTP2NNTP_1_1b1:1.30 L2_0_1_0:1.26 START_MICHAEL:1.4 L2_INITIAL:1.1.1.1 OSSP:1.1.1; locks; strict; comment @ * @; 1.40 date 2005.10.03.08.08.11; author rse; state Exp; branches; next 1.39; 1.39 date 2005.01.24.15.03.17; author rse; state Exp; branches; next 1.38; 1.38 date 2003.01.06.11.41.51; author rse; state Exp; branches; next 1.37; 1.37 date 2002.11.09.14.44.31; author rse; state Exp; branches; next 1.36; 1.36 date 2002.07.30.19.08.25; author rse; state Exp; branches; next 1.35; 1.35 date 2002.01.02.17.07.38; author rse; state Exp; branches; next 1.34; 1.34 date 2001.11.07.13.05.20; author rse; state Exp; branches; next 1.33; 1.33 date 2001.11.07.11.37.18; author rse; state Exp; branches; next 1.32; 1.32 date 2001.11.03.20.49.25; author rse; state Exp; branches; next 1.31; 1.31 date 2001.11.02.18.42.51; author ms; state Exp; branches; next 1.30; 1.30 date 2001.10.04.13.35.47; author ms; state Exp; branches; next 1.29; 1.29 date 2001.09.26.08.55.19; author ms; state Exp; branches; next 1.28; 1.28 date 2001.09.13.19.18.34; author rse; state Exp; branches; next 1.27; 1.27 date 2001.09.13.16.19.06; author ms; state Exp; branches; next 1.26; 1.26 date 2001.09.13.12.19.45; author thl; state Exp; branches; next 1.25; 1.25 date 2001.09.12.09.42.34; author ms; state Exp; branches; next 1.24; 1.24 date 2001.09.11.10.37.04; author thl; state Exp; branches; next 1.23; 1.23 date 2001.09.10.14.32.57; author ms; state Exp; branches; next 1.22; 1.22 date 2001.09.10.06.43.10; author ms; state Exp; branches; next 1.21; 1.21 date 2001.09.10.06.41.59; author thl; state Exp; branches; next 1.20; 1.20 date 2001.09.07.13.03.07; author ms; state Exp; branches; next 1.19; 1.19 date 2001.09.07.10.23.31; author ms; state Exp; branches; next 1.18; 1.18 date 2001.09.06.19.28.24; author ms; state Exp; branches; next 1.17; 1.17 date 2001.09.06.16.14.54; author rse; state Exp; branches; next 1.16; 1.16 date 2001.09.06.16.10.05; author rse; state Exp; branches; next 1.15; 1.15 date 2001.09.06.14.43.25; author rse; state Exp; branches; next 1.14; 1.14 date 2001.09.06.14.37.53; author rse; state Exp; branches; next 1.13; 1.13 date 2001.09.05.16.15.38; author ms; state Exp; branches; next 1.12; 1.12 date 2001.09.05.07.47.12; author rse; state Exp; branches; next 1.11; 1.11 date 2001.09.04.19.34.33; author ms; state Exp; branches; next 1.10; 1.10 date 2001.09.04.19.18.49; author rse; state Exp; branches; next 1.9; 1.9 date 2001.09.04.15.44.48; author rse; state Exp; branches; next 1.8; 1.8 date 2001.09.04.15.41.17; author rse; state Exp; branches; next 1.7; 1.7 date 2001.09.04.13.52.59; author rse; state Exp; branches; next 1.6; 1.6 date 2001.09.02.14.38.51; author ms; state Exp; branches; next 1.5; 1.5 date 2001.08.26.13.07.27; author ms; state Exp; branches; next 1.4; 1.4 date 2001.08.15.10.36.03; author rse; state Exp; branches; next 1.3; 1.3 date 2001.05.26.08.02.55; author rse; state Exp; branches; next 1.2; 1.2 date 2001.05.11.17.07.52; author rse; state Exp; branches; next 1.1; 1.1 date 2001.05.10.19.46.01; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.05.10.19.46.01; author rse; state Exp; branches; next ; desc @@ 1.40 log @Adjust copyright messages for new year 2005. @ text @/* ** OSSP l2 - Flexible Logging ** Copyright (c) 2001-2005 Cable & Wireless ** Copyright (c) 2001-2005 The OSSP Project ** Copyright (c) 2001-2005 Ralf S. Engelschall ** ** This file is part of OSSP l2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/lib/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_ch_socket.c: socket channel implementation */ #include #include #include #include #include #include #include #include "l2.h" #include "l2_p.h" /* declare private channel configuration */ typedef struct { char *szProto; char *szHost; char *szPort; long nTimeout; sa_addr_t *saaRemote; sa_t *saRemote; } l2_ch_socket_t; /* create channel */ static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_socket_t *cfg = NULL; /* allocate private channel configuration */ if ((cfg = (l2_ch_socket_t *)malloc(sizeof(l2_ch_socket_t))) == NULL) return L2_ERR_MEM; /* initialize configuration with reasonable defaults */ cfg->szProto = strdup("tcp"); cfg->szHost = NULL; cfg->szPort = NULL; cfg->nTimeout = 30; cfg->saaRemote = NULL; cfg->saRemote = NULL; /* link private channel configuration into channel context */ ctx->vp = cfg; return L2_OK; } /* configure channel */ static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap) { l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; l2_param_t pa[5]; l2_result_t rv; l2_env_t *env; /* feed and call generic parameter parsing engine */ L2_PARAM_SET(pa[0], proto, STR, &cfg->szProto); L2_PARAM_SET(pa[1], host, STR, &cfg->szHost); L2_PARAM_SET(pa[2], port, STR, &cfg->szPort); L2_PARAM_SET(pa[3], timeout, INT, &cfg->nTimeout); L2_PARAM_END(pa[4]); l2_channel_env(ch, &env); rv = l2_util_setparams(env, pa, fmt, ap); /* sanity check configuration parameters */ if ( cfg->szProto != NULL && !( strcmp(cfg->szProto, "udp") == 0 || strcmp(cfg->szProto, "tcp") == 0)) return L2_ERR_ARG; return rv; } /* open channel */ static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; sa_rc_t rc; /* make sure a path was set */ if (cfg->szHost == NULL || cfg->szPort == NULL) return L2_ERR_USE; /* create socket address */ if ((rc = sa_addr_create(&cfg->saaRemote)) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); if ((rc = sa_addr_u2a(cfg->saaRemote, "inet://%s:%s", cfg->szHost, cfg->szPort)) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); /* create socket */ if ((rc = sa_create(&cfg->saRemote)) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); /* configure socket parameters */ sa_timeout(cfg->saRemote, SA_TIMEOUT_ALL, cfg->nTimeout, 0); if (strcmp(cfg->szProto, "tcp") == 0) { sa_buffer(cfg->saRemote, SA_BUFFER_READ, 4096); sa_buffer(cfg->saRemote, SA_BUFFER_WRITE, 4096); } return L2_OK; } /* write to channel */ static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, l2_level_t level, const char *buf, size_t buf_size) { l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; size_t sizeWrite; size_t sizeRemain; sa_rc_t rc; /* establish connection to server (TCP only) */ if (strcmp(cfg->szProto, "tcp") == 0) { if ((rc = sa_connect(cfg->saRemote, cfg->saaRemote)) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); } /* write message to channel socket, but check to make sure that the whole message was successfully written */ sizeWrite = 0; sizeRemain = buf_size; while (sizeRemain > 0) { if (strcmp(cfg->szProto, "tcp") == 0) rc = sa_write(cfg->saRemote, buf, sizeRemain, &sizeWrite); else rc = sa_send(cfg->saRemote, cfg->saaRemote, buf, sizeRemain, &sizeWrite); if (rc != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); sizeRemain = sizeRemain - sizeWrite; /* how much is left? */ } /* shutdown connection to server (TCP only) */ if (strcmp(cfg->szProto, "tcp") == 0) { if ((rc = sa_shutdown(cfg->saRemote, "rw")) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); } return L2_OK; } /* close channel */ static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; /* destroy remote address */ if (cfg->saRemote != NULL) { sa_destroy(cfg->saRemote); cfg->saRemote = NULL; } if (cfg->saaRemote != NULL) { sa_addr_destroy(cfg->saaRemote); cfg->saaRemote = NULL; } return L2_OK; } /* destroy channel */ static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; /* destroy channel configuration */ if (cfg->szProto != NULL) free(cfg->szProto); if (cfg->szHost != NULL) free(cfg->szHost); if (cfg->szPort != NULL) free(cfg->szPort); free(cfg); return L2_OK; } /* exported channel handler structure */ l2_handler_t l2_handler_socket = { "socket", L2_CHANNEL_OUTPUT, hook_create, hook_configure, hook_open, hook_write, NULL, hook_close, hook_destroy }; @ 1.39 log @Adjust copyright messages for new year 2005. @ text @d3 3 a5 3 ** Copyright (c) 2001-2004 Cable & Wireless ** Copyright (c) 2001-2004 The OSSP Project ** Copyright (c) 2001-2004 Ralf S. Engelschall @ 1.38 log @- remove trailing whitespaces - adjust copyright messages - consistently use "OSSP l2" - consistently talk about "Flexible Logging" - use standard OSSP ASCII-art @ text @d3 3 a5 3 ** Copyright (c) 2001-2003 Cable & Wireless Deutschland GmbH ** Copyright (c) 2001-2003 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2003 Ralf S. Engelschall @ 1.37 log @Upgrade to OSSP sa 1.0.1 @ text @d2 4 a5 3 ** OSSP l2 - Logging Library ** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) d7 1 a7 1 ** This file is part of OSSP L2, a flexible logging library which d47 1 a47 1 long nTimeout; d147 1 a147 1 /* write message to channel socket, but check to make @ 1.36 log @polish for release @ text @d154 1 a154 1 rc = sa_send(cfg->saRemote, buf, sizeRemain, &sizeWrite, cfg->saaRemote); @ 1.35 log @bump copyright year @ text @d2 1 a2 1 ** L2 - OSSP Logging Library d7 1 a7 1 ** can be found at http://www.ossp.org/pkg/l2/. @ 1.34 log @Hell, I've seldom seen that it is needed to prepare and adjust such a lot of subtle details of existing code in order to make a new feature implementable in a straight-forward way. Anyway, here comes one more preparation change for the forthcoming channel tree specification parser: - change l2_util_setparam() to take an l2_env_t parameter which allows the function to report better error messages. - completely rewrite l2_util_setparam() to support calls l2_channel_configure(ch, "n1=v1,n2=v2,n3=v3") and/or l2_channel_configure(ch, "n1=%x,n2=%x,n3=%x", v1, v2, v3) instead of l2_channel_configure(ch, "n1,n2,n3", v1, v2, v3) This is both a step forward to make the interface of l2_channel_configure() more flexible (because one now can directly inline values instead of having them to be passed explicitly) and allows the spec parser not having to know the type (integer, floating point or string) of a parameter (which is important if one wants the parser to be independent of the implementing channel handlers). @ text @d3 2 a4 2 ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.33 log @More preparations for forthcoming channel tree specification parser (especially to allow the parser to determine the handler structure from a handler name without introducing another and this way redundant sub-API): - add "char *name" to l2_handler_t in order to tag each handler structure with the corresponding channel name - add l2_env_handler() function to add handler to l2_env_t objects. All l2_handler_xxxx are automatically pre-configured there after l2_env_create(). - change l2_channel_create() to take a "const char *name" (handler name) instead of the "l2_handler_t *h" (handler pointer) to make the stuff consistent and more clear. - adjust l2_test.c to reflect the changes. @ text @d80 1 d83 4 a86 4 L2_PARAM_SET(pa[0], proto, STRING, &cfg->szProto); L2_PARAM_SET(pa[1], host, STRING, &cfg->szHost); L2_PARAM_SET(pa[2], port, STRING, &cfg->szPort); L2_PARAM_SET(pa[3], timeout, INT, &cfg->nTimeout); d88 2 a89 1 rv = l2_util_setparams(pa, fmt, ap); @ 1.32 log @- change protocol parameter from "IPPROTO_XXX" to just "xxx" - add support for numerical and textual ports - add UDP support - remove unused iSocket variable - fix massive memory leaks on channel destruction - generally simplify implementation - cleanup coding style @ text @d204 1 @ 1.31 log @Partially rewrote the socket channel to use the OSSP socket abstraction library. Channel still needs UDP configuration and writing logic. @ text @a40 3 #define L2_SOCKET_SABUFREAD 4096 #define L2_SOCKET_SABUFWRITE 4096 d43 6 a48 8 sa_addr_t *saaServer; sa_t *saServer; long lTimeout; char *szHost; /* IP Address or name of host to connect to */ int iProto; /* Protocol to use, IPPROTO_TCP or IPPROTO_UDP */ int iPort; /* TCP Port to connect to */ int iSocket; /* Socket descriptor used during writing */ d61 6 a66 8 cfg->saaServer = NULL; cfg->saServer = NULL; cfg->lTimeout = 30; cfg->szHost = NULL; cfg->iProto = -1; cfg->iPort = 0; cfg->iSocket = -1; a77 1 char *szProtocol = NULL; d82 4 a85 4 L2_PARAM_SET(pa[0], protocol, STRING, &szProtocol); L2_PARAM_SET(pa[1], timeout, INT, &cfg->lTimeout); L2_PARAM_SET(pa[2], host, CHARPTR, &cfg->szHost); L2_PARAM_SET(pa[3], port, INT, &cfg->iPort); d89 5 a93 9 /* translate incoming configuration parameters */ if (szProtocol != NULL) { if (strcmp(szProtocol, "IPPROTO_UDP") == 0) cfg->iProto = IPPROTO_UDP; else if (strcmp(szProtocol, "IPPROTO_TCP") == 0) cfg->iProto = IPPROTO_TCP; else return L2_ERR_ARG; } a94 1 free(szProtocol); d101 1 a102 1 l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; d105 1 a105 1 if (cfg->szHost == NULL) d109 1 a109 1 if ((rc = sa_addr_create(&cfg->saaServer)) != SA_OK) d111 2 a112 2 if ((rc = sa_addr_u2a(cfg->saaServer, "inet://%s:%d", cfg->szHost, cfg->iPort)) != SA_OK) d116 1 a116 1 if ((rc = sa_create(&cfg->saServer)) != SA_OK) d120 5 a124 3 sa_timeout(cfg->saServer, SA_TIMEOUT_ALL, cfg->lTimeout, 0); sa_buffer (cfg->saServer, SA_BUFFER_READ, L2_SOCKET_SABUFREAD); sa_buffer (cfg->saServer, SA_BUFFER_WRITE, L2_SOCKET_SABUFWRITE); d134 22 a155 15 size_t sizeWrite; size_t sizeRemain; sa_t *sa; sa_rc_t rc; sa_addr_t *saa; /* parameter checks */ assert(cfg->saServer != NULL); /* establish connection to server */ saa = cfg->saaServer; sa = cfg->saServer; if ((rc = sa_connect(sa, saa)) != SA_OK) { sa_shutdown(sa, "rw"); /* shutdown connection to server */ return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); d158 4 a161 10 if (cfg->iProto == IPPROTO_TCP) { /* write message to channel socket, but check to make */ /* sure that the whole message was successfully written */ sizeWrite = 0; sizeRemain = buf_size; while(sizeRemain) { if ((rc = sa_write(sa, buf, sizeRemain, &sizeWrite)) != SA_OK) return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT); sizeRemain = sizeRemain - sizeWrite; /* how much is left? */ } a171 3 /* parameter checks */ /* FIXME! assert(cfg->saServer->fdSocket != -1); */ d173 7 a179 7 if (cfg->saServer != NULL) { sa_destroy(cfg->saServer); cfg->saServer = NULL; } if (cfg->saaServer != NULL) { sa_addr_destroy(cfg->saaServer); cfg->saaServer = NULL; d191 6 @ 1.30 log @More socket channel configuration parameter adjustments. @ text @d41 2 a42 46 #if defined(HAVE_INET_PTON) #define l2_inet_pton inet_pton #elif defined(HAVE_INET_ATON) /****************************************************************** IPv4 source used from Unix Network Programming by Richard STEVENS ******************************************************************/ static int l2_inet_pton(int iFamily, const char *szAddress, void *pvMemref) { int i = 0; struct in_addr IP4Addr; struct in6_addr IP6Addr; const char *szIndex = NULL; /* To index IPv6 validity */ char *szNextfield = ""; /* For IPv6 address trans */ assert(pvMemref != NULL); if (iFamily == AF_INET) { if (inet_aton(szAddress, &IP4Addr)) { memcpy(pvMemref, &IP4Addr, sizeof(struct in_addr)); return 1; /* Success */ } return 0; } else if (iFamily == AF_INET6) { /* Translate IPv6 addresses */ szIndex = szAddress; /* Initialize, verify in loop */ for (i = 0; (i < 8) && szNextfield; i++) { /* Iterate through fields */ IP6Addr.__u6_addr.__u6_addr16[i] =\ ntohs((u_int16_t)strtol(szIndex, &szNextfield, 16)); szIndex = szNextfield + 1; } if ((i != 8) || (*szNextfield)) return 0; else { /* Success */ memcpy(pvMemref, &IP6Addr, sizeof(struct in6_addr)); return 1; } } else { /* User converting from an address family that we don't support */ errno = EAFNOSUPPORT; return -1; } } #else #error "neither inet_pton nor inet_aton available" #endif d46 4 a50 1 int iFamily; /* IP version to use, AF_INET4 or AF_INET6 */ d66 4 a70 1 cfg->iFamily = -1; a85 1 char *szFamily = NULL; d90 2 a91 2 L2_PARAM_SET(pa[0], ipversion, STRING, szFamily); L2_PARAM_SET(pa[1], protocol, STRING, szProtocol); a97 9 if (szFamily != NULL) { if (strcmp(szFamily, "AF_INET6") == 0) cfg->iFamily = AF_INET6; else if (strcmp(szFamily, "AF_INET") == 0) cfg->iFamily = AF_INET; else return L2_ERR_ARG; } a106 1 free(szFamily); d114 2 a115 4 l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; struct hostent *pHostentry; struct sockaddr_in IP4Localsock, IP4Sockaddr; struct sockaddr_in6 IP6Localsock, IP6Sockaddr; d117 1 a117 1 /* make sure a target is configured */ d121 15 a135 24 /* open channel socket */ if (cfg->iFamily == AF_INET) { /* IPv4 */ /* initialize address structures */ memset(&IP4Localsock, 0, sizeof(IP4Localsock)); memset(&IP4Sockaddr, 0, sizeof(IP4Sockaddr)); /* resolve host numerically */ if (l2_inet_pton(AF_INET, cfg->szHost, &IP4Sockaddr.sin_addr.s_addr) == 1) { IP4Sockaddr.sin_family = AF_INET; IP4Sockaddr.sin_port = htons(cfg->iPort); } /* resolve host nominally */ else if ((pHostentry = gethostbyname(cfg->szHost)) != NULL) { if (pHostentry->h_addrtype == AF_INET) { IP4Sockaddr.sin_family = AF_INET; IP4Sockaddr.sin_port = htons(cfg->iPort); memcpy(&IP4Sockaddr.sin_addr.s_addr, pHostentry->h_addr_list[0], sizeof(IP4Sockaddr.sin_addr.s_addr)); } else return L2_ERR_USE; /* what?? we specify IPv4 when it is not? */ } else /* host string was not parsable for some reason */ return L2_ERR_SYS; d137 1 a137 100 if (cfg->iProto == IPPROTO_TCP) { /* with TCP we must connect */ if ((cfg->iSocket = socket(PF_INET, SOCK_STREAM, cfg->iProto)) == -1) return L2_ERR_SYS; /* if we have a socket, then bind ourselves to any port number */ IP4Localsock.sin_family = AF_INET; IP4Localsock.sin_addr.s_addr = htonl(INADDR_ANY); IP4Localsock.sin_port = htons(0); if (bind(cfg->iSocket, (struct sockaddr *)&IP4Localsock,\ sizeof(IP4Localsock))) { return L2_ERR_SYS; } if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr))) { close(cfg->iSocket); return L2_ERR_SYS; } } else if (cfg->iProto == IPPROTO_UDP) { /* with UDP we do not connect */ if ((cfg->iSocket = socket(PF_INET, SOCK_DGRAM, cfg->iProto)) == -1) return L2_ERR_SYS; /* if we have a socket, then bind ourselves to any port number */ IP4Localsock.sin_family = AF_INET; IP4Localsock.sin_addr.s_addr = htonl(INADDR_ANY); IP4Localsock.sin_port = htons(0); if (bind(cfg->iSocket, (struct sockaddr *)&IP4Localsock,\ sizeof(IP4Localsock))) { return L2_ERR_SYS; } } return L2_OK; } else if (cfg->iFamily == AF_INET6) { /* IPv6 */ /* initialize address structures */ memset(&IP6Localsock, 0, sizeof(IP6Localsock)); memset(&IP6Sockaddr, 0, sizeof(IP6Sockaddr)); /* resolve host numerically */ if (l2_inet_pton(AF_INET6, cfg->szHost, &IP6Sockaddr.sin6_addr.s6_addr) == 1) { IP6Sockaddr.sin6_family = AF_INET6; IP6Sockaddr.sin6_port = htons(cfg->iPort); } /* resolve host nominally */ else if ((pHostentry = gethostbyname(cfg->szHost)) != NULL) { if (pHostentry->h_addrtype == AF_INET6) { IP6Sockaddr.sin6_family = AF_INET6; IP6Sockaddr.sin6_port = htons(cfg->iPort); memcpy(&IP6Sockaddr.sin6_addr.s6_addr, pHostentry->h_addr_list[0],\ sizeof(IP6Sockaddr.sin6_addr.s6_addr)); } else return L2_ERR_USE; /* what?? we specify IPv6 when it is not? */ } else /* host string was not parsable for some reason */ return L2_ERR_SYS; if (cfg->iProto == IPPROTO_TCP) { /* with TCP we must connect */ if ((cfg->iSocket = socket(PF_INET6, SOCK_STREAM, cfg->iProto)) == -1) return L2_ERR_SYS; /* if we have a socket, then bind ourselves to any port number */ IP6Localsock.sin6_family = AF_INET6; IP6Localsock.sin6_addr = in6addr_any; IP6Localsock.sin6_port = htons(0); if (bind(cfg->iSocket, (struct sockaddr *)&IP6Localsock,\ sizeof(IP6Localsock))) { return L2_ERR_SYS; } if (connect(cfg->iSocket, (struct sockaddr *)&IP6Sockaddr,\ sizeof(IP6Sockaddr))) { close(cfg->iSocket); return L2_ERR_SYS; } } else if (cfg->iProto == IPPROTO_UDP) { /* with UDP we do not connect */ if ((cfg->iSocket = socket(PF_INET, SOCK_DGRAM, cfg->iProto)) == -1) return L2_ERR_SYS; /* if we have a socket, then bind ourselves to any port number */ IP6Localsock.sin6_family = AF_INET6; IP6Localsock.sin6_addr = in6addr_any; IP6Localsock.sin6_port = htons(0); if (bind(cfg->iSocket, (struct sockaddr *)&IP6Localsock,\ sizeof(IP6Localsock))) { return L2_ERR_SYS; } } return L2_OK; } return L2_ERR_USE; d144 6 a149 4 struct sockaddr_in IP4Sockaddr, IP6Sockaddr; l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; size_t sizeWrite; size_t sizeRemain; d152 9 a160 2 if (cfg->iSocket == -1) return L2_ERR_ARG; d168 2 a169 1 sizeWrite = send(cfg->iSocket, buf + sizeWrite, sizeRemain, 0); a170 31 if (sizeWrite == -1) return L2_ERR_SYS; } } else if (cfg->iProto == IPPROTO_UDP) { /* write message to the host target, but check to make */ /* sure that the whole message was successfully written */ sizeWrite = 0; sizeRemain = buf_size; while(sizeRemain) { if (cfg->iFamily == AF_INET) { /* IPv4 */ /* TODO !!! */ sizeWrite = sendto(cfg->iSocket, buf + sizeWrite, sizeRemain, 0,\ /* Fill in */ (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr)); /* the host */ /* address */ sizeRemain = sizeRemain - sizeWrite; /* how much is left? */ /* structs */ if (sizeWrite == -1) return L2_ERR_SYS; } else if (cfg->iFamily == AF_INET6) { /* IPv6 */ /* TODO !!! */ sizeWrite = sendto(cfg->iSocket, buf + sizeWrite, sizeRemain, 0,\ /* Fill in */ (struct sockaddr *)&IP6Sockaddr, sizeof(IP6Sockaddr)); /* the host */ /* address */ sizeRemain = sizeRemain - sizeWrite; /* how much is left? */ /* structs */ if (sizeWrite == -1) return L2_ERR_USE; } else /* Neither IPv4 nor IPv6 */ return L2_ERR_USE; d183 1 a183 2 if (cfg->iSocket == -1) return L2_ERR_USE; d185 9 a193 3 /* close channel socket */ if ((shutdown(cfg->iSocket, SHUT_RDWR)) || (close(cfg->iSocket))) return L2_ERR_SYS; @ 1.29 log @Cleanup before conversion to use sa_family socket calls. @ text @d123 2 d129 2 a130 2 L2_PARAM_SET(pa[0], ipversion, INT, &cfg->iFamily); L2_PARAM_SET(pa[1], protocol, INT, &cfg->iProto ); d132 1 a132 1 L2_PARAM_SET(pa[3], port, INT, &cfg->iPort ); d136 21 @ 1.28 log @use assert(3) instead of home-brewn stuff @ text @d48 1 a48 1 static int l2_inet_pton(int iFamily, const char *pszAddress, void *pvMemref) d50 1 a50 1 int i = 0; d53 2 a54 2 const char *pszIndex = NULL; /* To index IPv6 validity */ char *pszNextfield = ""; /* For IPv6 address trans */ d58 1 a58 1 if (inet_aton(pszAddress, &IP4Addr)) { d65 2 a66 2 pszIndex = pszAddress; /* Initialize, verify in loop */ for (i = 0; (i < 8) && pszNextfield; i++) { /* Iterate through fields */ d68 2 a69 2 ntohs((u_int16_t)strtol(pszIndex, &pszNextfield, 16)); pszIndex = pszNextfield + 1; d72 1 a72 1 if ((i != 8) || (*pszNextfield)) d90 1 a90 1 char *pszHost; /* IP Address or name of host to connect to */ d107 1 a107 1 cfg->pszHost = NULL; d129 1 a129 1 L2_PARAM_SET(pa[2], host, CHARPTR, &cfg->pszHost); d146 1 a146 1 if (cfg->pszHost == NULL) d156 1 a156 1 if (l2_inet_pton(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1) { d161 1 a161 1 else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL) { d217 1 a217 1 if (l2_inet_pton(AF_INET6, cfg->pszHost, &IP6Sockaddr.sin6_addr.s6_addr) == 1) { d222 1 a222 1 else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL) { @ 1.27 log @Added debug infrastructure, assertions, fixed one bug. @ text @d56 1 a56 1 ASSERT(pvMemref); @ 1.26 log @portability fixes for solaris @ text @d56 1 @ 1.25 log @Upgraded both stream and channel-level APIs to include new L2_LEVEL parameter design. @ text @d225 2 a226 2 memcpy(&IP6Sockaddr.sin6_addr.__u6_addr, pHostentry->h_addr_list[0],\ sizeof(IP6Sockaddr.sin6_addr.__u6_addr)); @ 1.24 log @add Dmalloc support to L2 @ text @d276 2 a277 2 static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, const char *buf, size_t buf_size) @ 1.23 log @Removed unused variables. @ text @d39 1 a39 1 #include "l2_config.h" @ 1.22 log @Bug fixes, cleanup, and removed makefile redundancies (see end.) @ text @a138 1 //FIXME int i; a142 1 //FIXME struct in6_addr *IP6Addr; @ 1.21 log @minor modifications for compile run to survive --pendantic-errors. Please review. @ text @d39 1 d41 3 a43 3 #define HAVE_INET_ATON #ifndef HAVE_INET_PTON #ifdef HAVE_INET_ATON d48 1 a48 1 static int inet_pton(int iFamily, const char *pszAddress, void *pvMemref) a85 1 #endif d157 1 a157 1 if (inet_pton(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1) { d218 1 a218 1 if (inet_pton(AF_INET6, cfg->pszHost, &IP6Sockaddr.sin6_addr.s6_addr) == 1) { @ 1.20 log @Bug fixes to both IPv4 and IPv6 socket binding. @ text @d52 2 a53 2 char *pszIndex = NULL; /* To index IPv6 validity */ char *pszNextfield = -1; /* For IPv6 address trans */ d139 1 a139 1 int i; d144 1 a144 1 struct in6_addr *IP6Addr; d223 1 a223 1 else if (pHostentry = gethostbyname(cfg->pszHost) != NULL) { @ 1.19 log @Cleaned up and KR styled. @ text @d142 2 a143 2 struct sockaddr_in IP4Sockaddr; struct sockaddr_in6 IP6Sockaddr; d152 4 d175 1 a175 1 if (cfg->iProto == IPPROTO_TCP) { /* With TCP we must connect */ d179 10 d195 1 a195 1 else if (cfg->iProto == IPPROTO_UDP) /* With UDP we do not connect */ d199 11 d213 4 d231 1 a231 1 return L2_ERR_USE; /* what?? we specify IPv6 when it is not? */ d233 1 a233 1 else /* host string was not parsable for some reason */ d236 1 a236 1 if (cfg->iProto == IPPROTO_TCP) { /* With TCP we must connect */ d240 10 d256 1 a256 1 else if (cfg->iProto == IPPROTO_UDP) /* With UDP we do not connect */ d259 11 @ 1.18 log @Redesigned IPv6 logic, added support for UDP. UDP write operation is still not working. @ text @d49 1 a49 1 int i = 0; d55 2 a56 4 if (iFamily == AF_INET) { if (inet_aton(pszAddress, &IP4Addr)) { d62 3 a64 6 else if (iFamily == AF_INET6) /* If we are translating IPv6 addresses */ { /* the user needs to use precise notation */ pszIndex = pszAddress; /* Initialize, verify in loop */ for (i = 0; (i < 8) && pszNextfield; i++) /* Iterate through fields */ { d72 1 a72 3 else /* Success */ { a75 1 d77 1 a77 3 else /* User converting from an address family that we don't support */ { a156 1 a167 1 d171 1 a171 2 if (cfg->iProto == IPPROTO_TCP) /* With TCP we must connect */ { d175 2 a176 2 if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr))) { a186 1 a192 1 a203 1 d240 1 a240 2 if (cfg->iProto == IPPROTO_TCP) { d245 1 a245 2 while(sizeRemain) { d253 1 a253 3 else if (cfg->iProto == IPPROTO_UDP) { d258 2 a259 4 while(sizeRemain) { if (cfg->iFamily == AF_INET) /* IPv4 */ { d268 1 a268 3 else if (cfg->iFamily == AF_INET6) /* IPv6 */ { a276 1 @ 1.17 log @Use plain K&R coding style. @ text @d53 1 a53 1 char *pszNextfield = NULL; /* For IPv6 address trans */ d60 1 a60 1 return 1; d67 2 a68 3 pszIndex = malloc(strlen(pszAddress)); strcpy(pszIndex, pszAddress); /* Initialize, verify in loop */ for (i = 0; i < 8; i++) /* Iterate through the IPv6 address fields */ d72 5 a76 5 if ((pszNextfield == '\0') ||\ ((pszNextfield - pszIndex) != (4 * sizeof(char)))) { return 0; /* User is supplying a IPv6 format we don't support */ } d78 4 a81 1 pszIndex = ++pszNextfield; a83 2 memcpy(pvMemref, &IP6Addr, sizeof(struct in6_addr)); return 1; d99 5 a103 4 int iFamily; /* IP version to use, AF_INET4 or AF_INET6 */ char *pszHost; /* IP Address or name of host to connect to */ int iPort; /* TCP Port to connect to */ int iSocket; /* Socket descriptor used during writing */ d117 2 d132 1 a132 1 l2_param_t pa[4]; d137 4 a140 3 L2_PARAM_SET(pa[1], host, CHARPTR, &cfg->pszHost); L2_PARAM_SET(pa[2], port, INT, &cfg->iPort); L2_PARAM_END(pa[3]); d149 4 a152 3 l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; struct hostent *pHostentry; struct sockaddr_in IP4Sockaddr; d154 1 a154 1 struct in6_addr *IP6Addr; d183 4 a186 2 if ((cfg->iSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) return L2_ERR_SYS; d188 5 a192 3 if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr))) { close(cfg->iSocket); return L2_ERR_SYS; d194 3 d198 1 a198 1 return L2_OK; /* we are connected */ d223 9 a231 6 if ((cfg->iSocket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1) return L2_ERR_SYS; if (connect(cfg->iSocket, (struct sockaddr *)&IP6Sockaddr, sizeof(IP6Sockaddr))) { close(cfg->iSocket); return L2_ERR_SYS; d233 3 d237 1 a237 1 return L2_OK; /* we are connected */ d247 4 a250 3 l2_ch_socket_t *cfg = (l2_ch_socket_t *)ctx->vp; size_t sizeWrite; size_t sizeRemain; d254 47 a300 1 return L2_ERR_USE; d302 3 a304 9 /* write message to channel socket, but check to make sure that the whole message was successfully written */ sizeWrite = 0; sizeRemain = buf_size; while (sizeRemain) { sizeWrite = send(cfg->iSocket, buf + sizeWrite, sizeRemain, 0); sizeRemain = sizeRemain - sizeWrite; if (sizeWrite == -1) return L2_ERR_SYS; @ 1.16 log @Simplify channels again: The channel framework gurranties that the handler context is available if the handler has set it, so there is no need to perform an additional run-time check and try to return L2_ERR_ARG. @ text @d98 1 a98 2 typedef struct { d146 2 a147 2 struct hostent *pHostentry; struct sockaddr_in IP4Sockaddr; d149 1 a149 1 struct in6_addr *IP6Addr; d155 2 a156 3 /* open channel socket */ if (cfg->iFamily == AF_INET) /* IPv4 */ { d158 1 a158 2 if (inet_pton(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1) { d164 2 a165 4 else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL) { if (pHostentry->h_addrtype == AF_INET) { d168 2 a169 2 memcpy(&IP4Sockaddr.sin_addr.s_addr, pHostentry->h_addr_list[0],\ sizeof(IP4Sockaddr.sin_addr.s_addr)); a170 1 d181 1 a181 2 if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr))) { d189 1 a189 2 else if (cfg->iFamily == AF_INET6) /* IPv6 */ { d191 1 a191 2 if (inet_pton(AF_INET6, cfg->pszHost, &IP6Sockaddr.sin6_addr.s6_addr) == 1) { d197 2 a198 4 else if (pHostentry = gethostbyname(cfg->pszHost) != NULL) { if (pHostentry->h_addrtype == AF_INET6) { a203 1 d214 1 a214 2 if (connect(cfg->iSocket, (struct sockaddr *)&IP6Sockaddr, sizeof(IP6Sockaddr))) { d230 2 a231 2 size_t sizeWrite; size_t sizeRemain; d237 2 a238 2 /* write message to channel socket, but check to make */ /* sure that the whole message was successfully written */ d241 1 a241 2 while(sizeRemain) { d243 1 a243 2 sizeRemain = sizeRemain - sizeWrite; /* how much is left? */ @ 1.15 log @It is fully legal to have some handler operations not implemented in case there is nothing to do for the handler. So remove the No-op hooks. @ text @d129 1 a129 1 l2_ch_socket_t *cfg; a132 4 /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERR_ARG; d146 1 a146 1 l2_ch_socket_t *cfg; d152 1 a152 3 /* parameter checks */ if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERR_ARG; d242 1 a242 1 l2_ch_socket_t *cfg; a246 2 if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERR_ARG; d269 1 a269 1 l2_ch_socket_t *cfg; a271 2 if ((cfg = (l2_ch_socket_t *)ctx->vp) == NULL) return L2_ERR_ARG; d285 1 a285 3 /* parameter checks */ if (ctx->vp == NULL) return L2_ERR_ARG; d288 1 a288 1 free(ctx->vp); @ 1.14 log @Replace generic L2_ERROR with more granular L2_ERR_XXX and make sure that we always check with "!= L2_OK". @ text @a273 8 /* flush channel */ static l2_result_t hook_flush(l2_context_t *ctx, l2_channel_t *ch) { /* NOP for this channel, because Unix I/O sockets are unbuffered! */ return L2_OK; } d312 1 a312 1 hook_flush, @ 1.13 log @Gethostbyname2() is not yet stable across platforms, and actually unnecessary in this case. @ text @d113 1 a113 1 return L2_ERROR; d135 1 a135 1 return L2_ERROR; d158 1 a158 1 return L2_ERROR; d160 1 a160 1 return L2_ERROR; d184 1 a184 1 return L2_ERROR; /* what?? we specify IPv4 when it is not? */ d188 1 a188 1 return L2_ERROR; d191 1 a191 1 return L2_ERROR; d196 1 a196 1 return L2_ERROR; d223 1 a223 1 return L2_ERROR; /* what?? we specify IPv6 when it is not? */ d227 1 a227 1 return L2_ERROR; d230 1 a230 1 return L2_ERROR; d235 1 a235 1 return L2_ERROR; d241 1 a241 1 return L2_ERROR; d254 1 a254 1 return L2_ERROR; d256 1 a256 1 return L2_ERROR; d268 1 a268 1 return L2_ERROR; d289 1 a289 1 return L2_ERROR; d291 1 a291 1 return L2_ERROR; d295 1 a295 1 return L2_ERROR; d305 1 a305 1 return L2_ERROR; @ 1.12 log @Be politically correct: channels are intended to be implemented also by users, which have only access to the public API (l2.h), so do not even try to use anything more in our own shipped channels. @ text @d42 5 a46 1 #ifdef HAVE_INET_ATON d212 1 a212 1 else if ((pHostentry = gethostbyname2(cfg->pszHost, AF_INET6)) != NULL) @ 1.11 log @Completed IPv4 and IPv6 implementations of configure, open, and write callbacks functions. @ text @d30 3 d36 1 a36 2 #include #include a38 1 #include "l2_p.h" @ 1.10 log @Be pedantically correct: handler hooks return "l2_result_t" and not "int", although currently it is just an int/enum. @ text @a32 1 #include d42 1 a42 2 /* !!! TODO change pton1 to pton !!! */ static int inet_pton1(int iFamily, const char *pszAddress, void *pvMemref) d47 2 a48 2 char *pszNextfield = NULL; /* For IPv6 address trans */ char **ppszVerify = &pszNextfield; /* To check IPv6 validity */ d60 5 a64 3 else if (iFamily == AF_INET6) { for (i = 0; i < 16; i++) /* Iterate through the IPv6 address fields */ d66 7 a72 4 ppszVerify = &pszNextfield; /* Reset and compare later to verify */ IP6Addr.__u6_addr.__u6_addr8[i] = (u_int8_t)strtol(pszAddress,\ &pszNextfield, 16); *pszNextfield++; /* !!! TODO Problema !!! */ d74 1 a74 2 if ((&pszNextfield - ppszVerify) != 2) return 0; /* User is supplying a IPv6 format we don't support */ d76 1 d95 1 d125 1 a125 1 l2_param_t pa[3]; d133 4 a136 3 L2_PARAM_SET(pa[0], host, CHARPTR, &cfg->pszHost); L2_PARAM_SET(pa[1], port, INT, &cfg->iPort); L2_PARAM_END(pa[2]); d149 1 d158 1 a158 9 /* resolve host numerically */ if (inet_pton1(AF_INET, cfg->pszHost, &IP4Sockaddr.sin_addr.s_addr) == 1) { IP4Sockaddr.sin_family = AF_INET; IP4Sockaddr.sin_port = htons(cfg->iPort); } /* resolve host nominally */ else if ((pHostentry = gethostbyname(cfg->pszHost)) != NULL) d160 2 a161 1 if (pHostentry->h_addrtype == AF_INET) a164 2 memcpy(&IP4Sockaddr.sin_addr.s_addr, pHostentry->h_addr_list[0],\ sizeof(IP4Sockaddr.sin_addr.s_addr)); d167 34 a200 1 else if (pHostentry->h_addrtype == AF_INET6) a203 2 memcpy(&IP6Sockaddr.sin6_addr.__u6_addr, pHostentry->h_addr_list[0],\ sizeof(IP6Sockaddr.sin6_addr.__u6_addr)); a204 1 } d206 26 a231 2 else return L2_ERROR; d233 1 a233 6 if ((cfg->iSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) return L2_ERROR; if (connect(cfg->iSocket, (struct sockaddr *)&IP4Sockaddr, sizeof(IP4Sockaddr))) { close(cfg->iSocket); return L2_ERROR; d236 1 a236 1 return L2_OK; d244 2 d253 12 a264 3 /* write message to channel socket */ if (send(cfg->iSocket, buf, buf_size, 0) == -1) return L2_ERROR; @ 1.9 log @Whohooo, now we can simplify output channels: because output channels are guarrantied to be not on top of other channels, they do not have any downstream channels. So remove all downstream handling from them. Only filter channels have to be aware of downstream channels. @ text @d98 1 a98 1 static int hook_create(l2_context_t *ctx, l2_channel_t *ch) d118 1 a118 1 static int hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap) d138 1 a138 1 static int hook_open(l2_context_t *ctx, l2_channel_t *ch) d194 1 a194 1 static int hook_write(l2_context_t *ctx, l2_channel_t *ch, d213 1 a213 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *ch) d221 1 a221 1 static int hook_close(l2_context_t *ctx, l2_channel_t *ch) d239 1 a239 1 static int hook_destroy(l2_context_t *ctx, l2_channel_t *ch) @ 1.8 log @Revamp channel handler API: Instead of passing the downstream channel to all channels we instead provide a l2_channel_downstream() function and provide the current channel. This way the handler API is prototype-wise fully orthogonal with the channel API (which it implements) and we no longer pass information to 2/3 of our (output) channels which is of no use there. Additionally add a channel type field to l2_handler_t which allows a handler to say what type of channel it implements (filter or output). This information is now used in l2_channel_stack() to make sure that one can only stack a filter channel on top of another channel. For convinience reasons there is also a new l2_channel_type() function which allows one to query the type of a particular channel. @ text @a143 1 l2_channel_t *downstream; a189 5 /* optionally open downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_open(downstream) == L2_ERROR) return L2_ERROR; a197 1 l2_channel_t *downstream; a208 5 /* optionally write to downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_write(downstream, buf, buf_size) == L2_ERROR) return L2_ERROR; a214 2 l2_channel_t *downstream; a216 5 /* optionally flush downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_flush(downstream) == L2_ERROR) return L2_ERROR; a223 6 l2_channel_t *downstream; /* optionally close downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_close(downstream) == L2_ERROR) return L2_ERROR; @ 1.7 log @Wohhooooo! Here comes the underlying message formatting support: 1. renamed l2_channel_setparam() to l2_util_setparam() because it is just a utility function and is not tied to any channel. 2. moved l2_util_setparam() to its own l2_ut_param.c source file. 3. added l2_ut_format.c which contains a slightly adjusted version of Str's str_format() stuff under the name l2_util_format(). 4. use l2_util_format() in l2_stream.c instead of vsnprintf() and this way finally support l2_formatter_t callbacks. 5. cleanup adjustments to the l2_stream_formatter() API. Let's rock... @ text @d98 1 a98 1 static int hook_create(l2_context_t *ctx) d118 1 a118 1 static int hook_configure(l2_context_t *ctx, const char *fmt, va_list ap) d138 1 a138 1 static int hook_open(l2_context_t *ctx, l2_channel_t *downstream) d144 1 d192 1 a192 1 if (downstream != NULL) d200 1 a200 1 static int hook_write(l2_context_t *ctx, l2_channel_t *downstream, d204 1 d217 1 a217 1 if (downstream != NULL) d225 1 a225 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *downstream) d227 2 d232 1 a232 1 if (downstream != NULL) d240 1 a240 1 static int hook_close(l2_context_t *ctx, l2_channel_t *downstream) d243 1 d246 1 a246 1 if (downstream != NULL) d264 1 a264 1 static int hook_destroy(l2_context_t *ctx) d278 1 @ 1.6 log @Basic architecture and functionality additions. @ text @d132 1 a132 1 rv = l2_channel_setparams(pa, fmt, ap); @ 1.5 log @Wrote the l2_ch_socket_t class, and its create and configure methods. @ text @d30 7 d40 48 a87 3 #include #include #include d90 5 a94 6 typedef struct { int iSocket; /* Socket descriptor */ int iDomain; /* Hardcoded to support only IPv4 and IPv6 */ int iProtocol; /* Hardcoded to support only IPv4 and IPv6 */ int iType; /* Hardcoded for writing streams to iSocket */ struct sockaddr *pAddr; /* Where do we open a socket? */ d100 1 a100 1 l2_ch_socket_t *cfg; d107 3 a109 5 cfg->iSocket = 0; cfg->iDomain = PF_INET; /* Internet family */ cfg->iType = SOCK_STREAM; /* We write streams reliably */ cfg->iProtocol = IPPROTO_TCP; /* TCP socket */ cfg->pAddr = NULL; a120 2 char pszAddress[L2_MAX_STRING]; unsigned short unInport; a123 2 unInport = 0; d129 2 a130 3 L2_PARAM_SET(pa[0], address, CHARPTR, pszAddress); L2_PARAM_SET(pa[1], port, USHORT, &unInport); /* TODO: Fill in the cfg-> structure after building the socket */ d140 4 a143 1 l2_ch_socket_t *cfg; d148 33 d182 7 a188 1 /* open channel socket */ d207 2 d211 2 d225 2 d248 2 d252 2 @ 1.4 log @Fix more ossp.com references by replacing with the correct domain name ossp.org. @ text @d33 14 d49 16 d68 1 d71 20 a90 1 return L2_OK; d93 1 d96 13 d112 1 d116 13 d132 1 d135 5 d143 1 d146 13 d162 1 d165 7 d175 1 @ 1.3 log @change terminology: below -> downstream @ text @d7 1 a7 1 ** can be found at http://www.ossp.com/pkg/l2/. @ 1.2 log @Fill in channel handler template code. @ text @d43 1 a43 1 static int hook_open(l2_context_t *ctx, l2_channel_t *below) d48 1 a48 1 static int hook_write(l2_context_t *ctx, l2_channel_t *below, d54 1 a54 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *below) d59 1 a59 1 static int hook_close(l2_context_t *ctx, l2_channel_t *below) @ 1.1 log @Initial revision @ text @d33 46 @ 1.1.1.1 log @L2 initial source tree @ text @@