NetMessage API#
Oasis network messages are processed through the NetMessage API.
NetMessage is passed as a parameter to network component interfaces and is used for requests or responses.
Header File#
OasisNet.h
Functions#
true, and creates a response message if false.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- true: The key exists in the query set.
- false: The key does not exist in the query set.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- true: It is a request message.
- false: It is a response message.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- true: It is a chunked message.
- false: It is a single message.
- true: It is in a ready state.
- false: It is still downloading.
- 0: Success
- -1: Failure
- true: It is in a connected state.
- false: It is in a disconnected state.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
Access-Control-Allow-Origin header field. If nullptr, the value "" is assigned. When msg is a response message and the Access-Control-Allow-Origin header field value is "", if the Origin header field of the request message (req_msg) exists, it can be replaced with the value of the Origin header field of the request message. Refer to the descriptions for allow_credentials and allow_private_network_access.
Access-Control-Allow-Methods header field. If nullptr, the value "OPTIONS,GET" is assigned.
Access-Control-Allow-Headers header field. If nullptr, the value "*" is assigned.
Access-Control-Request-Credentials header field exists in the request message (req_msg). It does not apply if the request message is invalid. It sets the Access-Control-Allow-Credentials header field value of the response message to "true" or "false" according to allow_credentials. If the Access-Control-Request-Credentials header field value of the request message is "true" and the origin value is nullptr or "*", the Access-Control-Allow-Origin header field value of the response message is replaced with the Origin header field value of the request message.
Access-Control-Request-Private-Network header field exists in the request message (req_msg). It does not apply if the request message is invalid. It sets the Access-Control-Allow-Private-Network header field value of the response message to "true" or "false" according to allow_private_network_access. If the Access-Control-Request-Private-Network header field value of the request message is "true" and the origin value is nullptr or "*", the Access-Control-Allow-Origin header field value of the response message is replaced with the Origin header field value of the request message.
Access-Control-Max-Age header field value. If 0, it is set to 86400 seconds.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
*file_data_ptr value can be nullptr, which implies that the file data is saved as a cache file rather than in memory. In this case, the data must be read by explicitly passing the std::vector<char> &file_data argument using the netMessageGetFormDataFileData API below. This function can be called by specifying the file_data_ptr value as nullptr for the simple purpose of verifying the file data type, filename, and file data length.
*file_data_ptr value returns nullptr.
- 0: Success
- -1: Failure
- 0: Success
- -1: Failure
Below is an example of processing when a file transmission request is received from a client on a web server. Error situations are not considered.
void MyHttpUpStreamDelegate::onRequest(const NetMessageRef &msg)
{
std::string url;
netMessageUriGetPath(msg, url);
NetMessageRef res = netMessageCreate(msg, false);
std::string path = http_root_dir_path + url;
if(access(path.c_str(), F_OK) == 0) {
//get mime type based on extension
const char *mime_type = get_file_mime_type(path.c_str());
if(mime_type == nullptr) {
//not supported
netMessageSetStatusCodeAndReasonString(res, 403, "Forbidden");
netMessagePost(res);
} else {
// Transmits the file.
netMessageSendFile(res, path.c_str(), mime_type);
}
} else {
netMessageSetStatusCodeAndReasonString(res, 400, "Bad Request");
netMessagePost(res);
}
}
- 0: Success
- -1: Failure
Examples#
Examples using the message API are located in the documentation for each network component of Oasis.
Below is an example of a web client receiving a large file from a web server, an example of transmitting form data to a web server, and an example of a web server saving a form data file transmitted by a web client.
Receiving a Large File from a Web Server#
Connect to the web server.
const int32_t timeout = 60000;
HttpConnectionRef conn = httpOpenConnection(
"https://example.com/data/firmware.img",
timeout,
"/tmp" /* Cache directory */
);
Obtain the request message from the connection object, set the Method to GET, and transmit the request message to the server.
NetMessageRef msg = httpConnectionGetRequestMessage(conn);
netMessageSetMethod(msg, "GET");
netMessagePost(msg);
Receive the response header from the server. If there is no response within a certain period of time, it is considered a failure.
NetMessageRef res_msg;
wait_count = 0;
do {
res_msg = httpConnectionGetResponseHeaderMessage(conn, 1000);
wait_count++;
} while(res_msg == nullptr && continuing_ && wait_count*1000 < timeout);
if(res_msg == nullptr || !continuing_) {
return -1;
}
Verify the response code. If it is not 200, it is considered an error response.
std::string reason_string;
int32_t status_code = netMessageGetStatusCodeAndReasonString(res_msg, reason_string);
if(status_code != 200) {
return -1;
}
Verify the response content length. If the file length is invalid, it is considered an error.
ssize_t content_length = netMessageGetContentLength(res_msg);
if(content_length < 0) {
return -1;
}
Verify until the file data reception is completely finished through the loop below. If the connection is cut off or the user cancels during reception, it is considered an error.
do {
ssize_t current_length = netMessageGetCurrentContentLength(res_msg);
if(current_length >= 0) {
// The data length received up to the current point can be verified.
}
usleep(1000000);
} while(netMessageIsConnected(res_msg) && netMessageIsContentReady(res_msg) == false && continuing_);
if(!netMessageIsContentReady(res_msg) || !continuing_) {
return -1;
}
Obtain the file path saved in the cache directory (/tmp).
std::string filepath;
netMessageGetContentFilePath(res_msg, filepath);
Delete the file after use.
unlink(filepath.c_str());
Transmitting Form Data to a Web Server#
Connect to the web server.
const int32_t timeout = 60000;
HttpConnectionRef conn = httpOpenConnection(
"https://example.com/api/status/update",
timeout;
Obtain the request message from the connection object and set the Method to POST.
NetMessageRef msg = httpConnectionGetRequestMessage(conn);
netMessageSetMethod(msg, "POST");
Configure the form field data and transmit.
netMessageAddFieldToMultipartFormData(msg, "state", "idle");
// Specifies the file path to transmit the file data together.
netMessageAddFileToMultipartFormData(msg, "image", file_name.c_str(), file_path_.c_str(), get_file_mime_type(file_path_.c_str()));
netMessagePost(msg);
Receive the response header from the server. If there is no response within a certain period of time, it is considered a failure.
NetMessageRef res_msg;
wait_count = 0;
do {
res_msg = httpConnectionGetResponseHeaderMessage(conn, 1000);
wait_count++;
} while(res_msg == nullptr && continuing_ && wait_count*1000 < timeout);
if(res_msg == nullptr || !continuing_) {
return -1;
}
Verify the response code. If it is not 200, it is considered an error response.
std::string reason_string;
int32_t status_code = netMessageGetStatusCodeAndReasonString(res_msg, reason_string);
if(status_code != 200) {
return -1;
}
Verify the response content length and obtain the response content. Usually, the server transmits response data in JSON format. If the file length of the message is invalid, it is considered an error.
ssize_t content_length = netMessageGetContentLength(res_msg);
if(content_length < 0) {
return -1;
}
std::vector<char> res_content;
netMessageGetContent(res_msg, res_content);
Process the response message.
Saving a Form Data File on a Web Server#
Create and start the web server. Specify the cache directory and specify multipart/form-data for the content types to be cached.
Error situations are not considered in the example.
parameters["port"] = std::to_string(http_port);
parameters["root-dir"] = "/var/www/htdocs";
parameters["content-length-max"] = std::to_string(200*1024*1024);
parameters["cache-dir"] = "/tmp";
parameters["cached-content-types"] = "multipart/form-data,multipart/mixed";
std::shared_ptr<MyHttpUpStreamDelegate> http_delegate = std::make_shared<MyHttpUpStreamDelegate>();
HttpServerRef http_server = oasis::createHttpServer(parameters, http_delegate);
oasis::startHttpServer(http_server);
When a web client transmits the file specified in the "image" file input field of the form data to the web server, the web server saves this response message in the cache folder.
The web server saves the file uploaded by the web client in the MyHttpUpStreamDelegate::onRequest callback function and sends a response code in JSON.
virtual void MyHttpUpStreamDelegate::onRequest(const NetMessageRef &msg) {
std::string url;
netMessageUriGetPath(msg, url);
if(url == "/api/status/update") {
std::string content_type, filename;
ssize_t size = netMessageGetFormDataFileData(msg, "image", content_type, filename, nullptr);
if(size > 0) {
char path[PATH_MAX];
sprintf(path, "/tmp/%s", filename.c_str());
ssize_t saved_size = netMessageSaveFormDataFileDataAs(msg, "image", path);
}
NetMessageRef res = netMessageCreate(msg, false);
netMessageSetStatusCodeAndReasonString(res, 200, "OK");
netMessageSetHeaderField(res, "Connection", "close");
std::string json_string = R"({ "result":"OK" })";
netMessageSetContent(res, "application/json", json_string.c_str(), json_string.length());
netMessagePost(res);
}
}