Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
gwsocket(1)			 User Manuals			   gwsocket(1)

NAME
       gwsocket	 is  a standalone, simple, yet powerful	rfc6455	compliant Web-
       Socket Server.

SYNOPSIS
       gwsocket	-p [--addr][--origin][gwsocket options ...]

DESCRIPTION
       gwsocket	is a free (MIT Licensed),  standalone,	WebSocket  Server.  It
       sits  between  your  application	 and  the client's browser, giving the
       ability for bidirectional communication between these two with ease and
       flexibility.

Start the Server
       You  can	 run gwsocket without passing any options to the command line.
       By default, it will listen on port 7890 on all  the  interfaces,	 e.g.,
       127.0.0.1, ::1, etc. For	instance:

       #  gwsocket  --access-log=/tmp/access.log Note: See a basic client-side
       example at the bottom of	the man	page.

OPTIONS
       -p --port
	      Specifies	the port to bind.

       -h --help
	      Command line help.

       -V --version
	      Display version information and exit.

       --access-log=<path/file>
	      Specifies	the path/file for the access log.

       --addr=<addr>
	      Specifies	the address to bind.

       --echo-mode
	      Set the server to	echo all received messages.

       --max-frame-size=<bytes>
	      Maximum size of a	websocket frame. This includes received	frames
	      from the client and messages through the named pipe.

       --origin=<origin>
	      Ensure  clients  send  the specified origin header upon the Web-
	      Socket handshake.

       --pipein=<path/file>
	      Creates a	named  pipe  (FIFO)  that  reads  from	on  the	 given
	      path/file.

       --pipeout=<path/file>
	      Creates a	named pipe (FIFO) that writes to the given path/file.

       --strict
	      Parse messages using strict mode.	See below for more details.

       --ssl-cert=<cert.crt>
	      Path to TLS/SSL certificate.

       --ssl-key=<priv.key>
	      Path to TLS/SSL private key.

CONFIGURATION
       --enable-debug
	      Compile  with  debugging symbols and turn	off compiler optimiza-
	      tions.

       --with-openssl
	      Compile gwsocket with OpenSSL support for	its WebSocket server.

