示例#1
0
    def makeRequest(self, request):
        """Connect to the remote HTTP server and send request"""
        self.tcpclient = None
        self.httpparser = None
        port = intval(request.requestobject.get("uri-port", ""))
        if port == None:
            port = 80

        self.tcpclient = self.connectionclass(
            request.requestobject["uri-server"], port)
        self.httpparser = HTTPParser(mode="response")

        self.link((self, "_tcpoutbox"), (self.tcpclient, "inbox"))
        self.link((self, "_tcpsignal"), (self.tcpclient, "control"))
        self.link((self.tcpclient, "signal"), (self, "_tcpcontrol"))

        self.link((self.tcpclient, "outbox"),
                  (self.httpparser,
                   "inbox"))  #incoming TCP data -> HTTPParser directly

        self.link((self, "_parsersignal"), (self.httpparser, "control"))
        self.link((self.httpparser, "outbox"), (self, "_parserinbox"))
        self.link((self.httpparser, "signal"), (self, "_parsercontrol"))

        self.addChildren(self.tcpclient, self.httpparser)
        self.tcpclient.activate()
        self.httpparser.activate()
        self.response = ""
        if isinstance(request.requestobject["request"], str):
            self.send(request.requestobject["request"], "_tcpoutbox")
        else:
            for part in request.requestobject["request"]:
                self.send(part, "_tcpoutbox")
示例#2
0
    def initialiseComponent(self):
        """Create an HTTPParser component to convert the requests we receive
        into a more convenient form, and a HTTPRequestHandler component to
        sort out the correct response to requests received."""

        self.mimehandler = HTTPParser()
        self.httphandler = HTTPRequestHandler(createRequestHandler)
        #self.httphandler.filereader = TriggeredFileReader()

        self.link((self, "mime-control"), (self.mimehandler, "control"))
        self.link((self.mimehandler, "signal"), (self, "mime-signal"))

        self.link((self.mimehandler, "outbox"), (self.httphandler, "inbox"))

        self.link((self, "http-control"), (self.httphandler, "control"))
        self.link((self.httphandler, "signal"), (self, "http-signal"))

        self.addChildren(self.mimehandler,
                         self.httphandler)  #self.httphandler.filereader)
        self.httphandler.activate()
        self.mimehandler.activate()
        #self.httphandler.filereader.activate()

        self.link((self.httphandler, "outbox"), (self, "outbox"),
                  passthrough=2)
        self.link((self, "inbox"), (self.mimehandler, "inbox"), passthrough=1)
示例#3
0
 def handle_packets(self, packet):
     global STOP
     if STOP:
         print("stop sniff")
         return
     nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
     global PACKET_NUM
     PACKET_NUM += 1
     lenth = len(packet)
     ip_forward(packet)
     if int(packet.getlayer(Ether).type) == 34525:
         self.ipv6_count += 1
         proto = 'IPv6'
         src = str(packet.getlayer(IPv6).src)
         dst = str(packet.getlayer(IPv6).dst)
         info = str(packet.summary())
         self.newPacketCatched.emit(str(PACKET_NUM), nowTime, src, dst,
                                    proto, str(lenth), info)
         PACKETS.append(packet)
     elif int(packet.getlayer(Ether).type) == 2048:
         self.ipv4_count += 1
         src = str(packet.getlayer(IP).src)
         dst = str(packet.getlayer(IP).dst)
         info = str(packet.summary())
         proto = ''
         if int(packet.getlayer(IP).proto) == 6:
             self.tcp_count += 1
             proto = 'TCP'
             if packet.haslayer(TCP):
                 if HTTPParser.isHTTP(packet):
                     self.http_count += 1
                     proto = 'HTTP'
                     info = HTTPParser.generateInfo(packet)
         elif int(packet.getlayer(IP).proto) == 17:
             proto = 'UDP'
             self.udp_count += 1
         elif int(packet.getlayer(IP).proto) == 1:
             proto = 'ICMP'
             self.icmp_count += 1
         self.newPacketCatched.emit(str(PACKET_NUM), nowTime, src, dst,
                                    proto, str(lenth), info)
         PACKETS.append(packet)
     elif int(packet.getlayer(Ether).type) == 2054:
         proto = 'ARP'
         self.arp_count += 1
         src = str(packet.getlayer(ARP).psrc)
         dst = str(packet.getlayer(ARP).pdst)
         info = str(packet.summary())
         #self.packet_table.row_append(src, dst, proto, info)
         self.newPacketCatched.emit(str(PACKET_NUM), nowTime, src, dst,
                                    proto, str(lenth), info)
         PACKETS.append(packet)
     self.updateCount.emit(PACKET_NUM, self.ipv4_count, self.ipv6_count,
                           self.tcp_count, self.udp_count, self.arp_count,
                           self.http_count, self.icmp_count)
