Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/chat/p2p.py
blob: f944ba13a13c8e21ec8cd82d9dda958c6918cf9c (plain)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import os
import pwd
import xmlrpclib
import socket
import traceback

import presence
import BuddyList
import network

class GroupRequestHandler(object):
	def __init__(self, group):
		self._group = group

	def message(self, message):
		address = network.get_authinfo()
		self._group.recv(address[0], message)
		return True

class Owner:
	instance = None

	def __init__(self):
		ent = pwd.getpwuid(os.getuid())
		self._nick = ent[0]
		if not self._nick or not len(self._nick):
			self._nick = "n00b"
		self._realname = ent[4]
		if not self._realname or not len(self._realname):
			self._realname = "Some Clueless User"

	def get_realname(self):
		return self._realname

	def get_nick(self):
		return self._nick

	def get_instance():
		if not Owner.instance:
			Owner.instance = Owner()
		return Owner.instance

	get_instance = staticmethod(get_instance)
		
class Group:
	instance = None

	_SERVER_PORT = 6666

	def __init__(self):
		self._pipes = {}

	def get_instance():
		if not Group.instance:
			Group.instance = Group()
			Group.instance.join()
		return Group.instance
	
	get_instance = staticmethod(get_instance)
	
	def join(self):
		self._pannounce = presence.PresenceAnnounce()

		rname = Owner.get_instance().get_realname()
		nick = Owner.get_instance().get_nick()

		self._buddy_list = BuddyList.BuddyList(rname)
		self._buddy_list.start()

		self._pannounce.register_service(rname, self._SERVER_PORT, presence.OLPC_CHAT_SERVICE,
				name = nick, realname = rname)

		self._p2p_req_handler = GroupRequestHandler(self)
		self._p2p_server = network.GlibXMLRPCServer(("", self._SERVER_PORT))
		self._p2p_server.register_instance(self._p2p_req_handler)

		self._gc_controller = network.GroupChatController('224.0.0.221', 6666, self._recv_group_message)
		self._gc_controller.start()

	def get_buddy_list(self):
		return self._buddy_list
	
	def _serialize_msg(self, pipe_id, msg):
		return pipe_id + "|" + msg

	def _deserialize_msg(self, msg):
		sep_index = msg.find("|") 
		pipe_id = msg[0 : sep_index]
		message = msg[sep_index + 1 :]
		return [pipe_id, message]
	
	def send(self, buddy, pipe_id, msg):
		addr = "http://%s:%d" % (buddy.address(), buddy.port())
		peer = xmlrpclib.ServerProxy(addr)
		success = True
		try:
			print self._serialize_msg(pipe_id, msg)
			peer.message(self._serialize_msg(pipe_id, msg))
		except (socket.error, xmlrpclib.Fault, xmlrpclib.ProtocolError), e:
			print "Message Send Error:"
			traceback.print_exc()
			success = False
		return success
	
	def broadcast(self, pipe_id, msg):
		self._gc_controller.send_msg(self._serialize_msg(pipe_id, msg))

	def register_pipe(self, input_pipe):
		self._pipes[input_pipe.get_id()] = input_pipe

	def _recv_group_message(self, msg):
		self.recv(msg['addr'], msg['data'])

	def recv(self, address, message):
		sender = self._buddy_list.find_buddy_by_address(address)
		[pipe_id, msg] = self._deserialize_msg(message)
		pipe = self._pipes[pipe_id]
		if pipe:
			pipe.recv(sender, msg)	

class AbstractPipe:
	def __init__(self, group, pipe_id=None):
		self._group = group
		self._pipe_id = pipe_id 
	
	def get_id(self):
		return self._pipe_id
	
	def send(self, msg):
		pass

class AbstractOutputPipe(AbstractPipe):
	def __init__(self, group, pipe_id=None):
		AbstractPipe.__init__(self, group, pipe_id)
	
	def send(self, msg):
		pass

class OutputPipe(AbstractOutputPipe):
	def __init__(self, group, buddy, pipe_id=None):
		AbstractOutputPipe.__init__(self, group, pipe_id)
		self._buddy = buddy
	
	def send(self, msg):
		return self._group.send(self._buddy, self._pipe_id, msg)

class BroadcastOutputPipe(AbstractOutputPipe):
	def __init__(self, group, pipe_id=None):
		AbstractOutputPipe.__init__(self, group, pipe_id)
	
	def send(self, msg):
		return self._group.broadcast(self._pipe_id, msg)
		
class InputPipe(AbstractPipe):
	def __init__(self, group, pipe_id=None):
		AbstractPipe.__init__(self, group, pipe_id)
		group.register_pipe(self)
	
	def listen(self, callback):
		self.__callback = callback
	
	def recv(self, sender, msg):
		self.__callback(sender, msg)