Skip to content

Instantly share code, notes, and snippets.

@devilholk
Created August 16, 2020 09:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devilholk/8b1474dcf832f678222ec370478b5029 to your computer and use it in GitHub Desktop.
Save devilholk/8b1474dcf832f678222ec370478b5029 to your computer and use it in GitHub Desktop.
Test of receiving file descriptors from another process using AF_UNIX
AUTO_DELETE = False #Change this to True to delete the socket before usage in case it was never cleaned up for some reason
import socketserver, os, struct
from socket import *
class my_handler(socketserver.StreamRequestHandler):
def handle(self):
print('New request!', self.request)
while True:
msg, ancdata, flags, addr = self.request.recvmsg(1024, 1024)
#Print out message
print(msg, ancdata, flags, addr)
#Check if it was fit
if flags & MSG_TRUNC:
print('Oh noes! Message was truncated!')
if flags & MSG_CTRUNC:
print('Oh noes! Ancillary data was truncated!')
elif ancdata:
#Go throuhg ancillary data
for cmsg_level, cmsg_type, cmsg_data in ancdata:
#Make sure we understand it
assert (cmsg_level, cmsg_type) == (SOL_SOCKET, SCM_RIGHTS)
#Go through the file descriptors and check them out
for (fd,) in struct.iter_unpack('I', cmsg_data):
f = os.fdopen(fd)
print(f'File descriptor: {fd} File handle: {f} Pos: {f.tell()}')
f.close()
#If we get an empty message we will close
if not msg:
self.request.close()
print('Closing', self.request)
return
#socketserver.UnixStreamServer is actually SOCK_STREAM and even though SOCK_DGRAM will not be out of order on most systems it does not guarantee it per definition
#Therefore we will use SOCK_SEQPACKET which is a stream of messages that arrives in order
class my_server(socketserver.ThreadingMixIn, socketserver.UnixStreamServer):
socket_type = SOCK_SEQPACKET
#Try to remove socket reference before running (yes, we should only do this in case we need to but this is just a PoC)
if AUTO_DELETE:
try:
os.unlink('/tmp/fd_test.sock')
except:
pass
try:
server = my_server('/tmp/fd_test.sock', my_handler)
server.serve_forever()
finally:
#Clean up
os.unlink('/tmp/fd_test.sock')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment