def calculate_and_compare_checksum(self, data):
   calculated_checksum=self.get_checksum(data)
   received_checksum=data[-4:-2]
   print_to_log(
                     'Calculated checsum={}'.format(calculated_checksum),
                     'Received checsum={}'.format(received_checksum)
                     )
   return self.compare_checksum(received_checksum,calculated_checksum)
 def list_wait(self):
     print_to_log(
         'Listening to {} , {} , {} '.format(
             list(map(socket.socket.fileno, self.read_set)),
             list(map(socket.socket.fileno, self.write_set)),
             list(map(socket.socket.fileno, self.error_set))),
         'Heard from for {} , {} , {} '.format(
             list(map(socket.socket.fileno, self.readable)),
             list(map(socket.socket.fileno, self.writable)),
             list(map(socket.socket.fileno, self.exceptional))))
 def manage_write(self):
     #Send message in response to write_set->select->writable initiated by manage_read() and initiate_write()
     print_to_log('Following will be sent', self.write_msg)
     try:
         self.conn[0].send(self.write_msg)
         self.write_msg = ''  #not in astm. because status
     except Exception as my_ex:
         print_to_log("Disconnection from client?", my_ex)
     self.write_set.remove(
         self.conn[0])  #now no message pending, so remove it from write set
     self.error_set = self.read_set.union(self.write_set)  #update error set
