| 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 | import sys |
|---|
| 23 | |
|---|
| 24 | from common import i18n |
|---|
| 25 | _ = i18n._ |
|---|
| 26 | |
|---|
| 27 | |
|---|
| 28 | def XMLescape(txt): |
|---|
| 29 | "Escape XML entities" |
|---|
| 30 | txt = txt.replace("&", "&") |
|---|
| 31 | txt = txt.replace("<", "<") |
|---|
| 32 | txt = txt.replace(">", ">") |
|---|
| 33 | return txt |
|---|
| 34 | |
|---|
| 35 | def XMLunescape(txt): |
|---|
| 36 | "Unescape XML entities" |
|---|
| 37 | txt = txt.replace(">", ">") |
|---|
| 38 | txt = txt.replace("<", "<") |
|---|
| 39 | txt = txt.replace("&", "&") |
|---|
| 40 | return txt |
|---|
| 41 | |
|---|
| 42 | class plugin: |
|---|
| 43 | |
|---|
| 44 | def wait(self, what): |
|---|
| 45 | """Wait for a message from Core""" |
|---|
| 46 | #TODO: timeout |
|---|
| 47 | temp_q = Queue.Queue(50) |
|---|
| 48 | while 1: |
|---|
| 49 | if not self.queueIN.empty(): |
|---|
| 50 | ev = self.queueIN.get() |
|---|
| 51 | if ev[0] == what and ev[2][0] == 'sock': |
|---|
| 52 | #Restore messages |
|---|
| 53 | while not temp_q.empty(): |
|---|
| 54 | ev2 = temp_q.get() |
|---|
| 55 | self.queueIN.put(ev2) |
|---|
| 56 | return ev[2][1] |
|---|
| 57 | else: |
|---|
| 58 | #Save messages |
|---|
| 59 | temp_q.put(ev) |
|---|
| 60 | |
|---|
| 61 | def send(self, event, account, data): |
|---|
| 62 | self.queueOUT.put((event, account, data)) |
|---|
| 63 | |
|---|
| 64 | def handle_queue_quit(self, account, array): |
|---|
| 65 | # for sock in self.active_socket: |
|---|
| 66 | # if sock != self.active_socket: |
|---|
| 67 | # sock.close() |
|---|
| 68 | self.quit_recieved = 1 |
|---|
| 69 | |
|---|
| 70 | def handle_socket_reg_message(self, sock, array): |
|---|
| 71 | for type in array: |
|---|
| 72 | if self.message_types.has_key(type): |
|---|
| 73 | if not sock in self.message_types[type]: |
|---|
| 74 | self.message_types[type].append(sock) |
|---|
| 75 | else: |
|---|
| 76 | self.message_types[type] = [sock] |
|---|
| 77 | |
|---|
| 78 | def send_to_socket(self, ev, sock): |
|---|
| 79 | evp = pickle.dumps(ev) |
|---|
| 80 | sock.send('<'+XMLescape(evp)+'>') |
|---|
| 81 | |
|---|
| 82 | def unparse_socket(self, data): |
|---|
| 83 | list_ev = [] |
|---|
| 84 | while data: |
|---|
| 85 | deb = data.find('<') |
|---|
| 86 | end = data.find('>', deb) |
|---|
| 87 | list_ev.append(pickle.loads(data[deb+1:end])) |
|---|
| 88 | data = data[end+1:] |
|---|
| 89 | return list_ev |
|---|
| 90 | |
|---|
| 91 | def read_queue(self): |
|---|
| 92 | while self.queueIN.empty() == 0: |
|---|
| 93 | ev = self.queueIN.get() |
|---|
| 94 | if ev[0] in self.message_types: |
|---|
| 95 | for sock in self.message_types[ev[0]]: |
|---|
| 96 | self.send_to_socket(ev, sock) |
|---|
| 97 | if ev[0] == 'QUIT': |
|---|
| 98 | self.handle_queue_quit(ev[1], ev[2]) |
|---|
| 99 | # return 1 |
|---|
| 100 | return 0 |
|---|
| 101 | |
|---|
| 102 | def read_socket(self): |
|---|
| 103 | ready_to_read, ready_to_write, in_error = select.select( |
|---|
| 104 | self.active_socket, [], [], 0.1) |
|---|
| 105 | |
|---|
| 106 | for sock in ready_to_read: |
|---|
| 107 | if sock == self.socket: |
|---|
| 108 | conn, addr = self.socket.accept() |
|---|
| 109 | # Connected by addr |
|---|
| 110 | print _("Connection from "), addr |
|---|
| 111 | self.active_socket.append(conn) |
|---|
| 112 | else: |
|---|
| 113 | try: |
|---|
| 114 | data = sock.recv(1024) |
|---|
| 115 | except: |
|---|
| 116 | self.active_socket.remove(sock) |
|---|
| 117 | break |
|---|
| 118 | if not data: |
|---|
| 119 | # disconnected |
|---|
| 120 | print _("disconnected") |
|---|
| 121 | self.active_socket.remove(sock) |
|---|
| 122 | break |
|---|
| 123 | while len(data) == 1024: |
|---|
| 124 | data += sock.recv(1024) |
|---|
| 125 | list_ev = self.unparse_socket(data) |
|---|
| 126 | for ev in list_ev: |
|---|
| 127 | if ev[0] == 'REG_MESSAGE': |
|---|
| 128 | self.handle_socket_reg_message(sock, ev[2]) |
|---|
| 129 | ev = (ev[0], 'sock', ev[2]) |
|---|
| 130 | self.queueOUT.put(ev) |
|---|
| 131 | return 0 |
|---|
| 132 | |
|---|
| 133 | def __init__(self, quIN, quOUT): |
|---|
| 134 | self.queueIN = quIN |
|---|
| 135 | self.queueOUT = quOUT |
|---|
| 136 | self.send('REG_MESSAGE', 'sock', ['QUIT', 'CONFIG']) |
|---|
| 137 | quOUT.put(('ASK_CONFIG', None, ('sock', 'sock', {\ |
|---|
| 138 | 'port':8255}))) |
|---|
| 139 | self.config = self.wait('CONFIG') |
|---|
| 140 | self.message_types = {} |
|---|
| 141 | #create socket |
|---|
| 142 | self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|---|
| 143 | HOST = socket.gethostbyname(socket.gethostname()) |
|---|
| 144 | if self.config.has_key('host'): |
|---|
| 145 | HOST = socket.gethostbyname(self.config['host']) |
|---|
| 146 | try: |
|---|
| 147 | self.socket.bind((HOST, self.config['port'])) |
|---|
| 148 | except: |
|---|
| 149 | print _('plugin sock cannot be launched : ') + \ |
|---|
| 150 | str(sys.exc_info()[1][0:]) |
|---|
| 151 | return |
|---|
| 152 | self.socket.listen(5) |
|---|
| 153 | |
|---|
| 154 | self.active_socket = [self.socket] |
|---|
| 155 | end = 0 |
|---|
| 156 | self.quit_recieved = 0 |
|---|
| 157 | |
|---|
| 158 | while not end: |
|---|
| 159 | # listen to the socket |
|---|
| 160 | end = self.read_socket() |
|---|
| 161 | # listen to the input Queue |
|---|
| 162 | end = self.read_queue() |
|---|
| 163 | if self.quit_recieved: |
|---|
| 164 | if len(self.active_socket) == 1: |
|---|
| 165 | end = 1 |
|---|
| 166 | print _("plugin sock stopped") |
|---|
| 167 | |
|---|
| 168 | if __name__ == "__main__": |
|---|
| 169 | plugin(None, None) |
|---|
| 170 | |
|---|
| 171 | print _("plugin sock loaded") |
|---|