mosquitto and SSL/TLS in C [closed] - c

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.

Related

Eclipse Paho MQTT Client: How to check for existing connection?

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".

libssh: ssh_is_host_known called without cryptographic context

I was trying to include SSH communication into my program using libssh 0.7.0. I followed the tutorial to create a simple connection to a remote machine but I came across this error:
[2016/10/26 16:38:56.280261, 1] ssh_is_server_known: ssh_is_host_known called without cryptographic context
After searching the source code of the library and its documentation, I didn't find anything related to this "lack" of cryptographic context that could help solving the issue.
Here's the code I'm trying to execute (it's part of a function; IP address and user are not the actual ones):
ssh_session session;
int verbosity = SSH_LOG_PROTOCOL;
int port = 22;
int state;
ssh_init();
session = ssh_new();
if (session == NULL){
printf("Failed to create SSH session\n"); return NULL;
}
ssh_options_set(session, SSH_OPTIONS_HOST, "111.111.111.111");
ssh_options_set(session, SSH_OPTIONS_USER, "user");
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_PORT, &port);
state = ssh_is_server_known(session);
if(state != SSH_SERVER_KNOWN_OK){
printf("SSH Server is not known\n");
}
(I tried to execute this section without calling ssh_init() but the error occurred on both cases).
According to the tour (tutorial) on official page, you need to connect to the server, before verifying that the server is known (the server needs to send you its host key). Therefore add a
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
before checking ssh_is_server_known().

Why does this JNI call segfault on Windows only?

I have some C code that adds strings to a Java array using JNI. The call to NewStringUTF segfaults -- but only on Windows 7 32-bit (in a VirtualBox VM, which is all I have to test on). In some cases, it makes it to SetObjectArrayElement call and then segfaults.
void launch_jvm_in_proc(mrb_state *mrb, CreateJavaVM_t *createJavaVM, const char *java_main_class, const char **java_opts, int java_optsc, const char **v, int prgm_optsc) {
int i;
JavaVM *jvm;
JNIEnv *env;
//...
jclass j_class_string = (*env)->FindClass(env, "java/lang/String");
jstring j_string_arg = (*env)->NewStringUTF(env, "");
jobjectArray main_args = (*env)->NewObjectArray(env, prgm_optsc, j_class_string, j_string_arg);
for (i = 0; i < prgm_optsc; i++) {
j_string_arg = (*env)->NewStringUTF(env, (char *) prgm_opts[i]);
if (!j_string_arg) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "NewStringUTF() failed");
}
(*env)->SetObjectArrayElement(env, main_args, i, j_string_arg);
}
//...
}
There are also cases where the call is made to SetObjectArrayElement successfully, and then it consistently fails on the third iteration of the loop (when i=2). This happens when I consume this project a library in mjruby. I can't explain that either.
The complete project is on Github in mruby-jvm.
Error Details:
Problem signature:
Problem Event Name: APPCRASH
Application Name: mruby-jvm.exe
Application Version: 0.0.0.0
Application Timestamp: 55eb01a5
Fault Module Name: mruby-jvm.exe
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 55eb01a5
Exception Code: c0000005
Exception Offset: 0003fff2
OS Version: 6.1.7601.2.1.0.256.4
Locale ID: 1033
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
Is there a way to collect more information on the error?
It works perfectly on Linux and Mac.
I've included instructions on how to reproduce the problem in this Github issue.
EDIT
I should clarify that I've examined this every way I can. I've checked that the various args are not NULL. I even get condensed almost the entire program to this:
static void
jvm_wtf(const char *java_dl, const char *jli_dl) {
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs jvm_init_args;
CreateJavaVM_t* createJavaVM = NULL;
jvm_init_args.nOptions = 0;
jvm_init_args.version = JNI_VERSION_1_4;
jvm_init_args.ignoreUnrecognized = JNI_FALSE;
#if defined(_WIN32) || defined(_WIN64)
disable_folder_virtualization(GetCurrentProcess());
HMODULE jvmdll = LoadLibrary(java_dl);
createJavaVM = (CreateJavaVM_t*) GetProcAddress(jvmdll, "JNI_CreateJavaVM");
#elif defined(__APPLE__)
// jli needs to be loaded on OSX because otherwise the OS tries to run the system Java
void *libjli = dlopen(jli_dl, RTLD_NOW + RTLD_GLOBAL);
void *libjvm = dlopen(java_dl, RTLD_NOW + RTLD_GLOBAL);
createJavaVM = (CreateJavaVM_t*) dlsym(libjvm, "JNI_CreateJavaVM");
#else
void *libjvm = dlopen(java_dl, RTLD_NOW + RTLD_GLOBAL);
createJavaVM = (CreateJavaVM_t*) dlsym(libjvm, "JNI_CreateJavaVM");
#endif
printf("Begining\n");
createJavaVM(&jvm, (void**)&env, &jvm_init_args);
jclass main_class = (*env)->FindClass(env, "Main");
jmethodID main_method = (*env)->GetStaticMethodID(env, main_class, "main", "([Ljava/lang/String;)V");
jclass j_class_string = (*env)->FindClass(env, "java/lang/String");
jstring j_string_arg = (*env)->NewStringUTF(env, "");
printf("Checking for NULL\n");
if (!createJavaVM) { printf("createJavaVM is NULL\n");}
if (!main_class) { printf("main_class is NULL\n");}
if (!main_method) { printf("main_method is NULL\n");}
if (!j_class_string) { printf("j_class_string is NULL\n");}
if (!j_string_arg) { printf("j_string_arg is NULL\n");}
printf("Right before segfault\n");
jobjectArray main_args = (*env)->NewObjectArray(env, 1, j_class_string, j_string_arg);
printf("It won't get here\n");
(*env)->SetObjectArrayElement(env, main_args, 0, (*env)->NewStringUTF(env, "1"));
(*env)->CallStaticVoidMethod(env, main_class, main_method, main_args);
}
Now I get a segfault at NewObjectArray. Some googling has led me to believe that this may result from Windows terminating the program because it thinks the memory allocation by the JVM is malicious. How would I determine if this is true?
I have no idea why, but declaring this variable before the LoadLibrary call fixes the problem.
char stupid_var_that_means_nothing_but_makes_windows_work_i_dont_even[MAX_PATH];
HMODULE jvmdll = LoadLibrary(java_dl);
Commenting that line out causes the problem to start happening again. I've also tried adjusting it (changing the value in []) to no avail. I am completely stumped. I stumbled on this by accident after trying to add some code from jruby-launcher
Here is the full implementation of my JNI code.
I hate computers.

noPoll Web socket library in C language always failing to connect

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,

Specifying ipv6 interface using glib/gio

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

Resources