How to use Libwebsocket

Hi.

I’d like to compile libwebsocket but I couldn’t compile it. I’m using C and iMX6ULL.
Please let me know how to set Eclipse.

I referred here link text. You can see the followings.

git clone https://github.com/warmcat/libwebsockets.git

sudo apt-get install libssl-dev
mkdir build
cd build
cmake ..
make
sudo make install
ldconfig

pkg-config --modversion libwebsockets

The followings are my setting values in Eclipse.

C/C++ Build > Settings > Cross GCC Compiler ==> ${CC}
                         includes ==> /usr/local/include
                         Miscellaneous ==> ${CFLAGS} -c
Cross GCC Linker ==> ${CXX}
                    Libraries ==> Libraries (-l) ==> websockets
                    Library search path (-L) /usr/local/lib
                    Miscellaneous ==> ${LDFLAGS}
Cross GCC Assembler ==> ${AS}

I compiled the following example.

#include <stdio.h>
#include <stdlib.h>
#include <libwebsockets.h>

static int callback_http(struct lws_context * this,
						 struct libwebsocket *wsi,
						 enum lws_callback_reasons reason, void *user,
						 void *in, size_t len)
{
	return 0;
}

static int callback_dumb_increment(struct lws_context * this,
								   struct libwebsocket *wsi,
								   enum lws_callback_reasons reason,
								   void *user, void *in, size_t len)
{
	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.
			lws_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;
}

static struct lws_protocols 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 main(void) {
	// server url will be http://localhost:9000
	int port = 9000;
	struct lws_context *context;
	struct lws_context_creation_info context_info =
	{
		.port = port, .iface = NULL, .protocols = protocols, .extensions = NULL,
		.ssl_cert_filepath = NULL, .ssl_private_key_filepath = NULL, .ssl_ca_filepath = NULL,
		.gid = -1, .uid = -1, .options = 0, NULL, .ka_time = 0, .ka_probes = 0, .ka_interval = 0
	};
	// create libwebsocket context representing this server
	context = lws_create_context(&context_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) {
		lws_service(context, 50);
		// lws_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)
	}

	lws_context_destroy(context);

	return 0;
}

The following is the link errror. The compiler can’t find websocket library.

Building target: test_wss
Invoking: Cross GCC Linker
arm-angstrom-linux-gnueabi-g++  -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard --sysroot=/usr/local/oecore-x86_64/sysroots/armv7at2hf-neon-angstrom-linux-gnueabi -L/usr/local/lib -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -o "test_wss"  ./test_wss.o   -lwebsockets
/usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/libexec/arm-angstrom-linux-gnueabi/gcc/arm-angstrom-linux-gnueabi/7.3.0/real-ld: warning: skipping incompatible /usr/local/lib/libwebsockets.so while searching for websockets
/usr/local/oecore-x86_64/sysroots/x86_64-angstromsdk-linux/usr/libexec/arm-angstrom-linux-gnueabi/gcc/arm-angstrom-linux-gnueabi/7.3.0/real-ld: error: cannot find -lwebsockets
../test_wss.c:60: error: undefined reference to 'lws_write'
../test_wss.c:103: error: undefined reference to 'lws_create_context'
../test_wss.c:114: error: undefined reference to 'lws_service'
collect2: error: ld returned 1 exit status
make: *** [test_wss] Error 1
makefile:29: recipe for target 'test_wss' failed

The following is my library directory. There is libwebsocket.so.

r@p:/usr/local/lib$ ll
total 1320
drwxr-xr-x  6 root root    4096 Mar  2 16:42 ./
drwxr-xr-x 12 root root    4096 Oct 18 13:40 ../
drwxr-xr-x  3 root root    4096 Mar  2 13:30 cmake/
-rw-r--r--  1 root root  799572 Mar  2 16:41 libwebsockets.a
lrwxrwxrwx  1 root root      19 Mar  2 13:30 libwebsockets.so -> libwebsockets.so.15
-rw-r--r--  1 root root  522136 Mar  2 16:42 libwebsockets.so.15
drwxr-xr-x  2 root root    4096 Mar  2 16:42 pkgconfig/
drwxrwsr-x  4 root staff   4096 Oct 10 16:23 python2.7/
drwxrwsr-x  3 root staff   4096 Feb 27  2019 python3.5/
r@p:/usr/local/lib$ 


