예제 #1
0
axl_bool __myqtt_web_socket_session_setup (MyQttCtx * ctx, MyQttConn * conn, MyQttConnOpts * options, axlPointer user_data)
{
	noPollConn  * nopoll_conn = user_data;

	if (nopoll_conn_socket (nopoll_conn) < 0) {
		myqtt_log (MYQTT_LEVEL_CRITICAL, 
			   "Failed to create MQTT over WebSocket connection to %s:%s because socket is invalid or connection is not connected (socket: %d)",
			   nopoll_conn_host (nopoll_conn), nopoll_conn_port (nopoll_conn), nopoll_conn_socket (nopoll_conn));
		return axl_false;
	} /* end if */

	myqtt_log (MYQTT_LEVEL_DEBUG, "Creating new MQTT over WebSocket connection to %s:%s (socket: %d)",
		   nopoll_conn_host (nopoll_conn), nopoll_conn_port (nopoll_conn), nopoll_conn_socket (nopoll_conn));

	/* set socket on the connection */
	conn->session = nopoll_conn_socket (nopoll_conn);

	/* associate the connection to its websocket transport */
	__myqtt_web_socket_common_association (conn, nopoll_conn);

	/* configure this connection to have no preread */
	conn->preread_handler   = NULL;
	conn->preread_user_data = NULL;

	return axl_true;
}
/* following _wt_ functions are called from a worker thread so caution is required
 * to keep its operations thread safe
 */
