I'm trying to use the Gnome glib/gio C library to create a client program to connect to a server via IPv6. My server box has a link local IPv6 address:
inet6 addr: fe80::2d0:c9ff:feda:99e0/64 Scope:Link
So, I to access it, I have to tell the client software which interface to use (eth0 in this case). So the following works (using port 1500):
nc -6 fe80::2d0:c9ff:feda:99e0%eth0 1500
In glib, using the %eth0 notation violates the URI notation:
(process:31159): GLib-GIO-WARNING **: Invalid URI 'none://[fe80:0:0:0:2d0:c9ff:feda:99e0%eth0]:1500'
I've looked in the code and it clearly expects to see the percent escape notation (i.e. the characters '%25') but I can't seem to get the format correct:
** (process:5741): ERROR **: Invalid URI 'none://[fe80:0:0:0:2d0:c9ff:feda:99e0%25eth0]1500'
So, anyone know how to specify the interface?
EDIT: Here's the code
// gchar test[255] = "fe80:0:0:0:2d0:c9ff:feda:99e0%eth0";
// gchar test[255] = "fe80:0:0:0:2d0:c9ff:feda:99e0\%eth0";
// gchar test[255] = "fe80:0:0:0:2d0:c9ff:feda:99e0\x25eth0";
// gchar test[255] = "fe80:0:0:0:2d0:c9ff:feda:99e0\%%25eth0";
gchar test[255] = "[fe80:0:0:0:2d0:c9ff:feda:99e0\%%eth0]";
connection = g_socket_client_connect_to_uri (client,
test,
1500,
NULL,
&error);
EDIT 2: Complete code (with MichaelHampton's input):
#include <glib.h>
#include <gio/gio.h>
int
main (int argc, char *argv[])
{
/* initialize glib */
g_type_init ();
GError * error = NULL;
/* create a new connection */
GSocketConnection * connection = NULL;
GSocketClient * client = g_socket_client_new();
connection = g_socket_client_connect_to_host (client,
(gchar*)"fe80::5054:ff:fe1f:6b6c\%br0",
1500, /* your port goes here */
NULL,
&error);
/* don't forget to check for errors */
if (error != NULL)
{
g_error (error->message);
}
else
{
g_print ("Connection successful!\n");
}
return 0;
}
Ah, you're calling the wrong function. You should be using g_socket_client_connect_to_host to connect directly to a host and port.
Here is a working example:
connection = g_socket_client_connect_to_host (client,
(gchar*)"fe80::5054:ff:fe1f:6b6c\%br0",
1500, /* your port goes here */
NULL,
&error);
The complete example code, which it looked like you were using, was in the related question: GIO socket-server / -client example
Related
Trying to connect from a C application running as an IBM MQ client on a host to an MQ server running as a docker container.
The client code taken from an IBM example is provided below.
The questions is which protocol is used when MQCONN is called as no IP/port is provided? I can only guess it is some kind of an IPC.
For this reason I'm running the docker container with --ipc="host" option, but it still fails with CompCode=2, Reason=2058
#include <cmqc.h>
⋮
static char Parm1[MQ_Q_MGR_NAME_LENGTH] ;
⋮
int main(int argc, char *argv[] )
{
/* */
/* Variables for MQ calls */
/* */
MQHCONN Hconn; /* Connection handle */
MQLONG CompCode; /* Completion code */
MQLONG Reason; /* Qualifying reason */
⋮
/* Copy the queue manager name, passed in the */
/* parm field, to Parm1 */
strncpy(Parm1,argv[1],MQ_Q_MGR_NAME_LENGTH);
⋮
/* */
/* Connect to the specified queue manager. */
/* Test the output of the connect call. If the */
/* call fails, print an error message showing the */
/* completion code and reason code, then leave the */
/* program. */
/* */
MQCONN(Parm1,
&Hconn,
&CompCode,
&Reason);
if ((CompCode != MQCC_OK) | (Reason != MQRC_NONE))
{
sprintf(pBuff, MESSAGE_4_E,
ERROR_IN_MQCONN, CompCode, Reason);
PrintLine(pBuff);
RetCode = CSQ4_ERROR;
goto AbnormalExit2;
}
⋮
}
If your program will be running on the same server as the queue manager then it is best to link it with 'mqm.lib' (bindings mode) rather than 'mqic.lib' (client mode).
In the MQ KnowLedge Center, there are examples on how to compile and link your C program. The examples are listed as: 'C client application' (client mode) and 'C server application' (bindings mode).
If in the future, your C program needs to connect to a remote queue manager then you need to link it for 'client mode'.
To configure your C program to handle proper MQ security, change the MQCONN API call to MQCONNX API call.
i.e.
MQCNO cno = {MQCNO_DEFAULT};
MQCD cd = {MQCD_CLIENT_CONN_DEFAULT};
MQCSP csp = {MQCSP_DEFAULT};
strncpy(cd.ConnectionName, hostname, MQ_CONN_NAME_LENGTH);
strncpy(cd.ChannelName, channelName, MQ_CHANNEL_NAME_LENGTH);
csp.AuthenticationType = MQCSP_AUTH_USER_ID_AND_PWD;
csp.CSPUserIdPtr = &myUserId;
csp.CSPUserIdOffset = 0;
csp.CSPUserIdLength = strlen(myUserId);
csp.CSPPasswordPtr = &myPassword;
csp.CSPPasswordOffset = 0;
csp.CSPPasswordLength = strlen(myPassword);
cno.cdPtr = &cd;
cno.Version = MQCNO_CURRENT_VERSION;
cno.SecurityParmsPtr = &csp;
cno.SecurityParmsOffset = 0;
MQCONNX(QMgrName, &cno, &Hcon, &CompCode, &Reason);
A few years ago, I wrote a blog posting called: MQ API Verbs that IBM Forgot!!. I created wraps for MQCONN and MQCONNX that will allow the program to pass UserId & Password for MQCONN and MQCONNX API calls. You may find it easier to simply use the wrappers.
EDIT: I tested with a static IP on both the board and my computer with a python SSL server and it works as expected, leading me to believe that the DHCP is the problem. If anyone has a lead on what may be occuring it would be greatly appreciated.
I am using the mbedTLS library on a STM32F746-NUCLEO board and I want to use it as both a SSL client and server. The server works well, so i tried to use the client example code (as is, in a separate project).
The following mbedtls_net_connect call returns -68 (MBEDTLS_ERR_NET_CONNECT_FAILED). Digging deeper reveals that it is due to a routing error (line 900 in tcp.c from LwIP), because local_ip is set to 0. The board is in DHCP mode on a home router which is connected to the internet. The destination server is up and running and the SERVER_NAME is the IP address in plain text.
mbedtls_entropy_context client_entropy;
static mbedtls_net_context server_fd;
mbedtls_x509_crt cacert;
static uint32_t flags;
static uint8_t vrfy_buf[512];
static const uint8_t* client_pers = "ssl_client";
mbedtls_ssl_config client_config;
mbedtls_ctr_drbg_context client_ctr_drbg;
mbedtls_ssl_context client_ssl;
static uint8_t client_buf[1024];
void SSL_Server(void const *argument) {
int ret, len;
UNUSED(argument);
mbedtls_net_init(&server_fd);
mbedtls_ssl_init(&client_ssl);
mbedtls_ssl_config_init(&client_config);
mbedtls_x509_crt_init(&cacert);
mbedtls_ctr_drbg_init(&client_ctr_drbg);
// Seeding the random number generator
mbedtls_entropy_init( &client_entropy );
len = strlen((char *) client_pers);
if((ret = mbedtls_ctr_drbg_seed(&client_ctr_drbg, mbedtls_entropy_func,
&client_entropy, (const unsigned char *) client_pers, len)) != 0)
{
goto exit;
}
// 1. Initialize certificates
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len );
if( ret < 0 )
{
goto exit;
}
if((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, SERVER_PORT,
MBEDTLS_NET_PROTO_TCP)) != 0)
{
mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
goto exit;
}
}
Here the SSL_Server function is a FreeRTOS thread called in the main(). I can also confirm that the network interface has been assigned an IP address when the error occurs.
I expect the connection call to return 0 and connect to the server to initiate the SSL handshake.
You need to set the default netif route for LWIP to be able to route the remote address.
Simply add netif_set_default(&netif); after dhcp_start() inside the function mbedtls_net_init().
void mbedtls_net_init( mbedtls_net_context *ctx ) {
...
/* add the network interface */
netif_add(&netif, &addr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);
/* register the default network interface */
netif_set_up(&netif);
#ifdef USE_DHCP
netif.ip_addr.addr = 0;
dhcp_start(&netif);
#endif
netif_set_default(&netif); // <-- Here
osDelay(500);
start = HAL_GetTick();
while((netif.ip_addr.addr == 0) && (HAL_GetTick() - start < 10000))
{
}
if (netif.ip_addr.addr == 0) {
printf(" Failed to get ip address! Please check your network configuration.\n");
Error_Handler();
}
...
The documentation for MbedTLS can be kinda tricky, hope this helps.
On the Eclipse Paho MQTT website, the developers provide a client example (http://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/pubsync.html) that does the following:
Create a client object with the specified parameters
Connect the client with the specified connection options
Publish a MQTT message
Disconnect the client
Destroy the client object
This works well if all you want is to publish one single message.
In my code, I have a function that contains pretty much the same code as in the aforementioned example, however, the function is called repeatedly from main() as I need to publish a large number of messages one after another. The problem is, if I use the code exactly as in the example, every time my function is called a new connection is created and shortly after destroyed. This happens again and again and again as long as the function is called repeatedly, causing a huge overhead.
Is there a way to check whether a client object has already been created, and if so, don't do it again but use the existing one?
In my understanding, the MQTTClient_isConnected() function is supposed to do that: https://www.eclipse.org/paho/files/mqttdoc/MQTTClient/html/_m_q_t_t_client_8h.html#ad9e40bdb7149ee3e5d075db7f51a735f
But if I try it like this, I get a Segmentation fault:
if (!MQTTClient_isConnected(client)) {
MQTTClient_create(&client, mqtt.addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = TOKEN;
if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
printf("\n==> Connection to MQTT Broker failed.\n");
MQTTClient_destroy(&client);
exit(EXIT_FAILURE);
}
}
[EDIT]
Here is a simple demo code that better illustrates what I'm trying to accomplish:
#include <stdio.h>
#include <MQTTClient.h>
MQTTClient client;
void publish_MQTT() {
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
char *payload = (char *)calloc(1024, sizeof(char));
strcpy(payload, "hello");
printf("DEBUG_BEFORE >> MQTTClient_isConnected(client) = %d\n", MQTTClient_isConnected(client)); // DEBUG OUTPUT
if (!MQTTClient_isConnected(client)) {
MQTTClient_create(&client, addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = TOKEN;
if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
fprintf(stderr, RED "\n==> Connection to MQTT Broker failed.\n" RESET_CL);
MQTTClient_destroy(&client);
free(payload);
exit(EXIT_FAILURE);
}
}
printf("DEBUG_AFTER >> MQTTClient_isConnected(client) = %d\n", MQTTClient_isConnected(client)); // DEBUG OUTPUT
pubmsg.payload = payload;
pubmsg.payloadlen = strlen(payload);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
//MQTTClient_disconnect(client, 10000);
//MQTTClient_destroy(&client);
free(payload);
}
int main(void) {
for (i=0; i<1000; i++) {
publish_MQTT();
}
return 0;
}
Please ignore the fact that the addr parameter is never specified (in my real code it is) or that it is pretty useless specifying a message in the publish_MQTT() function (in my real code, data is passed from main() to that function).
I figured it out: Apparently, there is absolutely nothing wrong with the example codes in the original posting.
It turns out I was appending the port of the MQTT server to the addr parameter again and again (in a section of the code not shown here as I didn't suspect the source of the error to be there), every time the publish_MQTT() function was called. This made the addr char string grow and eventually exceed the specified length, thus causing the SegFault.
This way everything works just as intended:
printf("\nADDR = %s\n\n", addr); // DEBUG OUTPUT
if (!MQTTClient_isConnected(client)) {
strcat(strcat(addr, ":"), pt); // This line needed to be placed here, not before that if block
MQTTClient_create(&client, addr, CLIENT_ID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
conn_opts.username = TOKEN;
if (MQTTClient_connect(client, &conn_opts) != MQTTCLIENT_SUCCESS) {
printf("\n==> Connection to MQTT Broker failed.\n");
MQTTClient_destroy(&client);
free(payload);
exit(EXIT_FAILURE);
}
}
Probably you are setting up "clean session flag", what's mean: "
If the ClientId represents a Client already connected to the Server then the Server MUST disconnect the existing Client [MQTT-3.1.4-2]." (from mqtt standard). So you client is disconnected (the existing one).
Code from example seems to be reasobable. It looks like there is problem with passing function argument. For example if function needed address, and you are giving objects itself.
Morze from standard:
"3.2.2.2 Session Present
Position: bit 0 of the Connect Acknowledge Flags.
If the Server accepts a connection with CleanSession set to 1, the Server MUST set Session Present to 0 in the CONNACK packet in addition to setting a zero return code in the CONNACK packet [MQTT-3.2.2-1].
If the Server accepts a connection with CleanSession set to 0, the value set in Session Present depends on whether the Server already has stored Session state for the supplied client ID. If the Server has stored Session state, it MUST set Session Present to 1 in the CONNACK packet [MQTT-3.2.2-2]. If the Server does not have stored Session state, it MUST set Session Present to 0 in the CONNACK packet. This is in addition to setting a zero return code in the CONNACK packet".
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am trying to connect to an MQTT broker in SSL/TLS using libmosquitto (in C). I am sure it is working on the server side as I successfully connected to the borker using mosquitto_sub (or mosquitto_pub) in the command line and with the same certificate I am using in my code.
When I try to connect using my C program, I always get the following error : "Error: Unable to create TLS context."
I am using libmosquitto 1.4.8 on Linux. Here is the code I am using :
#include <mosquitto.h>
static struct SomeStruct *data = NULL;
// The variable mosq is included in the struct
// The struct has been created somewhere else
void foo(void)
{
// I usually check the return values but removed
// it to make the code easier to read
mosquitto_lib_init();
data->mosq = mosquitto_new("foobar", true, data);
// Connect the callbacks
mosquitto_username_pw_set(data->mosq, "user", "pass");
mosquitto_tls_set(data->mosq, "/path/to/ca/file.crt,
NULL, NULL, NULL, NULL);
mosquitto_tls_insecure_set(data->mosq, 1)
mosquitto_tls_opts_set(data->mosq,
1, // also tried 0
NULL, // also tried "tlsv1.2"
NULL);
// All the return values are correct up to here
mosquitto_connect(data->mosq, "mqtt.example.com", 8883, 30); // Fails
// Logs : Error: Unable to create TLS context.
// A TLS error occurred.
}
Does anyone know what could be the issue ?
Cheers,
Antoine
EDIT : I forgot to add that I am not using mosquitto's main loop beacause another library I use already has one and I need to have a very limited number of threads. I therefore call mosquitto_loop() everytime the file descriptor changes.
This problem can only occur if SSL_CTX_new() fails. This seems pretty unlikely if mosquitto_sub works just fine on the same machine. Try "tlsv1", "tlsv1.1" as other options to tls_opts_set. You can also try patching the mosquitto client library to get more information about why openssl is unhappy:
diff --git a/lib/net_mosq.c b/lib/net_mosq.c
index 08f24d9..d4c57fd 100644
--- a/lib/net_mosq.c
+++ b/lib/net_mosq.c
## -409,6 +409,8 ## int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t
#ifdef WITH_TLS
int ret;
BIO *bio;
+ int e;
+ char ebuf[256];
#endif
if(!mosq || !host || !port) return MOSQ_ERR_INVAL;
## -441,6 +443,11 ## int _mosquitto_socket_connect(struct mosquitto *mosq, const char *host, uint16_t
#endif
if(!mosq->ssl_ctx){
_mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "Error: Unable to create TLS context.");
+ e = ERR_get_error();
+ while(e){
+ _mosquitto_log_printf(mosq, MOSQ_LOG_ERR, "OpenSSL Error: %s", ERR_error_string(e, ebuf));
+ e = ERR_get_error();
+ }
COMPAT_CLOSE(sock);
return MOSQ_ERR_TLS;
}
Example code that reproduces the problem:
#include <stdio.h>
#include <mosquitto.h>
void my_log_callback(struct mosquitto *mosq, void *obj, int level, const char *str)
{
printf("LOG: %s\n", str);
}
int main(int argc, char *argv[])
{
struct mosquitto *mosq = NULL;
int rc;
printf("Calling connect before lib init, this should fail.\n");
mosq = mosquitto_new(NULL, true, NULL);
mosquitto_log_callback_set(mosq, my_log_callback);
mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
printf("connect returned %d\n", rc);
mosquitto_destroy(mosq);
mosquitto_lib_init();
printf("Calling connect after lib init, this should be fine.\n");
mosq = mosquitto_new(NULL, true, NULL);
mosquitto_log_callback_set(mosq, my_log_callback);
mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
printf("connect returned %d\n", rc);
mosquitto_destroy(mosq);
mosquitto_lib_cleanup();
printf("Calling connect after lib cleanup, this should fail.\n");
mosq = mosquitto_new(NULL, true, NULL);
mosquitto_log_callback_set(mosq, my_log_callback);
mosquitto_tls_set(mosq, "mosquitto.org.crt", NULL, NULL, NULL, NULL);
rc = mosquitto_connect(mosq, "test.mosquitto.org", 8883, 60);
printf("connect returned %d\n", rc);
mosquitto_destroy(mosq);
return 0;
}
This produces the output:
Calling connect before lib init, this should fail.
LOG: Error: Unable to create TLS context.
LOG: OpenSSL Error: error:140A90A1:lib(20):func(169):reason(161)
connect returned 8
Calling connect after lib init, this should be fine.
LOG: Client mosq/7v?>w#YfTKk\U=;sO] sending CONNECT
connect returned 0
Calling connect after lib cleanup, this should fail.
LOG: Error: Unable to create TLS context.
LOG: OpenSSL Error: error:140A90F1:lib(20):func(169):reason(241)
connect returned 8
The final OpenSSL error is the same as yours, so you need to check whether you've deinitialised openssl. This is something mosquitto_lib_cleanup() does, but it could be something your code is doing completely independently of libmosquitto.
I'am trying to build a open source Cometd Library for C developers, to be able to run a client under barely any given device.
I manage to complete the handshake and data transfer with the longPolling technique, the next step is logically to give the option to the user to choose a Websocket connection.
To ease up the work I decided to use a library for that, I again fetched the internet and found two really relevant libraries:
The WSlay library, which seems to work well but doesn't run under OSX due to the epoll.h include which is not supported by apple.
The NoPoll library, which I think is the best one to use.
The problem is that I can't make it perform right, I always get a failed connections. After reading the full documentation I still don't understand why?
Here is my code:
int main(void)
{
cometd *cometd = cometd_new();
JsonNode *connect = json_node_new(JSON_NODE_OBJECT);
noPollCtx *ctx = nopoll_ctx_new(); //init the context of the lib
noPollMsg *msg; //variable to get messages
if (!ctx) //check if the context is well inited
puts("error ctx is nill");
/*After the new you can enable or disable the Websocket simply do this, enabled by defautl*/
cometd->config->webSockState = true;
cometd_configure(cometd, COMETDOPT_URL, "http://m.zpush.ovh:8080/str/strd");
cometd_configure(cometd, COMETDOPT_MAX_BACKOFF, 5000);
struct _cometd_ext* logger = cometd_ext_logger_new();
cometd_ext_add(&cometd->exts, logger);
cometd_connect(cometd);
connect = cometd_msg_connect_new(cometd);
cometd_transport_send(cometd, connect);
//everything until here is for the handshake wich proceed well and the server returns a successful header
//here i check if the user wants to Websocket upgrade his connection
if (cometd->config->webSockState == true)
{
// here i target the server
noPollConn *conn = nopoll_conn_new(ctx, "54.171.156.38" , "8080" , "m.zpush.ovh:8080" , "ws://m.zpush.ovh:8080/str/strd", NULL, "null");
if (!nopoll_conn_wait_until_connection_ready(conn, 5) )
// here i check if the connection is ready
{puts("nopoll_conn failed"); 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_true) //the loop to receive and send messages
{
msg = nopoll_conn_get_msg(conn);
if (msg)
break;
if (! nopoll_conn_is_ok (conn))
{
puts("connection failed during msg wait");
return nopoll_false;
}
}
}
}
cometd_subscribe(cometd, "/service/GmY-HuzW/6sd0/ls", handler);
cometd_subscribe(cometd, "service/GmY-HuzW/6sd0/updateMeta", handler);
cometd_subscribe(cometd, "/service/GmY-HuzW/6sd0/ls", handler);
cometd_subscribe(cometd, "/service/GmY-HuzW/6sd0/newFile", handler);
cometd_transport_send(cometd, cometd_ping_ls(cometd, "/service/GmY-HuzW/6sd0/ls"));
cometd_listen(cometd);
nopoll_ctx_unref(ctx);
return 0;
}
NoPoll implements a debug option, here is the result :
(proc 49413): (debug) nopoll_ctx.c:260 (nopoll_bool nopoll_ctx_register_conn(noPollCtx *, noPollConn *)) registered connection id 2, role: 0
(proc 49413): (debug) nopoll_conn.c:505 (noPollConn *__nopoll_conn_new_common(noPollCtx *, nopoll_bool, const char *, const char *, const char *, const char *, const char *, const char *)) Created noPoll conn-id=2 (ptr: 0x7f9d00501b60, context: 0x7f9d0041cdf0, socket: 3)
(proc 49413): (debug) nopoll_conn.c:284 (char *__nopoll_conn_get_client_init(noPollConn *)) Created Sec-WebSocket-Key nonce: Z0WLawAAAADGI3syAAAAAA==
(proc 49413): (debug) nopoll_conn.c:551 (noPollConn *__nopoll_conn_new_common(noPollCtx *, nopoll_bool, const char *, const char *, const char *, const char *, const char *, const char *)) Sending websocket client init: GET / HTTP/1.1
Host: 10.0.0.103
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: Z0WLawAAAADGI3syAAAAAA==
Origin: http://10.0.0.103
Sec-WebSocket-Version: 13
(proc 49413): (critical) nopoll_conn.c:643 (noPollConn *__nopoll_conn_new_common(noPollCtx *, nopoll_bool, const char *, const char *, const char *, const char *, const char *, const char *)) ***Failed to send websocket init message, error code was: 57 (2), closing session***
(proc 49413): (debug) nopoll_conn.c:1036 (void nopoll_conn_shutdown(noPollConn *)) shutting down connection id=2 (session: 3, role: client)
(proc 49413): (debug) nopoll_conn.c:651 (noPollConn *__nopoll_conn_new_common(noPollCtx *, nopoll_bool, const char *, const char *, const char *, const char *, const char *, const char *)) Web socket initial client handshake sent
-> for better reading : Failed to send websocket init message, error code was: 57 (2), closing session
I really hope some one already successfully used the library and could give me some hints or guide lines. Any help would be very much appreciated, and will give me the ability to finish this library.
The code is still a little bit messy but if you want a full sight of my code I can upload to GitHub.
--> Update :
I found a nasty trick to overcome this problem, i commented line N•845 nopoll_conn_shutdown(); in nopoll_conn.c method wich i think you have guessed it, belongs to the library. Then make install and no more error 57.
Working on your example, I found out that the remote server is closing the connection by reporting the following error:
INFO: conn=0x1238500, conn-id=2, nopoll_conn_is_ok (0x1238500)=1, nopoll_conn_is_ready (0x1238500)=1...sending content
ERROR: connection failed during msg wait, peer reported status=[1011] and reason=[java.text.ParseException: hello how are you doing, do we connect ?]
That is, you are sending unexpected application format for this WebSocket, which is causing the connection close. However, noPoll's support for close frames with body (which includes a status code and a reason) wasn't supported.
I've updated the library and now it is fully supported. You'll have to get a copy of the library from here (use SVN rev 227 at least).
https://dolphin.aspl.es/svn/publico/nopoll/trunk/
http://www.aspl.es/nopoll/downloads.html
Along with that, here is a working updated example that goes to the point I'm talking about plus the couple of functions that will allow you get status and reason reported by remote peer:
#include <nopoll.h>
int main (void) {
/* init the context of the lib */
noPollCtx * ctx = nopoll_ctx_new();
/* variable to get messages */
noPollMsg * msg;
noPollConn * conn;
/* nopoll_log_enable (ctx, nopoll_true);
nopoll_log_color_enable (ctx, nopoll_true); */
if (!ctx) {
puts("error ctx is nill");
return -1; /* do not continue */
}
/* here i target the server */
conn = nopoll_conn_new (ctx, "54.171.156.38" ,
"8080" ,
"m.zpush.ovh:8080" ,
"ws://m.zpush.ovh:8080/str/strd",
NULL, "null");
if (!nopoll_conn_wait_until_connection_ready (conn, 5) ) {
/* here i check if the connection is ready */
puts ("nopoll_conn failed");
return -1;
} /* end if */
printf ("INFO: conn=%p, conn-id=%d, nopoll_conn_is_ok (%p)=%d, nopoll_conn_is_ready (%p)=%d...sending content\n",
conn, nopoll_conn_get_id (conn), conn,
nopoll_conn_is_ok (conn), conn,
nopoll_conn_is_ready (conn));
if (nopoll_conn_send_text (conn, "hello how are you doing, do we connect ?", 40) != 40) {
puts("send text just failed.");
return - 1;
} /* end if */
while (nopoll_true) {
/* the loop to receive and send messages */
msg = nopoll_conn_get_msg(conn);
if (msg)
break;
if (! nopoll_conn_is_ok (conn)) {
printf ("ERROR: connection failed during msg wait, peer reported status=[%d] and reason=[%s]\n",
nopoll_conn_get_close_status (conn),
nopoll_conn_get_close_reason (conn));
return nopoll_false;
}
}
/* close connection always */
nopoll_conn_close (conn);
/* release context */
nopoll_ctx_unref (ctx);
return 0;
}
Best Regards,