r@p:/usr/local/include$ ll
total 52
drwxr-xr-x  3 root root  4096 Mar  2 16:42 ./
drwxr-xr-x 12 root root  4096 Oct 18 13:40 ../
drwxr-xr-x  3 root root  4096 Mar  2 16:42 libwebsockets/
-rw-r--r--  1 root root 15746 Mar  2 16:39 libwebsockets.h
-rw-r--r--  1 root root  5561 Mar  2 16:41 lws_config.h
-rw-r--r--  1 root root 14468 Mar  2 16:40 lws-plugin-ssh.h
r@p:/usr/local/include$

Dear @HansKim72

I didn’t check your settings from eclipse, but it seems like that you configured it properly and that the proper toolchain was chosen for the compilation. I assume you configured and started eclipse like this article describes?

I’m more concerned about the toolchain itself. How did you build your SDK? It seems like that your SDK doesn’t contain the libraries for libwebsockets. This means, when building your image with Yocto Project / OpenEmbedded, you need to add the support for libwebsockets. After building your image, you need to create your custom SDK with bitbake your-image-name -c populate_sdk. Please see this article about how to build your image and the SDK with OpenEmbedded.

The files in your folder /usr/local/lib/ or /usr/local/include/ are the libraries and includes from your computer and can’t be used to work on your embedded system. You could check if your SDK contains the required libraries when searching in /usr/local/oecore-x86_64/sysroots/armv7at2hf-neon-angstrom-linux-gnueabi.

Best regards
Diego

Hi. Yes. I started eclipse this article. I’m using this toolchain. I’ve compiled for custom kernel and Yockto because I had to add some ethernet driver in kernel. Now I’m not using this SDK for this issue. I only tested simple code with external library on Eclipse like hello world. Source code is only this example but this is using libwebsocekt library. If I use gcc instead of {CC}, ${CXX}, ${AS}, I can compile this example. The output is running on Ubuntu16.04 but if I execute ELF file on iMX6ULL, it doesn’t work. I think you know the reason(ARM). I want to know how to add libraries such as libwebsocket, libcurl and so one. I changed link option many times but I couldn’t compile it with ${CC}, ${CXX} options. I have to add libcurl for ftp. Please let me know detailed information to link an external library.

Dear @HansKim72

This is the behaviour which results from things I described right above. The libraries on your computer in /usr/lib/ and the toolchain with the libraries on the target are total differenet things. When you start eclipse without setting the environment and using the system gcc instead, you are using your system’s libraries.

If you want to use specific libraries in your development environment and on the target itself, you need to create your custom image with your custom toolchain. The one you linked above doesn’t contain libwebsocket. This means, you have to follow this guide, create your own image and populate the SDK. Further, in this section it is described how to add additional layers. If you are not familiar with Yocto Project / OpenEmbedded at all, there is another helpful article about a hello world OpenEmbedded example which I would recommend to go through. There you will also learn how to create your of layer.

As described here, the libwebsocket is in the meta-oe which is the core. This means, you can simply append this recipe to your image without adding additional layers. How to do this would be described here.

Best regards
Diego

Are you saying that if I want to use libwebsocket while I assume that I have not installed SDK, I have to install SDK? If I link the libcurl library, I have to install SDK. Is that right?

Yes. If you want to use those libraries, then you need to add them in your custom image and build a SDK containing these libraries.
Then you need to install the SDK and use it to cross-compile the application for your module.

Best regards,
Jaski