示例#1
0
/**
 * This callback does things a bit differently.
 * Instead of using a MultiResult, we use a single HttpResult object.
 * We won't ever have "multiple" http objects.
 */
static void
http_complete_callback(lcb_http_request_t req,
                       lcb_t instance,
                       const void *cookie,
                       lcb_error_t err,
                       const lcb_http_resp_t *resp)
{
    pycbc_HttpResult *htres = (pycbc_HttpResult*)cookie;

    htres->htreq = NULL;
    htres->rc = err;
    htres->htcode = resp->v.v0.status;
    htres->htflags |= PYCBC_HTRES_F_COMPLETE;

    if (!htres->parent) {
        return;
    }


    PYCBC_CONN_THR_END(htres->parent);

    add_data(htres, resp->v.v0.bytes, resp->v.v0.nbytes);
    get_headers(htres, resp);
    finalize_data(htres);

    PYCBC_CONN_THR_BEGIN(htres->parent);

    if (htres->htflags & PYCBC_HTRES_F_CHUNKED) {
        /** No data here */
        if (!htres->parent->nremaining) {
            lcb_breakout(instance);
        }

        maybe_invoke_async_callback(htres);
        return;
    }

    if (htres->parent->flags & PYCBC_CONN_F_ASYNC) {
        maybe_invoke_async_callback(htres);
        return;
    }

    if (!--htres->parent->nremaining) {
        lcb_breakout(instance);
    }


    (void)instance;
    (void)req;
}
示例#2
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);
}