def accept (self): """Accept a new connection and create a client.""" # Add client. a = self.socket.accept () if self.log: self.log ('[%d] connect from %s' % (self.date, str (a[1]))) c = Hub.Client (self, a[0], self.next_client_id) self.next_client_id += 1 assert self.next_client_id < 256 self.clients[c.id] = c if self.min_clients: self.min_clients -= 1 # Send first date. date = Msg (mex.DATE) date.push ('L', self.date) c.send (date)
def select (self): """Wait until the next event (connection or message) occurs and handle it.""" if not self.min_clients: # Check idle and wanted dates. idle = True min_wait_date = None for c in self.clients.itervalues (): if not c.idle: idle = False break if c.wait_date != None and (c.wait_date < min_wait_date or min_wait_date == None): min_wait_date = c.wait_date # Abort if everyone waits forever. if idle and min_wait_date == None: self.date = None return # Send new date. if idle: self.date = min_wait_date if self.log: self.log ('[%d] date' % self.date) date = Msg (mex.DATE) date.push ('L', self.date) for c in self.clients.itervalues (): c.send (date) # Prepare fdset and select. infds = [ self.socket ] if not self.min_clients: infds += self.clients.values () readyfds = select.select (infds, (), ()) [0] for i in readyfds: if i is self.socket: self.accept () else: i.read ()
def read (self): """Read and dispatch a message from this client.""" # Read message. head = self.socket.recv (calcsize (mex.HEADER_FMT)) if head == '': self.socket.close () del self.hub.clients[self.id] return size, seq = unpack (mex.HEADER_FMT, head) data = self.socket.recv (size) m = Msg (data) if self.hub.log: self.hub.log ('[%d] received from %d(%d): %s' % (self.hub.date, self.id, seq, str (m))) # Dispatch. if m.mtype == mex.IDLE: if seq == self.seq: self.idle = True if len (m): self.wait_date, = m.pop ('L') assert self.wait_date >= self.hub.date else: self.wait_date = None elif m.mtype == mex.DATE: date = Msg (mex.DATE) date.push ('L', self.hub.date) self.send (date) elif m.mtype == mex.REQ: m.pop ('B') mr = Msg (mex.REQ) mr.push ('B', self.id) mr.push (m.pop ()) self.hub.broadcast (mr, self) elif m.mtype == mex.RSP: to, = m.pop ('B') mr = Msg (mex.RSP) mr.push ('B', 0) mr.push (m.pop ()) self.hub.clients[to].send (mr) elif m.mtype == mex.RES: mtype_str = m.pop () mr = Msg (mex.RES) mr.push ('B', self.hub.reserve (mtype_str)) self.send (mr) else: self.hub.broadcast (m, self)