Error: cannot call constructor - c++

I have included new module to ns2 for evaluation of video transmission. I have make changes which are required to the some files like agent.h ,agent.cc, makefile and so on.
During make getting stuck with the error.
The error is:
myevalvid/myudp.cc: In member function ‘virtual void myUdpAgent::sendmsg(int, AppData*, const char*)’:
myevalvid/myudp.cc:56:123: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long unsigned int’ [-Wformat]
myevalvid/myudp.cc:78:123: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long unsigned int’ [-Wformat]
make: *** No rule to make target `myevalvid/myevalvid_sink.o ', needed by `ns'. Stop.
The code is
#include "myudp.h"
#include "rtp.h"
#include "random.h"
#include "address.h"
#include "ip.h"
static class myUdpAgentClass : public TclClass {
public:
myUdpAgentClass() : TclClass("Agent/myUDP") {}
TclObject* create(int, const char*const*) {
return (new myUdpAgent());
}
} class_myudp_agent;
myUdpAgent::myUdpAgent() : id_(0), openfile(0)
{
bind("packetSize_", &size_);
}
void myUdpAgent::sendmsg(int nbytes, AppData* data, const char* flags)
{
Packet *p;
int n;
char buf[100]; //added by smallko
if (size_)
n = nbytes / size_;
else
printf("Error: myUDP size = 0\n");
if (nbytes == -1) {
printf("Error: sendmsg() for UDP should not be -1\n");
return;
}
// If they are sending data, then it must fit within a single packet.
if (data && nbytes > size_) {
printf("Error: data greater than maximum myUDP packet size\n");
return;
}
double local_time = Scheduler::instance().clock();
while (n-- > 0) {
p = allocpkt();
hdr_cmn::access(p)->size() = size_;
hdr_rtp* rh = hdr_rtp::access(p);
rh->flags() = 0;
rh->seqno() = ++seqno_;
hdr_cmn::access(p)->timestamp() =
(u_int32_t)(SAMPLERATE*local_time);
hdr_cmn::access(p)->sendtime_ = local_time; // (smallko)
if(openfile!=0){
hdr_cmn::access(p)->frame_pkt_id_ = id_++;
sprintf(buf, "%-16f id %-16d udp %-16d\n", local_time, hdr_cmn::access(p)->frame_pkt_id_, hdr_cmn::access(p)->size()-28);
fwrite(buf, strlen(buf), 1, BWFile);
//printf("%-16f id %-16d udp %-16d\n", local_time, hdr_cmn::access(p)->frame_pkt_id_, hdr_cmn::access(p)->size()-28);
}
// add "beginning of talkspurt" labels (tcl/ex/test-rcvr.tcl)
if (flags && (0 ==strcmp(flags, "NEW_BURST")))
rh->flags() |= RTP_M;
p->setdata(data);
target_->recv(p);
}
n = nbytes % size_;
if (n > 0) {
p = allocpkt();
hdr_cmn::access(p)->size() = n;
hdr_rtp* rh = hdr_rtp::access(p);
rh->flags() = 0;
rh->seqno() = ++seqno_;
hdr_cmn::access(p)->timestamp() =
(u_int32_t)(SAMPLERATE*local_time);
hdr_cmn::access(p)->sendtime_ = local_time; // (smallko)
if(openfile!=0){
hdr_cmn::access(p)->frame_pkt_id_ = id_++;
sprintf(buf, "%-16f id %-16d udp %-16d\n", local_time, hdr_cmn::access(p)->frame_pkt_id_, hdr_cmn::access(p)->size()-28);
fwrite(buf, strlen(buf), 1, BWFile);
//printf("%-16f id %-16d udp %-16d\n", local_time, hdr_cmn::access(p)->frame_pkt_id_, hdr_cmn::access(p)->size()-28);
}
// add "beginning of talkspurt" labels (tcl/ex/test-rcvr.tcl)
if (flags && (0 == strcmp(flags, "NEW_BURST")))
rh->flags() |= RTP_M;
p->setdata(data);
target_->recv(p);
}
idle();
}
int myUdpAgent::command(int argc, const char*const* argv)
{
if(argc ==2) { //added by smallko
if (strcmp(argv[1], "closefile") == 0) {
if(openfile==1)
fclose(BWFile);
return (TCL_OK);
}
}
if (argc ==3) { //added by smallko
if (strcmp(argv[1], "set_filename") == 0) {
strcpy(BWfile, argv[2]);
BWFile = fopen(BWfile, "w");
openfile=1;
return (TCL_OK);
}
}
return (UdpAgent::command(argc, argv));
}
please help me to sort out the error.

As the error says, you can't call a constructor directly, as this line seems to be trying to do:
UdpAgent::UdpAgent();
You probably just want to remove that line. That constructor is already being called (implicitly) at the beginning of your constructor. You could put UdpAgent() at the start of the initialiser list, if you want to be explicit about it.

Related

I want to read the ML-NTC2 temperature sensor value through Arduino. But I get error: invalid conversion from'char*' to'const uint8_t*'

