FConnection* FConnection::NewLC()
{
    FConnection* self = new ( ELeave ) FConnection();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
}
FConnection* FConnection::NewL()
{
    FConnection* self = FConnection::NewLC();
    CleanupStack::Pop( self );

    if (self->getLastError() != KErrNone) {
        // Something wrong.
        delete self;
        return NULL;
    }
    return self;
}
/**
 * CSymbianTransportAgent::ConstructL()
 * Second phase construction.
 */
void CSymbianTransportAgent::ConstructL(URL& /* aUrl */)
{
    
    // Open RHTTPSession with default protocol ("HTTP/TCP")
    // Note that RHTTPSession (and consequently the whole 
    // of HTTP) depends on the active scheduler; a scheduler 
    // must be installed when the session is opened and it 
    // must be running if a transaction is actually to do anything. 
    
    // Get the connection manager instance
    FConnection* connection = FConnection::getInstance();
    if (!connection) {
        LOG.error("TransportAgent: no active connection; exiting");
        setError(ERR_HTTP, "No active connection");
        return;
    }
    
    // Session is owned by FConnection!
    RSocketServ* socketServ = connection->getSession();
    RConnection* rConnection = connection->getConnection();
    // reuse active connection, please see:
    // http://wiki.forum.nokia.com/index.php/CS000825_-_Using_an_already_active_connection
    TInt err;
    TRAP( err, iHttpSession.OpenL() );
    User::LeaveIfError( err );

    // Set the session's connection info...
    RStringPool strPool = iHttpSession.StringPool();
    RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
    // ...to use the socket server
    connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketServ,RHTTPSession::GetTable() ),
                            THTTPHdrVal (socketServ->Handle()) );
    // ...to use the connection
    connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketConnection,RHTTPSession::GetTable() ),
                            THTTPHdrVal (REINTERPRET_CAST(TInt, rConnection)) );
     
    // Create the nested active scheduler
    // please see » Symbian OS v9.1 » Symbian OS reference » C++ component
    // reference » Base E32 » CActiveSchedulerWait
    iASWait = new (ELeave) CActiveSchedulerWait();
}
/**
 * CSymbianTransportAgent::sendMessage()
 */