static int np_wt_accept (void * args) {
    int rc;
    ServerNP * si = (ServerNP *)args;

    si->np_sock = nopoll_conn_accept (si->np_ctx, si->np_listener);
    if (si->np_sock == NULL) {
        /* nopoll library does not always set errno, in this case create 
         * a fake one.
         */
        if (errno == 0) errno = EINVAL;
        return -1;
    }

    (void) nopoll_conn_set_sock_block(nopoll_conn_socket(si->np_sock), nopoll_false);
    rc = channel_np_wait_until_connection_ready(si->np_sock, 1000, si->is_ssl);
    (void) nopoll_conn_set_sock_block(nopoll_conn_socket(si->np_sock), nopoll_true);

    if (rc == 0) {
        errno = EINVAL;
        return -1;
    }
    assert (rc);
    assert(nopoll_conn_is_ready(si->np_sock));
    return (si->np_sock != NULL);
}
static ChannelServer * channel_server_create(PeerServer * ps, noPollCtx * np_ctx, noPollConn * np_listener, int is_ssl) {
    ServerNP * si = (ServerNP *)loc_alloc_zero(sizeof *si);
    /* TODO: need to investigate usage of sizeof(sockaddr_storage) for address buffer size */
    si->serv.close = server_close;
    si->sock = nopoll_conn_socket(np_listener);
    si->serv.ps = ps;
    if (server_list.next == NULL) {
        list_init(&server_list);
        post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
    }
    list_add_last(&si->serv.servlink, &channel_server_root);
    shutdown_set_normal(&channel_shutdown);
    list_add_last(&si->servlink, &server_list);
    refresh_peer_server(si->sock, ps);


    si->accreq.done = np_server_accept_done;
    si->accreq.u.user.data = si;
    si->accreq.u.user.func = np_wt_accept;
    si->accreq.client_data = si;
    si->accreq.type = AsyncReqUser;

    si->np_listener = np_listener;
    si->np_ctx = np_ctx;
    si->is_ssl = is_ssl;
    async_req_post(&si->accreq);
    return &si->serv;
}
예제 #4
0
nopoll_bool on_connection_opened (noPollCtx * ctx, noPollConn * conn, noPollPtr user_data)
{
	/* set connection close */
	nopoll_conn_set_on_close (conn, __nopoll_regression_on_close, NULL);

	if (! nopoll_conn_set_sock_block (nopoll_conn_socket (conn), nopoll_false)) {
		printf ("ERROR: failed to configure non-blocking state to connection..\n");
		return nopoll_false;
	} /* end if */

	/* check to reject */
	if (nopoll_cmp (nopoll_conn_get_origin (conn), "http://deny.aspl.es"))  {
		printf ("INFO: rejected connection from %s, with Host: %s and Origin: %s\n",
			nopoll_conn_host (conn), nopoll_conn_get_host_header (conn), nopoll_conn_get_origin (conn));
		return nopoll_false;
	} /* end if */

	/* get protocol to reply an especific case. This is an example
	   on how to detect protocols requested by the client and how
	   to reply with a particular value at the server. */
	printf ("Requested protocol: %s\n", nopoll_conn_get_requested_protocol (conn));
	if (nopoll_cmp (nopoll_conn_get_requested_protocol (conn), "hello-protocol")) {
		/* set hello-protocol-response */
		nopoll_conn_set_accepted_protocol (conn, "hello-protocol-response");
	} /* end if */

	/* notify connection accepted */
	/* printf ("INFO: connection received from %s, with Host: %s and Origin: %s\n",
	   nopoll_conn_host (conn), nopoll_conn_get_host_header (conn), nopoll_conn_get_origin (conn)); */
	return nopoll_true;
}
static int channel_np_wait_until_connection_ready(noPollConn * conn, int timeout, int is_ssl) {
        long int total_timeout = timeout;
        int socket = nopoll_conn_socket(conn);

        /* check if the connection already finished its connection
           handshake */
        do {
            int rc;
#if defined(__linux__)
            struct pollfd ufd;
            memset(&ufd, 0, sizeof ufd);
            ufd.fd = socket;
            ufd.events = POLLIN;
            rc = poll(&ufd, 1, 10 * 1000);
#else
            struct timeval tv;
            fd_set readfds;
            fd_set writefds;
            fd_set errorfds;
            FD_ZERO(&readfds);
            FD_ZERO(&writefds);
            FD_ZERO(&errorfds);
            FD_SET(socket, &readfds);

            tv.tv_usec = 10 * 1000;
            tv.tv_sec = 0;

            /* Wait for some event to occur on file descriptor */

            rc = select(socket + 1, &readfds, &writefds, &errorfds, &tv);
#endif

            if (rc == -1) break;

            /* For SSL connection, we need to call nopoll_conn_get_msg
             * in order to handle SSL accept. One may expect this is
             * done in nopoll_conn_is_ready()...
             */

            if (is_ssl) nopoll_conn_get_msg (conn);

            /* check if the connection is ok */
            if (! nopoll_conn_is_ok (conn)) 
                return nopoll_false;

            /* reduce the amount of time we have to wait. This computation
             * is not fully accurate but overall it is okay*/
            total_timeout = total_timeout - 10;
        } while (! nopoll_conn_is_ready (conn) && (total_timeout > 0));

        /* report if the connection is ok */
        return nopoll_conn_is_ready (conn);
}
예제 #6
0
/** 
 * @brief Allows to start a MQTT server on the provided local host
 * address and port running MQTT over WebSocket protocol.
 *
 * <b>Important note:</b> you must call to \ref myqtt_storage_set_path
 * to define the path first before creating any listener. This is
 * because creating a listener activates all server side code which
 * among other things includes the storage loading (client
 * subscriptions, offline publishing, etc). In the case direction,
 * once the storage path is loaded it cannot be changed after
 * restarting the particular context used in this operation (\ref
 * MyQttCtx).
 *
 * @param ctx The context where the operation takes place.
 *
 * @param listener The webSocket listener connection created on top of which MQTT over WebSocket is expected.
 *
 * @param opts Optional connection options to modify default behaviour.
 *
 * @param on_ready Optional on ready notification handler that gets
 * called when the listener is created or a failure was
 * found. Providing this handler makes this function to not block the
 * caller.
 *
 * @param user_data Optional user defined pointer that is passed into
 * the on_ready function (in the case the former is defined too).
 *
 * See \ref myqtt_listener_new for more information.
 *
 * @return A newly created connection listener reference (\ref
 * MyQttConn). Use \ref myqtt_conn_is_ok to check listener was created
 * without errors.
 */
