void MethodResultJni::callRubyBack(jboolean jReleaseCallback)
{
    RAWTRACE(__FUNCTION__);
    RAWTRACE(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

    jhstring jhStrCallbackData = getStrCallbackData(m_env);
    jlong jRubyProc = getRubyProcCallback(m_env);

    if (jRubyProc != 0)
    {
        VALUE oProc = static_cast<VALUE>(jRubyProc);
        rho::String strResBody = RHODESAPP().addCallbackObject(new CRubyCallbackResult<MethodResultJni>(*this), "body");

        RAWTRACE1("Call Ruby proc by address: 0x%.8x", oProc);

        RHODESAPP().callCallbackProcWithData( oProc, strResBody, rho_cast<rho::String>(m_env, jhStrCallbackData.get()), true);

        if(static_cast<bool>(jReleaseCallback))
        {
            releaseRubyProcCallback(jRubyProc);
        }
    }
    else
    {
        jhstring jhStrCallback = getStrCallback(m_env);
        String strCallback = rho_cast<String>(m_env, jhStrCallback.get());
        if(strCallback.length())
        {
            RAWTRACE1("Call Ruby controller by URL: %s", rho_cast<rho::String>(jhStrCallback.get()).c_str());

            rho::String strResBody = RHODESAPP().addCallbackObject(new CRubyCallbackResult<MethodResultJni>(*this), "__rho_inline");
            RHODESAPP().callCallbackWithData(rho_cast<rho::String>(m_env, jhStrCallback.get()), strResBody, rho_cast<rho::String>(m_env, jhStrCallbackData.get()), true);
        }
    }
}
Beispiel #2
0
MethodResultJni::MethodResultJni(const MethodResultJni& result) : m_env(0), m_jhResult(0), m_bGlobalRef(false), m_bSlaveRef(false), m_hasCallback(false), m_resType(typeNone)
{
    JNIEnv* env = result.m_env;
    if(result.m_bGlobalRef) {
        RAWTRACE1("Copying MethodResult with global JNI reference: 0x%.8x ---------------------------------------", result.m_jhResult.get());
        m_jhResult = result.m_jhResult.get();
        result.m_bSlaveRef = true;
    } else {
        m_jhResult = env->NewGlobalRef(result.m_jhResult.get());
        RAWTRACE1("Copying MethodResult creating global JNI reference: 0x%.8x >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", m_jhResult.get());
    }
    m_bGlobalRef = true;
}
Beispiel #3
0
const PbPageParam* rho_phonebook_getpageparams(rho_param* param, PbPageParam* page)
{
    bool offset = false;
    bool per_page = false;
    if(param == 0 || page == 0)
    {
        RAWTRACE2("Param(0x%.8X) or page(0x%.8X) is NULL, skipping", param, page);
        return 0;
    }
    if (param->type == RHO_PARAM_HASH)
    {
        for (int i = 0, lim = param->v.hash->size; i < lim; ++i)
        {
            const char* key = param->v.hash->name[i];
            rho_param* value = param->v.hash->value[i];
            
            if (strcasecmp(key, "offset") == 0)
            {
                RAWTRACE("'offset' parameter found");
                if (value->type == RHO_PARAM_STRING)
                {
                    RAWTRACE1("'offset' parameter is string: %s", value->v.string);
                    sscanf(value->v.string, "%d", &page->offset);
                    offset = true;
                }
            } else if (strcasecmp(key, "per_page") == 0)
            {
                RAWTRACE("'per_page' parameter found");
                if (value->type == RHO_PARAM_STRING)
                {
                    RAWTRACE1("'per_page' parameter is string: %s", value->v.string);
                    sscanf(value->v.string, "%d", &page->per_page);
                    per_page = true;
                }
            }
            if(offset && per_page) break;
        }
    }
    else
    {
        RAWTRACE("rho_param is not a hash!");
    }
    if(!offset)
        page->offset = 0;
    if(!per_page)
        page->per_page = -1;

    return page;
}
int MethodResultJni::getResultType(JNIEnv* env) const
{
    RAWTRACE(__FUNCTION__);
    if(m_resType == typeNone && m_jhResult)
    {
        m_javaResultType = env->CallIntMethod(m_jhResult.get(), s_midGetResultType);
        RAWTRACE1("Java result type: %d", m_javaResultType);

        return m_javaResultType;
    } else
    {
        RAWTRACE1("Native result type: %d", m_resType);
        return m_resType;
    }
}
Beispiel #5
0
static size_t curlHeaderCallback(void *ptr, size_t size, size_t nmemb, void *opaque)
{
    Hashtable<String,String>* pHeaders = (Hashtable<String,String>*)opaque;
    size_t nBytes = size*nmemb;
    String strHeader((const char *)ptr, nBytes);
    RAWTRACE1("Received header: %s", strHeader.c_str());
    
    int nSep = strHeader.find(':');
    if (nSep > 0 )
    {		
        String strName = String_trim(strHeader.substr(0, nSep));
        String lName;
        std::transform(strName.begin(), strName.end(), std::back_inserter(lName), &::tolower);
        
        String strValue = String_trim(strHeader.substr(nSep+1, strHeader.length() - (nSep+3) ));
        
        if ( pHeaders->containsKey(lName) )
        {
            strValue += ";" + pHeaders->get( lName );
            pHeaders->put( lName, strValue );
        }
        else
            pHeaders->put(lName, strValue);
    }
    
    return nBytes;
}
Beispiel #6
0
int CURLNetRequest::getResponseCode(CURLcode err, char const *body, size_t bodysize, IRhoSession* oSession )	
{    
    //if (err != CURLE_OK)
    //    return -1;

    if (!body) {
        body = "";
        bodysize = 0;
    }
	
    long statusCode = 0;
    CURL *curl = m_curl.curl();
    if (curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode) != 0)
        statusCode = 500;
    
	if (statusCode == 416) {
		statusCode = 206;
	}
	
    if (statusCode >= 400) {
        RAWLOG_ERROR2("Request failed. HTTP Code: %d returned. HTTP Response: %s",
                      (int)statusCode, body);
        if (statusCode == 401)
            if (oSession)
                oSession->logout();
    }
    else {
        RAWTRACE1("RESPONSE----- (%d bytes)", bodysize);
        RAWTRACE(body);
        RAWTRACE("END RESPONSE-----");
    }

    return (int)statusCode;
}
Beispiel #7
0
VALUE require_compiled(VALUE fname, VALUE* result)
{
    VALUE path;
    char* szName = 0;
//    FilePathValue(fname);

	szName = RSTRING_PTR(fname);
    RAWTRACE1("require_compiled: %s", szName);

    rb_funcall(fname, rb_intern("sub!"), 2, rb_str_new2(".rb"), rb_str_new2("") );

    if ( strcmp("strscan",szName)==0 || strcmp("enumerator",szName)==0 )
        return Qtrue;

    path = find_file(fname);

    if ( path != 0 )
    {
        VALUE seq;
		
        if ( isAlreadyLoaded(path) == Qtrue )
            return Qtrue;

        rb_ary_push(GET_VM()->loaded_features, path);

        seq = loadISeqFromFile(path);

        //*result = rb_funcall(seq, rb_intern("eval"), 0 );
        *result = rb_iseq_eval(seq);

        return Qtrue;
    }

    return Qnil;
}
Beispiel #8
0
void MapProvider::unregisterMapEngine(String const &id)
{
    RAWTRACE1("Unregister map engine: id=%s", id.c_str());
    IMapEngine *engine = m_engines.get(id);
    if (engine)
        delete engine;
    m_engines.remove(id);
}
Beispiel #9
0
static size_t curlBodyStringCallback(void *ptr, size_t size, size_t nmemb, void *opaque)
{
    String *pStr = (String *)opaque;
    size_t nBytes = size*nmemb;
    RAWTRACE1("Received %d bytes", nBytes);
    pStr->append((const char *)ptr, nBytes);
    return nBytes;
}
Beispiel #10
0
static size_t curlBodyBinaryCallback(void *ptr, size_t size, size_t nmemb, void *opaque)
{
    Vector<char> *pBody = (Vector<char> *)opaque;
    size_t nBytes = size*nmemb;
    RAWTRACE1("Received %d bytes", nBytes);
    std::copy((char*)ptr, (char*)ptr + nBytes, std::back_inserter(*pBody));
    return nBytes;
}
Beispiel #11
0
MethodResultJni::~MethodResultJni()
{
    if(m_bGlobalRef)
    {
        jobject jResult = m_jhResult.release();
        if(!m_bSlaveRef)
        {
            RAWTRACE1("Deleting MethodResult global JNI reference: 0x%.8x ==========================================", jResult);
            m_env->DeleteGlobalRef(jResult);
        }
    }
}
Beispiel #12
0
void CBarcode1::setDefaultID(const rho::String& id)
{
    RAWTRACE1("setDefaultID(id = \"%s\")", id.c_str());

    JNIEnv *env = jniInit();
    if (!env) {
        RAWLOG_ERROR("JNI initialization failed");
        return;
    }

    jhobject instance = getSingleton(env);
    jhstring jhId = rho_cast<jstring>(env, id);
    env->CallVoidMethod(instance.get(), s_midSetDefaultID, jhId.get());
}
Beispiel #13
0
unsigned long CRhoTimer::getNextTimeout()
{
    synchronized(m_mxAccess);

    if ( (m_arItems.size() == 0) && (m_arNativeItems.size() == 0) )
        return 0;

    CTimeInterval curTime = CTimeInterval::getCurrentTime();
    unsigned long nMinInterval = ((unsigned long)-1);

    for( int i = 0; i < (int)m_arItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{	
        		nInterval=nMinInterval+m_arItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }

    for( int i = 0; i < (int)m_arNativeItems.size(); i++ )
    {
        unsigned long nInterval = 0;
        if ( m_arNativeItems.elementAt(i).m_oFireTime.toULong() > curTime.toULong() )
    		{
            nInterval = m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}
    		else
    		{	
        		nInterval=nMinInterval+m_arNativeItems.elementAt(i).m_oFireTime.toULong() - curTime.toULong();
    		}

        if ( nInterval < nMinInterval )
            nMinInterval = nInterval;
    }


    if ( nMinInterval < 100 )
        nMinInterval = 100;

    RAWTRACE1("CRhoTimer::getNextTimeout: %d",nMinInterval);

    return nMinInterval;
}
Beispiel #14
0
std::string rho_cast_helper<std::string, jstring>::operator()(JNIEnv *env, jstring s)
{
    if(env->IsSameObject(s, NULL) == JNI_TRUE)
    {
        //Avoid crash in case of null java reference
        RAWTRACE("rho_cast<string, jstring>: \"\"");
        return std::string();
    } else
    {
        const char *ts = env->GetStringUTFChars(s, JNI_FALSE);
        std::string ret(ts);
        env->ReleaseStringUTFChars(s, ts);
        RAWTRACE1("rho_cast<string, jstring>: %s", ret.c_str());
        return ret;
    }
}
Beispiel #15
0
RHO_GLOBAL void JNICALL Java_com_rhomobile_rhodes_api_MethodResult_nativeCallBack
  (JNIEnv * env, jobject jResult, jint jTabId, jboolean jIsRuby, jboolean jReleaseCallback)
{
    RAWTRACE1("nativeCallBack - env: 0x%.8x", env);

    initjnienv(env);

    MethodResultJni result(env, jResult);
    if (static_cast<bool>(jIsRuby))
    {
        result.callRubyBack(jReleaseCallback);
    } else
    {
        result.callJSBack(jTabId);
    }
}
Beispiel #16
0
void CBarcode1::setJavaFactory(JNIEnv* env, jobject jFactory)
{
    RAWTRACE("setJavaFactory");

    env = jniInit(env);
    if (!env) {
        RAWLOG_ERROR("JNI initialization failed");
        return;
    }

    RAWTRACE1("s_clsFactorySingleton: 0x%.8X ------------------------------------", s_clsFactorySingleton);

    env->CallStaticVoidMethod(s_clsFactorySingleton, s_midFactorySetInstance, jFactory);

    RAWTRACE("setJavaFactory succeeded");
}
MethodResultJni::~MethodResultJni()
{
	if(m_bhasLocalFrame && m_env)
	{
		m_bhasLocalFrame = false;
		m_env->PopLocalFrame(NULL);
	}
    if(m_bGlobalRef)
    {
        jobject jResult = m_jhResult.release();
        if(!m_bSlaveRef)
        {
            RAWTRACE1("Deleting MethodResult global JNI reference: 0x%.8x ==========================================", jResult);
            m_env->DeleteGlobalRef(jResult);
        }
    }
}
Beispiel #18
0
extern "C" void Init_Led(void)
{
    RAWTRACE(__FUNCTION__);

    JNIEnv *env = jnienv();
    if(env)
    {
        jclass cls = rho_find_class(env, LED_FACTORY_CLASS);
        if(!cls)
        {
            RAWLOG_ERROR1("Failed to find java class: %s", LED_FACTORY_CLASS);
            return;
        }
        jmethodID midFactory = env->GetMethodID(cls, "<init>", "()V");
        if(!midFactory)
        {
            RAWLOG_ERROR1("Failed to get constructor for java class %s", LED_FACTORY_CLASS);
            return;
        }
        jobject jFactory = env->NewObject(cls, midFactory);
        if(env->IsSameObject(jFactory, NULL))
        {
            RAWLOG_ERROR1("Failed to create %s instance", LED_FACTORY_CLASS);
            return;
        }
        
        RAWTRACE("Initializing Java factory");

        rho::notification::CLedBase::setJavaFactory(env, jFactory);

        RAWTRACE("Deleting JNI reference");

        env->DeleteLocalRef(jFactory);

        RAWTRACE("Initializing API");

        Init_Led_API();

        RAWTRACE1("%s succeeded", __FUNCTION__);
    }
    else
    {
        RAWLOG_ERROR1("%s failed: jnienv() is failed", __FUNCTION__);
    }
}
Beispiel #19
0
void CRhoTimer::stopTimer(const char* szCallback)
{
    RAWTRACE1("CRhoTimer::stopTimer: %s",szCallback);

    synchronized(m_mxAccess);

    if ( !szCallback || !*szCallback)
        m_arItems.removeAllElements();

    for( int i = (int)m_arItems.size()-1; i >= 0; i--)
    {
        CTimerItem oItem = m_arItems.elementAt(i);
        if ( oItem.m_strCallback.compare(szCallback) == 0 )
        {
            m_arItems.removeElementAt(i);
        }
    }
}
Beispiel #20
0
static VALUE db_execute(int argc, VALUE *argv, VALUE self)
{
	sqlite3 * db = NULL;
	void **ppDB = NULL;		
	sqlite3_stmt *statement = NULL;
	const char* sql = NULL;
	VALUE arRes = rb_ary_new();
    VALUE* colNames = NULL;
	int nRes = 0;
    char * szErrMsg = 0;
    int is_batch = 0;

	if ((argc < 2) || (argc > 3))
		rb_raise(rb_eArgError, "wrong # of arguments(%d for 3)",argc);
	
	Data_Get_Struct(self, void *, ppDB);
	db = (sqlite3 *)rho_db_get_handle(*ppDB);
	sql = RSTRING_PTR(argv[0]);
    is_batch = argv[1] == Qtrue ? 1 : 0;

    RAWTRACE1("db_execute: %s", sql);

    PROF_START_CREATED("SQLITE");
    if ( is_batch )
    {
        PROF_START_CREATED("SQLITE_EXEC");

        rho_db_lock(*ppDB);
        nRes = sqlite3_exec(db, sql,  NULL, NULL, &szErrMsg);
        rho_db_unlock(*ppDB);

        PROF_STOP("SQLITE_EXEC");
    }
    else
    {
        rho_db_lock(*ppDB);
        PROF_START_CREATED("SQLITE_PREPARE");
        nRes = rho_db_prepare_statement(*ppDB, sql, -1, &statement);
        PROF_STOP("SQLITE_PREPARE");
        //nRes = sqlite3_prepare_v2(db, sql, -1, &statement, NULL);
        if ( nRes != SQLITE_OK)
        {
            szErrMsg = (char *)sqlite3_errmsg(db);
            rho_db_unlock(*ppDB);

            rb_raise(rb_eArgError, "could not prepare statement: %d; Message: %s",nRes, (szErrMsg?szErrMsg:""));
        }

        if ( argc > 2 )
        {
            int i = 0;
            VALUE args = argv[2];
            if ( RARRAY_LEN(args) > 0 && TYPE(RARRAY_PTR(args)[0]) == T_ARRAY )
                args = RARRAY_PTR(args)[0];

            for( ; i < RARRAY_LEN(args); i++ )
            {
                VALUE arg = RARRAY_PTR(args)[i];
                if (NIL_P(arg))
                {
                    sqlite3_bind_null(statement, i+1);
                    continue;
                }

                switch( TYPE(arg) )
                {
                case T_STRING:
                    sqlite3_bind_text(statement, i+1, RSTRING_PTR(arg), RSTRING_LEN(arg), SQLITE_TRANSIENT);
                    break;
                case T_FLOAT:
                    sqlite3_bind_double(statement, i+1, NUM2DBL(arg));
                    break;
                case T_FIXNUM:
                case T_BIGNUM:
                    sqlite3_bind_int64(statement, i+1, NUM2LL(arg));
                    break;
                default:
					{
						VALUE strVal = rb_funcall(arg, rb_intern("to_s"), 0);	
	                    sqlite3_bind_text(statement, i+1, RSTRING_PTR(strVal), -1, SQLITE_TRANSIENT);	
					}
					break;
                }
            }
        }

        PROF_START_CREATED("SQLITE_EXEC");
        nRes = sqlite3_step(statement);
        PROF_STOP("SQLITE_EXEC");

	    while( nRes== SQLITE_ROW ) {
		    int nCount = sqlite3_data_count(statement);
		    int nCol = 0;
		    VALUE hashRec = rb_hash_new();

            //if ( !colNames )
            //    colNames = getColNames(statement, nCount);

		    for(;nCol<nCount;nCol++){
			    int nColType = sqlite3_column_type(statement,nCol);
			    const char* szColName = sqlite3_column_name(statement,nCol);
			    VALUE colName = rb_str_new2(szColName);
			    VALUE colValue = Qnil;
    			
			    switch(nColType){
				    case SQLITE_NULL:
					    break;
                    case SQLITE_FLOAT:
                    {
                        double dVal = sqlite3_column_double(statement, nCol);
                        colValue = DBL2NUM(dVal);
                        break;
                    }
                    case SQLITE_INTEGER:
                    {
                        sqlite_int64 nVal = sqlite3_column_int64(statement, nCol);
                        colValue = LL2NUM(nVal);
                        break;
                    }
				    default:{
                        sqlite3_value * sqlValue = sqlite3_column_value(statement, nCol);
                        int nLen = sqlite3_value_bytes(sqlValue);
                        const char*  szValue = (const char *)sqlite3_value_text(sqlValue);
					    //char *text = (char *)sqlite3_column_text(statement, nCol);
					    colValue = rb_str_new(szValue, nLen);
					    break;
				    }
			    }
    			
			    rb_hash_aset(hashRec, colName/*colNames[nCol]*/, colValue);
		    }
    		
		    rb_ary_push(arRes, hashRec);

            PROF_START_CREATED("SQLITE_EXEC");
            nRes = sqlite3_step(statement);
            PROF_STOP("SQLITE_EXEC");

	    }

        rho_db_unlock(*ppDB);

    }

    if ( statement )
        //sqlite3_finalize(statement);
        sqlite3_reset(statement);

    if ( colNames )
        free(colNames);

    if ( nRes != SQLITE_OK && nRes != SQLITE_ROW && nRes != SQLITE_DONE )
    {
        if ( !szErrMsg )
            szErrMsg = (char*)sqlite3_errmsg(db);

        rb_raise(rb_eArgError, "could not execute statement: %d; Message: %s",nRes, (szErrMsg?szErrMsg:""));
    }

    PROF_STOP("SQLITE");

	return arRes;
}
Beispiel #21
0
jstring rho_cast_helper<jstring, char const *>::operator()(JNIEnv *env, char const *s)
{
    RAWTRACE1("rho_cast<jstring, string>: %s", s);

    return s ? env->NewStringUTF(s) : (jstring)0;
}
Beispiel #22
0
jobject event_cast<jobject, VALUE>(VALUE rEvent)
{
    if (NIL_P(rEvent))
        return NULL;

    RHO_TRACE("eventFromRuby (1)");
    JNIEnv *env = jnienv();
    if (!init_event_stuff(env))
        return NULL;

    RHO_TRACE("eventFromRuby (2)");
    VALUE rId = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_ID));
    if (NIL_P(rId))
        rId = rb_str_new2("");
    Check_Type(rId, T_STRING);

    RHO_TRACE("eventFromRuby (3)");
    jmethodID mid = getJNIClassMethod(env, clsEvent, "<init>", "(Ljava/lang/String;)V");
    if (!mid) return NULL;
    jobject jEvent = env->NewObject(clsEvent, mid, rho_cast<jhstring>(RSTRING_PTR(rId)).get());
    if (!jEvent) return NULL;

    RHO_TRACE("eventFromRuby (4)");
    VALUE rTitle = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_TITLE));
    if (!NIL_P(rTitle))
    {
        Check_Type(rTitle, T_STRING);
        env->SetObjectField(jEvent, fidTitle, rho_cast<jhstring>(RSTRING_PTR(rTitle)).get());
    }

    RHO_TRACE("eventFromRuby (5)");
    VALUE rStartDate = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_START_DATE));
    if (!NIL_P(rStartDate))
        env->SetObjectField(jEvent, fidStartDate, date_cast<jobject>(rStartDate));

    RHO_TRACE("eventFromRuby (6)");
    VALUE rEndDate = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_END_DATE));
    if (!NIL_P(rEndDate))
        env->SetObjectField(jEvent, fidEndDate, date_cast<jobject>(rEndDate));

    RHO_TRACE("eventFromRuby (7)");
    VALUE rLastModified = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_LAST_MODIFIED));
    if (!NIL_P(rLastModified))
        env->SetObjectField(jEvent, fidLastModified, date_cast<jobject>(rLastModified));

    RHO_TRACE("eventFromRuby (8)");
    VALUE rLocation = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_LOCATION));
    if (!NIL_P(rLocation))
    {
        Check_Type(rLocation, T_STRING);
        env->SetObjectField(jEvent, fidLocation, rho_cast<jhstring>(RSTRING_PTR(rLocation)).get());
    }

    RHO_TRACE("eventFromRuby (9)");
    VALUE rNotes = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_NOTES));
    if (!NIL_P(rNotes))
    {
        Check_Type(rNotes, T_STRING);
        env->SetObjectField(jEvent, fidNotes, rho_cast<jhstring>(RSTRING_PTR(rNotes)).get());
    }

    RHO_TRACE("eventFromRuby privacy");
    VALUE rPrivacy = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_PRIVACY));
    if (!NIL_P(rPrivacy))
    {
        Check_Type(rPrivacy, T_STRING);
        env->SetObjectField(jEvent, fidPrivacy, rho_cast<jhstring>(RSTRING_PTR(rPrivacy)).get());
    }

    RHO_TRACE("eventFromRuby recurrence");
    VALUE rRecurrence = rb_hash_aref(rEvent, rb_str_new2(RUBY_EV_RECURRENCE));
    if (!NIL_P(rRecurrence)) {
        Check_Type(rRecurrence, T_HASH);

        VALUE rFrequency = rb_hash_aref(rRecurrence, rb_str_new2(RUBY_EV_RECURRENCE_FREQUENCY));
        Check_Type(rFrequency, T_STRING);
        const char *frequency = RSTRING_PTR(rFrequency);
        if (   strcasecmp(frequency, RUBY_EV_RECURRENCE_FREQUENCY_DAILY) != 0
        	&& strcasecmp(frequency, RUBY_EV_RECURRENCE_FREQUENCY_WEEKLY) != 0
        	&& strcasecmp(frequency, RUBY_EV_RECURRENCE_FREQUENCY_MONTHLY) != 0
        	&& strcasecmp(frequency, RUBY_EV_RECURRENCE_FREQUENCY_YEARLY) != 0)
        {
        	rb_raise(rb_eArgError, "Wrong recurrence frequency: %s", frequency);
        }
        env->SetObjectField(jEvent, fidFrequency, rho_cast<jhstring>(RSTRING_PTR(rFrequency)).get());

        VALUE rInterval = rb_hash_aref(rRecurrence, rb_str_new2(RUBY_EV_RECURRENCE_INTERVAL));
        rInterval = rb_funcall(rInterval, rb_intern("to_i"), 0);
        int interval = NUM2INT(rInterval);
        env->SetIntField(jEvent, fidInterval, interval);
        RAWTRACE1("eventFromRuby recurrence interval: %d", interval);

        VALUE rUntilDate = rb_hash_aref(rRecurrence, rb_str_new2(RUBY_EV_RECURRENCE_END));
        if (!NIL_P(rUntilDate))
        {
            env->SetObjectField(jEvent, fidRecurrenceEnd, date_cast<jobject>(rUntilDate));
            RAWTRACE("eventFromRuby recurrence until date");
        }

        VALUE rTimes = rb_funcall(rb_hash_aref(rRecurrence, rb_str_new2(RUBY_EV_RECURRENCE_COUNT)), rb_intern("to_i"), 0);;
        int times = NUM2INT(rTimes);
        env->SetIntField(jEvent, fidRecurrenceTimes, times);
        RAWTRACE1("eventFromRuby recurrence count: %d", times);
    }

    RHO_TRACE("eventFromRuby: return");
    return jEvent;
}
Beispiel #23
0
RHO_GLOBAL int rho_net_ping_network(const char* szHost)
{
    RAWTRACE1("Ping host: %s", szHost);
    return 1;
}
Beispiel #24
0
bool CHttpServer::receive_request(ByteVector &request)
{
	if (verbose) RAWTRACE("Receiving request...");

	ByteVector r;
    char buf[BUF_SIZE];
    int attempts = 0;
    for(;;) {
        if (verbose) RAWTRACE("Read portion of data from socket...");
        int n = recv(m_sock, &buf[0], sizeof(buf), 0);
        //RAWTRACE1("RECV: %d", n);
        if (n == -1) {
            int e = RHO_NET_ERROR_CODE;
            if (verbose) RAWTRACE1("RECV ERROR: %d", e);
#if !defined(WINDOWS_PLATFORM)
            if (e == EINTR)
                continue;
#else
			if (e == WSAEINTR)
				continue;
#endif

#if defined(OS_WP8) || (defined(RHODES_QT_PLATFORM) && defined(OS_WINDOWS_DESKTOP)) || defined(OS_WINCE)
            if (e == EAGAIN || e == WSAEWOULDBLOCK) {
#else
            if (e == EAGAIN) {
#endif
                if (!r.empty())
                    break;
                
                if(++attempts > (HTTP_EAGAIN_TIMEOUT*10))
                {
                    if (verbose) RAWLOG_ERROR("Error when receiving data from socket. Client does not send data for " HTTP_EAGAIN_TIMEOUT_STR " sec. Cancel recieve.");
                    return false;
                }

                fd_set fds;
                FD_ZERO(&fds);
                FD_SET(m_sock, &fds);
                timeval tv = {0};
				tv.tv_usec = 100000;//100 MS
                select(m_sock + 1, &fds, 0, 0, &tv);
                continue;
            }
            
            if (verbose) RAWLOG_ERROR1("Error when receiving data from socket: %d", e);
            return false;
        }
        
        if (n == 0) {
            if(!r.empty()) {
                if (verbose) RAWTRACE("Client closed connection gracefully");
                break;
            } else {
                if (verbose) RAWLOG_ERROR("Connection gracefully closed before we receive any data");
                return false;
            }
        } else {
            if (verbose) RAWTRACE1("Actually read %d bytes", n);
            r.insert(r.end(), &buf[0], &buf[0] + n);
        }
    }
    
    if (!r.empty()) {
        request.insert(request.end(), r.begin(), r.end());
        if ( !rho_conf_getBool("log_skip_post") ) {
            String strRequest(request.begin(),request.end());
            if (verbose) RAWTRACE1("Received request:\n%s", strRequest.c_str());
        }
    }
    return true;
}

bool CHttpServer::send_response_impl(String const &data, bool continuation)
{
#ifdef OS_MACOSX
    if ( m_localResponseWriter != 0 ) {
      m_localResponseWriter->writeResponse( data );
      return true;
    }
#endif

    if (verbose) {
        if (continuation)
            if (verbose) RAWTRACE("Send continuation data...");
        else
            if (verbose) RAWTRACE("Sending response...");
    }
    
    // First of all, make socket blocking
#if defined(WINDOWS_PLATFORM)
    unsigned long optval = 0;
        if(::ioctlsocket(m_sock, FIONBIO, &optval) == SOCKET_ERROR) {
        RAWLOG_ERROR1("Can not set blocking socket mode: %d", RHO_NET_ERROR_CODE);
        return false;
    }
#else
    int flags = fcntl(m_sock, F_GETFL);
    if (flags == -1) {
        if (verbose) RAWLOG_ERROR1("Can not get current socket mode: %d", errno);
        return false;
    }
    if (fcntl(m_sock, F_SETFL, flags & ~O_NONBLOCK) == -1) {
        if (verbose) RAWLOG_ERROR1("Can not set blocking socket mode: %d", errno);
        return false;
    }
#endif
    
    size_t pos = 0;
    for(; pos < data.size();) {
        int n = send(m_sock, data.c_str() + pos, data.size() - pos, 0);
        if (n == -1) {
            int e = RHO_NET_ERROR_CODE;
#if !defined(WINDOWS_PLATFORM)
            if (e == EINTR)
                continue;
#endif
            
            if (verbose) RAWLOG_ERROR1("Can not send response data: %d", e);
            return false;
        }
        
        if (n == 0)
            break;
        
        pos += n;
    }
    
    //String dbg_response = response.size() > 100 ? response.substr(0, 100) : response;
    //RAWTRACE2("Sent response:\n%s%s", dbg_response.c_str(), response.size() > 100 ? "..." : "   ");
    if (continuation) {
        if (verbose) RAWTRACE1("Sent response body: %d bytes", data.size());
    }
    else if ( !rho_conf_getBool("log_skip_post") ) {
        if (verbose) RAWTRACE1("Sent response (only headers displayed):\n%s", data.c_str());
    }

    return true;
}

bool CHttpServer::send_response(String const &response, bool redirect)
{
#ifdef OS_ANDROID
    if (redirect) {
        CAutoPtr<IRhoThreadImpl> ptrThread = rho_get_RhoClassFactory()->createThreadImpl();
        ptrThread->sleep(20);
    }
#endif
    return send_response_impl(response, false);
}

String CHttpServer::create_response(String const &reason)
{
    return create_response(reason, "");
}

String CHttpServer::create_response(String const &reason, HeaderList const &headers)
{
    return create_response(reason, headers, "");
}

String CHttpServer::create_response(String const &reason, String const &body)
{
    return create_response(reason, HeaderList(), body);
}

String CHttpServer::create_response(String const &reason, HeaderList const &hdrs, String const &body)
{
    String response = "HTTP/1.1 ";
    response += reason;
    response += "\r\n";
    
    char buf[50];
    snprintf(buf, sizeof(buf), "%d", m_port);
    
    HeaderList headers;
    headers.push_back(Header("Host", String("127.0.0.1:") + buf));
    headers.push_back(Header("Connection", "close"));
    headers.push_back(HttpHeader("Access-Control-Allow-Origin", "*"));
    std::copy(hdrs.begin(), hdrs.end(), std::back_inserter(headers));
    
    for(HeaderList::const_iterator it = headers.begin(), lim = headers.end();
        it != lim; ++it) {
        response += it->name;
        response += ": ";
        response += it->value;
        response += "\r\n";
    }
    
    response += "\r\n";
    
    response += body;
    
    return response;
}
Beispiel #25
0
bool CHttpServer::decide(String const &method, String const &arg_uri, String const &query,
                         HeaderList const &headers, String const &body/*, IResponseSender& respSender*/ )
{
    if (verbose) RAWTRACE1("Decide what to do with uri %s", arg_uri.c_str());
    callback_t callback = registered(arg_uri);
    if (callback) {
        if (verbose) RAWTRACE1("Uri %s is registered callback, so handle it appropriately", arg_uri.c_str());

        if ( callback == rho_http_ruby_proc_callback )
            call_ruby_proc( query, body );
        else
            callback(this, query.length() ? query : body);

        return false;
    }

    String uri = arg_uri;

    String fullPath = CFilePath::join(m_root, uri);
#ifndef RHO_NO_RUBY_API    
    if (rho_ruby_is_started())
    {
        Route route;
        if (dispatch(uri, route)) {
            if (verbose) RAWTRACE1("Uri %s is correct route, so enable MVC logic", uri.c_str());
            
            VALUE req = create_request_hash(route.application, route.model, route.action, route.id,
                                            method, uri, query, headers, body);
            VALUE data = callFramework(req);
            String reply(getStringFromValue(data), getStringLenFromValue(data));
            rho_ruby_releaseValue(data);

            bool isRedirect = String_startsWith(reply, "HTTP/1.1 301") ||
                              String_startsWith(reply, "HTTP/1.1 302");

            if (!send_response(reply, isRedirect))
                return false;

            if (method == "GET")
                rho_rhodesapp_keeplastvisitedurl(uri.c_str());

		    if ( sync::RhoconnectClientManager::haveRhoconnectClientImpl() ) {

			    if (!route.id.empty()) {
				    sync::RhoconnectClientManager::rho_sync_addobjectnotify_bysrcname(route.model.c_str(), route.id.c_str());
			    }			
		    }
            
            return true;
        }
        
        if (isdir(fullPath)) {
            if (verbose) RAWTRACE1("Uri %s is directory, redirecting to index", uri.c_str());
            String q = query.empty() ? "" : "?" + query;
            
            HeaderList headers;
            headers.push_back(Header("Location", CFilePath::join( uri, "index" RHO_ERB_EXT) + q));
            
            send_response(create_response("301 Moved Permanently", headers), true);
            return false;
        }

        if (isindex(uri)) {
            if (!isfile(fullPath)) {
                if (verbose) RAWLOG_ERROR1("The file %s was not found", fullPath.c_str());
                String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + uri + " was not found.</font></html>";
                send_response(create_response("404 Not Found",error));
                return false;
            }
            
            if (verbose) RAWTRACE1("Uri %s is index file, call serveIndex", uri.c_str());

            VALUE req = create_request_hash(route.application, route.model, route.action, route.id,
                                            method, uri, query, headers, body);

            VALUE data = callServeIndex((char *)fullPath.c_str(), req);
            String reply(getStringFromValue(data), getStringLenFromValue(data));
            rho_ruby_releaseValue(data);

            if (!send_response(reply))
                return false;

            if (method == "GET")
                rho_rhodesapp_keeplastvisitedurl(uri.c_str());

            return true;
        }
    }
#endif
    // Try to send requested file
    if (verbose) RAWTRACE1("Uri %s should be regular file, trying to send it", uri.c_str());

    PROF_START("READ_FILE");
    bool bRes = send_file(uri, headers);
    PROF_STOP("READ_FILE");

    return bRes;
}
Beispiel #26
0
bool CHttpServer::send_file(String const &path, HeaderList const &hdrs)
{
    String fullPath = CFilePath::normalizePath(path);

    if (String_startsWith(fullPath,"/app/db/db-files") )
        fullPath = CFilePath::join( rho_native_rhodbpath(), path.substr(4) );
    else if (fullPath.find(m_root) != 0 && fullPath.find(m_strRhoRoot) != 0 && fullPath.find(m_strRuntimeRoot) != 0 && fullPath.find(m_userroot) != 0 && fullPath.find(m_strRhoUserRoot) != 0)
        fullPath = CFilePath::join( m_root, path );
	
    struct stat st;
    bool bCheckExist = true;
#ifdef RHODES_EMULATOR
    String strPlatform = RHOSIMCONF().getString("platform");
    if ( strPlatform.length() > 0 )
    {
        String fullPath1 = fullPath;
        int nDot = fullPath1.rfind('.');
        if ( nDot >= 0 )
            fullPath1.insert(nDot, String(".") + strPlatform);
        else
            fullPath1 += String(".") + strPlatform;

        if (stat(fullPath1.c_str(), &st) == 0 && S_ISREG(st.st_mode))
        {
            fullPath = fullPath1;
            bCheckExist = false;
        }
    }

#endif

    bool doesNotExists = bCheckExist && (stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode));
    if ( doesNotExists ) {
        // looking for files at 'rho/apps' at runtime folder
        fullPath = CFilePath::join( m_strRuntimeRoot, path );
    }

    if (verbose) RAWTRACE1("Sending file %s...", fullPath.c_str());

    if ( doesNotExists ) {
        if ( stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode) ) {
            doesNotExists = true;
        }else
            doesNotExists = false;
    }

