Skip to content

Commit f7947b9

Browse files
committed
Added ability to benchmark different EPP servers
1 parent eeb6482 commit f7947b9

File tree

4 files changed

+272
-1
lines changed

4 files changed

+272
-1
lines changed

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,25 @@ After deleting the cookie file, try logging in again. This will force the creati
184184

185185
### Need More Help?
186186

187-
If the steps above don’t resolve your issue, refer to the EPP Client logs (`/path/to/tembo/log`) to identify the specific problem.
187+
If the steps above don’t resolve your issue, refer to the EPP Client logs (`/path/to/tembo/log`) to identify the specific problem.
188+
189+
## Benchmarking an EPP Server
190+
191+
To run tests against an EPP server using the Tembo EPP client, follow these steps:
192+
193+
### 1. Configure Your Connection
194+
195+
Edit the file `benchmark/Connection.php` - this file should contain the connection details for the server you want to test. It uses the same format as `examples/Connection.php`.
196+
197+
### 2. Run the Benchmark
198+
199+
From the root directory, run `php benchmark/Benchmark.php` - this will execute a series of domain check commands to test your server’s response and performance.
200+
201+
### 3. Customize the Benchmark
202+
203+
You can modify `benchmark/Benchmark.php` to:
204+
- Add your own EPP commands
205+
- Change the number of requests
206+
- Adjust the test logic
207+
208+
Use this script as a starting point to test and tune your EPP server setup.

benchmark/Benchmark.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/**
3+
* PlexEPP: EPP server benchmark
4+
*
5+
* Written in 2025 by Taras Kondratyuk (https://namingo.org)
6+
* Based on xpanel/epp-bundle written in 2019 by Lilian Rudenco ([email protected])
7+
*
8+
* @license MIT
9+
*/
10+
11+
require_once '../vendor/autoload.php';
12+
require_once 'Connection.php';
13+
require_once 'Helpers.php';
14+
15+
try {
16+
// Start timing
17+
$startTime = microtime(true);
18+
19+
$epp = connectEpp('generic');
20+
21+
// Create 200 batches of 5 domain checks each
22+
for ($i = 0; $i < 200; $i++) {
23+
$domains = [];
24+
for ($j = 0; $j < 5; $j++) {
25+
$domains[] = randomDomain();
26+
}
27+
performDomainCheck($epp, $domains);
28+
}
29+
30+
// Create 10,000 random domain create requests
31+
for ($i = 0; $i < 10000; $i++) {
32+
$domain = randomDomain();
33+
performDomainCreate($epp, $domain);
34+
}
35+
36+
// Create 10,000 random domain info requests
37+
for ($i = 0; $i < 10000; $i++) {
38+
$domain = randomDomain();
39+
performDomainInfo($epp, $domain);
40+
}
41+
42+
// End timing
43+
$endTime = microtime(true);
44+
$executionTime = $endTime - $startTime;
45+
echo 'Total Execution Time: ' . $executionTime . ' seconds' . PHP_EOL;
46+
47+
$epp->logout();
48+
} catch (\Pinga\Tembo\Exception\EppException $e) {
49+
echo "Error : " . $e->getMessage() . PHP_EOL;
50+
} catch (Throwable $e) {
51+
echo "Error : " . $e->getMessage() . PHP_EOL;
52+
}

