def send(self, packet): released_lock = None if self.locked: if packet.locked == self.locked: tmp_debug("IO", "O => %s: %s" % (self.uid, deprotect(packet.packet))) try: self.socket.sendall(str(packet.packet)) except: self.disconnect() return None released_lock = self.locked if not self.keep_flow: self.locked = 0 else: # just discard, may be too old pass else: # on let events go if not packet.locked: tmp_debug("IO", "O => %s %s" % (self.uid, deprotect(packet.packet))) try: self.socket.sendall(str(packet.packet)) except: self.disconnect() else: # humm, why we get that ?? pass return released_lock
def burials(self): apocalypse = bigtime(-10) for peer in self.peers: if peer and peer.locked and peer.logged and peer.locked < apocalypse: peer.locked = 0 tmp_debug("SQUIRM", "Removing the very old lock of %s" % \ peer.uid)
def handle_line(self): if self.socket: bytes = '' try: bytes = self.socket.recv(4096) except: pass if len(bytes) == 0: self.disconnect() self.buffer += bytes in_lines = self.buffer.split('\n') self.lines.extend([l + '\n' for l in in_lines[:-1]]) self.buffer = in_lines[-1] for line in self.lines: tmp_debug("IO", "%s => O: %s" % (self.uid, deprotect(line))) line = line.strip() # if locked, we are waiting for a result if not self.locked: if line.lower().startswith('action:'): self.action = \ Action(line[line.find(':') + 1:].strip()) elif line == '': if self.action: self.locked = bigtime() self.push(self.action) self.action = None else: if ':' in line: k = line.split(':')[0] v = line[line.find(':') + 1:].strip() if self.action: self.action.add_parameters({k: v}) self.lines = []
def push(self, packet): if packet.name.lower() in STARTING_EVENTS_KEYWORDS: self.keep_flow = True p = dict(emiter=self.id, locked=self.locked, timestamp=time(), packet=packet) tmp_debug("PACKET", "%s (L:%s, KF:%s) >> %s" % (self.uid, self.locked, self.keep_flow, deprotect(str(p)))) self.octopasty.in_queue.put(Packet(p))
def logoff_user(self, packet): client = self.clients.get(packet.emiter) response = Goodbye(parameters=dict(Message="Don't panic.")) p = dict(emiter='__internal__', locked=packet.locked, timestamp=time(), packet=response, dest=client.id) client.send(Packet(p)) tmp_debug("AUTH", "'%s' logout" % packet.emiter[:packet.emiter.find('_')]) client.disconnect()
def handle_line(self): if self.socket: bytes = '' try: bytes = self.socket.recv(4096) except: pass if len(bytes) == 0: self.disconnect() self.buffer += bytes in_lines = self.buffer.split('\n') self.lines.extend([l + '\n' for l in in_lines[:-1]]) self.buffer = in_lines[-1] for line in self.lines: tmp_debug("IO", "%s => O: L: %s D: %s" % ( self.uid, self.locked, deprotect(line))) line = line.strip() if line.startswith('Asterisk Call Manager'): self.login() self.lines = [] return if self.locked and line.lower().startswith('response:'): self.response = \ Response(line[line.find(':') + 1:].strip()) self.event = None elif line.lower().startswith('event:'): name = line[line.find(':') + 1:].strip() self.event = Event(name) self.response = None elif line == '': if self.response: self.push(self.response) self.response = None elif self.event: if self.keep_flow: self.push(self.event) else: self.push(self.event, locked=0) self.event = None else: if ':' in line: sc = line.find(':') k = line[:sc].strip() v = line[sc + 1:].strip() else: k = line v = None if self.response: self.response.add_parameters({k: v}) if self.event: self.event.add_parameters({k: v}) self.lines = []
def run(self): self.listening = True while self.listening: try: self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.bind((self.octopasty.config.get('bind_address'), int(self.octopasty.config.get('bind_port')))) tmp_debug("NETWORK", "Listening on %s %s" % \ (self.octopasty.config.get('bind_address'), self.octopasty.config.get('bind_port'))) self.s.listen(5) while self.listening: channel, details = self.s.accept() st = ServerThread(self.octopasty, channel, details) st.start() except socket.error, e: if e.errno == errno.EADDRINUSE: tmp_debug( "NETWORK", "Address already used trying to bind on %s %s" % \ (self.octopasty.config.get('bind_address'), self.octopasty.config.get('bind_port'))) for timeout in range(0, LISTENING_TIMEOUT): if self.listening == False: break sleep(1) elif e.errno == errno.EINVAL: tmp_debug("NETWORK", "Closing server, time to sleep") self.listening = False else: tmp_debug("NETWORK", "Unknown socket error: %s" % e) self.listening = False
def send(self, packet): if not self.locked: tmp_debug("IO", "O => %s: L: %s D: %s" % ( self.uid, packet.locked, deprotect(packet.packet))) self.socket.sendall(str(packet.packet)) if packet.packet.name.lower() in STARTING_EVENTS_KEYWORDS: self.keep_flow = True tmp_debug("PACKET", "%s Starting flow (L:%s)" % (self.uid, self.locked)) self.locked = packet.locked return self.locked else: return None
def push(self, packet, emiter=None, dest=None, locked=-1): p = dict(emiter=emiter or self.server, locked=locked == -1 and self.locked or locked, timestamp=time(), packet=packet) if dest: p['dest'] = dest tmp_debug("PACKET", "%s (L:%s, KF:%s) >> %s" % (self.uid, self.locked, self.keep_flow, deprotect(p))) self.octopasty.in_queue.put(Packet(p)) if packet.name.lower() in STOPPING_EVENTS_KEYWORDS: self.keep_flow = False tmp_debug("PACKET", "%s Stopping flow (L:%s)" % (self.uid, self.locked))
def auth_user(self, emiter, locked, username, secret, wants_events): login_sucessfull = False client = self.clients.get(emiter) if username in self.config.get('users'): hashed = self.config.get('users').get(username).get('password') if client.authtype is None: if sha1(secret).hexdigest() == hashed: login_sucessfull = True elif client.authtype[0] == 'md5': key = client.authtype[1] _md5 = md5(key) _md5.update(self.config.get('users').get(username).get('password')) if secret == _md5.hexdigest(): login_sucessfull = True if login_sucessfull: old_id = client.id client.id = '%s_%d' % (username, bigtime()) self.clients.pop(old_id) self.clients.update({client.id: client}) client.logged = True _servers = self.config.get('users').get(username).get('servers') _servers = [s.strip() for s in _servers.split(',')] if len(_servers) == 1: client.binded_server = _servers[0] else: client.multiple_servers = _servers client.wants_events = wants_events response = Success(parameters=dict( Message='Authentication accepted')) p = dict(emiter='__internal__', locked=locked, timestamp=time(), packet=response, dest=client.id) tmp_debug("AUTH", "'%s' logged successfully" % username) self.out_queue.put(Packet(p)) else: response = Error(parameters=dict(Message='Authentication failed')) p = dict(emiter='__internal__', locked=locked, timestamp=time(), packet=response, dest=client.id) client.send(Packet(p)) tmp_debug("AUTH", "'%s' failed to login" % username) client.disconnect()
def challenge(self, emiter, locked, authtype): if authtype == 'md5': key = str(randint(100000000, 999999999)) response = Success(parameters=dict( Challenge='%s' % key)) tmp_debug("AUTH", "'%s' asked for '%s' challenge, sent '%s'" % \ (emiter, authtype, key)) else: response = Error(parameters=dict( Message='Authentication type not supported')) client = self.clients.get(emiter) p = dict(emiter='__internal__', locked=locked, timestamp=time(), packet=response, dest=client.id) client.send(Packet(p)) client.authtype = (authtype, key)
def loop(self): looping = True self.listen_clients() while looping: try: self.connect_servers() self.idle() readall(self) squirm(self) burials(self) sendall(self) except KeyboardInterrupt: for ami in self.amis.values(): tmp_debug("NETWORK", "Disconecting from %s" % ami.uid) ami.disconnect() ami.join() for client in self.clients.values(): tmp_debug("NETWORK", "Disconecting %s" % client.uid) client.disconnect() client.join() looping = False self.listener.stop() self.listener.join()
def sendall(self): if not self.out_queue.empty(): outgoing = list(self.out_queue.queue) self.out_queue.queue.clear() for packet in outgoing: tmp_debug("PACKET", "%s << %s" % (packet.dest, deprotect(packet))) if packet.dest == '__internal__': handle_action(self, packet) else: dest = self.get_peer(packet.dest) if dest: # here is another place to check # and requeue if necessary if packet.locked != dest.locked and \ not dest.available: self.out_queue.put(packet) tmp_debug("SQUIRM", "Requeueing on output: %s" % \ deprotect(packet)) continue if not packet.locked and not dest.available: self.out_queue.put(packet) tmp_debug("SQUIRM", "Requeueing on output: %s" % \ deprotect(packet)) continue sent = dest.send(packet) if sent: if str(sent) in self.flow: keep_flow = dest.keep_flow if packet.packet.name.lower() in \ STOPPING_EVENTS_KEYWORDS: keep_flow = False dest.keep_flow = False dest.locked = 0 # then it was an answer if not keep_flow: self.flow.pop("%s" % sent) else: # then it was a query self.flow["%s" % sent] = packet.emiter else: # Then it was an event pass
def logged_on_ami(self, _ami): tmp_debug("AUTH", "Logged on '%s'" % _ami) ami = self.amis.get(_ami) ami.logged = True
def login_failed_on_ami(self, _ami): tmp_debug("AUTH", "Login failed on '%s'" % _ami)
def squirm(self): apocalypse = time() - 10 if not self.in_queue.empty(): incoming = list(self.in_queue.queue) self.in_queue.queue.clear() for packet in incoming: tmp_debug("SQUIRM", "Processing packet %s" % deprotect(packet)) if packet.timestamp < apocalypse: # not puting in the queue and just continuing # makes the packet go nowhere # TODO: figure what to do here, i was thinking about something # if packet.locked: # dest = self.flow.get("%s" % packet.locked) # if dest != '__internal__': # peer = self.get_peer(dest) tmp_debug("SQUIRM", "Removing very old packet: %s" % packet) continue if packet.emiter == '__internal__': peer = self.get_peer(packet.dest) if peer and peer.available: self.out_queue.put(packet) else: self.in_queue.put(packet) else: if packet.locked: if packet.emiter in self.connected_servers: tmp_debug("SQUIRM", "Emiter is server %s" % \ packet.emiter) emiter = self.get_peer(packet.emiter) if emiter.locked and not emiter.keep_flow: emiter.locked = 0 tmp_debug("SQUIRM", "Unlocking emiter %s" % \ emiter.uid) dest = self.flow.get("%s" % packet.locked) if dest: if dest == '__internal__': handle_action(self, packet) else: peer = self.get_peer(dest) if peer and peer.logged: if peer.locked: if peer.locked == packet.locked: packet.dest = dest self.out_queue.put(packet) else: tmp_debug("SQUIRM", "Requeueing packet " \ "from server: %s" % \ deprotect(packet)) self.in_queue.put(packet) else: # just forgot it, and stop flow if any if emiter.keep_flow: emiter.keep_flow = 0 emiter.locked = 0 else: if emiter.keep_flow: emiter.keep_flow = 0 emiter.locked = 0 if packet.emiter in self.connected_clients: tmp_debug("SQUIRM", "Emiter is client %s" % \ packet.emiter) if packet.packet.name.lower() in KEEP_INTERNAL: handle_action(self, packet) continue client = self.get_peer(packet.emiter) if client.logged: cid = client.id.split('_')[0] cu = self.config['users'].get(cid) if cu: cs = client.binded_server if cs: peer = self.get_peer(cs) if peer and peer.logged: if peer.available: # server seems already available # but may be busy just after, # then we need to verify that # in outgoing packets too packet.dest = cs self.out_queue.put(packet) tmp_debug("SQUIRM", "Packet from client " \ "pushed to queue %s" % \ deprotect(packet)) else: # server seems busy self.in_queue.put(packet) tmp_debug("SQUIRM", "Requeueing packet from " " client: %s" % \ deprotect(packet)) else: response = Error( parameters=dict( Message='Server unavailable')) p = dict(emiter=cs, locked=packet.locked, timestamp=time(), packet=response, dest=client.id) self.out_queue.put(Packet(p)) else: if len(client.multiple_servers): response = Error( parameters=dict( Message='Cannot send command ' 'to multiple servers')) p = dict(emiter='__internal__', locked=packet.locked, timestamp=time(), packet=response, dest=client.id) self.out_queue.put(Packet(p)) else: packet.dest = '__internal__' self.out_queue.put(packet) else: # packet not locked if packet.emiter in self.connected_servers: # broadcast events ami = self.get_peer(packet.emiter) if ami.logged: for client in self.connected_clients: peer = self.get_peer(client) if peer.binded_server == packet.emiter or \ packet.emiter in peer.multiple_servers and \ peer.wants_events: p = copy(packet) p.dest = client self.out_queue.put(p) else: # Do not remove that comment and that case # it might be logged one day # ami not logged, and no command before # i wonder what can it be pass