Note that there are some explanatory texts on larger screens.

plurals
  1. POMultiple Sub-protocol Websocket Javascript Client and Libwebsockets Server not working
    primarykey
    data
    text
    <p>I am trying to create a simple two protocol client and server for a demo. But when I specify two sub-protocols in the client initialization of the websocket I always get this message on the server side:</p> <pre><code>[1363089953:1535] ERR: Req protocol SIGN_IN_OUT_REQUEST_PROTOCOL, GET_REQUEST_PROTOCOL not supported </code></pre> <p>Client Javascript Code:</p> <pre><code> var host = 'ws://10.0.96.32:9000'; var webSocket = {}; var websocketStatus = {}; $(function() { function webSocketSupported() { if(window.MozWebSocket) { window.WebSocket = window.MozWebSocket; } return (window.webSocket != null); } if(!webSocketSupported) { $(document).simpledialog2({ mode: 'blank', headerClose: true, blankContent : "&lt;p&gt;Websockets not supported by this browser. How about &lt;a href='http://www.google.com/chrome'&gt;Google Chrome&lt;/a&gt;?&lt;/p&gt;"+ "&lt;a rel='close' data-role='button' href='#'&gt;Close&lt;/a&gt;" }); } else { $("#login_form").validate({ rules:{ username: {required: true, minlength: 2}, password: {required: true, minlength: 4} }, messages:{ username: {required: "Username is required", minlength: "Username must be atleast 2 characters"}, password: {required: "Password is required", minlength: "Password must be atleast 4 characters"} } }); /** Setting up WebSocket **/ webSocket = new WebSocket(host, 'SIGN_IN_OUT_REQUEST_PROTOCOL', 'GET_REQUEST_PROTOCOL'); webSocket.binaryType = "arraybuffer"; webSocket.onopen = onopen; webSocket.onmessage = onmessage; webSocket.onclose = onclose; webSocket.onerror = onerror; } }); function onopen() { $('#connectionStatus').text("Connected"); $('#connectionStatus').buttonMarkup({theme: 'b'}); $("#connectionStatus").data('icon', 'check'); $("#connectionStatus .ui-icon").addClass("ui-icon-check").removeClass("ui-icon-alert"); $('#login_info').append("Sub-protocol: "+webSocket.protocol+"\n"); } function onmessage(event) { var data = new DataView(event.data); if(data.getUint8(data.byteLength - 1) == 1) { $('#login_info').append("Login Attempt Successful"); $.mobile.loadPage("mobileApp.html"); $.mobile.changePage("mobileApp.html") } else { $('#login_info').append("Login Attempt Unsuccessful"); $('#username').val(""); $('#password').val(""); } } function onclose() { $('#connectionStatus').text("Connection Closed"); $('#connectionStatus').buttonMarkup({theme: 'a'}); $("#connectionStatus").data('icon', 'alert'); $("#connectionStatus .ui-icon").addClass("ui-icon-alert").removeClass("ui-icon-alert"); } function onerror() { $('#connectionStatus').text("Connection Error"); $('#connectionStatus').buttonMarkup({theme: 'a'}); $("#connectionStatus").data('icon', 'alert'); $("#connectionStatus .ui-icon").addClass("ui-icon-alert").removeClass("ui-icon-alert"); } function initialize() { $('#login_info').val(""); $('#username').val(""); $('#password').val(""); $('#connectionStatus').text("Connection Closed"); $('#connectionStatus').buttonMarkup({theme: 'a'}); $("#connectionStatus").data('icon', 'alert'); $("#connectionStatus .ui-icon").addClass("ui-icon-alert").removeClass("ui-icon-alert"); } function sendLoginRequest(event) { var i = 0; event.preventDefault(); if($("#login_form").valid()) { var username = $("#username").val(); var password = $("#password").val(); var loginRequest = new Uint8Array(calculateBufferLength()); loginRequest[i++] = 0x13; //User Accounts IP loginRequest[i++] = 0x13; //Sign In/Sign Out Request loginRequest[i++] = 0x07; //Sign In loginRequest[i++] = username.length; loginRequest[i++] = password.length; //Pushing username for(var j=0; j &lt; username.length; j++) { loginRequest[i++] = username.charCodeAt(j); } //Pushing password for(var j=0; j &lt; password.length; j++) { loginRequest[i++] = password.charCodeAt(j); } webSocket.send(loginRequest.buffer); $("#login_info").append("Login request sent with\nUsername: "+username+"\nPassword: "+password+"\n"); } } function calculateBufferLength() { var opIPLength = 1; var modeLength = 1; var subModeLength = 1; var UserNamePasswordlengths = 2; var userNameLength = $("#username").val().length; var passwordLength = $("#password").val().length; return (opIPLength + modeLength + subModeLength + UserNamePasswordlengths + userNameLength + passwordLength); } </code></pre> <p>Server C/C++ code (Libwebsockets)</p> <pre><code> #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;stdint.h&gt; #include &lt;string&gt; #include &lt;vector&gt; #include &lt;libwebsockets.h&gt; using namespace std; typedef enum { USER_ACCOUNTS_IP_REQUEST, MODE, SUB_MODE, USER_NAME_LENGTH, PASSWORD_LENGTH }user_accounts_ip_request_t; typedef enum { USER_ACCOUNTS_IP_RESPONSE, RESPONSE_IP }user_accounts_ip_response_t; int Hex_to_Dec(unsigned char *array, int size); void sendLoginResponse(struct libwebsocket *wsi, void *in_buffer, size_t bufferlen, struct per_session_data__binary *out_buffer); void printSocketInfo(struct libwebsocket *wsi, struct libwebsocket_context *currentContext); struct per_session_data__binary { unsigned int len; unsigned char buf[sizeof(LWS_SEND_BUFFER_PRE_PADDING) + 1024 + sizeof(LWS_SEND_BUFFER_POST_PADDING)]; }; static int callback_http(struct libwebsocket_context *currentContext, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) { return 0; } static int callback_sign_in_out_request(struct libwebsocket_context *currentContext, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) { struct per_session_data__binary *psb = (per_session_data__binary *)user; //////// switch (reason) { case LWS_CALLBACK_ESTABLISHED: // just log message that someone is connecting printf("connection established\n"); break; case LWS_CALLBACK_PROTOCOL_INIT: printf("LWS_CALLBACK_PROTOCOL_INIT\n"); break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: printf("LWS_CALLBACK_CLIENT_CONNECTION_ERROR\n"); break; case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: printf("LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH\n"); break; case LWS_CALLBACK_RECEIVE: { printf("Binary frame received decoding packet...\n"); sendLoginResponse(wsi, in, len, psb); } break; default: break; } return 0; } static int callback_get_request(struct libwebsocket_context *currentContext, struct libwebsocket *wsi, enum libwebsocket_callback_reasons reason, void *user, void *in, size_t len) { return 0; } static struct libwebsocket_protocols protocols[] = { /* first protocol must always be HTTP handler */ { "http-only", // name callback_http, // callback 0 // per_session_data_size }, { "SIGN_IN_OUT_REQUEST_PROTOCOL", // protocol name - very important! callback_sign_in_out_request, // callback sizeof(struct per_session_data__binary) // we don't use any per session data }, { "GET_REQUEST_PROTOCOL", callback_get_request, sizeof(struct per_session_data__binary) }, { NULL, NULL, 0 /* End of list */ } }; int main(void) { // server url will be http://localhost:9000 int port = 9000; const char *interface = NULL; struct libwebsocket_context *context; struct lws_context_creation_info info; // we're not using ssl const char *cert_path = NULL; const char *key_path = NULL; // no special options int opts = 0; info.port = port; info.iface = interface; info.protocols = protocols; info.extensions = libwebsocket_get_internal_extensions(); info.ssl_cert_filepath = cert_path; info.ssl_private_key_filepath = key_path; info.ssl_ca_filepath = NULL; info.gid = -1; info.uid = -1; info.options = opts; info.user = NULL; //info.ka_time = 0; //info.ka_probes = 100; //info.ka_interval= 60; context = libwebsocket_create_context(&amp;info); if (context == NULL) { fprintf(stderr, "libwebsocket init failed\n"); return -1; } printf("starting server...\n"); // infinite loop, to end this server send SIGTERM. (CTRL+C) while (1) { libwebsocket_service(context, 50); //printf("after service\n"); // libwebsocket_service will process all waiting events with their // callback functions and then wait 50 ms. // (this is a single threaded webserver and this will keep our server // from generating load while there are not requests to process) } libwebsocket_context_destroy(context); return 0; } void sendLoginResponse(struct libwebsocket *wsi, void *in_buffer, size_t bufferlen, struct per_session_data__binary *out_buffer) { vector&lt;string&gt; userNames, passwords; string userName, password; bool loginValid = false; int usernameLength, passwordLength; int usernamePos, passwordPos; userNames.push_back("Nautel"); passwords.push_back("password"); //Print Login Request Data char* loginRequest = (char*) in_buffer; usernameLength = loginRequest[USER_NAME_LENGTH]; passwordLength = loginRequest[PASSWORD_LENGTH]; usernamePos = PASSWORD_LENGTH + 1; passwordPos = usernamePos + usernameLength; //Get Username for(int i=usernamePos; i &lt; (usernamePos+usernameLength); i++) { userName.push_back(loginRequest[i]); } //Get Password for(int i=passwordPos; i &lt; (passwordPos + passwordLength); i++) { password.push_back(loginRequest[i]); } printf("Username: %s Password: %s\n", userName.c_str(), password.c_str()); for(int i=0; i &lt; userNames.size(); i++) { loginValid = (!userName.compare(userNames[i]) &amp;&amp; !password.compare(passwords[i])); if(loginValid) break; } out_buffer-&gt;buf[USER_ACCOUNTS_IP_RESPONSE] = 0x13; out_buffer-&gt;buf[RESPONSE_IP] = (loginValid) ? 0x01 : 0x00; out_buffer-&gt;len = 2; libwebsocket_write(wsi, out_buffer-&gt;buf, out_buffer-&gt;len, LWS_WRITE_BINARY); } void printSocketInfo(struct libwebsocket *wsi, struct libwebsocket_context *currentContext){ char name[128]; int name_len=sizeof(name); char rip[16]; int rip_len= sizeof(rip); int fd; fd = libwebsocket_get_socket_fd(wsi); libwebsockets_get_peer_addresses (currentContext, wsi, fd, name, name_len, rip, rip_len); printf("Name: %s, IP: %s\n", name, rip); } </code></pre> <p>Is it possible to have a client with multiple subprotocols supported by a single server or vice-versa. Or would I need multiple websocket connections from the client to the server for different protocols.</p> <p>Regards, Shreyas</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload