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/>.
28 #include <sys/types.h>
40 static const size_t MAX_CLIENT_LEN
= 80 + (3 * (IPADDR_STR_SIZE
+ 5) );
43 /* generate throughput statistic string
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
);
55 (void) snprintf( str
, len
, "N/A" );
62 /* generate individual clients' status records
65 mk_client_entries( const struct server_ctx
* ctx
,
66 char* buf
, size_t* len
)
70 size_t i
= 0, total
= 0;
73 assert( ctx
&& buf
&& len
);
76 n
= prbuf_open( &pb
, buf
, *len
);
80 n
= prbuf_printf( pb
, ACLIENT_TABLE
[0] );
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 ],
91 client
->src_addr
, client
->src_port
,
92 client
->mcast_addr
, client
->mcast_port
,
93 tpstat_str( &(client
->tstat
), tpinfo
,
101 n
= prbuf_printf( pb
, ACLIENT_TABLE
[1] );
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
,
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
);
150 n
= prbuf_open( &pb
, buf
, *len
);
153 if( options
& MSO_HTTP_HEADER
) {
154 n
= prbuf_printf( pb
, "%s", HTML_PAGE_HEADER
);
158 if( options
& MSO_RESTART
) {
159 n
= prbuf_printf( pb
, REDIRECT_SCRIPT_FMT
, delay_msec
);
163 for( i
= 0, n
= -1; n
&& (i
< LEN_STAT_PAGE_BASE
); ++i
) {
164 n
= prbuf_printf( pb
, "%s", STAT_PAGE_BASE
[i
] );
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__
);
185 n
= mk_client_entries( ctx
, client_text
, &text_size
);
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
,
195 (client_text
? client_text
: ""),
197 VERSION
, BUILDNUM
, COMPILE_MODE
, str_now
,
198 UDPXY_COPYRIGHT_NOTICE
);
204 TRACE( (void)tmfprintf( g_flog
,
205 "Error preparing status HTML: "
206 "insufficient memory size=[%lu]\n", (u_long
)(*len
) ));
209 *len
= prbuf_len( pb
);
213 (void) prbuf_close( pb
);
215 return (n
> 0 ? 0 : -1);