ultraspeed-epp 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/epp.rb +7 -4
  2. data/lib/epp/server.rb +125 -24
  3. metadata +2 -2
data/lib/epp.rb CHANGED
@@ -1,12 +1,15 @@
1
- require 'openssl'
2
- require 'socket'
3
-
4
1
  $:.unshift(File.dirname(__FILE__)) unless
5
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
3
 
4
+ require 'rubygems'
5
+ require 'openssl'
6
+ require 'socket'
7
+ require 'activesupport'
7
8
  require 'require_parameters'
9
+ require 'rexml/document'
10
+
8
11
  require 'epp/server.rb'
9
12
 
10
13
  module Epp #:nodoc:
11
- VERSION = '1.0'
14
+ VERSION = '1.0.2'
12
15
  end
data/lib/epp/server.rb CHANGED
@@ -1,46 +1,144 @@
1
1
  module Epp #:nodoc:
2
2
  class Server
3
+ include REXML
3
4
  include RequiresParameters
5
+
6
+ attr_accessor :tag, :password, :server, :port, :clTRID
4
7
 
8
+ # ==== Required Attrbiutes
9
+ #
10
+ # * <tt>:server</tt> - The EPP server to connect to
11
+ # * <tt>:tag</tt> - The tag or username used with <tt><login></tt> requests.
12
+ # * <tt>:password</tt> - The password used with <tt><login></tt> requests.
13
+ #
14
+ # ==== Optional Attributes
15
+ #
16
+ # * <tt>:port</tt> - The EPP standard port is 700. However, you can choose a different port to use.
17
+ # * <tt>:clTRID</tt> - The client transaction identifier is an element that EPP specifies MAY be used to uniquely identify the command to the server. You are responsible for maintaining your own transaction identifier space to ensure uniqueness. Defaults to "ABC-12345"
5
18
  def initialize(attributes = {})
6
- requires!(attributes, :server, :port)
19
+ requires!(attributes, :tag, :password, :server)
20
+
21
+ @tag = attributes[:tag]
22
+ @password = attributes[:password]
23
+ @server = attributes[:server]
24
+ @port = attributes[:port] || 700
25
+ @clTRID = attributes[:clTRID] || "ABC-12345"
26
+ end
27
+
28
+ # Sends an XML request to the EPP server, and receives an XML response.
29
+ # <tt><login></tt> and <tt><logout></tt> requests are also wrapped
30
+ # around the request, so we can close the socket immediately after
31
+ # the request is made.
32
+ def request(xml)
33
+ open_connection
34
+
35
+ begin
36
+ login
37
+ @response = send_request(xml)
38
+ ensure
39
+ logout
40
+ close_connection
41
+ end
42
+
43
+ return @response
44
+ end
45
+
46
+ private
47
+
48
+ # Wrapper which sends an XML frame to the server, and receives
49
+ # the response frame in return.
50
+ def send_request(xml)
51
+ send_frame(xml)
52
+ response = get_frame
53
+ end
54
+
55
+ def login
56
+ xml = Document.new
57
+ xml << XMLDecl.new("1.0", "UTF-8", "no")
58
+
59
+ xml.add_element("epp", {
60
+ "xmlns" => "urn:ietf:params:xml:ns:epp-1.0",
61
+ "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
62
+ "xsi:schemaLocation" => "urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"
63
+ })
64
+
65
+ command = xml.root.add_element("command")
66
+ login = command.add_element("login")
67
+
68
+ login.add_element("clID").text = @tag
69
+ login.add_element("pw").text = @password
70
+
71
+ options = login.add_element("options")
72
+ options.add_element("version").text = "1.0"
73
+ options.add_element("lang").text = "en"
74
+
75
+ services = login.add_element("svcs")
76
+ services.add_element("objURI").text = "urn:ietf:params:xml:ns:domain-1.0"
77
+ services.add_element("objURI").text = "urn:ietf:params:xml:ns:contact-1.0"
78
+ services.add_element("objURI").text = "urn:ietf:params:xml:ns:host-1.0"
79
+
80
+ command.add_element("clTRID").text = @clTRID
7
81
 
