added WebSockets and server name support

pull/39/head
Ciro 2022-11-07 11:06:13 -03:00
rodzic e498551de6
commit 81da498e4c
5 zmienionych plików z 781 dodań i 127 usunięć

Wyświetl plik

@ -60,6 +60,8 @@ app.run()
git clone https://github.com/cirospaciari/socketify.py.git git clone https://github.com/cirospaciari/socketify.py.git
cd ./socketify.py cd ./socketify.py
git submodule update --init --recursive --remote git submodule update --init --recursive --remote
#you can use make linux, make macos or call Make.bat from Visual Studio Development Prompt to build
cd ./src/socketify/native/ && make linux && cd ../../../
#install local pip #install local pip
pypy3 -m pip install . pypy3 -m pip install .
#install in editable mode #install in editable mode

Wyświetl plik

@ -1,2 +1,2 @@
from .socketify import App, AppOptions, AppListenOptions from .socketify import App, AppOptions, AppListenOptions, OpCode, SendStatus
from .helpers import sendfile from .helpers import sendfile

Wyświetl plik

@ -1,5 +1,6 @@
import cffi import cffi
from datetime import datetime from datetime import datetime
from enum import IntEnum
from http import cookies from http import cookies
import inspect import inspect
import json import json
@ -135,12 +136,12 @@ typedef struct uws_req_s uws_req_t;
typedef struct uws_res_s uws_res_t; typedef struct uws_res_s uws_res_t;
typedef struct uws_socket_context_s uws_socket_context_t; typedef struct uws_socket_context_s uws_socket_context_t;
typedef struct uws_websocket_s uws_websocket_t; typedef struct uws_websocket_s uws_websocket_t;
typedef void (*uws_websocket_handler)(uws_websocket_t *ws);
typedef void (*uws_websocket_message_handler)(uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode);
typedef void (*uws_websocket_ping_pong_handler)(uws_websocket_t *ws, const char *message, size_t length);
typedef void (*uws_websocket_close_handler)(uws_websocket_t *ws, int code, const char *message, size_t length);
typedef void (*uws_websocket_upgrade_handler)(uws_res_t *response, uws_req_t *request, uws_socket_context_t *context);
typedef void (*uws_websocket_handler)(uws_websocket_t *ws, void* user_data);
typedef void (*uws_websocket_message_handler)(uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode, void* user_data);
typedef void (*uws_websocket_ping_pong_handler)(uws_websocket_t *ws, const char *message, size_t length, void* user_data);
typedef void (*uws_websocket_close_handler)(uws_websocket_t *ws, int code, const char *message, size_t length, void* user_data);
typedef void (*uws_websocket_upgrade_handler)(uws_res_t *response, uws_req_t *request, uws_socket_context_t *context, void* user_data);
typedef struct typedef struct
{ {
uws_compress_options_t compression; uws_compress_options_t compression;
@ -168,7 +169,7 @@ typedef struct {
typedef void (*uws_listen_handler)(struct us_listen_socket_t *listen_socket, uws_app_listen_config_t config, void *user_data); typedef void (*uws_listen_handler)(struct us_listen_socket_t *listen_socket, uws_app_listen_config_t config, void *user_data);
typedef void (*uws_method_handler)(uws_res_t *response, uws_req_t *request, void *user_data); typedef void (*uws_method_handler)(uws_res_t *response, uws_req_t *request, void *user_data);
typedef void (*uws_filter_handler)(uws_res_t *response, int, void *user_data); typedef void (*uws_filter_handler)(uws_res_t *response, int, void *user_data);
typedef void (*uws_missing_server_handler)(const char *hostname, void *user_data); typedef void (*uws_missing_server_handler)(const char *hostname, size_t hostname_length, void *user_data);
typedef void (*uws_get_headers_server_handler)(const char *header_name, size_t header_name_size, const char *header_value, size_t header_value_size, void *user_data); typedef void (*uws_get_headers_server_handler)(const char *header_name, size_t header_name_size, const char *header_value, size_t header_value_size, void *user_data);
@ -193,14 +194,13 @@ bool uws_constructor_failed(int ssl, uws_app_t *app);
unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic, size_t topic_length); unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic, size_t topic_length);
bool uws_publish(int ssl, uws_app_t *app, const char *topic, size_t topic_length, const char *message, size_t message_length, uws_opcode_t opcode, bool compress); bool uws_publish(int ssl, uws_app_t *app, const char *topic, size_t topic_length, const char *message, size_t message_length, uws_opcode_t opcode, bool compress);
void *uws_get_native_handle(int ssl, uws_app_t *app); void *uws_get_native_handle(int ssl, uws_app_t *app);
void uws_remove_server_name(int ssl, uws_app_t *app, const char *hostname_pattern); void uws_remove_server_name(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length);
void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern); void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length);
void uws_add_server_name_with_options(int ssl, uws_app_t *app, const char *hostname_pattern, struct us_socket_context_options_t options); void uws_add_server_name_with_options(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length, struct us_socket_context_options_t options);
void uws_missing_server_name(int ssl, uws_app_t *app, uws_missing_server_handler handler, void *user_data); void uws_missing_server_name(int ssl, uws_app_t *app, uws_missing_server_handler handler, void *user_data);
void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, void *user_data); void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, void *user_data);
void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length, bool close_connection); void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length, bool close_connection);
void uws_res_pause(int ssl, uws_res_t *res); void uws_res_pause(int ssl, uws_res_t *res);
void uws_res_resume(int ssl, uws_res_t *res); void uws_res_resume(int ssl, uws_res_t *res);
@ -213,6 +213,7 @@ void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key, size_t k
void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection); void uws_res_end_without_body(int ssl, uws_res_t *res, bool close_connection);
bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length); bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length);
uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res); uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res);
void *uws_res_get_native_handle(int ssl, uws_res_t *res);
bool uws_res_has_responded(int ssl, uws_res_t *res); bool uws_res_has_responded(int ssl, uws_res_t *res);
void uws_res_on_writable(int ssl, uws_res_t *res, bool (*handler)(uws_res_t *res, uintmax_t, void *opcional_data), void *user_data); void uws_res_on_writable(int ssl, uws_res_t *res, bool (*handler)(uws_res_t *res, uintmax_t, void *opcional_data), void *user_data);
void uws_res_on_aborted(int ssl, uws_res_t *res, void (*handler)(uws_res_t *res, void *opcional_data), void *opcional_data); void uws_res_on_aborted(int ssl, uws_res_t *res, void (*handler)(uws_res_t *res, void *opcional_data), void *opcional_data);
@ -233,6 +234,18 @@ size_t uws_req_get_parameter(uws_req_t *res, unsigned short index, const char **
size_t uws_req_get_full_url(uws_req_t *res, const char **dest); size_t uws_req_get_full_url(uws_req_t *res, const char **dest);
void uws_req_for_each_header(uws_req_t *res, uws_get_headers_server_handler handler, void *user_data); void uws_req_for_each_header(uws_req_t *res, uws_get_headers_server_handler handler, void *user_data);
void uws_ws(int ssl, uws_app_t *app, const char *pattern, uws_socket_behavior_t behavior, void* user_data);
void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws);
void uws_ws_close(int ssl, uws_websocket_t *ws);
uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode);
uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode, bool compress, bool fin);
uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws, const char *message, size_t length, bool compress);
uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws, const char *message, size_t length, bool compress);
uws_sendstatus_t uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws, const char *message, size_t length, uws_opcode_t opcode, bool compress);
uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws, const char *message, size_t length, bool compress);
void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message, size_t length);
void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data), void *user_data);
""") """)
library_extension = "dll" if platform.system().lower() == "windows" else "so" library_extension = "dll" if platform.system().lower() == "windows" else "so"
@ -241,6 +254,181 @@ library_path = os.path.join(os.path.dirname(__file__), "libsocketify_%s_%s.%s" %
lib = ffi.dlopen(library_path) lib = ffi.dlopen(library_path)
@ffi.callback("void(const char *, size_t, void *)")
def uws_missing_server_name(hostname, hostname_length, user_data):
if not user_data == ffi.NULL:
app = ffi.from_handle(user_data)
try:
if hostname == ffi.NULL:
data = None
else:
data = ffi.unpack(hostname, hostname_length).decode('utf-8')
handler = app._missing_server_handler
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(data))
else:
handler(data)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t *, void *)")
def uws_websocket_drain_handler(ws, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
ws = WebSocket(ws, app.SSL, app.loop)
try:
handler = handlers.drain
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws))
else:
handler(ws)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t *, void *)")
def uws_websocket_open_handler(ws, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
ws = WebSocket(ws, app.SSL, app.loop)
try:
handler = handlers.open
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws))
else:
handler(ws)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t*, const char *,size_t, uws_opcode_t, void*)")
def uws_websocket_message_handler(ws, message, length, opcode, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
ws = WebSocket(ws, app.SSL, app.loop)
try:
if message == ffi.NULL:
data = None
else:
data = ffi.unpack(message, length)
opcode = OpCode(opcode)
if opcode == OpCode.TEXT:
data = data.decode('utf-8')
handler = handlers.message
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws, data, opcode))
else:
handler(ws, data, opcode)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t*, const char*, size_t, void*)")
def uws_websocket_pong_handler(ws, message, length, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
ws = WebSocket(ws, app.SSL, app.loop)
try:
if message == ffi.NULL:
data = None
else:
data = ffi.unpack(message, length)
handler = handlers.pong
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws, data))
else:
handler(ws, data)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t*, const char*, size_t, void*)")
def uws_websocket_ping_handler(ws, message,length, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
ws = WebSocket(ws, app.SSL, app.loop)
try:
if message == ffi.NULL:
data = None
else:
data = ffi.unpack(message, length)
handler = handlers.ping
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws, data))
else:
handler(ws, data)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_websocket_t*, int, const char*, size_t, void*)")
def uws_websocket_close_handler(ws, code, message, length, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
#pass to free data on WebSocket if needed
ws = WebSocket(ws, app.SSL, app.loop, True)
try:
if message == ffi.NULL:
data = None
else:
data = ffi.unpack(message, length)
handler = handlers.close
if handler is None:
return
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(ws, int(code), data))
else:
handler(ws, int(code), data)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(uws_res_t*, uws_req_t*, uws_socket_context_t*, void*)")
def uws_websocket_upgrade_handler(res, req, context, user_data):
if not user_data == ffi.NULL:
(handlers, app) = ffi.from_handle(user_data)
response = AppResponse(res, app.loop, app.SSL)
request = AppRequest(req)
try:
handler = handlers.upgrade
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(response, request, context))
else:
handler(response, request, context)
except Exception as err:
print("Uncaught Exception: %s" % str(err)) #just log in console the error to call attention
@ffi.callback("void(const char *topic, size_t length, void *user_data)")
def uws_req_for_each_topic_handler(topic, topic_size, user_data):
if not user_data == ffi.NULL:
ws = ffi.from_handle(user_data)
try:
header_name = ffi.unpack(topic, topic_size).decode("utf-8")
ws.trigger_for_each_topic_handler(header_name, header_value)
except Exception: #invalid utf-8
return
@ffi.callback("void(const char *, size_t, const char *, size_t, void *)") @ffi.callback("void(const char *, size_t, const char *, size_t, void *)")
def uws_req_for_each_header_handler(header_name, header_name_size, header_value, header_value_size, user_data): def uws_req_for_each_header_handler(header_name, header_name_size, header_value, header_value_size, user_data):
if not user_data == ffi.NULL: if not user_data == ffi.NULL:
@ -259,7 +447,7 @@ def uws_req_for_each_header_handler(header_name, header_name_size, header_value,
def uws_generic_method_handler(res, req, user_data): def uws_generic_method_handler(res, req, user_data):
if not user_data == ffi.NULL: if not user_data == ffi.NULL:
(handler, app) = ffi.from_handle(user_data) (handler, app) = ffi.from_handle(user_data)
response = AppResponse(res, app.loop, False) response = AppResponse(res, app.loop, app.SSL)
request = AppRequest(req) request = AppRequest(req)
try: try:
if inspect.iscoroutinefunction(handler): if inspect.iscoroutinefunction(handler):
@ -271,21 +459,6 @@ def uws_generic_method_handler(res, req, user_data):
response.grab_aborted_handler() response.grab_aborted_handler()
app.trigger_error(err, response, request) app.trigger_error(err, response, request)
@ffi.callback("void(uws_res_t *, uws_req_t *, void *)")
def uws_generic_ssl_method_handler(res, req, user_data):
if not user_data == ffi.NULL:
(handler, app) = ffi.from_handle(user_data)
response = AppResponse(res, app.loop, True)
request = AppRequest(req)
try:
if inspect.iscoroutinefunction(handler):
response.grab_aborted_handler()
response.run_async(handler(response, request))
else:
handler(response, request)
except Exception as err:
response.grab_aborted_handler()
app.trigger_error(err, response, request)
@ffi.callback("void(struct us_listen_socket_t *, uws_app_listen_config_t, void *)") @ffi.callback("void(struct us_listen_socket_t *, uws_app_listen_config_t, void *)")
def uws_generic_listen_handler(listen_socket, config, user_data): def uws_generic_listen_handler(listen_socket, config, user_data):
@ -337,9 +510,303 @@ def uws_generic_cork_handler(res, user_data):
response._cork_handler(response) response._cork_handler(response)
except Exception as err: except Exception as err:
print("Error on cork handler %s" % str(err)) print("Error on cork handler %s" % str(err))
# response.grab_aborted_handler()
# app.trigger_error(err, response, request)
@ffi.callback("void(void*)")
def uws_ws_cork_handler(user_data):
if not user_data == ffi.NULL:
ws = ffi.from_handle(user_data)
try:
if inspect.iscoroutinefunction(ws._cork_handler):
raise RuntimeError("Calls inside cork must be sync")
ws._cork_handler(ws)
except Exception as err:
print("Error on cork handler %s" % str(err))
class OpCode(IntEnum):
CONTINUATION = 0
TEXT = 1
BINARY = 2
CLOSE = 8
PING = 9
PONG = 10
class SendStatus(IntEnum):
BACKPRESSURE = 0
SUCCESS = 1
DROPPED = 2
#dict to keep socket data alive until closed if needed
SocketRefs = {}
class WebSocket:
def __init__(self, websocket, ssl, loop, free_socket_data=False):
self.ws = websocket
self.SSL = ssl
self._ptr = ffi.new_handle(self)
self.loop = loop
self._cork_handler = None
self._for_each_topic_handler = None
self.free_socket_data = free_socket_data
self.socket_data_id = None
self.socket_data = None
self.got_socket_data = False
def trigger_for_each_topic_handler(self, topic):
if hasattr(self, "_for_each_topic_handler") and hasattr(self._for_each_topic_handler, '__call__'):
try:
if inspect.iscoroutinefunction(self._for_each_topic_handler):
raise RuntimeError("WebSocket.for_each_topic_handler must be synchronous")
self._for_each_topic_handler(topic)
except Exception as err:
print("Error on for each topic handler %s" % str(err))
#uuid for socket data, used to free data after socket closes
def get_user_data_uuid(self):
if self.got_socket_data:
return self.socket_data_id
user_data = lib.uws_ws_get_user_data(self.SSL, self._ptr)
if user_data == ffi.NULL:
return None
(data, socket_data_id) = ffi.from_handle(user_data)
self.socket_data_id = socket_data_id
self.socket_data = data
self.got_socket_data = True
return socket_data_id
def get_user_data(self):
if self.got_socket_data:
return self.socket_data
user_data = lib.uws_ws_get_user_data(self.SSL, self._ptr)
if user_data == ffi.NULL:
return None
(data, socket_data_id) = ffi.from_handle(user_data)
self.socket_data_id = socket_data_id
self.socket_data = data
self.got_socket_data = True
return data
def get_buffered_amount(self):
return int(lib.uws_ws_get_buffered_amount(self.SSL, self._ptr))
def subscribe(self, topic):
try:
if isinstance(topic, str):
data = topic.encode("utf-8")
elif isinstance(topic, bytes):
data = topic
else:
return False
return bool(lib.uws_ws_subscribe(self.SSL, self.ws, data, len(data)))
except:
return False
def unsubscribe(self, topic):
try:
if isinstance(topic, str):
data = topic.encode("utf-8")
elif isinstance(topic, bytes):
data = topic
else:
return False
return bool(lib.uws_ws_unsubscribe(self.SSL, self.ws, data, len(data)))
except:
return False
def is_subscribed(self, topic):
try:
if isinstance(topic, str):
data = topic.encode("utf-8")
elif isinstance(topic, bytes):
data = topic
else:
return False
return bool(lib.uws_ws_is_subscribed(self.SSL, self.ws, data, len(data)))
except:
return False
def publish(self, topic, message, opcode=OpCode.BINARY, compress=False):
try:
if isinstance(topic, str):
topic_data = topic.encode("utf-8")
elif isinstance(topic, bytes):
topic_data = topic
else:
return False
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
data = b''
else:
data = json.dumps(message).encode("utf-8")
return bool(lib.uws_ws_publish_with_options(self.SSL, self.ws, topic_data, len(topic_data),data, len(data), int(opcode), bool(compress)))
except:
return False
def get_topics(self):
topics = []
def copy_topics(topic):
topics.append(value)
self.for_each_topic(copy_topics)
return topics
def for_each_topic(self, handler):
self._for_each_topic_handler = handler
lib.uws_ws_iterate_topics(self.SSL, self.ws, uws_req_for_each_topic_handler, self._ptr)
def get_remote_address_bytes(self):
buffer = ffi.new("char**")
length = lib.uws_ws_get_remote_address(self.SSL, self.ws, buffer)
buffer_address = ffi.addressof(buffer, 0)[0]
if buffer_address == ffi.NULL:
return None
try:
return ffi.unpack(buffer_address, length)
except Exception: #invalid
return None
def get_remote_address(self):
buffer = ffi.new("char**")
length = lib.uws_ws_get_remote_address_as_text(self.SSL, self.ws, buffer)
buffer_address = ffi.addressof(buffer, 0)[0]
if buffer_address == ffi.NULL:
return None
try:
return ffi.unpack(buffer_address, length).decode("utf-8")
except Exception: #invalid utf-8
return None
def send_fragment(self, message, compress=False):
try:
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
lib.uws_ws_send_fragment(self.SSL, self.ws, b'', 0, compress)
return self
else:
data = json.dumps(message).encode("utf-8")
return SendStatus(lib.uws_ws_send_fragment(self.SSL, self.ws, data, len(data),compress))
except:
return None
def send_last_fragment(self, message, compress=False):
try:
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
lib.uws_ws_send_last_fragment(self.SSL, self.ws, b'', 0, compress)
return self
else:
data = json.dumps(message).encode("utf-8")
return SendStatus(lib.uws_ws_send_last_fragment(self.SSL, self.ws, data, len(data),compress))
except:
return None
def send_first_fragment(self, message, opcode=OpCode.BINARY, compress=False):
try:
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
lib.uws_ws_send_first_fragment_with_opcode(self.SSL, self.ws, b'', 0, int(opcode), compress)
return self
else:
data = json.dumps(message).encode("utf-8")
return SendStatus(lib.uws_ws_send_first_fragment_with_opcode(self.SSL, self.ws, data, len(data), int(opcode), compress))
except:
return None
def cork_send(self, message, opcode=OpCode.BINARY, compress=False, fin=True):
self.cork(lambda ws: ws.send(message, opcode, compress, fin))
return self
def send(self, message, opcode=OpCode.BINARY, compress=False, fin=True):
try:
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
lib.uws_ws_send_with_options(self.SSL, self.ws, b'', 0, int(opcode), compress, fin)
return self
else:
data = json.dumps(message).encode("utf-8")
return SendStatus(lib.uws_ws_send_with_options(self.SSL, self.ws, data, len(data), int(opcode), compress, fin))
except:
return None
def cork_end(self, code=0, message=None):
self.cork(lambda ws: ws.end(message, code, message))
return self
def end(self, code=0, message=None):
try:
if not isinstance(code, int):
raise RuntimeError("code must be an int")
if isinstance(message, str):
data = message.encode("utf-8")
elif isinstance(message, bytes):
data = message
elif message == None:
lib.uws_ws_end(self.SSL, self.ws, b'', 0)
return self
else:
data = json.dumps(message).encode("utf-8")
lib.uws_ws_end(self.SSL, self.ws, code, data, len(data))
finally:
return self
def close(self):
lib.uws_ws_close(self.SSL, self._ptr)
return self
def cork(self, callback):
self._cork_handler = callback
if is_python: #call is enqueued to garantee corking works properly in python3
self.loop.enqueue(lambda instance: lib.uws_ws_cork(instance.SSL, instance.ws, uws_ws_cork_handler, instance._ptr), self)
else: #just add to uvloop in next tick to garantee corking works properly in pypy3
self.loop.set_timeout(0, lambda instance: lib.uws_ws_cork(instance.SSL, instance.ws, uws_ws_cork_handler, instance._ptr), self)
def __del__(self):
#free SocketRefs when if needed
if self.free_socket_data:
key = self.get_user_data_uuid()
if not key is None:
SocketRefs.pop(key, None)
self.ws = ffi.NULL
self._ptr = ffi.NULL
class WSBehaviorHandlers:
def __init__(self):
self.upgrade = None
self.open = None
self.message = None
self.drain = None
self.ping = None
self.pong = None
self.close = None
class AppRequest: class AppRequest:
def __init__(self, request): def __init__(self, request):
self.req = request self.req = request
@ -477,9 +944,9 @@ class AppRequest:
self._ptr = ffi.NULL self._ptr = ffi.NULL
class AppResponse: class AppResponse:
def __init__(self, response, loop, is_ssl): def __init__(self, response, loop, ssl):
self.res = response self.res = response
self.SSL = ffi.cast("int", 1 if is_ssl else 0) self.SSL = ssl
self.aborted = False self.aborted = False
self.loop = loop self.loop = loop
self._aborted_handler = None self._aborted_handler = None
@ -804,6 +1271,42 @@ class AppResponse:
lib.uws_res_on_data(self.SSL, self.res, uws_generic_on_data_handler, self._ptr) lib.uws_res_on_data(self.SSL, self.res, uws_generic_on_data_handler, self._ptr)
return self return self
def upgrade(self, sec_web_socket_key, sec_web_socket_protocol, sec_web_socket_extensions, socket_context, user_data=None):
if self.aborted:
return False
if isinstance(sec_web_socket_key, str):
sec_web_socket_key_data = sec_web_socket_key.encode('utf-8')
elif isinstance(sec_web_socket_key, bytes):
sec_web_socket_key_data = sec_web_socket_key
else:
raise RuntimeError("sec_web_socket_key need to be an String or Bytes")
if isinstance(sec_web_socket_protocol, str):
sec_web_socket_protocol_data = sec_web_socket_protocol.encode('utf-8')
elif isinstance(sec_web_socket_protocol, bytes):
sec_web_socket_protocol_data = sec_web_socket_protocol
else:
raise RuntimeError("sec_web_socket_protocol need to be an String or Bytes")
if isinstance(sec_web_socket_extensions, str):
sec_web_socket_extensions_data = sec_web_socket_extensions.encode('utf-8')
elif isinstance(sec_web_socket_extensions, bytes):
sec_web_socket_extensions_data = sec_web_socket_extensions
else:
raise RuntimeError("sec_web_socket_protocol need to be an String or Bytes")
user_data_ptr = ffi.NULL
if not user_data is None:
_id = uuid.uuid4()
user_data_ptr = (ffi.new_handle(user_data), _id)
#keep alive data
SocketRefs[_id] = user_data_ptr
lib.uws_res_upgrade(self.SSL, self.res, user_data_ptr, sec_web_socket_key_data, len(sec_web_socket_key_data),sec_web_socket_protocol_data, len(sec_web_socket_protocol_data),sec_web_socket_extensions_data, len(sec_web_socket_extensions_data), socket_context)
def on_writable(self, handler): def on_writable(self, handler):
if not self.aborted: if not self.aborted:
if hasattr(handler, '__call__'): if hasattr(handler, '__call__'):
@ -812,13 +1315,12 @@ class AppResponse:
lib.uws_res_on_writable(self.SSL, self.res, uws_generic_on_writable_handler, self._ptr) lib.uws_res_on_writable(self.SSL, self.res, uws_generic_on_writable_handler, self._ptr)
return self return self
def get_native_handle(self):
return lib.uws_res_get_native_handle(self.SSL, self.res)
def __del__(self): def __del__(self):
self.res = ffi.NULL self.res = ffi.NULL
self._ptr = ffi.NULL self._ptr = ffi.NULL
# void uws_res_on_data(int ssl, uws_res_t *res, void (*handler)(uws_res_t *res, const char *chunk, size_t chunk_length, bool is_end, void *opcional_data), void *opcional_data);
# void uws_res_upgrade(int ssl, uws_res_t *res, void *data, const char *sec_web_socket_key, size_t sec_web_socket_key_length, const char *sec_web_socket_protocol, size_t sec_web_socket_protocol_length, const char *sec_web_socket_extensions, size_t sec_web_socket_extensions_length, uws_socket_context_t *ws);
# void uws_res_on_writable(int ssl, uws_res_t *res, bool (*handler)(uws_res_t *res, uintmax_t, void *opcional_data), void *user_data);
class App: class App:
def __init__(self, options=None): def __init__(self, options=None):
@ -853,66 +1355,251 @@ class App:
self.handlers = [] self.handlers = []
self.error_handler = None self.error_handler = None
self._missing_server_handler = None
def static(self, route, directory):
def static(self, route, dire1ctory):
static_route(self, route, directory) static_route(self, route, directory)
return self return self
def get(self, path, handler): def get(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_get(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_get(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def post(self, path, handler): def post(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_post(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_post(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def options(self, path, handler): def options(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_options(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_options(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def delete(self, path, handler): def delete(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_delete(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_delete(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def patch(self, path, handler): def patch(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_patch(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_patch(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def put(self, path, handler): def put(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_put(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_put(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def head(self, path, handler): def head(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_head(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_head(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def connect(self, path, handler): def connect(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_connect(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_connect(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def trace(self, path, handler): def trace(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_trace(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_trace(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def any(self, path, handler): def any(self, path, handler):
user_data = ffi.new_handle((handler, self)) user_data = ffi.new_handle((handler, self))
self.handlers.append(user_data) #Keep alive handler self.handlers.append(user_data) #Keep alive handler
lib.uws_app_any(self.SSL, self.app, path.encode("utf-8"), uws_generic_ssl_method_handler if self.is_ssl else uws_generic_method_handler, user_data) lib.uws_app_any(self.SSL, self.app, path.encode("utf-8"), uws_generic_method_handler, user_data)
return self return self
def listen(self, port_or_options, handler=None): def get_native_handle(self):
return lib.uws_get_native_handle(self.SSL, self.app)
def num_subscribers(self, topic):
if isinstance(topic, str):
topic_data = topic.encode('utf-8')
elif isinstance(topic, bytes):
topic_data = topic
else:
raise RuntimeError("topic need to be an String or Bytes")
return int(lib.uws_num_subscribers(self.SSL, self.app, topic_data, len(topic_data)))
def publish(self, topic, message, opcode=OpCode.BINARY, compress=False):
if isinstance(topic, str):
topic_data = topic.encode('utf-8')
elif isinstance(topic, bytes):
topic_data = topic
else:
raise RuntimeError("topic need to be an String or Bytes")
if isinstance(message, str):
message_data = message.encode('utf-8')
elif isinstance(message, bytes):
message_data = message
elif message == None:
data = b''
else:
data = json.dumps(message).encode("utf-8")
return bool(lib.uws_publish(self.SSL, self.app, topic_data, len(topic_data), message_data, len(message_data), int(opcode), bool(compress)))
def remove_server_name(self, hostname):
if isinstance(hostname, str):
hostname_data = hostname.encode('utf-8')
elif isinstance(hostname, bytes):
hostname_data = hostname
else:
raise RuntimeError("hostname need to be an String or Bytes")
lib.uws_remove_server_name(self.SSL, self.app, hostname_data, len(hostname_data))
return self
def add_server_name(self, hostname, options=None):
if isinstance(hostname, str):
hostname_data = hostname.encode('utf-8')
elif isinstance(hostname, bytes):
hostname_data = hostname
else:
raise RuntimeError("hostname need to be an String or Bytes")
if options is None:
lib.uws_add_server_name(self.SSL, self.app, hostname_data, len(hostname_data))
else:
socket_options_ptr = ffi.new("struct us_socket_context_options_t *")
socket_options = socket_options_ptr[0]
socket_options.key_file_name = ffi.NULL if options.key_file_name == None else ffi.new("char[]", options.key_file_name.encode("utf-8"))
socket_options.key_file_name = ffi.NULL if options.key_file_name == None else ffi.new("char[]", options.key_file_name.encode("utf-8"))
socket_options.cert_file_name = ffi.NULL if options.cert_file_name == None else ffi.new("char[]", options.cert_file_name.encode("utf-8"))
socket_options.passphrase = ffi.NULL if options.passphrase == None else ffi.new("char[]", options.passphrase.encode("utf-8"))
socket_options.dh_params_file_name = ffi.NULL if options.dh_params_file_name == None else ffi.new("char[]", options.dh_params_file_name.encode("utf-8"))
socket_options.ca_file_name = ffi.NULL if options.ca_file_name == None else ffi.new("char[]", options.ca_file_name.encode("utf-8"))
socket_options.ssl_ciphers = ffi.NULL if options.ssl_ciphers == None else ffi.new("char[]", options.ssl_ciphers.encode("utf-8"))
socket_options.ssl_prefer_low_memory_usage = ffi.cast("int", options.ssl_prefer_low_memory_usage)
lib.uws_add_server_name_with_options(self.SSL, self.app, hostname_data, len(hostname_data), socket_options)
return self
def missing_server_name(self, handler):
self._missing_server_handler = handler
lib.uws_missing_server_name(self.SSL, self.app, uws_missing_server_name, self._ptr)
def ws(self, path, behavior):
native_options = ffi.new("uws_socket_behavior_t *")
native_behavior = native_options[0]
max_payload_length = None
idle_timeout = None
max_backpressure = None
close_on_backpressure_limit = None
reset_idle_timeout_on_send = None
send_pings_automatically = None
max_lifetime = None
compression = None
upgrade_handler = None
open_handler = None
message_handler = None
drain_handler = None
ping_handler = None
pong_handler = None
close_handler = None
if behavior is None:
raise RuntimeError("behavior must be an dict or WSBehavior")
elif isinstance(behavior, dict):
max_payload_length = behavior.get("max_payload_length", 16 * 1024)
idle_timeout = behavior.get("idle_timeout", 60 * 2)
max_backpressure = behavior.get("max_backpressure", 64 * 1024)
close_on_backpressure_limit = behavior.get("close_on_backpressure_limit", False)
reset_idle_timeout_on_send = behavior.get("reset_idle_timeout_on_send", False)
send_pings_automatically = behavior.get("send_pings_automatically", False)
max_lifetime = behavior.get("max_lifetime", 0)
compression = behavior.get("compression", 0)
upgrade_handler = behavior.get("upgrade", None)
open_handler = behavior.get("open", None)
message_handler = behavior.get("message", None)
drain_handler = behavior.get("drain", None)
ping_handler = behavior.get("ping", None)
pong_handler = behavior.get("pong", None)
close_handler = behavior.get("close", None)
native_behavior.maxPayloadLength = ffi.cast("unsigned int", max_payload_length if isinstance(max_payload_length, int) else 16 * 1024)
native_behavior.idleTimeout = ffi.cast("unsigned short", idle_timeout if isinstance(idle_timeout, int) else 16 * 1024)
native_behavior.maxBackpressure = ffi.cast("unsigned int", max_backpressure if isinstance(max_backpressure, int) else 64 * 1024)
native_behavior.compression = ffi.cast("uws_compress_options_t", compression if isinstance(compression, int) else 0)
native_behavior.maxLifetime = ffi.cast("unsigned short", max_lifetime if isinstance(max_lifetime, int) else 0)
native_behavior.closeOnBackpressureLimit = ffi.cast("int", 1 if close_on_backpressure_limit else 0)
native_behavior.resetIdleTimeoutOnSend = ffi.cast("int", 1 if reset_idle_timeout_on_send else 0)
native_behavior.sendPingsAutomatically = ffi.cast("int", 1 if send_pings_automatically else 0)
handlers = WSBehaviorHandlers()
if upgrade_handler:
handlers.upgrade = upgrade_handler
native_behavior.upgrade = uws_websocket_upgrade_handler
else:
native_behavior.upgrade = ffi.NULL
if open_handler:
handlers.open = open_handler
native_behavior.open = uws_websocket_open_handler
else:
native_behavior.open = ffi.NULL
if message_handler:
handlers.message = message_handler
native_behavior.message = uws_websocket_message_handler
else:
native_behavior.message = ffi.NULL
if drain_handler:
handlers.drain = drain_handler
native_behavior.drain = uws_websocket_drain_handler
else:
native_behavior.drain = ffi.NULL
if ping_handler:
handlers.ping = ping_handler
native_behavior.ping = uws_websocket_ping_handler
else:
native_behavior.ping = ffi.NULL
if pong_handler:
handlers.pong = pong_handler
native_behavior.pong = uws_websocket_pong_handler
else:
native_behavior.pong = ffi.NULL
if close_handler:
handlers.close = close_handler
native_behavior.close = uws_websocket_close_handler
else: #always keep an close
native_behavior.close = uws_websocket_close_handler
user_data = ffi.new_handle((handlers, self))
self.handlers.append(user_data) #Keep alive handlers
lib.uws_ws(self.SSL, self.app, path.encode("utf-8"), native_behavior, user_data)
return self
def listen(self, port_or_options=None, handler=None):
self._listen_handler = handler self._listen_handler = handler
if isinstance(port_or_options, int): if port_or_options is None:
lib.uws_app_listen(self.SSL, self.app, ffi.cast("int", 0), uws_generic_listen_handler, self._ptr)
elif isinstance(port_or_options, int):
lib.uws_app_listen(self.SSL, self.app, ffi.cast("int", port_or_options), uws_generic_listen_handler, self._ptr) lib.uws_app_listen(self.SSL, self.app, ffi.cast("int", port_or_options), uws_generic_listen_handler, self._ptr)
elif isinstance(port_or_options, dict):
native_options = ffi.new("uws_app_listen_config_t *")
options = native_options[0]
port = port_or_options.get("port", 0)
options = port_or_options.get("options", 0)
host = port_or_options.get("host", "0.0.0.0")
options.port = ffi.cast("int", port, 0) if isinstance(port, int) else ffi.cast("int", 0)
options.host = ffi.new("char[]", host.encode("utf-8")) if isinstance(host, str) else ffi.NULL
options.options = ffi.cast("int", port) if isinstance(options, int) else ffi.cast("int", 0)
self.native_options_listen = native_options #Keep alive native_options
lib.uws_app_listen_with_config(self.SSL, self.app, options, uws_generic_listen_handler, self._ptr)
else: else:
native_options = ffi.new("uws_app_listen_config_t *") native_options = ffi.new("uws_app_listen_config_t *")
options = native_options[0] options = native_options[0]
@ -980,7 +1667,7 @@ class AppListenOptions:
self.port = port self.port = port
self.host = host self.host = host
self.options = options self.options = options
class AppOptions: class AppOptions:
def __init__(self, key_file_name=None, cert_file_name=None, passphrase=None, dh_params_file_name=None, ca_file_name=None, ssl_ciphers=None, ssl_prefer_low_memory_usage=0): def __init__(self, key_file_name=None, cert_file_name=None, passphrase=None, dh_params_file_name=None, ca_file_name=None, ssl_ciphers=None, ssl_prefer_low_memory_usage=0):
if key_file_name != None and not isinstance(key_file_name, str): raise RuntimeError("key_file_name must be an String or None") if key_file_name != None and not isinstance(key_file_name, str): raise RuntimeError("key_file_name must be an String or None")

@ -1 +1 @@
Subproject commit 6da3fd5b0260d56664d85d62cc4e3dfeaa528e7d Subproject commit 4536669a85a8cd4ba72e489f33f44a57ff825cfd

Wyświetl plik

@ -3,73 +3,23 @@
# import os.path # import os.path
# def in_directory(file, directory): # DLL_EXPORT typedef void (*uws_listen_domain_handler)(struct us_listen_socket_t *listen_socket, const char* domain, size_t domain_length, int options, void *user_data);
# #make both absolute # DLL_EXPORT typedef void (*uws_missing_server_handler)(const char *hostname, size_t hostname_length, void *user_data);
# directory = os.path.join(os.path.realpath(directory), '')
# file = os.path.realpath(file)
# #return true, if the common prefix of both is equal to directory # DLL_EXPORT void uws_app_listen_domain(int ssl, uws_app_t *app, const char *domain,size_t server_name_length, uws_listen_domain_handler handler, void *user_data);
# #e.g. /a/b/c/d.rst and directory is /a/b, the common prefix is /a/b # DLL_EXPORT void uws_app_listen_domain_with_options(int ssl, uws_app_t *app, const char *domain,size_t server_name_length, int options, uws_listen_domain_handler handler, void *user_data);
# return os.path.commonprefix([file, directory]) == directory # DLL_EXPORT void uws_app_domain(int ssl, uws_app_t *app, const char* server_name, size_t server_name_length);
# application/x-www-form-urlencoded # DLL_EXPORT void uws_remove_server_name(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length);
# application/x-www-form-urlencoded # DLL_EXPORT void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length);
# multipart/form-data # DLL_EXPORT void uws_add_server_name_with_options(int ssl, uws_app_t *app, const char *hostname_pattern, size_t hostname_pattern_length, struct us_socket_context_options_t options);
# DLL_EXPORT void uws_missing_server_name(int ssl, uws_app_t *app, uws_missing_server_handler handler, void *user_data);
# DLL_EXPORT void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, void *user_data);
# void uws_res_prepare_for_sendfile(int ssl, uws_res_t *res) {
# if (ssl) {
# uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
# auto pair = uwsRes->getSendBuffer(2);
# char *ptr = pair.first;
# ptr[0] = '\r';
# ptr[1] = '\n';
# uwsRes->uncork();
# } else {
# uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
# auto pair = uwsRes->getSendBuffer(2);
# char *ptr = pair.first;
# ptr[0] = '\r';
# ptr[1] = '\n';
# uwsRes->uncork();
# }
# }
# int uws_res_state(int ssl, uws_res_t *res) {
# if (ssl) {
# uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
# return uwsRes->getHttpResponseData()->state;
# } else {
# uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
# return uwsRes->getHttpResponseData()->state;
# }
# }
#uws_res_get_native_handle
# void *uws_res_get_native_handle(int ssl, uws_res_t *res) {
# if (ssl) {
# uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res;
# return uwsRes->getNativeHandle();
# } else {
# uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res;
# return uwsRes->getNativeHandle();
# }
# }
# unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic);
# bool uws_publish(int ssl, uws_app_t *app, const char *topic, size_t topic_length, const char *message, size_t message_length, uws_opcode_t opcode, bool compress);
# void *uws_get_native_handle(int ssl, uws_app_t *app);
# void uws_remove_server_name(int ssl, uws_app_t *app, const char *hostname_pattern);
# void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern);
# void uws_add_server_name_with_options(int ssl, uws_app_t *app, const char *hostname_pattern, struct us_socket_context_options_t options);
# void uws_missing_server_name(int ssl, uws_app_t *app, uws_missing_server_handler handler, void *user_data);
# void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, void *user_data);
# https://github.com/uNetworking/uWebSockets.js/blob/master/examples/VideoStreamer.js
# from socketify import App # from socketify import App
from socketify import App, AppOptions from socketify import App, AppOptions, OpCode
# import os # import os
import multiprocessing import multiprocessing
@ -78,32 +28,47 @@ import time
import mimetypes import mimetypes
mimetypes.init() mimetypes.init()
#need to fix get_data using sel._data etc
async def home(res, req): async def home(res, req):
print("full", req.get_full_url()) res.end("Home")
print("normal", req.get_url())
print("method", req.get_method())
res.end("Test") def ws_open(ws):
print("Upgrated!")
print(ws.send("Xablau!", OpCode.TEXT))
def run_app(): def ws_message(ws, message, opcode):
app = App() print(message, opcode)
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)))
app.run()
def create_fork(): async def ws_upgrade(res, req, socket_context):
n = os.fork() key = req.get_header("sec-websocket-key")
# n greater than 0 means parent process protocol = req.get_header("sec-websocket-protocol")
if not n > 0: extensions = req.get_header("sec-websocket-extensions")
run_app() await asyncio.sleep(2)
print("request upgrade!")
res.upgrade(key, protocol, extensions, socket_context)
app = App()
app.ws("/*", {
'open': ws_open,
'message': ws_message,
'upgrade': ws_upgrade
})
app.get("/", home)
app.listen(3000, lambda config: print("Listening on port http://localhost:%d now\n" % (config.port)))
app.run()
# def create_fork():
# n = os.fork()
# # n greater than 0 means parent process
# if not n > 0:
# run_app()
#openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -passout pass:1234 -keyout ./misc/key.pem -out ./misc/cert.pem #openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -passout pass:1234 -keyout ./misc/key.pem -out ./misc/cert.pem
# # fork limiting the cpu count - 1 # # fork limiting the cpu count - 1
# for i in range(1, multiprocessing.cpu_count()): # for i in range(1, multiprocessing.cpu_count()):
# create_fork() # create_fork()
run_app() # run app on the main process too :) # run_app() # run app on the main process too :)
# from datetime import datetime # from datetime import datetime
# raw = "_ga=GA1.1.1871393672.1649875681; affclick=null; __udf_j=d31b9af0d332fec181c1a893320322c0cb33ce95d7bdbd21a4cc4ee66d6d8c23817686b4ba59dd0e015cb95e8196157c" # raw = "_ga=GA1.1.1871393672.1649875681; affclick=null; __udf_j=d31b9af0d332fec181c1a893320322c0cb33ce95d7bdbd21a4cc4ee66d6d8c23817686b4ba59dd0e015cb95e8196157c"