On Feb 13, 2014, at 7:37 AM, Emanuele Di Pascale <dipas...@tcd.ie> wrote:

> Hello,
> I'm trying to write a POX module to identify http GET requests to specific IP 
> addresses and react based on the page requested, but I'm struggling with the 
> http part. There doesn't seem to be a POX http packet class, so I assume I 
> need to convert the raw bytes read from the wire into a string representation 
> of the http message. However the couple of approaches I tried all failed 
> miserably. Specifically, after retrieving the tcp packet in my PacketIn 
> handler like this:
> 
> tcp = event.parsed.find('tcp')
> if tcp is not None and tcp.parsed:
> 
> any attempt to call tcp.payload() will result in a TypeError message (cannot 
> call str).

Peter was right with this.  .payload isn't a method/function you call.  It's a 
property, which means it's implemented like a function, but it acts like it's a 
normal data attribute.  Since TCP is the last parsed packet type, it just acts 
like a bytes/string.

> Calling tcp.next.decode("utf-8") and trying to print that through log.debug 
> will throw a "TypeError: not all arguments converted during string 
> formatting" exception .

I don't think there are any usecases for using .next instead of .payload.  
Always use .payload.  tcp.payload.decode("utf-8") should have identical meaning.

If you got this TypeError, though, it seems likely that your call to 
log.debug() was somehow faulty.  You probably want something like:
log.debug("HTTP: %s", tcp.payload)

> And similarly I get an exception for
> 
> dlen = len(tcp.next)
> (http) = struct.unpack('!'+str(dlen)+'s', tcp.next)
> log.debug("Http payload: " + http)

The problem here is that unpack() returns a tuple (in this case with a single 
element).  You can use destructuring assignment to extract the single field.  
This looks like it's probably what you're trying to do here, *but* (http) isn't 
a tuple.  It's just http with parentheses around it (a trivial subexpression).  
To make a length-one tuple, you need the comma: (http,).  In this case, a more 
straightforward way is probably just to use the index operator to extract the 
one and only element:
http = struct.unpack('!'+str(dlen)+'s', tcp.next)[0]

But, of course, this should be almost a no-op.  http = tcp.next (or, better 
yet, http = tcp.payload) should be basically the same.

> I'm assuming the problem might be the CR+LF characters in the http message, 
> but I have no way of knowing the length of the message as it depends on the 
> page that's being requested. It could also be something else, as I'm new to 
> Python and possibly missing something very obvious. Any hints?
> 
> Thanks in advance!
> 
> Emanuele Di Pascale

Reply via email to