Example #1
0
    def __init__(self, cond):

        self.channels = {}
        self.processes = {}
        self.guards = {}

        # Unknown messages, which is moved to known messages, if a channel or processes with a matching name registers.
        # TODO: This must be capped.
        self.channels_unknown = {}
        self.processes_unknown = {}

        self.cond = cond

        host = conf.get(PYCSP_HOST)
        port = conf.get(PYCSP_PORT)
        if port == 0 and ENVVAL_PORT in os.environ:
            port = int(os.environ[ENVVAL_PORT])
        if host == '' and ENVVAL_HOST in os.environ:
            host = os.environ[ENVVAL_HOST]

        host = host.encode()

        addr = (host, port)

        self.server_socket, self.server_addr = ossocket.start_server(addr)
        self.server_addr = (self.server_addr[0].encode(), self.server_addr[1])

        self.active_socket_list = [self.server_socket]
        self.active_socket_list_add = []

        self.thread = None

        self.handler = ossocket.ConnHandler()
Example #2
0
    def run(self):

        #print "Starting SocketThread"
        handler = ossocket.ConnHandler()

        while (not self.finished):

            # Performing select.select on possibly EBADF. A lingering socket may be left in the active_socket_list.
            # The following select.select is robust against Bad File Descriptors, and will remove them from the active_socket_list
            # The only way to test for a bad file descriptor, is to cause a socket.error exception.

            OK = False
            while (not OK):
                import socket
                try:
                    ready, _, exceptready = select.select(
                        self.data.active_socket_list, [], [], 10.0)
                    OK = True
                except:
                    new_socket_list = []
                    for s in self.data.active_socket_list:
                        try:
                            if s.fileno() > 0:
                                new_socket_list.append(s)
                        except socket.error:
                            # Ignoring EBADF file descriptor errors
                            pass
                        except ValueError:
                            # Ignoring file descriptors with a value of -1
                            pass
                    self.data.active_socket_list = new_socket_list
            # Select finished OK

            if not ready and not exceptready:
                # Timeout. Invoke ticks
                self.cond.acquire()
                for c in list(self.channels.values()):
                    c.timeout_tick()
                self.cond.release()

            else:
                for s in ready:
                    if s == self.data.server_socket:
                        conn, _ = self.data.server_socket.accept()
                        self.data.active_socket_list.append(conn)
                    else:
                        header = Header()
                        header.cmd = ERROR_CMD
                        self.cond.acquire()
                        try:
                            s.recv_into(header)
                        except ossocket.socket.error as e:
                            if e.errno == errno.ECONNRESET:
                                # Connection has been reset
                                header.cmd = ERROR_CMD
                            else:
                                raise
                        self.cond.release()

                        if header.cmd == ERROR_CMD:
                            # connection disconnected
                            if s in self.data.active_socket_list:
                                self.data.active_socket_list.remove(s)
                            s.close()
                        else:
                            if (header.cmd & HAS_PAYLOAD):
                                self.cond.acquire()
                                payload = ossocket.recvall(s, header.arg)
                                self.cond.release()
                            else:
                                payload = ""

                            m = Message(header, payload)

                            if (header.cmd & NATFIX):
                                # save reverse socket as payload
                                m.natfix = s

                            self.cond.acquire()
                            if (header.cmd == SOCKETTHREAD_PING):
                                if self.data.active_socket_list_add:
                                    self.data.active_socket_list.extend(
                                        self.data.active_socket_list_add)
                                    self.data.active_socket_list_add = []

                            elif (header.cmd == SOCKETTHREAD_SHUTDOWN):
                                if self.channels or self.processes:
                                    # Socketthread is still busy. Thus ignore and expect a later call to deregister to invoke stopThread.
                                    pass
                                else:
                                    self.finished = True

                                    # Remove thread reference
                                    self.data.thread = None

                                # Do not close sockets as the socketthread may be restarted at a later time

                            elif (header.cmd & PROCESS_CMD):
                                if header.id in self.processes:
                                    p = self.processes[header.id]
                                    p.handle(m)
                                elif (header.cmd & REQ_REPLY):
                                    raise FatalException(
                                        "A REQ_REPLY message should always be valid!"
                                    )
                                elif (header.cmd & IGN_UNKNOWN):
                                    raise FatalException(
                                        "IGN_UNKNOWN should never occur!")
                                else:
                                    if not header.id in self.data.processes_unknown:
                                        self.data.processes_unknown[
                                            header.id] = []
                                    self.data.processes_unknown[
                                        header.id].append(m)

                            else:
                                if header.id in self.channels:
                                    c = self.channels[header.id]
                                    if (header.cmd & IS_REPLY):
                                        c.put_reply(m)
                                    else:
                                        c.put_normal(m)
                                elif (header.cmd & IGN_UNKNOWN):
                                    pass
                                else:
                                    if not header.id in self.data.channels_unknown:
                                        self.data.channels_unknown[
                                            header.id] = QueueBuffer()

                                    c = self.data.channels_unknown[header.id]

                                    if (header.cmd & IS_REPLY):
                                        c.put_reply(m)
                                    else:
                                        c.put_normal(m)
                            self.cond.release()