MyQttConn       * myqtt_web_socket_listener_new         (MyQttCtx             * ctx,
							 noPollConn           * listener,
							 MyQttConnOpts        * opts,
							 MyQttListenerReady     on_ready, 
							 axlPointer             user_data)
{
	MyQttWebSocketReady * websocket_ready = NULL;
	MyQttConn           * myqtt_listener;

	if (! nopoll_conn_is_ok (listener)) {
		myqtt_log (MYQTT_LEVEL_CRITICAL, "Unable to create listener, received reference is not working");
		return NULL;
	} /* end if */

	/* create object for the function proxy but only in the user
	   on_ready function is defined */
	if (on_ready) {
		websocket_ready = axl_new (MyQttWebSocketReady, 1);
		if (websocket_ready == NULL) {
			myqtt_log (MYQTT_LEVEL_CRITICAL, "Unable to allocate memory to start the listener..");
			return NULL;
		} /* end if */
		
		websocket_ready->user_data     = user_data;
		websocket_ready->listener      = listener;
		websocket_ready->user_on_ready = on_ready;
	} /* end if */

	/* associate context */
	__myqtt_web_socket_associate_ctx (ctx, nopoll_conn_ctx (listener));

	myqtt_listener = __myqtt_listener_new_common (ctx, nopoll_conn_host (listener), 
						      __myqtt_listener_get_port (nopoll_conn_port (listener)), 
						      /* register connection and socket */
						      axl_true, nopoll_conn_socket (listener), 
						      opts, on_ready, MYQTT_IPv6, __myqtt_web_socket_accept_connection, 
						      /* configure proxy on ready */
						      __myqtt_web_socket_listener_ready, websocket_ready);

	if (myqtt_listener) {
		/* configure here reference to the noPoll listener */
		myqtt_conn_set_data_full (myqtt_listener, "__my:ws:lstnr", listener,
					  NULL, (axlDestroyFunc) __myqtt_web_socket_close_conn);

		/* configure on ready */
	} /* end if */

	return myqtt_listener;
}
static int np_wt_connect(void * args) {
    ChannelConnectInfo * info = (ChannelConnectInfo *)args;
    noPollConn * conn;
    
    if (info->is_ssl) {
        noPollConnOpts * opts = NULL;
        opts = nopoll_conn_opts_new ();
#ifdef _WRS_KERNEL
        /* For VxWorks SSL peer certificate verification does not work; let's
         * disable this for now.
         */
        nopoll_conn_opts_ssl_peer_verify (opts, nopoll_false);
#endif
	nopoll_conn_opts_set_ssl_protocol (opts, NOPOLL_METHOD_TLSV1_1);
        conn = nopoll_conn_tls_new (info->np_ctx, opts, info->host, info->port, NULL, info->get_url, info->host_name, NULL);
    } else {
        conn = nopoll_conn_new (info->np_ctx, info->host, info->port, NULL, info->get_url, NULL, NULL);
    }

    if (! nopoll_conn_is_ok (conn)) {
        nopoll_conn_close(conn);
        errno = ECONNREFUSED;
        return -1;
    }

    /* nopoll_conn_wait_until_connection_ready() can return true even if
     * the connection is not ready but simply ok; no clue why. Let's check
     * again that the connection is ready.
     */

    if (! nopoll_conn_wait_until_connection_ready (conn, 10) || ! nopoll_conn_is_ready(conn)) {
        nopoll_conn_close(conn);
        errno = EPERM;
        return -1;
    }

    assert (nopoll_conn_is_ready (conn));
    assert (nopoll_conn_is_ok (conn));

    /* Set the socket in blocking mode */
    (void) nopoll_conn_set_sock_block(nopoll_conn_socket(conn), nopoll_true);

    info->np_sock = conn;
    return 0;
}
예제 #8
0
/** 
 * @brief Allows to create a new MQTT connection to a MQTT
 * broker/server running MQTT over WebSocket.
 *
 * @param ctx The context where the operation will take place.
 *
 * @param client_identifier The client identifier that uniquely
 * identifies this MQTT client from others.  It can be NULL to let
 * MQTT 3.1.1 servers to assign a default client identifier BUT
 * clean_session must be set to axl_true. This is done automatically
 * by the library (setting clean_session to axl_true when NULL is
 * provided).
 *
 * @param clean_session Flag to clean client session or to reuse the
 * existing one. If set to axl_false, you must provide a valid
 * client_identifier (otherwise the function will fail).
 *
 * @param keep_alive Keep alive configuration in seconds after which
 * the server/broker will close the connection if it doesn't detect
 * any activity. Setting 0 will disable keep alive mechanism.
 *
 * @param conn A reference to an established noPollConn connection
 * that is connecting to the MQTT over WebSocket server we want to
 * connect to. 
 *
 * @param opts Optional connection options. See \ref myqtt_conn_opts_new
 *
 * @param on_connected Async notification handler that will be called
 * once the connection fails or it is completed. In the case this
 * handler is configured the caller will not be blocked. In the case
 * this parameter is NULL, the caller will be blocked until the
 * connection completes or fails.
 *
 * @param user_data User defined pointer that will be passed to the on_connected handler (in case it is defined).
 *
 * @return A reference to the newli created connection or NULL if
 * on_connected handler is provided. In both cases, the reference
 * returned (or received at the on_connected handler) must be checked
 * with \ref myqtt_conn_is_ok. 
 *
 * <b>About pending messages / queued messages </b>
 *
 * After successful connection with clean_session set to axl_false and
 * defined client identifier, the library will resend any queued or in
 * flight QoS1/QoS2 messages (as well as QoS0 if they were
 * stored). This is done in background without intefering the caller.
 *
 * If you need to get the number of queued messages that are going to
 * be sent use \ref myqtt_storage_queued_messages_offline. In the case
 * you need the number remaining during the process use \ref
 * myqtt_storage_queued_messages.
 *
 * See \ref myqtt_conn_new for more information.
 *
 * <b>About reconnecting</b>
 *
 * If you enable automatic reconnect support after connection close
 * (\ref myqtt_conn_opts_set_reconnect), remember to also configure
 * the recover handler by using \ref myqtt_conn_opts_set_init_session_setup_ptr. That function should
 * implement a complete reconnect and return a noPollConn reference
 * used by the internal session setup. If you don't configure this,
 * the function will disable reconnect support even if you enable it.
 *
 */
