libsodium: Needed for Dnscrypto-proxy Release 1.3.0
[tomato.git] / release / src / router / udpxy / mkpg.c
blob5046b98909b2a50ac4eafb19ce94c558af8aa420
1 /* @(#) HTML-page templates/generation for udpxy status page
3 * Copyright 2008-2011 Pavel V. Cherenkov (pcherenkov@gmail.com)
5 * This file is part of udpxy.
7 * udpxy is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * udpxy is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with udpxy. If not, see <http://www.gnu.org/licenses/>.
21 #include <time.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
28 #include <sys/types.h>
30 #include "ctx.h"
31 #include "prbuf.h"
32 #include "udpxy.h"
33 #include "util.h"
34 #include "mtrace.h"
36 #include "statpg.h"
37 #include "mkpg.h"
39 extern FILE* g_flog;
40 static const size_t MAX_CLIENT_LEN = 80 + (3 * (IPADDR_STR_SIZE + 5) );
43 /* generate throughput statistic string
45 static const char*
46 tpstat_str( const struct tput_stat* ts, char* str, size_t len )
48 assert( ts && str && len );
50 if( (0 != ts->sender_id) && (ts->nsec > 0.0) ) {
51 (void) snprintf( str, len, "%.2f Kb/sec",
52 (ts->nbytes / 1024.0) / ts->nsec );
54 else {
55 (void) snprintf( str, len, "N/A" );
58 return str;
62 /* generate individual clients' status records
64 static int
65 mk_client_entries( const struct server_ctx* ctx,
66 char* buf, size_t* len )
68 prbuf_t pb = NULL;
69 int n = -1;
70 size_t i = 0, total = 0;
71 char tpinfo[ 32 ];
73 assert( ctx && buf && len );
75 do {
76 n = prbuf_open( &pb, buf, *len );
77 if( -1 == n ) break;
79 /* table header */
80 n = prbuf_printf( pb, ACLIENT_TABLE[0] );
81 if( -1 == n ) break;
82 else
83 total += n;
85 for( i = 0, n = -1; n && (i < ctx->clmax); ++i ) {
86 struct client_ctx* client = &(ctx->cl[i]);
87 if( client->pid <= 0 ) continue;
89 n = prbuf_printf( pb, ACLIENT_REC_FMT[ i % 2 ],
90 ctx->cl[i].pid,
91 client->src_addr, client->src_port,
92 client->mcast_addr, client->mcast_port,
93 tpstat_str( &(client->tstat), tpinfo,
94 sizeof(tpinfo) ) );
95 if( n <= 0 ) break;
96 else
97 total += n;
98 } /* loop */
100 /* table footer */
101 n = prbuf_printf( pb, ACLIENT_TABLE[1] );
102 if( -1 == n ) break;
103 else
104 total += n;
106 } while(0);
108 if( n > 0 ) {
109 *len = total;
111 else {
112 TRACE( (void)tmfprintf( g_flog,
113 "Error preparing status (client) HTML: "
114 "insufficient memory\n" ) );
117 (void) prbuf_close( pb );
118 return (n > 0 ? 0 : -1);
123 /* generate service's (HTML) status page
126 mk_status_page( const struct server_ctx* ctx,
127 char* buf, size_t* len,
128 int options )
130 int n = -1;
131 prbuf_t pb = NULL;
132 time_t tm_now = time(NULL);
133 const char* str_now = Zasctime(localtime(&tm_now));
135 size_t num_clients = 0, i = 0;
136 char* client_text = NULL;
137 const char* page_format = NULL;
138 const unsigned delay_msec = 3000;
140 size_t text_size = 0, HEADER_SIZE = 0;
142 extern const char UDPXY_COPYRIGHT_NOTICE[];
143 extern const char COMPILE_MODE[];
144 extern const char VERSION[];
145 extern const int BUILDNUM;
147 assert( ctx && buf && len );
149 do {
150 n = prbuf_open( &pb, buf, *len );
151 if( -1 == n ) break;
153 if( options & MSO_HTTP_HEADER ) {
154 n = prbuf_printf( pb, "%s", HTML_PAGE_HEADER );
155 if( n <= 0 ) break;
158 if( options & MSO_RESTART ) {
159 n = prbuf_printf( pb, REDIRECT_SCRIPT_FMT, delay_msec );
160 if( n <= 0 ) break;
163 for( i = 0, n = -1; n && (i < LEN_STAT_PAGE_BASE); ++i ) {
164 n = prbuf_printf( pb, "%s", STAT_PAGE_BASE[i] );
166 if( n <= 0 ) break;
168 for( num_clients = 0, i = 0; i < ctx->clmax; ++i ) {
169 if( ctx->cl[i].pid > 0 ) ++num_clients;
172 if( ! (options & MSO_SKIP_CLIENTS) ) {
173 if( num_clients > (size_t)0 ) {
174 HEADER_SIZE = strlen(ACLIENT_TABLE[0]);
175 HEADER_SIZE += strlen(ACLIENT_TABLE[1]);
177 text_size = HEADER_SIZE + (MAX_CLIENT_LEN * num_clients);
178 client_text = malloc( text_size );
179 if( NULL == client_text ) {
180 mperror( g_flog, errno, "%s: calloc", __func__ );
181 n = -1;
182 break;
185 n = mk_client_entries( ctx, client_text, &text_size );
186 if( -1 == n ) break;
188 } /* MSO_SKIP_CLIENTS */
190 page_format = ( options & MSO_RESTART ) ? RST_PAGE_FMT1 : STAT_PAGE_FMT1;
191 n = prbuf_printf( pb, page_format,
192 getpid(), ctx->listen_addr, ctx->listen_port,
193 ctx->mcast_ifc_addr,
194 num_clients,
195 (client_text ? client_text : ""),
196 REQUEST_GUIDE,
197 VERSION, BUILDNUM, COMPILE_MODE, str_now,
198 UDPXY_COPYRIGHT_NOTICE );
199 if( -1 == n ) break;
201 } while(0);
203 if( -1 == n ) {
204 TRACE( (void)tmfprintf( g_flog,
205 "Error preparing status HTML: "
206 "insufficient memory size=[%lu]\n", (u_long)(*len) ));
208 else {
209 *len = prbuf_len( pb );
212 free( client_text );
213 (void) prbuf_close( pb );
215 return (n > 0 ? 0 : -1);
219 /* __EOF__ */