Communicate with zeromq with protobuf serialized messages - c

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.

Related

Segmentation fault due to file descriptor in multi threaded client

I have created a client-server file sharing system with multi threading. The client code is working correctly for a single client. When I increase the number of threads in client, segmentation fault is occurred in server code.
When I executed the code on gdb, it shows the error segmentation fault occurred, no such file or directory. Is this because of the threads sharing file descriptor? How to resolve the segmentation fault?
----------edit-----------
I considered all your suggestions. Most of the errors are resolved, but when I try to send a >10mb file, some send-recv call does not execute fully while sending it out with threads(It works fine with a single thread). I believe this is the reason memory leakage is happening and ultimately results in segmentation fault(file pointers not closed). The same is happening in gdb.
How to resolve this send receive blocking error?
client code
#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<pthread.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define SERVER_ADDR "192.168.43.158" //"10.15.36.112"
//defining number of threads
struct ser_data
{
int sockfd;
int n;
};
void *client_req(void * data){
// printf("inside thread\n");
//sleep(1);
int s,c,n,read_size,r;
//login_id and password of the user
//array to choose file names randomly
//char f_name[20][20]={"f0.txt","f1.txt","f2.txt","f3.txt","f4.txt","f5.txt","f6.txt","f7.txt","f8.txt","f9.txt","f10.txt\0","f11.txt\0","f12.txt\0" ,"f13.txt\0","f14.txt\0","f15.txt\0","f16.txt\0","f17.txt\0","f18.txt","f19.txt"};
//socket address for client and server
//used for generation of random no
time_t t;
struct sockaddr_in cli,serv;
FILE *f;
char fname[SIZE]="file_cli/";
char f_name[SIZE];
char login_id[21], pswd[21], choice[2];
//msg_cli_rec= message recieved form server
char msg_cli_rec[SIZE];
//msg_cli_send =message sent by client
char msg_cli_send[SIZE];
time_t start, stop;
int brk=0;
start = time(NULL);
s=socket(AF_INET,SOCK_STREAM,0);
bzero((char*)&serv,sizeof(cli));
cli.sin_family=AF_INET;
cli.sin_port=htons(PORT);
cli.sin_addr.s_addr = inet_addr(SERVER_ADDR);
connect(s,(struct sockaddr*)&cli,sizeof(cli));
//printf("\nConnected with server");
strcpy(choice, "1");
/*msg_cli_rec = (char *) malloc(1000* sizeof(char));
msg_cli_send = (char *) malloc(1000* sizeof(char));*/
//if user wants to login
if(strcmp(choice,"1")==0)
{
strcpy(login_id, "prach");
send(s, login_id, sizeof(login_id), 0);
strcpy(pswd, "prach");
send(s, pswd, sizeof(pswd), 0);
}
//making default choice download 1
do {
strcpy(choice, "1\0");
strcpy(msg_cli_send, choice);
//send(s, choice, sizeof(choice), 0);
send(s,msg_cli_send,sizeof(msg_cli_send),0);
//random number generation
srand((unsigned) time(NULL));
//r=((unsigned)rand()*(i++))%20;
r=15;
if(strcmp(choice,"1")==0)
{
/*if(recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0))
{
//if((strcmp("end",msg_cli_rec))==0)break;
printf("\n%s", msg_cli_rec);
}*/
/*printf("\nEnter the file name you want:");
scanf("%s", msg_cli_send);*/
// to select file name with index of the random number
sprintf(f_name,"file (%d).txt",r);
strcpy(msg_cli_send, "");
strcpy(msg_cli_send,f_name);
// printf("\n%s",msg_cli_send);
// printf("\n rand =%d\n", r );
send(s,msg_cli_send,sizeof(msg_cli_send),0);
// printf("\nThe received file content is:");
//receiving the file names
f = fopen(strcat(fname,f_name),"w");
bzero( msg_cli_rec, sizeof(msg_cli_rec));
while((recv(s, msg_cli_rec, sizeof(msg_cli_rec), 0)> 0)&&(*msg_cli_rec!='\0'))
{//fflush(stdout);
if((strcmp("quit",msg_cli_rec))==0)break;
fprintf(f, "%s", msg_cli_rec);
//printf("\n%s", msg_cli_rec);
bzero( msg_cli_rec, sizeof(msg_cli_rec));
}
// printf("File recieved");
fclose(f);
strcpy(fname,"\0" );
//sem_post(&sem);
}
stop = time(NULL);
// printf("\n%s\n", ctime(&stop));
//printf("%ld", (stop-start));
//set the timer to 300 seconds
}while(*choice == '1' && (stop-start)<10);
//tell the server that we are done with sending files
strcpy(choice, "0");
send(s, choice, sizeof(choice), 0);
printf("%ld\n", (stop-start) );
/* free(msg_cli_rec);
free(msg_cli_send);*/
close(s);
//pthread_exit(NULL);
}
int main()
{
int N_Threads=2, count =0;
struct ser_data data;
/*while(N_Threads<=2)
{
pthread_t t;
pthread_create( &t , NULL , client_req , NULL);
N_Threads++;
if ( ! pthread_detach(t) )
printf("Thread detached successfully !!!\n");
//pthread_join(t, NULL);
}*/
while(count != N_Threads){
pthread_t handle;
count = count+1;
data.sockfd = count;
if(pthread_create(&handle, NULL, client_req,(void *)&data)<0)
error("Error creating thread");
else
printf("Thread allocation successful for fd: %d\n",data.sockfd);
}
pthread_exit(NULL);
}
server code
#include <time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<dirent.h>
#include <mysql/mysql.h>
#include <semaphore.h>
#define PORT 8029
#define SIZE 1024
#define QUERY_SIZE 200
#define N_Threads 5
#define SERV_ADDR "192.168.43.158"
clock_t start, stop;
//login id and password of the user
int file_id=1;
/*Database variables*/
MYSQL *db_conn;
char *db_server = "localhost";
char *db_user = "root";
char *db_password = "root";
char *database = "file_db";
//for synchronization while accessing the db
sem_t sem;
/* A function which generates the and returns login query statement*/
char* query_login(char *query, char *login_id, char *pswd)
{
//generating query
strcpy(query,"SELECT * FROM user_info WHERE user_id='");
strcat(query, login_id);
strcat(query, "' AND pswd='");
strcat(query, pswd);
strcat(query, "'");
return query;
}
/* A function which generates and returns the register query statement*/
char* query_register(char *query, char *login_id, char *pswd)
{
strcpy(query, "INSERT INTO user_info VALUES ( '");
strcat(query, login_id);
strcat(query, "', '");
strcat(query, pswd);
strcat(query, "' )");
return query;
}
void *connect_client(void *socket)
{ int sock=*(int*)socket;
printf("\nFD %d",sock);
char msg_c_r[SIZE], msg_s_s[SIZE];
//for the choice given to the user to login or register
char choice='0';
char msg_serv_send[SIZE],msg_serv_rec[SIZE];
char msg_cli_rec[SIZE];
char fpath[SIZE] = "file_serv/";
char fname[SIZE];
int read_size;
int num_fields=0;
char * line = NULL;
size_t len = 0;
ssize_t read;
MYSQL_ROW row;
MYSQL_RES *db_res;
char login_id[21], pswd[21];
FILE *f;
FILE *fc;
char name[SIZE];
char query1[SIZE];
char query[QUERY_SIZE];
/*locking the database for mutual exclusion*/
//sem_wait(&sem);
//executing a query
choice = '1';
strcpy(query, "\0");
switch(choice)
{
//1 = login
case '1':
/*to find the login id and password of the user*/
bzero(login_id, sizeof(login_id));
recv(sock, login_id, sizeof(login_id), 0);
bzero(pswd, sizeof(pswd));
recv(sock, pswd, sizeof(pswd), 0);
printf("The login id is: %s\nThe Password is: %s\n", login_id, pswd);
//lock for accessing db in mutual exclusion
sem_wait(&sem);
query_login(query, login_id, pswd);
//checking the details given by client
if (mysql_query(db_conn, query)!=0) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
}
strcpy(query, "\0");
strcat(query,"select * from user_info where user_id='");
strcat(query,login_id);
strcat(query,"'");
mysql_query(db_conn, query);
db_res = mysql_store_result(db_conn);
row = mysql_fetch_row(db_res);
if (row!=0) {
//send(sock,"T",sizeof("T"),0);
printf("\nT");
}
//freeing the result variable so it can be used further
mysql_free_result(db_res);
//release lock
sem_post(&sem);
break;
}//switch case
/*send(sock, "\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n", sizeof("\nPlease enter your choice \n 1- File Download \n 2-File Upload\n 3-Rating\n"), 0);*/
int nu=1;
do{
bzero(msg_serv_rec,sizeof(msg_serv_rec));
if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
{
choice = msg_serv_rec ? *msg_serv_rec : '0';
printf("\n choice = %c\n", choice);
strcpy(query, "\0");
//printf("Client's choice is file Download\n" );
/*Sending File to the client line by line
checking the database connection*/
if(choice == '1'){
/*if(mysql_query(db_conn, "SELECT name FROM file_info")==0)
{
db_res = mysql_store_result(db_conn);
num_fields = mysql_num_fields(db_res);
if(num_fields>0)
{
while ((row = mysql_fetch_row(db_res)))
{
for(int i = 0; i < num_fields; i++)
{
char *fname1=row[i] ? row[i] : "NULL";
strcat(name,fname1);
strcat(name, "\n");
//send(sock,name,sizeof(name),0);
//printf("\n%s",name);
}
}
//sending list of all files to client
send(sock,name,sizeof(name),0);*/
/*emptying the name!!
strcpy(name, "");*/
//freeing the result variable so it can be used further
/*mysql_free_result(db_res);
sem_post(&sem);*/
bzero(msg_serv_rec,sizeof(msg_serv_rec));
if(recv(sock, msg_serv_rec,sizeof(msg_serv_rec), 0)>0)
{//which file recieved
printf("%s\n", msg_serv_rec );
// sem_wait(&sem);
f = fopen(strcat(fpath, msg_serv_rec),"r");
while(fgets(msg_serv_send, sizeof(msg_serv_send), f) !=NULL)
{
if((*msg_serv_send!=EOF || *msg_serv_send!='\n'))
{
send(sock, msg_serv_send, sizeof(msg_serv_send), 0);
//printf("\n%s", msg_serv_send);
}
else
break;
}
send(sock,"quit",sizeof("quit"),0);
fclose(f);
strcpy(fpath, "file_serv/");
//sem_post(&sem);
printf("\nFile sent to the client\n");
}
}
else if (choice == '0')
break;
strcpy(msg_serv_rec, "");
//stop = clock();
//time(NULL);
}
else
{
choice = '0';
}
}while ( choice != 'f' && choice != '0');
nu++;
/* unblocking the semaphores to allow other threads to access*/
//sem_post(&sem);
if(read_size == 0)
{
puts("\nClient disconnected\n");
fflush(stdout);
}
/*else if(read_size == -1)
{perror("recv failed");}
fclose(f);*/
close(sock);
pthread_exit(NULL);
}
int main()
{ int s,n,i, clilen;
int c;
int newsockfd;
int *new_sock;
start = clock();
//pthread_t handle;
struct sockaddr_in cli,serv;//socket address for client and server
MYSQL_ROW row;
MYSQL_RES *db_res;
//initializing the semaphore
sem_init(&sem, 0, 1);
//synchronization in DB
sem_wait(&sem);
/*Database connectivity*/
db_conn = mysql_init(NULL);
/* Connect to database */
if (!mysql_real_connect(db_conn, db_server, db_user, db_password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
exit(1);
}
/* send SQL query */
if (mysql_query(db_conn, "show tables")) {
fprintf(stderr, "%s\n", mysql_error(db_conn));
exit(1);
}
db_res = mysql_use_result(db_conn);
/* output table name */
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(db_res)) != NULL)
printf("%s \n", row[0]);
//freeing the result variable so it can be used further
mysql_free_result(db_res);
sem_post(&sem);
//Server socket
s=socket(AF_INET,SOCK_STREAM,0);
bzero((char*)&serv,sizeof(serv));
serv.sin_family=AF_INET;
serv.sin_port=htons(PORT);
serv.sin_addr.s_addr=inet_addr( SERV_ADDR);//"10.15.36.112");
/*printf("\nServer is waiting for client to respond");
i=0*/
//accept the incomming connections from client
bind(s,(struct sockaddr *)&serv,sizeof(serv));
printf("\nAddress bind successful");
listen(s,3000);//4 is the limit of the number of outstanding connections
n=sizeof(cli);
/*
i=0;
//accept the incomming connections from client
while( (c = accept(s, (struct sockaddr *)&cli, (socklen_t*)&n))) //&& (stop-start)<300 )
{ puts("Connection accepted\n");
pthread_t t;
printf("sock =%d\n", c);
if( pthread_create( &t , NULL , connect_client , (void*) c) < 0)
{
perror("could not create thread");
return 1;
}
i++;
/*Now detach the thread ,When a detached thread terminates, its resources are
automatically released back to the system without the need for
another thread to join with the terminated thread.*/
/* if ( ! pthread_detach(t) )
printf("Thread detached successfully !!!\n");
puts("Handler assigned");
stop = clock();
}*/
clilen=sizeof(cli);
while(newsockfd = accept(s, (struct sockaddr *) &cli, &clilen))
{
if(newsockfd < 0)
error("ERROR on accept");
else{
pthread_t handle;
new_sock = malloc(1);
*new_sock = newsockfd;
if(pthread_create(&handle, NULL,connect_client ,(void *)new_sock)<0)
error("Error creating thread");
else
printf("Thread fd: %d\n",newsockfd);
if ( ! pthread_detach(handle) )
printf("Thread detached successfully !!!\n");
}
}
/* close database connection */
mysql_free_result(db_res);
mysql_close(db_conn);
close(s);
/*destroying the mutex */
sem_destroy(&sem);
return 0;
}