#ifdef RHODES_EMULATOR
    if ( doesNotExists )
    {
        CTokenizer oTokenizer( RHOSIMCONF().getString("ext_path"), ";" );
	    while (oTokenizer.hasMoreTokens()) 
        {
		    String tok = oTokenizer.nextToken();
		    tok = String_trim(tok);
            
            String fullPath1 = CFilePath::join( tok, path );
            if (stat(fullPath1.c_str(), &st) == 0 && S_ISREG(st.st_mode))
            {
                fullPath = fullPath1;
                doesNotExists = false;
                break;
            }

        }
    }
#endif

    if ( doesNotExists ) {
        if (verbose) RAWLOG_ERROR1("The file %s was not found", path.c_str());
        String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + path + " was not found.</font></html>";
        send_response(create_response("404 Not Found",error));
        return false;
    }

    PROF_START("LOW_FILE");
    FILE *fp = fopen(fullPath.c_str(), "rb");
    PROF_STOP("LOW_FILE");
    if (!fp) {
        if (verbose) RAWLOG_ERROR1("The file %s could not be opened", path.c_str());
        String error = "<!DOCTYPE html><html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + path + " could not be opened.</font></html";
        send_response(create_response("404 Not Found",error));
        return false;
    }
    
    HeaderList headers;
    
    // Detect mime type
    headers.push_back(Header("Content-Type", get_mime_type(path)));
    if ( String_startsWith(path, "/public") )
    {
        headers.push_back(Header("Expires", "Thu, 15 Apr 2020 20:00:00 GMT") );
        headers.push_back(Header("Cache-Control", "max-age=2592000") );
    }

    // Content length
    char* buf = new char[FILE_BUF_SIZE];
    
    String start_line;
    
    size_t file_size = st.st_size;
    size_t range_begin = 0, range_end = file_size - 1;
    size_t content_size = file_size;
    if (parse_range(hdrs, &range_begin, &range_end))
    {
        if (range_end >= file_size)
            range_end = file_size - 1;
        if (range_begin >= range_end)
            range_begin = range_end - 1;
        content_size = range_end - range_begin + 1;
        
        if (fseek(fp, range_begin, SEEK_SET) == -1) {
            RAWLOG_ERROR1("Can not seek to specified range start: %lu", (unsigned long)range_begin);
			snprintf(buf, FILE_BUF_SIZE, "bytes */%lu", (unsigned long)file_size);
			headers.push_back(Header("Content-Range", buf));
			send_response(create_response("416 Request Range Not Satisfiable",headers));
            fclose(fp);
            delete[] buf;
            return false;
        }
		
		snprintf(buf, FILE_BUF_SIZE, "bytes %lu-%lu/%lu", (unsigned long)range_begin,
                 (unsigned long)range_end, (unsigned long)file_size);
        headers.push_back(Header("Content-Range", buf));
        
        start_line = "206 Partial Content";
    }
    else {
        start_line = "200 OK";
    }

    
    snprintf(buf, FILE_BUF_SIZE, "%lu", (unsigned long)content_size);
    headers.push_back(Header("Content-Length", buf));
    
    // Send headers
    if (!send_response(create_response(start_line, headers))) {
        if (verbose) RAWLOG_ERROR1("Can not send headers while sending file %s", path.c_str());
        fclose(fp);
        delete[] buf;
        return false;
    }
    
    // Send body
    for (size_t start = range_begin; start < range_end + 1;) {
        size_t need_to_read = range_end - start + 1;
        if (need_to_read == 0)
            break;
        
        if (need_to_read > FILE_BUF_SIZE)
            need_to_read = FILE_BUF_SIZE;

PROF_START("LOW_FILE");
        size_t n = fread(buf, 1, need_to_read, fp);//fread(buf, 1, need_to_read, fp);
PROF_STOP("LOW_FILE");
        if (n < need_to_read) {
			if (ferror(fp) ) {
				if (verbose) RAWLOG_ERROR2("Can not read part of file (at position %lu): %s", (unsigned long)start, strerror(errno));
			} else if ( feof(fp) ) {
				if (verbose) RAWLOG_ERROR1("End of file reached, but we expect data (%lu bytes)", (unsigned long)need_to_read);
			}
            fclose(fp);
            delete[] buf;
            return false;
        }
        
        start += n;
        
        if (!send_response_body(String(buf, n))) {
            if (verbose) RAWLOG_ERROR1("Can not send part of data while sending file %s", path.c_str());
            fclose(fp);
            delete[] buf;
            return false;
        }
    }