char* CSymbianTransportAgent::sendMessage(const char* msg)
{
    LOG.debug("entering CSymbianTransportAgent::sendMessage"); 
    
    // Check if user aborted current sync.
    if (getLastErrorCode() == KErrCancel) {
        LOG.debug("Leaving sendMessage - lastErrorCode is %d", getLastErrorCode());
        User::Leave(KErrCancel);    // leave is trapped at SyncActiveObject::RunL().
    }
    
    // Just to be sure the response buffer is ok
    //TO BE VERIFIED!!!!
    delete iResponseBody;
    iResponseBody = NULL; 
    
    // Set the POST body
    delete iPostBody;
    iPostBody = NULL;

    if (url.fullURL == NULL) {
        setErrorF(ERR_CONNECT, "Empty URL"); 
        LOG.error("Transport Agent: empty URL");
        return NULL;
    }

    char* response = NULL;
    RStringF method;
    RHTTPHeaders hdr;
    // Parse string to URI (as defined in RFC2396)
    TUriParser8 uri;
    HBufC8* fullUrl = charToNewBuf8(url.fullURL); 
    TInt parseErr = uri.Parse(*fullUrl);
    if (parseErr != KErrNone) {
        setErrorF(ERR_CONNECT, "Malformed URL"); 
        LOG.error("Transport Agent: malformed url");
        goto finally;
    }

    {
        TPtrC8 ptr(reinterpret_cast<const TUint8*>(msg));
        iPostBody = HBufC8::NewL(ptr.Length());
        iPostBody->Des().Copy(ptr);
    }
    
    FConnection* connection = FConnection::getInstance();
    if (connection->isConnected() == false) {
        int res = connection->startConnection();
        if (res) {
            setErrorF(ERR_CONNECT, "Connection error (%d): please check your internet settings.", res); 
            LOG.error("%s", getLastErrorMsg());
            goto finally;
        }
    }

    // Get request method string for HTTP POST
    method = iHttpSession.StringPool().StringF( HTTP::EPOST, RHTTPSession::GetTable());

    // Open transaction with previous method and parsed uri. This class will 
    // receive transaction events in MHFRunL and MHFRunError.
    iHttpTransaction = iHttpSession.OpenTransactionL( uri, *this, method );

    // Set headers for request; user agent, accepted content type and body's 
    // content type.
    hdr = iHttpTransaction.Request().GetHeaderCollection();
    SetHeaderL(hdr, HTTP::EUserAgent, _L8("Funambol Symbian SyncML client"));
    SetHeaderL(hdr, HTTP::EAccept, _L8("*/*"));
    SetHeaderL(hdr, HTTP::EContentType, _L8("application/vnd.syncml+xml"));

    LOG.debug("Sending message:");
    LOG.debug("%s", msg);

    // Set data supplier for POST body
    // Please see  » Symbian OS v9.1 » Symbian OS guide » Using HTTP Client »
    // Handling request body data for explanation on this part
    iDataSupplier = this;
    iHttpTransaction.Request().SetBody(*iDataSupplier);     

    // Submit the transaction. After this the framework will give transaction
    // events via MHFRunL and MHFRunError.
    iHttpTransaction.SubmitL();

    // Start the scheduler, once the transaction completes or is cancelled on an
    // error the scheduler will be stopped in the event handler
    // This is a trick to implement a synchronous method
    LOG.debug("starting ASync scheduler...");
    iASWait->Start();  // TO BE VERIFIED!!!!
    LOG.debug("ASync scheduler stopped");
    
    
    // Check if user aborted current sync.
    if (getLastErrorCode() == KErrCancel) {
        LOG.debug("Leaving sendMessage - lastErrorCode is %d", getLastErrorCode());
        User::Leave(KErrCancel);    // leave is trapped at SyncActiveObject::RunL().
    }
    
    // when all is finished, return char* to be delete []
    if(!iTransFailed) {
        TInt length = iResponseBody->Des().Length();
        response = new char[length+1];
        Mem::Copy(response, iResponseBody->Ptr(), length);
        response[length] = '\0';

        LOG.debug("Message received:");
        LOG.debug("%s", response);
    }
    else {
        LOG.debug("HTTP transaction failed");
        setErrorF(ERR_HTTP, "HTTP request error: request timed out waiting for response");
    }

finally:

    // Transaction can be closed now. It's not needed anymore.
    LOG.debug("closing HTTP transaction");
    iHttpTransaction.Close();

    delete fullUrl;
    LOG.debug("exiting CSymbianTransportAgent::sendMessage");
    return response;
}
Exemple #5
0
void FSocket::ConstructL(const StringBuffer& peer, int32_t port) 
{
    //LOG.debug("FSocket::ConstructL");
    
    StringBuffer  errorMsg;
    RHostResolver resolver; 
    RBuf          serverName;
    TNameEntry    hostAddress;
    TInetAddr     address;
    TInt          res = KErrNone;

    serverName.Assign(stringBufferToNewBuf(peer));
    
    //
    // Get the connection manager instance
    //
    FConnection* connection = FConnection::getInstance();
    if (!connection) {
        iStatus = -1;
        errorMsg = "Error opening connection";
        goto error;
    }
    // Session is owned by FConnection!
    RSocketServ* session = connection->getSession();

    //
    // Open the Client Socket tcp/ip
    //
#ifdef __WINSCW__
    // WINSCW: simply open the socket
    res = iSocket.Open(*session, KAfInet, KSockStream, KProtocolInetTcp);
#else
    // GCCE: use the existing connection
    // If first time, connect to gprs
    if (!connection->isConnected()) {
        LOG.debug("FSocket: not connected, start new connection");
        if (connection->startConnection()) {
            iStatus = -1;
            errorMsg = "FSocket: error starting connection";
            goto error;
        }
    }
    RConnection* conn = connection->getConnection();
    
    LOG.debug("Opening socket and associate with existing connection");
    res = iSocket.Open(*session, KAfInet, KSockStream, KProtocolInetTcp, *conn);
    //LOG.debug("Socket opened (err = %d)", res);
#endif
    if (res != KErrNone) {
        iStatus = -1;
        errorMsg.sprintf("FSocket : Error opening socket. code %d", res);
        goto error;
    }
    
    
    // This works if serverName is the ip address, like "x.y.z.w"
    res = address.Input(serverName);
    
    if (res != KErrNone) {
        //
        // Try to resolve the host address. (On GCCE, use the existing RConnection)
        //
        LOG.debug("Resolve IP address...");
#ifdef __WINSCW__
        res = resolver.Open(*session, KAfInet, KProtocolInetTcp);
#else
        res = resolver.Open(*session, KAfInet, KProtocolInetTcp, *conn);
#endif
        if (res != KErrNone) {
            iStatus = -2;
            errorMsg.sprintf("FSocket: Host resolver open failed. code %d", res);
            goto error;
        }
        
        resolver.GetByName(serverName, hostAddress, iStatus);
        User::WaitForRequest(iStatus);
        resolver.Close();
        if (iStatus != KErrNone) {
            errorMsg.sprintf("FSocket: DNS lookup failed. code %d", iStatus.Int());
            goto error;
        }

        // Set the socket server address/port
        address = hostAddress().iAddr;
    }
    
    address.SetPort(port);
    
    
    // --- Connect to host ---
    LOG.debug("Socket connect...");
    iSocket.Connect(address, iStatus);
    User::WaitForRequest(iStatus);
    if (iStatus != KErrNone) {
        errorMsg.sprintf("FSocket: Failed to connect to Server. code %d", iStatus.Int()); 
        goto error;
    }

    serverName.Close();
    return;
    
error:
    LOG.error("%s", errorMsg.c_str());
    serverName.Close();
    return;
}