예제 #1
0
void reset_signals()
{
    // Reset the signals to their old action
    if(sigaction(SIGUSR1, &old_sigusr_action, NULL) == -1)
    {
        CRITIC("Can't redirect SIGUSR1 to default handler.", strerror(errno));
    }
    if(sigaction(SIGINT, &old_sigint_action, NULL) == -1)
    {
        CRITIC("Can't redirect SIGINT to default handler.", strerror(errno));
    }
    if(sigaction(SIGUSR2, &old_sigthread_action, NULL) == -1)
    {
        CRITIC("Can't redirect SIGINT to default handler.", strerror(errno));
    }
} // reset_signals()
예제 #2
0
UInt32 RTMFPWriter::headerSize(UInt64 stage) { // max size header = 50
	UInt32 size= Util::Get7BitValueSize(id);
	size+= Util::Get7BitValueSize(stage);
	if(_stageAck>stage)
		CRITIC("stageAck ",_stageAck," superior to stage ",stage," on writer ",id);
	size+= Util::Get7BitValueSize(stage-_stageAck);
	size+= _stageAck>0 ? 0 : (signature.size()+(flowId==0?2:(4+Util::Get7BitValueSize(flowId))));
	return size;
}
예제 #3
0
UInt32 FlowWriter::headerSize(UInt64 stage) { // max size header = 50
	UInt32 size= Util::Get7BitValueSize(id);
	size+= Util::Get7BitValueSize(stage);
	if(_stageAck>stage)
		CRITIC("stageAck %s superior to stage %s on flowWriter %s",NumberFormatter::format(_stageAck).c_str(),NumberFormatter::format(stage).c_str(),NumberFormatter::format(id).c_str());
	size+= Util::Get7BitValueSize(stage-_stageAck);
	size+= _stageAck>0 ? 0 : (signature.size()+(flowId==0?2:(4+Util::Get7BitValueSize(flowId))));
	return size;
}
예제 #4
0
/**************************
*** SIGNAL MANAGEMENT
**************************/
void set_signals()
{
    // Redirect SIGUSR1 structure
    struct sigaction new_sigusr_action;
    sigemptyset(&new_sigusr_action.sa_mask);
    new_sigusr_action.sa_handler = SIG_DFL;
    new_sigusr_action.sa_sigaction = &sigusr_action;
    new_sigusr_action.sa_flags = SA_SIGINFO;

    // Redirect SIGINT structure
    struct sigaction new_sigint_action;
    sigemptyset(&new_sigint_action.sa_mask);
    new_sigint_action.sa_handler = SIG_DFL;
    new_sigint_action.sa_sigaction = &sigint_action;
    new_sigint_action.sa_flags = SA_SIGINFO;

    // Redirect SIGUSR2 structure
    struct sigaction new_sigthread_action;
    sigemptyset(&new_sigthread_action.sa_mask);
    new_sigthread_action.sa_handler = SIG_DFL;
    new_sigthread_action.sa_sigaction = &sigthread_action;
    new_sigthread_action.sa_flags = SA_SIGINFO;

    // Redirect signals structure
    if(sigaction(SIGUSR1, &new_sigusr_action, &old_sigusr_action) == -1)
    {
        CRITIC("Can't redirect SIGUSR1 to custom handler.", strerror(errno));
    }
    if(sigaction(SIGUSR2, &new_sigthread_action, &old_sigthread_action) == -1)
    {
        CRITIC("Can't redirect SIGUSR2 to custom handler.", strerror(errno));
    }
    if(sigaction(SIGINT, &new_sigint_action, &old_sigint_action) == -1)
    {
        CRITIC("Can't redirect SIGINT to custom handler.", strerror(errno));
    }
} // set_signals()
예제 #5
0
bool RTMFPCookieComputing::run(Exception& ex) {
	// First execution is for the DH computing if pDH == null, else it's to compute Diffie-Hellman keys
	if (!_diffieHellman.initialized())
		return _diffieHellman.initialize(ex);

	// Compute Diffie-Hellman secret
	_diffieHellman.computeSecret(ex,initiatorKey.data(),initiatorKey.size(),_sharedSecret);
	if (ex)
		return false;

	if (packet.size() > 0) {
		ex.set(Exception::CRYPTO, "RTMFPCookieComputing already executed");
		return false;
	}

	// string hex;
	// DEBUG("Shared Secret : ", Util::FormatHex(_sharedSecret.data(), _sharedSecret.size(), hex));

	// It's our key public part
	int size = _diffieHellman.publicKeySize(ex);
	if (size<0) {
		if (!ex)
			ex.set(Exception::CRYPTO, "DH public key not initialized");
		return false;
	}
	packet.write7BitLongValue(size+11);
	UInt32 noncePos = packet.size();
	packet.writeRaw(EXPAND_DATA_SIZE("\x03\x1A\x00\x00\x02\x1E\x00"));
	UInt8 byte2 = DH_KEY_SIZE-size;
	if(byte2>2) {
		CRITIC("Generation DH key with less of 126 bytes!");
		byte2=2;
	}
	packet.write8(0x81);
	packet.write8(2-byte2);
	packet.write8(0x0D);
	packet.write8(0x02);
	if (size>2000)
		ERROR("RTMFP diffie hellman public key with an error size key of ",size) // TODO remove this log one time fixed!
	_diffieHellman.readPublicKey(ex,packet.buffer(size));
	packet.write8(0x58);

	// Compute Keys
	RTMFP::ComputeAsymetricKeys(_sharedSecret,initiatorNonce.data(),initiatorNonce.size(),packet.data()+noncePos,size+11,decryptKey,encryptKey);
	
	waitHandle();
	return true;
}
예제 #6
0
void RTMFPWriter::acknowledgment(PacketReader& packet) {

	UInt64 bufferSize = packet.read7BitLongValue(); // TODO use this value in reliability mechanism?
	
	if(bufferSize==0) {
		// In fact here, we should send a 0x18 message (with id flow),
		// but it can create a loop... We prefer the following behavior
		fail("Negative acknowledgment");
		return;
	}

	UInt64 stageAckPrec = _stageAck;
	UInt64 stageReaden = packet.read7BitLongValue();
	UInt64 stage = _stageAck+1;

	if(stageReaden>_stage) {
		ERROR("Acknowledgment received ",stageReaden," superior than the current sending stage ",_stage," on writer ",id);
		_stageAck = _stage;
	} else if(stageReaden<=_stageAck) {
		// already acked
		if(packet.available()==0)
			DEBUG("Acknowledgment ",stageReaden," obsolete on writer ",id);
	} else
		_stageAck = stageReaden;

	UInt64 maxStageRecv = stageReaden;
	UInt32 pos=packet.position();

	while(packet.available()>0)
		maxStageRecv += packet.read7BitLongValue()+packet.read7BitLongValue()+2;
	if(pos != packet.position()) {
		// TRACE(stageReaden,"..x"Util::FormatHex(reader.current(),reader.available()));
		packet.reset(pos);
	}

	UInt64 lostCount = 0;
	UInt64 lostStage = 0;
	bool repeated = false;
	bool header = true;
	bool stop=false;

	auto it=_messagesSent.begin();
	while(!stop && it!=_messagesSent.end()) {
		RTMFPMessage& message(**it);

		if(message.fragments.empty()) {
			CRITIC("RTMFPMessage ",(stage+1)," is bad formatted on fowWriter ",id);
			++it;
			continue;
		}

		map<UInt32,UInt64>::iterator itFrag=message.fragments.begin();
		while(message.fragments.end()!=itFrag) {
			
			// ACK
			if(_stageAck>=stage) {
				message.fragments.erase(message.fragments.begin());
				itFrag=message.fragments.begin();
				++_ackCount;
				++stage;
				continue;
			}

			// Read lost informations
			while(!stop) {
				if(lostCount==0) {
					if(packet.available()>0) {
						lostCount = packet.read7BitLongValue()+1;
						lostStage = stageReaden+1;
						stageReaden = lostStage+lostCount+packet.read7BitLongValue();
					} else {
						stop=true;
						break;
					}
				}
				// check the range
				if(lostStage>_stage) {
					// Not yet sent
					ERROR("Lost information received ",lostStage," have not been yet sent on writer ",id);
					stop=true;
				} else if(lostStage<=_stageAck) {
					// already acked
					--lostCount;
					++lostStage;
					continue;
				}
				break;
			}
			if(stop)
				break;
			
			// lostStage > 0 and lostCount > 0

			if(lostStage!=stage) {
				if(repeated) {
					++stage;
					++itFrag;
					header=true;
				} else // No repeated, it means that past lost packet was not repeatable, we can ack this intermediate received sequence
					_stageAck = stage;
				continue;
			}

			/// Repeat message asked!
			if(!message.repeatable) {
				if(repeated) {
					++itFrag;
					++stage;
					header=true;
				} else {
					INFO("RTMFPWriter ",id," : message ",stage," lost");
					--_ackCount;
					++_lostCount;
					_stageAck = stage;
				}
				--lostCount;
				++lostStage;
				continue;
			}

			repeated = true;
			// Don't repeate before that the receiver receives the itFrag->second sending stage
			if(itFrag->second >= maxStageRecv) {
				++stage;
				header=true;
				--lostCount;
				++lostStage;
				++itFrag;
				continue;
			}

			// Repeat message

			DEBUG("RTMFPWriter ",id," : stage ",stage," repeated");
			UInt32 fragment(itFrag->first);
			itFrag->second = _stage; // Save actual stage sending to wait that the receiver gets it before to retry
			UInt32 contentSize = message.size() - fragment; // available
			++itFrag;

			// Compute flags
			UInt8 flags = 0;
			if(fragment>0)
				flags |= MESSAGE_WITH_BEFOREPART; // fragmented
			if(itFrag!=message.fragments.end()) {
				flags |= MESSAGE_WITH_AFTERPART;
				contentSize = itFrag->first - fragment;
			}

			UInt32 size = contentSize+4;
			UInt32 availableToWrite(_band.availableToWrite());
			if(!header && size>availableToWrite) {
				_band.flush();
				header=true;
			}

			if(header)
				size+=headerSize(stage);

			if(size>availableToWrite)
				_band.flush();

			// Write packet
			size-=3;  // type + timestamp removed, before the "writeMessage"
			flush(_band.writeMessage(header ? 0x10 : 0x11,(UInt16)size)
				,stage,flags,header,message,fragment,contentSize);
			header=false;
			--lostCount;
			++lostStage;
			++stage;
		}

		if(message.fragments.empty()) {
			if(message.repeatable)
				--_repeatable;
			if(_ackCount || _lostCount) {
				_qos.add(_lostCount / (_lostCount + _ackCount));
				_ackCount=_lostCount=0;
			}
			
			delete *it;
			it=_messagesSent.erase(it);
		} else
			++it;
	
	}

	if(lostCount>0 && packet.available()>0)
		ERROR("Some lost information received have not been yet sent on writer ",id);


	// rest messages repeatable?
	if(_repeatable==0)
		_trigger.stop();
	else if(_stageAck>stageAckPrec || repeated)
		_trigger.reset();
}
예제 #7
0
void FlowWriter::beginTransaction() {
	if(_transaction)
		CRITIC("beginTransaction seems have been called without have call a endTransaction after")
	_transaction=true;
}
예제 #8
0
/**************************
*** MAIN
**************************/
int main(int argc, char **argv)
{
    /*
    ** INIT SIGNALS
    */
    set_signals();

    /*
    ** INIT / SETTINGS VARS
    */
    client_count = 0;
    int port;

    /*
    ** ARGS MANAGEMENT
    */
    if(argc != 3 || !is_number(argv[2]))
    {
        CRITIC("Can't launch with these arguments.", "\tUsage: ./executable <directory> <port>");
    }

    port = atoi(argv[2]);

    if(port > 65535 || port < 1024)
    {
        CRITIC("Can't launch with this port.", "\tPort must be between 1024 and 65535.");
    }

    switch(check_directory(argv[1]))
    {
        case 0:
            strncpy(dir_path, argv[1], MAX_PATH - 1);
            if(dir_path[strlen(dir_path) - 1] != '/')
                strncat(dir_path, "/", 1);
            dir_path[MAX_PATH - 1] = '\0';
            break;
        case 1:
            // Ask to create directory
            INFO("Directory does not exist, do you want to create it? (yes/no)");
            char buffer[MAX_BUF];
            fgets(buffer, MAX_BUF, stdin);

            // If user said yes
            if(strcmp(buffer, "YES\n") == 0 || strcmp(buffer, "yes\n") == 0)
            {
                // Create directory and set full path
                create_directory(argv[1]);
                strncpy(dir_path, argv[1], MAX_PATH - 1);
                if(dir_path[strlen(dir_path) - 1] != '/')
                    strncat(dir_path, "/", 1);
                dir_path[MAX_PATH - 1] = '\0';
            }
            else
            {
                CRITIC("Can't launch with this directory.", "\tDirectory must exists.");
            }
            break;
        case 2:
            CRITIC("ERRNO ON STAT", strerror(errno));
            break;
        case 3:
            CRITIC("Can't launch with this directory.", "\tThe given path is not a directory.");
            break;
        case 4:
            CRITIC("Can't launch with this directory.", "\tYou don't have the required permissions.");
        default:
            CRITIC("Something impossible happened!", "Wrong switch value");
            break;
    }


    // INIT MUTEX
    if(pthread_mutex_init(&client_count_mutex, NULL) != 0)
    {
        CRITIC("Can't create client mutex", "MUTEX INIT ERROR");
    }
    if(pthread_mutex_init(&client_list_mutex, NULL) != 0)
    {
        CRITIC("Can't create list mutex", "MUTEX INIT ERROR");
    }
    /*
    ** SERVER MANAGEMENT
    */
    return start_server(port);
} // int main(int, char**)
예제 #9
0
/**************************
*** SERVER MANAGEMENT
**************************/
int start_server(int port)
{
    // Server socket
    int main_socket = socket(AF_INET, SOCK_STREAM, 0);

    // Set socket options to avoid waiting time
    int opt_val = 1;
    if(setsockopt(main_socket, SOL_SOCKET, SO_REUSEADDR, &opt_val, sizeof(opt_val)) < 0)
    {
        CRITIC("Error while setting socket", strerror(errno));
    }

    // Verify socket
    if(main_socket < 0)
    {
        CRITIC("Error while creating socket", strerror(errno));
    }

    // Setting the sockaddr_in struct
    struct sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(port);

    // Trying to bind the socket to the interface
    if(bind(main_socket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    {
        CRITIC("Error while binding socket", strerror(errno));
    }

    // Liten on socket
    if(listen(main_socket, MAX_PENDING) < 0)
    {
        CRITIC("Error while listening socket", strerror(errno));
    }

    // Sockets set
    fd_set in_desc;

    // Timeout setting
    struct timeval timeout_set;
    timeout_set.tv_sec = TIMEOUT_V;
    timeout_set.tv_usec = 1000 * TIMEOUT_V;

    INFO("Server started");

    while(server_listening)
    {
        // Setting the file desciptors set
        FD_ZERO(&in_desc);
        FD_SET(STDIN_FILENO, &in_desc);
        FD_SET(main_socket, &in_desc);

        // Select the socket to watch
        if(select(main_socket + 1, &in_desc , NULL , NULL , &timeout_set) < 0 && (errno != EINTR))
        {
            if(errno == EINTR)
            {
                WARNING("Select interupted", "No error is server is disconnecting");
                break;
            }
            else
            {
                CRITIC("Error while selecting sockets", strerror(errno));
            }
        }

        if(!server_listening)
            break;
        // If server socket changed state
        if(FD_ISSET(main_socket, &in_desc))
        {
            INFO("HERE");
            // Creating new client
            struct client_s *new_client = malloc(sizeof(struct client_s));
            new_client->client_addr_len = sizeof(struct sockaddr_in);

            // Accepting new client
            if ((new_client->client_socket = accept(main_socket, (struct sockaddr *)&new_client->client_addr, &new_client->client_addr_len)) < 0)
            {
                if(errno == EINTR)
                {
                    WARNING("Accept interupted", "No error is server is disconnecting");
                    break;
                }
                else
                {
                    CRITIC("Error while trying to accept new client", strerror(errno));
                }
            }

            INFO("Accepting new client");

            // Creating the client listening thread
            int ret;
            if((ret = pthread_create(&new_client->client_thread, NULL, client_thread, &new_client->client_socket)) != 0)
            {
                // In case of error
                if(ret == EAGAIN)
                {
                    ERROR("Can't create new client thread", "Insufficient resources");
                }
                else
                {
                    ERROR("Can't create new client thread", "Unknown");
                }

                if(close(new_client->client_socket) < 0)
                {
                    ERROR("Can't close new client socket", strerror(errno));
                }
                free(new_client);
            }
            else
            {
                // Adding the client to the list
                pthread_mutex_lock(&client_list_mutex);
                new_client->next = clients_list;
                new_client->prev = NULL;
                if(clients_list)
                {
                    clients_list->prev = new_client;
                }
                clients_list = new_client;
                pthread_mutex_unlock(&client_list_mutex);
                pthread_mutex_lock(&client_count_mutex);
                ++client_count;
                pthread_mutex_unlock(&client_count_mutex);
            }
        }

        // If stdin changed state
        if(FD_ISSET(STDIN_FILENO, &in_desc))
        {
            INFO("ECIT");
            char buffer[MAX_BUF];
            fgets(buffer, MAX_BUF, stdin);
            if(strcmp(buffer, "exit\n") == 0)
            {
                INFO("Server asked to quit");
                server_listening = server_kill();
            }
        }
    }

    INFO("Close main socket");
    if(close(main_socket) < 0)
    {
        ERROR("Can't close server socket", strerror(errno));
    }
    INFO("QUIT");
    return EXIT_SUCCESS;
} // int start_server(int)