Ensure door opening triggers
[uccvend-vendserver.git] / VendServer / LATClient.py
1 from socket import *
2 from select import select
3 from os import popen4
4 from time import sleep
5 import logging
6
7 LATCP_SOCKET = '/var/run/latlogin'
8
9 LAT_VERSION = '1.22'
10 LAT_VERSION = '1.24' # for running on Mermaid. [DAA] 20071107
11 LATCP_CMD_VERSION = 8
12 LATCP_CMD_TERMINALSESSION = 26
13 LATCP_CMD_ERRORMSG = 99
14
15 class LATClientException(Exception): pass
16
17 def read_for_a_bit(rfh):
18         message = ''
19         while 1:
20                 r = select([rfh], [], [], 5.0)[0]
21                 if r:
22                         try:
23                                 ch = rfh.read(1)
24                         except socket.error:
25                                 ch = ''
26                         if ch == '':
27                                 break
28                         message = message + ch
29                 else:
30                         break
31         logging.debug("Received message: ", repr(message))
32         return message
33
34 def write_and_get_response(rfh, wfh, message, expect_echo=True):
35         logging.debug("Writing message:", repr(message))
36         wfh.write(message+'\r\n')
37         wfh.flush()
38         logging.debug("  --> Sent")
39         response = read_for_a_bit(rfh)
40         if response.find(message) == -1 and expect_echo:
41                 raise LATClientException("Talking to DEC server, expected to find original message in echo but didn't")
42         return response
43
44 class LATClient:
45         def __init__(self, service = None, node = None, port = None,
46                      localport = None, password = None, is_queued = False,
47                      server_name = '', connect_password='', priv_password=''):
48
49                 self.server_name = server_name
50                 self.connect_password = connect_password
51                 self.priv_password = priv_password
52                 
53                 self.sock = socket(AF_UNIX, SOCK_STREAM, 0);
54                 self.sock.connect(LATCP_SOCKET)
55                 self.send_msg(LATCP_CMD_VERSION, LAT_VERSION+'\000')
56                 (cmd, msg) = self.read_reply()
57                 if service == None: service = ''
58                 if node == None: node = ''
59                 if port == None: port = ''
60                 if localport == None: localport = ''
61                 if password == None: password = ''
62                 if is_queued == True:
63                         is_queued = 1
64                 else:
65                         is_queued = 0
66                 self.send_msg(LATCP_CMD_TERMINALSESSION, '%c%c%s%c%s%c%s%c%s%c%s' % \
67                         (is_queued,
68                          len(service), service,
69                          len(node), node,
70                          len(port), port,
71                          len(localport), localport,
72                          len(password), password
73                          ))
74                 (cmd, msg) = self.read_reply()
75                 if ord(cmd) == LATCP_CMD_ERRORMSG:
76                         raise LATClientException(msg)
77
78                 self.rfh = self.sock.makefile('r')
79                 self.wfh = self.sock.makefile('w')
80
81                 r = select([self.rfh], [], [], 2.0)[0]
82                 if r:
83                         l = self.rfh.readline()
84                         if l.find('Service in use') >= 0:
85                                 logging.warning("Service in use, apparently: restarting DEC server")
86                                 self.reboot_server()
87
88         def __del__(self):
89                 try:
90                         self.sock.close()
91                         self.sock.shutdown(2)
92                 except:
93                         pass
94                 del self.sock
95
96         def send_msg(self, cmd, msg):
97                 self.sock.send('%c%c%c%s'%(cmd, len(msg)/256, len(msg)%256, msg))
98
99         def reboot_server(self):
100                 self.sock.shutdown(2)
101                 self.sock.close()
102                 
103                 logging.info('Logging into DEC server')
104                 mopw, mopr = popen4('/usr/sbin/moprc '+self.server_name)
105                 write_and_get_response(mopr, mopw, '')
106
107                 logging.info('Sending password')
108                 r = write_and_get_response(mopr, mopw, self.connect_password, False)
109                 if r.find('Enter username> ') == -1:
110                         logging.warning("Expected username prompt, got " + repr(r))
111                         raise LATClientException('failed to reboot server')
112
113                 logging.info('Sending username')
114                 r = write_and_get_response(mopr, mopw, 'grim reaper')
115                 if r.find('Local> ') == -1:
116                         logging.warning("Expected DEC server prompt, got " + repr(r))
117                         raise LATClientException('failed to reboot server')
118
119                 logging.info('Requesting privileges')
120                 r = write_and_get_response(mopr, mopw, 'set priv')
121                 if r.find('Password> ') == -1:
122                         logging.warning("Expected priv password prompt, got " + repr(r))
123                         raise LATClientException('failed to reboot server')
124
125                 logging.info('Sending password')
126                 r = write_and_get_response(mopr, mopw, self.priv_password, False)
127                 if r.find('Local> ') == -1:
128                         logging.warning("Expected DEC server prompt, got " + repr(r))
129                         raise LATClientException('failed to reboot server')
130
131                 logging.info('Sending reboot request')
132                 r = write_and_get_response(mopr, mopw, 'init del 0')
133                 if r.find('Target does not respond') == -1:
134                         logging.warning("Expected DEC server to die, got " + repr(r))
135                         raise LATClientException('failed to reboot server')
136
137                 logging.info('Closed connection to server')
138                 mopr.close()
139                 mopw.close()
140                 logging.info("Waiting 10 seconds for DEC server to come back to life...")
141                 sleep(10)
142                 logging.info("Rightyo, back to vending!")
143                 raise LATClientException('needed to reboot server')
144
145         def read_reply(self):
146                 head = self.sock.recv(3)
147                 if len(head) != 3:
148                         raise LATClientException('Short LAT packet')
149                 cmd = head[0]
150                 length = ord(head[1])*256 + ord(head[2])
151                 msg = self.sock.recv(length)
152                 if cmd == LATCP_CMD_ERRORMSG:
153                         raise LATClientException('Received LAT error: %s'%msg)
154                 return (cmd, msg)
155         
156         def get_fh(self):
157                 return (self.rfh, self.wfh)

UCC git Repository :: git.ucc.asn.au