IpAddress::IpAddress(const struct sockaddr *saddr) {
        EPYX_ASSERT(saddr != NULL);
        char ipBuffer[INET6_ADDRSTRLEN + 1];

        if (saddr->sa_family == AF_INET) {
            // IPv4
            struct sockaddr_in *ipv4 = (struct sockaddr_in *) saddr;
            inet_ntop(AF_INET, &(ipv4->sin_addr), ipBuffer, sizeof (ipBuffer));
            this->ip.assign(ipBuffer);
            this->ipVersion = 4;
        } else if (saddr->sa_family == AF_INET6) {
            // IPv6
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) saddr;
            inet_ntop(AF_INET6, &(ipv6->sin6_addr), ipBuffer, sizeof (ipBuffer));
            this->ip.assign(ipBuffer);
            this->ipVersion = 6;
        } else {
            log::fatal << "You have just invented a new IP version " \
                << "without giving me information about how to handle it\n" \
                << "The version is: " << saddr->sa_family << "\n" \
                << "IPv4 is: " << AF_INET << "\n" \
                << "IPv6 is: " << AF_INET6 \
                << log::endl;
            throw FailException("IpAddress", "Bad IP Version");
        }
    }
Esempio n. 2
0
    bool Server::_internal_bind(int socktype)
    {
        //EPYX_ASSERT(port < 65536);
        char charport[10];
        struct addrinfo hints, *addrAll, *pai;
        int status, flag;

        // Convert port to char* to find address hints
        snprintf(charport, sizeof(charport), "%u", port);
        memset(&hints, 0, sizeof hints);
        // AF_INET or AF_INET6 to force IP version
        hints.ai_family = AF_UNSPEC;
        // SOCK_STREAM (TCP) or SOCK_DGRAM (UDP)
        hints.ai_socktype = socktype;
        // Server = passive
        hints.ai_flags = AI_PASSIVE;
        status = ::getaddrinfo(NULL, charport, &hints, &addrAll);
        if (status != 0) {
            log::fatal << "getaddrinfo error " << status << ": "
                << gai_strerror(status) << log::endl;
            throw FailException("TCPServer::bind", "getaddrinfo error");
        }

        // getaddrinfo() returns a list of address structures.
        // Try each address until we successfully bind.
        for (pai = addrAll; pai != NULL; pai = pai->ai_next) {
            // Create a new socket
            this->sockfd = ::socket(pai->ai_family, pai->ai_socktype,
                pai->ai_protocol);
            if (this->sockfd == -1)
                continue;

            // Allow reusing the address (ignore failure)
            flag = 1;
            setsockopt(this->sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(int));

            // Bind to a listening address/port
            status = ::bind(this->sockfd, pai->ai_addr, pai->ai_addrlen);
            if (status == 0) {
                // Success : remember used address
                this->address = Address(pai->ai_addr);
                break;
            }
            log::warn << "bind(" << Address(pai->ai_addr) << "): " << log::errstd << log::endl;

            // Close socket if bind fails
            ::close(this->sockfd);
            this->sockfd = -1;
        }
        // Free results
        freeaddrinfo(addrAll);
        if (pai == NULL) {
            log::debug << "Nowhere to bind." << log::endl;
            return false;
        }

        // Now there is a socket, listen to nbConn connections
        EPYX_ASSERT(sockfd >= 0);
        return true;
    }
 void IpAddress::getSockAddr(struct sockaddr *saddr, unsigned short port) const {
     EPYX_ASSERT(saddr != NULL);
     EPYX_ASSERT(this->ipVersion > 0);
     if (this->ipVersion == 4) {
         // IPv4
         struct sockaddr_in *ipv4 = (struct sockaddr_in *) saddr;
         memset(&(ipv4->sin_zero), 0, sizeof (ipv4->sin_zero));
         ipv4->sin_family = AF_INET;
         inet_pton(AF_INET, ip.c_str(), &(ipv4->sin_addr));
         ipv4->sin_port = htons(port);
     } else if (this->ipVersion == 6) {
         // IPv6
         struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) saddr;
         ipv6->sin6_family = AF_INET6;
         ipv6->sin6_flowinfo = 0;
         ipv6->sin6_scope_id = 0;
         inet_pton(AF_INET6, ip.c_str(), &(ipv6->sin6_addr));
         ipv6->sin6_port = htons(port);
     } else {
         throw FailException("IpAddress", "Bad IP Version");
     }
 }