示例#4
0
    def makeRequest(self, request):
        """Connect to the remote HTTP server and send request"""
        self.tcpclient = None
        self.httpparser = None
        port = intval(request.requestobject.get("uri-port", ""))
        if port == None:
            port = 80
        
        self.tcpclient = self.connectionclass(request.requestobject["uri-server"], port)
        self.httpparser = HTTPParser(mode="response")
                
        self.link( (self, "_tcpoutbox"),       (self.tcpclient, "inbox") )
        self.link( (self, "_tcpsignal"),       (self.tcpclient, "control") )
        self.link( (self.tcpclient, "signal"), (self, "_tcpcontrol") )

        self.link( (self.tcpclient, "outbox"), (self.httpparser, "inbox") ) #incoming TCP data -> HTTPParser directly
        
        self.link( (self, "_parsersignal"), (self.httpparser, "control") )
        self.link( (self.httpparser, "outbox"), (self, "_parserinbox") )
        self.link( (self.httpparser, "signal"), (self, "_parsercontrol") )

        self.addChildren( self.tcpclient, self.httpparser )
        self.tcpclient.activate()
        self.httpparser.activate()
        self.response = ""
        if isinstance(request.requestobject["request"], str):
            self.send(request.requestobject["request"], "_tcpoutbox")
        else:
            for part in request.requestobject["request"]:
                self.send(part, "_tcpoutbox")
示例#5
0
    def initialiseComponent(self):
        """Create an HTTPParser component to convert the requests we receive
        into a more convenient form, and a HTTPRequestHandler component to
        sort out the correct response to requests received."""
        
        self.mimehandler = HTTPParser()
        self.httphandler = HTTPRequestHandler(createRequestHandler)
        #self.httphandler.filereader = TriggeredFileReader()
        
        self.link( (self,"mime-control"), (self.mimehandler,"control") )
        self.link( (self.mimehandler, "signal"), (self, "mime-signal") )

        self.link( (self.mimehandler, "outbox"), (self.httphandler, "inbox") )
        
        self.link( (self, "http-control"), (self.httphandler, "control") )
        self.link( (self.httphandler, "signal"), (self, "http-signal") )
        
        self.addChildren(self.mimehandler, self.httphandler) #self.httphandler.filereader)
        self.httphandler.activate()
        self.mimehandler.activate()
        #self.httphandler.filereader.activate()

        self.link((self.httphandler, "outbox"), (self, "outbox"), passthrough=2)
        self.link((self, "inbox"), (self.mimehandler, "inbox"), passthrough=1)
