UDP API¶
Oasis는 UDP(User Datagram Protocol) 서버와 클라이언트를 지원합니다.
보안 연결로 DTLS 버전1.2를 지원합니다.
헤더 파일¶
OasisNet.h
UdpEventDelegate 인터페이스¶
class UdpEventDelegate : public std::enable_shared_from_this<UdpEventDelegate>
{
public:
UdpEventDelegate();
virtual ~UdpEventDelegate();
public:
};
현재는 정의되어 있는 이벤트 콜백 함수가 없습니다.
함수¶
UdpConnectionRef
udpCreate
(
int32_t
s
,
bool
is_secure
,
key_value_map_t &
parameters
)
OasisNet.h
소켓 핸들로 부터 UDP 연결 객체를 생성합니다.
매개변수
s
SOCK_DGRAM 특성을 갖는 소켓 핸들 번호입니다.
is_secure
true이면 보안 프로토콜 (DTLS)를 적용합니다.
parameters
객체 생성에 필요한 key-value map입니다.
리턴값
성공하면 UDP 연결 객체를 리턴합니다. 실패하면 nullptr을 리턴합니다.
아래는 UDP 연결 객체 생성에 필요한 key-value map입니다.
키
기본값
필수
설명
tls-enabled
0
TLS 활성화 여부를 지정합니다. "1"이면 활성화되며, "0"이면 TLS를 사용하지 않습니다. 사용할 경우 인증서 경로등 키값이 유효해야 합니다. "1"인 경우, cert-file-path 와 pkey-file-path를 지정해야 합니다.
tls-version
1.2
TLS 버전입니다. "1.2"를 입력합니다.
tls-client-verify
0
접속 클라이언트의 인증서를 검증할 지 여부를 지정합니다. "1" 이면 tls-certificate-request-authority-names 키에 등록된 이름만 연결 허용합니다.
tls-certificate-request-authority-names
\0xa 로 구분된 기관명(CN) 목록입니다. 일례로, "MediaStek-Root-CA\x0aMediaStek Inc." 와 같은 형식입니다.
ca-certs-file-path
\0xa 로 구분된 PEM 양식의 ROOT CA 인증서 파일 경로입니다. 일례로, "/data/certs/cacerts.pem\x0a/data/certs/RootCA.pem" 와 같은 형식입니다.
cert-file-path
○
RSA, ECDSA, DSS 등의 PEM 양식의 공개 인증서 파일 경로입니다.
pkey-file-path
○
PEM 양식의 개인키 파일 경로입니다.
UdpConnectionRef
udpCreate
(
const char *
local_ip_address
,
uint16_t
local_port
,
bool
is_secure
,
key_value_map_t &
parameters
)
OasisNet.h
주소와 포트 번호를 이용하여 UDP 연결 객체를 생성합니다.
매개변수
local_ip_address
로컬 IPv4 주소 문자열입니다.
local_port
로컬 포트 번호입니다.
is_secure
true이면 보안 프로토콜 (DTLS)를 적용합니다.
parameters
객체 생성에 필요한 key-value map입니다.
리턴값
성공하면 UDP 연결 객체를 리턴합니다. 실패하면 nullptr을 리턴합니다.
int32_t
udpSetAsyncEventDelegate
(
const UdpConnectionRef &
connection
,
const std::shared_ptr<UdpEventDelegate> &
delegate
,
void *
user_data
)
OasisNet.h
UdpEventDelegate로 부터 유도된 사용자 정의 객체를 설정합니다. 현재는 아무런 이벤트도 발생하지 않습니다.
매개변수
connection
UDP 연결 객체입니다.
delegate
UdpEventDelegate로 부터 유도된 사용자 정의 객체입니다.
user_data
UdpEventDelegate로 부터 유도된 사용자 정의 객체의 이벤트 콜백 함수에 전달될 사용자 정의 데이터입니다.
리턴값
- 0: 성공
- -1: 실패
int32_t
udpAccept
(
const UdpConnectionRef &
connection
,
const char *
remote_ip_address
,
uint16_t
remote_port
,
int32_t
timeout
)
OasisNet.h
매개변수
connection
UDP 연결 객체입니다.
remote_ip_address
특정 원격지만 수락할 경우, 원격지의 IPv4 주소입니다.
remote_port
특정 원격지만 수락할 경우, 원격지의 포트 번호입니다.
timeout
접속 요청을 수락할 때까지 대기 시간입니다. 밀리초 단위입니다. "0" 값이면 무한정 대기합니다.
리턴값
성공할 경우, 소켓 핸들 번호를 리턴합니다. 실패하면 -1을 리턴합니다.
int32_t
udpConnect
(
const UdpConnectionRef &
connection
,
const char *
remote_ip_address
,
uint16_t
remote_port
,
int32_t
timeout
)
OasisNet.h
UDP 서버에 접속합니다.
매개변수
connection
UDP 연결 객체입니다.
remote_ip_address
접속할 원격지 서버의 IPv4 주소입니다.
remote_port
접속할 원격지 서버의 포트 번호입니다.
timeout
접속될 때 까지 기다리는 최대 시간입니다. 밀리초 단위입니다.
리턴값
성공하면 접속된 소켓 핸들 번호를 리턴합니다. 실패하면 -1을 리턴합니다.
ssize_t
udpSend
(
const UdpConnectionRef &
connection
,
int32_t
s
,
const void *
data
,
size_t
length
)
OasisNet.h
데이터를 전송합니다.
매개변수
connection
UDP 연결 객체입니다.
s
연결된 소켓 핸들 번호입니다.
data
전송할 데이터 버퍼 포인터입니다.
length
전송할 데이터 길이입니다. 바이트 단위입니다.
리턴값
ssize_t
udpReceive
(
const UdpConnectionRef &
connection
,
int32_t
s
,
void *
data
,
size_t
size
,
int32_t
timeout
)
OasisNet.h
데이터를 수신합니다.
매개변수
connection
UDP 연결 객체입니다.
s
연결된 소켓 핸들 번호입니다.
data
OUT
수신한 데이터를 저장할 버퍼 포인터입니다.
size
버퍼 최대 크기입니다. 바이트 단위입니다.
timeout
대기 시간입니다. 밀리초 단위입니다.
리턴값
수신된 데이터 길이를 리턴합니다. 바이트 단위입니다. 실패하거나 연결이 끊긴 경우, -1을 리턴합니다.
int32_t
udpClose
(
const UdpConnectionRef &
connection
,
int32_t
s
)
OasisNet.h
연결을 닫습니다.
매개변수
connection
UDP 연결 객체입니다.
s
연결된 소켓 핸들 번호입니다.
리턴값
- 0: 성공
- -1: 실패
int32_t
udpDestroy
(
UdpConnectionRef &
connection
)
OasisNet.h
UDP 연결 객체를 해제합니다.
매개변수
connection
UDP 연결 객체입니다.
리턴값
- 0: 성공
- -1: 실패
예제¶
UDP 서버¶
아래는 DTLS UDP 통신을 하는 서버 예입니다.
#include "OasisAPI.h"
#include "OasisLog.h"
#include "OasisNet.h"
#include <thread>
#include <mutex>
#include <memory>
#include <condition_variable>
#define DLOG_THIS 0x00080000
#undef DLOG_FLAGS
#define DLOG_FLAGS (DLOG_FLAGS_DEFAULT|DLOG_THIS/**/)
#undef DLOG_TAG
#define DLOG_TAG "DTLSS"
#define USE_RSA 1
#define USE_ECDSA 0
#define USE_DSS 0
#define DTLS_CLIENT_VERIFY 0
using namespace oasis;
static bool continuing = true;
class MyUdpEventDelegate : public UdpEventDelegate
{
public:
MyUdpEventDelegate() {}
virtual ~MyUdpEventDelegate() {}
};
void cancel_handler(int signum)
{
continuing = false;
}
int main(int argc, char* argv[])
{
int32_t c, err;
uint16_t port;
std::thread t3;
key_value_map_t parameters, fields;
if(argc < 2) {
printf("USAGE: %s <port number>\n", argv[0]);
return 255;
}
port = (uint16_t)atoi(argv[1]);
if(port == 0) {
printf("USAGE: %s <port number>\n", argv[0]);
return 255;
}
signal(SIGINT, cancel_handler);
parameters["offs-disable"] = "1";
if(oasis::initialize(parameters) < 0) {
DLOG(DLOG_ERROR, "Oasis init failed\n");
return -1;
}
parameters.clear();
#if DTLS_CLIENT_VERIFY
//when restrict the accessible clients, each of which root ca should be the same as the server's.
parameters["tls-client-verify"] = "1";
//\x0a-seperated strings (if needs. by default server's CN used)
parameters["tls-certificate-request-authority-names"] = "MediaStek-Root-CA\x0aMediaStek Inc.";
#endif
parameters["ca-certs-file-path"] = "/data/certs/RootCA.pem";
#if USE_RSA
parameters["cert-file-path"] = "/data/certs/fullchain.pem";
parameters["pkey-file-path"] = "/data/certs/privkey.pem";
#elif USE_ECDSA
//ECDSA
parameters["cert-file-path"] = "/data/certs/ec_fullchain.pem";
parameters["pkey-file-path"] = "/data/certs/ec_pkey.pem";
#elif USE_DSS
parameters["cert-file-path"] = "/data/certs/dsa_fullchain.pem";
parameters["pkey-file-path"] = "/data/certs/dsa_pkey.pem";
#else
#error "No certficates!"
#endif
std::shared_ptr<MyUdpEventDelegate> delegate = std::make_shared<MyUdpEventDelegate>();
UdpConnectionRef conn;
conn = udpCreate(nullptr, port, true, parameters);
ASSERT(conn != nullptr);
t3 = std::thread([&]() {
do {
DLOG(DLOG_THIS, "accepting...\n");
int32_t c = udpAccept(conn, nullptr, 0, 0);
DLOG(DLOG_THIS, "accepted socket %d\n", c);
if(c >= 0) {
uint8_t buffer[65536];
ssize_t length = udpReceive(conn, c, buffer, sizeof(buffer), 100000);
if(length > 0) {
DUMP("RX", buffer, length);
}
udpClose(conn, c);
}
} while(continuing && conn);
});
do {
usleep(100000);
} while (continuing);
udpDestroy(conn);
if (t3.joinable()) {
t3.join();
}
oasis::finalize();
return 0;
}
UDP 클라이언트¶
아래는 DTLS UDP 서버에 접속 후 1초 간격으로 메세지를 전송하는 클라이언트 예입니다.
#include "OasisAPI.h"
#include "OasisLog.h"
#include "OasisNet.h"
#include <thread>
#include <mutex>
#include <memory>
#include <condition_variable>
#define DLOG_THIS 0x00080000
#undef DLOG_FLAGS
#define DLOG_FLAGS (DLOG_FLAGS_DEFAULT|DLOG_THIS/**/)
#undef DLOG_TAG
#define DLOG_TAG "DTLSC"
using namespace oasis;
static bool continuing = true;
void cancel_handler(int signum)
{
continuing = false;
}
int main(int argc, char* argv[])
{
int32_t err;
int32_t status_code;
std::string reason_string;
std::string content_type;
std::vector<char> res_content;
size_t content_length;
int32_t wait_count = 0;
key_value_map_t parameters, fields;
if(argc < 3) {
printf("USAGE: %s <target address> <port>\n", argv[0]);
return 255;
}
signal(SIGINT, cancel_handler);
const char *remote_ip = argv[1];
uint16_t remote_port = (uint16_t)atoi(argv[2]);
if(remote_port == 0) {
printf("USAGE: %s <target address> <port>\n", argv[0]);
return 255;
}
parameters["offs-disable"] = "1";
if(oasis::initialize(parameters) < 0) {
DLOG(DLOG_ERROR, "Oasis init failed\n");
return -1;
}
parameters.clear();
parameters["ca-certs-file-path"] = "/data/certs/cacerts.pem\x0a/data/certs/RootCA.pem";
parameters["cert-file-path"] = "/data/certs/client_fullchain.pem";
parameters["pkey-file-path"] = "/data/certs/client_privkey.pem";
UdpConnectionRef conn;
char buffer[512];
ssize_t len;
int ch;
conn = udpCreate(nullptr, 0, true, parameters);
if(conn) {
int32_t c = udpConnect(conn, remote_ip, remote_port, 10000);
if(c >= 0) {
DLOG(DLOG_THIS, "connected %d\n", c);
DLOG(DLOG_THIS, "press Ctrl+C to disconnect and quit.\n");
do {
fprintf(stdout, "> ");
fflush(stdout);
len = 128;
for(int32_t i=0; i<len; i++) {
buffer[i] = '0' + (i%10);
}
buffer[len] = 0;
udpSend(conn, c, buffer, len);
usleep(1000000);
} while (continuing);
udpClose(conn, c);
}
udpDestroy(conn);
}
conn = nullptr;
done:
oasis::finalize();
return 0;
}