sendarp with multithreading function is not working for whole subnet (wifi environment)

I was trying to fetch Mac addrs of all the devices present in WiFi environment(whole subnet).
Initially when i ran the code approx it took 10 mins to get the result for whole subnet so in order to reduce the time i used multithreaded concept in windows machine but this method is not at all working.
I am pasting the code snippet below.
Even i tried different logic like running 255, 100, 50 ,2 threads at a time but still it failed.
I suspect synchronization issue in this but i don't have any idea to resolve this, so please help me in this getting done.
DWORD WINAPI GetMacAddrOfSubNet(LPVOID lpParam)
{
DWORD dwRetVal;
IPAddr DestIp = 0;
IPAddr SrcIp = 0; /* default for src ip */
ULONG MacAddr[2]; /* for 6-byte hardware addresses */
ULONG PhysAddrLen = 6; /* default to length of six bytes */
char look[100];
strcpy(look ,(char *)lpParam);
DestIp = inet_addr(look);
memset(&MacAddr, 0xff, sizeof (MacAddr));
/*Pinging particular ip and retrning mac addrs if response is thr*/
dwRetVal = SendARP(DestIp, SrcIp, &MacAddr, &PhysAddrLen);
if (dwRetVal == NO_ERROR)
{
/**/
}
return 0;
}
extern "C" __declspec(dllexport) int __cdecl PopulateARPTable(char *IpSubNetMask)
{
char ipn[100];
char buffer[10];
unsigned int k;
DWORD dwThreadIdArray[260];
HANDLE hThreadArray[260];
/*Run 255 threads at once*/
for (k=1; k<255; k++)
{
itoa(k, buffer, 10);
strcpy(ipn, IpSubNetMask);
strcat(ipn, ".");
strcat(ipn, buffer);
/*Thread creation */
hThreadArray[k] = CreateThread( NULL, 0, GetMacAddrOfSubNet, ipn, 0, &dwThreadIdArray[k]);
if (hThreadArray[k] == NULL)
{
//ExitProcess(3);
}
}
WaitForMultipleObjects(255, hThreadArray, TRUE, INFINITE);
return 0;
}
The ipn buffer only exists once. You are using and modifying it as parameter for your (up to) 255 threads. And you expect that the statement strcpy(look ,(char *)lpParam) in the thread will be performed before the main thread modifies ipnagain for calling the next thread. But this is not the case, at least it's not guaranteed. So your threads may use wrong parameters.
Either use different buffers for each thread, or implement a synchronization, that ensures that the parameter has been copied by the thread before main thread modifies the buffer again.
I've done this already for Excel, wrote a multi-threaded DLL that in addition to getting MAC addresses, will do DNS reverse hostname and ICMP ping RT.
Lemme know if you want the VBA code that goes with it. The source for the C-based DLL (which you may be happy with as a template) is:
/*
ExcelNet library: Provide threaded networking functions
NOTE: Serially doing these on the network involves serially waiting for timeouts, much ouchies!
Written by: Danny Holstein
*/
#if 1 // header stuff
#include <windows.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MSEXPORT __declspec(dllexport)
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define BUFSZ 256
typedef struct {
char ip[BUFSZ]; // IP addresses in dotted notation.
int ipSize; // size of IP address buffer
char data[BUFSZ]; // general network data (MAC, hostname, etc)
int dataSize; // size of data buffer ^
int err_no; // WinAPI error number
int (*func)(LPCSTR Addr, char* buf, int BufSz); // function address, &GetNameInfos, &GetARP or &GetICMP
} NET_DATA;
int GetARP(LPCSTR Addr, char* Buf, int BufSz);
int GetNameInfos(LPCSTR Addr, char* Buf, int BufSz);
int GetICMP(LPCSTR Addr, char* Buf, int BufSz);
char msg_dbg[BUFSZ], dan[BUFSZ];
#define DEBUG_PRT() {snprintf(msg_dbg, BUFSZ, "lineno = %d\tfunc = %s", __LINE__ , __func__); MessageBox(0, msg_dbg, "debug", 0);}
#define DEBUG_MSG(msg) {snprintf(msg_dbg, BUFSZ, "msg=\"%s\"\tlineno = %d\tfunc = %s", msg, __LINE__ , __func__); MessageBox(0, msg_dbg, "debug", 0);}
#if 0 // documentation indicates malloc/realloc/free shouldn't be used in DLLs
#define malloc(A) malloc(A)
#define realloc(A, B) realloc(A, B)
#define free(A) free(A)
// #define NOMEMLEAK // dudint work
#else // kinda works, when NOT allocating all the NET_DATA structure elements
#define malloc(A) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, A)
#define realloc(A, B) HeapReAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, A, B)
#define free(A) (void) HeapFree(A, HEAP_GENERATE_EXCEPTIONS, NULL)
#define NOMEMLEAK
#endif
#endif
MSEXPORT void __stdcall ArrayDGH(SAFEARRAY **IntArr, SAFEARRAY **StrArr)
{
SAFEARRAY *A = (SAFEARRAY*) (*IntArr);
SAFEARRAY *S = (SAFEARRAY*) (*StrArr);
int n = (*A).rgsabound[0].cElements;
snprintf(dan, BUFSZ, "a num elems = %d, str num elems = %d", n, (*S).rgsabound[0].cElements); DEBUG_MSG(dan);
// for (int i=0; i<n; i++) {snprintf(dan, BUFSZ, "elem[%d] = %d", i, ((int*) (*A).pvData)[i]); DEBUG_MSG(dan);}
OLECHAR* str[] = {L"Da",L"Fuk",L"Waz",L"Dat?",L"dot",L"dot"};
for (int i=0; i<n; i++) {SysReAllocString(&(((BSTR*) (*S).pvData)[i]), str[i]);}
}
DWORD dwMilliseconds = 10000;
MSEXPORT void __stdcall SetTIMO(DWORD Timo) {dwMilliseconds = Timo;}
MSEXPORT bool __stdcall ExcelSendARP(LPCSTR Addr, BSTR* MAC)
{
char buf[BUFSZ];
int err = GetARP(Addr, buf, BUFSZ);
*MAC = SysAllocStringByteLen(buf, strlen(buf)); // avoid WIDE to ANSI stuff
return !err;
}
MSEXPORT bool __stdcall ExcelICMPRT(LPCSTR Addr, BSTR* RoundTrip)
{
char buf[BUFSZ];
int err = GetICMP(Addr, buf, BUFSZ);
*RoundTrip = SysAllocStringByteLen(buf, strlen(buf)); // avoid WIDE to ANSI stuff
return !err;
}
MSEXPORT bool __stdcall ExcelGetNameInfo(LPCSTR Addr, BSTR* NameInfo)
{
char buf[BUFSZ];
#ifdef TEST_FUNC_PTR
int (*FunAddr[2])(LPCSTR Addr, char** buf, int BufSz);
FunAddr[0] = &GetARP; FunAddr[1] = &GetNameInfos; // DRY code hooks
int err = (*(FunAddr[1]))(Addr, buf, BUFSZ);
#else
int err = GetNameInfos(Addr, buf, BUFSZ);
#endif
*NameInfo = SysAllocStringByteLen(buf, strlen(buf)); // avoid WIDE to ANSI stuff
return !err;
}
int GetNameInfos(LPCSTR Addr, char* buf, int BufSz)
{
ULONG inet; DWORD resp = 0; HOSTENT *tHI;
struct in_addr addr = { 0 };
if ((inet = inet_addr(Addr)) == INADDR_NONE) {
if (strcpy_s(buf, BufSz, "inet_addr failed and returned INADDR_NONE")) DEBUG_MSG("strcpy_s error!");
return inet;
}
addr.s_addr = inet; tHI = gethostbyaddr((char *) &addr, 4, AF_INET);
if (tHI == NULL) { // no reponse for this IP condition, decode condition and place in PCHAR buf
resp = WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, resp, 0, buf, BufSz, 0);
return resp;
}
_snprintf_s(buf, BufSz-1, _TRUNCATE, "%s", tHI->h_name); // place hostname in PCHAR buf
return resp; // <- resp = 0, we have a hostname associated with this IP, SUCCESS!
}
int GetARP(LPCSTR Addr, char* buf, int BufSz)
{
#define BUFLEN 6
ULONG pMacAddr[BUFLEN], inet, BufLen = BUFLEN; DWORD resp = 0;
if ((inet = inet_addr(Addr)) == INADDR_NONE) {
if (strcpy_s(buf, BufSz, "inet_addr failed and returned INADDR_NONE")) DEBUG_MSG("strcpy_s error!");
return inet;
}
resp = SendARP(inet, 0, pMacAddr, &BufLen);
if (resp) { // no reponse for this IP condition, decode condition and place in PCHAR buf
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, resp, 0, buf, BufSz, 0);
return resp;
}
UCHAR *pMacAddrBytes = (UCHAR *) pMacAddr;
_snprintf_s(buf, BufSz, _TRUNCATE, "%02x:%02x:%02x:%02x:%02x:%02x", pMacAddrBytes[0], pMacAddrBytes[1], pMacAddrBytes[2],
pMacAddrBytes[3], pMacAddrBytes[4], pMacAddrBytes[5]); // place MAC in PCHAR buf
return resp; // <- resp = 0, we have a MAC associated with this IP, SUCCESS!
}
int GetICMP(LPCSTR Addr, char* buf, int BufSz)
{
HANDLE hIcmpFile;
ULONG inet; DWORD resp = 0;
char SendData[] = "Data Buffer";
LPVOID ReplyBuffer = NULL;
DWORD ReplySize = 0;
if ((inet = inet_addr(Addr)) == INADDR_NONE) {
if (strcpy_s(buf, BufSz, "inet_addr failed and returned INADDR_NONE")) DEBUG_MSG("strcpy_s error!");
return inet;
}
hIcmpFile = IcmpCreateFile();
if (hIcmpFile == INVALID_HANDLE_VALUE) {
resp = GetLastError();
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, resp, 0, buf, BufSz, 0);
return resp;
}
// Allocate space for at a single reply
ReplySize = sizeof (ICMP_ECHO_REPLY) + sizeof (SendData) + 8;
ReplyBuffer = (VOID *) malloc(ReplySize);
resp = IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL,
inet, SendData, sizeof (SendData), NULL,
ReplyBuffer, ReplySize, dwMilliseconds);
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY) ReplyBuffer;
if (resp == 0) { // no reponse for this IP condition, decode condition and place in PCHAR buf
resp = pEchoReply->Status; // WSAGetLastError();
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, resp, 0, buf, BufSz, 0);
return resp;
}
_snprintf_s(buf, BufSz-1, _TRUNCATE, "%d", ((PICMP_ECHO_REPLY) ReplyBuffer)->RoundTripTime); // place roundtrip time in PCHAR buf (ASCII representation)
IcmpCloseHandle(hIcmpFile);
return 0; // we have a RT time in milliseconds associated with this IP, SUCCESS!
}
NET_DATA *NetData;
DWORD WINAPI tGetDATA(LPVOID NetData)
{
char buf[BUFSZ];
NET_DATA *m = NetData; // stupid me, I had allocated the space, instead of address of, not thinking it all disappears on exit
m->err_no = (*(m->func))(m->ip, buf, BUFSZ); // GetARP, GetNameInfos or GetICMP
if (_snprintf_s(m->data, m->dataSize-1, _TRUNCATE, "%s", buf) == -1) DEBUG_MSG("_snprintf_s error!");
// A resources error may have hit AFTER the calling function has returned, including having the thread/memory deallocated in the calling function
return 0;
}
MSEXPORT BSTR __stdcall ExcelRngNetData(UCHAR *list, ULONG *ErrNos, BSTR *DataArry, DWORD dwMilliseconds, char sep, char FunctType)
{ // take list of IP addresses (newline-separated), create thread for each to get network data. Return results in (sep-separated) BSTR.
int i=0, j, NumIPs=0, k = strlen(list), l=0;
#define NMSZ 100
char nm[NMSZ];
void* FuncAddr[3]; // DRY code hooks
FuncAddr[0] = &GetARP; FuncAddr[1] = &GetNameInfos; FuncAddr[2] = &GetICMP;
while (i<k && sscanf_s(list+i, "%[^\n]\n", nm, NMSZ)){i += strnlen_s(nm, NMSZ) + 1; NumIPs++;} // count newline-separated items before doing malloc(), because realloc() is REALLY resource intensive
NetData = malloc(NumIPs * sizeof(NET_DATA)); i = 0;
while (i<k && sscanf_s(list+i, "%[^\n]\n", nm, NMSZ)){ // load calling routines list into structures
j = strnlen_s(nm, NMSZ) + 1; i += j;
NetData[l].err_no = WAIT_TIMEOUT; // easy way to preset the error to a TIMEOUT, if the thread successfully completes before the timeout, this will be set to reflect its timeout
NetData[l].dataSize = BUFSZ;
NetData[l].func = FuncAddr[FunctType]; // DRY (Don't Repeat Yourself) code hook
if (strncpy_s(NetData[l].ip, (NetData[l].ipSize = BUFSZ), nm, j)) DEBUG_MSG("strcpy_s error!");
l++;
}
HANDLE *tHandles = malloc(NumIPs * sizeof(HANDLE)); DWORD ThreadId;
for (i=0; i<NumIPs; i++){
tHandles[i] = CreateThread(NULL, 0, tGetDATA, &(NetData[i]), 0, &ThreadId);
if (tHandles[i] == NULL) {DEBUG_MSG("Could not create threads!\nExiting now"); ExitProcess(3);}
}
if(WaitForMultipleObjects(NumIPs, tHandles, TRUE, dwMilliseconds) == WAIT_FAILED) {
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, GetLastError(), 0, dan, BUFSZ, 0); DEBUG_MSG(dan);
// Prolly means too many threads, kicked in when I exceeded 64; ERROR_INVALID_PARAMETER = "The parameter is incorrect"
}
#define CHUNK 1024
#define DATASZ 256 // tested with intentionally small size to check "safe" string functions
wchar_t wcs[DATASZ]; char MacChunk[DATASZ];
char *ans = malloc(CHUNK); int anslen = 0, anssz = CHUNK;
char separator[2]; separator[0] = sep; separator[1] = 0;
for(i=0; i<NumIPs; i++) { // build return BSTR and load array with data
CloseHandle(tHandles[i]); ErrNos[i] = NetData[i].err_no;
if (strncpy_s(MacChunk, DATASZ-1, NetData[i].err_no == 0 ? NetData[i].data : "", NetData[i].dataSize-1)) DEBUG_MSG("strcpy_s error!");
if (i<NumIPs-1 && sep != 0) if (strncat_s(MacChunk, DATASZ-1, separator, 1)) DEBUG_MSG("strcpy_s error!");
while (strnlen_s(MacChunk, DATASZ) > anssz - anslen -1) ans = realloc(ans, (anssz += CHUNK)); // choose CHUNK size to avoid constant realloc(), because realloc() is REALLY resource intensive
if (strncpy_s(&(ans[anslen]), DATASZ-1, MacChunk, DATASZ-1)) DEBUG_MSG("strcpy_s error!"); anslen += strnlen_s(MacChunk, DATASZ); // return data in returned BSTR
MultiByteToWideChar(CP_UTF8, 0,
ErrNos[i] == WAIT_TIMEOUT ? "The wait operation timed out." : NetData[i].data,
-1, wcs, DATASZ-1); // return data in supplied array
SysReAllocString(&DataArry[i], wcs);
}
BSTR r = SysAllocStringByteLen(ans, strlen(ans));
#ifdef NOMEMLEAK
free(NetData); free(tHandles); free(ans);
#endif
return r;
}