示例#6
0
    def setPacket(self, packet):
        if packet is None:
            return
        self.rootItem.clearChildren()

        src = packet.getlayer(Ether).src
        dst = packet.getlayer(Ether).dst
        eth_type = str(packet.getlayer(Ether).type)
        if int(packet.getlayer(Ether).type) == 34525:  #IPv6
            eth_type = "IPv6(0x86DD)"
        elif int(packet.getlayer(Ether).type) == 2048:  #IPv4
            eth_type = "IPv4(0x0800)"
        elif int(packet.getlayer(Ether).type) == 2054:  #ARP
            eth_type = "ARP(0x0800)"

        EtherNet_item = TreeItem(["Ethernet II"], self.rootItem)
        src_item = TreeItem(["Source: " + src], EtherNet_item)
        dst_item = TreeItem(["Destination: " + dst], EtherNet_item)
        type_item = TreeItem(["Type: " + eth_type], EtherNet_item)
        EtherNet_item.appendChild(src_item)
        EtherNet_item.appendChild(dst_item)
        EtherNet_item.appendChild(type_item)
        EtherNet_item.itemData = [
            "Ethernet II, " + "Src: " + src + ", Dst: " + dst
        ]
        self.rootItem.appendChild(EtherNet_item)
        #-----EtherNet end----------

        if int(packet.getlayer(Ether).type) == 34525:
            proto = 'IPv6'
            src = str(packet.getlayer(IPv6).src)
            dst = str(packet.getlayer(IPv6).dst)
            info = str(packet.summary())

        elif int(packet.getlayer(Ether).type) == 2048:
            proto = "Ethernet"
            if int(packet.getlayer(IP).proto) == 6:
                proto = 'TCP'
            elif int(packet.getlayer(IP).proto) == 17:
                proto = 'UDP'
            elif int(packet.getlayer(IP).proto) == 1:
                proto = 'ICMP'

            src = str(packet.getlayer(IP).src)
            dst = str(packet.getlayer(IP).dst)
            header_len = packet.getlayer(IP).ihl
            header_len_str = ".... {:04b} = Header Length: {:d} bytes({:d})".format(
                header_len, header_len * 4, header_len)
            total_len_str = "Total length: {:d}".format(
                packet.getlayer(IP).len)
            identification_str = "Identification: 0x{:04x} ({:d})".format(
                packet.getlayer(IP).id,
                packet.getlayer(IP).id)
            # flags_str = "Flag: 0x{:04x}".format(packet.getlayer(IP).flag) TODO
            ttl_str = "Time to live: {:d}".format(packet.getlayer(IP).ttl)
            proto_str = "Protocol: {proto_str} ({:d})".format(
                packet.getlayer(IP).proto, proto_str=proto)
            chksum_str = "Header cheaksum: {:04x}".format(
                packet.getlayer(IP).chksum)
            info = str(packet.summary())

            ipv4_item = TreeItem(
                ["Internet Protocal Version 4, Src:" + src + ", Dst: " + dst],
                self.rootItem)
            src_item = TreeItem(["Source: " + src], ipv4_item)
            dst_item = TreeItem(["Destination: " + dst], ipv4_item)
            version_item = TreeItem(["0100 .... = Version 4"], ipv4_item)
            header_len_item = TreeItem([header_len_str], ipv4_item)
            total_len_item = TreeItem([total_len_str], ipv4_item)
            identification_item = TreeItem([identification_str], ipv4_item)
            # flags_item = TreeItem([flags_str], ipv4_item)
            ttl_item = TreeItem([ttl_str], ipv4_item)
            proto_item = TreeItem([proto_str], ipv4_item)
            chksum_item = TreeItem([chksum_str], ipv4_item)

            ipv4_item.appendChild(version_item)
            ipv4_item.appendChild(header_len_item)
            ipv4_item.appendChild(total_len_item)
            ipv4_item.appendChild(identification_item)
            # ipv4_item.appendChild(flags_item)
            ipv4_item.appendChild(ttl_item)
            ipv4_item.appendChild(proto_item)
            ipv4_item.appendChild(chksum_item)
            ipv4_item.appendChild(src_item)
            ipv4_item.appendChild(dst_item)
            self.rootItem.appendChild(ipv4_item)

            if int(packet.getlayer(IP).proto) == 6:  #TCP
                tcp_packet = packet.getlayer(TCP)
                sport_str = "Source Port: {:d}".format(tcp_packet.sport)
                dport_str = "Destination Port: {:d}".format(tcp_packet.dport)
                dataofs_str = "Data offset: {:d}".format(tcp_packet.dataofs)
                reserved_str = "Reserved: {:d}".format(tcp_packet.reserved)
                sql_str = "Sequence Number: {:d}".format(tcp_packet.seq)
                ack_str = "Acknowledge number: {:d}".format(tcp_packet.ack)
                header_len_str = "0101 .... = Header Length: 20 bytes (5)"
                window_str = "Window size value: {:d}".format(
                    tcp_packet.window)
                chksum_str = "Checksum: 0x{:04x}".format(tcp_packet.chksum)
                urgptr_str = "Urgent pointer: {:d}".format(tcp_packet.urgptr)
                tcp_str = "Transmission Control Protocol, Src Port: {:d}, Dst Port: {:d}, " \
                          "Seq: {:d}, Ack: {:d}, Len: 1"\
                            .format(tcp_packet.sport, tcp_packet.dport,
                                    tcp_packet.seq, tcp_packet.ack)
                tcp_item = TreeItem([tcp_str], self.rootItem)
                sport_item = TreeItem([sport_str], tcp_item)
                dport_item = TreeItem([dport_str], tcp_item)
                dataofs_item = TreeItem([dataofs_str], tcp_item)
                reserved_item = TreeItem([reserved_str], tcp_item)
                sql_item = TreeItem([sql_str], tcp_item)
                ack_item = TreeItem([ack_str], tcp_item)
                header_len_item = TreeItem([header_len_str], tcp_item)
                window_item = TreeItem([window_str], tcp_item)
                chksum_item = TreeItem([chksum_str], tcp_item)
                urgptr_item = TreeItem([urgptr_str], tcp_item)

                tcp_item.appendChild(sport_item)
                tcp_item.appendChild(dport_item)
                tcp_item.appendChild(dataofs_item)
                tcp_item.appendChild(reserved_item)
                tcp_item.appendChild(sql_item)
                tcp_item.appendChild(ack_item)
                tcp_item.appendChild(header_len_item)
                tcp_item.appendChild(window_item)
                tcp_item.appendChild(chksum_item)
                tcp_item.appendChild(urgptr_item)
                self.rootItem.appendChild(tcp_item)

                #Parse HTTP
                if HTTPParser.isHTTP(packet):
                    httpItem = TreeItem(["Hypertext Transfer Protocol"],
                                        self.rootItem)
                    packet_str = packet.getlayer(Raw).load.decode(
                        errors='ignore')
                    HTTP_list = packet_str.split("\n")
                    for http_str in HTTP_list:
                        http_str = http_str.strip()
                        if len(http_str) > 0:
                            newItem = TreeItem([http_str], httpItem)
                            httpItem.appendChild(newItem)
                    self.rootItem.appendChild(httpItem)

            elif int(packet.getlayer(IP).proto) == 17:
                udp_packet = packet.getlayer(UDP)
                udp_str = "User Datagram Protocol, Src Port: {:d}, Dst Port: {:d}"\
                    .format(udp_packet.sport, udp_packet.dport)
                sport_str = "Source Port: {:d}".format(udp_packet.sport)
                dport_str = "Destination Port: {:d}".format(udp_packet.dport)
                len_str = "Length: {:d}".format(udp_packet.len)
                chksum_str = "Checksum: 0x{:04x}".format(udp_packet.chksum)
                udp_item = TreeItem([udp_str], self.rootItem)
                sport_item = TreeItem([sport_str], udp_item)
                dport_item = TreeItem([dport_str], udp_item)
                len_item = TreeItem([len_str], udp_item)
                chksum_item = TreeItem([chksum_str], udp_item)
                udp_item.appendChild(sport_item)
                udp_item.appendChild(dport_item)
                udp_item.appendChild(len_item)
                udp_item.appendChild(chksum_item)
                self.rootItem.appendChild(udp_item)

                if packet.haslayer(Raw):
                    raw_packet = udp_packet.load
                    data_str = "Data ({:d} bytes)".format(len(raw_packet))
                    raw_str = raw_packet.hex()
                    if len(raw_str) >= 100:
                        raw_str = raw_str[:100] + "..."

                    load_str = "Data: " + raw_str
                    data_item = TreeItem([data_str], self.rootItem)
                    load_item = TreeItem([load_str], data_item)
                    data_item.appendChild(load_item)
                    self.rootItem.appendChild(data_item)

            elif int(packet.getlayer(IP).proto) == 1:
                icmp_packet = packet.getlayer(ICMP)
                icmp_str = "Internet Control Message Protocol"
                icmp_type = ""
                if icmp_packet.type == 0:
                    icmp_type = "(Echo (ping) reply)"
                elif icmp_packet.type == 8:
                    icmp_type = "(Echo (ping) request)"
                type_str = "Type: {:d} {icmp_type}".format(icmp_packet.type,
                                                           icmp_type=icmp_type)
                code_str = "Code: {:d}".format(icmp_packet.code)
                chksum_str = "Checksum: 0x{:04x}".format(icmp_packet.chksum)

                icmp_item = TreeItem([icmp_str], self.rootItem)
                type_item = TreeItem([type_str], icmp_item)
                code_item = TreeItem([code_str], icmp_item)
                chksum_item = TreeItem([chksum_str], icmp_item)
                if (icmp_packet.id):
                    id_str = "Identifier : {:d} (0x{:04x})".format(
                        icmp_packet.id, icmp_packet.id)
                    id_item = TreeItem([id_str], icmp_item)
                    icmp_item.appendChild(id_item)
                if (icmp_packet.seq):
                    seq_str = "Sequence number : {:d} (0x{:04x})".format(
                        icmp_packet.seq, icmp_packet.seq)
                    seq_item = TreeItem([seq_str], icmp_item)
                    icmp_item.appendChild(seq_item)

                icmp_item.appendChild(type_item)
                icmp_item.appendChild(code_item)
                icmp_item.appendChild(chksum_item)

                self.rootItem.appendChild(icmp_item)

        elif int(packet.getlayer(Ether).type) == 2054:
            arp_packet = packet.getlayer(ARP)
            arp_str = "Address Resolution Protocol"
            hwtype_str = "Hardware type: Ethernet ({:d})".format(
                arp_packet.hwtype)
            ptype_str = "Protocol type: IPv4 (0x0800)"
            hwlen_str = "Hardware size: {:d}".format(arp_packet.hwlen)
            plen_str = "Protocol size: {:d}".format(arp_packet.plen)
            op_str = "Opcode: {op} ({:d})".format(
                arp_packet.op, op="request" if arp_packet.op == 1 else "reply")
            hwsrc_str = "Sender MAC address: " + arp_packet.hwsrc
            psrc_str = "Sender IP address: " + str(packet.getlayer(ARP).psrc)
            hwdst_str = "Target MAC address: " + arp_packet.hwdst
            pdst_str = "Target IP address: " + str(packet.getlayer(ARP).pdst)
            arp_item = TreeItem([arp_str], self.rootItem)
            hwtype_item = TreeItem([hwtype_str], arp_item)
            ptype_item = TreeItem([ptype_str], arp_item)
            hwlen_item = TreeItem([hwlen_str], arp_item)
            plen_item = TreeItem([plen_str], arp_item)
            op_item = TreeItem([op_str], arp_item)
            hwsrc_item = TreeItem([hwsrc_str], arp_item)
            psrc_item = TreeItem([psrc_str], arp_item)
            hwdst_item = TreeItem([hwdst_str], arp_item)
            pdst_item = TreeItem([pdst_str], arp_item)
            arp_item.appendChild(hwtype_item)
            arp_item.appendChild(ptype_item)
            arp_item.appendChild(hwlen_item)
            arp_item.appendChild(plen_item)
            arp_item.appendChild(op_item)
            arp_item.appendChild(hwsrc_item)
            arp_item.appendChild(psrc_item)
            arp_item.appendChild(hwdst_item)
            arp_item.appendChild(pdst_item)
            self.rootItem.appendChild(arp_item)

        self.modelReset.emit()
