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