The arduino model name is wemos d1 mini and the board manager installed esp-8266. ML-NTC2 temperature sensor is Modbus 485 communication RTU method. Communication module is Esp-8266.
http://comfilewiki.co.kr/ko/doku.php?id=ml-ntc2:index
//Source file.ino//
#include <ML_NTC2.h> //
Includes a library for using the ML_NTC2 module.
void setup() {
NTC2_begin(&Serial3); //
Select the serial port to communicate with the ML_NTC2 module.
Serial.begin(57600);
}
void loop() {
// ML_NTC2 module #1 value is read.
float data_1 = NTC_readTemp(1,0);
float data_2 = NTC_readTemp(1,1);
delay(20);
// ML_NTC2 module #2 value is read.
float data_3 = NTC_readTemp(2,0);
float data_4 = NTC_readTemp(2,1);
char outputData[20];
Serial.printf(outputData,"%7s %7s",String(data_1).c_str(),String(data_2).c_str());
Serial.printf(outputData,"%7s %7s",String(data_3).c_str(),String(data_4).c_str());
delay(500); .
}
The following error occurs in the execution result
C:\Users\easy\Documents\Arduino\libraries\ML_NTC2\ML_NTC2.cpp: In function 'float NTC_readTemp(char, char)':
C:\Users\easy\Documents\Arduino\libraries\ML_NTC2\ML_NTC2.cpp:17:39: error: invalid conversion from 'char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]
short computeCrc = CRC::crc16(data,6);
^
In file included from C:\Users\easy\Documents\Arduino\libraries\ML_NTC2\ML_NTC2.cpp:2:0:
C:\Users\easy\Documents\Arduino\libraries\CRC/CRC.h:32:14: error: initializing argument 1 of 'uint16_t CRC::crc16(const uint8_t*, size_t)' [-fpermissive]
uint16_t crc16(const uint8_t* buff, size_t size)
^
C:\Users\easy\Documents\Arduino\libraries\ML_NTC2\ML_NTC2.cpp:23:35: error: invalid conversion from 'char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]
computeCrc = CRC::crc16(data,5);
^
In file included from C:\Users\easy\Documents\Arduino\libraries\ML_NTC2\ML_NTC2.cpp:2:0:
C:\Users\easy\Documents\Arduino\libraries\CRC/CRC.h:32:14: error: initializing argument 1 of 'uint16_t CRC::crc16(const uint8_t*, size_t)' [-fpermissive]
uint16_t crc16(const uint8_t* buff, size_t size)
^
exit status 1
Board WeMos D1 R1 Comfile error.
The code of the library used is as follows
CRC.H
#pragma once
#ifndef CRC_ARDUINO_H
#define CRC_ARDUINO_H
namespace CRC
{
uint8_t crc8(const uint8_t *buff, size_t size)
{
uint8_t* p = (uint8_t*)buff;
uint8_t result = 0xFF;
for (result = 0 ; size != 0 ; size--)
{
result ^= *p++;
for (size_t i = 0 ; i < 8; i++)
{
if (result & 0x80)
{
result <<= 1;
result ^= 0x85; // x8 + x7 + x2 + x0
}
else
{
result <<= 1;
}
}
}
return result;
}
uint16_t crc16(const uint8_t* buff, size_t size)
{
uint8_t* data = (uint8_t*)buff;
uint16_t result = 0xFFFF;
for (size_t i = 0; i < size; ++i)
{
result ^= data[i];
for (size_t j = 0; j < 8; ++j)
{
if (result & 0x01) result = (result >> 1) ^ 0xA001;
else result >>= 1;
}
}
return result;
}
}
#endif // CRC_ARDUINO_H
ML_NTC2.CPP
#include "ML_NTC2.h"
#include <CRC.h>
#define MAX_ULONG 4294967295UL
static HardwareSerial *comm;
void NTC2_begin(HardwareSerial *serial)
{
comm = serial;
comm->begin(57600);
}
float NTC_readTemp(char address,char channel)
{
char data[8] = {address,0x03,0x01,0xf4+channel,0x00,0x01,};
short computeCrc = CRC::crc16(data,6);
*(short*)&data[6] = computeCrc;
comm->write(data,8);
unsigned long old_time = millis();
unsigned long cur_time;
bool state_req = false;
do
{
if(comm->available() < 7)
{
cur_time = millis();
}
else
{
state_req = true;
break;
}
} while((MAX_ULONG-old_time+cur_time) % MAX_ULONG < 500);
if(state_req == true)
{
comm->readBytes(data,7);
computeCrc = CRC::crc16(data,5);
if(computeCrc == *(short*)&data[5])
{
short result = ((short)data[3] << 8) + data[4];
return result / 100.0f;
}
}
while(comm->available()) comm->read();
return -200.0f; // false.
}
ML_NTC.H
/*
* ML_NTC2.h
*
* Created on: 2019. 7. 3.
* Author: user
*/
#ifndef ML_NTC2_H_
#define ML_NTC2_H_
#ifndef Arduino_h
#include <Arduino.h>
#endif
void NTC2_begin(HardwareSerial *serial);
float NTC_readTemp(char address, char channel);
#endif /* ML_NTC2_H_ */
The chain in that the functions are called is
float NTC_readTemp(char address,char channel)
{
char data[8] = {address,0x03,0x01,0xf4+channel,0x00,0x01,}; // data is an array of char values
short computeCrc = CRC::crc16(data,6); // this array of char values is passed to the CRC check CRC::crc16
->
uint16_t crc16(const uint8_t* buff, size_t size)
{
uint8_t* data = (uint8_t*)buff; // but CRC::crc16 requires an const uint8_t pointer
...
}
The conversion from char* to a const uint8_t* is not possible, because of the const
If you wrote ML_NTC2.CPP and CRC.H you have to adapt this (the const definition is critical), else this a bug in the libraries
Try to change the critical in ML_NTC2.CPP into
short computeCrc = CRC::crc16((const uint8_t *)data,6);
to perform a typecast manually

error C2664: 'send' : cannot convert parameter 2 from 'ServerGreeting' to 'const char *'

I'm beginner on C++ and I'm porting a C code (TWAMP RFC5357) to a new project (IPSLA RFC 6812) and I facing this problem:
When I try to use the function send, I see the error "error C2664: 'send' : cannot convert parameter 2 from 'ServerGreeting' to 'const char *'" "No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called".
So, I searched about this and I found some answers that I didn't understood.
Here is a bit of the code:
typedef struct server_greeting
{
UINT8 Unused[12];
UINT32 Modes;
UINT8 Challenge[16];
UINT8 Salt[16];
UINT32 Count;
UINT8 MBZ[12];
} ServerGreeting;
struct active_session {
int socket;
// RequestSession req;
};
struct client_info {
int socket;
sockaddr_in addr;
int sess_no;
struct active_session sessions[MAX_SESSIONS_PER_CLIENT];
timeval shutdown_time;
};
static void cleanup_client (struct client_info *client)
{
fprintf (stderr,"Cleanup client %s\n", inet_ntoa(client->addr.sin_addr));
FD_CLR(client->socket,&read_fds);
closesocket(client->socket);
used_sockets--;
int i;
for (i = 0; i < client->sess_no; i++)
/* If socket is -1 the session has already been closed */
if (client->sessions[i].socket > 0) {
FD_CLR(client->sessions[i].socket, &read_fds);
closesocket(client->sessions[i].socket);
client->sessions[i].socket = -1;
used_sockets--;
}
memset(client, 0, sizeof(struct client_info));
//client->status = kOffline;
}
static int send_greeting(UINT8 mode_mask, struct client_info *client)
{
int socket = client->socket;
int i;
ServerGreeting greet;
memset(&greet, 0, sizeof(greet));
greet.Modes = 1 & mode_mask;
for (i = 0; i < 16; i++)
greet.Challenge[i] = rand() % 16;
for (i = 0; i < 16; i++)
greet.Salt[i] = rand() % 16;
greet.Count = (1 << 12);
int rv = send (socket, greet, sizeof(greet), 0);
if (rv < 0) {
fprintf(stderr, "[%s] ", inet_ntoa(client->addr.sin_addr));
perror("Failed to send ServerGreeting message");
cleanup_client(client);
} else {
printf("Sent ServerGreeting message to %s. Result %d\n",
inet_ntoa(client->addr.sin_addr), rv);
}
return rv;
}
Could you help me with this? Thanks
The send function takes as its second parameter a const char* pointer to a buffer, so you'd need to pass in the address of your struct with an appropriate cast,
int rv = send (socket, (const char*)&greet, sizeof(greet), 0);
The compiler tells you that it cannot perform the conversion from the struct you're trying to pass to the type of pointer it expects, you should believe it.

Issues with converting a constant char array to an unsigned char pointer

I have been working on a project and boy oh boy does my head hurt on this one. I am using a networking library called "enet" and I am trying to assign the client who connects information. Using the tutorial on the site, I use: server.event.packet->data = "client info"; However, enet complains that the string is not an "unsigned char *". Here is the build log (using clang++ to compile):
./network.h:9:14: warning: in-class initialization of non-static data member accepted as a C++11 extension
[-Wc++11-extensions]
int clients = 0;
^
main.cpp:142:28: error: assigning to 'enet_uint8 *' (aka 'unsigned char *') from incompatible type
'const char [12]';
server.event.packet->data = "client info";
^ ~~~~~~~~~~~~~
I have tried every type of casting I can think of and that I have searched for, but nothing seems to work. I can't make the darn thing happy.
Main.cpp:
#include <iostream>
#include <string>
#include <sstream>
#include <istream>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <stdio.h>
#include "network.h"
#include "clients.h"
#include "config.h"
void runCommand(std::string command);
int startNetwork();
void shutdownNetwork();
void addClientRecord();
std::string getUsername();
std::string username;
bool manualInput = false;
bool debug = true;
int iPeerCount = 0;
Server server;
int main(int argc, char ** argv){
std::string currentCommand;
if(manualInput==true){
std::cout << "Please type a command: ";
std::getline(std::cin,currentCommand);
if(debug == true){
std::cout << currentCommand << std::endl;
}
runCommand(currentCommand);
}
startNetwork();
atexit(shutdownNetwork);
return 0;
}
int startNetwork(){
if (enet_initialize () != 0){
std::cout << "\nAn error has occured while initializing ENet.\n";
return EXIT_FAILURE;
}
server.startServer();
return 1;
}
void shutdownNetwork(){
enet_deinitialize();
}
int Server::startServer(){
// server.serverOne = enet_host_create (& server.address, 32, 2, 0, 0);
// if(CUSTOM_HOST == true){
// enet_address_set_host(&address, HOST);
// } else {
server.address.host = ENET_HOST_ANY;
// }
server.address.port = PORT;
server.serverOne = enet_host_create( & server.address, 32, 2, 0, 0);
if(debug==true){
printf("[NETWORK] Host: %x \n[NETWORK] Port: %u\n", server.address.host, address.port);
}
if(server.serverOne==NULL){
std::cout << "\nAn error has occured while starting the ENet server.\n";
exit (EXIT_FAILURE);
}
monitor();
return 1;
}
void Server::monitor(){
int clients = 0;
if(debug==true){
printf( "[NETWORK] Waiting for commands...\n" );
}
printf("[NETWORK] Server online, awaiting commands and/or connections...\n");
scan_network:
while(enet_host_service (serverOne, & event, 1000) > 0){
switch(event.type){
case ENET_EVENT_TYPE_CONNECT:
clients++;
printf("[INFO] New connection from: %x:%u.\n", event.peer -> address.host, event.peer -> address.port);
addClientRecord();
/* for(int x=0;x<32;x++){
if(clients[x].name != ""){ }
else{
clients[x].name = "full";
}
}*/
break;
case ENET_EVENT_TYPE_RECEIVE:
if(debug==true){ printf("A packet of length %lu containing %s was received from %s on channel %u.\n", event.packet -> dataLength, event.packet -> data, event.peer -> data, event.channelID); }
runCommand(reinterpret_cast<const char*>(event.packet -> data));
enet_packet_destroy(event.packet);
/* printf("Disconnect client %s ? ", event.peer -> data);
gets(buffer);
std::cout<<buffer<<std::endl;
if(buffer=="yes"){
enet_peer_disconnect(event.peer, 0);
}*/ //Do not use until fixed or spam!
break;
case ENET_EVENT_TYPE_DISCONNECT:
clients--;
printf("%s disconnected.\n", event.peer -> data);
event.peer -> data = NULL;
case ENET_EVENT_TYPE_NONE:
break;
}
}
goto scan_network;
}
void runCommand(std::string command){
if((command == "disconnect") || (command == "Disconnect") || (command=="DISCONNECT")){
enet_peer_disconnect(server.event.peer,0);
printf("[INFO] Client %s issued the disconnect command.\n", server.event.peer -> data);
}
}
std::string getUsername(){
return username;
}
void addClientRecord(){
std::string bufferName = ("client " + server.clients);
server.event.packet->data = "client info";
}
Network.h:
#include <enet/enet.h>
class Server {
public:
ENetAddress address;
ENetHost * serverOne;
ENetEvent event;
int clients = 0;
int startServer();
void monitor();
};
Any ideas and help is appreciated greatly. Cheers!
As far as I can see server is a struct of type Server, its field event is ENetEvent, and its field packet is of type _ENetPacket* and its field data is a unsigned char*. So now what is hapening: you create a сstring on the stack, then assign address of the first element to the data field of global object, then you leave the function and pointer is still alive while data stored there is no longer avaliable. That is why you get segfault when using correct typecast to unsigned char*.
So you should do the following:
void addClientRecord()
{
std::string bufferName = ("client " + server.clients);
char* clientName = "client info";
// Allocate mem
char* data = new unsigned char[strlen(clientName)];
// Copy string there
strcpy(data, clientName);
// Store pointer
server.event.packet->data = (unsigned char*)data;
}
and do no not forget to clear that allocated mem. That is for you should always check if server.event.packet->data contains non-nullptr value and if it does - delete and only then assign. And you should provide a destructor for Server where it will delete that string if any present and constructor to write there a nullptr on start so you won't delete some trash address, which most certainly will lead to crash. But first of all you need to figure out whether _ENetPacket or ENetEvent classes provide any functionality for data mentioned above. This is how cstrings work.
P.S. There should be a compiler flag that will toggle char to be unsigned by default.

Boost, creating a thread that's creating a socket reader - Getting a compile error

I'm writing code for a gateway (aka router), using boost, C++, Codeblocks on a Linux device running Debian 7.1. I'm stuck with an annoying boost bind error and I simply cannot figure out what the problem is. I have been able to print out the MAC Header before I started creating threads
Here's a my code:
#include <errno.h>
#include <sys/ioctl.h>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <iostream>
#include <features.h>
#include <stdlib.h>
using namespace std;
int CreateRawSocket(int protocol_to_sniff)
{
int s;
if((s = socket(AF_PACKET, SOCK_RAW, htons(protocol_to_sniff))) == -1)
{
perror("Error creating raw socket");
exit(-1);
}
return s;
}
int BindRawSocketToInterface(char *device, int raw, int protocol)
{
struct sockaddr_ll sll;
struct ifreq ifr;
bzero(&sll, sizeof(sll));
bzero(&ifr, sizeof(ifr));
strncpy((char *)ifr.ifr_name, device, IFNAMSIZ);
if((ioctl(raw, SIOCGIFINDEX, &ifr)) == -1)
{
printf("Error getting interface index!\n");
exit(-1);
}
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(protocol);
if((bind(raw, (struct sockaddr *)&sll, sizeof(sll))) == -1)
{
perror("Error binding raw socket to interface\n");
exit(-1);
}
return 1;
}
int rawpacket_recv(int s, unsigned char *packet, int length)
{
int to_recv = 0;
to_recv = read(s, packet, length);
if(to_recv == -1)
{
perror("Error receiving packet");
exit(-1);
}
return to_recv;
}
int PrintPacketMACHdr(unsigned char *eth_packet)
{
unsigned char *ethhead;
int j;
ethhead = eth_packet;
printf("---Start of Ethernet header---");
printf("\nDestination address:\n");
for(j = 0; j < 6; j++)
{
printf("%02x:", *(ethhead+j)); //destination address (0 to 6 bit)
}
printf("\nSource address:\n");
for(j = 6; j < 12; j++)
{
printf("%02x:", *(ethhead+j)); //source address
}
printf("\nEther protocol number:\n");
for(j = 12; j < 14; j++)
{
printf("%02x", *(ethhead+j)); //protocol number
}
printf("\n---End of Ethernet header---\n");
if(*(ethhead + 12) == 8 && *(ethhead + 13) == 0)
{
return 1; //IP packet
}
if(*(ethhead + 12) == 8 && *(ethhead + 13) == 6)
{
return 2; //ARP packet
}
return 0;
}
int CreateAndBindSocket(int protocol_to_sniff, int *socket, char *interface)
{
int ethSocket = *socket; //eth1recv;
ethSocket = CreateRawSocket(protocol_to_sniff);
BindRawSocketToInterface(interface, ethSocket, ETH_P_ALL);
return ethSocket;
}
void RecvThread(int *socket) //thread function for receiving packets
{
int counter;
unsigned char *eth_buffer;
int eth_receiver;
int eth_socket = *socket
eth_buffer = (unsigned char *)malloc(ETH_P_ALL);
eth_receiver = rawpacket_recv(eth_socket, eth_buffer, ETH_P_ALL);
for(;;)
{
cout << "thread iteration " << ++counter << " Press Enter to stop" << endl;
try
{
//Sleep and check for interrupt();
//boost::this_thread::sleep(boost::posix_time::milliseconds(500));
usleep(50000);
PrintPacketMACHdr(eth_buffer);
}
catch(boost::thread_interrupted&)
{
cout << "Thread is stopped" << endl;
return;
}
}
}
int main(int argc, char **argv)
{
int eth0socket, eth1socket;
char eth0[] = "eth0";
char eth1[] = "eth1";
eth0socket = CreateAndBindSocket(ETH_P_ALL, &eth0socket, eth0);
eth1socket = CreateAndBindSocket(ETH_P_ALL, &eth1socket, eth1);
boost::thread eth0recvthread(RecvThread, &eth0socket); //instantiate thread in main
char ch;
cin.get(ch);
eth0recvthread.interrupt();
eth0recvthread.join();
return 0;
}
Right now I'm trying to create a thread that listens on one of the sockets and (for now) prints the MAC Header of the Ethernet frame. Later I will have to save the packet in some sort of array and then make another thread that handles the packets in this array. But as the headline says, I'm getting a boost error:
/home/thomas/Workspace/minisniffer/main.cpp||In function ‘void RecvThread(int)’:|
/home/thomas/Workspace/minisniffer/main.cpp|181|warning: variable ‘eth_receiver’ set but not used [-Wunused-but-set-variable]|
../../../../usr/local/boost_1_54_0/boost/bind/bind_template.hpp|20| required from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void; F = void (*)(int); L = boost::_bi::list1<boost::_bi::value<int*> >; boost::_bi::bind_t<R, F, L>::result_type = void]’|
../../../../usr/local/boost_1_54_0/boost/thread/detail/thread.hpp|117| required from ‘void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void, void (*)(int), boost::_bi::list1<boost::_bi::value<int*> > >]’|
/home/thomas/Workspace/minisniffer/main.cpp|306| required from here|
../../../../usr/local/boost_1_54_0/boost/bind/bind.hpp|253|error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]|
../../../../usr/local/boost_1_54_0/boost/system/error_code.hpp|222|warning: ‘boost::system::posix_category’ defined but not used [-Wunused-variable]|
../../../../usr/local/boost_1_54_0/boost/system/error_code.hpp|223|warning: ‘boost::system::errno_ecat’ defined but not used [-Wunused-variable]|
../../../../usr/local/boost_1_54_0/boost/system/error_code.hpp|224|warning: ‘boost::system::native_ecat’ defined but not used [-Wunused-variable]|
||=== Build finished: 4 errors, 4 warnings ===|
Tbh I have no idea what's failing, but then again I'm pretty new to C++ and Boost.
The creating and binding of sockets works just fine as they have been tested already, but the thread function RecvThread() is the one that fails me.
If someone has some idea to what I'm doing wrong (could easily be a pointer (*) or address (&) that is messing everything up) I would be so thankful!!
Thanks in advance!