示例#7
0
class SingleShotHTTPClient(component):
    """\
    SingleShotHTTPClient() -> component that can download a file using HTTP by URL

    Arguments:
    - starturl     -- the URL of the file to download
    - [postbody]   -- data to POST to that URL
    - [connectionclass] -- specify a class other than TCPClient to connect with
    """

    Inboxes = {
        "inbox": "UNUSED",
        "control": "UNUSED",
        "_parserinbox": "Data from HTTP parser",
        "_parsercontrol": "Signals from HTTP parser",
        "_tcpcontrol": "Signals from TCP client",
    }

    Outboxes = {
        "outbox": "Requested file",
        "debug": "Output to aid debugging",
        "_parsersignal": "Signals for HTTP parser",
        "_tcpoutbox": "Send over TCP connection",
        "_tcpsignal": "Signals shutdown of TCP connection",
        "signal": "UNUSED"
    }

    def __init__(self, starturl, postbody="", connectionclass=TCPClient):
        #print "SingleShotHTTPClient.__init__()"
        super(SingleShotHTTPClient, self).__init__()
        self.tcpclient = None
        self.httpparser = None
        self.requestqueue = []
        self.starturl = starturl
        self.connectionclass = connectionclass

        self.postbody = postbody
        #print "Start url: " + starturl

    def formRequest(self, url):
        """Craft a HTTP request string for the supplied url"""
        splituri = splitUri(url)

        host = splituri["uri-server"]
        if splituri.has_key("uri-port"):
            host += ":" + splituri["uri-port"]

        splituri["request"] = []
        if self.postbody == "":
            splituri["request"].append("GET " + splituri["raw-uri"] +
                                       " HTTP/1.1\r\n")
        else:
            splituri["request"].append("POST " + splituri["raw-uri"] +
                                       " HTTP/1.1\r\n")
            splituri["request"].append("Content-Length: " +
                                       str(len(self.postbody)) + "\r\n")

        splituri["request"].append("Host: " + host + "\r\n")
        splituri["request"].append(
            "User-agent: Kamaelia HTTP Client 0.3 (RJL)\r\n")
        splituri["request"].append(
            "Connection: Keep-Alive\r\n"
        )  # keep-alive is a work around for lack of shutdown notification in TCPClient
        splituri["request"].append("\r\n")

        splituri["request"] = [string.join(
            splituri["request"],
            "")]  # might improve performance by sending more together

        if self.postbody != "":
            splituri["request"].append(self.postbody)

        return splituri

    def makeRequest(self, request):
        """Connect to the remote HTTP server and send request"""
        self.tcpclient = None
        self.httpparser = None
        port = intval(request.requestobject.get("uri-port", ""))
        if port == None:
            port = 80

        self.tcpclient = self.connectionclass(
            request.requestobject["uri-server"], port)
        self.httpparser = HTTPParser(mode="response")

        self.link((self, "_tcpoutbox"), (self.tcpclient, "inbox"))
        self.link((self, "_tcpsignal"), (self.tcpclient, "control"))
        self.link((self.tcpclient, "signal"), (self, "_tcpcontrol"))

        self.link((self.tcpclient, "outbox"),
                  (self.httpparser,
                   "inbox"))  #incoming TCP data -> HTTPParser directly

        self.link((self, "_parsersignal"), (self.httpparser, "control"))
        self.link((self.httpparser, "outbox"), (self, "_parserinbox"))
        self.link((self.httpparser, "signal"), (self, "_parsercontrol"))

        self.addChildren(self.tcpclient, self.httpparser)
        self.tcpclient.activate()
        self.httpparser.activate()
        self.response = ""
        if isinstance(request.requestobject["request"], str):
            self.send(request.requestobject["request"], "_tcpoutbox")
        else:
            for part in request.requestobject["request"]:
                self.send(part, "_tcpoutbox")

    def shutdownKids(self):
        """Close TCP connection and HTTP parser"""
        if self.tcpclient != None and self.httpparser != None:
            self.send(producerFinished(), "_tcpsignal")
            self.send(shutdown(), "_parsersignal")
            self.removeChild(self.tcpclient)
            self.removeChild(self.httpparser)
            self.tcpclient = None
            self.httpparser = None

    def handleRedirect(self, header):
        """Check for a redirect response and queue the fetching the page it points to if it is such a response.
        Returns true if it was a redirect page and false otherwise."""

        if header["responsecode"] == "302" or header[
                "responsecode"] == "303" or header["responsecode"] == "307":
            # location header gives the redirect URL
            newurl = header["headers"].get("location", "")
            if newurl != "":
                redirectedrequest = HTTPRequest(
                    self.formRequest(newurl),
                    self.currentrequest.redirectcount + 1)
                self.requestqueue.append(redirectedrequest)
                return True
            else:
                return False
                # do something equivalent to what we'd do for 404
        else:
            return False

    def main(self):
        """Main loop."""
        self.requestqueue.append(
            HTTPRequest(self.formRequest(self.starturl), 0))
        while self.mainBody():
            #print "SingleShotHTTPClient.main"
            yield 1
        self.send(producerFinished(self), "signal")
        yield 1
        return

    def mainBody(self):
        """Called repeatedly by main loop. Checks inboxes and processes messages received.
        Start the fetching of the new page if the current one is a redirect and has been
        completely fetched."""

        self.send("SingleShotHTTPClient.mainBody()", "debug")
        while self.dataReady("_parserinbox"):
            msg = self.recv("_parserinbox")
            if isinstance(msg, ParsedHTTPHeader):
                self.send(
                    "SingleShotHTTPClient received a ParsedHTTPHeader on _parserinbox",
                    "debug")
                # if the page is a redirect page
                if not self.handleRedirect(msg.header):
                    if msg.header["responsecode"] == "200":
                        self.send(
                            msg, "outbox"
                        )  # if not redirecting then send the response on
                    else:  #treat as not found
                        pass

            elif isinstance(msg, ParsedHTTPBodyChunk):
                self.send(
                    "SingleShotHTTPClient received a ParsedHTTPBodyChunk on _parserinbox",
                    "debug")
                if len(self.requestqueue
                       ) == 0:  # if not redirecting then send the response on
                    self.send(msg, "outbox")

            elif isinstance(msg, ParsedHTTPEnd):
                self.send(
                    "SingleShotHTTPClient received a ParsedHTTPEnd on _parserinbox",
                    "debug")
                if len(self.requestqueue
                       ) == 0:  # if not redirecting then send the response on
                    self.send(msg, "outbox")
                self.shutdownKids()
                return 1

        while self.dataReady("_parsercontrol"):
            temp = self.recv("_parsercontrol")
            self.send(
                "SingleShotHTTPClient received something on _parsercontrol",
                "debug")

        while self.dataReady("_tcpcontrol"):
            msg = self.recv("_tcpcontrol")
            self.send(msg, "_parsersignal")

        while self.dataReady("control"):
            msg = self.recv("control")
            if isinstance(msg, shutdownMicroprocess) or isinstance(
                    msg, shutdown):
                self.shutdownKids()
                return 0

        # if we're not currently downloading a page
        if self.tcpclient == None:
            # then either we've finished or we should download the next URL (if we've been redirected)
            if len(self.requestqueue) > 0:
                self.currentrequest = self.requestqueue.pop(0)
                if self.currentrequest.redirectcount == 3:  # 3 redirects is excessive, give up, we're probably in a loop anyway
                    return 0
                else:
                    self.makeRequest(self.currentrequest)
            else:
                return 0

        self.pause()
        return 1
