I want to get events from freeswitch using ZMQ. I have enable mod_event_socket and mod_event_zmq in freeswitch and I am using following code to receive events but I am not getting anything.
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
static char * s_recv (void *socket) {
char buffer [256];
int size = zmq_recv (socket, buffer, 255, 0);
if (size == -1)
return NULL;
if (size > 255)
size = 255;
buffer [size] = 0;
return strdup (buffer);
}
int main (int argc, char *argv [])
{
// Socket to talk to server
void *context = zmq_ctx_new ();
void *subscriber = zmq_socket (context, ZMQ_SUB);
int rc = zmq_connect (subscriber, "tcp://10.50.202.169:5556");
assert (rc == 0);
char filter[256] = {0};
rc = zmq_setsockopt (subscriber, ZMQ_SUBSCRIBE,
"", 256);
assert (rc == 0);
// Process 100 updates
int update_nbr;
for (update_nbr = 0; update_nbr < 100; update_nbr++) {
char *string = s_recv (subscriber);
printf("%s",string);
free (string);
}
zmq_close (subscriber);
zmq_ctx_destroy (context);
return 0;
}
I am using default configurations for both these modules of freeswitch.
was the zmq connection to FreeSWITCH successful?
did FreeSWITCH actually load mod_event_zmq module?
Related
Can someone show me "Hello World" example for zeromq pub/sub in c using libzmq. I have done coding req/rep example It's well documented but I couldn't find good hello world example for pub/sub that works fine with me.
Here is my try.
pub.c
#include <zmq.h>
#include <string.h>
int main()
{
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
zmq_bind(publisher, "tcp://127.0.0.1:5555");
char message[15] = "Hello World!";
while(1)
{
zmq_msg_t msg;
zmq_msg_init_size(&message, strlen(message));
memcpy(zmq_msg_data(&msg), message, strlen(message));
zmq_msg_send(publisher, &msg, 0);
zmq_msg_close(&msg);
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
}
sub.c
#include <zmq.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main()
{
void *context = zmq_ctx_new();
void *subscriber = zmq_socket(context, ZMQ_SUB);
int rc = zmq_connect(subscriber, "tcp://127.0.0.1:5555");
assert(rc == 0);
zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
char message[15] = "";
while(1)
{
zmq_msg_t msg;
zmq_msg_init(&msg);
zmq_msg_recv(subscriber, &msg, 0);
int size = zmq_msg_size(&msg);
memcpy(message, zmq_msg_data(&msg), size);
zmq_msg_close(&msg);
printf("%s\n", message);
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
Thanks in advance
Finally this code works with me
pub.c
#include <stdio.h>
#include <assert.h>
#include <zmq.h>
int main()
{
void *context = zmq_ctx_new();
void *publisher = zmq_socket(context, ZMQ_PUB);
int rc = zmq_bind(publisher, "tcp://127.0.0.1:5556");
assert(rc == 0);
while(1)
{
rc = zmq_send(publisher, "Hello World!", 12, 0);
assert(rc == 12);
}
zmq_close(publisher);
zmq_ctx_destroy(context);
return 0;
}
sub.c
#include <stdio.h>
#include <assert.h>
#include <zmq.h>
int main()
{
void *context = zmq_ctx_new();
void *subscriber = zmq_socket(context, ZMQ_SUB);
int rc = zmq_connect(subscriber, "tcp://127.0.0.1:5556");
assert(rc == 0);
rc = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, "", 0);
assert(rc == 0);
char message[12];
while(1)
{
rc = zmq_recv(subscriber, message, 12, 0);
assert(rc != -1);
printf("%s\n", message);
}
zmq_close(subscriber);
zmq_ctx_destroy(context);
return 0;
}
I have a program below
#include <stdio.h>
#include <cmqc.h>
#include <cmqxc.h>
#include "dte_mq.h"
#include <string.h>
#include <stdlib.h>
typedef struct tagDTE_QUEUE_DESCRIPTOR
{
MQHOBJ handle;
int IsSyncpointControled;
} DTE_QUEUE_DESCRIPTOR, *PDTE_QUEUE_DESCRIPTOR;
static MQHCONN sHConn = 0;
static MQLONG sCompCode = MQCC_OK;
static MQLONG sReason = MQRC_NONE;
static int sNumOpenQueues = 0;
static PDTE_QUEUE_DESCRIPTOR sQueues = NULL;
MQLONG OpenCode;
MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
MQMD md = {MQMD_DEFAULT};
MQPMO pmo = {MQPMO_DEFAULT};
MQLONG O_options;
MQLONG C_options;
MQGMO gmo = {MQGMO_DEFAULT};
/* MQCONNX options */
MQCNO Connect_options = {MQCNO_DEFAULT};
/* Client connection channel */
MQCD ClientConn = {MQCD_CLIENT_CONN_DEFAULT};
DTE_MQ_RESULT dteMqSend(int qd, void *buf, int len)
{
printf("oleg\n");
/* memcpy(md.Format, MQFMT_STRING, MQ_FORMAT_LENGTH); */
md.MsgType = MQMT_DATAGRAM;
printf("oleg1\n");
memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId));
printf("oleg2\n");
memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId));
printf("oleg3\n");
memcpy(md.Format, MQFMT_STRING, (size_t)MQ_FORMAT_LENGTH);
printf("oleg4\n");
if(sQueues[qd].IsSyncpointControled)
pmo.Options |= MQPMO_SYNCPOINT;
printf("oleg5\n");
MQPUT(sHConn, sQueues[qd].handle, &md, &pmo, len, buf, &sCompCode, &sReason);
printf("MQput CC=%ld RC=%ld\n", sCompCode, sReason);
if (sCompCode != MQCC_OK) return DTE_MQR_FAILED;
return DTE_MQR_OK;
}
I put print statement and found out that after printf("oleg4\n";) I get error
Segmentation fault
Could you please help me top debug the program? Do I have to use malloc for the structure? It is written in C and using MQPUT
Below is a program, where above function is called
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h> /* includes for MQI */
#include <cmqxc.h>
int main(int argc, char **argv)
{
MQLONG messlen; /* message length received */
char QMgrName[MQ_Q_MGR_NAME_LENGTH+1];
char QName[MQ_Q_NAME_LENGTH+1];
char channelName[MQ_CHANNEL_NAME_LENGTH+1];
char hostname[1024];
char port[4];
MQLONG buflen;
MQBYTE TmpBuf[65536] = "This is a simple test message.";
int msgsToGet;
int msgsGot;
int dteretinit;
int dteretdeinit;
int dteretopen;
int dteretclose;
int qd;
int dteretput;
if (argc != 6)
{
printf("Usage: NewMQTest QMgrName ChlName hostname port QName\n");
exit(-1);
}
strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH);
QMgrName[MQ_Q_MGR_NAME_LENGTH] = '\0';
strncpy(channelName, argv[2], MQ_CHANNEL_NAME_LENGTH);
channelName[MQ_CHANNEL_NAME_LENGTH] = '\0';
strncpy(hostname, argv[3], 1023);
hostname[1023] = '\0';
strncpy(port,argv[4],4);
strncpy(QName, argv[5], MQ_Q_NAME_LENGTH);
QName[MQ_Q_NAME_LENGTH] = '\0';
dteretinit = dteMqInit(QMgrName,hostname,channelName);
printf("Return code from dteMqInit = %d\n",dteretinit);
qd = -1;
dteretopen = dteMqOpen(QName, qd);
printf ("Return code from dteMqOpen = %d\n",dteretopen);
if (dteretopen == 0 )
{
buflen = strlen(TmpBuf);
TmpBuf[buflen + 1] = '\0';
dteretput = dteMqSend(qd,*TmpBuf,buflen);
printf("return mqput %d\n",dteretput);
}
dteretclose = dteMqClose(qd);
printf("Return code from dteMqClose = %d\n",dteretclose);
dteretdeinit = dteMqDeinit();
printf("Return code from dteMqDeinit = %d\n",dteretdeinit);
}
I analyzed my program and check MQ. SSL didn't let me connect to MQ, that is why I couldn't change qd. The program is very old, and when failed, return value was set up as 0, 1 is success. I never did it like that. 0 is always success.
Thanks
This is some bad code.
typedef struct tagDTE_QUEUE_DESCRIPTOR
{
MQHOBJ handle;
int IsSyncpointControled;
} DTE_QUEUE_DESCRIPTOR, *PDTE_QUEUE_DESCRIPTOR;
static PDTE_QUEUE_DESCRIPTOR sQueues = NULL;
if(sQueues[qd].IsSyncpointControled)
In the code that you have posted, 'sQueues' is never set, so that is why it is throwing segmentation fault on the 'if' statement. And if 'qd' is really '-1' as per your comment, then I have to wonder what in the world you are doing.
dteretinit = dteMqInit(QMgrName,hostname,channelName);
How come you don't pass the port number into the dteMqInit subroutine?
when calling a ONC-RPC-function that returns a char array I get (apparently) uninitialized memory on the first call. Subsequent calls give me the correct result.
This example showcases the issue:
ftp.x:
const BLOCKSIZE = 1024;
struct block {
char arr<BLOCKSIZE>;
};
program FILE_GET_BLOCK_PROG {
version FILE_GET_BLOCK_VERS {
block FILE_GET_BLOCK() = 1;
} = 1;
} = 0x42424243;
ftp_client.c:
#include "ftp.h"
#include <errno.h>
#include <string.h>
size_t
file_get_block_prog_1(char *host, char *buf)
{
CLIENT *clnt;
block *result_1;
#ifndef DEBUG
clnt = clnt_create (host, FILE_GET_BLOCK_PROG, FILE_GET_BLOCK_VERS, "udp");
if (clnt == NULL) {
clnt_pcreateerror (host);
exit (1);
}
#endif /* DEBUG */
result_1 = file_get_block_1(NULL, clnt);
if (result_1 == (block *) NULL) {
clnt_perror (clnt, "call failed");
}
#ifndef DEBUG
clnt_destroy (clnt);
#endif /* DEBUG */
memcpy(buf, result_1->arr.arr_val, result_1->arr.arr_len);
return result_1->arr.arr_len;
}
int
main (int argc, char *argv[])
{
char *host, *source_filename;
char buf[BLOCKSIZE+1];
int block_count;
size_t bytes_read;
if (argc < 2) {
printf ("usage: %s server_host\n", argv[0]);
exit (1);
}
host = argv[1];
bytes_read = file_get_block_prog_1 (host, buf);
buf[bytes_read] = '\0';
printf("%d bytes:\n%s\n", bytes_read, buf);
exit (0);
}
ftp_server.c:
#include "ftp.h"
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
block *
file_get_block_1_svc(void *argp, struct svc_req *rqstp)
{
static block result;
static int request = 1;
char buf[BLOCKSIZE+1];
size_t bytes_read;
strcpy(buf, "This is just a simple test block. There is nothing relevant in here.");
result.arr.arr_len = strlen(buf);
result.arr.arr_val = buf;
printf("Request #%d:\n%s\n", request++, buf);
return &result;
}
When running the server and calling the client twice, this is my output:
client:
$ ./ftp_client localhost
68 bytes:
$ ./ftp_client localhost
68 bytes:
This is just a simple test bock. There is nothing relevant in here.
server:
Request #1:
This is just a simple test bock. There is nothing relevant in here.
Request #2:
This is just a simple test bock. There is nothing relevant in here.
Is there any initialization I missed that I need to do before the first request? What else would cause this behavior?
I have currently a synchronous UDP application receiving messages.
The code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <glib.h>
#include <gio/gio.h>
int main(argc,argv)
int argc;
char ** argv;{
char buf[256], *ptr, sep[] = "| ";
GError * error = NULL;
GSocket * socket;
GSocketAddress *gsockAddr, *gfromAddr;
guint16 udp_port = 1500;
//Creates socket udp ipv4
socket = g_socket_new(G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP,
&error);
g_assert(error == NULL);
if (socket == NULL) {
g_print("ERROR");
exit(1);
}
//sockaddr struct like
gsockAddr = G_SOCKET_ADDRESS(g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4), udp_port));
if(gsockAddr == NULL){
g_error("Error socket\n");
exit(1);
}
//
if (g_socket_bind (socket, gsockAddr, TRUE, NULL) == FALSE){
g_print("Error bind\n");
exit(1);
}
int bytes = g_socket_receive_from (socket,
&gfromAddr,
buf,
255,
NULL,
&error);
if (bytes == -1) {
g_warning ("Failed to receive from socket: %s", error->message);
g_error_free (error);
return TRUE;
}
g_message("Server receive: %s", buf);
guint16 port = g_inet_socket_address_get_port(G_INET_SOCKET_ADDRESS(gfromAddr));
g_print("...from %s(%d)\n",g_inet_address_to_string(g_inet_socket_address_get_address(G_INET_SO CKET_ADDRESS(gfromAddr))), (int) port);
exit(0);
}
So, I want to make the receive operation, non-blocking instead of blocking. I want to make it either ansynchronous, or/and threaded so that, meanwhile, I could do other operations related to the application I want to develop.
But I did not suceed to make it like I want. I tried to use GLib IO Channels, but I can not make it works. The processus is waiting, but only because of the Main Loop (I can not telnet the application).
The code :
#include <gio/gio.h>
#include <glib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BLOCK_SIZE 1024
static gboolean
gio_read_socket (GIOChannel *channel,
GIOCondition condition,
gpointer data)
{
char buf[1024];
gsize bytes_read;
GError *error = NULL;
if (condition & G_IO_HUP) return FALSE; /* this channel is done */
g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read,
&error);
g_assert (error == NULL);
buf[bytes_read] = '\0';
g_print ("%s", buf);
return TRUE;
}
int
main (int argc, char **argv)
{
GSocket * s_udp;
GError *err = NULL;
guint16 udp_port = 5556;
s_udp = g_socket_new(G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP,
&err);
g_assert(err == NULL);
if (s_udp == NULL) {
g_print("ERROR");
exit(1);
}
g_socket_bind(s_udp,
G_SOCKET_ADDRESS(g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4), udp_port)),
TRUE,
&err);
g_assert(err == NULL);
int fd = g_socket_get_fd(s_udp);
GIOChannel* channel = g_io_channel_unix_new(fd);
guint source = g_io_add_watch(channel, G_IO_IN,
(GIOFunc) gio_read_socket, NULL);
g_io_channel_unref(channel);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
}
I am quite a beginner with GLib/Gio, and I think I am doing wrong with the IO Channels. I would like to add it to the main loop as an event, so that I could use my callback function. Maybe there is a simpler way to do that.
Besides, I have a TCP asynchronous and threaded server that is working, but I did not find how to do the same with UDP (using a GThreadedSocketService and creating a socket listener, then adding the service to the main loop. Easy as pie with TCP).
Do you have any idea how to proceed ? If you know how to do but only with the basic API socket, I still take it ! Thanks.
I figure it out.
I am indeed quite a beginner. Because, when I wanted to test my udp application (the second code block), I used telnet to connect to it and try to send messages. However, we can not telnet udp applications of course...
So I tried with a simple udp sender (I used Glib/Gio for it by the way) instead of telnet and it worked, perfectly non-blocking and reusable. I did make some changes but basically, it is the same. I put an idle function to show you how non-blocking it is, whether this can help someone one day.
My simple Glib/Gio UDP app, non blocking :
#include <gio/gio.h>
#include <glib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BLOCK_SIZE 1024
static gboolean
gio_read_socket (GIOChannel *channel,
GIOCondition condition,
gpointer data)
{
char buf[1024];
gsize bytes_read;
GError *error = NULL;
if (condition & G_IO_HUP) return FALSE; /* this channel is done */
g_io_channel_read_chars (channel, buf, sizeof (buf), &bytes_read,
&error);
g_assert (error == NULL);
buf[bytes_read] = '\0';
g_print ("%s", buf);
int *a = data;
*a = *a + 1;
return TRUE;
}
gboolean
idleCpt (gpointer user_data){
int *a = user_data;
g_print("%d\n", *a);
sleep(1);
return TRUE;
}
int
main (int argc, char **argv)
{
GSocket * s_udp;
GError *err = NULL;
int idIdle = -1, dataI = 0;
guint16 udp_port = 1505;
GSocketAddress * gsockAddr = G_SOCKET_ADDRESS(g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4), udp_port));
s_udp = g_socket_new(G_SOCKET_FAMILY_IPV4,
G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP,
&err);
g_assert(err == NULL);
if (s_udp == NULL) {
g_print("ERREUR");
exit(1);
}
if (g_socket_bind (s_udp, gsockAddr, TRUE, NULL) == FALSE){
g_print("Erreur bind\n");
exit(1);
}
g_assert(err == NULL);
int fd = g_socket_get_fd(s_udp);
GIOChannel* channel = g_io_channel_unix_new(fd);
guint source = g_io_add_watch(channel, G_IO_IN,
(GIOFunc) gio_read_socket, &dataI);
g_io_channel_unref(channel);
GMainLoop *loop = g_main_loop_new(NULL, FALSE);
idIdle = g_idle_add(idleCpt, &dataI);
g_main_loop_run(loop);
}
The code is not perfect, there is a lot of optimisations to make, but we can do nice things from that I think. If you want to see my udp sender, just ask.
I am unable to receive message serialized in protobuf over ZeroMQ sockets using C.
I have serialized message entered by client and send this buffer to server using s_send() function defined in zhelpers.h. The server code is same test code bundled with zeromq package as an examples.
Here is my client side:
#include "amessage.pb-c.h"
#include "zhelpers.h"
int main (void)
{
AMessage msg = AMESSAGE__INIT; // AMessage
void *buf; // Buffer to store serialized data
unsigned len;
printf ("Connecting to server...\n");
void *context = zmq_ctx_new ();
void *requester = zmq_socket (context, ZMQ_REQ);
char buffer[256] = "";
printf("[client] :");
scanf("%s", buffer );
msg.csmsg = buffer;
len = amessage__get_packed_size(&msg);
buf = malloc(len);
printf("[client]: pack msg len : %d\n ", len);
printf("Sent msg : %d\n", buf);
amessage__pack(&msg,buf);
s_send(requester, buf);
zmq_close (requester);
zmq_ctx_destroy (context);
return 0;
}
And server side:
#include "zhelpers.h"
#include <pthread.h>
#include <stdlib.h>
#include "amessage.pb-c.h"
#define MAX_MSG_SIZE 256
static size_t read_buffer (unsigned max_length, unsigned char *out)
{
size_t cur_len = 0, nread;
uint8_t c;
while ((nread=fread(out + cur_len, 1, max_length - cur_len, stdin)) != 0)
{
cur_len += nread;
if (cur_len == max_length)
{
fprintf(stderr, "[server]: max message length exceeded\n");
exit(1);
}
}
return cur_len;
}
static void * worker_routine (void *context)
{
AMessage *msg;
uint8_t buf[MAX_MSG_SIZE];
char buffer[256];
// Socket to talk to dispatcher
void *receiver = zmq_socket (context, ZMQ_REP);
zmq_connect (receiver, "inproc://workers");
while (1) {
uint8_t *string = s_recv (receiver);
if(string == 0)
printf("[server]: Error: In receiving msg.\n");
else
{
size_t msg_len = read_buffer (MAX_MSG_SIZE, string);
printf("[server]: client msg len is: %d.\n", msg_len);
msg = amessage__unpack(NULL, msg_len, string);
if (msg == NULL)
{
fprintf(stderr, "[server]: error unpacking incoming message\n");
exit(1);
}
printf ("[client]: %s \n", msg->csmsg);
}
amessage__free_unpacked(msg, NULL);
free (string);
// Do some 'work'
sleep (1);
}
zmq_close (receiver);
return NULL;
}
int main (void)
{
void *context = zmq_ctx_new ();
void *clients = zmq_socket (context, ZMQ_ROUTER);
zmq_bind (clients, "tcp://*:5555");
void *workers = zmq_socket (context, ZMQ_DEALER);
zmq_bind (workers, "inproc://workers");
// Launch pool of worker threads
int thread_nbr;
for (thread_nbr = 0; thread_nbr < 5; thread_nbr++) {
pthread_t worker;
pthread_create (&worker, NULL, worker_routine, context);
}
// Connect work threads to client threads via a queue proxy
zmq_proxy (clients, workers, NULL);
zmq_close (clients);
zmq_close (workers);
zmq_ctx_destroy (context);
return 0;
}
Any idea what I am doing wrong?
You are using s_send() which expects a C string as an argument, and calls strlen() to determine its size. However, protocol buffers data is binary data, and may contain null bytes anywhere in the message.
Instead use zmq_send() and give the length of the message to the zmq_msg_init_size() function.