Quite a few fixes on EPP poll functionality

This commit is contained in:
Pinga 2025-02-07 12:31:54 +02:00
parent eba9ffdad6
commit 7a6385ed91
2 changed files with 129 additions and 58 deletions

View file

@ -1,6 +1,20 @@
# Namingo Registry EPP Server
This section includes examples of commonly used EPP commands for domains, hosts, contacts, and session management. Explore key operations like create, update, delete, transfer, and poll, with practical XML samples for each.
The **Namingo EPP Server** provides a robust and standards-compliant interface for managing domain registrations, hosts, and contacts via the **Extensible Provisioning Protocol (EPP)**. This section offers practical examples of commonly used EPP commands, showcasing request and response structures for seamless integration with the Namingo Registry.
## Overview
EPP is an XML-based protocol designed for secure communication between registrars and registries. The Namingo EPP Server adheres to **RFC 5730-5734** and relevant extensions to support modern domain management operations, including:
- **Session Management**: Login, logout, and keep-alive commands
- **Domain Management**: Create, update, renew, transfer, delete, and check domain availability
- **Host (Nameserver) Management**: Create, update, delete, and query hosts
- **Contact Management**: Create, update, delete, and retrieve contact information
- **Poll Mechanism**: Retrieve registry notifications (e.g., transfer approvals, policy updates)
Each command section below includes real-world XML request and response samples to facilitate easy integration.
---
## Commands
@ -97,7 +111,9 @@ This section includes examples of commonly used EPP commands for domains, hosts,
</epp>
```
#### 1.3. Hello Request
#### 1.3. Hello
**Request:**
```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
@ -108,7 +124,11 @@ This section includes examples of commonly used EPP commands for domains, hosts,
</epp>
```
#### 1.4. Poll Request
**Response:**
#### 1.4. Poll
**Request:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
@ -122,8 +142,63 @@ This section includes examples of commonly used EPP commands for domains, hosts,
</epp>
```
**Response without message:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
<response>
<result code="1300">
<msg>Command completed successfully; no messages</msg>
</result>
<trID>
<clTRID>client-20241128-12345</clTRID>
<svTRID>namingo-1234567890-abcdef1234</svTRID>
</trID>
</response>
</epp>
```
**Response with message:**
```xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
<response>
<result code="1301">
<msg>Command completed successfully; ack to dequeue</msg>
</result>
<msgQ count="3" id="3">
<qDate>2025-02-03T11:17:38.014Z</qDate>
<msg lang="en-US">Transfer requested.</msg>
</msgQ>
<resData>
<domain:trnData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>test8.test</domain:name>
<domain:trStatus>pending</domain:trStatus>
<domain:reID>nordregistrar</domain:reID>
<domain:reDate>2025-02-03T11:17:38.013Z</domain:reDate>
<domain:acID>leonet</domain:acID>
<domain:acDate>2025-02-08T11:17:38.013Z</domain:acDate>
<domain:exDate>2027-12-06T11:19:20.343Z</domain:exDate>
</domain:trnData>
</resData>
<trID>
<clTRID>client-20241128-12345</clTRID>
<svTRID>namingo-1234567890-abcdef1234</svTRID>
</trID>
</response>
</epp>
```
#### 1.5. Poll Acknowledge
**Request:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
@ -136,6 +211,25 @@ This section includes examples of commonly used EPP commands for domains, hosts,
</epp>
```
**Response:**
```xml
<?xml version="1.0" encoding="UTF-8"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
<response>
<result code="1300">
<msg>Command completed successfully; no messages</msg>
</result>
<trID>
<clTRID>client-20241128-12345</clTRID>
<svTRID>namingo-1234567890-abcdef1234</svTRID>
</trID>
</response>
</epp>
```
### 2. Contact
#### 2.1. Contact Check Request

View file

