Example #1
0
std::streamsize Socket::send(const char_type* buffer, std::streamsize size) {
    if(size == 0) return 0;

    switch(type) {
        case UDP_PEER: {
            AddrinfoContainer info = getSocketInfoFor(hostRemote.c_str(), portRemote, false);
            
            size_t sentBytes = 0;
            while(sentBytes < size) {
                int result = ::sendto(handle, (const char*)buffer + sentBytes, size - sentBytes, 0, info->ai_addr, info->ai_addrlen);
                
                if(result == -1)
                    throw Exception(Exception::ERROR_SEND);
                
                sentBytes += result;
            }

            return sentBytes;
        }
        case TCP_CLIENT:
        case TCP_SERVERS_CLIENT: {
            size_t sentBytes = 0;
            while(sentBytes < size) {
                int result = ::send(handle, (const char*)buffer + sentBytes, size - sentBytes, 0);
                
                if(result == -1)
                    throw Exception(Exception::ERROR_SEND);
                
                sentBytes += result;
            }
            return sentBytes;
        }
		default:
        case NONE:
        case TCP_SERVER:
            throw Exception(Exception::BAD_TYPE);
    }
}
Example #2
0
std::streamsize Socket::showmanyc() {
	#ifdef WIN32
	unsigned long result = 0;
	if(ioctlsocket(handle, FIONREAD, &result)) {
	#else
	int result = 0;
	if(ioctl(handle, FIONREAD, &result)) {
	#endif
        disconnect();
		throw Exception(Exception::ERROR_IOCTL);
    }else
        return result;
}

std::streamsize Socket::advanceInputBuffer() {
    if(inputIntermediateSize == 0) //No input buffer
        return 0;

    std::streamsize inAvail;
    if(type == UDP_PEER)
        inAvail = 0;
    else{
        inAvail = egptr()-gptr();
        memmove(eback(), gptr(), inAvail);
    }

    try {
        inAvail += receive(eback()+inAvail, inputIntermediateSize-inAvail);
    } catch(Exception err) {

    }

    setg(eback(), eback(), eback()+inAvail);
    return inAvail;
}

std::streamsize Socket::receive(char_type* buffer, std::streamsize size) {
	if(type == TCP_SERVER)
		throw Exception(Exception::BAD_TYPE);
	if(status != Socket::Status::READY && status != Socket::Status::BUSY)
		return 0;
    size = std::min(size, showmanyc());
    if(size == 0)
		return 0;

    switch(type) {
        case UDP_PEER: {
            struct sockaddr_storage remoteAddr;
			#ifdef WIN32
			int addrSize = sizeof(remoteAddr);
			#else
			unsigned int addrSize = sizeof(remoteAddr);
			#endif
            int result = recvfrom(handle, (char*)buffer, size, 0, reinterpret_cast<struct sockaddr*>(&remoteAddr), &addrSize);

            if(result <= 0) {
                portRemote = 0;
                hostRemote = "";
                throw Exception(Exception::ERROR_READ);
            }else
                readSockaddr(&remoteAddr, hostRemote, portRemote);

            return result;
        }
        case TCP_CLIENT:
        case TCP_SERVERS_CLIENT: {
            int result = recv(handle, (char*)buffer, size, 0);

            if(result <= 0)
				throw Exception(Exception::ERROR_READ);

            return result;
        }
		default:
        case NONE:
        case TCP_SERVER:
            throw Exception(Exception::BAD_TYPE);
    }
}

std::streamsize Socket::send(const char_type* buffer, std::streamsize size) {
	if(type == TCP_SERVER)
		throw Exception(Exception::BAD_TYPE);
	if(status != Socket::Status::READY || size == 0)
		return 0;

    switch(type) {
        case UDP_PEER: {
            AddrinfoContainer info = getSocketInfoFor(hostRemote.c_str(), portRemote, false);

            size_t sentBytes = 0;
            while(sentBytes < (size_t)size) {
                int result = ::sendto(handle, (const char*)buffer + sentBytes, size - sentBytes, 0, info->ai_addr, info->ai_addrlen);
				if(result <= 0) {
					status = BUSY;
	                throw Exception(Exception::ERROR_SEND);
				}
                sentBytes += result;
            }

            return sentBytes;
        }
        case TCP_CLIENT:
        case TCP_SERVERS_CLIENT: {
            size_t sentBytes = 0;
            while(sentBytes < (size_t)size) {
                int result = ::send(handle, (const char*)buffer + sentBytes, size - sentBytes, 0);
				if(result <= 0) {
					status = BUSY;
	                throw Exception(Exception::ERROR_SEND);
				}
                sentBytes += result;
            }
            return sentBytes;
        }
		default:
        case NONE:
        case TCP_SERVER:
            throw Exception(Exception::BAD_TYPE);
    }
}

std::streamsize Socket::redirect(const std::vector<std::shared_ptr<Socket>>& destinations) {
	if(type == TCP_SERVER)
		throw Exception(Exception::BAD_TYPE);

	std::streamsize size = 0;
	while(in_avail()) {
		auto length = egptr()-gptr();
		for(const auto& destination : destinations)
			if(destination->sputn(gptr(), length) < length)
				throw Exception(Exception::ERROR_SEND);
		gbump(length);
		size += length;
		advanceInputBuffer();
	}

	return size;
}

std::streamsize Socket::getInputBufferSize() {
    return inputIntermediateSize;
}

std::streamsize Socket::getOutputBufferSize() {
    return epptr()-pbase();
}

void Socket::setInputBufferSize(std::streamsize n) {
    if(eback()) {
        delete[] eback();
        setg(NULL, NULL, NULL);
    }
    if(n == 0) return;
    if(type == TCP_SERVER)
        throw Exception(Exception::BAD_TYPE);

    char_type* readBuffer = new char_type[n];
    setg(readBuffer, readBuffer, readBuffer);
    inputIntermediateSize = n;
}

void Socket::setOutputBufferSize(std::streamsize n) {
    if(pbase()) {
        delete[] pbase();
        setp(NULL, NULL);
    }
    if(n == 0) return;
    if(type == TCP_SERVER)
        throw Exception(Exception::BAD_TYPE);

    char_type* writeBuffer = new char_type[n];
    setp(writeBuffer, writeBuffer+n);
}

void Socket::setBlockingMode(bool blocking) {
	#ifdef WIN32
	unsigned long flag = !blocking;
	if(ioctlsocket(handle, FIONBIO, &flag) != 0)
	#else
    int flags = fcntl(handle, F_GETFL);
    if(blocking)
        flags &= ~O_NONBLOCK;
    else
        flags |= O_NONBLOCK;
    if(fcntl(handle, F_SETFL, flags) == -1)
	#endif
		throw Exception(Exception::ERROR_IOCTL);
}
Example #3
0
void Socket::initSocket(bool blockingConnect) {
    AddrinfoContainer info;

    if(type == TCP_CLIENT)
        info = getSocketInfoFor(hostRemote.c_str(), portRemote, false);
    else{
        const char* host;
        if(!hostLocal.compare("") || !hostLocal.compare("*"))
            host = NULL;
        else
            host = hostLocal.c_str();
        info = getSocketInfoFor(host, portLocal, true);
    }

    struct addrinfo* nextAddr = info.get();
    while(nextAddr) {
        handle = socket(nextAddr->ai_family, nextAddr->ai_socktype, nextAddr->ai_protocol);
        if(handle == -1) {
            nextAddr = nextAddr->ai_next;
            continue;
        }

        setBlockingMode(blockingConnect);
		#ifdef WIN32
		char flag = 1;
		#else
		int flag = 1;
		#endif
        if(setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
            disconnect();
            throw Exception(Exception::ERROR_SET_SOCK_OPT);
        }

        switch(nextAddr->ai_family) {
            case AF_INET:
                ipVersion = IPv4;
            break;
            case AF_INET6:
                ipVersion = IPv6;
            break;
        }

        switch(type) {
            case NONE:
            case TCP_SERVERS_CLIENT:
                disconnect();
                throw Exception(Exception::BAD_TYPE);
            case TCP_CLIENT:
                if(connect(handle, nextAddr->ai_addr, nextAddr->ai_addrlen) == -1 && blockingConnect) {
					closesocket(handle);
                    handle = -1;
                }else if(blockingConnect)
                    status = READY;
                else
                    status = CONNECTING;
            break;
            case TCP_SERVER: {
                if(bind(handle, nextAddr->ai_addr, nextAddr->ai_addrlen) == -1) {
					closesocket(handle);
                    handle = -1;
                }

                if(listen(handle, status) == -1) {
                    disconnect();
                    throw Exception(Exception::ERROR_INIT);
                }
            } break;
            case UDP_PEER: {
                if(bind(handle, nextAddr->ai_addr, nextAddr->ai_addrlen) == -1) {
					closesocket(handle);
                    handle = -1;
                }

                status = READY;
            } break;
        }
        if(handle == -1) {
            nextAddr = nextAddr->ai_next;
            continue;
        }

        if(blockingConnect)
            setBlockingMode(false);
        break;
    }

    if(handle == -1) {
        disconnect();
        throw Exception(Exception::ERROR_INIT);
    }

    struct sockaddr_storage localAddr;
	#ifdef WIN32
    int size = sizeof(localAddr);
	#else
	unsigned int size = sizeof(localAddr);
	#endif
    if(getsockname(handle, reinterpret_cast<struct sockaddr*>(&localAddr), &size) != 0) {
        disconnect();
        throw Exception(Exception::ERROR_GET_SOCK_NAME);
    }

    readSockaddr(&localAddr, hostLocal, portLocal);
}