MyQttConn        * myqtt_web_socket_conn_new            (MyQttCtx        * ctx,
							 const char      * client_identifier,
							 axl_bool          clean_session,
							 int               keep_alive,
							 noPollConn      * conn,
							 MyQttConnOpts   * opts,
							 MyQttConnNew      on_connected, 
							 axlPointer        user_data)
{

	/* check if the conn reference is not defined. In that case,
	   try to craete it with the init session setup ptr */
	if (conn == NULL && opts && opts->init_session_setup_ptr)
		conn = opts->init_session_setup_ptr (ctx, NULL, opts->init_user_data, opts->init_user_data2, opts->init_user_data3);

	/* report what we are doing */
	myqtt_log (MYQTT_LEVEL_DEBUG, "Creating new MQTT over WebSocket connection to %s:%s (is ready:%d, socket: %d)",
		   nopoll_conn_host (conn), nopoll_conn_port (conn), nopoll_conn_is_ready (conn), nopoll_conn_socket (conn));

	/* check and disable reconnect if it is not configured the
	   recover handler */
	if (opts && opts->reconnect) {
		if (opts->init_session_setup_ptr == NULL) {
			myqtt_log (MYQTT_LEVEL_CRITICAL, "Disable reconnect flag because user didn't provide a recover handler (myqtt_conn_opts_set_recover_session_setup_ptr)");
			opts->reconnect = axl_false; /* disable it */
		} /* end if */
	} /* end opts */

	/* associate context */
	__myqtt_web_socket_associate_ctx (ctx, nopoll_conn_ctx (conn));

	/* call to create the connection */
	return myqtt_conn_new_full_common (ctx, client_identifier, clean_session, keep_alive, 
					   /* destination host and port but only as a matter of reporting 
					      because we are handling everything through the setup handler */
					   nopoll_conn_host (conn), nopoll_conn_port (conn), 
					   /* this is the handler that will establish the connection on top
					      of the provided noPoll connection */
					   __myqtt_web_socket_session_setup, conn, 
					   /* additional user handlers */
					   on_connected, -1, opts, user_data);
}
static void np_server_accept_done(void * x) {
    AsyncReqInfo * req = (AsyncReqInfo *)x;
    ServerNP * si = (ServerNP *)req->client_data;
    if (si->sock < 0) {
        /* Server closed. */
        loc_free(si);
        return;
    }
    if (req->error) {
        trace(LOG_ALWAYS, "Socket accept failed: %s", errno_to_str(req->error));
    }
    else {
        ChannelNP * c = create_channel(si->np_sock, si->is_ssl, 1);
        if (c == NULL) {
            trace(LOG_ALWAYS, "Cannot create channel for accepted connection: %s", errno_to_str(errno));
            closesocket(req->u.acc.rval);
        }
        else {
            struct sockaddr * addr_buf; /* Socket remote address */
            socklen_t addr_len;
#if defined(SOCK_MAXADDRLEN)
            addr_len = SOCK_MAXADDRLEN;
#else
            addr_len = 0x1000;
#endif
            addr_buf = (struct sockaddr *)loc_alloc(addr_len);
            if (getpeername(nopoll_conn_socket (si->np_sock), addr_buf, &addr_len) < 0) {
                trace(LOG_ALWAYS, "Unable to get peer remote name: %s", errno_to_str(errno));
                closesocket(req->u.acc.rval);
            }
            else {
                set_peer_addr(c, addr_buf, addr_len);
                si->serv.new_conn(&si->serv, &c->chan);
            }
            loc_free(addr_buf);
        }
    }
    async_req_post(req);
}
static ChannelNP * create_channel(noPollConn * np_sock, int en_ssl, int server) {
    const int i = 1;
    ChannelNP * c;
    int sock = nopoll_conn_socket(np_sock);

    assert(np_sock >= 0);
    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)) < 0) {
        int error = errno;
        trace(LOG_ALWAYS, "Can't set TCP_NODELAY option on a socket: %s", errno_to_str(error));
        errno = error;
        return NULL;
    }
    if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof(i)) < 0) {
        int error = errno;
        trace(LOG_ALWAYS, "Can't set SO_KEEPALIVE option on a socket: %s", errno_to_str(error));
        errno = error;
        return NULL;
    }

    c = (ChannelNP *)loc_alloc_zero(sizeof *c);
