iNotify multiple read - c++

I use the following code to monitor a file using I notify. I first poll and then read if there is a change to prevent blocking:
int settingsCheck(int &length, int &i, char * buffer, int &fd, string setRead[])
{
int f_change = 0;
struct pollfd pfd = { fd, POLLIN, 0 };
/* Poll with a timeout of 100ms */
int ret = poll(&pfd, 1, 100);
/* Check to see the result of the poll */
if (ret < 0) {
fprintf(stderr, "Poll failed: %s\n", strerror(errno));
}
else if (ret == 0) {
/* Timeout with no events -> move on */
}
else {
/* Process the new event */
struct inotify_event event;
length = read(fd, buffer, BUF_LEN);
printf("read\n");
while (i < length)
{
struct inotify_event *event = (struct inotify_event *) &buffer[i];
if (event->len)
{
if (event->mask & IN_MODIFY && event->name == "setitngs.txt")
{
printf("The file %s was modified.\n", event->name);
//f_change = 1;
}
else if(event->mask & IN_MODIFY)
{
printf("Not settings\n");
}
}
i += EVENT_SIZE + event->len;
}
readSettings(setRead);
return 1;
}
return 0;
}
When I modify the text file being monitored (which is modified by a php script), my program reads the file multiple times (2-4), sometimes only reading the correct data on the final read.
Does anyone know why this happens / how to fix it?
PS: I am correct in saying that if I call the readSettings() function inside the following if:
if (event->mask & IN_MODIFY && event->name == "setitngs.txt")
then readSettings() should be called only once when "settings.txt" is monitored?

Related

Unable to read all messages sent from client

I want to read all messages that are sent from the client.
I am implementing a tcp server and it receives data. Each message is appended by the size of the message as a header. So Now I can read the header and find the size from that and allocate that much memory for the message to be read later. However, with my very little exposure to C++ this is what I came up with.
How to read all messages ?
void *dothistask(void *socket_desc)
{
int sock = *(int*)socket_desc;
free(socket_desc);
int read_size;
unsigned int x = 4;
char *header = (char*)malloc(sizeof(char) * 4);
char *message;
int index = 0;
long p;
int status;
while(true) {
status = ReadXBytes(sock, 4, header);
if(status == -1)
{
break;
}
message = (char *)malloc(sizeof(char) * 10);
status = ReadXBytes(sock, 10, message);
if(status == -1)
{
break;
}
cout<<"The header is "<<header<<endl;
cout<<"The message is "<<message<<endl;
}
return 0;
}
int ReadXBytes(int socket, unsigned int x, void* buff)
{
char *buffer = (char*)buff;
int bytesRead = 0;
int result;
while (bytesRead < x)
{
result = recv(socket, buffer + bytesRead, x - bytesRead, 0);
if(result == 0)
{
cout<<"Client disconnected"<<endl;
fflush(stdout);
return -1;
}
else if( result == -1)
{
perror("recv failed");
return -1;
}
bytesRead += result;
}
return 0;
}
Read that it is ideal to read the header first and then read the message. I am able to do this once but I want to do this over a repeated period of time, basically forever, till the client disconnects.
Thank you! for the help!
To read the message, you have
ReadXBytes(sock, 10, message);
but it should be something like
ReadXBytes(sock, *((int*)header), message);
depending on the content of header. As you have a hard-coded 10 in there, you will only ever read 10 bytes. You will also have to adjust the malloc accordingly to not only allocate 10 bytes.

How to set up ffmpeg options for HLS?

