1/* 2 logging.c 3 4 Message logging plugin and stat collector for webserver. 5 6 Register the plugin with: 7 soap_register_plugin(soap, logging); 8 9 Change logging destinations: 10 soap_set_logging_inbound(struct soap*, FILE*); 11 soap_set_logging_outbound(struct soap*, FILE*); 12 13 Obtain stats (sent and recv octet count, independent of log dest): 14 soap_get_logging_stats(soap, size_t *sent, size_t *recv); 15 16gSOAP XML Web services tools 17Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. 18This part of the software is released under one of the following licenses: 19GPL, the gSOAP public license, or Genivia's license for commercial use. 20-------------------------------------------------------------------------------- 21gSOAP public license. 22 23The contents of this file are subject to the gSOAP Public License Version 1.3 24(the "License"); you may not use this file except in compliance with the 25License. You may obtain a copy of the License at 26http://www.cs.fsu.edu/~engelen/soaplicense.html 27Software distributed under the License is distributed on an "AS IS" basis, 28WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 29for the specific language governing rights and limitations under the License. 30 31The Initial Developer of the Original Code is Robert A. van Engelen. 32Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. 33-------------------------------------------------------------------------------- 34GPL license. 35 36This program is free software; you can redistribute it and/or modify it under 37the terms of the GNU General Public License as published by the Free Software 38Foundation; either version 2 of the License, or (at your option) any later 39version. 40 41This program is distributed in the hope that it will be useful, but WITHOUT ANY 42WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 43PARTICULAR PURPOSE. See the GNU General Public License for more details. 44 45You should have received a copy of the GNU General Public License along with 46this program; if not, write to the Free Software Foundation, Inc., 59 Temple 47Place, Suite 330, Boston, MA 02111-1307 USA 48 49Author contact information: 50engelen@genivia.com / engelen@acm.org 51 52This program is released under the GPL with the additional exemption that 53compiling, linking, and/or using OpenSSL is allowed. 54-------------------------------------------------------------------------------- 55A commercial use license is available from Genivia, Inc., contact@genivia.com 56-------------------------------------------------------------------------------- 57*/ 58 59#include "logging.h" 60 61#ifdef __cplusplus 62extern "C" { 63#endif 64 65const char logging_id[] = LOGGING_ID; 66 67static int logging_init(struct soap *soap, struct logging_data *data); 68static void logging_delete(struct soap *soap, struct soap_plugin *p); 69static int logging_send(struct soap *soap, const char *buf, size_t len); 70static size_t logging_recv(struct soap *soap, char *buf, size_t len); 71 72/* plugin registry function, invoked by soap_register_plugin */ 73int logging(struct soap *soap, struct soap_plugin *p, void *arg) 74{ p->id = logging_id; 75 /* create local plugin data */ 76 p->data = (void*)SOAP_MALLOC(soap, sizeof(struct logging_data)); 77 /* register the destructor */ 78 p->fdelete = logging_delete; 79 /* if OK then initialize */ 80 if (p->data) 81 { if (logging_init(soap, (struct logging_data*)p->data)) 82 { SOAP_FREE(soap, p->data); /* error: could not init */ 83 return SOAP_EOM; /* return error */ 84 } 85 } 86 return SOAP_OK; 87} 88 89/* set inbound logging FD, NULL to disable */ 90void soap_set_logging_inbound(struct soap *soap, FILE *fd) 91{ struct logging_data *data = (struct logging_data*)soap_lookup_plugin(soap, logging_id); 92 if (data) 93 data->inbound = fd; 94} 95 96/* set outbound logging FD, NULL to disable */ 97void soap_set_logging_outbound(struct soap *soap, FILE *fd) 98{ struct logging_data *data = (struct logging_data*)soap_lookup_plugin(soap, logging_id); 99 if (data) 100 data->outbound = fd; 101} 102 103/* get logging sent and recv octet counts */ 104void soap_get_logging_stats(struct soap *soap, size_t *sent, size_t *recv) 105{ struct logging_data *data = (struct logging_data*)soap_lookup_plugin(soap, logging_id); 106 if (data) 107 { *sent = data->stat_sent; 108 *recv = data->stat_recv; 109 } 110} 111 112/* used by plugin registry function */ 113static int logging_init(struct soap *soap, struct logging_data *data) 114{ data->inbound = NULL; 115 data->outbound = NULL; 116 data->stat_sent = 0; 117 data->stat_recv = 0; 118 data->fsend = soap->fsend; /* save old recv callback */ 119 data->frecv = soap->frecv; /* save old send callback */ 120 soap->fsend = logging_send; /* replace send callback with ours */ 121 soap->frecv = logging_recv; /* replace recv callback with ours */ 122 return SOAP_OK; 123} 124 125static void logging_delete(struct soap *soap, struct soap_plugin *p) 126{ 127 /* free allocated plugin data. If fcopy() is not set, then this function is 128 not called for all copies of the plugin created with soap_copy(). In this 129 example, the fcopy() callback is omitted and the plugin data is shared by 130 the soap copies created with soap_copy() */ 131 SOAP_FREE(soap, p->data); 132} 133 134static size_t logging_recv(struct soap *soap, char *buf, size_t len) 135{ struct logging_data *data = (struct logging_data*)soap_lookup_plugin(soap, logging_id); 136 size_t res; 137 /* get data from old recv callback */ 138 res = data->frecv(soap, buf, len); 139 /* update should be in mutex, but we don't mind some inaccuracy in stats */ 140 data->stat_recv += res; 141 if (data->inbound) 142 fwrite(buf, res, 1, data->inbound); 143 return res; 144} 145 146static int logging_send(struct soap *soap, const char *buf, size_t len) 147{ struct logging_data *data = (struct logging_data*)soap_lookup_plugin(soap, logging_id); 148 /* update should be in mutex, but we don't mind some inaccuracy in stats */ 149 data->stat_sent += len; 150 if (data->outbound) 151 fwrite(buf, len, 1, data->outbound); 152 return data->fsend(soap, buf, len); /* pass data on to old send callback */ 153} 154 155#ifdef __cplusplus 156} 157#endif 158 159