user3842234
user3842234

Reputation: 77

Wait using sockets

Is there a method to wait for a result from an SSL socket before continuing?

for example this is my current code :

circ_to_rend.createStream(1, "xx.x.x.x", 80)
connected = recvCell(ssl_sock)

but is there a way to pause the program until something is sent back from that stream or do I just simply carry on using the code above which should do this as connected willn't be assigned a value until somthing is received?

create stream is a section of code i have written which creates a stream to send data through the tor network,and recvCell is below, this gets a reply and decodes it so it can be read :

def recvCell(sock, waitFor = 0):
        while True:
                hdr = sock.recv(3)
                circid, cmd = struct.unpack(">HB", hdr[0:3])
                ln = 509
                if cmd == 7 or cmd >= 128:
                        ln = struct.unpack(">H", sock.recv(2))[0]
                pl = sock.recv(ln)

                print "got pkt circ ",circid, " cmd", cmd
                if cmd == waitFor or waitFor == 0:
                        print "Return pkt circ ",circid, " cmd", cmd
                        return { 'circId': circid, 'cmd': cmd, 'len': ln, 'pl': pl}

Upvotes: 0

Views: 206

Answers (2)

abarnert
abarnert

Reputation: 366013

To answer your literal question:

is there a way to pause the program until something is sent back from that stream

Yes, the select module (or, in 3.4+, the higher-level selectors module) provides ways to pause until something has been sent back, after which you know you can receive it without blocking.

But there's a much simpler way to do this, and as far as I can tell you're already doing it:

do I just simply carry on using the code above which should do this as connected willn't be assigned a value until somthing is received?

If connected isn't assigned a value until something is received, then you're already pausing the program until something is sent back from the stream. Unless you switch a socket to non-blocking mode, recv automatically does that. So… I don't know what your problem is, but if you're looking for validation that your code is correct, then yes, it is—at least in this aspect.


There is at least one other problem, however. There is absolutely no guarantee that recv(509) will block until 509 bytes come in. It will block until any packet comes in. Which could be less than 509 bytes. Which means your code will read the first, say, 300 bytes of a message and treat it as a whole message, and then the next time you try to recv you'll get the remaining 209 bytes of that message (or maybe those 209 bytes plus the first 140 of the next message, or whatever) and confuse your code badly. You should always loop and accumulate until you get the full data. The easiest way to do that is to write a function like this:

def recvall(sock, bufsize):
    buf = ''
    while len(buf) < bufsize:
        newbuf = sock.recv(bufsize - len(buf))
        if not newbuf:
            return buf # or maybe raise an exception
        buf += newbuf

Upvotes: 0

enrico.bacis
enrico.bacis

Reputation: 31524

The code you provided is not complete so we can't figure out the entire design, but the ssl module uses socket, whose recv() method can:

  1. (socket in blocking mode): Blocks the execution until some data is ready.

  2. (socket in non-blocking mode): Throws an error if no data is available

The sockets are created in blocking mode as default (the blocking setting can be changed using setblocking). So a call to recv() should block until some data is ready on the SSL socket.

Upvotes: 1

Related Questions