示例#8
0
class HTTPServer(component):
    """\
    HTTPServer() -> new HTTPServer component capable of handling a single connection
    
    Arguments:
       -- createRequestHandler - a function required by HTTPRequestHandler that
                                 creates the appropriate request-handler component
                                 for each request, see HTTPResourceGlue
    """

    Inboxes = {
        "inbox": "TCP data stream - receive",
        "mime-signal": "Error signals from MIME handler",
        "http-signal": "Error signals from the HTTP resource retriever",
        "control": "Receive shutdown etc. signals"
    }

    Outboxes = {
        "outbox": "TCP data stream - send",
        "mime-control": "To MIME handler",
        "http-control": "To HTTP resource retriever's signalling inbox",
        "signal": "UNUSED"
    }

    def __init__(self, createRequestHandler):
        super(HTTPServer, self).__init__()
        self.createRequestHandler = createRequestHandler

    def initialiseComponent(self):
        """Create an HTTPParser component to convert the requests we receive
        into a more convenient form, and a HTTPRequestHandler component to
        sort out the correct response to requests received."""

        self.mimehandler = HTTPParser()
        self.httphandler = HTTPRequestHandler(createRequestHandler)
        #self.httphandler.filereader = TriggeredFileReader()

        self.link((self, "mime-control"), (self.mimehandler, "control"))
        self.link((self.mimehandler, "signal"), (self, "mime-signal"))

        self.link((self.mimehandler, "outbox"), (self.httphandler, "inbox"))

        self.link((self, "http-control"), (self.httphandler, "control"))
        self.link((self.httphandler, "signal"), (self, "http-signal"))

        self.addChildren(self.mimehandler,
                         self.httphandler)  #self.httphandler.filereader)
        self.httphandler.activate()
        self.mimehandler.activate()
        #self.httphandler.filereader.activate()

        self.link((self.httphandler, "outbox"), (self, "outbox"),
                  passthrough=2)
        self.link((self, "inbox"), (self.mimehandler, "inbox"), passthrough=1)

    def main(self):
        self.initialiseComponent()
        loop = True
        while loop:
            yield 1
            while self.dataReady("control"):
                temp = self.recv("control")
                if isinstance(temp, producerFinished):
                    self.send(temp, "mime-control")
                elif isinstance(temp, shutdownMicroprocess) or isinstance(
                        temp, shutdown):
                    self.send(shutdown(), "mime-control")
                    self.send(shutdown(), "http-control")
                    #print "HTTPServer received shutdown"
                    loop = False
                    break

            while self.dataReady("mime-signal"):
                temp = self.recv("mime-signal")
                if isinstance(temp, producerFinished):
                    pass
                    #we don't need to care yet - wait 'til the request handler finishes

            while self.dataReady("http-signal"):
                temp = self.recv("http-signal")
                if isinstance(temp, producerFinished):
                    sig = producerFinished(self)
                    self.send(sig, "mime-control")
                    self.send(sig, "signal")
                    loop = False
                    #close the connection

            self.pause()

        self.closeDownComponent()

    def closeDownComponent(self):
        "Remove my subcomponents (HTTPParser, HTTPRequestHandler)"
        for child in self.childComponents():
            self.removeChild(child)
        self.mimehandler = None
        self.httphandler = None
