-
Notifications
You must be signed in to change notification settings - Fork 1
/
VistaConnection.py
113 lines (89 loc) · 3.33 KB
/
VistaConnection.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
from RpcParameter import RpcParameter
__author__ = 'Joe'
import socket
from VistaException import VistaException
from VistaRpc import VistaRpc
class VistaConnection(object):
def __init__(self, host, port):
self.host = host
self.port = port
self.is_connected = False
def connect(self):
my_hostname = socket.gethostname()
my_ip = socket.gethostbyname(my_hostname)
self.socket = None
vista_info = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM)
af, socktype, proto, canonname, sa = vista_info[0]
try:
self.socket = socket.socket(af, socktype, proto)
self.socket.connect(sa)
except socket.error as message:
if self.socket:
self.socket.close();
self.socket = None
raise VistaException('Unable to connect: ' + message)
params = [
RpcParameter(RpcParameter.LITERAL, my_ip),
RpcParameter(RpcParameter.LITERAL, my_hostname)
]
rpc = VistaRpc.prepare('HELLO', params)
try:
response = self.execute(rpc)
except:
raise VistaException('No VistA listener at ' + self.host + ', port ' + self.port)
if response != 'accept':
self.disconnect()
raise VistaException('Connection not accepted: ' + response)
self.is_connected = True
def execute(self, rpc):
self.send(rpc)
return self.recv()
def send(self, rpc):
try:
self.socket.send(rpc)
except socket.error as message:
raise VistaException('Error sending RPC: ' + message)
def recv(self):
# Header first...
buf = self.socket.recv(256)
if buf is None:
raise VistaException('Error receiving: no response')
# SECURITY error?
if buf[0] != "\x00":
buf = buf[1:ord(buf[0])]
raise VistaException('VistA SECURITY error: ' + buf)
# APPLICATION error?
if buf[1] != "\x00":
buf = buf[1:len(buf)]
raise VistaException('VistA APPLICATION error: ' + buf)
buf = buf[2:len(buf)]
# Is there more response?
end_idx = buf.find(VistaRpc.EOT)
# If not, trim the EOT off the end
if end_idx != -1: buf = buf[0:-1]
# Sometimes there's a trailing '\0'
if buf[-1] == "\x00": buf = buf[0:-1]
# Here's the response so far...
response = buf
# Add to it if there's more...
while end_idx == -1:
buf = self.socket.recv(256)
if buf is None:
raise VistaException('Error receiving: no EOT and no MORE')
# Is there more response?
end_idx = buf.find(VistaRpc.EOT)
# If not, trim the EOT off the end
if end_idx != -1: buf = buf[0:-1]
# Sometimes there's a trailing '\0'
if buf[-1] == "\x00": buf = buf[0:-1]
response += buf
# Was there an error?
if response.startswith('M ERROR'):
raise VistaException(response)
return response
def disconnect(self):
if self.is_connected:
rpc = VistaRpc.prepare('BYE')
response = self.execute(rpc)
self.socket.close()
self.is_connected = False