PROF_START("LOW_FILE");
    fclose(fp);
PROF_STOP("LOW_FILE");
    delete[] buf;
    if (verbose) RAWTRACE1("File %s was sent successfully", path.c_str());
    return false;
}
Beispiel #27
0
//--------------------------------------------------------------------------------------------------
RHO_GLOBAL void rho_nativethread_end(void *)
{
    RAWTRACE1("Thread ended - env: 0x%.8x ===================================================", jnienv());
    jvm()->DetachCurrentThread();
    store_thr_jnienv(0);
}
Beispiel #28
0
bool CHttpServer::decide(String const &method, String const &arg_uri, String const &query,
                         HeaderList const &headers, String const &body)
{
    RAWTRACE1("Decide what to do with uri %s", arg_uri.c_str());
    callback_t callback = registered(arg_uri);
    if (callback) {
        RAWTRACE1("Uri %s is registered callback, so handle it appropriately", arg_uri.c_str());

        if ( callback == rho_http_ruby_proc_callback )
            call_ruby_proc( query, body );
        else
            callback(this, query.length() ? query : body);

        return false;
    }

    String uri = arg_uri;

//#ifdef OS_ANDROID
//    //Work around malformed Android WebView URLs
//    if (!String_startsWith(uri, "/app") &&
//        !String_startsWith(uri, "/public") &&
//        !String_startsWith(uri, "/data")) 
//    {
//        RAWTRACE1("Malformed URL: '%s', adding '/app' prefix.", uri.c_str());
//        uri = CFilePath::join("/app", uri);
//    }
//#endif

    String fullPath = CFilePath::join(m_root, uri);
    
    Route route;
    if (dispatch(uri, route)) {
        RAWTRACE1("Uri %s is correct route, so enable MVC logic", uri.c_str());
        
        VALUE req = create_request_hash(route.application, route.model, route.action, route.id,
                                        method, uri, query, headers, body);
        VALUE data = callFramework(req);
        String reply(getStringFromValue(data), getStringLenFromValue(data));
        rho_ruby_releaseValue(data);

        bool isRedirect = String_startsWith(reply, "HTTP/1.1 301") ||
                          String_startsWith(reply, "HTTP/1.1 302");

        if (!send_response(reply, isRedirect))
            return false;

        if (method == "GET")
            rho_rhodesapp_keeplastvisitedurl(uri.c_str());

		if ( sync::RhoconnectClientManager::haveRhoconnectClientImpl() ) {

			if (!route.id.empty()) {
				sync::RhoconnectClientManager::rho_sync_addobjectnotify_bysrcname(route.model.c_str(), route.id.c_str());
			}			
		}
        
        return true;
    }
    
//#ifndef OS_ANDROID
    if (isdir(fullPath)) {
        RAWTRACE1("Uri %s is directory, redirecting to index", uri.c_str());
        String q = query.empty() ? "" : "?" + query;
        
        HeaderList headers;
        headers.push_back(Header("Location", CFilePath::join( uri, "index"RHO_ERB_EXT) + q));
        
        send_response(create_response("301 Moved Permanently", headers), true);
        return false;
    }
//#else
//    //Work around this Android redirect bug:
//    //http://code.google.com/p/android/issues/detail?can=2&q=11583&id=11583
//    if (isdir(fullPath)) {
//        RAWTRACE1("Uri %s is directory, override with index", uri.c_str());
//        return decide(method, CFilePath::join( uri, "index"RHO_ERB_EXT), query, headers, body);
//    }
//#endif
    if (isindex(uri)) {
        if (!isfile(fullPath)) {
            RAWLOG_ERROR1("The file %s was not found", fullPath.c_str());
            String error = "<html><font size=\"+4\"><h2>404 Not Found.</h2> The file " + uri + " was not found.</font></html>";
            send_response(create_response("404 Not Found",error));
            return false;
        }
        
        RAWTRACE1("Uri %s is index file, call serveIndex", uri.c_str());

        VALUE req = create_request_hash(route.application, route.model, route.action, route.id,
                                        method, uri, query, headers, body);

        VALUE data = callServeIndex((char *)fullPath.c_str(), req);
        String reply(getStringFromValue(data), getStringLenFromValue(data));
        rho_ruby_releaseValue(data);

        if (!send_response(reply))
            return false;

        if (method == "GET")
            rho_rhodesapp_keeplastvisitedurl(uri.c_str());

        return true;
    }
    
    // Try to send requested file
    RAWTRACE1("Uri %s should be regular file, trying to send it", uri.c_str());
    return send_file(uri, headers);
}
Beispiel #29
0
int Curl_resolv(struct connectdata *conn,
                const char *hostname,
                int port,
                struct Curl_dns_entry **entry)
{
  char *entry_id = NULL;
  struct Curl_dns_entry *dns = NULL;
  size_t entry_len;
  struct SessionHandle *data = conn->data;
  CURLcode result;
  int rc = CURLRESOLV_ERROR; /* default to failure */

