olm_jni_helper.cpp 9.17 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * Created by pedrocon on 06/10/2016.
 */
/*
 * Copyright 2016 OpenMarket Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pedroGitt's avatar
pedroGitt committed
20
#include "olm_jni_helper.h"
21
#include "olm/olm.h"
22
#include <sys/time.h>
pedroGitt's avatar
pedroGitt committed
23
24

using namespace AndroidOlmSdk;
25
26
27
28
29
30
31
32
33
34

/**
* Init a buffer with a given number of random values.
* @param aBuffer2Ptr the buffer to be initialized
* @param aRandomSize the number of random values to apply
* @return true if operation succeed, false otherwise
**/
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize)
{
    bool retCode = false;
35
36
    struct timeval timeValue;

37
38
    if(NULL == aBuffer2Ptr)
    {
pedroGitt's avatar
pedroGitt committed
39
        LOGE("## setRandomInBuffer(): failure - aBuffer=NULL");
40
41
42
    }
    else if(0 == aRandomSize)
    {
pedroGitt's avatar
pedroGitt committed
43
        LOGE("## setRandomInBuffer(): failure - random size=0");
44
45
46
    }
    else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t))))
    {
pedroGitt's avatar
pedroGitt committed
47
        LOGE("## setRandomInBuffer(): failure - alloc mem OOM");
48
49
50
    }
    else
    {
pedroGitt's avatar
pedroGitt committed
51
        LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast<long unsigned int>(aRandomSize));
52

53
54
55
        gettimeofday(&timeValue, NULL);
        srand(timeValue.tv_usec); // init seed

56
57
58
        for(size_t i=0;i<aRandomSize;i++)
        {
            (*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);
59
60
            // debug purpose
            //LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
61
62
63
64
65
66
67
68
69
        }

        retCode = true;
    }
    return retCode;
}


/**
70
* Read the instance ID of the calling object.
71
72
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
73
* @param aCallingClass java calling clas name
74
75
* @return the instance ID if operation succeed, -1 if instance ID was not found.
**/
76
jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass)
77
{
pedroGitt's avatar
pedroGitt committed
78
  jlong instanceId = 0;
79
80
  jfieldID instanceIdField;
  jclass loaderClass;
81
  jclass requiredClass = 0;
82
83
84

  if(NULL!=aJniEnv)
  {
85
    requiredClass = aJniEnv->FindClass(aCallingClass);
86
87
88

    if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass)))
    {
pedroGitt's avatar
pedroGitt committed
89
        LOGE("## getAccountInstanceId() failure - invalid instance of");
90
91
    }
    else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
92
    {
93
      if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeId", "J")))
94
95
96
      {
        instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
        aJniEnv->DeleteLocalRef(loaderClass);
97
        LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId);
98
99
100
      }
      else
      {
101
        LOGE("## getInstanceId() ERROR! GetFieldID=null");
102
103
104
105
      }
    }
    else
    {
106
      LOGE("## getInstanceId() ERROR! GetObjectClass=null");
107
108
109
110
    }
  }
  else
  {
111
    LOGE("## getInstanceId() ERROR! aJniEnv=NULL");
112
  }
113
  LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId);
114
115
116
117
  return instanceId;
}

/**
118
* Read the account instance ID of the calling object.
119
120
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
121
* @return the instance ID if operation succeed, -1 if instance ID was not found.
122
**/
123
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
124
{
125
126
127
  jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT);
  return instanceId;
}
128

129

130

131
132
133
134
135
136
137
138
139
/**
* Read the session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
  jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION);
140
141
142
143
144
145
146
147
148
149
150
  return instanceId;
}

/**
* Read the inbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
151
  jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION);
152
153
154
155
156
157
158
159
160
161
162
163
  return instanceId;
}


/**
* Read the outbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
164
  jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION);
165
166
167
  return instanceId;
}

168
169
170
171
172
173
/**
* Read the utility instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
174
175
jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
176
  jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY);
177
178
  return instanceId;
}
179

180

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
template <typename T>
jstring serializeDataWithKey(JNIEnv *env, jobject thiz,
                                jstring aKey,
                                jobject aErrorMsg,
                                olmPickleLengthFuncPtr<T> aGetLengthFunc,
                                olmPickleFuncPtr<T> aGetPickleFunc,
                                olmLastErrorFuncPtr<T> aGetLastErrorFunc)
{
    jstring pickledDataRetValue = 0;
    jclass errorMsgJClass = 0;
    jmethodID errorMsgMethodId = 0;
    jstring errorJstring = 0;
    const char *keyPtr = NULL;
    void *pickledPtr = NULL;
    T accountPtr = NULL;

    LOGD("## serializeDataWithKeyJni(): IN");

    if(NULL == (accountPtr = (T)getAccountInstanceId(env,thiz)))
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr");
    }
    else if(0 == aKey)
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - invalid key");
    }
    else if(0 == aErrorMsg)
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object");
    }
    else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg)))
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class");
    }
    else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;")))
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID");
    }
    else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0)))
    {
        LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM");
    }
    else
    {
        size_t pickledLength = aGetLengthFunc(accountPtr);
        size_t keyLength = (size_t)env->GetStringUTFLength(aKey);
pedroGitt's avatar
pedroGitt committed
227
        LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast<long unsigned int>(pickledLength), static_cast<long unsigned int>(keyLength));
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
        LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr);

        if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t))))
        {
            LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM");
        }
        else
        {
            size_t result = aGetPickleFunc(accountPtr,
                                           (void const *)keyPtr,
                                           keyLength,
                                           (void*)pickledPtr,
                                           pickledLength);
            if(result == olm_error())
            {
                const char *errorMsgPtr = aGetLastErrorFunc(accountPtr);
                LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr);

                if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr)))
                {
                    env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring);
                }
            }
            else
            {
                // build success output
                (static_cast<char*>(pickledPtr))[pickledLength] = static_cast<char>('\0');
                pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr);
pedroGitt's avatar
pedroGitt committed
256
                LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast<long unsigned int>(result), static_cast<char*>(pickledPtr));
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
            }
        }
    }

    // free alloc
    if(NULL != keyPtr)
    {
     env->ReleaseStringUTFChars(aKey, keyPtr);
    }

    if(NULL != pickledPtr)
    {
        free(pickledPtr);
    }

    return pickledDataRetValue;
}