Passing webM file as parameter in C++?

I'm trying to write a program that accepts a webM file (media) as a parameter, and then output the stream details via TTY in as much detail as possible. I figured I'd try to open the file in binary mode, but am not sure where to start.
Thanks for the help.
This sounds like a very high level question, so I'll answer it as such:
If you're creating a command line program in C/C++ that needs to accept parameters, look up how to use the 'argc' and 'argv' parameters to the main() function.
Once you have the parameter being passed into your main function, you will try to open it using some file reading library (there are several to choose from based on your needs and platform). Yes, you will want to open a WebM file in binary mode if the file library cares about the difference. If using fopen(), specify "rb" to read in binary mode-- this won't make any difference on Unix (vs. plain "r") but it will make a big difference on Windows.
From there, you can start reading bytes from the WebM file and processing them. Be advised that WebM is based on the Matroska multimedia format which is quite involved. If you are doing this as an academic exercise, more power to you. If you are looking to get something accomplished on a tight deadline, there are libraries you can call to do the heavy lifting of Matroska parsing on your behalf.
You can do this by making use of libwebm. The sample code is given below. It prints header, cluster, segments etc.
main.cpp
#include "stdio.h"
#include "stdlib.h"
#include "stdbool.h"
#include "string.h"
#include <memory>
#include <mkv/mkvreader.hpp>
#include <mkv/mkvparser.hpp>
#include <mkv/mkvparser.hpp>
#include "webm_parser.h"
static const wchar_t* utf8towcs(const char* str);
bool InputHasCues(const mkvparser::Segment* const segment);
using namespace mkvparser;
/**
* This file reads an webm file. Generates a new file with random number
* of packets in a single webm page.
*/
int webm_parse(int argc, char **argv)
{
int ret = -1;
char *file_out;
char *file_in;
FILE *fd_out = NULL;
MkvReader reader;
if(argc != 3)
{
printf("Usage: ./webm <input webm file> <output webm file>\n");
exit(0);
}
file_in = argv[1];
file_out = argv[2];
printf("\n\nInput webm file = %s , Output webm file = %s\n", file_in, file_out);
fd_out = fopen(file_out, "w+");
if(fd_out == NULL) goto on_error;
if(reader.Open(file_in))
{
printf("Error opening input file %s", file_in);
}
else
{
printf("Successfully opened input file %s\n", file_in);
}
webm_parse_header(&reader);
/** Return 0 on success */
printf("\n");
return ret;
on_error:
if(fd_out) fclose(fd_out);
printf("Error while parse/generate webm file\n");
/** Return -1 on failure */
return -1;
}
int webm_parse_header(void *reader)
{
int maj, min, build, rev;
long long pos = 0;
typedef mkvparser::Segment seg_t;
seg_t* pSegment_;
long long ret;
MkvReader *mkvrdr = (MkvReader *)reader;
EBMLHeader ebmlHeader;
GetVersion(maj, min, build, rev);
printf("libmkv verison: %d.%d.%d.%d\n", maj, min, build, rev);
ebmlHeader.Parse(mkvrdr, pos);
printf("\t\t\t EBML Header\n");
printf("\t\tEBML Version\t\t: %lld\n", ebmlHeader.m_version);
printf("\t\tEBML MaxIDLength\t: %lld\n", ebmlHeader.m_maxIdLength);
printf("\t\tEBML MaxSizeLength\t: %lld\n", ebmlHeader.m_maxSizeLength);
printf("\t\tDoc Type\t\t: %s\n", ebmlHeader.m_docType);
printf("\t\tPos\t\t\t: %lld\n", pos);
ret = seg_t::CreateInstance(mkvrdr, pos, pSegment_);
if (ret)
{
printf("Segment::CreateInstance() failed.\n");
return -1;
}
else
{
printf("Segment::CreateInstance() successful.\n");
}
const std::auto_ptr<seg_t> pSegment(pSegment_);
ret = pSegment->Load();
if (ret < 0)
{
printf("Segment::Load() failed.\n");
return -1;
}
else
{
printf("Segment::Load() successful.\n");
}
const SegmentInfo* const pSegmentInfo = pSegment->GetInfo();
const long long timeCodeScale = pSegmentInfo->GetTimeCodeScale();
const long long duration_ns = pSegmentInfo->GetDuration();
const char* const pTitle_ = pSegmentInfo->GetTitleAsUTF8();
const wchar_t* const pTitle = utf8towcs(pTitle_);
const char* const pMuxingApp_ = pSegmentInfo->GetMuxingAppAsUTF8();
const wchar_t* const pMuxingApp = utf8towcs(pMuxingApp_);
const char* const pWritingApp_ = pSegmentInfo->GetWritingAppAsUTF8();
const wchar_t* const pWritingApp = utf8towcs(pWritingApp_);
printf("\n");
printf("\t\t\t Segment Info\n");
printf("\t\tTimeCodeScale\t\t: %lld \n", timeCodeScale);
printf("\t\tDuration\t\t: %lld\n", duration_ns);
const double duration_sec = double(duration_ns) / 1000000000;
printf("\t\tDuration(secs)\t\t: %7.3lf\n", duration_sec);
if (pTitle == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls\n", pTitle);
delete[] pTitle;
}
if (pMuxingApp == NULL)
printf("\t\tMuxing App\t\t: NULL\n");
else
{
printf("\t\tMuxing App\t\t: %ls\n", pMuxingApp);
delete[] pMuxingApp;
}
if (pWritingApp == NULL)
printf("\t\tWriting App\t\t: NULL\n");
else
{
printf("\t\tWriting App\t\t: %ls\n", pWritingApp);
delete[] pWritingApp;
}
// pos of segment payload
printf("\t\tPosition(Segment)\t: %lld\n", pSegment->m_start);
// size of segment payload
printf("\t\tSize(Segment)\t\t: %lld\n", pSegment->m_size);
const mkvparser::Tracks* pTracks = pSegment->GetTracks();
unsigned long track_num = 0;
const unsigned long num_tracks = pTracks->GetTracksCount();
printf("\n\t\t\t Track Info\n");
while (track_num != num_tracks)
{
const Track* const pTrack = pTracks->GetTrackByIndex(track_num++);
if (pTrack == NULL)
continue;
const long trackType = pTrack->GetType();
const long trackNumber = pTrack->GetNumber();
const unsigned long long trackUid = pTrack->GetUid();
const wchar_t* const pTrackName = utf8towcs(pTrack->GetNameAsUTF8());
printf("\t\tTrack Type\t\t: %ld\n", trackType);
printf("\t\tTrack Number\t\t: %ld\n", trackNumber);
printf("\t\tTrack Uid\t\t: %lld\n", trackUid);
if (pTrackName == NULL)
printf("\t\tTrack Name\t\t: NULL\n");
else
{
printf("\t\tTrack Name\t\t: %ls \n", pTrackName);
delete[] pTrackName;
}
const char* const pCodecId = pTrack->GetCodecId();
if (pCodecId == NULL)
printf("\t\tCodec Id\t\t: NULL\n");
else
printf("\t\tCodec Id\t\t: %s\n", pCodecId);
const char* const pCodecName_ = pTrack->GetCodecNameAsUTF8();
const wchar_t* const pCodecName = utf8towcs(pCodecName_);
if (pCodecName == NULL)
printf("\t\tCodec Name\t\t: NULL\n");
else
{
printf("\t\tCodec Name\t\t: %ls\n", pCodecName);
delete[] pCodecName;
}
if (trackType == mkvparser::Track::kVideo)
{
const VideoTrack* const pVideoTrack =
static_cast<const VideoTrack*>(pTrack);
const long long width = pVideoTrack->GetWidth();
printf("\t\tVideo Width\t\t: %lld\n", width);
const long long height = pVideoTrack->GetHeight();
printf("\t\tVideo Height\t\t: %lld\n", height);
const double rate = pVideoTrack->GetFrameRate();
printf("\t\tVideo Rate\t\t: %f\n", rate);
}
if (trackType == mkvparser::Track::kAudio)
{
const AudioTrack* const pAudioTrack =
static_cast<const AudioTrack*>(pTrack);
const long long channels = pAudioTrack->GetChannels();
printf("\t\tAudio Channels\t\t: %lld\n", channels);
const long long bitDepth = pAudioTrack->GetBitDepth();
printf("\t\tAudio BitDepth\t\t: %lld\n", bitDepth);
const double sampleRate = pAudioTrack->GetSamplingRate();
printf("\t\tAddio Sample Rate\t: %.3f\n", sampleRate);
const long long codecDelay = pAudioTrack->GetCodecDelay();
printf("\t\tAudio Codec Delay\t: %lld\n", codecDelay);
const long long seekPreRoll = pAudioTrack->GetSeekPreRoll();
printf("\t\tAudio Seek Pre Roll\t: %lld\n", seekPreRoll);
}
}
printf("\n\n\t\t\t Cluster Info\n");
const unsigned long clusterCount = pSegment->GetCount();
printf("\t\tCluster Count\t: %ld\n\n", clusterCount);
if (clusterCount == 0)
{
printf("\t\tSegment has no clusters.\n");
return -1;
}
const mkvparser::Cluster* pCluster = pSegment->GetFirst();
while ((pCluster != NULL) && !pCluster->EOS())
{
const long long timeCode = pCluster->GetTimeCode();
printf("\t\tCluster Time Code\t: %lld\n", timeCode);
const long long time_ns = pCluster->GetTime();
printf("\t\tCluster Time (ns)\t: %lld\n", time_ns);
const BlockEntry* pBlockEntry;
long status = pCluster->GetFirst(pBlockEntry);
if (status < 0) // error
{
printf("\t\tError parsing first block of cluster\n");
fflush(stdout);
return -1;
}
while ((pBlockEntry != NULL) && !pBlockEntry->EOS())
{
const Block* const pBlock = pBlockEntry->GetBlock();
const long long trackNum = pBlock->GetTrackNumber();
const unsigned long tn = static_cast<unsigned long>(trackNum);
const Track* const pTrack = pTracks->GetTrackByNumber(tn);
if (pTrack == NULL)
printf("\t\t\tBlock\t\t:UNKNOWN TRACK TYPE\n");
else
{
const long long trackType = pTrack->GetType();
const int frameCount = pBlock->GetFrameCount();
const long long time_ns = pBlock->GetTime(pCluster);
const long long discard_padding = pBlock->GetDiscardPadding();
printf("\t\t\tBlock\t\t:%s,%s,%15lld,%lld\n",
(trackType == mkvparser::Track::kVideo) ? "V" : "A",
pBlock->IsKey() ? "I" : "P", time_ns, discard_padding);
for (int i = 0; i < frameCount; ++i)
{
const Block::Frame& theFrame = pBlock->GetFrame(i);
const long size = theFrame.len;
const long long offset = theFrame.pos;
printf("\t\t\t %15ld,%15llx\n", size, offset);
}
}
status = pCluster->GetNext(pBlockEntry, pBlockEntry);
if (status < 0)
{
printf("\t\t\tError parsing next block of cluster\n");
fflush(stdout);
return -1;
}
}
pCluster = pSegment->GetNext(pCluster);
}
if (InputHasCues(pSegment.get()))
{
// Walk them.
const mkvparser::Cues* const cues = pSegment->GetCues();
const mkvparser::CuePoint* cue = cues->GetFirst();
int cue_point_num = 1;
printf("\t\tCues\n");
do
{
for (track_num = 0; track_num < num_tracks; ++track_num)
{
const mkvparser::Track* const track =
pTracks->GetTrackByIndex(track_num);
const mkvparser::CuePoint::TrackPosition* const track_pos =
cue->Find(track);
if (track_pos != NULL)
{
const char track_type =
(track->GetType() == mkvparser::Track::kVideo) ? 'V' : 'A';
printf(
"\t\t\tCue Point %4d Track %3lu(%c) Time %14lld "
"Block %4lld Pos %8llx\n",
cue_point_num, track->GetNumber(), track_type,
cue->GetTime(pSegment.get()), track_pos->m_block,
track_pos->m_pos);
}
}
cue = cues->GetNext(cue);
++cue_point_num;
} while (cue != NULL);
}
const mkvparser::Tags* const tags = pSegment->GetTags();
if (tags && tags->GetTagCount() > 0)
{
printf("\t\tTags\n");
for (int i = 0; i < tags->GetTagCount(); ++i)
{
const mkvparser::Tags::Tag* const tag = tags->GetTag(i);
printf("\t\t\tTag\n");
for (int j = 0; j < tag->GetSimpleTagCount(); j++)
{
const mkvparser::Tags::SimpleTag* const simple_tag =
tag->GetSimpleTag(j);
printf("\t\t\t\tSimple Tag \"%s\" Value \"%s\"\n",
simple_tag->GetTagName(), simple_tag->GetTagString());
}
}
}
fflush(stdout);
return 0;
on_error:
return -1;
}
static const wchar_t* utf8towcs(const char* str)
{
if (str == NULL)
return NULL;
// TODO: this probably requires that the locale be
// configured somehow:
const size_t size = mbstowcs(NULL, str, 0);
if (size == 0)
return NULL;
wchar_t* const val = new wchar_t[size + 1];
mbstowcs(val, str, size);
val[size] = L'\0';
return val;
}
bool InputHasCues(const mkvparser::Segment* const segment)
{
const mkvparser::Cues* const cues = segment->GetCues();
if (cues == NULL)
return false;
while (!cues->DoneParsing())
cues->LoadCuePoint();
const mkvparser::CuePoint* const cue_point = cues->GetFirst();
if (cue_point == NULL)
return false;
return true;
}