[Mediaserver]mini_Mediaserver_1-코드설명/code description-handshake-(1-1)

👉🏻 아래는 RTMP 핸드 셰이크에 대한 설명입니다.
Below is an explanation of the RTMP handshake.

👉🏻RTMP 전체 흐름 / RTMP full flow , RTMP핸드 셰이크 / RTMP Handshake

  1. TCP 연결 / TCP connection
    OBS →server:1935 연결
    OBS → server:1935 connection
  2. RTMP 핸드셰이크 / RTMP Handshake
    1)OBS → 서버: C0+C1 1537바이트
    OBS → Server: C0+C1 1537 bytes

    2)서버 → OBS: S0+S1+S2 3073바이트
    Server → OBS: S0+S1+S2 3073 bytes

    3)OBS → 서버: C2 1536바이트
    OBS → Server: C2 1536 bytes –> 여기까지 / Until here

👉🏻1.TCP 연결 / TCP connection

# 1935 연결 / 1935 connection,rtmp_server.cpp
void RtmpServer::do_accept() {}

👉🏻2.RTMP 핸드 셰이크 / RTMP Handshake

✔️ RTMP는 Adobe가 만든 프로토콜로 C0C1 → S0S1S2 → C2 순서를 무조건 지켜야합니다.

✔️ 서버와 클라이언트 간의 통신이 RTMP 프로토콜이 맞는지 확인하기 위해서 핸드셰이크 과정 실행합니다.
The handshake process is executed to verify that the communication between the server and the client uses the RTMP protocol.

# OBS -> Server
void RtmpSession::do_handshake_c0c1() {}
void RtmpSession::do_handshake_s0s1s2() {}
void RtmpSession::do_handshake_c2() {}

✔️ void RtmpSession::do_handshake_c0c1(){}

— 핸드셰이크 1단계입니다. / This is step 1 of the handshake.

— OBS가 보낸 C0+C1 받는 함수 입니다.
This is a function that receives C0+C1 sent by OBS.

— asio::async_read(socket_, asio::buffer(c0c1_, 1537) :

1)RTMP 규격 / RTMP standard:

  • C0: 1바이트 = RTMP 버전. 항상 0x03(16진수,10진수로는 3)
    C0: 1 byte = RTMP version. Always 0x03 (hexadecimal, 3 in decimal)
  • C1: 1536바이트 = time, zero, random 데이터
  • C1: 1536 bytes = time, zero, random data

2)C0 + C1 = 1537 byte

3)버전체크 성공하면 do_handshake_s0s1s2(); 실행
If the version check is successful, execute do_handshake_s0s1s2();

void RtmpSession::do_handshake_c0c1() {

    // RtmpSession정보 복사
    // Copy RtmpSession information
    //
    // auto self = shared_from_this();
    // auto self = shared_from_this();
    //
    // 아래는 shared_ptr 객체를 하나더 만듦
    // The following creates another shared_ptr object
    auto self(shared_from_this());

    // OBS가 보낸 C0+C1 1537바이트를 c0c1_ 배열에 저장
    // Store the 1537 bytes of C0+C1 sent by OBS in the c0c1_ array
    asio::async_read(socket_, asio::buffer(c0c1_, 1537),
        [this, self](std::error_code ec, std::size_t) {
            // 프로토콜 버전 체크 / Check protocol version
            if (ec || c0c1_[0]!= 0x03) return;
            std::cout << "[Handshake] C0C1 received\n";
            do_handshake_s0s1s2();
        });
}

✔️ void RtmpSession::do_handshake_s0s1s2(){}

— 핸드셰이크 2단계입니다.
This is step 2 of the handshake.

— OBS에서 받은 정보를 서버정보와 취합해서 다시 OBS에게 돌려 줍니다.
It combines the information received from OBS with server information and returns it to OBS.

— 3073바이트를 OBS에 전송하고나서 do_handshake_c2();를 실행합니다.
After sending 3073 bytes to OBS, execute do_handshake_c2();.

영역/Area크기/Size인덱스/Index내용/Detail코드/Code
S01byte[0]Version 0x03s0s1s2_[0] = 0x03
S11536byte[1∼1536]서버 데이터/Server data
S1:time4byte[1∼4]서버 현재시간/Server Current timememcpy(&s0s1s2_[1], &time, 4)
S1:zero4byte[5∼8]0으로 채움 / Fill with zerosmemset(&s0s1s2_[5], 0, 4)
S1:random1528byte[9∼1536]랜덤값 / Random valueRAND_bytes(&s0s1s2_[9], 1528)
S21536byte[1537∼3072]C1 복사본 / C1 copymemcpy(&s0s1s2_[1537], &c0c1_[1], 1536)
// 서버 → OBS로 S0+S1+S2 3073바이트 보내는 핸드셰이크 2단계
// Handshake Step 2: Sending 3073 bytes (S0+S1+S2) from Server to OBS
void RtmpSession::do_handshake_s0s1s2() {
    // 세션 정보 유지 / Maintain session information
    auto self(shared_from_this());
    s0s1s2_[0] = 0x03; // 서버버전 03 / Server version 03

    // 현재시간 빅엔디안 변환,네트워크 바이트 순서 = 빅엔디안 변환,OBS가 RTT 계산할 때 씀.
    // Current time converted to Big Endian, Network Byte Order = Big Endian conversion,
    // used by OBS when calculating RTT.
    uint32_t time = htonl(static_cast<uint32_t>(::time(nullptr)));

    // S1 첫 4바이트에 서버 현재시간 넣음.
    // Insert server current time into the first 4 bytes of S1.
    std::memcpy(&s0s1s2_[1], &time, 4);

    // S1 4∼7바이트는 규격상 0으로 채워야 함.
    // S1 bytes 4~7 must be filled with zeros according to the standard.
    std::memset(&s0s1s2_[5], 0, 4);

    // OpenSSL로 랜덤값 채움(RTMPE면 공개 키 역할)
    // Fill with random values ​​using OpenSSL (acts as public key if RTMPE)
    RAND_bytes(&s0s1s2_[9], 1528);

    // &s0s1s2_[1537]에 &c0c1_[1] 정보를 1536바이트만큼 복사
    // Copy 1536 bytes of &c0c1_[1] information to &s0s1s2_[1537]
    //
    // 1537 = S0+S1이 1537바이트

    // 1537 = S0+S1 is 1537 bytes
    std::memcpy(&s0s1s2_[1537], &c0c1_[1], 1536);

    // 전체 3073바이트를 OBS로 전송
    // Send the entire 3073 bytes to OBS
    asio::async_write(socket_, asio::buffer(s0s1s2_, 3073),
        [this, self](std::error_code ec, std::size_t) {
            if (ec) return;
            std::cout << "[Handshake] S0S1S2 sent\n";
            do_handshake_c2();
        });
}

✔️ void RtmpSession::do_handshake_c2() {}

— 핸드셰이크 3단계입니다.
This is step 3 of the handshake.

— OBS로 부터 두번째로(C2) 1536바이트를 받습니다.
Receive 1536 bytes for the second (C2) from OBS.

— 완전히 다 받으면 send_protocol_messages(); 함수를 실행합니다.
Once everything is fully received, the send_protocol_messages(); function is executed.

Leave a Reply