maybe you have an example for your open api for websocketapp?

Created at 11 Apr 2023, 01:56
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
JO

jon.slater

Joined 26.01.2023

maybe you have an example for your open api for websocketapp?
11 Apr 2023, 01:56


 hello,

I am an python engineer, and I can already see that ctrader_open_api will work for me. However, I have a problem.

I do not want to use reactor; instead I want like to write a python websocketApp to use your protobuf api.

Therefore I apparently have a problem with SSL. I've spend some time to try to understand the ssl context, specifically the set_ciphers() from ctrader_open_api.

There is some code:

```

def on_open(ws):
    print(f"on_open ws={ws}")

    # Create an instance of ProtoOAApplicationAuthReq
    auth_request = ProtoOAAccountAuthReq()
    # Set the client ID and secret
    auth_request.ctidTraderAccountId = 25928084
    auth_request.accessToken = "97RfUCjLnvqM2-v_HzLwRN_-_hUhCLhhq23xxxxxx"
    auth_request.payloadType = ProtoOAPayloadType.PROTO_OA_ACCOUNT_AUTH_REQ
    # # Serialize the message to a string

    msg = ProtoMessage(payload=auth_request.SerializeToString(),
                       clientMsgId="nothing",
                       payloadType=auth_request.payloadType)
    data = msg.SerializeToString()

    # data = sendall(message=auth_request, clientMsgId="web-socket.py")
    ws.send(data)


host = "wss://demo.ctraderapi.com:5035"

ssl_context = ssl.create_default_context()
ssl_context.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_COMPRESSION | ssl.OP_CIPHER_SERVER_PREFERENCE | ssl.OP_NO_SSLv3 | ssl.OP_SINGLE_DH_USE | ssl.OP_SINGLE_ECDH_USE | ssl.OP_NO_TICKET
ssl_context.set_ciphers("TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-CCM8:ECDHE-ECDSA-AES256-CCM:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-CCM8:DHE-RSA-AES256-CCM:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-CCM8:ECDHE-ECDSA-AES128-CCM:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-CCM8:DHE-RSA-AES128-CCM:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-CCM8:AES256-CCM:AES128-CCM8:AES128-CCM:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA")

web_socket_app = websocket.WebSocketApp(host,
                                        on_message=on_message,
                                        on_error=on_error,
                                        on_close=on_close,
                                        on_open=on_open)

sslopt = {"ssl_context": ssl_context}
web_socket_app.run_forever(sslopt=sslopt)

```

The problem, as far as I can see, the WebSocketApp becomes closed immediately, I'm not sure why.

this is the output:

```

on_open ws=<websocket._app.WebSocketApp object at 0x7f4f28147620>
++Sent raw: b'\x81\xc1\xd2\x86\x9fn\xda0\x8f|\xe1\x8e)~\xc2\x12\\\xc0\xde\x9c\xb6W\xe5\xd4\xf9;\x91\xec\xd3\x00\xa4\xf7\xd2\\\xff\xf0\xc0&\xa8\xca\xe8<\x9c\xd9\xb21\xba\xd3\xf7-\x9e\xee\xf7\x1f\xe0\xb5\xe7\x16\xaa\xfe\xe7\x16\xc8\x81\xf1\x01\xa6\xee\xf6\x00\xb5'
++Sent decoded: fin=1 opcode=1 data=b'\x08\xb6\x10\x123\x08\xb6\x10\x10\x94\xc3\xae\x0c\x1a)97RfUCjLnvqM2-v_HzLwRN_-_hUhCLhhq23xxxxxx\x1a\x07nothing'
++Rcv raw: b'\x88\x05\x03\xe8Bye'
++Rcv decoded: fin=1 opcode=8 data=b'\x03\xe8Bye'
++Sent raw: b'\x88\x82\x97\xe3\xe2\x12\x94\x0b'
++Sent decoded: fin=1 opcode=8 data=b'\x03\xe8'
on_close ws=<websocket._app.WebSocketApp object at 0x7f4f28147620>, status_code=1000, msg=Bye
sys:1: ResourceWarning: unclosed <ssl.SSLSocket fd=6, family=2, type=1, proto=6, laddr=('192.168.1.192', 41470), raddr=('3.33.208.221', 5035)>
ResourceWarning: Enable tracemalloc to get the object allocation traceback

```

I believe that the ws.send should come from SSL.y send() but does not; ie:

```

    def send(self, buf, flags=0):
        """
        Send data on the connection. NOTE: If you get one of the WantRead,
        WantWrite or WantX509Lookup exceptions on this, you have to call the
        method again with the SAME buffer.

        :param buf: The string, buffer or memoryview to send
        :param flags: (optional) Included for compatibility with the socket
                      API, the value is ignored
        :return: The number of bytes written
        """

I cannot get and data from on_message().

I hope you could help, perhaps even if you have a python SSL websocketapp example for your api?

Kinds regards,

Jon


@jon.slater
Replies

jon.slater
06 May 2023, 01:22 ( Updated at: 06 May 2023, 01:23 )

 

Instead I used a websocket and a http server :

 

    for path, resource in resources.items():
        root.putChild(path, resource)

    reactor.listenTCP(http_port, Site(root))

    factory_set_live = WebSocketServerFactory()
    factory_set_live.protocol = WebSocketProtocol
    set_live_ws_resource = WebSocketResource(factory_set_live)
    root.putChild(b"ws", set_live_ws_resource)
    reactor.listenTCP(websocket_port, factory_set_live)

    print(
        f"listening on ports {http_port} (HTTP) and {websocket_port} (WebSocket).")

    _data.start()

    reactor.run()

 

Reactor is very robust; I never used it before.

I hope this can help somebody else.

 


@jon.slater