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; }
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); }
/** * @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; }
/** * @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; }
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); }
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; }