9b0bee2310f5db73a7dd8b0e86a9294669393d52
[platform/upstream/iotivity.git] / resource / csdk / connectivity / src / adapter_util / cafragmentation.c
1 /******************************************************************
2  *
3  * Copyright 2016 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************/
20
21 #include <string.h>
22 #include <math.h>
23
24 #include "cacommon.h"
25 #include "caadapterutils.h"
26 #include "cafragmentation.h"
27 #include "caleinterface.h"
28
29 /**
30  * Debugging tag for fragmentation module.
31  */
32 #define TAG "OIC_CA_FRAG"
33
34 //packet format define value
35 #define CA_BLE_START_POS 7
36 #define CA_BLE_START_LEN 1
37 #define CA_BLE_SOURCE_PORT_POS 6
38 #define CA_BLE_SOURCE_PORT_LEN 7
39 #define CA_BLE_SECURE_POS 7
40 #define CA_BLE_SECURE_LEN 1
41 #define CA_BLE_DESTINATION_PORT_POS 6
42 #define CA_BLE_DESTINATION_PORT_LEN 7
43
44 /**
45  * This function is used to set value in specific bit position.
46  *
47  * @param[out]  x  Pointer to the octet variable that will contain
48  *                 value in specific bit position.
49  * @param[in]   p  Position which need to embed specific bits(0~7).
50  * @param[in]   n  Length to fill several bits from the position.
51  * @param[in]   v  Value to contain in specific bit position.
52  */
53 static void CASetBits(uint8_t *x, unsigned p, unsigned n, unsigned v)
54 {
55     if ((p+1) < n)
56     {
57         OIC_LOG(ERROR, TAG, "set bits - lower err");
58         return;
59     }
60     else if(~(unsigned)(~0u<<n) < v)
61     {
62         OIC_LOG(ERROR, TAG, "set bits - upper err");
63         return;
64     }
65     *x = (*x & (~(~0u << (p-n+1)))) | (*x & (~0u << (p+1))) | ((v & ~(~0u << n)) << (p-n+1));
66 }
67
68 /**
69  * This function is used to get value in specific bit position.
70  *
71  * @param[in]   x  Pointer to the octet variable that have infomation
72  *                 to be extracted.
73  * @param[in]   p  Position which need to get specific bits(0~7).
74  * @param[in]   n  Length to get several bits from the position.
75  *
76  * @return @c Extracted value from specific position.
77  */
78 static uint8_t CAGetBits(uint8_t x, unsigned p, unsigned n)
79 {
80     return (x >> (p + 1 - n)) & ~(~0u << n);
81 }
82
83 CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
84                                               uint32_t *midPacketCount,
85                                               size_t *remainingLen,
86                                               size_t *totalLength,
87                                               uint16_t mtuSize)
88 {
89     OIC_LOG_V(DEBUG, TAG, "IN, dataLength = %zu, mtu = %zu", dataLength, mtuSize);
90
91     size_t remainDataSize = 0;
92     size_t dataOnlyLen =
93             mtuSize - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
94     //total data size is smaller than 14 byte case.
95     if (dataLength < dataOnlyLen)
96     {
97         remainDataSize = 0;
98     }
99     else
100     {
101         remainDataSize = dataLength - dataOnlyLen;
102     }
103
104     if (mtuSize - CA_BLE_HEADER_SIZE <= 0)
105     {
106         OIC_LOG_V(ERROR, TAG, "BLE header size shouldn't be bigger than BLE MTU size.");
107         return CA_STATUS_FAILED;
108     }
109
110     *midPacketCount = (uint32_t)remainDataSize / (mtuSize - CA_BLE_HEADER_SIZE);
111     *remainingLen = (uint32_t)remainDataSize % (mtuSize - CA_BLE_HEADER_SIZE);
112     uint32_t remainHeaderSize = CA_BLE_HEADER_SIZE * (*midPacketCount + (*remainingLen == 0 ? 0:1));
113     *totalLength = dataLength + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE) + remainHeaderSize;
114
115     OIC_LOG(DEBUG, TAG, "OUT");
116
117     return CA_STATUS_OK;
118 }
119
120 CAResult_t CAGenerateHeader(uint8_t *header,
121                             CABLEPacketStart_t type,
122                             const uint8_t sourcePort,
123                             CABLEPacketSecure_t secure,
124                             const uint8_t destPort)
125 {
126     OIC_LOG(DEBUG, TAG, "IN");
127
128     VERIFY_NON_NULL(header, TAG, "header is NULL");
129
130     if (sourcePort > CA_SUPPORTED_BLE_MAX_PORT ||
131         sourcePort < CA_SUPPORTED_BLE_MIN_PORT ||
132         destPort > CA_SUPPORTED_BLE_MAX_PORT)
133     {
134         OIC_LOG_V(ERROR, TAG, "source port(%d) or destination port(%d) is invalid number!!",
135                 sourcePort, destPort);
136         return CA_STATUS_FAILED;
137     }
138
139     CASetBits(&header[0], CA_BLE_START_POS, CA_BLE_START_LEN, type);
140     CASetBits(&header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN, sourcePort);
141     CASetBits(&header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN, secure);
142     CASetBits(&header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN, destPort);
143
144     return CA_STATUS_OK;
145 }
146
147 CAResult_t CAGenerateHeaderPayloadLength(uint8_t *header,
148                                          size_t headerLength,
149                                          size_t dataLength)
150 {
151     VERIFY_NON_NULL(header, TAG, "header is NULL");
152
153     if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
154     {
155         return CA_STATUS_FAILED;
156     }
157
158     for(size_t idx = 1; idx < CA_BLE_LENGTH_HEADER_SIZE; idx++)
159     {
160         header[CA_BLE_LENGTH_HEADER_SIZE - idx] = dataLength & 0xFF;
161         dataLength >>= 8;
162     }
163     header[0] = dataLength & 0xFF;
164
165     return CA_STATUS_OK;
166 }
167
168 CAResult_t CAMakeFirstDataSegment(uint8_t *dataSegment,
169                                   const uint8_t *data,
170                                   const uint32_t dataLength,
171                                   const uint8_t *dataHeader,
172                                   const uint8_t *lengthHeader)
173 {
174     OIC_LOG(DEBUG, TAG, "IN");
175
176     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
177     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
178     VERIFY_NON_NULL(lengthHeader, TAG, "lengthHeader is NULL");
179
180     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
181     memcpy(dataSegment + CA_BLE_HEADER_SIZE, lengthHeader, CA_BLE_LENGTH_HEADER_SIZE);
182     memcpy(dataSegment + CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE, data, dataLength);
183
184     OIC_LOG(DEBUG, TAG, "OUT");
185
186     return CA_STATUS_OK;
187 }
188
189 CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
190                                    const uint32_t segmentPayloadLength,
191                                    const uint8_t *sourceData,
192                                    const uint32_t sourceDataLength,
193                                    const uint32_t segmentNum,
194                                    const uint8_t *dataHeader,
195                                    uint16_t mtuSize)
196 {
197     OIC_LOG(DEBUG, TAG, "IN");
198
199     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
200     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
201
202     uint32_t index = (mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE) +
203             (segmentNum * (mtuSize - CA_BLE_HEADER_SIZE));
204     if (sourceDataLength < index + segmentPayloadLength)
205     {
206         OIC_LOG(DEBUG, TAG, "dataSegment will exceed");
207         return CA_STATUS_FAILED;
208     }
209
210     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
211     memcpy(dataSegment + CA_BLE_HEADER_SIZE, sourceData + index, segmentPayloadLength);
212
213     OIC_LOG(DEBUG, TAG, "OUT");
214
215     return CA_STATUS_OK;
216 }
217
218 CAResult_t CAParseHeader(const uint8_t *header,
219                          CABLEPacketStart_t *startFlag,
220                          uint16_t *sourcePort,
221                          CABLEPacketSecure_t *secureFlag,
222                          uint16_t *destPort)
223 {
224     OIC_LOG(DEBUG, TAG, "IN");
225
226     VERIFY_NON_NULL(header, TAG, "header is NULL");
227
228     *startFlag = CAGetBits(header[0], CA_BLE_START_POS, CA_BLE_START_LEN);
229     *sourcePort = CAGetBits(header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN);
230     *secureFlag = CAGetBits(header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN);
231     *destPort = CAGetBits(header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN);
232
233     OIC_LOG(DEBUG, TAG, "OUT");
234
235     return CA_STATUS_OK;
236 }
237
238 CAResult_t CAParseHeaderPayloadLength(uint8_t *header,
239                                       size_t headerLength,
240                                       uint32_t *dataLength)
241 {
242     OIC_LOG(DEBUG, TAG, "IN");
243     VERIFY_NON_NULL(header, TAG, "header is NULL");
244
245     if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
246     {
247         return CA_STATUS_FAILED;
248     }
249
250     for(size_t idx = 0; idx < headerLength; idx++)
251     {
252         *dataLength <<= 8;
253         *dataLength |= header[CA_BLE_HEADER_SIZE+idx];
254     }
255
256     OIC_LOG(DEBUG, TAG, "OUT");
257     return CA_STATUS_OK;
258 }