Example #3
0
    def run(self):

        #print "Starting SocketThread"
        handler = ossocket.ConnHandler()

        while (not self.finished):
            ready, _, exceptready = select.select(self.data.active_socket_list,
                                                  [], [], 10.0)
            if not ready and not exceptready:
                # Timeout. Invoke ticks
                self.cond.acquire()
                for c in self.channels.values():
                    c.timeout_tick()
                self.cond.release()

            else:
                for s in ready:
                    if s == self.data.server_socket:
                        conn, _ = self.data.server_socket.accept()
                        self.data.active_socket_list.append(conn)
                    else:
                        header = Header()
                        header.cmd = ERROR_CMD
                        self.cond.acquire()
                        try:
                            s.recv_into(header)
                        except ossocket.socket.error as e:
                            if e.errno == errno.ECONNRESET:
                                # Connection has been reset
                                header.cmd = ERROR_CMD
                            else:
                                raise
                        self.cond.release()

                        if header.cmd == ERROR_CMD:
                            # connection disconnected
                            if s in self.data.active_socket_list:
                                self.data.active_socket_list.remove(s)
                            s.close()
                        else:
                            if (header.cmd & HAS_PAYLOAD):
                                self.cond.acquire()
                                payload = ossocket.recvall(s, header.arg)
                                self.cond.release()
                            else:
                                payload = ""

                            m = Message(header, payload)

                            if (header.cmd & NATFIX):
                                # save reverse socket as payload
                                m.natfix = s

                            self.cond.acquire()
                            if (header.cmd == SOCKETTHREAD_PING):
                                if self.data.active_socket_list_add:
                                    self.data.active_socket_list.extend(
                                        self.data.active_socket_list_add)
                                    self.data.active_socket_list_add = []

                            elif (header.cmd == SOCKETTHREAD_SHUTDOWN):
                                if self.channels or self.processes:
                                    # Socketthread is still busy. Thus ignore and expect a later call to deregister to invoke stopThread.
                                    pass
                                else:
                                    self.finished = True

                                    # Remove thread reference
                                    self.data.thread = None

                                # Do not close sockets as the socketthread may be restarted at a later time

                            elif (header.cmd & PROCESS_CMD):
                                if header.id in self.processes:
                                    self.processes[header.id].handle(m)
                                elif (header.cmd & REQ_REPLY):
                                    raise FatalException(
                                        "A REQ_REPLY message should always be valid!"
                                    )
                                elif (header.cmd & IGN_UNKNOWN):
                                    raise FatalException(
                                        "IGN_UNKNOWN should never occur!")
                                else:
                                    if not header.id in self.data.processes_unknown:
                                        self.data.processes_unknown[
                                            header.id] = []
                                    self.data.processes_unknown[
                                        header.id].append(m)
                            else:
                                if header.id in self.channels:
                                    if (header.cmd & IS_REPLY):
                                        self.channels[header.id].put_reply(m)
                                    else:
                                        self.channels[header.id].put_normal(m)
                                elif (header.cmd & IGN_UNKNOWN):
                                    pass
                                else:
                                    if not header.id in self.data.channels_unknown:
                                        self.data.channels_unknown[
                                            header.id] = QueueBuffer()

                                    if (header.cmd & IS_REPLY):
                                        self.data.channels_unknown[
                                            header.id].put_reply(m)
                                    else:
                                        self.data.channels_unknown[
                                            header.id].put_normal(m)
                            self.cond.release()