Beispiel #4
0
    def manage_read(self, data):
        #EOF is handled in base class
        #for receiving data
        if (data == b'\x05'):
            signal.alarm(0)
            self.main_status = 1
            self.write_msg = b'\x06'
            self.write_set.add(
                self.conn[0]
            )  #Add in write set, for next select() to make it writable
            self.error_set = self.read_set.union(
                self.write_set)  #update error set

            #new file need not be class global (unlike existing file -> which needs to be deleted)
            new_file = self.get_inbox_filename()
            self.fd = open(new_file, 'wb')
            fcntl.flock(self.fd, fcntl.LOCK_EX | fcntl.LOCK_NB)  #lock file
            #Now use this fd for stx-etb/etx frame writing
            self.fd.write(data)
            print_to_log('File Content written:', data)

            signal.alarm(self.alarm_time)

        elif (data[-1:] == b'\x0a'):
            signal.alarm(0)

            if (self.calculate_and_compare_checksum(data) == True):
                print_to_log('checksum matched:', 'Proceeding to write data')
                self.fd.write(data)
                print_to_log('File Content written:', data)

                self.write_msg = b'\x06'
                self.write_set.add(
                    self.conn[0]
                )  #Add in write set, for next select() to make it writable
                self.error_set = self.read_set.union(
                    self.write_set)  #update error set
            else:
                print_to_log('checksum mismatched:', 'Proceeding to send NAK')
                self.write_msg = b'\x15'
                self.write_set.add(
                    self.conn[0]
                )  #Add in write set, for next select() to make it writable
                self.error_set = self.read_set.union(
                    self.write_set)  #update error set

            signal.alarm(self.alarm_time)

        elif (data == b'\x04'):
            signal.alarm(0)

            self.fd.write(data)
            print_to_log('File Content written:', data)

            self.fd.close()
            self.main_status = 0
            self.send_status = 0

        elif (data == b'\x06'):  #ACK when sending

            print_to_log("main_status", self.main_status)
            print_to_log("send_status", self.send_status)
            print_to_log("total_lines", self.total_lines)
            print_to_log("current_line", self.current_line)
            print_to_log("byte_data_list", self.byte_data_list)

            if ((self.send_status == 1 or self.send_status == 2)
                    and (self.current_line < self.total_lines
                         or self.current_line == 0)):
                signal.alarm(0)
                self.send_status = 2
                print_to_log('send_status=={}'.format(self.send_status),
                             'post-ENQ ACK')

                #writing

                self.write_set.add(
                    self.conn[0]
                )  #Add in write set, for next select() to make it writable
                self.error_set = self.read_set.union(
                    self.write_set)  #update error set
                print_to_log('######current line: ', self.current_line)

                if (self.current_line == 0):  #open, set data
                    self.get_first_outbox_file()  #set current_outbox file
                    fd = open(self.outbox_data + self.current_outbox_file,
                              'rb')

                    #data must not be >1024
                    #it will be ETX data , not ETB data
                    #Frame number will always be one and only one
                    #line by line data setup
                    self.byte_data_list = fd.read(2024).split(b'\x0a')
                    print_to_log('byte_data_list', self.byte_data_list)

                    self.total_lines = len(
                        self.byte_data_list
                    ) - 1  #python split alway return minimum 1 len list
                    self.current_line = 0
                    print_to_log('total_lines', self.total_lines)
                    print_to_log('current line: ', self.current_line)

                byte_data = self.byte_data_list[self.current_line] + b'\x0a'
                print_to_log('File Content', byte_data)
                chksum = self.get_checksum(byte_data)
                print_to_log('CHKSUM', chksum)
                self.write_msg = byte_data  #set message
                self.current_line = self.current_line + 1

                #self.send_status=3
                #data sent -> change status only when really data of stx-lf or anyother-inappropriate frame really sent

                #print_to_log('send_status=={}'.format(self.send_status),'changed send_status to 3 (data sent to write buffer)')
                #writing end
                signal.alarm(self.alarm_time)  #wait for receipt of second ack

            elif (self.send_status == 3):
                signal.alarm(0)
                self.send_status = 4
                print_to_log('send_status=={}'.format(self.send_status),
                             'post-LF ACK')

                #write
                self.write_set.add(
                    self.conn[0]
                )  #Add in write set, for next select() to make it writable
                self.error_set = self.read_set.union(
                    self.write_set)  #update error set
                self.write_msg = b'\x04'  #set message EOT
                print_to_log("main_status", self.main_status)
                print_to_log("send_status", self.send_status)
                print_to_log("total_lines", self.total_lines)
                print_to_log("current_line", self.current_line)
                print_to_log("byte_data_list", self.byte_data_list)
                self.current_line = 0
                self.total_lines = 0
                print_to_log("main_status", self.main_status)
                print_to_log("send_status", self.send_status)
                print_to_log("total_lines", self.total_lines)
                print_to_log("current_line", self.current_line)
                print_to_log("byte_data_list", self.byte_data_list)
                self.archive_outbox_file()
                #self.send_status=0                                    #change only where actually sent
                #self.main_status=0                                   #change only where actually sent
                #print_to_log('send_status=={}'.format(self.send_status),'sent EOT')
                #print_to_log('main_status=={}'.format(self.main_status),'connection is now, neutral')
                #write end
                #alarm not required, no expectation signal.alarm(self.alarm_time)
                signal.alarm(
                    self.alarm_time
                )  #when EOT is really sent, change status, or if nothing is sent change status using alarm

        elif (data == b'\x15'):  #NAK
            signal.alarm(0)
            self.send_status = 4
            print_to_log('send_status=={}'.format(self.send_status),
                         'post-ENQ/LF NAK. Some error')

            #write - same as above
            self.write_set.add(
                self.conn[0]
            )  #Add in write set, for next select() to make it writable
            self.error_set = self.read_set.union(
                self.write_set)  #update error set
            self.write_msg = b'\x04'  #set message EOT
            self.archive_outbox_file()
            #self.send_status=0                                    #only when actually sent
            #self.main_status=0
            print_to_log('send_status=={}'.format(self.send_status),
                         'initiate_write() sent EOT')
            print_to_log('main_status=={}'.format(self.main_status),
                         'initiate_write() now, neutral')
            #write end
            #alarm not required, no expectation signal.alarm(self.alarm_time)
            signal.alarm(
                self.alarm_time
            )  #when EOT is really sent then change status , or if nothing is sent change status
Beispiel #5
0
    def signal_handler(self, signal, frame):
        print_to_log('Alarm Stopped',
                     'Signal:{} Frame:{}'.format(signal, frame))
        print_to_log('change statuses ', ' and close file')

        print_to_log(
            'main_status={} send_status={}'.format(self.main_status,
                                                   self.send_status),
            ' -->previous ')
        self.send_status = 0  #data sent
        self.main_status = 0
        print_to_log(
            'current main_status={} send_status={}'.format(
                self.main_status, self.send_status), ' -->current ')

        try:
            if self.fd != None:
                self.fd.close()
                print_to_log('self.signal_handler()', 'file closed')
        except Exception as my_ex:
            print_to_log('self.signal_handler()',
                         'error in closing file:{}'.format(my_ex))

        print_to_log('Alarm..response NOT received in stipulated time',
                     'data receving/sending may be incomplate')