DATA MODES
       In order	to establish  a	 channel  between  your	 application  and  the
       client's	 browser, gwsocket provides two	methods	that allow the user to
       send data in and	out. The first one is through the use of the  standard
       input  (stdin)  ,and  the standard output (stdout) followed by the pay-
       load. See options below for more	details.

   1. stdin/stdout
       The standard input/output is the	simplest way of	sending/receiving data
       to/from a client. However, it's limited to broadcasting messages	to all
       clients.	To send	messages to or receive from a specific client, use the
       strict mode in section 2.

   1.1 Sending Data to all Clients _a stdout
       If you need to broadcast	data from your application to all clients con-
       nected to gwsocket, then, the simplest way of doing  it	is  by	piping
       your application	output into a named pipe (also known as	FIFO) that gw-
       socket makes use	of. Once gwsocket receives the payload,	then  it  will
       automatically broadcast the message to all connected clients.

       1.1. Examples

	 #include <fcntl.h>
	 #include <sys/stat.h>
	 #include <sys/types.h>
	 #include <unistd.h>

	 int main() {
	     int fd;
	     char *myfifo = "/tmp/wspipein.fifo";
	     const char	*msg = "Message	to broadcast";

	     fd	= open(myfifo, O_WRONLY);
	     write(fd, msg, strlen(msg));
	     close(fd);

	     return 0;
	 }

       Note:  You  can	send  as many bytes PIPE_BUF can hold. If a message is
       greater than PIPE_BUF, it would send the	rest on	a  second  message  or
       third, and so on. See strict mode below for more	control	over messages.

   1.2 Receiving Data from Clients _a stdin
       When  a client sends a message to the server, it	is possible to capture
       that message in your application. To do this, your  application	simply
       needs  to  read	from a named pipe. By default, gwsocket	creates	a FIFO
       under /tmp/wspipeout.fifo.

       1.2. Examples

       Receiving data can be as	simple as doing	a # cat	/tmp/wspipeout.fifo or
       you can do it in	the language of	your choice. See examples below.

	 #include <stdio.h>
	 #include <stdlib.h>
	 #include <fcntl.h>
	 #include <limits.h>

	 static	void read_message (int fd, fd_set set) {
	   int bytes = 0;
	   char	buf[PIPE_BUF] =	{ 0 };

	   FD_ZERO (&set);
	   FD_SET (fd, &set);

	   if ((select (fd + 1,	&set, NULL, NULL, NULL)) < 1)
	     exit (1);
	   if (!FD_ISSET (fd, &set))
	     return;

	   if (read (fd, buf, PIPE_BUF)	> 0)
	     printf ("%s0, buf);
	 }

	 int main (void) {
	   fd_set set;
	   char	*fifo =	"/tmp/wspipeout.fifo";
	   int fd = 0;

	   if ((fd = open (fifo, O_RDWR	| O_NONBLOCK)) < 0)
	     exit (1);
	   while (1)
	     read_message(fd, set);

	   return 0;
	 }

       Note:  Make  sure the reader in your application	is set as non-blocking
       to get a	constant feed.

       Tip If you need to know which client sent the message, for example,  in
       a chat application, please see the strict mode below.

   2. Strict Mode
       gwsocket	 implements  its own tiny protocol for sending/receiving data.
       In contrast to the stdin/stdout mode, the strict	 mode  allows  you  to
       send/receive data to/from specific connected clients as well as to keep
       track of	who opened/closed a WebSocket connection. It  also  gives  you
       the ability to pack and send as much data as you	would like on a	single
       message.

       2. Data Format

       The  message  header  is	 a  fixed-size	header.	 The  first  12	 bytes
       (uint32_t) are packed in	network	byte order and contain the "meta-data"
       of the message we are sending/receiving.	The rest of it is  the	actual
       message.

	 0	      1		      2		       3
	 +---------------------------------------------+
	 |	  Client Socket	Id (listener)	       |
	 +---------------------------------------------+
	 |    Message Type (binary: 0x2	/ text:	0x1)   |
	 +---------------------------------------------+
	 |	       Payload length		       |
	 +---------------------------------------------+
	 |		Payload	Data		       |
	 +---------------------------------------------+

   2.1 Sending Data _a Strict Mode
       If  you need to send a message to a specific client, then you can do so
       by specifying the client	id in the message header. If  set  to  0,  the
       message	will  be broadcasted to	all clients. The first 4 bytes are re-
       served for the client id	or listener. The following  4  bytes  are  re-
       served  for  the	 message type. 0x01 for	a text message,	and 0x02 for a
       binary message. And the last 4 bytes are	 reserved  for	the  payload's
       length.

       Once  the  header  has  been written to the pipe, you may now write the
       message.

       2.1. Examples

       First, start the	server in strict-mode.

       # gwsocket --strict-mode
	 #include <stdio.h>
	 #include <stdlib.h>
	 #include <string.h>
	 #include <fcntl.h>

	 size_t	pack_uint32(void* buf, uint32_t	val) {
	   uint32_t v32	= htonl(val);
	   memcpy(buf, &v32, sizeof(uint32_t));
	   return sizeof(uint32_t);
	 }

	 int main() {
	   char	*p = calloc (sizeof(uint32_t) *	3, sizeof(char)), *ptr;
	   const char *msg = "Message to broadcast";
	   const char *fifo = "/tmp/wspipein.fifo";
	   int fd;

	   ptr = p;
	   ptr += pack_uint32(ptr, 0);
	   ptr += pack_uint32(ptr, 0x01);
	   ptr += pack_uint32(ptr, strlen(msg));

	   fd =	open(fifo, O_WRONLY);
	   write(fd, p,	sizeof(uint32_t) * 3);
	   write(fd, msg, strlen(msg));
	   close(fd);
	   free	(p);

	   return 0;
	 }

   2.2 Receiving Data from Clients _a Strict Mode
       Now, to get a message from a specific client and	route  it  to  another
       client, you just	need to	do the opposite	of sending data. First you un-
       pack the	header from network byte order to host	byte  order  and  then
       read the	payload.

       2.2. Examples

       First, start the	server in strict-mode.

       # gwsocket --strict-mode
	 #include <stdio.h>
	 #include <stdlib.h>
	 #include <fcntl.h>
	 #include <limits.h>
	 #include <int.h>

	 static	size_t unpack_uint32 (const void *b, uint32_t *	val) {
	   uint32_t v32	= 0;
	   memcpy (&v32, b, sizeof (uint32_t));
	   *val	= ntohl	(v32);
	   return sizeof (uint32_t);
	 }

	 static	void read_message (int fd, fd_set set) {
	   int bytes = 0;
	   uint32_t size = 0, listener = 0, type = 0;
	   char	hdr[PIPE_BUF] =	{ 0 }, buf[PIPE_BUF] = {0};
	   char	*ptr = NULL;

	   FD_ZERO (&set);
	   FD_SET (fd, &set);

	   if ((select (fd + 1,	&set, NULL, NULL, NULL)) < 1)
	     exit (1);
	   if (!FD_ISSET (fd, &set))
	     return;

	   if (hdr[0] == ' ') {
	     if	(read (fd, hdr,	sizeof (uint32_t) * 3) < 1)
	       return;
	   }

	   ptr = hdr;
	   ptr += unpack_uint32(ptr, &listener);
	   ptr += unpack_uint32(ptr, &type);
	   ptr += unpack_uint32(ptr, &size);

	   if (read (fd, buf, size) < 1)
	     return;

	   printf ("client: %d,	msg: %s0, listener, buf);
	 }

	 int main (void) {
	   fd_set set;
	   char	*fifo =	"/tmp/wspipeout.fifo";
	   int fd = 0;

	   if ((fd = open (fifo, O_RDWR	| O_NONBLOCK)) < 0)
	     exit (1);
	   while (1)
	     read_message(fd, set);

	   return 0;
	 }

       Note:  If  you read/write to a stream, be aware that they do not	neces-
       sarily read/write the full amount of data you have requested. Your  ap-
       plication will need to handle the case where only a single byte is read
       or written. Examples above do not handle	this.

OBLIGATORY CLIENT EXAMPLE
       Here's the basic	example, client	 and  server  side.  First  start  the
       server and set it in echo mode.

       # gwsocket --echo-mode

       Now, let's create the client side.

	 <!DOCTYPE html>
	 <html lang="en">
	 <style>
	 pre {
	     background: #EEE;
	     border: 1px solid #CCC;
	     padding: 10px;
	 }
	 #page-wrapper {
	     border-top: 5px solid #69c773;
	     margin: 1em auto;
	     width: 950px;
	 }
	 </style>
	 <script>
	 window.onload = function() {
	     function $(selector) {
		 return	document.querySelector(selector);
	     }
	     var socket	= new WebSocket('ws://localhost:7890');
	     socket.onopen = function(event) {
		 $('#messages').innerHTML = 'Connected<br>';
	     };
	     socket.onmessage =	function(event)	{
		 $('#messages').innerHTML  +=  'Received:<br>'	+ event.data +
       '<br>';
	     };
	     socket.onclose = function(event) {
		 $('#messages').innerHTML = 'Disconnected ' + event.reason;
	     };
	     $('#submit').onclick = function(e)	{
		 socket.send($('input').value);
		 $('#messages').innerHTML += 'Sent:<br>' + $('input').value  +
       '<br>';
		 $('input').value = '';
	     };
	 };
	 </script>

	 <div id="page-wrapper">
	     <pre id="messages">Connecting...</pre>
	     <input id="message" required>
	     <button id="submit">Send Message</button>
	 </div>

BUGS
       If  you	think  you  have found a bug, please send me an	email to hello
       [@at] goaccess.io.

AUTHOR
       Gerardo Orellana. For more details about	it, or	new  releases,	please
       visit http://gwsocket.io

Linux				  AUGUST 2018			   gwsocket(1)

NAME | SYNOPSIS | DESCRIPTION | Start the Server | OPTIONS | CONFIGURATION | DATA MODES | OBLIGATORY CLIENT EXAMPLE | BUGS | AUTHOR

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=gwsocket&sektion=1&manpath=FreeBSD+12.1-RELEASE+and+Ports>

home | help