I have a streaming device that streams mpegts video and audio. I am trying to capture those streams and save them multiple .ts file using HLS of ffmpeg.
So, I have been successful in capturing and saving the streams in a single .ts file. It seems like when I send the output file to be .m3u8, ffmpeg automatically chooses hls demuxer. But, doing so I get a floating point exception.
Here is my simple code...
static int ipcam_streaming_main_configure_input_parameters(const char *p_ifilename, AVFormatContext **ppx_ifmt_ctx)
{
AVStream *px_istream = NULL;
AVCodecContext *px_icodec_ctx = NULL;
int ret = -1;
unsigned int i = 0;
enum AVCodecID input_codec_id = AV_CODEC_ID_NONE;
AVCodec *p_decoder = NULL;
if (avformat_open_input(ppx_ifmt_ctx, p_ifilename, NULL, NULL) < 0)
{
printf("%s(): avformat_open_input() failed\n", __FUNCTION__);
}
else if (avformat_find_stream_info(*ppx_ifmt_ctx, NULL) < 0)
{
printf("%s(): avformat_find_stream_info() failed\n", __FUNCTION__);
}
else
{
/* find the input streams to be remuxed */
for (i = 0; i < (*ppx_ifmt_ctx)->nb_streams; i++)
{
/* get the stream, codec context for the stream */
px_istream = (*ppx_ifmt_ctx)->streams[i];
px_icodec_ctx = px_istream->codec;
if ((AVMEDIA_TYPE_VIDEO == px_icodec_ctx->codec_type)
|| (AVMEDIA_TYPE_AUDIO == px_icodec_ctx->codec_type))
{
/* get the codec_id for the audio/video stream */
input_codec_id = px_icodec_ctx->codec_id;
/* get the decoder for the input codec id */
p_decoder = avcodec_find_decoder(px_icodec_ctx->codec_id);
/* Open decoder for the input codec audio/video */
ret = avcodec_open2(px_icodec_ctx,
p_decoder,
NULL);
if (ret < 0)
{
printf("%s(): avcodec_open2() failed\n", __FUNCTION__);
}
else
{
printf("Input stream type <%d> with codec_id <%d> found and decoder opened\n", px_icodec_ctx->codec_type, input_codec_id);
}
}
}
}
/* dump the data into stdout */
av_dump_format(*ppx_ifmt_ctx, 0, p_ifilename, 0);
return ret;
}
static int ipcam_streaming_main_configure_output_parameters(const char *p_ofilename,
AVFormatContext *px_ifmt_ctx,
AVFormatContext **ppx_ofmt_ctx)
{
AVStream *px_ostream = NULL;
AVStream *px_istream = NULL;
AVCodecContext *px_dec_ctx = NULL;
AVCodecContext *px_enc_ctx = NULL;
int ret = -1;
unsigned int i = 0;
if ((NULL == p_ofilename) || (NULL == px_ifmt_ctx) || (NULL == ppx_ofmt_ctx))
{
printf("%s(): NULL arg(s) <%p, %p, %p>", __FUNCTION__, p_ofilename, px_ifmt_ctx, ppx_ofmt_ctx);
return -1;
}
/* remove the output file if already exists */
remove(p_ofilename);
/* allocate the output format context */
if (avformat_alloc_output_context2(ppx_ofmt_ctx, NULL, NULL, p_ofilename) < 0)
{
printf("%s(): avformat_alloc_output_context2() failed\n", __FUNCTION__);
}
else
{
for (i = 0; i < px_ifmt_ctx->nb_streams; i++)
{
if ((AVMEDIA_TYPE_VIDEO == px_ifmt_ctx->streams[i]->codec->codec_type)
|| (AVMEDIA_TYPE_AUDIO == px_ifmt_ctx->streams[i]->codec->codec_type))
{
printf("Stream <%d> is type <%d>: Adding to output stream\n", i, px_ifmt_ctx->streams[i]->codec->codec_type);
/* create a new output stream */
px_ostream = avformat_new_stream(*ppx_ofmt_ctx, NULL);
if (NULL == px_ostream)
{
printf("%s(): avformat_new_stream() failed\n", __FUNCTION__);
}
else
{
px_istream = px_ifmt_ctx->streams[i];
px_dec_ctx = px_istream->codec;
px_enc_ctx = px_ostream->codec;
/* Since, we do not need to encode the video stream, it is just remuxing
just copying the input codec context to output is sufficient */
ret = avcodec_copy_context((*ppx_ofmt_ctx)->streams[i]->codec,
px_ifmt_ctx->streams[i]->codec);
if ((*ppx_ofmt_ctx)->oformat->flags & AVFMT_GLOBALHEADER)
{
px_enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
}
}
else
{
printf("Stream <%d> is Unknown: Ignore it \n", i);
}
}
/* dump the output media file into stdout */
av_dump_format(*ppx_ofmt_ctx, 0, p_ofilename, 1);
if (0 == ((*ppx_ofmt_ctx)->oformat->flags & AVFMT_NOFILE))
{
/* open the output media file so that we can write the data into it */
ret = avio_open(&(*ppx_ofmt_ctx)->pb, p_ofilename, AVIO_FLAG_WRITE);
if (ret < 0)
{
printf("%s(): avio_open() failed\n", __FUNCTION__);
}
else
{
/* init muxer, write output file header */
ret = avformat_write_header((*ppx_ofmt_ctx), NULL);
if (ret < 0)
{
printf("%s(): avformat_write_header() failed\n", __FUNCTION__);
}
}
}
}
return ret;
}
int main(int argnum, char **argv)
{
AVFormatContext *px_ifmt_ctx = NULL;
AVFormatContext *px_ofmt_ctx = NULL;
AVPacket packet = {0};
enum AVMediaType type = AVMEDIA_TYPE_UNKNOWN;
unsigned int stream_index = -1;
unsigned int i = 0;
int ret = -1;
if (argnum != 3)
{
printf("Please enough number of parameters\n");
return -1;
}
/* register all the services requred */
av_register_all();
avformat_network_init();
if (0 != ipcam_streaming_main_configure_input_parameters(argv[1],
&px_ifmt_ctx))
{
printf("%s(): ipcam_streaming_main_configure_iput_parameters() failed\n", __FUNCTION__);
}
else if (0 != ipcam_streaming_main_configure_output_parameters(argv[2],
px_ifmt_ctx,
&px_ofmt_ctx))
{
printf("%s(): ipcam_streaming_main_configure_output_parameters() failed\n", __FUNCTION__);
}
else
{
printf("Input and output configuration done successfully: Now reading packets\n");
while (true)
{
if ((ret = av_read_frame(px_ifmt_ctx, &packet)) < 0)
{
printf("av_read_frame() failed with error <%d>: Exit\n", ret);
break;
}
/* get the stream index and codec type of the packet read */
stream_index = packet.stream_index;
type = px_ifmt_ctx->streams[stream_index]->codec->codec_type;
/* remux only if the type is video, otherwise ignore it */
if ((AVMEDIA_TYPE_VIDEO == type)
|| (AVMEDIA_TYPE_AUDIO == type))
{
printf("Remuxing the stream type <%d>, frame with stream index <%d>\n", type, stream_index);
/* remux this frame without reencoding */
packet.dts = av_rescale_q_rnd(packet.dts,
px_ifmt_ctx->streams[stream_index]->time_base,
px_ofmt_ctx->streams[stream_index]->time_base,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
packet.pts = av_rescale_q_rnd(packet.pts,
px_ifmt_ctx->streams[stream_index]->time_base,
px_ofmt_ctx->streams[stream_index]->time_base,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
/* write the frame into the output media file */
ret = av_write_frame(px_ofmt_ctx, &packet);
if (ret < 0)
{
printf("Ignoring video packet stream index <%d>\n", packet.stream_index);
}
/* free the packet for next use */
av_free_packet(&packet);
}
else
{
printf("Ignoring stream index <%d>, type <%d>\n", packet.stream_index, type);
}
}
}
/* write the trailer */
av_write_trailer(px_ofmt_ctx);
av_free_packet(&packet);
for (i = 0; i < px_ifmt_ctx->nb_streams; i++)
{
/* close the input codec that has been opened */
avcodec_close(px_ifmt_ctx->streams[i]->codec);
if ((NULL != px_ofmt_ctx) && (px_ofmt_ctx->nb_streams > i) &&
(NULL != px_ofmt_ctx->streams[i]) && ( NULL != px_ofmt_ctx->streams[i]->codec))
{
/* close the output code */
avcodec_close(px_ofmt_ctx->streams[i]->codec);
}
}
/* close the input */
avformat_close_input(&px_ifmt_ctx);
if ((NULL != px_ofmt_ctx) && (0 == (px_ofmt_ctx->oformat->flags & AVFMT_NOFILE)))
{
/* close the output context */
avio_close(px_ofmt_ctx->pb);
}
/* free the output context */
avformat_free_context(px_ofmt_ctx);
return ret;
}
So, If i pass the output filename to be .m3u8 file, it gives a floating point exception.

Handle many Gpio Interruptions C++ Linux

I have an interruptions problem. I am working in an application which has to handle many buttons by interruptions. I am using this program to handle one:
int main(){
gpio_export(gpio);
gpio_set_dir(gpio, 0);
gpio_set_edge(gpio, "falling");
gpio_fd = gpio_fd_open(gpio);
timeout = POLL_TIMEOUT;
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
rc = poll(fdset, nfds, timeout);
if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0) {
printf(".");
}
if (fdset[1].revents & POLLPRI) {
len = read(fdset[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio);
}
if (fdset[0].revents & POLLIN) {
(void)read(fdset[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
fflush(stdout);
}
gpio_fd_close(gpio_fd);
gpio_fd_close(gpio_fd2);
return 0;
}
It is working perfectly, my problem is that what I want to do is handle more interruptions so what I tried is this:
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = STDIN_FILENO;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
rc = poll(fdset, nfds, timeout);
memset((void*)fdset2, 0, sizeof(fdset2));
fdset2[0].fd = STDIN_FILENO;
fdset2[0].events = POLLIN;
fdset2[1].fd = gpio_fd2;
fdset2[1].events = POLLPRI;
rc2 = poll(fdset2, nfds, timeout);
if (rc < 0 || rc2 < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0 || rc2==0) {
printf(".");
}
if (fdset[1].revents & POLLPRI) {
len = read(fdset[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio);
}
if (fdset2[1].revents & POLLPRI) {
len = read(fdset2[1].fd, buf, MAX_BUF);
printf("\npoll() GPIO %d interrupt occurred\n", gpio2);
}
if (fdset[0].revents & POLLIN) {
(void)read(fdset[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
if (fdset2[0].revents & POLLIN) {
(void)read(fdset2[0].fd, buf, 1);
printf("POLLIN");
//printf("\npoll() stdin read 0x%2.2X\n", (unsigned int) buf[0]);
}
fflush(stdout);
}
gpio_fd_close(gpio_fd);
gpio_fd_close(gpio_fd2);
return 0;
}
Basically I tried to handle two interruptions in the same program, but when I push any button nothing happend. What can I do that? shall I use threads?
Thank you guys
You have to merge fdset-s before you call poll. Basically the program waits at first poll call instead of waiting on first and second in parralel. So you can use threads or call one poll for all fdset-s and once.

Sniffing an ethernet interface on linux

I am trying to capture only packets from a specific interface and instead I am getting packets from all of the interfaces. what am I doing wrong?
bool Snooper::raw_init (const char *device)
{
uid_t privid = geteuid();
int retval;
bool retVal = false;
do {
if ((retval = setuid(0)) != 0) {
perror("seteuid error");
break;
}
cap_t caps = cap_get_proc();
cap_value_t cap_list[2];
cap_list[0] = CAP_NET_RAW;
cap_list[1] = CAP_SETUID;
if ((retval = cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET)) == -1) {
perror("cap_set_flag error");
break;
}
if ((retval = cap_set_proc(caps)) == -1) {
perror("cap_set_proc error");
break;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof (struct ifreq));
/* Open A Raw Socket */
if ((m_sockfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 1) {
perror("Snooper::raw_init:socket Error");
break;
}
/* Set the device to use */
strncpy(ifr.ifr_name, device, strlen(device) + 1);
/* Get the current flags that the device might have */
if (ioctl(m_sockfd, SIOCGIFFLAGS, &ifr) == -1) {
perror("Error: Could not retrieve the flags from the device.\n");
break;
}
printf("The interface is ::: %s\n", device);
perror("Retrieved flags from interface successfully");
/* Set the old flags plus the IFF_PROMISC flag */
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(m_sockfd, SIOCSIFFLAGS, &ifr) == -1) {
perror("Error: Could not set flag IFF_PROMISC");
break;
}
printf("Setting interface ::: %s ::: to promisc\n", device);
/* Configure the device */
if (ioctl(m_sockfd, SIOCGIFINDEX, &ifr) < 0) {
perror("Error: Error getting the device index.\n");
break;
}
retVal = true;
} while(false);
if ((retval = seteuid(privid)) != 0) {
perror("seteuid error");
}
return retVal;
}
I first validate that I can suid to root since IFF_PROMISC requires it. Then create the socket for UDP traffic, preform the IOCtl for the device, and finally IOCtl for PROMISC.
Now that I have a socket ready I loop on a recv, however I get packets from the other interfaces as well.
To capture packets from a specific interface, you have to bind your socket to that interface using bind function. You can check out this answer for an example.
A small pcap Program that might be able to help You
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pcap/pcap.h>
#include<netinet/if_ether.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
void process_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *buffer)
{
// printf("In Process_Packet\n");
struct ethhdr *eth = (struct ethhdr *)(buffer);
printf("%.2x: %.2x: %.2x: %.2x: %.2x: %.2x: %.2x:\n ", eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], eth->h_dest[3], eth->h_dest[4], eth->h_dest[5], eth->h_dest[6]);
printf("%x \n", htons(eth->h_proto));
if(htons(eth->h_proto)== ETHERTYPE_ARP)
{
printf("ARP PACKET\n");
}
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
int ipheader = iph-> ihl *4;
printf("Source IP Address :%s\n ", inet_ntoa(iph->saddr));
printf("Destination IP Address :%s\n ", inet_ntoa(iph->daddr));
}
int main()
{
pcap_if_t *alldevspec,*devices;
pcap_addr_t *a;
pcap_t *handle;
const char filter_exp[]="IP";
bpf_u_int32 netp;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
int ret=0, count =1, n=0;
char devs[100][100],*devicename;
ret = pcap_findalldevs(&alldevspec,errbuf);
if(ret < 0)
{
printf("Error in finding the devices\n");
return -1;
}
for(devices = alldevspec; devices!= NULL; devices = devices->next)
{
printf("%d %s-%s \n",count, devices->name,devices->description);
for(a=devices->addresses;a;a=a->next)
{
printf("family %d \n", (a->addr)->sa_family);
if(devices->name != NULL)
{
strcpy(devs[count], devices->name);
}
switch((a->addr)->sa_family)
{
case AF_INET:
printf("%s \n",inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr.s_addr));
break;
case AF_INET6:
break;
}
}
++count;
}
printf("Enter the device u want to select\n");
scanf("%d",&n);
devicename = devs[n];
handle = pcap_open_live(devicename,65536,1,-1,errbuf);
if(handle == NULL)
{
printf("Error in opening the device\n");
return -1;
}
pcap_compile(handle,&fp, filter_exp,-1,netp);
pcap_setfilter(handle, &fp);
pcap_loop(handle,-1,process_packet,NULL);
return 0;
}

Expected token error in file RecvFile function

I'm learning some examples about C++ socket. One of the code here has an error : "expect token while got fclose" at the line above the last line
The code seems fine with me, so I can't figure out what is wrong here.
Any ideas are appreciated.
void RecvFile(int sock, const char* filename)
{
int rval;
char buf[0x1000];
FILE *file = fopen(filename, "wb");
if (!file)
{
printf("Can't open file for writing");
return;
}
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
}
fclose(file);
}
You have a do with no corresponding while:
do
{
// ...
do
{
// ...
}
while (off < rval);
}
// No while here
fclose(file);
It appears that it should just be while (true), which you might as well just stick at the top, instead of doing a do while. Execution will break from the loop if recv returns 0 or less, which indicate an orderly shutdown and an error respectively. So change it to:
while (true)
{
// ...
do
{
// ...
}
while (off < rval);
}
fclose(file);
You have a do statement without a corresponding while:
do // <== THERE IS NO CORRESPONDING while FOR THIS do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// ...
}
// ...
do
{
// ...
}
while (off < rval); // <== This is OK: the "do" has a matching "while"
}
// Nothing here! Should have a "while (condition)"
If you just want to repeat your loop indefinitely, then you should use while (true) - either replacing the do keyword (preferably), or adding it where the missing while should go (as indicated by the above comments).
You started a do without actually supplying a while();
do
{
rval = recv(sock, buf, sizeof(buf), 0);
if (rval < 0)
{
// if the socket is non-blocking, then check
// the socket error for WSAEWOULDBLOCK/EAGAIN
// (depending on platform) and if true then
// use select() to wait for a small period of
// time to see if the socket becomes readable
// again before failing the transfer...
printf("Can't read from socket");
fclose(file);
return;
}
if (rval == 0)
break;
int off = 0;
do
{
int written = fwrite(&buf[off], 1, rval - off, file);
if (written < 1)
{
printf("Can't write to file");
fclose(file);
return;
}
off += written;
}
while (off < rval);
} //while() Needs to go here
fclose(file);