@ -3,7 +3,8 @@
function processPoll($conn, $db, $xml, $clid, $trans) {
$clTRID = (string) $xml->command->clTRID;
$node = $xml->command->poll;
$op = (string) $node['op'];
$op = (string) $node->attributes()->op;
$response = [];
$stmt = $db->prepare("SELECT id FROM registrar WHERE clid = :clid LIMIT 1");
$stmt->bindParam(':clid', $clid, PDO::PARAM_STR);
@ -11,8 +12,10 @@ function processPoll($conn, $db, $xml, $clid, $trans) {
$clid = $stmt->fetch(PDO::FETCH_ASSOC);
$clid = $clid['id'];
$next_msg_id = null;
if ($op === 'ack') {
$id = (string)$node['msgID'];
$id = (string) $node->attributes()->msgID;
$stmt = $db->prepare("SELECT id FROM poll WHERE registrar_id = :registrar_id AND id = :id LIMIT 1");
$stmt->execute([':registrar_id' => $clid, ':id' => $id]);
$ack_id = $stmt->fetchColumn();
@ -20,41 +23,30 @@ function processPoll($conn, $db, $xml, $clid, $trans) {
if (!$ack_id) {
$response['resultCode'] = 2303; // Object does not exist
} else {
// Delete acknowledged message
$stmt = $db->prepare("DELETE FROM poll WHERE registrar_id = :registrar_id AND id = :id");
$stmt->execute([':registrar_id' => $clid, ':id' => $id]);
$response['resultCode'] = 1300;
}
$stmt = $db->prepare("SELECT id, qdate, msg, msg_type, obj_name_or_id, obj_trStatus, obj_reID, obj_reDate, obj_acID, obj_acDate, obj_exDate, registrarName, creditLimit, creditThreshold, creditThresholdType, availableCredit FROM poll WHERE registrar_id = :registrar_id ORDER BY id DESC LIMIT 1");
// Find the next available poll message
$stmt = $db->prepare("SELECT id FROM poll WHERE registrar_id = :registrar_id ORDER BY id ASC LIMIT 1");
$stmt->execute([':registrar_id' => $clid]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$id = $result['id'] ?? null;
$next_msg_id = $stmt->fetchColumn();
if (isset($id) && is_numeric($id) && $id >= 1) {
$stmt = $db->prepare("SELECT id, qdate, msg, msg_type, obj_name_or_id, obj_trStatus, obj_reID, obj_reDate, obj_acID, obj_acDate, obj_exDate, registrarName, creditLimit, creditThreshold, creditThresholdType, availableCredit FROM poll WHERE registrar_id = :registrar_id ORDER BY id DESC LIMIT 1");
if ($next_msg_id) {
// Messages remain, return 1000 with next message ID
$stmt = $db->prepare("SELECT COUNT(*) FROM poll WHERE registrar_id = :registrar_id");
$stmt->execute([':registrar_id' => $clid]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$remaining = $stmt->fetchColumn();
$id = $result['id'] ?? null;
$response['resultCode'] = $id ? 1301 : 1300;
$response['resultCode'] = 1000; // Command completed successfully
} else {
$stmt = $db->prepare("SELECT COUNT(id) AS counter FROM poll WHERE registrar_id = :registrar_id");
$stmt->execute([':registrar_id' => $clid]);
$counter = $stmt->fetchColumn();
$response['count'] = $counter;
$response['id'] = $id;
$response['command'] = 'poll';
$response['clTRID'] = $clTRID;
$response['svTRID'] = generateSvTRID();
$epp = new EPP\EppWriter();
$xml = $epp->epp_writer($response);
updateTransaction($db, 'poll', null, null, $response['resultCode'], 'Command completed successfully', $response['svTRID'], $xml, $trans);
sendEppResponse($conn, $xml);
return;
// No more messages remaining
$response['resultCode'] = 1300; // No messages remaining
}
}
} else {
$stmt = $db->prepare("SELECT id, qdate, msg, msg_type, obj_name_or_id, obj_trStatus, obj_reID, obj_reDate, obj_acID, obj_acDate, obj_exDate, registrarName, creditLimit, creditThreshold, creditThresholdType, availableCredit FROM poll WHERE registrar_id = :registrar_id ORDER BY id DESC LIMIT 1");
// $op === 'req'
$stmt = $db->prepare("SELECT id, qdate, msg, msg_type, obj_name_or_id, obj_trStatus, obj_reID, obj_reDate, obj_acID, obj_acDate, obj_exDate, registrarName, creditLimit, creditThreshold, creditThresholdType, availableCredit FROM poll WHERE registrar_id = :registrar_id ORDER BY id ASC LIMIT 1");
$stmt->execute([':registrar_id' => $clid]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
@ -62,33 +54,18 @@ function processPoll($conn, $db, $xml, $clid, $trans) {
$response['resultCode'] = $id ? 1301 : 1300;
}
if ((int) $response['resultCode'] === 1300) {
$svTRID = generateSvTRID();
$response = [
'command' => 'poll',
'clTRID' => $clTRID,
'svTRID' => $svTRID,
'resultCode' => $response['resultCode'],
'msg' => 'Command completed successfully; no messages',
];
$epp = new EPP\EppWriter();
$xml = $epp->epp_writer($response);
updateTransaction($db, 'poll', null, null, $response['resultCode'], 'Command completed successfully', $svTRID, $xml, $trans);
sendEppResponse($conn, $xml);
return;
}
$stmt = $db->prepare("SELECT COUNT(id) AS counter FROM poll WHERE registrar_id = :registrar_id");
$stmt->execute([':registrar_id' => $clid]);
$counter = $stmt->fetchColumn();
$response = [];
$response['command'] = 'poll';
$response['count'] = $counter;
if ($next_msg_id) {
$response['id'] = $next_msg_id;
} else {
$response['id'] = $id;
}
$response['msg'] = $result['msg'] ?? null;
$response['resultCode'] = 1301;
$response['poll_msg_type'] = $result['msg_type'] ?? null;
$response['lang'] = 'en-US';
$qdate = str_replace(' ', 'T', $result['qdate'] ?? '') . 'Z';