示例#9
0
class SingleShotHTTPClient(component): 
    """\
    SingleShotHTTPClient() -> component that can download a file using HTTP by URL

    Arguments:
    - starturl     -- the URL of the file to download
    - [postbody]   -- data to POST to that URL
    - [connectionclass] -- specify a class other than TCPClient to connect with
    """
   
    Inboxes =  {             
        "inbox"          : "UNUSED",
        "control"        : "UNUSED",
                    
        "_parserinbox"   : "Data from HTTP parser",
        "_parsercontrol" : "Signals from HTTP parser",
        "_tcpcontrol"    : "Signals from TCP client",
    }
        

    Outboxes = {
        "outbox"         : "Requested file",
        "debug"          : "Output to aid debugging",
        
        "_parsersignal"  : "Signals for HTTP parser",
                
        "_tcpoutbox"     : "Send over TCP connection",
        "_tcpsignal"     : "Signals shutdown of TCP connection",
        
        "signal"         : "UNUSED"
    }
        
    def __init__(self, starturl, postbody = "", connectionclass = TCPClient):
        #print "SingleShotHTTPClient.__init__()"
        super(SingleShotHTTPClient, self).__init__()
        self.tcpclient = None
        self.httpparser = None
        self.requestqueue = []
        self.starturl = starturl
        self.connectionclass = connectionclass
        
        self.postbody = postbody
        #print "Start url: " + starturl
        
    def formRequest(self, url):
        """Craft a HTTP request string for the supplied url"""
        splituri = splitUri(url)
        
        host = splituri["uri-server"]
        if splituri.has_key("uri-port"):
            host += ":" + splituri["uri-port"]

        splituri["request"] = []        
        if self.postbody == "":    
            splituri["request"].append("GET " + splituri["raw-uri"] + " HTTP/1.1\r\n")
        else:
            splituri["request"].append("POST " + splituri["raw-uri"] + " HTTP/1.1\r\n")
            splituri["request"].append("Content-Length: " + str(len(self.postbody)) + "\r\n")

        splituri["request"].append("Host: " + host + "\r\n")
        splituri["request"].append("User-agent: Kamaelia HTTP Client 0.3 (RJL)\r\n")
        splituri["request"].append("Connection: Keep-Alive\r\n") # keep-alive is a work around for lack of shutdown notification in TCPClient
        splituri["request"].append("\r\n") 

        splituri["request"] = [string.join(splituri["request"], "")] # might improve performance by sending more together
        
        if self.postbody != "":
            splituri["request"].append(self.postbody)
        
        return splituri

    def makeRequest(self, request):
        """Connect to the remote HTTP server and send request"""
        self.tcpclient = None
        self.httpparser = None
        port = intval(request.requestobject.get("uri-port", ""))
        if port == None:
            port = 80
        
        self.tcpclient = self.connectionclass(request.requestobject["uri-server"], port)
        self.httpparser = HTTPParser(mode="response")
                
        self.link( (self, "_tcpoutbox"),       (self.tcpclient, "inbox") )
        self.link( (self, "_tcpsignal"),       (self.tcpclient, "control") )
        self.link( (self.tcpclient, "signal"), (self, "_tcpcontrol") )

        self.link( (self.tcpclient, "outbox"), (self.httpparser, "inbox") ) #incoming TCP data -> HTTPParser directly
        
        self.link( (self, "_parsersignal"), (self.httpparser, "control") )
        self.link( (self.httpparser, "outbox"), (self, "_parserinbox") )
        self.link( (self.httpparser, "signal"), (self, "_parsercontrol") )

        self.addChildren( self.tcpclient, self.httpparser )
        self.tcpclient.activate()
        self.httpparser.activate()
        self.response = ""
        if isinstance(request.requestobject["request"], str):
            self.send(request.requestobject["request"], "_tcpoutbox")
        else:
            for part in request.requestobject["request"]:
                self.send(part, "_tcpoutbox")

    def shutdownKids(self):
        """Close TCP connection and HTTP parser"""
        if self.tcpclient != None and self.httpparser != None:
            self.send(producerFinished(), "_tcpsignal")
            self.send(shutdown(), "_parsersignal")
            self.removeChild(self.tcpclient)
            self.removeChild(self.httpparser)            
            self.tcpclient = None
            self.httpparser = None

    def handleRedirect(self, header):
        """Check for a redirect response and queue the fetching the page it points to if it is such a response.
        Returns true if it was a redirect page and false otherwise."""
        
        if header["responsecode"] == "302" or header["responsecode"] == "303" or header["responsecode"] == "307":
            # location header gives the redirect URL
            newurl = header["headers"].get("location", "")
            if newurl != "":
                redirectedrequest = HTTPRequest(self.formRequest(newurl), self.currentrequest.redirectcount + 1)
                self.requestqueue.append(redirectedrequest)
                return True
            else:
                return False
                # do something equivalent to what we'd do for 404
        else:
            return False
                            
    def main(self):
        """Main loop."""
        self.requestqueue.append(HTTPRequest(self.formRequest(self.starturl), 0))
        while self.mainBody():
            #print "SingleShotHTTPClient.main"
            yield 1
        self.send(producerFinished(self), "signal")
        yield 1
        return
        
    def mainBody(self):
        """Called repeatedly by main loop. Checks inboxes and processes messages received.
        Start the fetching of the new page if the current one is a redirect and has been
        completely fetched."""
        
        self.send("SingleShotHTTPClient.mainBody()", "debug")
        while self.dataReady("_parserinbox"):
            msg = self.recv("_parserinbox")
            if isinstance(msg, ParsedHTTPHeader):
                self.send("SingleShotHTTPClient received a ParsedHTTPHeader on _parserinbox", "debug")                        
                # if the page is a redirect page
                if not self.handleRedirect(msg.header):
                    if msg.header["responsecode"] == "200":
                        self.send(msg, "outbox") # if not redirecting then send the response on
                    else:  #treat as not found
                        pass
                        
            elif isinstance(msg, ParsedHTTPBodyChunk):
                self.send("SingleShotHTTPClient received a ParsedHTTPBodyChunk on _parserinbox", "debug")
                if len(self.requestqueue) == 0: # if not redirecting then send the response on
                    self.send(msg, "outbox")
                
            elif isinstance(msg, ParsedHTTPEnd):
                self.send("SingleShotHTTPClient received a ParsedHTTPEnd on _parserinbox", "debug")
                if len(self.requestqueue) == 0: # if not redirecting then send the response on
                    self.send(msg, "outbox")
                self.shutdownKids()
                return 1
            
        while self.dataReady("_parsercontrol"):
            temp = self.recv("_parsercontrol")
            self.send("SingleShotHTTPClient received something on _parsercontrol", "debug")
            
        while self.dataReady("_tcpcontrol"):
            msg = self.recv("_tcpcontrol")
            self.send(msg, "_parsersignal")

        while self.dataReady("control"):
            msg = self.recv("control")
            if isinstance(msg, shutdownMicroprocess) or isinstance(msg, shutdown):
                self.shutdownKids()
                return 0

        # if we're not currently downloading a page
        if self.tcpclient == None:
            # then either we've finished or we should download the next URL (if we've been redirected)
            if len(self.requestqueue) > 0:
                self.currentrequest = self.requestqueue.pop(0)
                if self.currentrequest.redirectcount == 3: # 3 redirects is excessive, give up, we're probably in a loop anyway
                    return 0
                else:
                    self.makeRequest(self.currentrequest)
            else:
                return 0
                    
        self.pause()
        return 1
