Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-AMF-Simple
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
CommunityXG
OpenXG-AMF-Simple
Commits
a5e65b39
Commit
a5e65b39
authored
Jul 28, 2020
by
Tien-Thinh Nguyen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use a simple Mime parser instead of multipartparser
parent
824102f8
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
318 additions
and
573 deletions
+318
-573
src/sbi/amf_server/api/N1N2MessageCollectionDocumentApi.cpp
src/sbi/amf_server/api/N1N2MessageCollectionDocumentApi.cpp
+21
-51
src/utils/CMakeLists.txt
src/utils/CMakeLists.txt
+1
-1
src/utils/http_multi_parser.cpp
src/utils/http_multi_parser.cpp
+25
-51
src/utils/mime_parser.cpp
src/utils/mime_parser.cpp
+165
-0
src/utils/mime_parser.hpp
src/utils/mime_parser.hpp
+106
-0
src/utils/multipartparser.cpp
src/utils/multipartparser.cpp
+0
-328
src/utils/multipartparser.hpp
src/utils/multipartparser.hpp
+0
-142
No files found.
src/sbi/amf_server/api/N1N2MessageCollectionDocumentApi.cpp
View file @
a5e65b39
...
...
@@ -12,7 +12,7 @@
#include "N1N2MessageCollectionDocumentApi.h"
#include "Helpers.h"
#include "m
ultipart
parser.hpp"
#include "m
ime_
parser.hpp"
#include "logger.hpp"
namespace
oai
{
...
...
@@ -45,71 +45,42 @@ void N1N2MessageCollectionDocumentApi::n1_n2_message_transfer_handler(const Pist
Logger
::
amf_server
().
debug
(
"Received a N1N2MessageTrasfer request with ue_ctx_id(%s) "
,
ueContextId
.
c_str
());
// Getting the body param
std
::
size_t
found
=
request
.
body
().
find
(
"Content-Type"
);
std
::
string
boundary_str
=
request
.
body
().
substr
(
2
,
found
-
4
);
Logger
::
amf_server
().
debug
(
"Boundary: %s"
,
boundary_str
.
c_str
());
//step 1. use multipartparser to decode the request
multipartparser_callbacks_init
(
&
g_callbacks
);
g_callbacks
.
on_body_begin
=
&
on_body_begin
;
g_callbacks
.
on_part_begin
=
&
on_part_begin
;
g_callbacks
.
on_header_field
=
&
on_header_field
;
g_callbacks
.
on_header_value
=
&
on_header_value
;
g_callbacks
.
on_headers_complete
=
&
on_headers_complete
;
g_callbacks
.
on_data
=
&
on_data
;
g_callbacks
.
on_part_end
=
&
on_part_end
;
g_callbacks
.
on_body_end
=
&
on_body_end
;
multipartparser
parser
=
{};
init_globals
();
multipartparser_init
(
&
parser
,
reinterpret_cast
<
const
char
*>
(
boundary_str
.
c_str
()));
unsigned
int
str_len
=
request
.
body
().
length
();
unsigned
char
*
data
=
(
unsigned
char
*
)
malloc
(
str_len
+
1
);
memset
(
data
,
0
,
str_len
+
1
);
memcpy
((
void
*
)
data
,
(
void
*
)
request
.
body
().
c_str
(),
str_len
);
//if ((multipartparser_execute(&parser, &g_callbacks, request.body().c_str(), strlen(request.body().c_str())) != strlen(request.body().c_str())) or (!g_body_begin_called)){
if
((
multipartparser_execute
(
&
parser
,
&
g_callbacks
,
reinterpret_cast
<
const
char
*>
(
data
),
str_len
)
!=
strlen
(
request
.
body
().
c_str
()))
or
(
!
g_body_begin_called
))
{
Logger
::
amf_server
().
warn
(
"The received message can not be parsed properly!"
);
//response.send(Pistache::Http::Code::Bad_Request, "");
//return;
}
//simple parser
mime_parser
sp
=
{
};
sp
.
parse
(
request
.
body
());
std
::
vector
<
mime_part
>
parts
=
{
};
sp
.
get_mime_parts
(
parts
);
uint8_t
size
=
parts
.
size
();
Logger
::
amf_server
().
debug
(
"Number of MIME parts %d"
,
size
);
Logger
::
amf_server
().
debug
(
"Number of g_parts %d"
,
g_parts
.
size
());
//at least 2 parts for Json data and N1 (+ N2)
if
(
g_parts
.
size
()
<
2
)
{
response
.
send
(
Pistache
::
Http
::
Code
::
Bad_Request
,
""
);
if
(
size
<
2
)
{
response
.
send
(
Pistache
::
Http
::
Code
::
Bad_Request
);
return
;
}
part
p0
=
g_parts
.
front
();
g_parts
.
pop_front
();
Logger
::
amf_server
().
debug
(
"Request body, part 1:
\n
%s"
,
p0
.
body
.
c_str
());
part
p1
=
g_parts
.
front
();
g_parts
.
pop_front
();
Logger
::
amf_server
().
debug
(
"Request body, part 2:
\n
%s"
,
p1
.
body
.
c_str
());
part
p2
;
bool
is_ngap
=
false
;
if
(
g_parts
.
size
()
>
0
)
{
p2
=
g_parts
.
front
();
g_parts
.
pop_front
();
Logger
::
amf_server
().
debug
(
"Request body, part 1:
\n
%s"
,
parts
[
0
].
body
.
c_str
());
Logger
::
amf_server
().
debug
(
"Request body, part 2:
\n
%s"
,
parts
[
1
].
body
.
c_str
());
bool
is_ngap
=
false
;
if
(
size
>
2
)
{
is_ngap
=
true
;
Logger
::
amf_server
().
debug
(
"Request body, part 3:
\n
%s"
,
p
2
.
body
.
c_str
());
Logger
::
amf_server
().
debug
(
"Request body, part 3:
\n
%s"
,
p
arts
[
2
]
.
body
.
c_str
());
}
N1N2MessageTransferReqData
n1N2MessageTransferReqData
=
{};
try
{
//from_json(nlohmann::json::parse(p0.body.c_str()), n1N2MessageTransferReqData);
nlohmann
::
json
::
parse
(
p0
.
body
.
c_str
()).
get_to
(
n1N2MessageTransferReqData
);
nlohmann
::
json
::
parse
(
parts
[
0
].
body
.
c_str
()).
get_to
(
n1N2MessageTransferReqData
);
if
(
!
is_ngap
)
this
->
n1_n2_message_transfer
(
ueContextId
,
n1N2MessageTransferReqData
,
p
1
.
body
,
response
);
this
->
n1_n2_message_transfer
(
ueContextId
,
n1N2MessageTransferReqData
,
p
arts
[
1
]
.
body
,
response
);
else
this
->
n1_n2_message_transfer
(
ueContextId
,
n1N2MessageTransferReqData
,
p
1
.
body
,
p2
.
body
,
response
);
this
->
n1_n2_message_transfer
(
ueContextId
,
n1N2MessageTransferReqData
,
p
arts
[
1
].
body
,
parts
[
2
]
.
body
,
response
);
}
catch
(
nlohmann
::
detail
::
exception
&
e
)
{
//send a 400 error
Logger
::
amf_server
().
error
(
"response 400 error"
);
response
.
send
(
Pistache
::
Http
::
Code
::
Bad_Request
,
e
.
what
());
//response.send(Pistache::Http::Code::Bad_Request, "error");
return
;
}
catch
(
std
::
exception
&
e
)
{
//send a 500 error
...
...
@@ -117,7 +88,6 @@ void N1N2MessageCollectionDocumentApi::n1_n2_message_transfer_handler(const Pist
response
.
send
(
Pistache
::
Http
::
Code
::
Internal_Server_Error
,
e
.
what
());
return
;
}
}
void
N1N2MessageCollectionDocumentApi
::
n1_n2_message_collection_document_api_default_handler
(
const
Pistache
::
Rest
::
Request
&
,
Pistache
::
Http
::
ResponseWriter
response
)
{
...
...
src/utils/CMakeLists.txt
View file @
a5e65b39
...
...
@@ -11,8 +11,8 @@ add_library (AMF_UTILS STATIC
${
CMAKE_CURRENT_SOURCE_DIR
}
/hex_string_convert.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/http_multi_parser.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/if.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/multipartparser.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/string.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/thread_sched.cpp
${
CMAKE_CURRENT_SOURCE_DIR
}
/mime_parser.cpp
)
src/utils/http_multi_parser.cpp
View file @
a5e65b39
#include "multipartparser.hpp"
#include "mime_parser.hpp"
#include <string>
#include <iostream>
using
namespace
std
;
extern
"C"
{
#include <string.h>
}
bool
multipart_parser
(
string
input
,
string
&
jsonData
,
string
&
n1sm
,
string
&
n2sm
){
std
::
size_t
found
=
input
.
find
(
"Content-Type"
);
std
::
string
boundary_str
=
input
.
substr
(
2
,
found
-
4
);
//step 1. use multipartparser to decode the input
multipartparser_callbacks_init
(
&
g_callbacks
);
g_callbacks
.
on_body_begin
=
&
on_body_begin
;
g_callbacks
.
on_part_begin
=
&
on_part_begin
;
g_callbacks
.
on_header_field
=
&
on_header_field
;
g_callbacks
.
on_header_value
=
&
on_header_value
;
g_callbacks
.
on_headers_complete
=
&
on_headers_complete
;
g_callbacks
.
on_data
=
&
on_data
;
g_callbacks
.
on_part_end
=
&
on_part_end
;
g_callbacks
.
on_body_end
=
&
on_body_end
;
multipartparser
parser
=
{};
init_globals
();
multipartparser_init
(
&
parser
,
reinterpret_cast
<
const
char
*>
(
boundary_str
.
c_str
()));
unsigned
int
str_len
=
input
.
length
();
unsigned
char
*
data
=
(
unsigned
char
*
)
malloc
(
str_len
+
1
);
memset
(
data
,
0
,
str_len
+
1
);
memcpy
((
void
*
)
data
,
(
void
*
)
input
.
c_str
(),
str_len
);
if
((
multipartparser_execute
(
&
parser
,
&
g_callbacks
,
reinterpret_cast
<
const
char
*>
(
data
),
str_len
)
!=
strlen
(
input
.
c_str
()))
or
(
!
g_body_begin_called
))
{
//return;
std
::
cout
<<
"multipartparser_execute"
<<
std
::
endl
;
}
//at least 2 parts for Json data and N1 (+ N2)
if
(
g_parts
.
size
()
<
2
){
return
false
;
}
part
p0
=
g_parts
.
front
();
g_parts
.
pop_front
();
jsonData
=
p0
.
body
;
part
p1
=
g_parts
.
front
();
g_parts
.
pop_front
();
n1sm
=
p1
.
body
;
part
p2
;
bool
is_ngap
=
false
;
if
(
g_parts
.
size
()
>
0
)
{
p2
=
g_parts
.
front
();
g_parts
.
pop_front
();
is_ngap
=
true
;
}
if
(
is_ngap
)
n2sm
=
p2
.
body
;
else
n2sm
=
"null"
;
return
true
;
bool
multipart_parser
(
std
::
string
input
,
std
::
string
&
jsonData
,
std
::
string
&
n1sm
,
std
::
string
&
n2sm
)
{
//simple parser
mime_parser
sp
=
{
};
sp
.
parse
(
input
);
std
::
vector
<
mime_part
>
parts
=
{
};
sp
.
get_mime_parts
(
parts
);
uint8_t
size
=
parts
.
size
();
//at least 2 parts for Json data and N1 (+ N2)
if
(
size
<
2
)
{
return
false
;
}
jsonData
=
parts
[
0
].
body
;
n1sm
=
parts
[
1
].
body
;
bool
is_ngap
=
false
;
if
(
size
>
2
)
{
n2sm
=
parts
[
2
].
body
;
}
else
{
n2sm
=
"null"
;
}
return
true
;
}
src/utils/mime_parser.cpp
0 → 100644
View file @
a5e65b39
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "mime_parser.hpp"
#include "logger.hpp"
#include "conversions.hpp"
bool
mime_parser
::
parse
(
const
std
::
string
&
str
)
{
std
::
string
CRLF
=
"
\r\n
"
;
Logger
::
amf_app
().
debug
(
"Parsing the message with Simple Parser"
);
//find boundary
std
::
size_t
content_type_pos
=
str
.
find
(
"Content-Type"
);
//first part
if
((
content_type_pos
<=
4
)
or
(
content_type_pos
==
std
::
string
::
npos
))
return
false
;
std
::
string
boundary_str
=
str
.
substr
(
2
,
content_type_pos
-
4
);
// 2 for -- and 2 for CRLF
Logger
::
amf_app
().
debug
(
"Boundary: %s"
,
boundary_str
.
c_str
());
std
::
string
boundary_full
=
"--"
+
boundary_str
+
CRLF
;
std
::
string
last_boundary
=
"--"
+
boundary_str
+
"--"
+
CRLF
;
std
::
size_t
crlf_pos
=
str
.
find
(
CRLF
,
content_type_pos
);
std
::
size_t
boundary_pos
=
str
.
find
(
boundary_full
);
std
::
size_t
boundary_last_post
=
str
.
find
(
last_boundary
);
while
(
boundary_pos
<
boundary_last_post
)
{
mime_part
p
=
{
};
content_type_pos
=
str
.
find
(
"Content-Type"
,
boundary_pos
);
crlf_pos
=
str
.
find
(
CRLF
,
content_type_pos
);
if
((
content_type_pos
==
std
::
string
::
npos
)
or
(
crlf_pos
==
std
::
string
::
npos
))
break
;
p
.
content_type
=
str
.
substr
(
content_type_pos
+
14
,
crlf_pos
-
(
content_type_pos
+
14
));
Logger
::
amf_app
().
debug
(
"Content Type: %s"
,
p
.
content_type
.
c_str
());
crlf_pos
=
str
.
find
(
CRLF
+
CRLF
,
content_type_pos
);
//beginning of content
boundary_pos
=
str
.
find
(
boundary_full
,
crlf_pos
);
if
(
boundary_pos
==
std
::
string
::
npos
)
{
boundary_pos
=
str
.
find
(
last_boundary
,
crlf_pos
);
}
if
(
boundary_pos
>
0
)
{
p
.
body
=
str
.
substr
(
crlf_pos
+
4
,
boundary_pos
-
2
-
(
crlf_pos
+
4
));
Logger
::
amf_app
().
debug
(
"Body: %s"
,
p
.
body
.
c_str
());
mime_parts
.
push_back
(
p
);
}
}
return
true
;
}
void
mime_parser
::
get_mime_parts
(
std
::
vector
<
mime_part
>
&
parts
)
const
{
for
(
auto
it
:
mime_parts
)
{
parts
.
push_back
(
it
);
}
}
//---------------------------------------------------------------------------------------------
unsigned
char
*
mime_parser
::
format_string_as_hex
(
const
std
::
string
&
str
)
{
unsigned
int
str_len
=
str
.
length
();
char
*
data
=
(
char
*
)
malloc
(
str_len
+
1
);
memset
(
data
,
0
,
str_len
+
1
);
memcpy
((
void
*
)
data
,
(
void
*
)
str
.
c_str
(),
str_len
);
unsigned
char
*
data_hex
=
(
uint8_t
*
)
malloc
(
str_len
/
2
+
1
);
conv
::
ascii_to_hex
(
data_hex
,
(
const
char
*
)
data
);
Logger
::
amf_app
().
debug
(
"[Format string as Hex] Input string (%d bytes): %s "
,
str_len
,
str
.
c_str
());
Logger
::
amf_app
().
debug
(
"Data (formatted):"
);
#if DEBUG_IS_ON
for
(
int
i
=
0
;
i
<
str_len
/
2
;
i
++
)
printf
(
" %02x "
,
data_hex
[
i
]);
printf
(
"
\n
"
);
#endif
//free memory
//free_wrapper((void**) &data);
free
(
data
);
data
=
NULL
;
return
data_hex
;
}
//------------------------------------------------------------------------------
void
mime_parser
::
create_multipart_related_content
(
std
::
string
&
body
,
const
std
::
string
&
json_part
,
const
std
::
string
boundary
,
const
std
::
string
&
n1_message
,
const
std
::
string
&
n2_message
)
{
//TODO: provide Content-Ids as function parameters
//format string as hex
unsigned
char
*
n1_msg_hex
=
format_string_as_hex
(
n1_message
);
unsigned
char
*
n2_msg_hex
=
format_string_as_hex
(
n2_message
);
std
::
string
CRLF
=
"
\r\n
"
;
body
.
append
(
"--"
+
boundary
+
CRLF
);
body
.
append
(
"Content-Type: application/json"
+
CRLF
);
body
.
append
(
CRLF
);
body
.
append
(
json_part
+
CRLF
);
body
.
append
(
"--"
+
boundary
+
CRLF
);
body
.
append
(
"Content-Type: application/vnd.3gpp.5gnas"
+
CRLF
+
"Content-Id: n1SmMsg"
+
CRLF
);
body
.
append
(
CRLF
);
body
.
append
(
std
::
string
((
char
*
)
n1_msg_hex
,
n1_message
.
length
()
/
2
)
+
CRLF
);
body
.
append
(
"--"
+
boundary
+
CRLF
);
body
.
append
(
"Content-Type: application/vnd.3gpp.ngap"
+
CRLF
+
"Content-Id: n2msg"
+
CRLF
);
body
.
append
(
CRLF
);
body
.
append
(
std
::
string
((
char
*
)
n2_msg_hex
,
n2_message
.
length
()
/
2
)
+
CRLF
);
body
.
append
(
"--"
+
boundary
+
"--"
+
CRLF
);
}
//------------------------------------------------------------------------------
void
mime_parser
::
create_multipart_related_content
(
std
::
string
&
body
,
const
std
::
string
&
json_part
,
const
std
::
string
boundary
,
const
std
::
string
&
message
,
const
multipart_related_content_part_e
content_type
)
{
//TODO: provide Content-Id as function parameters
//format string as hex
unsigned
char
*
msg_hex
=
format_string_as_hex
(
message
);
std
::
string
CRLF
=
"
\r\n
"
;
body
.
append
(
"--"
+
boundary
+
CRLF
);
body
.
append
(
"Content-Type: application/json"
+
CRLF
);
body
.
append
(
CRLF
);
body
.
append
(
json_part
+
CRLF
);
body
.
append
(
"--"
+
boundary
+
CRLF
);
if
(
content_type
==
multipart_related_content_part_e
::
NAS
)
{
//NAS
body
.
append
(
"Content-Type: application/vnd.3gpp.5gnas"
+
CRLF
+
"Content-Id: n1SmMsg"
+
CRLF
);
}
else
if
(
content_type
==
multipart_related_content_part_e
::
NGAP
)
{
//NGAP
body
.
append
(
"Content-Type: application/vnd.3gpp.ngap"
+
CRLF
+
"Content-Id: n2msg"
+
CRLF
);
}
body
.
append
(
CRLF
);
body
.
append
(
std
::
string
((
char
*
)
msg_hex
,
message
.
length
()
/
2
)
+
CRLF
);
body
.
append
(
"--"
+
boundary
+
"--"
+
CRLF
);
}
src/utils/mime_parser.hpp
0 → 100644
View file @
a5e65b39
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file mime_parser.hpp
\brief
\author
\company Eurecom
\email:
*/
#ifndef FILE_MIME_PARSER_HPP_SEEN
#define FILE_MIME_PARSER_HPP_SEEN
# include <string>
#include <map>
#include <vector>
enum
class
multipart_related_content_part_e
{
JSON
=
0
,
NAS
=
1
,
NGAP
=
2
};
static
const
std
::
vector
<
std
::
string
>
multipart_related_content_part_e2str
=
{
"JSON"
,
"NAS"
,
"NGAP"
};
typedef
struct
mime_part
{
std
::
string
content_type
;
std
::
string
body
;
}
mime_part
;
class
mime_parser
{
public:
/*
* Parse the input string into different Mime parts
* @param [const std::string &] str: input string
* @return void
*/
bool
parse
(
const
std
::
string
&
str
);
/*
* Get vector of Mime parts
* @param [std::vector<mime_part> &] parts: store vector of Mime parts
* @return void
*/
void
get_mime_parts
(
std
::
vector
<
mime_part
>
&
parts
)
const
;
/*
* Represent a string as hex
* @param [const std::string&] str: input string
* @return String represents string in hex format
*/
unsigned
char
*
format_string_as_hex
(
const
std
::
string
&
str
);
/*
* Create HTTP body content for multipart/related message
* @param [std::string] body: Body of the created message
* @param [std::string] json_part: Json part of multipart/related msg
* @param [std::string] boundary: Boundary of multipart/related msg
* @param [std::string] n1_message: N1 (NAS) part
* @param [std::string] n2_message: N2 (NGAP) part
* @return void
*/
void
create_multipart_related_content
(
std
::
string
&
body
,
const
std
::
string
&
json_part
,
const
std
::
string
boundary
,
const
std
::
string
&
n1_message
,
const
std
::
string
&
n2_message
);
/*
* Create HTTP body content for multipart/related message
* @param [std::string] body: Body of the created message
* @param [std::string] json_part: Json part of multipart/related msg
* @param [std::string] boundary: Boundary of multipart/related msg
* @param [std::string] message: N1 (NAS) or N2 (NGAP) part
* @param [uint8_t] content_type: 1 for NAS content, else NGAP content
* @return void
*/
void
create_multipart_related_content
(
std
::
string
&
body
,
const
std
::
string
&
json_part
,
const
std
::
string
boundary
,
const
std
::
string
&
message
,
const
multipart_related_content_part_e
content_type
);
private:
std
::
vector
<
mime_part
>
mime_parts
;
};
#endif
/* FILE_MIME_PARSER_HPP_SEEN */
src/utils/multipartparser.cpp
deleted
100644 → 0
View file @
824102f8
This diff is collapsed.
Click to expand it.
src/utils/multipartparser.hpp
deleted
100644 → 0
View file @
824102f8
/*
* https://github.com/iafonov/multipart-parser-c
*/
#ifndef MULTIPARTPARSER_H
#define MULTIPARTPARSER_H
#include <map>
#include <string>
#include <list>
extern
"C"
{
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>
}
typedef
struct
multipartparser
multipartparser
;
typedef
struct
multipartparser_callbacks
multipartparser_callbacks
;
typedef
int
(
*
multipart_cb
)
(
multipartparser
*
);
typedef
int
(
*
multipart_data_cb
)
(
multipartparser
*
,
const
char
*
data
,
size_t
size
);
struct
multipartparser
{
/** PRIVATE **/
char
boundary
[
70
];
int
boundary_length
;
int
index
;
uint16_t
state
;
/** PUBLIC **/
void
*
data
;
};
struct
multipartparser_callbacks
{
multipart_cb
on_body_begin
;
multipart_cb
on_part_begin
;
multipart_data_cb
on_header_field
;
multipart_data_cb
on_header_value
;
multipart_cb
on_headers_complete
;
multipart_data_cb
on_data
;
multipart_cb
on_part_end
;
multipart_cb
on_body_end
;
};
void
multipartparser_init
(
multipartparser
*
parser
,
const
char
*
boundary
);
void
multipartparser_callbacks_init
(
multipartparser_callbacks
*
callbacks
);
size_t
multipartparser_execute
(
multipartparser
*
parser
,
multipartparser_callbacks
*
callbacks
,
const
char
*
data
,
size_t
size
);
#define BOUNDARY "----Boundary"
typedef
struct
part
{
std
::
map
<
std
::
string
,
std
::
string
>
headers
;
std
::
string
body
;
}
part
;
static
multipartparser_callbacks
g_callbacks
;
static
bool
g_body_begin_called
;
static
std
::
string
g_header_name
;
static
std
::
string
g_header_value
;
static
std
::
list
<
part
>
g_parts
;
static
bool
g_body_end_called
;
static
void
init_globals
()
{
g_body_begin_called
=
false
;
g_header_name
.
clear
();
g_header_value
.
clear
();
g_parts
.
clear
();
g_body_end_called
=
false
;
}
static
int
on_body_begin
(
multipartparser
*
/*parser*/
)
{
g_body_begin_called
=
true
;
return
0
;
}
static
int
on_part_begin
(
multipartparser
*
/*parser*/
)
{
g_parts
.
push_back
(
part
());
return
0
;
}
static
void
on_header_done
()
{
g_parts
.
back
().
headers
[
g_header_name
]
=
g_header_value
;
g_header_name
.
clear
();
g_header_value
.
clear
();
}
static
int
on_header_field
(
multipartparser
*
/*parser*/
,
const
char
*
data
,
size_t
size
)
{
if
(
g_header_value
.
size
()
>
0
)
on_header_done
();
g_header_name
.
append
(
data
,
size
);
return
0
;
}
static
int
on_header_value
(
multipartparser
*
/*parser*/
,
const
char
*
data
,
size_t
size
)
{
g_header_value
.
append
(
data
,
size
);
return
0
;
}
static
int
on_headers_complete
(
multipartparser
*
/*parser*/
)
{
if
(
g_header_value
.
size
()
>
0
)
on_header_done
();
return
0
;
}
static
int
on_data
(
multipartparser
*
/*parser*/
,
const
char
*
data
,
size_t
size
)
{
std
::
string
str
;
//g_parts.back().body.append(data, size);
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
//printf("%02x ",data[i]);
str
.
push_back
(
data
[
i
]);
}
g_parts
.
back
().
body
.
append
(
str
);
return
0
;
}
static
int
on_part_end
(
multipartparser
*
/*parser*/
)
{
return
0
;
}
static
int
on_body_end
(
multipartparser
*
/*parser*/
)
{
g_body_end_called
=
true
;
return
0
;
}
#endif // MULTIPARTPARSER_H
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment