1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup logger Logging functions
36 * @ingroup dnscore
37 * @brief
38 *
39 *
40 *
41 * @{
42 *
43 *----------------------------------------------------------------------------*/
44 #include "dnscore/dnscore-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <dnscore/thread.h>
48
49 #include "dnscore/logger_channel_stream.h"
50 #include "dnscore/logger_handle.h"
51 #include "dnscore/output_stream.h"
52 #include "dnscore/format.h"
53
54 /*
55 * The new logger model does not requires MT protection on the channels
56 */
57
58 typedef struct stream_data stream_data;
59
60 struct stream_data
61 {
62 output_stream os;
63 bool force_flush;
64 };
65
66 static ya_result
logger_channel_stream_constmsg(logger_channel * chan,int level,char * text,u32 text_len,u32 date_offset)67 logger_channel_stream_constmsg(logger_channel* chan, int level, char* text, u32 text_len, u32 date_offset)
68 {
69 (void)level;
70 (void)date_offset;
71
72 stream_data* sd = (stream_data*)chan->data;
73
74 output_stream_write(&sd->os, (const u8*)text, text_len);
75
76 ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1);
77
78 if(sd->force_flush)
79 {
80 output_stream_flush(&sd->os);
81 }
82
83 return ret;
84 }
85
86 static ya_result
logger_channel_stream_vmsg(logger_channel * chan,int level,char * text,va_list args)87 logger_channel_stream_vmsg(logger_channel* chan, int level, char* text, va_list args)
88 {
89 (void)level;
90
91 stream_data* sd = (stream_data*)chan->data;
92
93 vosformat(&sd->os, text, args);
94
95 ya_result ret = output_stream_write(&sd->os, (const u8*)"\n", 1);
96
97 if(sd->force_flush)
98 {
99 output_stream_flush(&sd->os);
100 }
101
102 return ret;
103 }
104
105 static ya_result
logger_channel_stream_msg(logger_channel * chan,int level,char * text,...)106 logger_channel_stream_msg(logger_channel* chan, int level, char* text, ...)
107 {
108 va_list args;
109 va_start(args, text);
110
111 ya_result ret = logger_channel_stream_vmsg(chan, level, text, args);
112
113 va_end(args);
114
115 return ret;
116 }
117
118 static void
logger_channel_stream_flush(logger_channel * chan)119 logger_channel_stream_flush(logger_channel* chan)
120 {
121 stream_data* sd = (stream_data*)chan->data;
122
123 output_stream_flush(&sd->os);
124 }
125
126 static void
logger_channel_stream_close(logger_channel * chan)127 logger_channel_stream_close(logger_channel* chan)
128 {
129 stream_data* sd = (stream_data*)chan->data;
130
131 output_stream_flush(&sd->os);
132 output_stream_close(&sd->os);
133
134 chan->vtbl = NULL;
135 sd->os.data = NULL;
136 sd->os.vtbl = NULL;
137
138 free(chan->data);
139 chan->data = NULL;
140 }
141
142 static ya_result
logger_channel_stream_reopen(logger_channel * chan)143 logger_channel_stream_reopen(logger_channel* chan)
144 {
145 stream_data* sd = (stream_data*)chan->data;
146
147 // there is no way to reopen a steam, simply flush its current contents
148
149 output_stream_flush(&sd->os);
150
151 return SUCCESS;
152 }
153
154 static void
logger_channel_steam_sync(logger_channel * chan)155 logger_channel_steam_sync(logger_channel* chan)
156 {
157 (void)chan;
158 }
159
160 static const logger_channel_vtbl stream_vtbl =
161 {
162 logger_channel_stream_constmsg,
163 logger_channel_stream_msg,
164 logger_channel_stream_vmsg,
165 logger_channel_stream_flush,
166 logger_channel_stream_close,
167 logger_channel_stream_reopen,
168 logger_channel_steam_sync,
169 "stream_channel"
170 };
171
172 /*
173 * Takes ownership of the stream.
174 * The stream will be unusable by the caller at the return of this function
175 */
176
177 void
logger_channel_stream_open(output_stream * os,bool forceflush,logger_channel * chan)178 logger_channel_stream_open(output_stream* os, bool forceflush, logger_channel* chan)
179 {
180 if(chan == NULL)
181 {
182 osformatln(termerr, "tried to open stream on uninitialised channel");
183 return;
184 }
185
186 stream_data* sd;
187 MALLOC_OBJECT_OR_DIE(sd, stream_data, 0x4d5254534e414843); /* CHANSTRM */
188
189 sd->os.data = os->data;
190 sd->os.vtbl = os->vtbl;
191 sd->force_flush = forceflush;
192
193 /* NOTE: Do NOT use a black hole.
194 * Let the application crashes if it tries to use a stream it does not own anymore
195 */
196 os->data = NULL;
197 os->vtbl = NULL;
198
199 chan->data = sd;
200 chan->vtbl = &stream_vtbl;
201 }
202
203 /** @} */
204