#ifndef SRCCTL_RTSP_DATA_CHANNEL_H #define SRCCTL_RTSP_DATA_CHANNEL_H #include "Socket/CCServerSocket.h" #include "Socket/CCDatagramSocket.h" #include "CCSDP.h" #define CC_R_RTSP_BUFFER_SIZE 1 namespace CTL{ typedef struct RTSP_Message{ int statusCode = 0; // 状态码 (响应时使用) int port = 0; // 客户端端口号 bool isRequest = true; // 是否为请求消息(true)还是响应消息(false) String client_ip; // 客户端IP String url_data; // 请求URL String method; // RTSP方法 (OPTIONS, DESCRIBE, SETUP, PLAY等) String uri; // 请求URI String uri_path; // 请求URI路径 String version; // RTSP版本 (如"RTSP/1.0") String reasonPhrase; // 原因短语 (响应时使用) std::map headers; // 头部字段 String body; // 消息体 String sdp_content; // SDP内容 } RTSP_Request; class RTSPDataChannel{ ClientSocket* socket_t = nullptr; public: explicit RTSPDataChannel(ClientSocket* socket){ socket_t = socket; } ~RTSPDataChannel(){ if (socket_t) { socket_t->close(); socket_t = nullptr; } } static void MessagePrint(const String& message,...){ System::Println(message); } int receive(char *buffer, const size_t size) const { if (socket_t && socket_t->isConnect()) { const auto input = socket_t->getInputStream(); if (input->available()) { return input->read(buffer, size); } return -2; } return -1; } int write(const char *buffer, const size_t size) const { if (socket_t && socket_t->isConnect()) { const auto output = socket_t->getOutputStream(); return output->write(buffer,size); } return 0; } String readHeader() const{ if (this->socket_t) { String data; data.reserve(4096); // 预分配内存 int ET = 1; while (true){ char buffer[CC_R_RTSP_BUFFER_SIZE] = {0}; if(const auto length = receive(buffer,CC_R_RTSP_BUFFER_SIZE); length > 0){ data.append(buffer, length); // 块追加代替逐个字符处理 if (const auto pos = data.find("\r\n\r\n"); pos != CTL::String::npos) { data.resize(pos + 4); // 截断到header结束位置 break; } } else if (length == -2) { if (ET >= 1000 * 1000) { this->MessagePrint("RTSPDataChannel readHeader -> Timeout"); break; } ET++; Thread::Sleep(1); } else{ return "close"; } } return data; } return "Error_10030"; } String readData(const uint64_t length) const{ if (this->socket_t) { String data; data.reserve(length); // 预分配内存 int ET = 1; while (true){ char buffer[CC_R_RTSP_BUFFER_SIZE] = {0}; if(const auto len = receive(buffer,CC_R_RTSP_BUFFER_SIZE); len > 0){ data.append(buffer, len); if (data.length() >= length) { break; } } else if (len == -2) { if (ET >= 1000 * 300) { this->MessagePrint("RTSPDataChannel readData -> Timeout"); break; } ET++; Thread::Sleep(1); } else{ return "close"; } } return data; } return "Error_10030"; } static RTSP_Message ParseRTSP(const String& data){ RTSP_Message msg; if (data.empty()) { return msg; } msg.url_data = data; // 查找空行(\r\n\r\n)来分离头部和消息体 size_t headerEndPos = data.find("\r\n\r\n"); String headersPart; String bodyPart; if (headerEndPos != CTL::String::npos) { headersPart = data.substr(0, headerEndPos); bodyPart = data.substr(headerEndPos + 4); // 跳过"\r\n\r\n" } else { headersPart = data; } // 分割头部行 std::vector lines; String currentLine; for (size_t i = 0; i < headersPart.length(); ++i) { if (headersPart[i] == '\r' && i + 1 < headersPart.length() && headersPart[i + 1] == '\n') { lines.push_back(currentLine); currentLine.clear(); i++; // 跳过'\n' } else { currentLine += headersPart[i]; } } if (!currentLine.empty()) { lines.push_back(currentLine); } if (!lines.empty()) { // 解析第一行 (请求行或状态行) const String& firstLine = lines[0]; // 检查是请求还是响应 if (firstLine.find("RTSP/") == 0) { // 这是响应行: "RTSP/1.0 200 OK" msg.isRequest = false; size_t firstSpace = firstLine.find(' '); if (firstSpace != String::npos) { size_t secondSpace = firstLine.find(' ', firstSpace + 1); if (secondSpace != String::npos) { msg.version = firstLine.substr(0, firstSpace); try { msg.statusCode = std::stoi(firstLine.substr(firstSpace + 1, secondSpace - firstSpace - 1)); } catch (...) { msg.statusCode = 500; // 默认错误状态 } msg.reasonPhrase = firstLine.substr(secondSpace + 1); } } } else { // 这是请求行: "OPTIONS rtsp://... RTSP/1.0" size_t firstSpace = firstLine.find(' '); size_t lastSpace = firstLine.rfind(' '); if (firstSpace != String::npos && lastSpace != String::npos && firstSpace < lastSpace) { msg.method = firstLine.substr(0, firstSpace); msg.uri = firstLine.substr(firstSpace + 1, lastSpace - firstSpace - 1); msg.version = firstLine.substr(lastSpace + 1); // 从URI中解析路径部分 size_t schemeEnd = msg.uri.find("://"); if (schemeEnd != String::npos) { // 跳过协议和主机部分,找到路径 size_t hostStart = schemeEnd + 3; size_t pathStart = msg.uri.find('/', hostStart); if (pathStart != String::npos) { msg.uri_path = msg.uri.substr(pathStart); } else { // 如果没有路径,则设置为根路径 msg.uri_path = "/"; } } else { // 如果没有协议前缀,整个URI可能是路径 if (msg.uri.empty() || msg.uri[0] != '/') { msg.uri_path = "/" + msg.uri; } else { msg.uri_path = msg.uri; } } } } // 解析头部字段 for (size_t i = 1; i < lines.size(); ++i) { const String& line = lines[i]; size_t colonPos = line.find(':'); if (colonPos != String::npos) { String key = line.substr(0, colonPos); String value = line.substr(colonPos + 1); // 移除键和值前后的空白字符 size_t startKey = key.find_first_not_of(" \t"); size_t endKey = key.find_last_not_of(" \t"); if (startKey != String::npos && endKey != String::npos) { key = key.substr(startKey, endKey - startKey + 1); } else if (startKey == String::npos) { continue; // 跳过无效行 } size_t startPos = value.find_first_not_of(" \t"); size_t endPos = value.find_last_not_of(" \t"); if (startPos != String::npos && endPos != String::npos) { value = value.substr(startPos, endPos - startPos + 1); } else if (startPos == String::npos) { value.clear(); } // 将头部字段转换为小写作为键 String lowerKey = key; std::transform(lowerKey.begin(), lowerKey.end(), lowerKey.begin(), ::tolower); msg.headers[lowerKey] = value; } } } // 设置消息体 msg.body = bodyPart; return msg; } }; class RTSP_Response{ RTSPDataChannel* socket_t = nullptr; std::map headers; SDPBuilder sdp_builder; public: //----------------------------------------------------------------------------------------- int statusCode = 200; String reasonPhrase = "OK"; bool auto_send = true; //----------------------------------------------------------------------------------------- void setSocket(RTSPDataChannel* socket){ this->socket_t = socket; } RTSPDataChannel* getSocket() const{ return socket_t; } String getHeader(const String& key) const{ auto it = headers.find(key); if (it != headers.end()) { return it->second; } return ""; } void setHeader(const String& key, const String& value){ headers[key] = value; } String getBuild() const{ String response = String::format("RTSP/1.0 {} {}\r\n", statusCode, reasonPhrase.c_str()); for (const auto& header : headers) { response.append(String::format("{}: {}\r\n",header.first.c_str(),header.second.c_str())); } response.append("\r\n"); return response; } bool send(){ if(socket_t != nullptr){ int ret = socket_t->write(getBuild().c_str(), getBuild().length()); if (ret > 0) { auto_send = false; return true; } } return false; } //----------------------------------------------------------------------------------------- }; } #endif