-1

Ok, so this problem has been bugging me for a while. I'm creating a c++ program with the libpcap and libnet libraries. It will scan a given country for open ports by SYN'ing with libnet and checking for replies with libpcap. I have a main.cpp file that includes network.h which includes the source files necessary for generating the IPv4 ranges (regex.cpp) and for scanning them (libnet.cpp). Now, my network.h file contains the definition for struct range which is just two uint32_t's representing the starting address of the range and the end.

network.h:

#ifndef NETWORK_H
#define NETWORK_H

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <regex>
#include <fstream>
#include <libnet.h>
#include <pcap.h>
#include "src/regex.cpp"
#include "src/libnet.cpp"
#include "src/libpcap.cpp"

#define COLOR_GREEN "\x1b[32m"
#define COLOR_RED "\x1b[31m"
#define COLOR_RESET "\x1b[0m"

#define SNAP_LEN 1518

typedef struct range {
    uint32_t begin;
    uint32_t end;
} range;
#endif

And I use struct range as the return type for getRangeByCountry

#include "../network.h"

std::vector<struct range> getRangeByCountry(const char* country){
    std::vector<struct range> ranges;
    try {
    std::ifstream f("csv/geoip.csv");
    std::regex re("\"\\d+.\\d+.\\d+.\\d+\",\"\\d+.\\d+.\\d+.\\d+\",\"(\\d+)\",\"(\\d+)\",\"\\w$
    while (1){
            std::string line;
            std::getline(f, line);
            std::smatch m;
            if(line == ""){break;}
            std::regex_match(line, m, re);
            if (m[3] == country){
                    struct range r;
                    r.begin = std::stoul(std::string(m[1]), NULL, 0);
                    r.end = std::stoul(std::string(m[2]), NULL, 0);
                    ranges.push_back(r);
            }
    }
    } catch (...){return ranges;}
    return std::move(ranges);
}

But when I compile I get this error:

src/regex.cpp: In function ‘std::vector<range> getRangeByCountry(const 
char*)’:
src/regex.cpp:15:17: error: aggregate ‘range r’ has incomplete type and 
cannot be defined
 struct range r;

Why doesn't the compiler throw an error when I set declare a vector of struct range locally? Or when I set the same as the return type? When I define the struct in the same file as getRangebyCountry() it compiles without error. Is this a problem with my g++ parameters? Here they are just in case: g++ main.cpp -lpcap -lnet --std=c++11

Nash
  • 19
  • 7
  • You should see [this](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) and [this](https://stackoverflow.com/questions/1686204/why-should-i-not-include-cpp-files-and-instead-use-a-header). – LogicStuff Jun 27 '17 at 22:16
  • This isn't the problem, but names that begin with an underscore followed by a capital letter (`_NETWORK_H`) and names that contain two consecutive underscores are reserved for use by the implementation. Don't use them in your code. – Pete Becker Jun 27 '17 at 22:21
  • @PeteBecker thanks i'll edit. – Nash Jun 27 '17 at 22:22
  • 1
    You have circular `#include`s: `network.h` includes `range.cpp` (why on earth?) and `range.cpp` includes `network.h`. – Igor Tandetnik Jun 27 '17 at 22:29
  • it also uses the struct in a header (which is named cpp?) before it is defined – Kenny Ostrom Jun 27 '17 at 22:31
  • @IgorTandetnik I always thought that having header guards eliminated the dangers of circular includes. I just had **regex.cpp** include **network.h** as a personal reminder but ill edit if it's screwing things up. – Nash Jun 27 '17 at 22:34
  • 1
    No, include guards solve the problem of the same header being included twice into the same source file, indirectly via other headers. They don't help any with circular dependencies. Those simply can't be made to work - you have to arrange your headers in a way that they don't include each other circularly. – Igor Tandetnik Jun 27 '17 at 22:36
  • @IgorTandetnik that's helpful, thanks. – Nash Jun 27 '17 at 22:38
  • 1
    as a basic rule, a header file should never include a `.cpp` file. – Walter Jun 27 '17 at 22:44
  • @KennyOstrom I don't understand. If my **main.cpp** file includes **network.h** which includes **regex.cpp**, doesnt **regex.cpp** have access to the definitions of the header file which includes it? – Nash Jun 27 '17 at 22:47
  • No one includes it. regex.cpp is compiled into its own object file that is linked in with main.cpp. This allows you to create little modules of code that don't have to be recompiled whenever an implementation detain in one of the other modules is changed. Speeds up compilation greatly if you don't have to rebuild every thing every time. – user4581301 Jun 27 '17 at 23:00

1 Answers1

0

Fixed the problem. @Walter and @IgorTandetnik were right. In network I included a definition for getRangeByCountry() and removed the .cpp includes like so:

#ifndef _NETWORK_H
#define _NETWORK_H

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <regex>
#include <fstream>
#include <libnet.h>
#include <pcap.h>

#define COLOR_GREEN "\x1b[32m"
#define COLOR_RED "\x1b[31m"
#define COLOR_RESET "\x1b[0m"

#define SNAP_LEN 1518

std::vector<struct range> getRangeByCountry(const char*);

typedef struct range {
    uint32_t begin;
    uint32_t end;
} range;

Then I compiled regex.cpp separately and included it in my compilation of main.cpp like so: g++ main.cpp src/regex.o

But I'm still really shakey on the concept. If I want to include other cpp source files, do I need to compile them separately then include their definition in a header file and their actual definition in a .o when I compile main.cpp?

Nash
  • 19
  • 7