67a6aab0652a1bf68c79f3bcfaf7040422b7dcf0
[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
28 /**
29  * Debugging tag for fragmentation module.
30  */
31 #define TAG "OIC_CA_FRAG"
32
33 //packet format define value
34 #define CA_BLE_START_POS 7
35 #define CA_BLE_START_LEN 1
36 #define CA_BLE_SOURCE_PORT_POS 6
37 #define CA_BLE_SOURCE_PORT_LEN 7
38 #define CA_BLE_SECURE_POS 7
39 #define CA_BLE_SECURE_LEN 1
40 #define CA_BLE_DESTINATION_PORT_POS 6
41 #define CA_BLE_DESTINATION_PORT_LEN 7
42
43 /**
44  * This function is used to set value in specific bit position.
45  *
46  * @param[out]  x  Pointer to the octet variable that will contain
47  *                 value in specific bit position.
48  * @param[in]   p  Position which need to embed specific bits(0~7).
49  * @param[in]   n  Length to fill several bits from the position.
50  * @param[in]   v  Value to contain in specific bit position.
51  */
52 static void CASetBits(uint8_t *x, unsigned p, unsigned n, unsigned v)
53 {
54     if ((p+1) < n)
55     {
56         OIC_LOG(ERROR, TAG, "set bits - lower err");
57         return;
58     }
59     else if(~(unsigned)(~0u<<n) < v)
60     {
61         OIC_LOG(ERROR, TAG, "set bits - upper err");
62         return;
63     }
64     *x = (*x & (~(~0u << (p-n+1)))) | (*x & (~0u << (p+1))) | ((v & ~(~0u << n)) << (p-n+1));
65 }
66
67 /**
68  * This function is used to get value in specific bit position.
69  *
70  * @param[in]   x  Pointer to the octet variable that have infomation
71  *                 to be extracted.
72  * @param[in]   p  Position which need to get specific bits(0~7).
73  * @param[in]   n  Length to get several bits from the position.
74  *
75  * @return @c Extracted value from specific position.
76  */
77 static uint8_t CAGetBits(uint8_t x, unsigned p, unsigned n)
78 {
79     return (x >> (p + 1 - n)) & ~(~0u << n);
80 }
81
82 CAResult_t CAGenerateVariableForFragmentation(size_t dataLength,
83                                               uint32_t *midPacketCount,
84                                               size_t *remainingLen,
85                                               size_t *totalLength)
86 {
87     OIC_LOG_V(DEBUG, TAG, "IN, dataLength = %zu", dataLength);
88
89     size_t remainDataSize = 0;
90     size_t dataOnlyLen =
91         CA_SUPPORTED_BLE_MTU_SIZE - (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE);
92     //total data size is smaller than 14 byte case.
93     if (dataLength < dataOnlyLen)
94     {
95         remainDataSize = 0;
96     }
97     else
98     {
99         remainDataSize = dataLength - dataOnlyLen;
100     }
101
102     if (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE <= 0)
103     {
104         OIC_LOG_V(ERROR, TAG, "BLE header size shouldn't be bigger than BLE MTU size.");
105         return CA_STATUS_FAILED;
106     }
107
108     *midPacketCount = (uint32_t)remainDataSize / (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
109     *remainingLen = (uint32_t)remainDataSize % (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE);
110     uint32_t remainHeaderSize = CA_BLE_HEADER_SIZE * (*midPacketCount + (*remainingLen == 0 ? 0:1));
111     *totalLength = dataLength + (CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE) + remainHeaderSize;
112
113     OIC_LOG(DEBUG, TAG, "OUT");
114
115     return CA_STATUS_OK;
116 }
117
118 CAResult_t CAGenerateHeader(uint8_t *header,
119                             CABLEPacketStart_t type,
120                             const uint8_t sourcePort,
121                             CABLEPacketSecure_t secure,
122                             const uint8_t destPort)
123 {
124     OIC_LOG(DEBUG, TAG, "IN");
125
126     VERIFY_NON_NULL(header, TAG, "header is NULL");
127
128     if (sourcePort > CA_SUPPORTED_BLE_MAX_PORT ||
129         sourcePort < CA_SUPPORTED_BLE_MIN_PORT ||
130         destPort > CA_SUPPORTED_BLE_MAX_PORT)
131     {
132         OIC_LOG_V(ERROR, TAG, "source port(%d) or destination port(%d) is invalid number!!",
133                 sourcePort, destPort);
134         return CA_STATUS_FAILED;
135     }
136
137     CASetBits(&header[0], CA_BLE_START_POS, CA_BLE_START_LEN, type);
138     CASetBits(&header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN, sourcePort);
139     CASetBits(&header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN, secure);
140     CASetBits(&header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN, destPort);
141
142     return CA_STATUS_OK;
143 }
144
145 CAResult_t CAGenerateHeaderPayloadLength(uint8_t *header,
146                                          size_t headerLength,
147                                          size_t dataLength)
148 {
149     VERIFY_NON_NULL(header, TAG, "header is NULL");
150
151     if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
152     {
153         return CA_STATUS_FAILED;
154     }
155
156     for(size_t idx = 1; idx < CA_BLE_LENGTH_HEADER_SIZE; idx++)
157     {
158         header[CA_BLE_LENGTH_HEADER_SIZE - idx] = dataLength & 0xFF;
159         dataLength >>= 8;
160     }
161     header[0] = dataLength & 0xFF;
162
163     return CA_STATUS_OK;
164 }
165
166 CAResult_t CAMakeFirstDataSegment(uint8_t *dataSegment,
167                                   const uint8_t *data,
168                                   const uint32_t dataLength,
169                                   const uint8_t *dataHeader,
170                                   const uint8_t *lengthHeader)
171 {
172     OIC_LOG(DEBUG, TAG, "IN");
173
174     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
175     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
176     VERIFY_NON_NULL(lengthHeader, TAG, "lengthHeader is NULL");
177
178     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
179     memcpy(dataSegment + CA_BLE_HEADER_SIZE, lengthHeader, CA_BLE_LENGTH_HEADER_SIZE);
180     memcpy(dataSegment + CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE, data, dataLength);
181
182     OIC_LOG(DEBUG, TAG, "OUT");
183
184     return CA_STATUS_OK;
185 }
186
187 CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
188                                    const uint8_t *data,
189                                    const uint32_t dataLength,
190                                    const uint32_t index,
191                                    const uint8_t *dataHeader)
192 {
193     OIC_LOG(DEBUG, TAG, "IN");
194
195     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
196     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
197
198     const uint8_t *cur_pos = data +
199         (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE +
200          (index * (CA_SUPPORTED_BLE_MTU_SIZE - CA_BLE_HEADER_SIZE)));
201     if (NULL == cur_pos)
202     {
203         OIC_LOG(ERROR, TAG, "data is NULL");
204         return CA_STATUS_FAILED;
205     }
206
207     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
208     memcpy(dataSegment + CA_BLE_HEADER_SIZE, cur_pos, dataLength);
209
210     OIC_LOG(DEBUG, TAG, "OUT");
211
212     return CA_STATUS_OK;
213 }
214
215 CAResult_t CAParseHeader(const uint8_t *header,
216                          CABLEPacketStart_t *startFlag,
217                          uint16_t *sourcePort,
218                          CABLEPacketSecure_t *secureFlag,
219                          uint16_t *destPort)
220 {
221     OIC_LOG(DEBUG, TAG, "IN");
222
223     VERIFY_NON_NULL(header, TAG, "header is NULL");
224
225     *startFlag = CAGetBits(header[0], CA_BLE_START_POS, CA_BLE_START_LEN);
226     *sourcePort = CAGetBits(header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN);
227     *secureFlag = CAGetBits(header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN);
228     *destPort = CAGetBits(header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN);
229
230     OIC_LOG(DEBUG, TAG, "OUT");
231
232     return CA_STATUS_OK;
233 }
234
235 CAResult_t CAParseHeaderPayloadLength(uint8_t *header,
236                                       size_t headerLength,
237                                       uint32_t *dataLength)
238 {
239     OIC_LOG(DEBUG, TAG, "IN");
240     VERIFY_NON_NULL(header, TAG, "header is NULL");
241
242     if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
243     {
244         return CA_STATUS_FAILED;
245     }
246
247     for(size_t idx = 0; idx < headerLength; idx++)
248     {
249         *dataLength <<= 8;
250         *dataLength |= header[CA_BLE_HEADER_SIZE+idx];
251     }
252
253     OIC_LOG(DEBUG, TAG, "OUT");
254     return CA_STATUS_OK;
255 }