Beispiel #6
0
    def manage_write(self):
        #common code
        #Send message in response to write_set->select->writable initiated by manage_read() and initiate_write()
        print_to_log('Following will be sent', self.write_msg)

        try:
            self.conn[0].send(self.write_msg)
            #self.write_msg='' #not here because write message is evaluated below
        except Exception as my_ex:
            print_to_log("Disconnection from client?", my_ex)

        self.write_set.remove(
            self.conn[0])  #now no message pending, so remove it from write set
        self.error_set = self.read_set.union(self.write_set)  #update error set

        #specific code for ASTM status update
        #if sending: ENQ, ...LF, EOT is sent
        #ff receiving: ACK, NAK sent (ACK sending donot need to change status, it activates only alarm
        if (self.write_msg == b'\x04'):  #if EOT sent
            self.main_status = 0
            self.send_status = 0
            print_to_log(
                'main_status={} send_status={}'.format(self.main_status,
                                                       self.send_status),
                '.. because EOT is sent')
            signal.alarm(0)
            print_to_log('Neutral State', '.. so stopping alarm')
        elif (self.write_msg[-1:] == b'\x0a'):  #if main message sent
            if (self.current_line >= self.total_lines):
                self.send_status = 3
                print_to_log(
                    'main_status={} send_status={}'.format(
                        self.main_status, self.send_status),
                    '.. because message is sent(LF)')
            else:
                pass  #donot change status

        elif (self.write_msg == b'\x05'):  #if enq sent
            self.send_status = 1
            print_to_log(
                'main_status={} send_status={}'.format(self.main_status,
                                                       self.send_status),
                '.. because ENQ is sent')
        elif (self.write_msg == b'\x06'):  #if ack sent
            print_to_log(
                'main_status={} send_status={}'.format(self.main_status,
                                                       self.send_status),
                '.. no change in status ACK is sent')

        elif (self.write_msg == b'\x15'):  #if NAK sent = EOT sent
            self.main_status = 0
            self.send_status = 0
            print_to_log(
                'main_status={} send_status={}'.format(self.main_status,
                                                       self.send_status),
                '.. because NAK is sent. going neutral')
            signal.alarm(0)
            print_to_log('Neutral State', '.. so stopping alarm')
        else:  #if data stream is incomplate/inappropriate containing EOT etc
            self.send_status = 3
            print_to_log(
                'main_status={} send_status={}'.format(self.main_status,
                                                       self.send_status),
                '.. incomplate message (without LF) sent. EOT will be sent in next round'
            )