Get freeswitch events using ZMQ

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?

Capture a child process's stdout with libuv

I'm using libuv. I've read http://nikhilm.github.com/uvbook/processes.html and still cannot work out how to capture the stdout of a child process so that it is available in the parent (but not in place of the parent's stdin).
My code is currently:
#include <stdio.h>
#include <stdlib.h>
#include "../../libuv/include/uv.h"
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
uv_pipe_t apipe;
void on_child_exit(uv_process_t *req, int exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %d, signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req, NULL);
}
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) {
printf("alloc_buffer called\n");
uv_buf_t buf;
buf.base = malloc(len);
buf.len = len;
return buf;
}
void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
printf("read %li bytes from the child process\n", nread);
}
int main(int argc, char *argv[]) {
printf("spawn_test\n");
loop = uv_default_loop();
char* args[3];
args[0] = "dummy";
args[1] = NULL;
args[2] = NULL;
uv_pipe_init(loop, &apipe, 0);
uv_pipe_open(&apipe, 0);
options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_INHERIT_STREAM;
child_stdio[1].data.stream = (uv_stream_t *) &apipe;
child_stdio[2].flags = UV_IGNORE;
options.stdio = child_stdio;
options.exit_cb = on_child_exit;
options.file = args[0];
options.args = args;
uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe);
if (uv_spawn(loop, &child_req, options)) {
fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop)));
return 1;
}
return uv_run(loop, UV_RUN_DEFAULT);
}
dummy.c:
#include <unistd.h>
#include <stdio.h>
int main() {
printf("child starting\n");
sleep(1);
printf("child running\n");
sleep(2);
printf("child ending\n");
return 0;
}
I have the nagging feeling that I do not quite understand the point of libuv's pipes yet.
I've found the solution:
I had the wrong flags, they should have been UV_CREATE_PIPE | UV_READABLE_PIPE not UV_INHERIT_STREAM.
I needed to call uv_read_start after uv_spawn. I assume that there's no chance of data loss, as uv_run has not yet been called.
The above two fixes showed all the output from dummy to arriving at once, rather than in three lumps (as it does on the command line). An fflush in dummy.c fixed this.
spawn_test:
#include <stdio.h>
#include <stdlib.h>
#include "../../libuv/include/uv.h"
uv_loop_t *loop;
uv_process_t child_req;
uv_process_options_t options;
uv_pipe_t apipe;
void on_child_exit(uv_process_t *req, int exit_status, int term_signal) {
fprintf(stderr, "Process exited with status %d, signal %d\n", exit_status, term_signal);
uv_close((uv_handle_t*) req, NULL);
}
uv_buf_t alloc_buffer(uv_handle_t *handle, size_t len) {
printf("alloc_buffer called, requesting a %lu byte buffer\n");
uv_buf_t buf;
buf.base = malloc(len);
buf.len = len;
return buf;
}
void read_apipe(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) {
printf("read %li bytes in a %lu byte buffer\n", nread, buf.len);
if (nread + 1 > buf.len) return;
buf.base[nread] = '\0'; // turn it into a cstring
printf("read: |%s|", buf.base);
}
int main(int argc, char *argv[]) {
printf("spawn_test\n");
loop = uv_default_loop();
char* args[3];
args[0] = "dummy";
args[1] = NULL;
args[2] = NULL;
uv_pipe_init(loop, &apipe, 0);
uv_pipe_open(&apipe, 0);
options.stdio_count = 3;
uv_stdio_container_t child_stdio[3];
child_stdio[0].flags = UV_IGNORE;
child_stdio[1].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
child_stdio[1].data.stream = (uv_stream_t *) &apipe;
child_stdio[2].flags = UV_IGNORE;
options.stdio = child_stdio;
options.exit_cb = on_child_exit;
options.file = args[0];
options.args = args;
if (uv_spawn(loop, &child_req, options)) {
fprintf(stderr, "%s\n", uv_strerror(uv_last_error(loop)));
return 1;
}
uv_read_start((uv_stream_t*)&apipe, alloc_buffer, read_apipe);
return uv_run(loop, UV_RUN_DEFAULT);
}
dummy.c:
#include <unistd.h>
#include <stdio.h>
int main() {
printf("child starting\n");
fflush(stdout);
sleep(1);
printf("child running\n");
fflush(stdout);
sleep(2);
printf("child ending\n");
fflush(stdout);
return 0;
}
See how they do it in the libuv unit test libuv/test/test-stdio-over-pipes.c:
Don't call uv_pipe_open
Flags for child's stdin: UV_CREATE_PIPE | UV_READABLE_PIPE
Flags for child's stdout and stderr: UV_CREATE_PIPE | UV_WRITABLE_PIPE
There is also an issue on Windows, where uv_spawn might return zero even though it encountered an error, and in those cases, you need to check process.spawn_error, which only exists on Windows.

