Search code examples
pythonsocketsssl

" An operation was attempted on something that is not a socket" when I try to add SSL authentication


I created a server that displays data sent from a client. It worked initially but stopped after I tried to include SSL authentication. The issue seems to arise when I attempt to use the wrap_socket() function.

import socket
import json
import ssl 

HOST: str = '127.0.0.1'
PORT: int = 5507

def create_server_socket() -> socket.socket:
    """Creates a TCP socket, binds it to the host and port and listens for a connection. Will try again should the process fail"""
    try:
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.bind((HOST, PORT))
        server_socket.listen()

        print(f"SERVER LISTENING ON {HOST, PORT}")
        return server_socket
    except socket.error as message:
        print("Socket creation error: " + str(message) + "\n Retrying...")
        return create_server_socket()

def main() -> None:
    """Main function to start the server."""
    context : ssl.SSLContext = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)    
    context.load_cert_chain("ssl/server.crt", "ssl/server.key")
    server_socket: socket.socket = create_server_socket()

    context.wrap_socket(server_socket, server_side=True)

    client_socket, client_address = server_socket.accept()
    with client_socket:
        data: bytes = client_socket.recv(1024)
        print(f"{client_address} connected as {data.decode(encoding='utf-8')}\n")
        while True:
            data: bytes = client_socket.recv(1024)
            decoded_data: str = data.decode(encoding='utf-8')
            try:
                data: dict =json.loads(decoded_data)
            except json.JSONDecodeError:
                print(f"{client_address} disconnected!")
                server_socket.close()
                client_socket.close()
                break
            print(f"{data['sender']}: {data['msg']}")
            

if __name__ == '__main__':
    main()

I received the following error:

Traceback (most recent call last):
  File "c:\Users\Yoocee\Desktop\Algorithmic Sciences\server.py", line 82, in <module>
    main()
  File "c:\Users\Yoocee\Desktop\Algorithmic Sciences\server.py", line 57, in main
    client_socket, client_address = server_socket.accept()
                                    ^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Yoocee\AppData\Local\Programs\Python\Python311\Lib\socket.py", line 294, in accept
    fd, addr = self._accept()
               ^^^^^^^^^^^^^^
OSError: [WinError 10038] An operation was attempted on something that is not a socket

What am I doing wrong and how do I fix it?


Solution

  • context.wrap_socket(server_socket, server_side=True)
    
    client_socket, client_address = server_socket.accept()
    

    According to the documentation wrap_socket wraps "an existing Python socket sock and return an instance of SSLContext.sslsocket_class". You ignore the return value though. Instead you should do

    server_socket = context.wrap_socket(server_socket, server_side=True)
    
    client_socket, client_address = server_socket.accept()
    

    That you should use the socket returned by wrap_socket can also be seen from various examples in the documentation. So please use the documentation, it is pretty good.