Source code for cmd_tcp

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# 
# Copyright 2012-2017 Frédéric Magniette, Miguel Rubio-Roy
# This file is part of Pyrame.
# 
# Pyrame is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# Pyrame is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
# 
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrame.  If not, see <http://www.gnu.org/licenses/>

import pools,conf_strings,buses,socket
socket.setdefaulttimeout(60)

# TCP_BUS ########################################################

class tcp_bus(buses.buses):
    def __init__(self):
        self.tcp_pool=pools.pool("tcp")
        super(tcp_bus,self).__init__()

    def init(self,tcp_id,conf_string):
        try:
            conf=conf_strings.parse(conf_string)
        except Exception as e:
            return 0,str(e)
        if conf.name!="tcp":
            return 0,"Invalid module name %s in conf_string. Should be tcp"%(conf.name)
        if not conf.has("host","port"):
            return 0,"A required parameter in conf_string is not present"
        host=conf.params["host"]
        port=int(conf.params["port"])
        if conf.has("timeout") and conf.params["timeout"]!="undef":
            timeout=float(conf.params["timeout"])
        else:
            timeout=socket.getdefaulttimeout()
        # Validate parameters
        if (port < 0 or port > 65535):
            return 0,"Invalid destination port: %d"%(port)
        #build the canonical name
        canonical="%s,%s"%(socket.gethostbyname(host),port)
        # Add to the pool
        self.tcp_pool.new(tcp_id,{"name":tcp_id,"host": host, "port": port, "timeout": timeout, "descr":canonical, "connected":0})
        return 1,"ok"

    def deinit(self,tcp_id):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 1,str(e)
        # Check status
        if tcp["connected"]:
            self.inval(tcp_id)
        try:
            self.tcp_pool.remove(tcp_id)
        except Exception as e:
            return 0,str(e)
        return 1,"ok"

    def config(self,tcp_id):
        #get pool object
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        retcode,res=self.ll_new_link(tcp)
        if retcode==0:
            return 0,res
        return 1,tcp["descr"]

    def inval(self,tcp_id):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        self.ll_del_link(tcp)
        return 1,"ok"

    def write(self,tcp_id,mode,data):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        return super(tcp_bus,self).write(tcp,mode,data)

    def read(self,tcp_id,mode,bytes_to_read,timeout="undef"):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        return super(tcp_bus,self).read(tcp,mode,bytes_to_read,timeout)

    def read_until(self,tcp_id,mode,eot,timeout="undef"):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        return super(tcp_bus,self).read_until(tcp,mode,eot,timeout)

    def expect(self,tcp_id,pattern,timeout="undef"):
        try:
            tcp=self.tcp_pool.get(tcp_id)
        except Exception as e:
            return 0,str(e)
        return super(tcp_bus,self).expect(tcp,pattern,timeout)

    def ll_open(self,tcp):
        try:
            s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((tcp["host"],tcp["port"]))
        except:
            return None
        return s

    def ll_close(self,sock):
        try:
            sock.close()
        except:
            print("warning: unable to close socket")
        
    def ll_send(self,sock,tcp,data):
        try:
            if sock.sendall(data) != None:
                return 0,"Error sending data %s to %s:%s"%(data,sock.getpeername()[0],sock.getpeername()[1])
        except Exception as e:
            return 0,"Error sending data %s to %s:%s <- %s"%(data,sock.getpeername()[0],sock.getpeername()[1],str(e))
        return 1,"ok"

    def ll_receive(self,sock,tcp,bytes_to_read,timeout="undef"):
        # Set timeout
        if timeout=="" or timeout=="undef":
            sock.settimeout(tcp["timeout"])
        else:
            sock.settimeout(float(timeout))
        # Read
        bytes_read=0
        try:
            response=""
            while bytes_read<int(bytes_to_read):
                response += sock.recv(int(bytes_to_read)-bytes_read)
                bytes_read=len(response)
                #print("read so far (%d bytes): %s"%(bytes_read,response.encode("hex")))
        except socket.timeout as e:
            return 0,"%s:%s is not responding <- %s"%(sock.getpeername()[0],sock.getpeername()[1],e)
        except Exception as e:
            return 0,"error at tcp to %s:%s <- %s"%(sock.getpeername()[0],sock.getpeername()[1],e)
        return 1,response