#if ENABLE_Splice
    if (pipe(c->pipefd) == -1) {
        int err = errno;
        loc_free(c);
        trace(LOG_ALWAYS, "Cannot create channel pipe : %s", errno_to_str(err));
        errno = err;
        return NULL;
    }
#endif /* ENABLE_Splice */
    c->magic = CHANNEL_MAGIC;
    c->is_ssl = en_ssl;
    c->chan.inp.read = np_read_stream;
    c->chan.inp.peek = np_peek_stream;
    c->obuf = output_queue_alloc_obuf();
    c->chan.out.cur = c->obuf->buf;
    c->chan.out.end = c->obuf->buf + sizeof(c->obuf->buf);
    c->chan.out.write = np_write_stream;
    c->chan.out.write_block = np_write_block_stream;
    c->chan.out.splice_block = np_splice_block_stream;
    list_add_last(&c->chan.chanlink, &channel_root);
    shutdown_set_normal(&channel_shutdown);
    c->chan.state = ChannelStateStartWait;
    c->chan.incoming = server;
    c->chan.start_comm = start_channel;
    c->chan.check_pending = channel_check_pending;
    c->chan.message_count = channel_get_message_count;
    c->chan.lock = np_lock;
    c->chan.unlock = np_unlock;
    c->chan.is_closed = np_is_closed;
    c->chan.close = send_eof_and_close;
    ibuf_init(&c->ibuf, &c->chan.inp);
    c->ibuf.post_read = np_post_read;
    c->ibuf.wait_read = np_wait_read;
    c->ibuf.trigger_message = np_trigger_message;
    c->socket = nopoll_conn_socket(np_sock);
    c->np_socket = np_sock;
    c->lock_cnt = 1;
    c->rd_req.done = np_channel_read_done;
    c->rd_req.client_data = c;
    c->rd_req.type = AsyncReqSelect;
#if ENABLE_OutputQueue
    output_queue_ini(&c->out_queue);