copy_to_user not working - where I am on mistake?

I am trying to get some message from kernel space to userspace, when a condition fails!
Here's my kernel code:
#define MESSAGTOUSER 1
int ret_val;
struct siginfo sinfo;
pid_t id;
struct task_struct *task;
unsigned char msgBuffer[20];
unsigned char buf1[20]= "HI";
static int major_no;
static struct class *safe_class;
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
static int device_open(struct inode *inode, struct file *file);
static int device_write(struct file *file, const char *gdata, size_t len, loff_t *off);
static int device_read(struct file *file, char *buf, size_t len, loff_t *off);
static int device_release(struct inode *inode, struct file *file);
int failureDetection (char* faultMsg) {
strcpy (msgBuffer, faultMsg);
printk(KERN_ALERT"\nMessage from HBM %s\n", msgBuffer);
printk(KERN_ALERT".......... RETURN VALUE ...... : %d", ret_val);
int Reg_Dev(void);
memset (&sinfo, 0, sizeof(struct siginfo));
sinfo.si_signo = SIGUSR1;
sinfo.si_code = SI_USER;
if (id == 0) {
printk("\ncan't find User PID: %d\n", id);
}else {
//task = pid_task(find_vpid(pid), PIDTYPE_PID);
task = find_task_by_vpid(id);
send_sig_info(SIGUSR1, &sinfo, task);
}
return 0;
}
static int device_open(struct inode *inode, struct file *file){
/*sucess*/
return 0;
}
void strPrint(void) {
printk("value of msgBuffer: %s", msgBuffer);
}
static int device_write(struct file *file, const char *gdata, size_t len, loff_t *off){
get_user (id,(int *)gdata);
if(id <0)
printk(KERN_ALERT"Cann't find PID from userspace its : %i", id);
else
printk(KERN_ALERT"Successfully received the PID of userspace %i", id);
return len;
}
static int
device_read(struct file *file, char *buf, size_t len, loff_t *off){
/*success*/
return 0;
}
static int device_release(struct inode *inode, struct file *file){
/*success*/
return 0;
}
static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
switch (cmd) {
case MESSAGTOUSER:
ret_val = copy_to_user((char *)arg, msgBuffer, sizeof(arg));
printk("Msg of Kernel %s", msgBuffer);
break;
default:
break;
}
return 0;
}
static struct file_operations fops = {
.open = device_open,
.write = device_write,
.read = device_read,
.release = device_release,
.unlocked_ioctl = device_ioctl
};
int Reg_Dev(void) {
major_no = register_chrdev(0, "safe_dev", &fops);
safe_class = class_create(THIS_MODULE, "safe_dev");
device_create(safe_class,NULL, MKDEV(major_no, 0), "safe_dev");
printk("\n Device Registered and Created \n");
return 0;
}
void UnReg_dev (void) {
printk("\nUser PID : %d\n", id);
unregister_chrdev(major_no, "safe_dev");
device_destroy(safe_class, MKDEV(major_no,0));
class_unregister(safe_class);
class_destroy(safe_class);
printk("\n Device Un-Registered and Destroyed \n");
}
extern int Reg_Dev(void);
for he userspace i have this code:
#define PORT 9930
#define G_IP "192.168.10.71"
#define BUFLEN 512
#define MESSAGTOUSER 0
unsigned char *str[20];
char b1[BUFLEN], b2[BUFLEN];
struct sockaddr_in me,client;
int s, i, n=sizeof(me);
int fd;
void error_handler(char *s) {
perror(s);
exit(1);
}
void signal_handler (int signum) {
if(signum == SIGUSR1)
{
printf("\n%s\n",str);
if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
error_handler("\nERROR: in Socket\n");
memset((char *) &me, 0, sizeof(me));
me.sin_family = AF_INET;
me.sin_port = PORT;
if (inet_aton(G_IP, &me.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
printf("Message from Kernel : %s", &str);
//strcpy (str, newStr);
int cntr =0; sprintf(b2, "\nFailure Message: %s\n",str);
printf("\nsending Fault to PMN Group : Tick - %d\n", cntr++);
if(sendto(s, str, sizeof(str),0,(struct sockaddr *) &me,n)==-1)
error_handler("\nERROR: in sendto()\n");
close (s);
// counter ++;
// sendAndReceiveOverUDP();
return;
}
}
int main() {
pid_t u_id;
u_id = getpid();
int i = 1;
fd = open("/dev/safe_dev",O_RDWR);
write(fd, &u_id, 4);
ioctl (fd, MESSAGTOUSER, &str);
printf("\n PID sent to device successfully: %d \n", u_id);
close(fd);
signal(SIGUSR1, signal_handler);
printf("\nMy PID is: %d\n",u_id);
//printf("Subnet 1 working fine.. Tick - %d", tv.tv_sec);
while (1)
sleep(1);
return 0;
}
Now what I am expecting to receive on Userspace:
Message from Kernel: A<->B
Sending Fault o PMN Group : tick - 0
Message from Kernel: B<->B
Sending Fault o PMN Group : tick - 1
....
...
but what is the output:
Message from Kernel:
Sending Fault o PMN Group : tick - 0
Message from Kernel:
Sending Fault o PMN Group : tick - 1
....
...
It seems that copy_to_user is not working, while in simple program just copying a string from kernel to user is working fine, but while i am using in this scenario then its not working, its compiling without any warning,
Some other Details:
failureDetection() is getting a string like A<->B mentioned in output from rest of the programs..
the same message from failureDetection is printing on kernel level but not transferring at the user level.
I have also tried to create an own string in this and tried to transfer that, but it is also not working! suppose msgBuffer = HI, then I should receive HI on to the userspace. but its not happening! can anyone please please make me correct whats wrong with this code? how can i get updates onto the userspace!!??
Sindhu..
The copy_to_user() only happens in response to the ioctl(), which only happens once, very early on in your code. Presumably at that point the kernel buffer msgBuffer is empty, because the failureDetection() function has not yet run at that point. It doesn't matter if failureDetection() runs later and sets msgBuffer then, because your userspace program never calls the ioctl() again so it doesn't see the new contents of msgBuffer.
You also have a bug in your copy_to_user() call - instead of sizeof(args) (which is a constant 4) you should probably use sizeof msgBuffer.
#caf: Thank you so much..
void signal_handler (int signum) {
if(signum == SIGUSR1)
{
fd = open ("/dev/safe_dev",O_RDWR);
ioctl (fd, MESSAGTOUSER, &str);
close (fd);
if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
error_handler("\nERROR: in Socket\n");
memset((char *) &me, 0, sizeof(me));
me.sin_family = AF_INET;
me.sin_port = PORT;
if (inet_aton(G_IP, &me.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
printf("Failure Detected on Eth Cards as : %s are non reachable.", str);
printf("\nsending Fault to PMN Group : Tick - %d\n", cntr++);
sprintf(b2, "\nFailure Message: %s\n",str);
if(sendto(s, str, sizeof(str),0,(struct sockaddr *) &me,n)==-1)
error_handler("\nERROR: in sendto()\n");
close (s);
return;
}
}
I was just making a stupid mistake.. hehehe.. i was not adding it in between file open and close block.. your suggestion resolved my issue...
Thank you so much for your response..
Rahee..

Resources