Skip to content

Commit

Permalink
Async: remove length at the beginning of RPC messages.
Browse files Browse the repository at this point in the history
This fix a nasty bug that would have been triggered by having
a JSON length that contains the bytes '\r\n', which are used for
message termination. Fortunately our messages are always short
enough that, to my knowledge, this bug has never been triggered.
  • Loading branch information
giomasce committed Jun 1, 2013
1 parent a382a2d commit 4d829a0
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 41 deletions.
15 changes: 4 additions & 11 deletions cms/async/AsyncLibrary.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

from cms.async import ServiceCoord, Address, get_service_address
from cms.async.Utils import random_string, Logger, \
encode_length, encode_json, decode_length, decode_json
encode_json, decode_json


# Our logger object - can be a standard one (provided in Utils), or a
Expand Down Expand Up @@ -526,12 +526,7 @@ def found_terminator(self):

# We decode the arriving data
try:
json_length = decode_length(data[:4])
if len(data) != json_length + 4:
logger.warning("Incoming message with binary data aren't "
"supported anymore, discarding.")
return
message = decode_json(data[4:json_length + 4])
message = decode_json(data)
except:
logger.warning("Cannot understand incoming message, discarding.")
return
Expand Down Expand Up @@ -596,12 +591,11 @@ def send_reply(self, response, method_response):
try:
response["__data"] = method_response
json_message = encode_json(response)
json_length = encode_length(len(json_message))
except ValueError as error:
logger.warning("Cannot send response because of " +
"encoding error. %s" % repr(error))
return
self._push_right(json_length + json_message)
self._push_right(json_message)

def execute_rpc(self, method, data, callback=None, plus=None,
timeout=None):
Expand Down Expand Up @@ -678,13 +672,12 @@ def callback(self, data, error=None):
# We encode the request and send it
try:
json_message = encode_json(message)
json_length = encode_length(len(json_message))
except ValueError:
msg = "Cannot send request of method %s because of " \
"encoding error." % method
request.complete({"__error": msg})
return
ret = self._push_right(json_length + json_message)
ret = self._push_right(json_message)
if not ret:
msg = "Transfer interrupted"
request.complete({"__error": msg})
Expand Down
30 changes: 0 additions & 30 deletions cms/async/Utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import sys
import datetime
import struct
import time

import simplejson as json
Expand All @@ -40,35 +39,6 @@ def random_string(length):
return "".join(choice(letters) for unused_i in xrange(length))


def encode_length(length):
"""Encode an integer as a 4 bytes string
length (int): the integer to encode
return (string): a 4 bytes representation of length
"""
try:
return struct.pack(">I", length)
except Exception as error:
print >> sys.stderr, "Can't encode length: %s %r" % (length, error)
raise ValueError


def decode_length(string):
"""Decode an integer from a 4 bytes string
string (string): a 4 bytes representation of an integer
return (int): the corresponding integer
"""
try:
val, = struct.unpack(">I", string[:4])
return val
except:
print >> sys.stderr, "Can't decode length"
raise ValueError


def encode_json(obj):
"""Encode a dictionary as a JSON string; on failure, returns None.
Expand Down

0 comments on commit 4d829a0

Please sign in to comment.