#endif
    return c;
}
예제 #11
0
void*          webSocketery()
{
  noPollCtx			*ctx = nopoll_ctx_new();
  noPollMsg			*msg;
  noPollRole			*role = nopoll_conn_role(NOPOLL_ROLE_UNKNOWN);
  struct noPollHandshake	*fetch;
  noPollConnOpts		*opts;

  /* Comment the log lines to disable loging Debug Warnings and Critical errors (Better not)*/
  //nopoll_log_color_enable(ctx, true);
  //nopoll_log_enable(ctx, nopoll_true);
  /* Initializing the cookie options */
  opts = nopoll_conn_opts_new();

  if (!ctx)
    puts("error ctx is nill");
 
  //To add Cookies use this method below
  /* nopoll_conn_opts_set_cookie(opts, "BAYEUX_BROWSER=56a9-mchhnynonz6ji8a6hs1sh49; JSESSIONID=8gz8e00htqrl15vcm3o9yi95f"); */

  // Websocketery Works for mtgox and others servers but not for m.zpush.ovh it keeps rejecting me for an unknown f*****g 400 error ! Use Methods below to connect to server, a working example is provided
  //nopoll_conn_new(ctx, ip, port, host, get, protocols, origin)    nopoll_conn_new_opts(ctx, opts, ip, port, host, get, protocols, origin)// 
  

  //noPollConn *conn = nopoll_conn_new(ctx , "54.171.156.38" ,"80" ,"m.zpush.ovh:8080" ,"ws://m.zpush.ovh:8080/str/strd" ,NULL, "Authorize");
  noPollConn *conn = nopoll_conn_new(ctx, "54.238.149.121", "80", "websocket.mtgox.com", "/mtgox", NULL, "chat");
  
  if (!nopoll_conn_wait_until_connection_ready(conn, 50) )
    { puts("nopoll_conn failed, timeout"); return (0);}
  if (nopoll_conn_send_text (conn, "hello how are you doing, do we connect ?", 40) != 40)
    {puts("send text just failed...."); return(0);}
  else
    {
      while (! nopoll_conn_is_ready (conn)) {

	if (! nopoll_conn_is_ok (conn)) {
	  printf ("ERROR (4.1 jkd412): expected to find proper connection handshake finished, but found connection is broken: session=%d, errno=%d : %s..\n",
		  (int) nopoll_conn_socket (conn), errno, strerror (errno));
	  return nopoll_false;
	} /* end if */

	/* wait a bit 10ms */
	nopoll_sleep (10000);
      } /* end if */
      nopoll_conn_close (conn);

      /* finish */
      nopoll_ctx_unref (ctx);

      puts("nopoll conn sucess");
      while (nopoll_true)
	{
	  if (nopoll_conn_is_ready(conn))
	    {
	      puts("break");
	      break;
	    }
	  nopoll_sleep(10000);
	}
	  msg = nopoll_conn_get_msg(conn);
	  if (msg)
	    printf("Msg received = %s\n", nopoll_msg_get_payload(msg));
	    
	  if (!nopoll_conn_is_ok(conn))
	    {
	      puts("------------ Connection Dead ----------------");
	      return nopoll_false;
	    }
	
    }
    nopoll_ctx_unref(ctx);
    return (0);
}
예제 #12
0
void listener_on_message (noPollCtx * ctx, noPollConn * conn, noPollMsg * msg, noPollPtr user_data)
{
	const char * content = (const char *) nopoll_msg_get_payload (msg);
	FILE       * file = NULL;
	char         buffer[1024];
	int          bytes;
	int          sent;
	char         example[100];
	int          shown;
	noPollMsg  * aux;
	nopoll_bool  dont_reply = nopoll_false;
	FILE       * open_file_cmd = NULL;
	int          iterator;
	char       * ref;

	/* check for open file commands */
	if (nopoll_ncmp (content, "open-file: ", 11)) {
#if defined(NOPOLL_OS_WIN32)
		open_file_cmd = fopen (content + 11, "ab");
#else
		open_file_cmd = fopen (content + 11, "a");
#endif
		if (open_file_cmd == NULL) {
			printf ("ERROR: unable to open file: %s\n", content + 11);
			return;
		} /* end if */

		/* set handler */
		nopoll_conn_set_on_msg (conn, write_file_handler, open_file_cmd);

		return;
	} /* end if */

	/* printf ("Message received: %s\n", content); */
	if (nopoll_ncmp (content, "close with message", 18)) {
		printf ("Listener: RELEASING connection (closing it) with reason..\n");
		nopoll_conn_close_ext (conn, 1048, "Hey, this is a very reasonable error message", 44);
		return;
	} /* end if */

	if (nopoll_ncmp (content, "release-message", 15)) {
		printf ("Listener: RELEASING previous message..\n");
		nopoll_msg_unref (previous_msg);
		previous_msg = NULL;
		return;
	} /* end if */
	if (nopoll_ncmp (content, "get-cookie", 10)) {
		printf ("Listener: reporting cookie: %s\n", nopoll_conn_get_cookie (conn));
		nopoll_conn_send_text (conn, nopoll_conn_get_cookie (conn), strlen (nopoll_conn_get_cookie (conn)));
		return;
	}

	/* printf ("Checking for set-broken socket: %s\n", content); */
	if (nopoll_ncmp (content, "set-broken-socket", 17)) {
		printf ("Listener: setting broken socket on conn: %p (socket=%d)\n",
			conn, (int) nopoll_conn_socket (conn));
		nopoll_conn_shutdown (conn);
		return;
	} /* end if */

	if (nopoll_ncmp (content, "get-connection-close-count", 26)) {
		printf ("Sending reply to report connection close...\n");
		ref = nopoll_strdup_printf ("%d", connection_close_count);
		nopoll_conn_send_text (conn, ref, strlen (ref));
		nopoll_free (ref);
		return;
	} /* end if */

	if (nopoll_ncmp (content, "1234-1) ", 8)) {
		printf ("Listener: waiting a second to force buffer flooding..\n");
		nopoll_sleep (100000);
		dont_reply = nopoll_true;
	} /* end if */

	/* get initial bytes */
	bytes = nopoll_msg_get_payload_size (msg);
	shown = bytes > 100 ? 99 : bytes;

	memset (example, 0, 100);
	/*	if (! nopoll_msg_is_fragment (msg)) */
		memcpy (example, (const char *) nopoll_msg_get_payload (msg), shown);

	printf ("Listener received (size: %d, ctx refs: %d): (first %d bytes, fragment: %d) '%s'\n", 
		nopoll_msg_get_payload_size (msg),
		nopoll_ctx_ref_count (ctx), shown, nopoll_msg_is_fragment (msg), example);

	if (nopoll_cmp (content, "ping")) {
		/* send a ping */
		nopoll_conn_send_ping (conn);
		return;
	} else if (nopoll_cmp (content, "get-file")) {
		iterator = 0;
		file     = NULL;
		while (nopoll_true) {
#if defined(NOPOLL_OS_WIN32)
			file = fopen ("nopoll-regression-client.c", "rb");
#else
			file = fopen ("nopoll-regression-client.c", "r");
#endif		
			printf ("LISTENER: file pointer (%p, errno=%d : %s)..\n", file, errno, strerror (errno));
			
			if (file)
				break;
			iterator++;
			if (iterator > 3) {
				printf ("ERROR: failed to open nopoll-regression-client.c (fopen call failed)\n");
				nopoll_conn_shutdown (conn);
				return;
			} /* end if */
		} /* end while */

		while (! feof (file)) {
			/* read content */
			bytes = fread (buffer, 1, 1024, file);
			/* send content */
			if (bytes > 0) {
				/* send content and get the result */
				/* printf ("Sending message with %d bytes..\n", bytes); */
				/* nopoll_log_enable (ctx, nopoll_true); */
				
				while (nopoll_true) {
					/* try to send content */
					sent = nopoll_conn_send_text (conn, buffer, bytes);
					/* nopoll_log_enable (ctx, nopoll_false); */
					if (sent != bytes) {
						if (errno == NOPOLL_EWOULDBLOCK) {
							nopoll_sleep (1000);
							/* printf ("   ..retrying..sending message with %d bytes..\n", bytes); */
							continue;
						} /* end if */
						printf ("ERROR: expected to send %d bytes but sent different content size (%d bytes), errno=%d (%d)..\n", 
							bytes, sent, errno, NOPOLL_EWOULDBLOCK);
					} /* end if */
					break;
				}
			} /* end if */
			/* next */
		} /* end while */

		/* now close the handle */
		fclose (file);
		return;
	} /* end if */

	/* check if we have to reply */
	if (dont_reply)
		return;

	if (nopoll_msg_is_fragment (msg)) {
		printf ("Found fragment, FIN = %d (%p)?..\n", nopoll_msg_is_final (msg), msg);
		/* call to join this message */
		aux          = previous_msg;
		previous_msg = nopoll_msg_join (previous_msg, msg);
		nopoll_msg_unref (aux);
		if (! nopoll_msg_is_final (msg)) {
			printf ("Found fragment that is not final..\n");
			printf ("Not replying because frame fragment received..\n");
			return;
		} /* end if */

		printf ("Found final fragment, replying with complete content: %s (refs: %d)..\n",
			(const char *) nopoll_msg_get_payload (previous_msg), 
			nopoll_msg_ref_count (previous_msg));

		/* ok, now found final piece, replying */
		nopoll_conn_send_text (conn, (const char *) nopoll_msg_get_payload (previous_msg), 
				       nopoll_msg_get_payload_size (previous_msg));
		/* release reference */
		nopoll_msg_unref (previous_msg);
		previous_msg = NULL;

		return;
	}

	/* send reply as received */
	printf ("Sending reply... (same message size: %d)\n", nopoll_msg_get_payload_size (msg));
	nopoll_conn_send_text (conn, (const char *) nopoll_msg_get_payload (msg), 
			       nopoll_msg_get_payload_size (msg));
	return;
}