| 1 | ## plugins/sock.py |
|---|
| 2 | ## |
|---|
| 3 | ## Gajim Team: |
|---|
| 4 | ## - Yann Le Boulanger <asterix@lagaule.org> |
|---|
| 5 | ## - Vincent Hanquez <tab@snarc.org> |
|---|
| 6 | ## |
|---|
| 7 | ## Copyright (C) 2003-2005 Gajim Team |
|---|
| 8 | ## |
|---|
| 9 | ## This program is free software; you can redistribute it and/or modify |
|---|
| 10 | ## it under the terms of the GNU General Public License as published |
|---|
| 11 | ## by the Free Software Foundation; version 2 only. |
|---|
| 12 | ## |
|---|
| 13 | ## This program is distributed in the hope that it will be useful, |
|---|
| 14 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | ## GNU General Public License for more details. |
|---|
| 17 | ## |
|---|
| 18 | |
|---|
| 19 | import socket, select |
|---|
| 20 | import pickle |
|---|
| 21 | import Queue |
|---|
| 22 | |
|---|
| 23 | from common import i18n |
|---|
| 24 | _ = i18n._ |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | def XMLescape(txt): |
|---|
| 28 | "Escape XML entities" |
|---|
| 29 | txt = txt.replace("&", "&") |
|---|
| 30 | txt = txt.replace("<", "<") |
|---|
| 31 | txt = txt.replace(">", ">") |
|---|
| 32 | return txt |
|---|
| 33 | |
|---|
| 34 | def XMLunescape(txt): |
|---|
| 35 | "Unescape XML entities" |
|---|
| 36 | txt = txt.replace(">", ">") |
|---|
| 37 | txt = txt.replace("<", "<") |
|---|
| 38 | txt = txt.replace("&", "&") |
|---|
| 39 | return txt |
|---|
| 40 | |
|---|
| 41 | class plugin: |
|---|
| 42 | |
|---|
| 43 | def wait(self, what): |
|---|
| 44 | """Wait for a message from Core""" |
|---|
| 45 | #TODO: timeout |
|---|
| 46 | temp_q = Queue.Queue(50) |
|---|
| 47 | while 1: |
|---|
| 48 | if not self.queueIN.empty(): |
|---|
| 49 | ev = self.queueIN.get() |
|---|
| 50 | if ev[0] == what and ev[2][0] == 'sock': |
|---|
| 51 | #Restore messages |
|---|
| 52 | while not temp_q.empty(): |
|---|
| 53 | ev2 = temp_q.get() |
|---|
| 54 | self.queueIN.put(ev2) |
|---|
| 55 | return ev[2][1] |
|---|
| 56 | else: |
|---|
| 57 | #Save messages |
|---|
| 58 | temp_q.put(ev) |
|---|
| 59 | |
|---|
| 60 | def send(self, event, account, data): |
|---|
| 61 | self.queueOUT.put((event, account, data)) |
|---|
| 62 | |
|---|
| 63 | def handle_queue_quit(self, account, array): |
|---|
| 64 | # for sock in self.active_socket: |
|---|
| 65 | # if sock != self.active_socket: |
|---|
| 66 | # sock.close() |
|---|
| 67 | self.quit_recieved = 1 |
|---|
| 68 | |
|---|
| 69 | def handle_socket_reg_message(self, sock, array): |
|---|
| 70 | for type in array: |
|---|
| 71 | if self.message_types.has_key(type): |
|---|
| 72 | if not sock in self.message_types[type]: |
|---|
| 73 | self.message_types[type].append(sock) |
|---|
| 74 | else: |
|---|
| 75 | self.message_types[type] = [sock] |
|---|
| 76 | |
|---|
| 77 | def send_to_socket(self, ev, sock): |
|---|
| 78 | evp = pickle.dumps(ev) |
|---|
| 79 | sock.send('<'+XMLescape(evp)+'>') |
|---|
| 80 | |
|---|
| 81 | def unparse_socket(self, data): |
|---|
| 82 | list_ev = [] |
|---|
| 83 | while data: |
|---|
| 84 | deb = data.find('<') |
|---|
| 85 | end = data.find('>', deb) |
|---|
| 86 | list_ev.append(pickle.loads(data[deb+1:end])) |
|---|
| 87 | data = data[end+1:] |
|---|
| 88 | return list_ev |
|---|
| 89 | |
|---|
| 90 | def read_queue(self): |
|---|
| 91 | while self.queueIN.empty() == 0: |
|---|
| 92 | ev = self.queueIN.get() |
|---|
| 93 | if ev[0] in self.message_types: |
|---|
| 94 | for sock in self.message_types[ev[0]]: |
|---|
| 95 | self.send_to_socket(ev, sock) |
|---|
| 96 | if ev[0] == 'QUIT': |
|---|
| 97 | self.handle_queue_quit(ev[1], ev[2]) |
|---|
| 98 | # return 1 |
|---|
| 99 | return 0 |
|---|
| 100 | |
|---|
| 101 | def read_socket(self): |
|---|
| 102 | ready_to_read, ready_to_write, in_error = select.select( |
|---|
| 103 | self.active_socket, [], [], 0.1) |
|---|
| 104 | |
|---|
| 105 | for sock in ready_to_read: |
|---|
| 106 | if sock == self.socket: |
|---|
| 107 | conn, addr = self.socket.accept() |
|---|
| 108 | # Connected by addr |
|---|
| 109 | print _("Connection from "), addr |
|---|
| 110 | self.active_socket.append(conn) |
|---|
| 111 | else: |
|---|
| 112 | try: |
|---|
| 113 | data = sock.recv(1024) |
|---|
| 114 | except: |
|---|
| 115 | self.active_socket.remove(sock) |
|---|
| 116 | break |
|---|
| 117 | if not data: |
|---|
| 118 | # disconnected |
|---|
| 119 | print _("disconnected") |
|---|
| 120 | self.active_socket.remove(sock) |
|---|
| 121 | break |
|---|
| 122 | while len(data) == 1024: |
|---|
| 123 | data += sock.recv(1024) |
|---|
| 124 | list_ev = self.unparse_socket(data) |
|---|
| 125 | for ev in list_ev: |
|---|
| 126 | if ev[0] == 'REG_MESSAGE': |
|---|
| 127 | self.handle_socket_reg_message(sock, ev[2]) |
|---|
| 128 | ev = (ev[0], 'sock', ev[2]) |
|---|
| 129 | self.queueOUT.put(ev) |
|---|
| 130 | return 0 |
|---|
| 131 | |
|---|
| 132 | def __init__(self, quIN, quOUT): |
|---|
| 133 | self.queueIN = quIN |
|---|
| 134 | self.queueOUT = quOUT |
|---|
| 135 | self.send('REG_MESSAGE', 'sock', ['QUIT', 'CONFIG']) |
|---|
| 136 | quOUT.put(('ASK_CONFIG', None, ('sock', 'sock', {\ |
|---|
| 137 | 'port':8255}))) |
|---|
| 138 | self.config = self.wait('CONFIG') |
|---|
| 139 | self.message_types = {} |
|---|
| 140 | #create socket |
|---|
| 141 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|---|
| 142 | HOST = socket.gethostbyname(socket.gethostname()) |
|---|
| 143 | if self.config.has_key('host'): |
|---|
| 144 | HOST = socket.gethostbyname(self.config['host']) |
|---|
| 145 | self.socket.bind((HOST, self.config['port'])) |
|---|
| 146 | self.socket.listen(5) |
|---|
| 147 | |
|---|
| 148 | self.active_socket = [self.socket] |
|---|
| 149 | end = 0 |
|---|
| 150 | self.quit_recieved = 0 |
|---|
| 151 | |
|---|
| 152 | while not end: |
|---|
| 153 | # listen to the socket |
|---|
| 154 | end = self.read_socket() |
|---|
| 155 | # listen to the input Queue |
|---|
| 156 | end = self.read_queue() |
|---|
| 157 | if self.quit_recieved: |
|---|
| 158 | if len(self.active_socket) == 1: |
|---|
| 159 | end = 1 |
|---|
| 160 | print _("plugin sock stopped") |
|---|
| 161 | |
|---|
| 162 | if __name__ == "__main__": |
|---|
| 163 | plugin(None, None) |
|---|
| 164 | |
|---|
| 165 | print _("plugin sock loaded") |
|---|