  *entry = NULL;

  /* Create an entry id, based upon the hostname and port */
  entry_id = create_hostcache_id(hostname, port);
  /* If we can't create the entry id, fail */
  if(!entry_id)
    return rc;

  RAWTRACE1("Curl_resolv host: cache_id: %s", entry_id);

  entry_len = strlen(entry_id);

  if(data->share)
    Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

  /* See if its already in our dns cache */
  dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1);

  /* See whether the returned entry is stale. Done before we release lock */
  if( remove_entry_if_stale(data, dns) )
    dns = NULL; /* the memory deallocation is being handled by the hash */

  if(dns) {
    dns->inuse++; /* we use it! */
    rc = CURLRESOLV_RESOLVED;
  }

  if(data->share)
    Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

  /* free the allocated entry_id again */
  free(entry_id);

  if(!dns) {
    /* The entry was not in the cache. Resolve it to IP address */

    Curl_addrinfo *addr;
    int respwait;

    /* Check what IP specifics the app has requested and if we can provide it.
     * If not, bail out. */
    if(!Curl_ipvalid(data))
      return CURLRESOLV_ERROR;

    /* If Curl_getaddrinfo() returns NULL, 'respwait' might be set to a
       non-zero value indicating that we need to wait for the response to the
       resolve call */
    addr = Curl_getaddrinfo(conn,
#ifdef DEBUGBUILD
                            (data->set.str[STRING_DEVICE]
                             && !strcmp(data->set.str[STRING_DEVICE],
                                        "LocalHost"))?"localhost":
#endif
                            hostname, port, &respwait);

    if(!addr) {
      if(respwait) {
        /* the response to our resolve call will come asynchronously at
           a later time, good or bad */
        /* First, check that we haven't received the info by now */
        result = Curl_is_resolved(conn, &dns);
        if(result) /* error detected */
          return CURLRESOLV_ERROR;
        if(dns)
          rc = CURLRESOLV_RESOLVED; /* pointer provided */
        else
          rc = CURLRESOLV_PENDING; /* no info yet */
      }
    }
    else {
      if(data->share)
        Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE);

      /* we got a response, store it in the cache */
      dns = Curl_cache_addr(data, addr, hostname, port);

      if(data->share)
        Curl_share_unlock(data, CURL_LOCK_DATA_DNS);

      if(!dns)
        /* returned failure, bail out nicely */
        Curl_freeaddrinfo(addr);
      else
        rc = CURLRESOLV_RESOLVED;
    }
  }

  *entry = dns;

  return rc;
}