I have written program to work like a telephone operator for TCP clients.
A TCP client connects to the server, and then gives a channel name to the server.
If another TCP client connect to the server and give the same channel name, the server connects the 2 TCP clients together, allowing them to talk to each other without interference.
When I compile this on Mac, it works fine, but when I put it on a digital ocean droplet, I get this error during compilation. I have generated the makefile using netbeans.
This is StreamSwitch.h
#ifndef STREAMSWITCH_H
#define STREAMSWITCH_H
#include <string>
#include <sstream>
#include <iostream>
#include <list>
using namespace std;
struct Comparator{
int length;
uint8_t *pointer;
};
class DiscriptorNode{
public:
int FileDiscriptor;
uint8_t ChannelName[1000];
bool operator == (const DiscriptorNode& s) const { return (this->FileDiscriptor) == (s.FileDiscriptor); }
bool operator == (const Comparator& s) const { return memcmp(s.pointer,this->ChannelName,s.length)==0; }
bool operator != (const DiscriptorNode& s) const { return !operator==(s); }
};
class StreamConnection{
public:
int FileDiscriptors[2];
bool operator == (const StreamConnection& s) const { return this->FileDiscriptors == s.FileDiscriptors; }
bool operator != (const StreamConnection& s) const { return !operator==(s); }
};
class StreamSwitch{
list <DiscriptorNode> Unconnected;
list <StreamConnection> Connected;
int ServerFileDiscriptor;
int PortNumber;
string ErrorMessage;
public:
StreamSwitch(int portNumber);
void HandleCommunication();
bool Begin();
string GetError();
};
#endif /* STREAMSWITCH_H */
This is StreamSwitch.cpp
#include "StreamSwitch.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdlib>
#include <iostream>
#include <sys/select.h>
#include <unistd.h>
void remove(list<DiscriptorNode> List, list<DiscriptorNode>:: iterator &Iterator){
list<DiscriptorNode> ::iterator temp=Iterator;
Iterator++;
List.erase(temp);
}
void remove(list<StreamConnection> List, list<StreamConnection>:: iterator &Iterator){
list<StreamConnection> ::iterator temp=Iterator;
Iterator++;
List.erase(temp);
}
StreamSwitch::StreamSwitch(int portNumber) {
this->PortNumber=portNumber;
}
bool StreamSwitch::Begin(){
int ReUseSocket=1;
struct sockaddr_in ServerAddress;
this->ServerFileDiscriptor=socket(AF_INET, SOCK_STREAM, 0);
bzero((char *) &ServerAddress, sizeof (ServerAddress));
ServerAddress.sin_family = AF_INET;
ServerAddress.sin_port = htons(PortNumber);
ServerAddress.sin_addr.s_addr = INADDR_ANY;
if (setsockopt(this->ServerFileDiscriptor, SOL_SOCKET, SO_REUSEADDR, &ReUseSocket, sizeof (ReUseSocket)) == 1) {
return 1;
}
if (bind(this->ServerFileDiscriptor, (struct sockaddr *) &ServerAddress, sizeof (ServerAddress)) < 0) {
std::stringstream ss;
ss<<"Could not bind, port "<<this->PortNumber<<" is being used";
this->ErrorMessage=ss.str();
return false;
}
listen(this->ServerFileDiscriptor, 1024);
return true;
}
uint8_t InputDataBuffer[1000];
void StreamSwitch::HandleCommunication(){
int maximumFd=0;
struct timeval Timer_Variable;
list<DiscriptorNode> ::iterator DiscIterator;
list<StreamConnection> ::iterator ConnectionIterator;
fd_set ReadFileDiscriptors, ExceptFileDiscriptors, WriteFileDiscriptors;
Timer_Variable.tv_sec = 0;
Timer_Variable.tv_usec = 100;
FD_ZERO(&ReadFileDiscriptors);
FD_ZERO(&WriteFileDiscriptors);
FD_ZERO(&ExceptFileDiscriptors);
FD_SET(this->ServerFileDiscriptor, &ReadFileDiscriptors);
FD_SET(this->ServerFileDiscriptor, &WriteFileDiscriptors);
FD_SET(this->ServerFileDiscriptor, &ExceptFileDiscriptors);
if (maximumFd<this->ServerFileDiscriptor) {
maximumFd = this->ServerFileDiscriptor;
}
for (DiscIterator = this->Unconnected.begin(); DiscIterator != this->Unconnected.end(); DiscIterator++) {
FD_SET((*DiscIterator).FileDiscriptor, &ReadFileDiscriptors);
FD_SET((*DiscIterator).FileDiscriptor, &WriteFileDiscriptors);
FD_SET((*DiscIterator).FileDiscriptor, &ExceptFileDiscriptors);
if (maximumFd < (*DiscIterator).FileDiscriptor) {
maximumFd = (*DiscIterator).FileDiscriptor;
}
}
for (ConnectionIterator = this->Connected.begin(); ConnectionIterator != this->Connected.end(); ConnectionIterator++) {
for (int i = 0; i < 2; i++) {
FD_SET((*ConnectionIterator).FileDiscriptors[i], &ReadFileDiscriptors);
FD_SET((*ConnectionIterator).FileDiscriptors[i], &WriteFileDiscriptors);
FD_SET((*ConnectionIterator).FileDiscriptors[i], &ExceptFileDiscriptors);
if (maximumFd < (*ConnectionIterator).FileDiscriptors[i]) {
maximumFd = (*ConnectionIterator).FileDiscriptors[i];
}
}
}
maximumFd++;
select(maximumFd,&ReadFileDiscriptors,&WriteFileDiscriptors,&ExceptFileDiscriptors,&Timer_Variable);
if(FD_ISSET(this->ServerFileDiscriptor,&ReadFileDiscriptors)){
struct sockaddr_in ClientAddress;
DiscriptorNode node;
socklen_t clientLength=sizeof(ClientAddress);
node.FileDiscriptor=accept(this->ServerFileDiscriptor, (struct sockaddr *) &ClientAddress, &clientLength);
cout<<"Got a new connection"<<endl;
bzero(node.ChannelName,sizeof(node.ChannelName));
this->Unconnected.push_back(node);
}
for (DiscIterator = this->Unconnected.begin(); DiscIterator != this->Unconnected.end(); DiscIterator++) {
if(FD_ISSET((*DiscIterator).FileDiscriptor,&ExceptFileDiscriptors)){
close((*DiscIterator).FileDiscriptor);
remove(this->Unconnected,DiscIterator);
continue;
}
int errorsoc = 0;
socklen_t len = sizeof (errorsoc);
int retval = getsockopt((*DiscIterator).FileDiscriptor
, SOL_SOCKET
, SO_ERROR
, &errorsoc
, &len);
if ((retval != 0) || (errorsoc != 0)) {
close((*DiscIterator).FileDiscriptor);
remove(this->Unconnected,DiscIterator);
continue;
}
if(FD_ISSET((*DiscIterator).FileDiscriptor,&ReadFileDiscriptors)){
int TransferCount;
bzero(InputDataBuffer,sizeof(InputDataBuffer));
TransferCount=read((*DiscIterator).FileDiscriptor, InputDataBuffer, sizeof(InputDataBuffer));
if (TransferCount < 1) {
close((*DiscIterator).FileDiscriptor);
remove(this->Unconnected,DiscIterator);
continue;
}
Comparator s;
cout<<"Got this data "<<InputDataBuffer<<endl;
s.pointer=InputDataBuffer;
s.length=TransferCount;
list<DiscriptorNode>::iterator matching=std::find(this->Unconnected.begin(),this->Unconnected.end(),s);
if(matching==this->Unconnected.end()){
cout<<"Did not find matching"<<endl;
memcpy((*DiscIterator).ChannelName,InputDataBuffer,TransferCount);
continue;
}
cout<<"Matched "<<InputDataBuffer<<endl;
StreamConnection connect;
connect.FileDiscriptors[0]=(*matching).FileDiscriptor;
connect.FileDiscriptors[1]=(*DiscIterator).FileDiscriptor;
remove(this->Unconnected,matching);
remove(this->Unconnected,DiscIterator);
this->Connected.push_back(connect);
}
}
for (ConnectionIterator = this->Connected.begin(); ConnectionIterator != this->Connected.end(); ConnectionIterator++) {
for (int i = 0; i < 2; i++) {
if (FD_ISSET((*ConnectionIterator).FileDiscriptors[i], &ExceptFileDiscriptors)) {
close((*ConnectionIterator).FileDiscriptors[i]);
close((*ConnectionIterator).FileDiscriptors[1-i]);
remove(this->Connected,ConnectionIterator);
break;
}
int errorsoc = 0;
socklen_t len = sizeof (errorsoc);
int retval = getsockopt((*ConnectionIterator).FileDiscriptors[i]
, SOL_SOCKET
, SO_ERROR
, &errorsoc
, &len);
if ((retval != 0) || (errorsoc != 0)) {
close((*ConnectionIterator).FileDiscriptors[i]);
close((*ConnectionIterator).FileDiscriptors[1-i]);
remove(this->Connected,ConnectionIterator);
break;
}
if (FD_ISSET((*ConnectionIterator).FileDiscriptors[i], &ReadFileDiscriptors)) {
int TransferCount;
bzero(InputDataBuffer, sizeof (InputDataBuffer));
TransferCount = read((*ConnectionIterator).FileDiscriptors[i], InputDataBuffer, sizeof (InputDataBuffer));
if (TransferCount < 1) {
close((*ConnectionIterator).FileDiscriptors[i]);
close((*ConnectionIterator).FileDiscriptors[1 - i]);
remove(this->Connected,ConnectionIterator);
break;
}
// cout<<"This is the data received "<<InputDataBuffer<<endl;
write((*ConnectionIterator).FileDiscriptors[1-i],InputDataBuffer,TransferCount);
}
}
}
}
string StreamSwitch::GetError(){
return this->ErrorMessage;
}
And this is my main
#include <list>
#include <cstdlib>
#include <iostream>
#include <unistd.h>
#include "StreamSwitch.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
StreamSwitch switcher(1234);
bool success=switcher.Begin();
if(!success){
cout<<switcher.GetError();
return 0;
}
while(1){
switcher.HandleCommunication();
usleep(1000);
}
return 0;
}
I have checked my make file and confirmed that it runs the following commands for compilation
g++ -c -g -MMD -MP -MF "build/Debug/GNU-MacOSX/StreamSwitch.o.d" -o build/Debug/GNU-MacOSX/StreamSwitch.o StreamSwitch.cpp
mkdir -p dist/Debug/GNU-MacOSX
g++ -o dist/Debug/GNU-MacOSX/streamswitch build/Debug/GNU-MacOSX/StreamSwitch.o build/Debug/GNU-MacOSX/main.o
This is the error I get on digital ocean droplet
g++ -c -g -MMD -MP -MF "build/Debug/GNU-MacOSX/StreamSwitch.o.d" -o build/Debug/GNU-MacOSX/StreamSwitch.o StreamSwitch.cpp
In file included from StreamSwitch.cpp:7:0:
StreamSwitch.h:23:5: error: ‘uint8_t’ does not name a type
uint8_t *pointer;
^
StreamSwitch.h:28:5: error: ‘uint8_t’ does not name a type
uint8_t ChannelName[1000];
^
StreamSwitch.h: In member function ‘bool DiscriptorNode::operator==(const Comparator&) const’:
StreamSwitch.h:30:68: error: ‘const struct Comparator’ has no member named ‘pointer’
bool operator == (const Comparator& s) const { return memcmp(s.pointer,this->ChannelName,s.length)==0; }
^
StreamSwitch.h:30:82: error: ‘const class DiscriptorNode’ has no member named ‘ChannelName’
bool operator == (const Comparator& s) const { return memcmp(s.pointer,this->ChannelName,s.length)==0; }
^
StreamSwitch.h:30:102: error: ‘memcmp’ was not declared in this scope
bool operator == (const Comparator& s) const { return memcmp(s.pointer,this->ChannelName,s.length)==0; }
^
StreamSwitch.cpp: In member function ‘bool StreamSwitch::Begin()’:
StreamSwitch.cpp:34:58: error: ‘bzero’ was not declared in this scope
bzero((char *) &ServerAddress, sizeof (ServerAddress));
^
StreamSwitch.cpp: In member function ‘void StreamSwitch::HandleCommunication()’:
StreamSwitch.cpp:95:20: error: ‘class DiscriptorNode’ has no member named ‘ChannelName’
bzero(node.ChannelName,sizeof(node.ChannelName));
^
StreamSwitch.cpp:95:44: error: ‘class DiscriptorNode’ has no member named ‘ChannelName’
bzero(node.ChannelName,sizeof(node.ChannelName));
^
StreamSwitch.cpp:95:56: error: ‘bzero’ was not declared in this scope
bzero(node.ChannelName,sizeof(node.ChannelName));
^
StreamSwitch.cpp:119:58: error: ‘bzero’ was not declared in this scope
bzero(InputDataBuffer,sizeof(InputDataBuffer));
^
StreamSwitch.cpp:128:15: error: ‘struct Comparator’ has no member named ‘pointer’
s.pointer=InputDataBuffer;
^
StreamSwitch.cpp:130:114: error: no matching function for call to ‘find(std::list<DiscriptorNode>::iterator, std::list<DiscriptorNode>::iterator, Comparator&)’
list<DiscriptorNode>::iterator matching=std::find(this->Unconnected.begin(),this->Unconnected.end(),s);
^
StreamSwitch.cpp:130:114: note: candidate is:
In file included from /usr/include/c++/4.8/bits/locale_facets.h:48:0,
from /usr/include/c++/4.8/bits/basic_ios.h:37,
from /usr/include/c++/4.8/ios:44,
from /usr/include/c++/4.8/istream:38,
from /usr/include/c++/4.8/sstream:38,
from StreamSwitch.h:17,
from StreamSwitch.cpp:7:
/usr/include/c++/4.8/bits/streambuf_iterator.h:369:5: note: template<class _CharT2> typename __gnu_cxx::__enable_if<std::__is_char<_CharT2>::__value, std::istreambuf_iterator<_CharT> >::__type std::find(std::istreambuf_iterator<_CharT>, std::istreambuf_iterator<_CharT>, const _CharT2&)
find(istreambuf_iterator<_CharT> __first,
^
/usr/include/c++/4.8/bits/streambuf_iterator.h:369:5: note: template argument deduction/substitution failed:
StreamSwitch.cpp:130:114: note: ‘std::_List_iterator<DiscriptorNode>’ is not derived from ‘std::istreambuf_iterator<_CharT>’
list<DiscriptorNode>::iterator matching=std::find(this->Unconnected.begin(),this->Unconnected.end(),s);
^
StreamSwitch.cpp:133:40: error: ‘class DiscriptorNode’ has no member named ‘ChannelName’
memcpy((*DiscIterator).ChannelName,InputDataBuffer,TransferCount);
^
StreamSwitch.cpp:133:81: error: ‘memcpy’ was not declared in this scope
memcpy((*DiscIterator).ChannelName,InputDataBuffer,TransferCount);
^
StreamSwitch.cpp:168:64: error: ‘bzero’ was not declared in this scope
bzero(InputDataBuffer, sizeof (InputDataBuffer));
^
Please help me figure out how to fix this for ubuntu, and I would love it if someone could explain how I can avoid this issue in the future.
Edited:
I fixed the issue by adding the following headers in StreamSwitch.h
#include <string.h>
#include <algorithm>
#include <inttypes.h>
and removing the following from StreamSwitch.h
#include <string>
I still don't know what is going on, or why code compiled on Mac and not on the digital Ocean droplet, or how I can avoid this issue all-together in the future.
The fixed width standard types appeared in C99 and C++11, see
http://en.cppreference.com/w/c/types/integer
http://en.cppreference.com/w/cpp/types/integer
They are declared/defined in "" and "".
So two steps to take to solve you problem platofrm independently is
1) #include <stdint.h> or #include <stdint>
2) make sure to compile by C99 or C++11 standards,
which might need to use special comandline parameters,
to be looked up in the documentation/help of your compilers
Note:
I extended an initially C answer to cover both. The C tag has been removed meanwhile. I think keeping the info on C is worth/harmless.
Related
I am unsure how to solve my error. How do I make is so that my void run() function can see this variable 'intf'? the value of intf itself was declared separately in a .cnf file. Thank you
My errors are as follows
monreqserver.cc: In member function 'void Pds::MyXtcMonitorServer::run()':
monreqserver.cc:57: error: 'intf' was not declared in this scope
My code is as follows:
#include "pdsdata/app/XtcMonitorServer.hh"
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <stdlib.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#define mult_address "225.0.0.37"
#define mult_port "1100"
namespace Pds {
class MyXtcMonitorServer : public XtcMonitorServer {
public:
MyXtcMonitorServer(const char* tag,
unsigned sizeofBuffers,
unsigned numberofEvBuffers,
unsigned numberofEvQueues, const char * intf) :
XtcMonitorServer(tag,
sizeofBuffers,
numberofEvBuffers,
numberofEvQueues)
{
_init();
}
~MyXtcMonitorServer() {}
public:
void run() {
//////////////
//udp socket//
//////////////
int udp_socket_info;
struct sockaddr_in udp_server;
udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket_info == -1) {
puts("Could not create socket");
}
udp_server.sin_addr.s_addr = inet_addr(mult_address);
udp_server.sin_port = htons(1100);
udp_server.sin_family = AF_INET;
ifreq ifr;
ifr.ifr_addr.sa_family = AF_INET;
strcpy(ifr.ifr_name, intf);
if (ioctl(udp_socket_info, SIOCGIFADDR, &ifr)<0) {
perror("SIOCGIFADDR failed");
}
char* port = "1100";
char* ip = inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr);
char* zero = "/0";
char ip_port[100];
sprintf(ip_port, "%s %s %s", ip, port, zero);
sendto(udp_socket_info , ip_port , strlen(ip_port), 0, (struct sockaddr *)&udp_server, sizeof(udp_server));
puts("Message Sent");
///////////////////////////////
///SETTING UP TCP CONNECTION///
///////////////////////////////
int tcp_socket_info, tcp_new_socket;
struct sockaddr_in tcp_server, tcp_client;
tcp_socket_info = socket(AF_INET, SOCK_STREAM, 0);
if (tcp_socket_info == -1) {
printf("Could not create socket");
}
tcp_server.sin_addr.s_addr = INADDR_ANY;
tcp_server.sin_family = AF_INET;
tcp_server.sin_port = htons(1100);
int y=1;
if(setsockopt(tcp_socket_info, SOL_SOCKET, SO_REUSEADDR, (char*)&y, sizeof(y)) == -1) {
perror("set reuseaddr");
}
//binds socket
if (bind(tcp_socket_info, (struct sockaddr *)&tcp_server, sizeof(tcp_server)) < 0) {
perror("Bind error");
}
//listen
listen(tcp_socket_info , 5);
//waiting for connection
puts("Waiting for incoming connections...");
int c = sizeof(struct sockaddr_in);
//accept connection loop
tcp_new_socket = accept(tcp_socket_info, (struct sockaddr *)&tcp_client, (socklen_t*)&c);
puts("Connection accepted");
while(1)
sleep(1);
}
private:
void _copyDatagram(Dgram* dg, char*) {}
void _deleteDatagram(Dgram* dg) {}
void _requestDatagram() {}
private:
};
};
using namespace Pds;
void usage(char* progname) {
printf("Usage: %s -p <platform> -P <partition> -i <node mask> -n <numb shm buffers> -s <shm buffer size> [-q <# event queues>] [-t <tag name>] [-d] [-c] [-g <max groups>] [-h]\n", progname);
}
int main(int argc, char** argv) {
const unsigned NO_PLATFORM = unsigned(-1UL);
unsigned platform=NO_PLATFORM;
const char* partition = 0;
const char* tag = 0;
const char* intf = 0;
int numberOfBuffers = 0;
unsigned sizeOfBuffers = 0;
unsigned nevqueues = 1;
unsigned node = 0xffff;
unsigned nodes = 6;
bool ldist = false;
int c;
while ((c = getopt(argc, argv, "I:p:i:g:n:P:s:q:t:dch")) != -1) {
errno = 0;
char* endPtr;
switch (c) {
case 'p':
platform = strtoul(optarg, &endPtr, 0);
if (errno != 0 || endPtr == optarg) platform = NO_PLATFORM;
break;
case 'I':
intf = optarg;
break;
case 'i':
node = strtoul(optarg, &endPtr, 0);
break;
case 'g':
nodes = strtoul(optarg, &endPtr, 0);
break;
case 'n':
sscanf(optarg, "%d", &numberOfBuffers);
break;
case 'P':
partition = optarg;
break;
case 't':
tag = optarg;
break;
case 'q':
nevqueues = strtoul(optarg, NULL, 0);
break;
case 's':
sizeOfBuffers = (unsigned) strtoul(optarg, NULL, 0);
break;
case 'd':
ldist = true;
break;
case 'h':
// help
usage(argv[0]);
return 0;
break;
default:
printf("Unrecogized parameter\n");
usage(argv[0]);
break;
}
}
if (!numberOfBuffers || !sizeOfBuffers || platform == NO_PLATFORM || !partition || node == 0xffff) {
fprintf(stderr, "Missing parameters!\n");
usage(argv[0]);
return 1;
}
if (numberOfBuffers<8) numberOfBuffers=8;
if (!tag) tag=partition;
printf("\nPartition Tag:%s\n", tag);
MyXtcMonitorServer* apps = new MyXtcMonitorServer(tag,
sizeOfBuffers,
numberOfBuffers,
nevqueues, intf);
apps->distribute(ldist);
apps->run();
return 0;
}
and the header file include is as follows:
#ifndef Pds_XtcMonitorServer_hh
#define Pds_XtcMonitorServer_hh
#include "pdsdata/app/XtcMonitorMsg.hh"
#include "pdsdata/xtc/TransitionId.hh"
#include <pthread.h>
#include <mqueue.h>
#include <queue>
#include <stack>
#include <vector>
#include <poll.h>
#include <time.h>
namespace Pds {
class Dgram;
class TransitionCache;
class XtcMonitorServer {
public:
XtcMonitorServer(const char* tag,
unsigned sizeofBuffers,
unsigned numberofEvBuffers,
unsigned numberofEvQueues, const char * intf);
virtual ~XtcMonitorServer();
public:
enum Result { Handled, Deferred };
Result events (Dgram* dg);
void discover ();
void routine ();
void unlink ();
public:
void distribute (bool);
protected:
int _init ();
private:
void _initialize_client();
mqd_t _openQueue (const char* name, mq_attr&);
void _flushQueue (mqd_t q);
void _flushQueue (mqd_t q, char* m, unsigned sz);
void _moveQueue (mqd_t iq, mqd_t oq);
bool _send (Dgram*);
void _update (int,TransitionId::Value);
void _clearDest (mqd_t);
private:
virtual void _copyDatagram (Dgram* dg, char*);
virtual void _deleteDatagram(Dgram* dg);
virtual void _requestDatagram();
private:
const char* _tag; // name of the complete shared memory segment
unsigned _sizeOfBuffers; // size of each shared memory datagram buffer
unsigned _numberOfEvBuffers; // number of shared memory buffers for events
unsigned _numberOfEvQueues; // number of message queues for events
char* _myShm; // the pointer to start of shared memory
XtcMonitorMsg _myMsg; // template for messages
mqd_t _discoveryQueue; // message queue for clients to get
// the TCP port for initiating connections
mqd_t _myInputEvQueue; // message queue for returned events
mqd_t* _myOutputEvQueue; // message queues[nclients] for distributing events
std::vector<int> _myTrFd; // TCP sockets to clients for distributing
// transitions and detecting disconnects.
std::vector<int> _msgDest; // last client to which the buffer was sent
TransitionCache* _transitionCache;
int _initFd;
pollfd* _pfd; /* poll descriptors for:
** 0 new client connections
** 1 buffer returned from client
** 2 events to be distributed
** 3+ transition send/receive */
int _nfd;
mqd_t _shuffleQueue; // message queue for pre-distribution event processing
mqd_t _requestQueue; // message queue for buffers awaiting request completion
timespec _tmo;
pthread_t _discThread; // thread for receiving new client connections
pthread_t _taskThread; // thread for datagram distribution
unsigned _ievt; // event vector
};
};
#endif
The variable intf is a local variable of main(). It is therefore unknown outside the scope of main(). This is why you can't access it in the member functions of your class.
Three possible solutions:
you make the variable global (as it seems to be a global parameter that applies to all the classes
you make the variable a public static variable in the class. You then can initialize it from main, by using the prefix of your class.
or you define it as parameter of the run() member function (and invoke run from main accordingly).
The last one is the on which I'd choose, but i don't know enough about the context to give more objective advices for the choice:
// in the class:
void run(const char*intf) { // for convenience you can use the same name
...
}
// in main:
...
apps->run(intf); // pass the local variable as parameter
Name intf is referred in function run. But the compiler does not see any its declaration before its usage in the function
void run() {
//...
strcpy(ifr.ifr_name, intf);
^^^^^
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.
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, ð0socket, eth0);
eth1socket = CreateAndBindSocket(ETH_P_ALL, ð1socket, eth1);
boost::thread eth0recvthread(RecvThread, ð0socket); //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!
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <cstdio>
using namespace std;
int main(int argc, char *argv[])
{
int port, n,sockfd;
struct sockaddr_in srv_addr;
struct hostent *serv;
char buffer[256];
if(argc<3)
{
cout <<"\n ussage: host port\nexiting\n";
return 0;
}
port=atoi(argv[2]);
sockfd=socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
cout <<"\nsocket creation on"<<port<<" failed\nexiting\ncheck to see if port is in use";
return 0;
}
serv = gethostbyname(argv[1]);
if (serv=NULL)
{
cout <<"\n"<<serv<<" is not a valid host name\nexiting";
return 0;
}
bzero((char *) &srv_addr, sizeof(srv_addr));
srv_addr.sin_family=AF_INET;
bcopy((char *) serv->h_addr,
(char *) &srv_addr.sin_addr.s_addr,
serv->h_length);
srv_addr.sin_port=htons(port);
if (connect(sockfd,&srv_addr,
sizeof (srv_addr))<0)
{
cout <<" \nconnection failed\n";
}
cout <<"\nType message\n";
bzero(buffer, 256);
cin.getline(buffer,256);
n=write(sockfd,buffer,strlen(buffer));
if (n>0)
{
cout <<"\nsocket write error\nexiting\n";
}
n=read(sockfd,buffer,255);
if (n>0)
{
cout <<"\nsocket read error\nexiting\n";
}
cout <<buffer;
return 0;
}
When compiled, I get this error:
fg.c: In function ‘int main(int, char**)’:
fg.c:53:33: error: cannot convert ‘sockaddr_in*’ to ‘const sockaddr*’ for argument ‘2’ to ‘int connect(int, const sockaddr*, socklen_t)’
I cant figure it out. I am a noob to programming. Any help is grateful.
You need explicit cast. Replace
connect(sockfd,&srv_addr, sizeof (srv_addr))
with
connect(sockfd,(sockaddr*)&srv_addr, sizeof (srv_addr))
I'm writing a sniffer class with c++ as following code.
#include "Capture.h"
#include <sys/socket.h>
#include <cstring>
#include <linux/if_ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <pthread.h>
Capture::Capture(int sniff_socket): sniff_socket_(sniff_socket), sniff_threadID_(0)
{
}
bool Capture::endCapture()
{
if(!sniff_threadID_)
return false;
cout << "Asking capture thread to stop\n" <<endl;
return !pthread_cancel(sniff_threadID_);
}
bool Capture::startCapture()
{
if(pthread_create(&sniff_threadID_, NULL, Capture::sniffer_thread, NULL)) {
cerr << "Unable to create capture thread"<<endl;
return false;
}
return true;
}
void *Capture::sniffer_thread(void *)
{
int MTU = 2048;
char buffer[MTU];
ssize_t msg_len;
struct iphdr *ip_header;
struct ethhdr *eth_header;
struct tcphdr *tcp_header;
void *packet;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while (1) {
msg_len = recvfrom(sniff_socket_, buffer, MTU, 0, NULL, NULL);
eth_header = (struct ethhdr*)buffer;
ip_header = (iphdr*)(buffer + sizeof(ethhdr));
tcp_header = (struct tcphdr*)(buffer + sizeof(struct ethhdr) + sizeof(struct iphdr));
if(msg_len != -1){
packet = malloc(msg_len);
memcpy(packet, buffer, msg_len);
pthread_testcancel();
//queue add should be here
} else {
cerr<<"Error capture thread recvfrom"<<endl;
pthread_exit(NULL);
}
}
return NULL;
}
Capture::~Capture()
{
// TODO Auto-generated destructor stub
}
However, when I compiled the code, g++ said that
../Capture.cpp: In member function ‘bool Capture::startCapture()’:
../Capture.cpp:30: error: argument of type ‘void* (Capture::)(void*)’ does not match ‘void* (*)(void*)’
Could somebody help me out of this problem?
A member function in C++ class passes this as hidden parameter, the C function pthread_create cannot understand what this is, Since static member functions dont pass this you can use a static function like this:
class Capture
{
public:
static void *sniffer_thread(void*);
};
pthread_create(..., Capture::sniffer_thread, NULL);
First of all: is Capture::sniffer_thread static? cause a member function pointer is not a function pointer! These two kinds of pointers are incompatible!