Hello
I try to build a project with server and client, both written in c++ and they communicate via websockets.
#include "Websocket.h"
const char* Websocket::interface = NULL;
// we're not using ssl
const char* Websocket::cert_path = NULL;
const char* Websocket::key_path = NULL;
int Websocket::opts = 1;
libwebsocket_extension* Websocket::libwebsocket_internal_extensions = libwebsocket_internal_extensions;
int Websocket::port;
struct libwebsocket_context* Websocket::context = NULL;
Websocket::Websocket(int port)
{
Websocket::setPort(port);
}
Websocket::~Websocket()
{
}
void Websocket::setPort(int port)
{
Websocket::port = port;
}
int Websocket::callback_http(struct libwebsocket_context* context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len)
{
return 0;
}
void Websocket::createWebsocket()
{
}
int Websocket::callback_dumb_increment(struct libwebsocket_context * context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
std::cout << "callback_dumb_increment" << std::endl;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: // just log message that someone is connecting
printf("connection established\n");
break;
case LWS_CALLBACK_RECEIVE: { // the funny part
// create a buffer to hold our response
// it has to have some pre and post padding. You don't need to care
// what comes there, libwebsockets will do everything for you. For more info see
//
http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n597
unsigned char *buf = (unsigned char*) malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
LWS_SEND_BUFFER_POST_PADDING);
int i;
// pointer to `void *in` holds the incomming request
// we're just going to put it in reverse order and put it in `buf` with
// correct offset. `len` holds length of the request.
for (i=0; i < len; i++) {
buf[LWS_SEND_BUFFER_PRE_PADDING + (len - 1) - i ] = ((char *) in)[i];
}
// log what we recieved and what we're going to send as a response.
// that disco syntax `%.*s` is used to print just a part of our buffer
//
http://stackoverflow.com/questions/5189071/print-part-of-char-array
printf("received data: %s, replying: %.*s\n", (char *) in, (int) len,
buf + LWS_SEND_BUFFER_PRE_PADDING);
// send response
// just notice that we have to tell where exactly our response starts. That's
// why there's `buf[LWS_SEND_BUFFER_PRE_PADDING]` and how long it is.
// we know that our response has the same length as request because
// it's the same message in reverse order.
libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
// release memory back into the wild
free(buf);
break;
}
default:
break;
}
return 0;
}
libwebsocket_protocols Websocket::protocols[] = {
/* first protocol must always be HTTP handler */
{
"http-only", // name
callback_http, // callback
0 // per_session_data_size
},
{
"dumb-increment-protocol", // protocol name - very important!
callback_dumb_increment, // callback
0 // we don't use any per session data
},
{
NULL, NULL, 0 /* End of list */
}
};
int Websocket::threadCode(void) {
// server url will be
http://localhost:9000
// no special options
// create libwebsocket context representing this server
Websocket::context = libwebsocket_create_context(Websocket::port, Websocket::interface, Websocket::protocols, Websocket::libwebsocket_internal_extensions, Websocket::cert_path, Websocket::key_path, "", -1, -1, Websocket::opts);
if (!context) {
fprintf(stderr, "libwebsocket1 init failed\n");
return -1;
}
printf("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
int counter = 1;
while (1)
{
if(counter > 100)
{
counter = 0;
std::cout << "Listening" << std::endl;
}
libwebsocket_service(context, 50);
// 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 Websocket::sendMessage()
{
std::cout << "Send message" << std::endl;
Websocket::context = libwebsocket_create_context(Websocket::port, Websocket::interface, Websocket::protocols, Websocket::libwebsocket_internal_extensions, Websocket::cert_path, Websocket::key_path, "", -1, -1, Websocket::opts);
if (!context)
{
fprintf(stderr, "libwebsocket init failed\n");
return;
}
std::cout << "Open websocket" << std::endl;
libwebsocket* wsi = libwebsocket_client_connect(Websocket::context, "localhost", Websocket::port, -1, "/", "localhost", "localhost", "callback_dumb_increment", -1);
unsigned char* buf = (unsigned char*)"Test";
std::cout << "Sending message: " << buf << std::endl;
// send response
// just notice that we have to tell where exactly our response starts. That's
// why there's `buf[LWS_SEND_BUFFER_PRE_PADDING]` and how long it is.
// we know that our response has the same length as request because
// it's the same message in reverse order.
int rc = libwebsocket_write(wsi, buf, sizeof(buf), LWS_WRITE_TEXT);
std::cout << "Result of sending message: " << rc << std::endl;
}
I want the server to open a context on port PORT and the client to open a context on PORT as well in order to establish the link.
Is there some trick I have to pull in order make it work?
The client context always returns NULL.