From 6a0ddc61f2981645babeaf3d657ded6b0050ff65 Mon Sep 17 00:00:00 2001 From: oskwon Date: Mon, 23 Jun 2014 13:45:25 +0900 Subject: Add error/athorization response. Fix mis-typo on help. --- src/Demuxer.cpp | 47 ++++++++++++++++++++----------- src/Demuxer.h | 4 +-- src/Http.cpp | 14 ++++++++++ src/Http.h | 8 ++++-- src/main.cpp | 85 ++++++++++++++++++++++++++++++++++----------------------- 5 files changed, 104 insertions(+), 54 deletions(-) diff --git a/src/Demuxer.cpp b/src/Demuxer.cpp index 04cd35b..fbe5b49 100644 --- a/src/Demuxer.cpp +++ b/src/Demuxer.cpp @@ -22,7 +22,7 @@ using namespace std; //------------------------------------------------------------------------------- -std::string Demuxer::webif_reauest(std::string service, std::string auth) throw(trap) +std::string Demuxer::webif_reauest(std::string request) throw(http_trap) { if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) throw(trap("webif create socket fail.")); @@ -32,15 +32,10 @@ std::string Demuxer::webif_reauest(std::string service, std::string auth) throw( sock_addr.sin_port = htons(80); sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sock, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr_in))) - throw(trap("webif connect fail.")); - - std::string request = string("GET /web/stream?StreamService=") + service + " HTTP/1.0\r\n"; - if (auth != "") - request += "Authorization: " + auth + "\r\n"; - request += "\r\n"; + throw(http_trap("webif connect fail.", 502, "Bad Gateway, webif connect fail")); if (write(sock, request.c_str(), request.length()) != request.length()) - throw(trap("webif send(request) fail.")); + throw(http_trap("webif request fail.", 502, "Bad Gateway, webif request error")); DEBUG("webif request :\n", request.c_str()); std::string response = ""; @@ -56,7 +51,7 @@ std::string Demuxer::webif_reauest(std::string service, std::string auth) throw( break; else if (poll_state < 0) { ERROR("webif receive poll error : %s (%d)", strerror(errno), errno); - throw(trap("webif receive response error.")); + throw(http_trap("webif response fail.", 502, "Bad Gateway, webif response error")); } if (pollevt[0].revents & POLLIN) { if (read(sock, buffer, 1024) <= 0) { @@ -183,27 +178,47 @@ bool Demuxer::parse_webif_response(std::string& response, std::vectorparams["WWW-Authenticate"]; - std::string service = header->path.substr(1); - std::string webif_response = webif_reauest(service, auth); + std::string webif_request = string("GET /web/stream?StreamService=") + header->path.substr(1) + " HTTP/1.0\r\n"; + if (header->params.find("Authorization") != header->params.end()) { + if (header->params["Authorization"].length() < 5) { + throw(http_trap("no authorization data.", 401, "Unauthorized")); + } + webif_request += "Authorization: " + header->params["Authorization"] + "\r\n"; + if (header->params["Cookie"].length() > 0) { + webif_request += "Cookie: " + header->params["Cookie"] + "\r\n"; + } + } + webif_request += "\r\n"; + + std::string webif_response = webif_reauest(webif_request); DEBUG("webif response :\n%s", webif_response.c_str()); + if (webif_response.find("WWW-Authenticate") != std::string::npos) { + header->authorization = webif_response; + throw(http_trap("webif whthentication fail.", 401, "Unauthorized")); + } + std::vector new_pids; if (!parse_webif_response(webif_response, new_pids)) - throw(trap("webif response parsing fail.")); + throw(http_trap("webif response parsing fail.", 503, "Service Unavailable")); std::string demuxpath = "/dev/dvb/adapter0/demux" + Util::ultostr(demux_id); if ((fd = open(demuxpath.c_str(), O_RDWR | O_NONBLOCK)) < 0) { - throw(trap(std::string("demux open fail : ") + demuxpath)); + throw(http_trap(std::string("demux open fail : ") + demuxpath, 503, "Service Unavailable")); } INFO("demux open success : %s", demuxpath.c_str()); - set_filter(new_pids); + try { + set_filter(new_pids); + } + catch (const trap &e) { + throw(http_trap(e.what(), 503, "Service Unavailable")); + } } //------------------------------------------------------------------------------- diff --git a/src/Demuxer.h b/src/Demuxer.h index 033c54d..5c90dda 100644 --- a/src/Demuxer.h +++ b/src/Demuxer.h @@ -34,13 +34,13 @@ private: std::vector pids; protected: - std::string webif_reauest(std::string service, std::string auth) throw(trap); + std::string webif_reauest(std::string request) throw(http_trap); bool already_exist(std::vector &pidlist, int pid); void set_filter(std::vector &new_pids) throw(trap); bool parse_webif_response(std::string& response, std::vector &new_pids); public: - Demuxer(HttpHeader *header) throw(trap); + Demuxer(HttpHeader *header) throw(http_trap); virtual ~Demuxer() throw(); int get_fd() const throw(); }; diff --git a/src/Http.cpp b/src/Http.cpp index 7b736c6..7746cc9 100644 --- a/src/Http.cpp +++ b/src/Http.cpp @@ -172,3 +172,17 @@ std::string HttpHeader::read_request() return request; } //---------------------------------------------------------------------- + +std::string HttpUtil::http_error(int errcode, std::string errmsg) +{ + std::ostringstream oss; + + oss << "HTTP/1.1 " << Util::ultostr(errcode) << " " << errmsg << "\r\n"; + oss << "Content-Type: text/html\r\n"; + oss << "Connection: close\r\n"; + oss << "Accept-Ranges: bytes\r\n"; + oss << "\r\n"; + + return oss.str(); +} +//---------------------------------------------------------------------- diff --git a/src/Http.h b/src/Http.h index 31246bc..69f7a09 100644 --- a/src/Http.h +++ b/src/Http.h @@ -33,8 +33,7 @@ public: std::string page; std::map page_params; -private: - + std::string authorization; public: HttpHeader() : type(UNKNOWN) {} virtual ~HttpHeader() {} @@ -46,4 +45,9 @@ public: }; //---------------------------------------------------------------------- +namespace HttpUtil { + std::string http_error(int errcode, std::string errmsg); +}; +//---------------------------------------------------------------------- + #endif /* HTTP_H_ */ diff --git a/src/main.cpp b/src/main.cpp index 9121be6..3749d06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,9 +31,7 @@ using namespace std; #define BUFFFER_SIZE (188 * 256) void show_help(); - void signal_handler(int sig_no); -void do_exit(const char *message); void *source_thread_main(void *params); void *streaming_thread_main(void *params); @@ -63,7 +61,20 @@ int main(int argc, char **argv) std::string req = HttpHeader::read_request(); DEBUG("request head :\n%s", req.c_str()); - if (header.parse_request(req)) { + + try { + if (req.find("\r\n\r\n") == std::string::npos) { + throw(http_trap("no found request done code.", 400, "Bad Request")); + } + + if (header.parse_request(req) == false) { + throw(http_trap("request parse error.", 400, "Bad Request")); + } + + if (header.method != "GET") { + throw(http_trap("not support request type.", 400, "Bad Request, not support request")); + } + Encoder encoder; Source *source = 0; ThreadParams thread_params = { 0, &encoder, &header }; @@ -81,8 +92,7 @@ int main(int argc, char **argv) source = ts; } catch (const trap &e) { - ERROR("fail to create source : %s", e.what()); - exit(-1); + throw(http_trap(e.what(), 404, "Not Found")); } break; case HttpHeader::TRANSCODING_LIVE: @@ -93,9 +103,8 @@ int main(int argc, char **argv) audio_pid = dmx->audio_pid; source = dmx; } - catch (const trap &e) { - ERROR("fail to create source : %s", e.what()); - exit(-1); + catch (const http_trap &e) { + throw(e); } break; case HttpHeader::M3U: @@ -109,20 +118,18 @@ int main(int argc, char **argv) } exit(0); default: - ERROR("not support source type (type : %d)", header.type); - exit(-1); + throw(http_trap(std::string("not support source type : ") + Util::ultostr(header.type), 400, "Bad Request")); } thread_params.source = source; if (!encoder.retry_open(2, 3)) { - exit(-1); + throw(http_trap("encoder open fail.", 503, "Service Unavailable")); } if (encoder.state == Encoder::ENCODER_STAT_OPENED) { std::string response = header.build_response((Mpeg*) source); if (response == "") { - do_exit(0); - return 0; + throw(http_trap("response build fail.", 503, "Service Unavailable")); } streaming_write(response.c_str(), response.length(), true); @@ -132,44 +139,63 @@ int main(int argc, char **argv) } if (!encoder.ioctl(Encoder::IOCTL_SET_VPID, video_pid)) { - do_exit("fail to set video pid."); - exit(-1); + throw(http_trap("video pid setting fail.", 503, "Service Unavailable")); } if (!encoder.ioctl(Encoder::IOCTL_SET_APID, audio_pid)) { - do_exit("fail to set audio pid."); - exit(-1); + throw(http_trap("audio pid setting fail.", 503, "Service Unavailable")); } if (!encoder.ioctl(Encoder::IOCTL_SET_PMTPID, pmt_pid)) { - do_exit("fail to set pmtid."); - exit(-1); + throw(http_trap("pmt pid setting fail.", 503, "Service Unavailable")); } } is_terminated = false; source_thread_id = pthread_create(&source_thread_handle, 0, source_thread_main, (void *)&thread_params); if (source_thread_id < 0) { - do_exit("fail to create source thread."); + is_terminated = true; + throw(http_trap("souce thread create fail.", 503, "Service Unavailable")); } else { pthread_detach(source_thread_handle); sleep(1); if (!encoder.ioctl(Encoder::IOCTL_START_TRANSCODING, 0)) { - do_exit("fail to start transcoding."); + is_terminated = true; + throw(http_trap("start transcoding fail.", 503, "Service Unavailable")); } else { stream_thread_id = pthread_create(&stream_thread_handle, 0, streaming_thread_main, (void *)&thread_params); if (stream_thread_id < 0) { - do_exit("fail to create stream thread."); + is_terminated = true; + throw(http_trap("stream thread create fail.", 503, "Service Unavailable")); } } } pthread_join(stream_thread_handle, 0); + is_terminated = true; if (source != 0) { delete source; source = 0; } } + catch (const http_trap &e) { + ERROR("%s", e.message.c_str()); + std::string error = ""; + if (e.http_error == 401 && header.authorization.length() > 0) { + error = header.authorization; + } + else { + error = HttpUtil::http_error(e.http_error, e.http_header); + } + streaming_write(error.c_str(), error.length(), true); + exit(-1); + } + catch (...) { + ERROR("unknown exception..."); + std::string error = HttpUtil::http_error(400, "Bad request"); + streaming_write(error.c_str(), error.length(), true); + exit(-1); + } return 0; } //---------------------------------------------------------------------- @@ -232,7 +258,7 @@ void *streaming_thread_main(void *params) catch (const trap &e) { ERROR("%s %s (%d)", e.what(), strerror(errno), errno); } - do_exit(0); + is_terminated = true; INFO("streaming thread stop."); if (encoder->state == Encoder::ENCODER_STAT_STARTED) { @@ -324,19 +350,10 @@ int streaming_write(const char *buffer, size_t buffer_len, bool enable_log) } //---------------------------------------------------------------------- -void do_exit(const char *message) -{ - is_terminated = true; - if (message) { - ERROR("%s", message); - } -} -//---------------------------------------------------------------------- - void signal_handler(int sig_no) { INFO("signal no : %d", sig_no); - do_exit("signal detected.."); + is_terminated = true; } //---------------------------------------------------------------------- @@ -347,6 +364,6 @@ void show_help() printf(" * To active debug mode, input NUMBER on /tmp/debug_on file. (default : warning)\n"); printf(" NUMBER : error(1), warning(2), info(3), debug(4), log(5)\n"); printf("\n"); - printf(" ex > echo \"4\" > /tmp/debug_on\n"); + printf(" ex > echo \"4\" > /tmp/.debug_on\n"); } //---------------------------------------------------------------------- -- cgit