gfsocket.py :  » Web-Frameworks » Zope » Zope-2.6.0 » lib » python » Products » ZGadflyDA » gadfly » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Zope 
Zope » Zope 2.6.0 » lib » python » Products » ZGadflyDA » gadfly » gfsocket.py


"""socket interactions for gadfly client and server"""

from select import select

# responses

SUCCESS = "SUCCESS"
EXCEPTION = "EXCEPTION"
            
def reply_exception(exception, info, socket):
    """send an exception back to the client"""
    # any error is invisible to client
    from gfserve import ServerError
    import sys
    try:
        reply( (EXCEPTION, (exception, info)), socket)
    except:
        #info = "%s %s" % (sys.exc_type, sys.exc_value)
        socket.close()
        #raise ServerError, "reply_exception failed: "+`info`
        
def reply_success(data, socket):
    """report success with data back to client"""
    reply( (SUCCESS, data), socket)
        
def reply(data, socket):
    from marshal import dumps
    marshaldata = dumps(data)
    send_packet(socket, marshaldata)
    socket.close()
    
def send_packet(socket, data):
    """blast out a length marked packet"""
    send_len(data, socket)
    socket.send(data)
    
def send_len(data, socket):
    """send length of data as cr terminated int rep"""
    info = `len(data)`+"\n"
    socket.send(info)
    
def send_certified_action(actor_name, action, arguments, password, socket):
    from marshal import dumps
    marshaldata = dumps( (action, arguments) )
    cert = certificate(marshaldata, password)
    #print actor_name, cert,  marshaldata
    marshaldata = dumps( (actor_name, cert, marshaldata) )
    send_packet(socket, marshaldata)
    
def unpack_certified_data(data):
    from marshal import loads
    # sanity check
    unpack = (actor_name, certificate, marshaldata) = loads(data)
    return unpack
    
def recv_data(socket, timeout=10):
    """receive data or time out"""
    from time import time
    endtime = time() + timeout
    reader = Packet_Reader(socket)
    done = 0
    while not done:
        timeout = endtime - time()
        if timeout<0:
            raise IOError, "socket time out (1)"
        (readable, dummy, error) = select([socket], [], [socket], timeout)
        if error:
            raise IOError, "socket in error state"
        if not readable:
            raise IOError, "socket time out (2)"
        reader.poll()
        done = (reader.mode==READY)
    return reader.data
    
def interpret_response(data):
    """interpret response data, raise exception if needed"""
    from marshal import loads
    (indicator, data) = loads(data)
    if indicator==SUCCESS:
        return data
    elif indicator==EXCEPTION:
        # ???
        raise EXCEPTION, data
    else:
        raise ValueError, "unknown indicator: "+`indicator`
    
# packet reader modes
LEN = "LEN"
DATA = "DATA"
READY = "READY"
ERROR = "ERROR"

BLOCK_SIZE = 4028

LEN_LIMIT = BLOCK_SIZE * 10
    
class Packet_Reader:
    """nonblocking pseudo-packet reader."""
    
    # packets come in as decimal_len\ndata
    # (note: cr! not crlf)
    
    # kick too large requests if set
    limit_len = LEN_LIMIT
    
    def __init__(self, socket):
        self.socket = socket
        self.length = None
        self.length_remaining = None
        self.len_list = []
        self.data_list = []
        self.received = ""
        self.data = None
        self.mode = LEN
        
    def __len__(self):
        if self.mode is LEN:
            raise ValueError, "still reading length"
        return self.length
        
    def get_data(self):
        if self.mode is not READY:
            raise ValueError, "still reading"
        return self.data
        
    def poll(self):
        mode = self.mode
        if mode is READY:
            raise ValueError, "data is ready"
        if mode is ERROR:
            raise ValueError, "socket error previously detected"
        socket = self.socket
        (readable, dummy, error) = select([socket], [], [socket], 0)
        if error:
            self.socket.close()
            self.mode = ERROR
            raise ValueError, "socket is in error state"
        if readable:
            if mode is LEN:
                self.read_len()
            # note: do not fall thru automatically
            elif mode is DATA:
                self.read_data()
                
    def read_len(self):
        """assume socket is readable now, read length"""
        socket = self.socket
        received = self.received
        len_list = self.len_list
        if not received:
            # 10 bytes at a time until len is read.
            received = socket.recv(10)
        while received:
            # consume, test one char
            input = received[0]
            received = received[1:]
            if input == "\n":
                # done reading length
                from string import join,atoi
                try:
                    length = self.length = atoi(join(len_list, ""))
                except:
                    self.mode = ERROR
                    socket.close()
                    raise ValueError, "bad len string? "+`len_list`
                self.received = received
                self.length_remaining = length
                self.mode = DATA
                limit_len = self.limit_len
                if limit_len and length>limit_len:
                    raise ValueError, "Length too big: "+`(length, limit_len)`
                return
            if len(len_list)>10:
                self.mode = ERROR
                socket.close()
                raise ValueError, "len_list too long: "+`len_list`
            len_list.append(input)
            if not received:
                (readable, dummy, error) = select(\
                   [socket], [], [socket], 0)
                if error:
                    self.mode = ERROR
                    socket.close()
                    raise ValueError, "socket in error state"
                if readable:
                    received = socket.recv(10)
        # remember extra data received.
        self.received = received

    def read_data(self):
        # assume socket is readable
        socket = self.socket
        received = self.received
        length_remaining = self.length_remaining
        data_list = self.data_list
        if received:
            data_list.append(received)
            self.received = ""
            length_remaining = length_remaining - len(received)
        recv_len = max(length_remaining, BLOCK_SIZE)
        received = socket.recv(recv_len)
        if received:
            data_list.append(received)
            length_remaining = length_remaining - len(received)
        if length_remaining<1:
            self.mode = READY
            from string import join
            self.data = join(data_list, "")
        self.length_remaining = length_remaining

def certificate(String, password):
    """generate a certificate for a string, using a password"""
    from md5 import new
    if not String:
        raise ValueError, "cannot generate certificate for empty string"
    taggedstring = password + String
    return new(taggedstring).digest()
    
def certify(String, cert, password):
    """check a certificate for a string"""
    return certificate(String, password) == cert

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.