============ Extensions ============ Introduction ============ You will read short overview about extensions and learn how to use already provided ones. Overview ======== Extensions add extra features and/or functionality for UMPA. They are not necessary to correct usage of the library, but they may make your life easier. Extensions are module-oriented. Usually they provide independent functions and add similar methods for objects. Also they can change behaviour of the objects. But they are not imported automatically, so if you don't import them, there is no risk of odd objects behaviour at all. There is a one function provided by ``umit.umpa.extensions`` package. It's called ``load_extensions()``. But it's not necessary to use it here. Read more about this function in next tutorial. XML === XML is a markup language for documents containing structured information. We can save and restore packets/protocols with XML. XML extension uses DOM. Files are relatively small, so there is no need to use SAX. But, perhaps it will be rewritten with SAX someday.. save packets to the file ------------------------ Let's create a packet (the same one TCP/IP packet as we created in our first tutorial). .. code-block:: python import umit.umpa import umit.umpa.utils.security from umit.umpa.protocols import IP, TCP, Payload # droping priviliges umit.umpa.utils.security.drop_priviliges() # IP header ip = IP() ip.source_address = "127.0.0.1" ip.destination_address = "67.205.14.183" # TCP header tcp = TCP() tcp.source_port = 2958 tcp.destination_port = 0 tcp.set_flags('control_bits', syn=True) # Payload data = Payload() data.data = "this is umpa!" # packet packet = umit.umpa.Packet(ip, tcp, data) So, let's store it as a XML file on the harddrive. .. code-block:: python from umit.umpa.extensions import XML XML.save('packet.xml', (packet,)) Second ``save()`` function's argument is a list. We can save more than one packet in the single file. So, we have sucessfully stored our packet. Let's read the XML file. .. code-block:: xml <?xml version="1.0" ?> <UMPA> <packet id="0" strict="True"> <protocol class="umit.umpa.protocols.IP.IP"> <_version type="int"> 4 </_version> <_ihl type="NoneType"> None </_ihl> <type_of_service type="bits"> <relibility type="bool"> False </relibility> <reserved0 type="bool"> False </reserved0> <delay type="bool"> False </delay> <throughput type="bool"> False </throughput> <reserved1 type="bool"> False </reserved1> <precedence2 type="bool"> False </precedence2> <precedence1 type="bool"> False </precedence1> <precedence0 type="bool"> False </precedence0> </type_of_service> <_total_length type="NoneType"> None </_total_length> <_identification type="int"> 0 </_identification> <flags type="bits"> <df type="bool"> False </df> <mf type="bool"> False </mf> <reserved type="bool"> False </reserved> </flags> <_fragment_offset type="int"> 0 </_fragment_offset> <time_to_live type="int"> 64 </time_to_live> <_protocol type="NoneType"> None </_protocol> <_header_checksum type="int"> 0 </_header_checksum> <source_address type="str"> 127.0.0.1 </source_address> <destination_address type="str"> 67.205.14.183 </destination_address> <options type="bits"/> <_padding type="int"> 0 </_padding> </protocol> <protocol class="umit.umpa.protocols.TCP.TCP"> <source_port type="int"> 2958 </source_port> <destination_port type="int"> 0 </destination_port> <_sequence_number type="NoneType"> None </_sequence_number> <_acknowledgment_number type="NoneType"> None </_acknowledgment_number> <_data_offset type="NoneType"> None </_data_offset> <_reserved type="int"> 0 </_reserved> <control_bits type="bits"> <psh type="bool"> False </psh> <urg type="bool"> False </urg> <ack type="bool"> False </ack> <syn type="bool"> True </syn> <rst type="bool"> False </rst> <fin type="bool"> False </fin> </control_bits> <_window type="NoneType"> None </_window> <_checksum type="NoneType"> None </_checksum> <_urgent_pointer type="NoneType"> None </_urgent_pointer> <options type="bits"/> <_padding type="int"> 0 </_padding> </protocol> <protocol class="umit.umpa.protocols.Payload.Payload"> <data type="str"> this is umpa! </data> </protocol> </packet> </UMPA> Isn't it look so nice? :) restore the packet ------------------ Just call ``load()`` function! .. code-block:: python packets = XML.load('packet.xml') ``packets`` is a list of loaded packets. If we need the first packet from the list, just do something like .. code-block:: python packet = XML.load('packet.xml')[0] What if we have a packet's object and we just want to load protocols from the file into the object? .. code-block:: python packet.protos = XML.load('packet.xml', proto_only=True) With ``proto_only=True load()`` function loads *ONLY* first packet and returns *ONLY* protocols (instead of the packet's object). Huh, this case doesn't look so nice, does it? Let's do the same in object-oriented style! object-oriented XML ------------------- Let's back to the state when we created our packet... .. code-block:: python import umit.umpa.extensions.XML packet.save_xml('packet.xml') another_packet = umit.umpa.Packet() another_packet.load_xml('packet.xml') By importing XML extensions Packet objects get 2 extra methods (``save_xml()`` and ``load_xml()``). It's so simple now! .. note:: ``another_packet`` *is not* exactly the same as ``packet``! ``id()`` results vary. They have the same values but this is different instance of the Packet class. schedule ======== This extension adds extra features for ``Socket`` objects. It helps us to keep control when to send our packets. delay ----- If we call ``Socket.send()`` method, passed packets will be sent immediately. We can make a delay for this in 2 ways: by calling function (``send()``) from the extension or calling new method of Socket's object. In general, both ways are the same, they have a minor difference, we will talk about it later .. code-block:: python import umit.umpa import umit.umpa.extensions.schedule sock = umit.umpa.Socket() sock.send_schedule(5, packet1, packet2) UMPA will wait 5 seconds before send 2 packets. extra options ------------- There are 3 extra options which can be passed. Let's describe them! interval ```````` If we want to send more than one packet at once, we may add interval between them. It means, UMPA will sleep between sending next packets. .. code-block:: python sock.send_schedule(5, packet1, packet2, interval=2) In this case, UMPA'll sleep 5 secs at the beginning, and additional 2 secs after ``packet1`` will be sent. socket `````` Here is that minor difference between ``umit.umpa.extensions.schedule.send()`` function and ``send_schedule()`` method. We don't use this option for the method. It's set to the ``self`` by default. So, let's focus on the function. If we don't pass the socket option, the extension will create new ``umit.umpa.Socket`` object for us, and will use it. But we can pass the already created object instead. .. code-block:: python import umit.umpa import umit.umpa.extensions.schedule sock = umit.umpa.Socket() umit.umpa.extensions.schedule.send(0, packet1, packet2, interval=10, socket=sock) In this case we're sending 2 packets with 10 secs delay between them, but without a delay at the beginning. Also the extension will not create a new instance of ``umit.umpa.Socket``, just use passed ``sock`` object instead. detach `````` When we set a delay or interval, our process/application is being blocked till everything will be sent out. By using detach option, sending is done in backgroung and we can go with next instructions. .. code-block:: python import umit.umpa import umit.umpa.extensions.schedule umit.umpa.extensions.schedule.send(10, packet1, packet2, interval=5, detach=True) print "we can print something immediately" In this case, the print statement is run without waiting till both packets will be sent out (they will be in a background after set delays).
