long .vd

@hellfire11

Albania, â

Institution: TP

AMF.cpp 143: unsigned int numberElement = 0; Buffer.cpp 79: //Xu li truong hop het buffer 88: (*ppBuffer) = data_pos; Buffer.h remove 1 13: //#include "log.h" 14: #pragma once RTMP.cpp #include "rtmp.h" #include "RTMP_LOG.h" #define FLOW_CODE #define PREFIX "[%s]: " #define FUNCTION __FUNCTION__ /*Temp*/ int32_t GetTime() { #if defined(WIN32) return timeGetTime(); #else struct tms t; return times(&t); #endif } /** * Send * @param buffer: * @param length: * @returns: */ int RTMP::Send(char* buffer, int length) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE int nbyte_send = 0; return 0; } /** * Receive * @param buffer: * @param length: * @returns: */ int RTMP::Receive(char* buffer, int len) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE int nbyte_send = 0; return 0; } /** * Send data * @param buffer: buffer data * @param length: length of data can be read * @returns: number of bytes was sent */ //int RTMP::SendRTMPMessage(char* buffer, int length) //{ // int nByteSent = 0, result = length; // char* pBuffer = buffer; // while (length > 0) // { // nByteSent = send(service.connect_socket, pBuffer, length, 0); // assert(nByteSent > 0); // length -= nByteSent; // pBuffer += nByteSent; // } // // return result - length; //} /** * received data from Server * @param r: contains network information which used to connect contains receiver data * @param buffer: buffer store data * @param len: length of data can be read * @returns: length of data was received */ //int RTMP::ReceiveRTMPMessage(char* buffer, int length) //{ // int nByteRecv = 0, result = length; // char* pBuffer = buffer; // while (length > 0) // { // nByteRecv = recv(service.connect_socket, pBuffer, length, 0); // assert(nByteRecv > 0); // length -= nByteRecv; // // pBuffer += nByteRecv; // } // // return result - length; //} /** * Handle the connection via socket between Client and Server * @param hostname: server domain or IP * @param port: port connect * @returns: true == success */ bool RTMP::SocketConnect(const char* hostname, const unsigned short port) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE ConfigSocket(hostname, port); SOCKET _socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); assert(_socket != SOCKET_ERROR && "Cannot init socket"); //assert(connect(_socket, (sockaddr*)&(service.sockAddr), sizeof(service.sockAddr)) >= 0); int iResult = connect(_socket, (SOCKADDR *)& (service.sockAddr), sizeof(service.sockAddr)); if (iResult == SOCKET_ERROR) { RTMP_LOG(PREFIX"Connect function failed with error: %d\n", FUNCTION, WSAGetLastError()); iResult = closesocket(_socket); if (iResult == SOCKET_ERROR) RTMP_LOG(PREFIX"losesocket function failed with error: %d\n", FUNCTION, WSAGetLastError()); WSACleanup(); return false; } DWORD timeout = SOCKET_READ_TIMEOUT_SEC * 1000; setsockopt(_socket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, "1", 1); service.connect_socket = _socket; return true; } /** * decode the host name to IP Address * @param hostname: * @param port: * @returns: */ bool RTMP::ConfigSocket(const char* hostname, const unsigned short port) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE if (hostname == NULL || strlen(hostname) == 0 || port < 0) { RTMP_LOG(PREFIX"Hostname or port is invalid\n", FUNCTION); return false; } service.sockAddr.sin_family = AF_INET; service.sockAddr.sin_addr.s_addr = inet_addr(hostname); service.sockAddr.sin_port = htons((u_short)port); if (service.sockAddr.sin_addr.s_addr == INADDR_NONE) { //assert(strlen(hostname) != 0 && isalpha(hostname[0]) && "Host name have no value"); if (!isalpha(hostname[0])) { RTMP_LOG(PREFIX"Hostname is invalid\n", FUNCTION); return false; } struct hostent *remoteHost = gethostbyname(hostname); //assert(remoteHost != NULL && "Cannot decode the hostname"); if (remoteHost == NULL) { RTMP_LOG(PREFIX"Cannot decode the hostname\n", FUNCTION); return false; } memcpy(&(service.sockAddr.sin_addr), remoteHost->h_addr_list[0], remoteHost->h_length); } return true; } int RTMP::AMFEncodeNumber64(char* buffer, double value) { char* pBuffer = buffer; *pBuffer++ = 0x00; uint64_t x = *((uint64_t*)&value); memcpy(pBuffer, &x, 8); SWAP64(pBuffer); pBuffer += 8; return RESULT(pBuffer, buffer, 9); } int RTMP::AMFEncodeNumber32(char* buffer, int value) { char* pBuffer = buffer; memcpy(pBuffer, &value, 4); SWAP32(pBuffer); pBuffer += 4; return RESULT(pBuffer, buffer, 4); } int RTMP::AMFEncodeNumber24(char* buffer, int value) { char* pBuffer = buffer; memcpy(pBuffer, &value, 3); SWAP(pBuffer[0], pBuffer[2]); pBuffer += 3; return RESULT(pBuffer, buffer, 3); } int RTMP::AMFEncodeNumber16(char* buffer, unsigned short value) { char* pBuffer = buffer; memcpy(pBuffer, &value, 2); SWAP16(pBuffer); pBuffer += 2; return RESULT(pBuffer, buffer, 2); } int RTMP::AMFEncodeBoolean(char* buffer, bool value) { char* pBuffer = buffer; *pBuffer++ = 0x01; *pBuffer = value ? 0x01 : 0x00; pBuffer++; return RESULT(pBuffer, buffer, 2); } int RTMP::AMFEncodeString(char* buffer, char* str, int length) { if (length > 0xffff) { return AMFEncodeLongString(buffer, str, length); } char* pBuffer = buffer; *pBuffer++ = 0x02; pBuffer += AMFEncodeNumber16(pBuffer, (unsigned short)length); memcpy(pBuffer, str, length); pBuffer += strlen(str); return RESULT(pBuffer, buffer, length + 3); } int RTMP::AMFEncodeStringKey(char * buffer, char * str, int length) { char* pBuffer = buffer; pBuffer += AMFEncodeNumber16(pBuffer, (unsigned short)length); memcpy(pBuffer, str, length); pBuffer += strlen(str); return RESULT(pBuffer, buffer, length + 2); } int RTMP::AMFEncodeObject(char* buffer, char* objName, int length) { char* pBuffer = buffer; *pBuffer++ = 0x03; pBuffer += AMFEncodeNumber16(pBuffer, (unsigned short)length); memcpy(pBuffer, objName, length); pBuffer += strlen(objName); return RESULT(pBuffer, buffer, length + 3); } int RTMP::AMFEncodeMovieclip() { return 0; } int RTMP::AMFEncodeNull() { return 0; } int RTMP::AMFEncodeUndefined() { return 0; } /** * Initiates use of the Winsock DLL by a process. * @param null * @returns null */ RTMP::RTMP() { WSAData wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); byte_read = 0; chunk_size = CHUNK_SIZE_DEFAULT; if (!vect_message_arrived.empty()) { vect_message_arrived.clear(); } if (!vect_command_sent.empty()) { vect_command_sent.clear(); } memset(chunk_message.data, 0, sizeof(chunk_message)); } RTMP::~RTMP() { } bool RTMP::ConnectToServer(const char* hostname, const unsigned short port) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE if (!SocketConnect(hostname, port)) { return false; } InitBuffer(service.port, service.connect_socket); if (!HandShake()) { return false; } service.app = "BigBuckBunny_115k.mov"; service.transaction_id = 1.0; service.flash_vers = "WIN 10,0,32,18"; service.swfURL = NULL_STRING; service.tcURL = "rtmp://184.72.239.149/vod/BigBuckBunny_115k.mov"; service.capabilities = "9947.57"; service.audio_codecs = 3191.0; service.video_codecs = 252.0; service.video_function = 1.0; service.pageUrl = NULL_STRING; service.object_encoding = 3.0; chunk_message.header.chunk_type = 0x00; chunk_message.header.chunk_stream_id = 0x03; chunk_message.header.message_length = 0; chunk_message.header.message_stream_id = 0; chunk_message.header.message_type_id = 0; chunk_message.header.timestamp = 0; chunk_message.header.extended_timestamp = 0; ConnectPacket(); RTMPMessage packet; ReceiveRTMPPacket(packet); return true; } int RTMP::ReadRTMPPacketHeader(RTMPMessage & packet) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE BYTE *pBuffer = nullptr; INT32 nbyte_read = 0; if (iBuffer->Read(&pBuffer, 1) != 1) { //LOG("%s: Read data failed!"); return -1; } nbyte_read++; packet.header.chunk_type = (pBuffer[0] >> 6); //2bits high packet.header.chunk_stream_id = (pBuffer[0] & 0x3F); //6bits low if (packet.header.chunk_stream_id == 0) { if (iBuffer->Read(&pBuffer, 1) != 1) { //LOG("%s: Read data failed!"); return -1; } packet.header.chunk_stream_id += pBuffer[0]; nbyte_read++; } else if (packet.header.chunk_stream_id == 1) { if (iBuffer->Read(&pBuffer, 2) != 2) { //LOG("%s: Read data failed!"); return -1; } unsigned short cs_id = 0; RTMP::AMFDecodeNumber16((char*)pBuffer, 2, cs_id); packet.header.chunk_stream_id = cs_id + 64; nbyte_read += 2; } if (packet.header.chunk_type < 3) { if (iBuffer->Read(&pBuffer, 3) != 3) { //false return -1; } RTMP::AMFDecodeNumber24((char*)pBuffer, 3, packet.header.timestamp); nbyte_read += 3; } if (packet.header.chunk_type < 2) { if (iBuffer->Read(&pBuffer, 4) != 4) { //flase return -1; } RTMP::AMFDecodeNumber24((char*)pBuffer, 3, packet.header.message_length); packet.header.message_type_id = pBuffer[3]; nbyte_read += 4; } if (packet.header.chunk_type < 1) { if (iBuffer->Read(&pBuffer, 4) != 4) { //flase return -1; } packet.header.message_stream_id = *((UINT32*)pBuffer); nbyte_read += 4; } if (packet.header.timestamp == 0xFFFFFF) { if (iBuffer->Read(&pBuffer, 4) != 4) { //false return -1; } RTMP::AMFDecodeNumber32((char*)pBuffer, 4, packet.header.extended_timestamp); nbyte_read += 4; } return nbyte_read; } /* //Define message type ID #define RTMP_SET_CHUNK_SIZE 0x01 #define RTMP_ABORT_MESSAGE 0x02 #define RTMP_ACKNOWLEDGEMENT 0x03 #define RTMP_USER_CONTROL_MESSAGE 0x04 #define RTMP_WINDOW_ACK_SIZE 0x05 #define RTMP_SET_PEER_BAND_WIDTH 0x06 #define RTMP_AUDIO_MESSAGE 0x08 #define RTMP_VIDEO_MESSAGE 0x09 #define RTMP_SHARE_OBJECT_AMF0 0x13 #define RTMP_SHARE_OBJECT_AMF3 0x10 #define RTMP_DATA_MESSAGE_AMF0 0x12 #define RTMP_DATA_MESSAGE_AMF3 0x0F #define RTMP_AGGREGATE_MESSAGE 0x16 #define RMTP_COMMAND_MESSAGE_AMF0 0x14 #define RTMP_COMMAND_MESSAGE_AMF3 0x11 */ int RTMP::HandlePacket(RTMPMessage & packet) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE switch (packet.header.message_type_id) { case RTMP_SET_CHUNK_SIZE: //0x01 { unsigned int new_chunk_size = 0; RTMP::AMFDecodeNumber32(packet.data, 4, new_chunk_size); SetChunkSize(new_chunk_size); break; } case RTMP_ABORT_MESSAGE: //0x02 { unsigned int chunk_stream_id_abort = *(unsigned int*)(packet.data); //Notification abort chunk stream id break; } case RTMP_ACKNOWLEDGEMENT: //0x03 { //Notification... break; } case RTMP_USER_CONTROL_MESSAGE: //0x04 { UserControlMessage(packet); break; } case RTMP_WINDOW_ACK_SIZE: //0x05 { break; } case RTMP_SET_PEER_BAND_WIDTH: //0x06 { break; } case RTMP_AUDIO_MESSAGE: //0x08 { break; } case RTMP_VIDEO_MESSAGE: //0x09 { break; } case RTMP_SHARE_OBJECT_AMF0: //0x13 { break; } case RTMP_SHARE_OBJECT_AMF3: //0x10 { break; } case RTMP_DATA_MESSAGE_AMF0: //0x12 { break; } case RTMP_DATA_MESSAGE_AMF3: //0x0F { break; } case RTMP_AGGREGATE_MESSAGE: //0x16 { break; } case RMTP_COMMAND_MESSAGE_AMF0: //0x14 { break; } case RTMP_COMMAND_MESSAGE_AMF3: //0x11 { break; } default: { } } return 0; } //Note: Message Stream ID store little endian int RTMP::ReceiveRTMPPacket(RTMPMessage & packet) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE BYTE *pBuffer = nullptr; INT32 nbyte_read = 0; nbyte_read = ReadRTMPPacketHeader(packet); if (iBuffer->Read(&pBuffer, packet.header.message_length) != packet.header.message_length) { //false return -1; } memcpy(packet.data, pBuffer, packet.header.message_length); nbyte_read += packet.header.message_length; return nbyte_read; } bool RTMP::HandShake() { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE //assert(service.connect_socket > 0); #define MAX_PACKET_LENGTH 1536 BYTE client_signal[MAX_PACKET_LENGTH + 1], *pclient_send = nullptr; BYTE server_signal[MAX_PACKET_LENGTH + 1], *pserver_send = nullptr; memset(client_signal, 0, MAX_PACKET_LENGTH + 1); memset(server_signal, 0, MAX_PACKET_LENGTH + 1); client_signal[0] = 0x03; unsigned int epoch_time = GetTime(); memcpy(client_signal + 1, &epoch_time, sizeof(epoch_time)); SWAP32((client_signal + 1)); for (int i = 9; i < MAX_PACKET_LENGTH + 1; i++) { client_signal[i] = i % 256; } //Send C0 + C1 //if (SendRTMPMessage(client_signal, MAX_PACKET_LENGTH + 1) != MAX_PACKET_LENGTH + 1) //{ // return false; //} if (oBuffer->Write(client_signal, MAX_PACKET_LENGTH + 1) != MAX_PACKET_LENGTH + 1) { RTMP_LOG(PREFIX"Send C0+C1 failed\n", FUNCTION); return false; } //Read S0 //if (ReceiveRTMPMessage(server_signal, 1) != 1 // && server_signal[0] != 0x03) //{ // return false; //} if (iBuffer->Read( &pserver_send, 1) != 1 || pserver_send[0] != 0x03) //may be null? { RTMP_LOG(PREFIX"C0 and S0 not match\n", FUNCTION); return false; } ////Read S1 //if (ReceiveRTMPMessage(server_signal, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) //{ // return false; //} if (iBuffer->Read(&pserver_send, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) { RTMP_LOG(PREFIX"Read S1 failed\n", FUNCTION); return false; } ////Send C2(S1) //if (SendRTMPMessage(server_signal, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) //{ // return false; //} if (oBuffer->Write(server_signal, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) { RTMP_LOG(PREFIX"Send C2 failed\n", FUNCTION); return false; } ////Read S2 //if (ReceiveRTMPMessage(server_signal + 1, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) //{ // return false; //} if (iBuffer->Read(&pserver_send, MAX_PACKET_LENGTH) != MAX_PACKET_LENGTH) { RTMP_LOG(PREFIX"Read S2 failed\n", FUNCTION); return false; } if (memcmp(client_signal + 1, pserver_send, MAX_PACKET_LENGTH)) { RTMP_LOG(PREFIX"C1 and S2 not match\n", FUNCTION); return false; } return true; } void RTMP::InitBuffer(UINT32 port, SOCKET socket) { SAFE_DELETE(iBuffer); SAFE_DELETE(oBuffer); iBuffer = new IBuffer(port, socket); oBuffer = new OBuffer(port, socket); } void RTMP::SetChunkSize(int new_chunk_size) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE chunk_size = new_chunk_size; } void RTMP::AbortMessage() { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE } //rtmp_specification_1.0.pdf section 6.2, 7.1.7 void RTMP::UserControlMessage(RTMPMessage &packet) { #ifdef FLOW_CODE RTMP_LOG(PREFIX"\n", FUNCTION); #endif // FLOW_CODE if (packet.header.message_length < 6) { RTMP_LOG(PREFIX"Payload data not enough\n"); return; } unsigned short event_type = 0; RTMP::AMFDecodeNumber16(packet.data, 2, event_type); switch (event_type) { case 0x00: //Stream begin case 0x01: //Stream EOF case 0x02: //Stream dry case 0x03: //Set Buffer Length case 0x04: //Stream Is Recorded case 0x06: //Ping request case 0x07: //Ping response default: { } } } int RTMP::AMFEncodeLongString(char* buffer, char* str, int length) { char* pBuffer = buffer; *pBuffer++ = 0x0c; pBuffer += AMFEncodeNumber32(pBuffer, length); memcpy(pBuffer, str, length); return RESULT(pBuffer, buffer, length + 5); } int RTMP::AMFEncodeUnsupported() { return 0; } int RTMP::AMFEncodeRecordset() { return 0; } int RTMP::AMFEncodeXMLDocument() { return 0; } int RTMP::AMFEncodeTypedObject() { return 0; } int RTMP::AMFDecodeNumber64(char* buffer, int length, double & value) { if (length < 8) { return -1; } char str[8] = { 0 }; memcpy(str, buffer, 8); SWAP64(str); value = *(double *)(&str); return 8; } int RTMP::AMFDecodeNumber32(char* buffer, int length, unsigned int & value) { if (length < 4) { return -1; } char str[4] = { 0 }; memcpy(str, buffer, 4); SWAP32(str); value = *(int *)(&str); return 4; } int RTMP::AMFDecodeNumber24(char* buffer, int length, unsigned int & value) { if (length < 3) { return -1; } char str[3] = { 0 }; memcpy(str, buffer, 3); SWAP(str[0], str[2]); value = *(unsigned short *)(&str); return 3; } int RTMP::AMFDecodeNumber16(char* buffer, int length, unsigned short & value) { if (length < 2) { return -1; } char str[2] = { 0 }; memcpy(str, buffer, 2); SWAP16(str); value = *(unsigned short *)(&str); return 2; } int RTMP::AMFDecodeBoolean(char* buffer, int length, bool & value) { if (length < 1) { return -1; } value = buffer[0] == 0 ? false : true; return 1; } int RTMP::AMFDecodeString(char* buffer, STRING & str, int length) { STRING ss(buffer, length); str = ss; return length; } int RTMP::AMFDecodeObject(char* buffer, STRING & objName, int length) { return 0; } int RTMP::AMFEncodeReference() { return 0; } int RTMP::AMFEncodeECMAArray() { return 0; } int RTMP::AMFEncodeObjectEnd(char* buffer) { char* pBuffer = buffer; *pBuffer++ = 0x00; *pBuffer++ = 0x00; *pBuffer++ = 0x09; return RESULT(pBuffer, buffer, 3); } int RTMP::AMFEncodeStrictArray() { return 0; } int RTMP::AMFEncodeDate() { return 0; } /* 1. C->S: csid = 3, sid = 0, connect 2. S->C: csid = 2, sid = 0, serverBW csid = 2, sid = 0, clientBW csid = 2, sid = 0, ping (stream begin, stream ID = 0) csid = 2, sid = 0, chunkSize csid = 3, sid = 0, _result 3. C->S: csid = 2, sid = 0, serverBW 4. C->S: csid = 3, sid = 0, createStream (client stream ID = 2) 5. S->C: csid = 3, sid = 0, _result (client stream ID = 2, server stream ID = 1) 6. C->S: csid = 2, sid = 0, ping (set buffer size, stream ID = 1, size = 0) csid = 8, sid = 1, publish csid = 8, sid = 1, notify 7. S->C: csid = 2, sid = 0, ping (stream begin, stream ID = 1) 8. C->S: csid = 4, sid = 1, audio data 9. S->C: csid = 3, sid = 1, onStatus 10. C->S: csid = 6, sid = 1, video data */ /* RTMP Chunk Stream uses message type IDs 1, 2, 3, 5, and 6 for protocol control messages. These messages contain information needed by the RTMP Chunk Stream protocol. These protocol control messages MUST have message stream ID 0 (known as the control stream) and be sent in chunk stream ID 2. Protocol control messages take effect as soon as they are received; their timestamps are ignored. */ /* NetConnection is the default communication channel, which has a stream ID 0. Protocol and a few command messages, including createStream, use the default communication channel. */ int RTMP::ConnectPacket() { #ifdef FLOW_CODE RTMP_LOG(PREFIX"n", FUNCTION); #endif // FLOW_CODE char buffer[MAXIMUM_MESSAGE_SIZE] = { 0 }; int nbyte_buffer = 0, nbyte_header = 0; buffer[nbyte_buffer] = 0x00; buffer[nbyte_buffer] |= 0x03; //fmt nbyte_buffer++; memset(buffer + nbyte_buffer, 0, 4); //timestamp nbyte_buffer += 4; memset(buffer + nbyte_buffer, 0, 3); //reuse for message length nbyte_buffer += 3; buffer[nbyte_buffer] = 0x14; //message type ID 0x14 AMF0 nbyte_buffer++; memset(buffer + nbyte_buffer, 0, 4); //message stream ID 0x00 nbyte_buffer += 4; //Continue payload data //Command name + transaction nbyte_header = nbyte_buffer; nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, "connect", 7); nbyte_buffer += RTMP::AMFEncodeNumber64(buffer + nbyte_buffer, 1.0); buffer[nbyte_buffer] = 0x03; nbyte_buffer++; //Object nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "app", 3); nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.app, strlen(service.app)); nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "flashver", 8); nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.flash_vers, strlen(service.flash_vers)); //nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "swfUrl", 6); //nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.swfURL, strlen(service.swfURL)); nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "tcUrl", 5); nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.tcURL, strlen(service.tcURL)); //nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "swfUrl", 6); //nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.swfURL, strlen(service.swfURL)); /*nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "capabilities", 12); nbyte_buffer += RTMP::AMFEncodeString(buffer + nbyte_buffer, service.capabilities, strlen(service.capabilities));*/ nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "audioCodes", 10); nbyte_buffer += RTMP::AMFEncodeNumber64(buffer + nbyte_buffer, service.audio_codecs); nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "videoCodes", 10); nbyte_buffer += RTMP::AMFEncodeNumber64(buffer + nbyte_buffer, service.video_codecs); nbyte_buffer += RTMP::AMFEncodeStringKey(buffer + nbyte_buffer, "objectEncoding", 14); nbyte_buffer += RTMP::AMFEncodeNumber64(buffer + nbyte_buffer, service.object_encoding); //End of Object buffer[nbyte_buffer++] = 0x00; buffer[nbyte_buffer++] = 0x00; buffer[nbyte_buffer++] = 0x09; RTMP::AMFEncodeNumber24(buffer + 5, nbyte_buffer - nbyte_header); if (oBuffer->Write((BYTE*)buffer, nbyte_buffer) != nbyte_buffer) { RTMP_LOG(PREFIX"Send data failed\n", FUNCTION); return -1; } return nbyte_buffer; } RTMP.h #pragma once /********************************************************************** * File: rtmp.h * * Last edit: 27-Nov-2017 * Last Editor: LongVD2 * * Notes: This file define rtmp property, funct * * Copyright(C) 2008-2015 by Fuji Xerox Co., Ltd. All rights reserved. * Other Copyright information **********************************************************************/ #ifndef __RTMP_H__ #define __RTMP_H__ #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS #endif // !_WINSOCK_DEPRECATED_NO_WARNINGS //#ifndef __WINSOCKAPI__ //#define __WINSOCKAPI__ // //#include <WinSock2.h> //#include <Windows.h> // //#endif // !__WINSOCKAPI__ #include "Buffer.h" #include <stdlib.h> #include <stdint.h> #include <assert.h> #include <vector> #include <iostream> #include <bitset> #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") #pragma comment (lib, "Winmm.lib") #define VECTOR std::vector #define STRING std::string #define SOCKET_READ_TIMEOUT_SEC 30 #define MAXIMUM_MESSAGE_SIZE int(1<<14) //exactly 1<<24 (3bytes packet length) #define CHUNK_SIZE_DEFAULT 128 #define NULL_STRING "null" #define SWAP(x,y) (x)==(y)?(x):((x)^=(y),(y)^=(x),(x)^=(y)) #define SWAP64(ptr)\ ((SWAP(ptr[0],ptr[7])),\ (SWAP(ptr[1],ptr[6])),\ (SWAP(ptr[2],ptr[5])),\ (SWAP(ptr[3],ptr[4]))) #define SWAP32(ptr)\ ((SWAP(ptr[0],ptr[3])),\ (SWAP(ptr[1],ptr[2]))) #define SWAP16(ptr)\ ((SWAP(ptr[0],ptr[1]))) #define RESULT(pBuffer, buffer, size) (((pBuffer) - (buffer)) == (size) ? (size) : -1) //Define message type ID #define RTMP_SET_CHUNK_SIZE 0x01 #define RTMP_ABORT_MESSAGE 0x02 #define RTMP_ACKNOWLEDGEMENT 0x03 #define RTMP_USER_CONTROL_MESSAGE 0x04 #define RTMP_WINDOW_ACK_SIZE 0x05 #define RTMP_SET_PEER_BAND_WIDTH 0x06 #define RTMP_AUDIO_MESSAGE 0x08 #define RTMP_VIDEO_MESSAGE 0x09 #define RTMP_SHARE_OBJECT_AMF0 0x13 #define RTMP_SHARE_OBJECT_AMF3 0x10 #define RTMP_DATA_MESSAGE_AMF0 0x12 #define RTMP_DATA_MESSAGE_AMF3 0x0F #define RTMP_AGGREGATE_MESSAGE 0x16 #define RMTP_COMMAND_MESSAGE_AMF0 0x14 #define RTMP_COMMAND_MESSAGE_AMF3 0x11 typedef struct Service //contains params Server host and Client { char* host; char* app; char* protocol; char* flash_vers; char* swfURL; char* tcURL; char* capabilities; char* pageUrl; double object_encoding; double transaction_id; double audio_codecs; double video_codecs; double video_function; UINT32 port; struct sockaddr_in sockAddr; SOCKET connect_socket; Service() { transaction_id = 0.0; port = -1; memset(&sockAddr, 0, sizeof(sockAddr)); connect_socket = 0; } }Service; typedef struct RTMPHeader //Chunk Header max 18bytes { BYTE chunk_type; //fmt BYTE message_type_id; //Type ID UINT32 chunk_stream_id; //CS-ID UINT32 timestamp; UINT32 message_length; UINT32 message_stream_id; UINT32 extended_timestamp; RTMPHeader() : chunk_type(0) , message_type_id(0) , timestamp(0) , message_length(0) , message_stream_id(0) , extended_timestamp(0){} }RTMPHeader; typedef struct RTMPMessage //Communication message { RTMPHeader header; char data[MAXIMUM_MESSAGE_SIZE + 1]; //Nomarly 128 bytes, can be changed by SetChunkSize RTMPMessage() { memset(data, 0, sizeof(data)); } }RTMPMessage; class RTMP { private: IBuffer* iBuffer; //start pointer to data OBuffer* oBuffer; //end pointer to data UINT32 byte_read; //number bytes dont read UINT32 chunk_size; //ChunkSize which accepted between Client and Server, default 128 bytes Service service; RTMPMessage chunk_message; //Current message arrived VECTOR<RTMPHeader> vect_message_arrived; //Contains all message header arrived, it reuse for ChunkType 0,1,2,3 VECTOR<STRING> vect_command_sent; //Save command Sent from Client and waiting Server responsed public: RTMP(); ~RTMP(); /** * \brief * Config param to connect the Server * @param r: Be filled data like IP, hostname, port number.. * @param hostName: * @param port: * @returns: TRUE if successful, otherwise return FALSE */ bool ConnectToServer(const char* hostname, const unsigned short port); int ReceiveRTMPPacket(RTMPMessage &packet); protected: /** * \brief * Handle "Handshake" which is first step connection Server * @returns: TRUE if successful, otherwise return FALSE */ bool HandShake(); void InitBuffer(UINT32 port, SOCKET socket); /* * Protocol Control Message * These messages contain information needed by the RTMP Chunk Stream protocol * Message Stream ID 0x00 (know as the Control Stream) * Chunk Stream ID 0x02 * Ignore Timestamp */ void SetChunkSize(int new_chunk_size); //Message Type ID 0x01 void AbortMessage(); //Message Type ID 0x02 void Acknowledgement(); //Message Type ID 0x03 void UserControlMessage(RTMPMessage &packet); //Message Type ID 0x04 void WindowAckSize(); //Message Type ID 0x05 void SetPeerBandwidth(); //Message Type ID 0x06 /* * RTMP Command Message * These messages are exchanged between the Server and the Client (audio, media, command ... message). * Command messages carry the AMF encoded commands between the client and the server. * Message Stream ID 0x00 (know as the Control Stream) * Chunk Stream ID 0x03 (?) */ void AudioMessage(); //Message Type ID 0x08 void VideoMessage(); //Message Type ID 0x09 void ShareObject(); //Message Type ID 0x13 || 0x10 (AMF0 || AMF3) void DataMessage(); //Message Type ID 0x12 || 0x0F void AggregateMessage(); //Message Type ID 0x16 void CommandMessage(); //Message Type ID 0x14 || 0x11 /* * Protocol Funct * Make connections and exchange data with the Server. */ bool SocketConnect(const char* hostname, const unsigned short port); bool ConfigSocket(const char* hostname, const unsigned short port); int Send(char* buffer, int len); int Receive(char* buffer, int len); //int SendRTMPMessage(char* buffer, int len); //int ReceiveRTMPMessage(char* buffer, int len); int ConnectPacket(); int ReadRTMPPacketHeader(RTMPMessage &packet); int HandlePacket(RTMPMessage &packet); public: /* * AMF0 Decoded * Receive data - Decode * Send data - Encode * Ref: http://download.macromedia.com/pub/labs/amf/amf0_spec_121207.pdf */ int AMFEncodeNumber64(char* buffer, double value); //0x00 int AMFEncodeNumber32(char* buffer, int value); int AMFEncodeNumber24(char* buffer, int value); int AMFEncodeNumber16(char* buffer, unsigned short value); int AMFEncodeBoolean(char* buffer, bool value); //0x01 int AMFEncodeString(char* buffer, char* str, int length); //0x02 int AMFEncodeStringKey(char* buffer, char* str, int length); int AMFEncodeObject(char* buffer, char* objName, int length); //0x03 int AMFEncodeMovieclip(); //0x04 int AMFEncodeNull(); //0x05 int AMFEncodeUndefined(); //0x06 int AMFEncodeReference(); //0x07 int AMFEncodeECMAArray(); //0x08 int AMFEncodeObjectEnd(char* buffer); //0x09 int AMFEncodeStrictArray(); //0x0a int AMFEncodeDate(); //0x0b int AMFEncodeLongString(char* buffer, char* str, int length); //0x0c int AMFEncodeUnsupported(); //0x0d int AMFEncodeRecordset(); //0x0e int AMFEncodeXMLDocument(); //0x0f int AMFEncodeTypedObject(); //0x10 static int AMFDecodeNumber64(char* buffer, int length, double &value); //0x00 static int AMFDecodeNumber32(char* buffer, int length, unsigned int &value); static int AMFDecodeNumber24(char* buffer, int length, unsigned int &value); static int AMFDecodeNumber16(char* buffer, int length, unsigned short &value); static int AMFDecodeBoolean(char* buffer, int length, bool &value); //0x01 static int AMFDecodeString(char* buffer, STRING &str, int length); //0x02 static int AMFDecodeObject(char* buffer, STRING &objName, int length); //0x03 static int AMFDecodeMovieclip(); //0x04 static int AMFDecodeNull(); //0x05 static int AMFDecodeUndefined(); //0x06 static int AMFDecodeReference(); //0x07 static int AMFDecodeECMAArray(); //0x08 static int AMFDecodeObjectEnd(char* buffer); //0x09 static int AMFDecodeStrictArray(); //0x0a static int AMFDecodeDate(); //0x0b static int AMFDecodeLongString(char* buffer, char* str, int length); //0x0c static int AMFDecodeUnsupported(); //0x0d static int AMFDecodeRecordset(); //0x0e static int AMFDecodeXMLDocument(); //0x0f static int AMFDecodeTypedObject(); //0x10 }; #endif // !__RTMP_H__ RTMP_LOG #ifndef __RTMP_LOG_H__ #define __RTMP_LOG_H__ #pragma once #include <stdio.h> #include <stdarg.h> #include <string.h> #define MAX_BUFFER_LOG_SIZE 1024 //#define LOG_ERROR 0 //flag print error log //#define LOG_NORMAL 1 //flag print normal log //#define DEBUG_LOG //define to print debug log //#define _in_ //input param //#define _out_ //output param //#define _in_out_ //in&out param #define RTMP_ERROR(error) (RTMPError(error)) #define RTMP_LOG RTMPLOG void RTMPLOG(const char *format, ...) { char szLogBuffer[MAX_BUFFER_LOG_SIZE + 1]; va_list args; va_start(args, format); vsnprintf(szLogBuffer, MAX_BUFFER_LOG_SIZE, format, args); printf("%s\n", szLogBuffer); va_end(args); return; } /** * print socket error * @param error: socket error code * @returns errmsg: The error message which be depended on the error code */ char* RTMPError(int error) { char szErrmsg[MAX_BUFFER_LOG_SIZE + 1]; strerror_s(szErrmsg, MAX_BUFFER_LOG_SIZE + 1, error); return szErrmsg; } #endif // !__RTMP_LOG_H__

Các lần nộp bài đã được ghi nhân
(Xem dạng tệp tin văn bản)

Problems

Danh sách các bài đã làm đạt yêu cầu:

AMSSEQ HAM12 MPILOT PNUMBER QBSTR
BCDIV IOIBIN NKCABLE POST VCOWFLIX
BLGEN LATGACH NKLINEUP PTRANG VSTEPS
BONUS LEM3 NKPALIN QBHV
C11CAVE LNACS NKREZ QBMAX
C11KM M3TILE NKSEQ QBPAL
DTDOI MINROAD NKTICK QBSEQ

Danh sách các bài làm chưa đạt yêu cầu:

QBHEAP
SETNJA
© Spoj.com. All Rights Reserved. Spoj uses Sphere Engine™ © by Sphere Research Labs.