benchmark/Connection.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
/**
3+
* PlexEPP: EPP server benchmark
4+
*
5+
* Written in 2025 by Taras Kondratyuk (https://namingo.org)
6+
* Based on xpanel/epp-bundle written in 2019 by Lilian Rudenco ([email protected])
7+
*
8+
* @license MIT
9+
*/
10+
11+
// Include the Composer autoloader
12+
require_once '../vendor/autoload.php';
13+
14+
use Pinga\Tembo\EppRegistryFactory;
15+
16+
function connectEpp(string $registry) {
17+
try
18+
{
19+
$epp = EppRegistryFactory::create($registry);
20+
$info = array(
21+
//For EPP-over-HTTPS, 'host' => 'https://registry.example.com/epp',
22+
'host' => 'epp.example.com',
23+
//For EPP-over-HTTPS , port is usually 443
24+
'port' => 700,
25+
'timeout' => 30,
26+
'tls' => '1.2', // Change to 1.3 if required
27+
'bind' => false,
28+
'bindip' => '1.2.3.4:0',
29+
'verify_peer' => false,
30+
'verify_peer_name' => false,
31+
//For EPP-over-HTTPS , change false to 2
32+
'verify_host' => false,
33+
'cafile' => '',
34+
'local_cert' => '/root/tembo/cert.pem',
35+
'local_pk' => '/root/tembo/key.pem',
36+
'passphrase' => '',
37+
'allow_self_signed' => true
38+
);
39+
$epp->connect($info);
40+
$login = $epp->login(array(
41+
'clID' => 'testregistrar1',
42+
'pw' => 'testpassword1',
43+
//'newpw' => 'testpassword2',
44+
'prefix' => 'tembo'
45+
));
46+
if (array_key_exists('error', $login)) {
47+
throw new RuntimeException('Login Error: ' . $login['error']);
48+
} else {
49+
echo 'Login Result: ' . $login['code'] . ': ' . $login['msg'][0] . PHP_EOL;
50+
}
51+
return $epp;
52+
} catch(\Pinga\Tembo\Exception\EppException $e) {
53+
echo "Error : ".$e->getMessage() . PHP_EOL;
54+
} catch(Throwable $e) {
55+
echo "Error : ".$e->getMessage() . PHP_EOL;
56+
}
57+
}