Beispiel #7
0
 def initiate_write(self):
     print_to_log(
         'main_status={} send_status={}'.format(self.main_status,
                                                self.send_status),
         'Entering initiate_write()')
     if (self.main_status == 0):
         print_to_log('main_status=={}'.format(self.main_status),
                      'initiate_write() will find some pending work')
         if (self.get_first_outbox_file() == True
             ):  #There is something to work
             signal.alarm(0)
             self.main_status = 2  #announce that we are busy sending data
             print_to_log(
                 'main_status=={}'.format(self.main_status),
                 'initiate_write() changed main_status to 2 to send data')
             self.write_set.add(
                 self.conn[0]
             )  #Add in write set, for next select() to make it writable
             self.error_set = self.read_set.union(
                 self.write_set)  #update error set
             self.write_msg = b'\x05'  #set message ENQ
             #self.send_status=1                                    #status to ENQ sent only when written
             print_to_log('send_status=={}'.format(self.send_status),
                          'initiate_write() sent ENQ to write buffer')
             signal.alarm(self.alarm_time)  #wait for receipt of 1st ACK
         else:
             print_to_log('main_status=={}'.format(self.main_status),
                          'no data in outbox. sleeping for a while')
             return
     else:
         print_to_log(
             'main_status={} send_status={}'.format(self.main_status,
                                                    self.send_status),
             'busy somewhre.. initiate_write() will not initiate anything')
    def __init__(self, host_address, host_port, select_timeout):
        #logging.basicConfig(filename=conf.log_filename,level=logging.CRITICAL)
        #logging.basicConfig(filename=conf.log_filename,level=logging.DEBUG)
        #self.logger = logging.getLogger('astm_bidirectional_general')
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        self.s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
        self.s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 3)
        self.s.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
        self.select_timeout = select_timeout  #second
        self.host_address = host_address
        self.host_port = host_port
        try:
            self.s.bind(
                (self.host_address, int(self.host_port)))  #it is a tuple
        except Exception as my_exception:
            print_to_log(my_exception,
                         'bind() failed, ip/port correct??Quitting')
            quit()
        self.s.listen(2)

        print_to_log(self.s, 'select() is waiting..')
        self.readable, self.writable, self.exceptional = select.select(
            (self.s, ), (self.s, ), (self.s, ))
        print_to_log(self.s, 'select() detected activity')
        if (self.s in self.exceptional):
            print_to_log(self.s, 'some error on socket s. quitting')
            quit()
        if (self.s in self.writable):
            print_to_log(self.s, 'Can not understand why s is writting')
            quit()
        if (self.s in self.readable):
            self.conn = self.s.accept()
            print_to_log(self.s, 'Connection request is read')
            self.conn[0].setblocking(0)
    def astmg_loop(self):
        #First set
        #not tuple it is unmutable
        #not list, we need uniq values in error list which is sum of read and write

        self.read_set = {self.s, self.conn[0]}
        self.write_set = set(
        )  #must be managed when send is required, otherwise use 100% CPU to check writable buffer
        self.error_set = self.read_set.union(self.write_set)

        while True:
            #self.print_to_log('','before select')
            self.readable, self.writable, self.exceptional = select.select(
                self.read_set, self.write_set, self.error_set,
                self.select_timeout)
            #self.print_to_log('','after select')
            self.list_wait()
            ###if anybody else try to connect, reject it

            if (self.s in self.exceptional):
                print_to_log(self.s, 'some error on socket s. quitting')
                self.s.shutdown(socket.SHUT_RDWR)
                self.s.close()
                break

            if (self.s in self.writable):
                print_to_log(self.s, 'Can not understand why s is writting')
                self.s.shutdown(socket.SHUT_RDWR)
                self.s.close()
                break

            if (self.s in self.readable):
                dummy_conn = self.s.accept()
                print_to_log(
                    self.s,
                    'Connection request is read, This is second connection. We do not want it. shutdown, close'
                )
                dummy_conn[0].shutdown(socket.SHUT_RDWR)
                dummy_conn[0].close()

            ###For client do work
            if (self.conn[0] in self.exceptional):
                print_to_log(self.conn[0],
                             'some error on socket conn. quitting')
                self.s.shutdown(socket.SHUT_RDWR)
                self.s.close()
                break

            if (self.conn[0] in self.writable):
                #sending message (somewhere else conn[0] was added in writable and self.write_msg was given value
                print_to_log(self.conn[0],
                             'conn is writable. using manage_write()')
                self.manage_write()

            if (self.conn[0] in self.readable):
                print_to_log(
                    self.conn[0],
                    'Conn have sent some data. now using recv() and manage_read()'
                )
                try:
                    data = self.conn[0].recv(1024)
                    print_to_log('Following is received:', data)
                    self.manage_read(data)
                except Exception as my_exception:
                    print_to_log(
                        my_exception,
                        'recv() failed. something sent and then connection closed'
                    )
                    self.s.shutdown(socket.SHUT_RDWR)
                    self.s.close()
                    '''to prevent: DEBUG:root:[Errno 110] Connection timed out recv() failed. something sent and then connection closed
          DEBUG:root:[Errno 98] Address already in use bind() failed, ip/port correct??Quitting'''
                    break

                #only EOF is handled here, rest is handled in manage_read()
                #if EOF 1)close socket 2)remove from list 3)accept new
                if (data == b''):
                    print_to_log(self.conn[0],
                                 'Conn have closed, accepting new connection')

                    #1) close socket
                    try:
                        self.conn[0].shutdown(socket.SHUT_RDWR)
                        self.conn[0].close()
                    except Exception as my_ex:
                        print_to_log('Connection from client closed??', my_ex)

                    #2)remove from read list

                    #no if:() for read_set because, we reached here due to its presence in read_set
                    self.read_set.remove(self.conn[0])
                    #write list with if exist
                    if (self.conn[0] in self.write_set):
                        self.write_set.remove(self.conn[0])
                    #error list is union
                    #so, no need to manage
                    #finally error_set
                    self.error_set = self.read_set.union(self.write_set)

                    #3) Accept new, add to read set, this is blocking here. No need to go for initiate_write, because nothing to do
                    self.conn = self.s.accept()
                    print_to_log(self.s, 'New Connection request is read')
                    self.conn[0].setblocking(0)
                    self.read_set.add(self.conn[0])
                    self.error_set = self.read_set.union(self.write_set)

            self.initiate_write()