Exemple #1
0
DTerr DeviceNetworkSockets::udp_send (const NetworkPacket &packet, const NetworkSocket &socket)
{
	if (socket.is_empty())
		return DT3_ERR_NONE;

	DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data());
	
	struct sockaddr_storage sast = string_to_address(packet.network_address().network_address());
    struct sockaddr *sa = (struct sockaddr *) &sast;

#if DT3_OS == DT3_ANDROID
    ::sendto(   socket_raw, 
                packet.data(),
                packet.data_size(),
                0, 
                sa,
                sizeof(sockaddr));
#else
    ::sendto(   socket_raw, 
                packet.data(),
                (DTuint) packet.data_size(),
                0, 
                sa,
                sa->sa_len);
                
#endif

	return DT3_ERR_NONE;
}
Exemple #2
0
DTerr DeviceNetworkSockets::tcp_recv (NetworkPacket &packet, const NetworkSocket &socket)
{
	if (socket.is_empty())
		return DT3_ERR_NONE;

	DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data());

    ssize_t size = ::recv(  socket_raw,
                            packet.data(),
                            (DTuint) packet.data_size(),
                            0
                        );
                            

    if (size < 0) {
        packet.set_data_size(0);

        switch (errno) {
            //case EAGAIN:  // Same as EWOULDBLOCK
			case EWOULDBLOCK:	
                return DT3_ERR_NET_WOULD_BLOCK;
			default:			
                LOG_MESSAGE << "TCPRecv: recv: " << strerror(errno) << " (" << (DTuint) errno << ")";
                return DT3_ERR_NET_UNKNOWN;
		};
	} else {
        packet.set_data_size(size);
    }

	return DT3_ERR_NONE;
}
Exemple #3
0
DTerr DeviceNetworkSockets::udp_recv (NetworkPacket &packet, const NetworkSocket &socket)
{    
	if (socket.is_empty())
		return DT3_ERR_NONE;

	DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data());

    struct sockaddr from;
    socklen_t       from_size = sizeof(from);

    DTsize size = ::recvfrom(   socket_raw,
                                packet.data(),
                                (DTuint) packet.data_size(),
                                0, 
                                &from,
                                &from_size
                            );
                            
    if (size > 0) {
        packet.set_network_address( address_to_string(&from) );
        packet.set_data_size(size);
    
	} else {	
		switch (errno) {
			case EWOULDBLOCK:	return DT3_ERR_NET_WOULD_BLOCK;
			default:			return DT3_ERR_NET_UNKNOWN;
		};
	}

	return DT3_ERR_NONE;

}
Exemple #4
0
DTerr DeviceNetworkSockets::tcp_send (const NetworkPacket &packet, const NetworkSocket &socket)
{
	if (socket.is_empty())
		return DT3_ERR_NONE;

	DTint socket_raw = *reinterpret_cast<DTint*>(socket.network_socket_data());
	
    ::send(   socket_raw, 
                packet.data(),
                (DTuint) packet.data_size(),
                0
            );

	return DT3_ERR_NONE;
}
Exemple #5
0
void AssetDownloader::downloader_task   (   const URL url,
                                            const FilePath save_path,
                                            DTfloat timeout)
{
    std::shared_ptr<DeviceNetwork> network = System::network_manager();

    //
    // Connecting Phase
    //
    
    // Update status
    update_status (STATUS_CONNECTING, 0,0);
    
    // Resolve the host
    NetworkSocket socket;
    NetworkAddress ip; 
    
    DTerr err = network->resolve_host( ip, url.hostname(), url.port() );
    if (err != DT3_ERR_NONE) {
        LOG_MESSAGE << "HTTPRequest: Unable to resolve host.";
        update_status (STATUS_ERROR, 0,0);
        return;
    }
        
    err = network->tcp_open(socket,ip);
    if (err != DT3_ERR_NONE) {
        LOG_MESSAGE << "HTTPRequest: Unable to resolve host.";
        update_status (STATUS_ERROR, 0,0);
        return;
    }
        
	// Send http request
    std::string server = url.hostname();
    std::string path = url.path();
    
    // Note:
    // HTTP/1.1 defines the "close" connection option for the sender to signal that the connection 
    // will be closed after completion of the response. For example,
    //      Connection: close
    // in either the request or the response header fields indicates that the connection SHOULD NOT
    // be considered `persistent' (section 8.1) after the current request/response is complete.
    // HTTP/1.1 applications that do not support persistent connections MUST include the "close" 
    // connection option in every message.

    std::string request =   "GET " + path + " HTTP/1.1\r\n" +
                            "Host: " + server + "\r\n" +
                            "User-Agent: DT3\r\n" +
                            "Accept: */*\r\n" +
                            "Cache-Control: max-age=0\r\n" +
                            "Connection: close\r\n" +
                            "\r\n";

    LOG_MESSAGE << "Sending...";
    LOG_MESSAGE << request;
    
    NetworkPacket packet_request;
    packet_request.set_data(request);
    
    err = network->tcp_send(packet_request, socket);
    if (err != DT3_ERR_NONE) {
        network->tcp_close(socket);
        
        LOG_MESSAGE << "HTTPRequest: Unable to send packet.";
        update_status (STATUS_ERROR, 0,0);
        return;
    }
    
    //
    // Downloading Phase
    //
    
    update_status (STATUS_DOWNLOADING, 0,0);

    // Hash the URL
    FilePath temp_file_path = FilePath(HAL::save_dir().full_path() + "/" + MoreStrings::cast_to_string(MoreStrings::hash(url.full_url())));
    
    // Create a temporary file
    BinaryFileStream temp_file;
    err = FileManager::open(temp_file, temp_file_path, false);
    
    if (err != DT3_ERR_NONE) {
        network->tcp_close(socket);
        
        LOG_MESSAGE << "HTTPRequest: Unable to open file for writing.";
        update_status (STATUS_ERROR, 0,0);
        return;
    }
    
    LOG_MESSAGE << "HTTPRequest: Opened temp file at " << temp_file_path.full_path();

    
    // Temporary storage for buffer
    std::string data;
        
    // Timer for timeout
    TimerHires timeout_timer;
    
    do {

        // Get the results
        NetworkPacket packet;
        packet.set_data_size(1024*16);

        err = network->tcp_recv(packet,socket);
        
        // If we recieved some data, append it to the buffer
        if (packet.data_size() > 0) {
            data += packet.data_as_string();
            append_data(data, temp_file);
            timeout_timer.reset_abs_time();
        }
        
        // Check complete
        if ( (_current_size == _total_size) && (_total_size > 0) ) {
            break;
        }
        
        // If we hit our timeout, then we abort
        if (timeout_timer.abs_time() > timeout) {
            network->tcp_close(socket);
            
            LOG_MESSAGE << "Http request timed out!";
            update_status (STATUS_ERROR, 0,0);
            
            // Remove the temporary file
            temp_file_path.del();
            return;
        }
        
        // Check for cancel
        if (_cancelled) {
            network->tcp_close(socket);
            
            LOG_MESSAGE << "Http request cancelled!";
            update_status (STATUS_CANCELLED, 0,0);
            
            // Remove the temporary file
            temp_file_path.del();
            return;
        }
        
    } while (err == DT3_ERR_NET_WOULD_BLOCK || err == DT3_ERR_NONE);
    
    // Close the connection, we're done
    network->tcp_close(socket);
    
    // Close off the stream
    finalize_data(data, temp_file);

    //
    // Finalizing phase
    //
    
    // Move the file
    save_path.del();
    temp_file_path.move(save_path);
    
    LOG_MESSAGE << "Saving file to " << save_path.full_path();


    // Final update of status
    update_status (STATUS_COMPLETE, _current_size, _total_size);
}