示例#10
0
class HTTPServer(component):
    """\
    HTTPServer() -> new HTTPServer component capable of handling a single connection
    
    Arguments:
       -- createRequestHandler - a function required by HTTPRequestHandler that
                                 creates the appropriate request-handler component
                                 for each request, see HTTPResourceGlue
    """
    
    Inboxes =  { "inbox"         : "TCP data stream - receive",
                 "mime-signal"   : "Error signals from MIME handler",
                 "http-signal"   : "Error signals from the HTTP resource retriever",
                 "control"       : "Receive shutdown etc. signals" }


    Outboxes = { "outbox"        : "TCP data stream - send",
                 "mime-control"  : "To MIME handler",
                 "http-control"  : "To HTTP resource retriever's signalling inbox",
                 "signal"        : "UNUSED" }

    def __init__(self, createRequestHandler):
        super(HTTPServer, self).__init__()
        self.createRequestHandler = createRequestHandler

    def initialiseComponent(self):
        """Create an HTTPParser component to convert the requests we receive
        into a more convenient form, and a HTTPRequestHandler component to
        sort out the correct response to requests received."""
        
        self.mimehandler = HTTPParser()
        self.httphandler = HTTPRequestHandler(createRequestHandler)
        #self.httphandler.filereader = TriggeredFileReader()
        
        self.link( (self,"mime-control"), (self.mimehandler,"control") )
        self.link( (self.mimehandler, "signal"), (self, "mime-signal") )

        self.link( (self.mimehandler, "outbox"), (self.httphandler, "inbox") )
        
        self.link( (self, "http-control"), (self.httphandler, "control") )
        self.link( (self.httphandler, "signal"), (self, "http-signal") )
        
        self.addChildren(self.mimehandler, self.httphandler) #self.httphandler.filereader)
        self.httphandler.activate()
        self.mimehandler.activate()
        #self.httphandler.filereader.activate()

        self.link((self.httphandler, "outbox"), (self, "outbox"), passthrough=2)
        self.link((self, "inbox"), (self.mimehandler, "inbox"), passthrough=1)
      
    def main(self):
        self.initialiseComponent()
        loop = True
        while loop:
            yield 1
            while self.dataReady("control"):
                temp = self.recv("control")
                if isinstance(temp, producerFinished):
                    self.send(temp, "mime-control")
                elif isinstance(temp, shutdownMicroprocess) or isinstance(temp, shutdown):
                    self.send(shutdown(), "mime-control")
                    self.send(shutdown(), "http-control")
                    #print "HTTPServer received shutdown"
                    loop = False
                    break
            
            while self.dataReady("mime-signal"):
                temp = self.recv("mime-signal")
                if isinstance(temp, producerFinished):
                    pass
                    #we don't need to care yet - wait 'til the request handler finishes
            
            while self.dataReady("http-signal"):
                temp = self.recv("http-signal")
                if isinstance(temp, producerFinished):
                    sig = producerFinished(self)
                    self.send(sig, "mime-control")                
                    self.send(sig, "signal")
                    loop = False
                    #close the connection
            
            self.pause()
                
        self.closeDownComponent()
        
    def closeDownComponent(self):
        "Remove my subcomponents (HTTPParser, HTTPRequestHandler)"
        for child in self.childComponents():
            self.removeChild(child)
        self.mimehandler = None
        self.httphandler = None