Esempio n. 4
0
void TCPServerThread::run()
{
    int newfd = -1;
    struct sockaddr_storage clientAddr;
    socklen_t clientAddrLen;
    Socket *newSock = NULL;
    _TCPSocketThread *sthread = NULL;
    int spawnId = 1;

    // Bind if no socket available
    if (this->sockfd < 0 && !this->bind())
        throw FailException("TCPServer::run", "Unable to bind");

    EPYX_ASSERT(this->sockfd >= 0);
    log::debug << "Listening on " << this->address << log::endl;
    try {
        this->running = true;
        while (this->running && this->sockfd >= 0) {
            clientAddrLen = sizeof clientAddr;
            newfd = ::accept(this->sockfd, (struct sockaddr*)&clientAddr,
                             &clientAddrLen);

            // If this thread was not killed, return
            if (!this->running || this->sockfd < 0) {
                ::shutdown(newfd, SHUT_RDWR);
                ::close(newfd);
                newfd = -1;
                break;
            }
            if (newfd == -1)
                throw ErrException("TCPServer::run", "accept");

            // Encapsulate socket
            try {
                newSock = new TCPSocket(newfd, Address((struct sockaddr*)&clientAddr));
            } catch (Exception e) {
                log::error << "Unable to setup the link:\n" << e << log::endl;
                if (newSock)
                    delete newSock;
                else if (newfd >= 0) {
                    // newfd is managed by newSock
                    ::close(newfd);
                }
                newSock = NULL;
            }
            // Make newfd variable invalid
            newfd = -1;

            if (newSock != NULL) {
                try {
                    sthread = new _TCPSocketThread(this, newSock,
                                                   this->getThisName(), spawnId++);
                    sthread->start();
                } catch (Exception e) {
                    log::error << e << log::endl;
                    log::error << "Unable to start a thread" << log::endl;
                    if (sthread != NULL)
                        delete sthread;
                    delete newSock;
                }
                // DO NOT delete newSock nor srun as they are owned by an other thread
                newSock = NULL;
                sthread = NULL;
            }
        }
    } catch (Exception e) {
        log::error << e << log::endl;
        log::error << "Arg ! An exception killed me !" << log::endl;
        if (newSock)
            delete newSock;
    }
    log::debug << "Clean exit on " << this->address << log::endl;
}
Esempio n. 5
0
    /**
     * @brief sInternal function, only called by GTTParser::getPacket
     *
     * @throw ParserException on errors
     */
    bool GTTParser::processChar(char c)
    {
        // Create a nw packet if we does not have anyone yet
        if (currentPkt == NULL)
            currentPkt = new GTTPacket();

        switch(currentType) {
            case start:
                // Start a new packet
                if (!isupper(c))
                    throw ParserException("protocol name should begin with capital letters");
                currentString = c;
                currentType = protocol_name;
                flagType = other;
                break;
            case protocol_name:
                if(isupper(c) || isdigit(c) || (c == '_')) {
                    currentString += c;
                } else if(c == ' ') {
                    currentPkt->protocol = currentString;
                    currentString = "";
                    currentType = method;
                    flagType = start;
                }
                else
                    throw ParserException("protocol name should continue with [A-Z0-9]* or end with a space");
                break;
            case method:
                if (flagType == start){
                    if (!isupper(c))
                        throw ParserException("method should begin with capital letters");
                    currentString = c;
                    flagType = other;
                }
                else if (isupper(c) || isdigit(c) || (c == '_'))
                    currentString += c;
                else if (c == '\r') {
                    currentPkt->method = currentString;
                    currentString = "";
                    currentType = method_line;
                } else
                    throw ParserException("method should continue with [A-Z0-9_] or end with CRLF");
                break;
            case method_line:
                if (c != '\n')
                    throw ParserException("newline should be CRLF");
                currentType = flag_name;
                flagType = start;
                break;
            case flag_name:
                if(flagType == start){
                    if (isalpha(c))
                        currentString = c;
                    else if (c == '\r') {
                        // New line at the end of the headers
                        currentType = newline;
                    } else
                        throw ParserException("flag_name should begin with [a-zA-Z] or we should add newline to end the header");
                    flagType = other;
                } else if(isalnum(c) || (c == '_') || (c == '-')) {
                    currentString += c;
                } else if(c == ':') {
                    currentFlagName = currentString;
                    currentString = "";
                    currentType = flag_indicator;
                    /*
                    if(!strcasecmp(currentString.c_str(), "content-length")) {
                        if(currentPkt->size > 0)
                            throw FailException("Parser", "content-length flag has already appeared");
                        else
                            hasBody=true;

                    }*/
                } else
                    throw ParserException("flag_name should continue with [a-zA-Z0-9_-] or end with :");
                break;
            case flag_indicator:
                // Skip spaces
                if(c == ' ')
                    break;
                /* Walk through */
            case flag_value:
                if (32 <= c && c < 126) {
                    // Printable ASCII characters
                    currentString += c;
                } else if(c == '\r') {
                    if(!strcasecmp(currentFlagName.c_str(), "content-length")) {
                        if(currentPkt->size > 0)
                            throw FailException("Parser", "content-length flag has already appeared");
                        currentPkt->size = String::toInt(currentString.c_str());
                        if (currentPkt->size <= 0)
                            throw FailException("Parser", "not valid body size, body size should be a positive integer");
                        currentPkt->body = new char[currentPkt->size];
                    } else
                        currentPkt->headers[currentFlagName] = currentString;
                    currentString = "";
                    currentFlagName = "";
                    currentType = flag_line;
                } else
                    throw ParserException("flag_value should consist of printable characters or just end with CRLF");
                break;
            case flag_line:
                if (c != '\n')
                    throw ParserException("newline should be CRLF");
                currentType = flag_name;
                flagType = start;
                break;
            case newline:
                if (c != '\n')
                    throw ParserException("newline should be CRLF");
                if (currentPkt->size == 0) {
                    // No body
                    return true;
                }
                bodyCounter = 0;
                currentType = body;
                break;
            case body:
                EPYX_ASSERT(bodyCounter < currentPkt->size);
                currentPkt->body[bodyCounter] = c;
                bodyCounter ++;
                if (bodyCounter == currentPkt->size) {
                    // Return there is a new packet
                    return true;
                }
                break;
            case other:
                throw ParserException("Unreachable state");
        }
        return false;
    }