Skip to content

fix cloud server#658

Draft
TheCommCraft wants to merge 7 commits into
semver2from
semver2_cloudserver_fix
Draft

fix cloud server#658
TheCommCraft wants to merge 7 commits into
semver2from
semver2_cloudserver_fix

Conversation

@TheCommCraft

@TheCommCraft TheCommCraft commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Solves issue #648

Changes

Added SSL version of cloud server and refactored cloud server module

Tests

@TheCommCraft

Copy link
Copy Markdown
Collaborator Author

When we merge this, we will need to update the documentation.

@faretek1 faretek1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bunch of code duplication between TWCloudServer and TWSslCloudServer. Would it be worth reducing this? Inheritance/polymorphism could work here however that can tend to confuse where actual implementations are. Do you want me to try running this code to see if it works?

if self.server.log_var_sets:
print(self.address[0]+":"+str(self.address[1]), "tried to set a var on non-whitelisted project and was disconnected, project:", data["project_id"], "user:",data["user"])
print(
self.address[0] + ":" + str(self.address[1]),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could use fstring

@faretek1 faretek1 Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just because the old code has it, which is kind of a separate issue

@TheCommCraft

Copy link
Copy Markdown
Collaborator Author

I guess it can't hurt

@TheCommCraft

Copy link
Copy Markdown
Collaborator Author

so?

@faretek1 faretek1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried running it and have encountered issues (unable to connect to turbowarp project like I used to be able to). Am I doing something wrong?

keyfile: Optional[str] = None,
ssl_version: int = ssl.PROTOCOL_TLSv1_2,
ssl_context: Optional[ssl.SSLContext] = None,
thread: bool = True,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this argument is unused

hostname: str = "127.0.0.1",
port: int = 8080,
*,
thread: bool = True,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this argument also appears unused. i fixed this in the main branch a while ago. thread=True/False has to be provided when calling server.start() e.g. server.start(thread=False)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, it was already unused and this is semver2 so we cannot make api incompatible changes. we could however issue a warning if this is supplied.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i have added a warning for both unused params

)


class TwSSLCloudServer(SimpleSSLWebSocketServer, BaseEventHandler):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the use of SimpleWebSocketServer means that we are forced to have class duplication here. I think it may be a good idea, at some point, to refactor the server to use the more conventional websockets library for both client and server. However this is not high priority

thread: bool = True,
length_limit: Optional[int] = None,
allow_non_numeric: bool = True,
whitelisted_projects: Optional[list[Any]] = None,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default whitelisted_projects is None however when I use this default argument and try to connect to my project, it gives

127.0.0.1:60512 connected
             127.0.0.1:60512 tried to handshake on a non-whitelisted project: 1315568661 user: player
                                                                                                     127.0.0.1:60512 disconnected

i.e. it is not whitelisted when there is no whitelist in existence. This should not happen. I have not tested the SSLServer yet.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

full log:

uv run python
Python 3.14.0 (main, Nov 19 2025, 22:48:15) [Clang 21.1.4 ] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import scratchattach as sa
>>> sa.init_cloud_server.__annotations__
{'hostname': 'str', 'port': 'int', 'thread': 'bool', 'length_limit': 'Optional[int]', 'allow_non_numeric': 'bool', 'whitelisted_projects': 'Optional[list[Any]]', 'allow_nonscratch_names': 'bool', 'blocked_ips': 'Optional[list[str]]', 'sync_players': 'bool', 'log_var_sets': 'bool', 'return': 'TwCloudServer'}
>>> srv = sa.init_cloud_server()
>>> srv
<scratchattach.eventhandlers.cloud_server.TwCloudServer object at 0x72620d9abe00>
>>> srv
<scratchattach.eventhandlers.cloud_server.TwCloudServer object at 0x72620d9abe00>
>>> srv.start()
Serving websocket server: ws://127.0.0.1:8080
>>> 127.0.0.1:48630 connected
                             127.0.0.1:48630 tried to handshake on a non-whitelisted project: 1315568661 user: player
                                                                                                                     127.0.0.1:48630 disconnected
                                                                                                                                                 127.0.0.1:60512 connected
             127.0.0.1:60512 tried to handshake on a non-whitelisted project: 1315568661 user: player
                                                                                                     127.0.0.1:60512 disconnected
                                                                                                                             >>>
>>>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

url i used: https://turbowarp.org/1315568661?cloud_host=ws://127.0.0.1:8080

since it disconnects the user immediately, turbowarp thinks that the server rejected it because of its username, which is not true. Perhaps this should be added to documentation as a side note.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even when I explicitly whitelist the project, it still fails. Is it meant to be a string, not an int? maybe we should avoid Any here.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>>> srv = sa.init_cloud_server(whitelisted_projects=[1315568661])
>>> srv.start()
Serving websocket server: ws://127.0.0.1:8080
>>> 127.0.0.1:46418 connected
                             127.0.0.1:46418 tried to handshake on a non-whitelisted project: 1315568661 user: player
                                                                                                                     127.0.0.1:46418 disconnected

>>> srv.whitelisted_projects
[1315568661]
>>>

that is how i provided the id, which could be wrong

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be fixed

thread.join()


def init_ssl_cloud_server(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is not exported in __init__.py so i cannot use sa.init_ssl_cloud_server, but have to do sa.eventhandlers.cloud_server.init_ssl_cloud_server

port: int = 8080,
*,
certfile: Optional[str] = None,
keyfile: Optional[str] = None,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there should be docs for this. Also it would be nice if a more graceful error could be given (I am not aware of how to use ssl_context) instead of relying on SimpleSSLWebsockerServer to fail and give an error like so: TypeError: certfile should be a valid filesystem path. If I haven't provided a certfile, then how can I know what this means and how to fix it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot use this in a browser because it complains about it being a Self-signed cert, and when I add it to the CAs, it complains about a "CA cert being used as an end entity." How should I add an exception for my browser (or something else) so that I can use turbowarp's cloud_host parameter with the TWSSLCloudServer?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked it up and if one wants to be accepted by any browser (without changing any settings), one needs to use a domain instead of an ip to access the secure websocket. It might still be possible to use your own computer to host the cloud server but you would have to forward a port.

@TheCommCraft

Copy link
Copy Markdown
Collaborator Author

The easiest way to get a cloud server that is accessible from any normal browser is to start the cloud server without SSL and then just tunnel the port and use wss://<tunnel_domain>. You can also host a cloud server with SSL if your server is accessible from the internet by pointing a domain at the server and using a CA signed certificate with the SSL server.

@TheCommCraft

Copy link
Copy Markdown
Collaborator Author

I have only tested the first method but it works well and I don't have a server that I could use to test the second method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants