• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#***************************************************************************
2#                                  _   _ ____  _
3#  Project                     ___| | | |  _ \| |
4#                             / __| | | | |_) | |
5#                            | (__| |_| |  _ <| |___
6#                             \___|\___/|_| \_\_____|
7#
8# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9#
10# This software is licensed as described in the file COPYING, which
11# you should have received as part of this distribution. The terms
12# are also available at https://curl.se/docs/copyright.html.
13#
14# You may opt to use, copy, modify, merge, publish, distribute and/or sell
15# copies of the Software, and permit persons to whom the Software is
16# furnished to do so, under the terms of the COPYING file.
17#
18# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19# KIND, either express or implied.
20#
21# SPDX-License-Identifier: curl
22#
23#***************************************************************************
24
25# This perl module contains functions useful in writing test servers.
26
27package serverhelp;
28
29use strict;
30use warnings;
31
32BEGIN {
33    use base qw(Exporter);
34
35    our @EXPORT_OK = qw(
36        logmsg
37        $logfile
38        serverfactors
39        servername_id
40        servername_str
41        servername_canon
42        server_pidfilename
43        server_portfilename
44        server_logfilename
45        server_cmdfilename
46        server_inputfilename
47        server_outputfilename
48        mainsockf_pidfilename
49        mainsockf_logfilename
50        datasockf_pidfilename
51        datasockf_logfilename
52    );
53
54    # sub second timestamping needs Time::HiRes
55    eval {
56        no warnings "all";
57        require Time::HiRes;
58        import  Time::HiRes qw( gettimeofday );
59    }
60}
61
62
63our $logfile;  # server log file name, for logmsg
64
65#***************************************************************************
66# Just for convenience, test harness uses 'https' and 'httptls' literals as
67# values for 'proto' variable in order to differentiate different servers.
68# 'https' literal is used for stunnel based https test servers, and 'httptls'
69# is used for non-stunnel https test servers.
70
71#**********************************************************************
72# logmsg is general message logging subroutine for our test servers.
73#
74sub logmsg {
75    my $now;
76    # sub second timestamping needs Time::HiRes
77    if($Time::HiRes::VERSION) {
78        my ($seconds, $usec) = gettimeofday();
79        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
80            localtime($seconds);
81        $now = sprintf("%02d:%02d:%02d.%06d ", $hour, $min, $sec, $usec);
82    }
83    else {
84        my $seconds = time();
85        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
86            localtime($seconds);
87        $now = sprintf("%02d:%02d:%02d ", $hour, $min, $sec);
88    }
89    if(open(my $logfilefh, ">>", "$logfile")) {
90        print $logfilefh $now;
91        print $logfilefh @_;
92        close($logfilefh);
93    }
94}
95
96
97#***************************************************************************
98# Return server characterization factors given a server id string.
99#
100sub serverfactors {
101    my $server = $_[0];
102    my $proto;
103    my $ipvnum;
104    my $idnum;
105
106    if($server =~
107        /^((ftp|http|imap|pop3|smtp|http-pipe)s?)(\d*)(-ipv6|)$/) {
108        $proto  = $1;
109        $idnum  = ($3 && ($3 > 1)) ? $3 : 1;
110        $ipvnum = ($4 && ($4 =~ /6$/)) ? 6 : 4;
111    }
112    elsif($server =~
113        /^(tftp|sftp|socks|ssh|rtsp|gopher|httptls)(\d*)(-ipv6|)$/) {
114        $proto  = $1;
115        $idnum  = ($2 && ($2 > 1)) ? $2 : 1;
116        $ipvnum = ($3 && ($3 =~ /6$/)) ? 6 : 4;
117    }
118    else {
119        die "invalid server id: '$server'"
120    }
121    return($proto, $ipvnum, $idnum);
122}
123
124
125#***************************************************************************
126# Return server name string formatted for presentation purposes
127#
128sub servername_str {
129    my ($proto, $ipver, $idnum) = @_;
130
131    $proto = uc($proto) if($proto);
132    die "unsupported protocol: '$proto'" unless($proto &&
133        ($proto =~ /^(((FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTP-PIPE)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|HTTPTLS|DICT|SMB|SMBS|TELNET|MQTT))$/));
134
135    $ipver = (not $ipver) ? 'ipv4' : lc($ipver);
136    die "unsupported IP version: '$ipver'" unless($ipver &&
137        ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/));
138    $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : '');
139
140    $idnum = 1 if(not $idnum);
141    die "unsupported ID number: '$idnum'" unless($idnum &&
142        ($idnum =~ /^(\d+)$/));
143    $idnum = '' if($idnum <= 1);
144
145    return "${proto}${idnum}${ipver}";
146}
147
148
149#***************************************************************************
150# Return server name string formatted for identification purposes
151#
152sub servername_id {
153    my ($proto, $ipver, $idnum) = @_;
154    return lc(servername_str($proto, $ipver, $idnum));
155}
156
157
158#***************************************************************************
159# Return server name string formatted for file name purposes
160#
161sub servername_canon {
162    my ($proto, $ipver, $idnum) = @_;
163    my $string = lc(servername_str($proto, $ipver, $idnum));
164    $string =~ tr/-/_/;
165    $string =~ s/\//_v/;
166    return $string;
167}
168
169
170#***************************************************************************
171# Return file name for server pid file.
172#
173sub server_pidfilename {
174    my ($piddir, $proto, $ipver, $idnum) = @_;
175    my $trailer = '_server.pid';
176    return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
177}
178
179#***************************************************************************
180# Return file name for server port file.
181#
182sub server_portfilename {
183    my ($piddir, $proto, $ipver, $idnum) = @_;
184    my $trailer = '_server.port';
185    return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
186}
187
188
189#***************************************************************************
190# Return file name for server log file.
191#
192sub server_logfilename {
193    my ($logdir, $proto, $ipver, $idnum) = @_;
194    my $trailer = '_server.log';
195    $trailer = '_stunnel.log' if(lc($proto) =~ /^(ftp|http|imap|pop3|smtp)s$/);
196    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
197}
198
199
200#***************************************************************************
201# Return file name for server commands file.
202#
203sub server_cmdfilename {
204    my ($logdir, $proto, $ipver, $idnum) = @_;
205    my $trailer = '_server.cmd';
206    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
207}
208
209
210#***************************************************************************
211# Return file name for server input file.
212#
213sub server_inputfilename {
214    my ($logdir, $proto, $ipver, $idnum) = @_;
215    my $trailer = '_server.input';
216    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
217}
218
219
220#***************************************************************************
221# Return file name for server output file.
222#
223sub server_outputfilename {
224    my ($logdir, $proto, $ipver, $idnum) = @_;
225    my $trailer = '_server.output';
226    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
227}
228
229
230#***************************************************************************
231# Return file name for main or primary sockfilter pid file.
232#
233sub mainsockf_pidfilename {
234    my ($piddir, $proto, $ipver, $idnum) = @_;
235    die "unsupported protocol: '$proto'" unless($proto &&
236        (lc($proto) =~ /^(ftp|imap|pop3|smtp)s?$/));
237    my $trailer = (lc($proto) =~ /^ftps?$/) ? '_sockctrl.pid':'_sockfilt.pid';
238    return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
239}
240
241
242#***************************************************************************
243# Return file name for main or primary sockfilter log file.
244#
245sub mainsockf_logfilename {
246    my ($logdir, $proto, $ipver, $idnum) = @_;
247    die "unsupported protocol: '$proto'" unless($proto &&
248        (lc($proto) =~ /^(ftp|imap|pop3|smtp)s?$/));
249    my $trailer = (lc($proto) =~ /^ftps?$/) ? '_sockctrl.log':'_sockfilt.log';
250    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
251}
252
253
254#***************************************************************************
255# Return file name for data or secondary sockfilter pid file.
256#
257sub datasockf_pidfilename {
258    my ($piddir, $proto, $ipver, $idnum) = @_;
259    die "unsupported protocol: '$proto'" unless($proto &&
260        (lc($proto) =~ /^ftps?$/));
261    my $trailer = '_sockdata.pid';
262    return "${piddir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
263}
264
265
266#***************************************************************************
267# Return file name for data or secondary sockfilter log file.
268#
269sub datasockf_logfilename {
270    my ($logdir, $proto, $ipver, $idnum) = @_;
271    die "unsupported protocol: '$proto'" unless($proto &&
272        (lc($proto) =~ /^ftps?$/));
273    my $trailer = '_sockdata.log';
274    return "${logdir}/". servername_canon($proto, $ipver, $idnum) ."$trailer";
275}
276
277
278#***************************************************************************
279# End of library
2801;
281