8
- @connection = TCPSocket.new(attributes[:server], attributes[:port])
82
+ send_request(xml.to_s)
83
+ end
84
+
85
+ def logout
86
+ xml = Document.new
87
+ xml << XMLDecl.new("1.0", "UTF-8", "no")
88
+
89
+ xml.add_element('epp', {
90
+ 'xmlns' => "urn:ietf:params:xml:ns:epp-1.0",
91
+ 'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
92
+ 'xsi:schemaLocation' => "urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"
93
+ })
94
+
95
+ command = xml.root.add_element("command")
96
+ login = command.add_element("logout")
97
+
98
+ send_request(xml.to_s)
99
+ end
100
+
101
+ # Establishes the connection to the server. If the connection is
102
+ # established, then this method will call get_frame and return
103
+ # the EPP <tt><greeting></tt> frame which is sent by the
104
+ # server upon connection.
105
+ def open_connection
106
+ @connection = TCPSocket.new(@server, @port)
9
107
  @socket = OpenSSL::SSL::SSLSocket.new(@connection)
10
108
 
11
- # Initiate the connection to the server through the SSL socket
109
+ # Synchronously close the connection & socket
110
+ @socket.sync_close
111
+
112
+ # Connect
12
113
  @socket.connect
13
114
 
14
- # Receive the EPP <greeting> frame which is sent by the server
15
- # upon initial connection
16
- get_frame
17
- end
18
-
19
- # Sends an XML request to the EPP server, and receives an XML response
20
- def request(xml)
21
- send_frame(xml)
115
+ # Get the initial frame
22
116
  get_frame
23
117
  end
24
118
 
25
- # Closes the connection to the EPP server. It should be noted
26
- # that the EPP specification indicates that clients should send
27
- # a <logout> command before ending the session, so it is recommended
28
- # that you do so.
119
+ # Closes the connection to the EPP server.
29
120
  def close_connection
30
- @socket.close if defined?(@socket) && !@socket.closed?
31
- @connection.close if defined?(@connection) && !@connection.closed?
121
+ if defined?(@socket) and @socket.is_a?(OpenSSL::SSL::SSLSocket)
122
+ @socket.close
123
+ @socket = nil
124
+ end
125
+
126
+ if defined?(@connection) and @connection.is_a?(TCPSocket)
127
+ @connection.close
128
+ @connection = nil
129
+ end
130
+
131
+ return true if @connection.nil? and @socket.nil?
32
132
  end
33
133
 
34
- private
35
-
36
134
  # Receive an EPP frame from the server. Since the connection is blocking,
37
135
  # this method will wait until the connection becomes available for use. If
38
136
  # the connection is broken, a SocketError will be raised. Otherwise,
39
137
  # it will return a string containing the XML from the server.
40
- def get_frame
138
+ def get_frame
41
139
  header = @socket.read(4)
42
140
 
43
- if header.nil? and @socket.closed?
141
+ if header.nil? and @socket.eof?
44
142
  raise SocketError.new("Connection closed by remote server")
45
143
  elsif header.nil?
46
144
  raise SocketError.new("Error reading frame from remote server")
@@ -51,15 +149,18 @@ module Epp #:nodoc:
51
149
  if length < 5
52
150
  raise SocketError.new("Got bad frame header length of #{length} bytes from the server")
53
151
  else
54
- @socket.read(length - 4)
152
+ response = @socket.read(length - 4)
55
153
  end
56
154
  end
57
155
  end
58
156
 
59
157
  # Send an XML frame to the server. Should return the total byte
60
- # size of the frame sent to the server.
158
+ # size of the frame sent to the server. If the socket returns EOF,
159
+ # the connection has closed and a SocketError is raised.
61
160
  def send_frame(xml)
62
- @socket.write([xml.length].pack("N") + xml)
161
+ raise SocketError.new("Connection closed by remote server") if @socket.eof?
162
+
163
+ @socket.write([xml.size + 4].pack("N") + xml)
63
164
  end
64
165
  end
65
166
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ultraspeed-epp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Delsman
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-03 00:00:00 -07:00
12
+ date: 2009-06-04 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15