replace : iotivity -> iotivity-sec
[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     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     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
173     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
174     VERIFY_NON_NULL(lengthHeader, TAG, "lengthHeader is NULL");
175
176     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
177     memcpy(dataSegment + CA_BLE_HEADER_SIZE, lengthHeader, CA_BLE_LENGTH_HEADER_SIZE);
178     memcpy(dataSegment + CA_BLE_HEADER_SIZE + CA_BLE_LENGTH_HEADER_SIZE, data, dataLength);
179     return CA_STATUS_OK;
180 }
181
182 CAResult_t CAMakeRemainDataSegment(uint8_t *dataSegment,
183                                    const uint32_t segmentPayloadLength,
184                                    const uint8_t *sourceData,
185                                    const uint32_t sourceDataLength,
186                                    const uint32_t segmentNum,
187                                    const uint8_t *dataHeader,
188                                    uint16_t mtuSize)
189 {
190     VERIFY_NON_NULL(dataSegment, TAG, "dataSegment is NULL");
191     VERIFY_NON_NULL(dataHeader, TAG, "dataHeader is NULL");
192
193     uint32_t index = (mtuSize - CA_BLE_HEADER_SIZE - CA_BLE_LENGTH_HEADER_SIZE) +
194             (segmentNum * (mtuSize - CA_BLE_HEADER_SIZE));
195     if (sourceDataLength < index + segmentPayloadLength)
196     {
197         OIC_LOG(DEBUG, TAG, "dataSegment will exceed");
198         return CA_STATUS_FAILED;
199     }
200
201     memcpy(dataSegment, dataHeader, CA_BLE_HEADER_SIZE);
202     memcpy(dataSegment + CA_BLE_HEADER_SIZE, sourceData + index, segmentPayloadLength);
203     return CA_STATUS_OK;
204 }
205
206 CAResult_t CAParseHeader(const uint8_t *header,
207                          CABLEPacketStart_t *startFlag,
208                          uint16_t *sourcePort,
209                          CABLEPacketSecure_t *secureFlag,
210                          uint16_t *destPort)
211 {
212     VERIFY_NON_NULL(header, TAG, "header is NULL");
213
214     *startFlag = CAGetBits(header[0], CA_BLE_START_POS, CA_BLE_START_LEN);
215     *sourcePort = CAGetBits(header[0], CA_BLE_SOURCE_PORT_POS, CA_BLE_SOURCE_PORT_LEN);
216     *secureFlag = CAGetBits(header[1], CA_BLE_SECURE_POS, CA_BLE_SECURE_LEN);
217     *destPort = CAGetBits(header[1], CA_BLE_DESTINATION_PORT_POS, CA_BLE_DESTINATION_PORT_LEN);
218
219     return CA_STATUS_OK;
220 }
221
222 CAResult_t CAParseHeaderPayloadLength(uint8_t *header,
223                                       size_t headerLength,
224                                       uint32_t *dataLength)
225 {
226     VERIFY_NON_NULL(header, TAG, "header is NULL");
227
228     if (headerLength != CA_BLE_LENGTH_HEADER_SIZE)
229     {
230         return CA_STATUS_FAILED;
231     }
232
233     for(size_t idx = 0; idx < headerLength; idx++)
234     {
235         *dataLength <<= 8;
236         *dataLength |= header[CA_BLE_HEADER_SIZE+idx];
237     }
238
239     return CA_STATUS_OK;
240 }