# CREATE BUS POOL ################################################

bus=tcp_bus()

# COMMANDS #######################################################

[docs]def init_tcp(tcp_id,conf_string): """Initialize a TCP link. *conf_string* must include: - host: hostname or IP address of the remote device - port: port on the remote device optionally: - timeout: default timeout in seconds for this link. Can be float""" return bus.init(tcp_id,conf_string)
[docs]def deinit_tcp(tcp_id): "Deinitialize and deregister TCP link *tcp_id*." return bus.deinit(tcp_id)
[docs]def config_tcp(tcp_id): "Configure tcp link *tcp_id*." return bus.config(tcp_id)
[docs]def inval_tcp(tcp_id): "Invalidate configuration of tcp link *tcp_id*." return bus.inval(tcp_id)
# WRITE ##########################################################
[docs]def write_tcp(tcp_id,data): "Write *data* to TCP link *tcp_id*." return bus.write(tcp_id,"escaped",data)
[docs]def write_bin_tcp(tcp_id,data): "Write binary *data* to TCP link *tcp_id*. *data* is a string where each character represents 4 bits in hexadecimal base. Little endian for each group of 8 bits." return bus.write(tcp_id,"bin",data)
# READ ###########################################################
[docs]def read_tcp(tcp_id,bytes_to_read,timeout="undef"): "Read up to *bytes_to_read* bytes from TCP link *tcp_id*" return bus.read(tcp_id,"ignore_chars",bytes_to_read,timeout)
[docs]def read_bin_tcp(tcp_id,bytes_to_read,timeout="undef"): "Read up to *bytes_to_read* bytes from TCP link *tcp_id* in binary format. The data read is encoded by blocks of 8 bits with two hexadecimal characters little endian." return bus.read(tcp_id,"bin",bytes_to_read,timeout)
# READ UNTIL #####################################################
[docs]def read_until_tcp(tcp_id,eot,timeout="undef"): "Read from TCP link *tcp_id* until a character from *eot* comma-separated list is found" return bus.read_until(tcp_id,"ignore_chars",eot,timeout)
[docs]def read_bin_until_tcp(tcp_id,eot,timeout="undef"): "Read from TCP link *tcp_id* until a character from *eot* comma-separated list is found. The data read is encoded by blocks of 8 bits with two hexadecimal characters little endian." return bus.read_until(tcp_id,"bin",eot,timeout)
# WRNRD ##########################################################
[docs]def wrnrd_tcp(tcp_id,data,bytes_to_read,timeout="undef"): "Write and read *data* to and from TCP link *tcp_id*" retcode,res=bus.write(tcp_id,"escaped",data) if retcode==0: return 0,res return bus.read(tcp_id,"ignore_chars",bytes_to_read,timeout)
[docs]def wrnrd_bin_tcp(tcp_id,data,bytes_to_read,timeout="undef"): "Write and read binary *data* to and from TCP link *tcp_id*. *data* is a string where each character represents 4 bits in hexadecimal base. Little endian for each group of 8 bits." retcode,res=bus.write(tcp_id,"bin",data) if retcode==0: return 0,res return bus.read(tcp_id,"bin",bytes_to_read,timeout)
# WRNRD_UNTIL ####################################################
[docs]def wrnrd_until_tcp(tcp_id,data,eot,timeout="undef"): "Write and read *data* to and from TCP link *tcp_id* until a character from comma-separated list *eot* is found" retcode,res=bus.write(tcp_id,"escaped",data) if retcode==0: return 0,res return bus.read_until(tcp_id,"ignore_chars",eot,timeout)
[docs]def wrnrd_bin_until_tcp(tcp_id,data,eot,timeout="undef"): "Write and read *data* to and from TCP link *tcp_id* until a character from comma-separated list *eot* is found. *data* is a string where each character represents 4 bits in hexadecimal base. Little endian for each group of 8 bits. Read data is return in the same format." retcode,res=bus.write(tcp_id,"bin",data) if retcode==0: return 0,res return bus.read_until(tcp_id,"bin",eot,timeout)
# EXPECT #########################################################
[docs]def expect_tcp(tcp_id,pattern,timeout="undef"): "Read data from TCP link *tcp_id* until *pattern* is found or timeout." return bus.expect(tcp_id,pattern,timeout)