benchmark/Helpers.php

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
/**
3+
* PlexEPP: EPP server benchmark
4+
*
5+
* Written in 2025 by Taras Kondratyuk (https://namingo.org)
6+
* Based on xpanel/epp-bundle written in 2019 by Lilian Rudenco ([email protected])
7+
*
8+
* @license MIT
9+
*/
10+
11+
// Function to generate random strings
12+
function randomString($length) {
13+
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
14+
$charactersLength = strlen($characters);
15+
$randomString = '';
16+
for ($i = 0; $i < $length; $i++) {
17+
$randomString .= $characters[rand(0, $charactersLength - 1)];
18+
}
19+
return $randomString;
20+
}
21+
22+
// Function to generate a random domain name
23+
function randomDomain() {
24+
return randomString(8) . '.test';
25+
}
26+
27+
// Function to perform domain check
28+
function performDomainCheck($epp, $domains) {
29+
try {
30+
$params = array('domains' => $domains);
31+
$domainCheck = $epp->domainCheck($params);
32+
33+
if (array_key_exists('error', $domainCheck)) {
34+
echo 'DomainCheck Error: ' . $domainCheck['error'] . PHP_EOL;
35+
} else {
36+
echo "DomainCheck result: " . $domainCheck['code'] . ": " . $domainCheck['msg'] . PHP_EOL;
37+
$x = 1;
38+
foreach ($domainCheck['domains'] as $domain) {
39+
if ($domain['avail']) {
40+
echo "Domain " . $x . ": " . $domain['name'] . " is available" . PHP_EOL;
41+
} else {
42+
echo "Domain " . $x . ": " . $domain['name'] . " is not available because: " . $domain['reason'] . PHP_EOL;
43+
}
44+
$x++;
45+
}
46+
}
47+
} catch (\Pinga\Tembo\Exception\EppException $e) {
48+
echo "Error : " . $e->getMessage() . PHP_EOL;
49+
} catch (Throwable $e) {
50+
echo "Error : " . $e->getMessage() . PHP_EOL;
51+
}
52+
}
53+
54+
// Function to perform domain create operation
55+
function performDomainCreate($epp, $domain) {
56+
try {
57+
$params = array(
58+
'domainname' => $domain,
59+
'period' => 1,
60+
'nss' => array('ns1.example.com','ns2.example.com'),
61+
'registrant' => 'tembo007',
62+
'contacts' => array(
63+
'admin' => 'tembo007',
64+
'tech' => 'tembo007',
65+
'billing' => 'tembo007'
66+
),
67+
'authInfoPw' => 'Domainpw123@'
68+
);
69+
$domainCreate = $epp->domainCreate($params);
70+
71+
if (array_key_exists('error', $domainCreate)) {
72+
echo 'DomainCreate Error: ' . $domainCreate['error'] . PHP_EOL;
73+
} else {
74+
echo 'DomainCreate Result: ' . $domainCreate['code'] . ': ' . $domainCreate['msg'] . PHP_EOL;
75+
echo 'New Domain: ' . $domainCreate['name'] . PHP_EOL;
76+
echo 'Created On: ' . $domainCreate['crDate'] . PHP_EOL;
77+
echo 'Expires On: ' . $domainCreate['exDate'] . PHP_EOL;
78+
}
79+
} catch (\Pinga\Tembo\Exception\EppException $e) {
80+
echo "Error : " . $e->getMessage() . PHP_EOL;
81+
} catch (Throwable $e) {
82+
echo "Error : " . $e->getMessage() . PHP_EOL;
83+
}
84+
}
85+
86+
// Function to perform domain info operation
87+
function performDomainInfo($epp, $domain) {
88+
try {
89+
$params = array(
90+
'domainname' => $domain,
91+
'authInfoPw' => 'P@ssword123!'
92+
);
93+
$domainInfo = $epp->domainInfo($params);
94+
95+
if (array_key_exists('error', $domainInfo)) {
96+
echo 'DomainInfo Error: ' . $domainInfo['error'] . PHP_EOL;
97+
} else {
98+
echo 'DomainInfo Result: ' . $domainInfo['code'] . ': ' . $domainInfo['msg'] . PHP_EOL;
99+
echo 'Name: ' . $domainInfo['name'] . PHP_EOL;
100+
echo 'ROID: ' . $domainInfo['roid'] . PHP_EOL;
101+
$status = $domainInfo['status'] ?? 'No status available';
102+
if (is_array($status)) {
103+
echo 'Status: ' . implode(', ', $status) . PHP_EOL;
104+
} else {
105+
echo 'Status: ' . $status . PHP_EOL;
106+
}
107+
echo 'Registrant: ' . $domainInfo['registrant'] . PHP_EOL;
108+
109+
$contact_types = array("admin", "billing", "tech");
110+
foreach ($contact_types as $type) {
111+
$contact = array_values(array_filter($domainInfo['contact'], function($c) use ($type) {
112+
return $c["type"] == $type;
113+
}));
114+
if (count($contact) > 0) {
115+
$type = ucfirst($type);
116+
echo $type . ": " . $contact[0]["id"] . "\n";
117+
}
118+
}
119+
asort($domainInfo['ns']);
120+
foreach ($domainInfo['ns'] as $server) {
121+
echo "Name Server: $server\n";
122+
}
123+
asort($domainInfo['host']);
124+
foreach ($domainInfo['host'] as $host) {
125+
echo "Host: $host\n";
126+
}
127+
echo 'Current Registrar: ' . $domainInfo['clID'] . PHP_EOL;
128+
echo 'Original Registrar: ' . $domainInfo['crID'] . PHP_EOL;
129+
echo 'Created On: ' . $domainInfo['crDate'] . PHP_EOL;
130+
echo 'Updated By: ' . $domainInfo['upID'] . PHP_EOL;
131+
echo 'Updated On: ' . $domainInfo['upDate'] . PHP_EOL;
132+
echo 'Expires On: ' . $domainInfo['exDate'] . PHP_EOL;
133+
echo 'Transferred On: ' . $domainInfo['trDate'] . PHP_EOL;
134+
echo 'Password: ' . $domainInfo['authInfo'] . PHP_EOL;
135+
}
136+
} catch (\Pinga\Tembo\Exception\EppException $e) {
137+
echo "Error : " . $e->getMessage() . PHP_EOL;
138+
} catch (Throwable $e) {
139+
echo "Error : " . $e->getMessage() . PHP_EOL;
140+
}
141+
}

0 commit comments

Comments
 (0)