4 * Created on: 2014. 6. 10.
15 #include <arpa/inet.h>
16 #include <sys/socket.h>
25 #include "UriDecoder.h"
28 //----------------------------------------------------------------------
30 std::string ultostr(int64_t data)
36 //----------------------------------------------------------------------
38 int strtollu(std::string data)
51 //----------------------------------------------------------------------
53 std::string trim(std::string& s, const std::string& drop)
55 std::string r = s.erase(s.find_last_not_of(drop) + 1);
56 return r.erase(0, r.find_first_not_of(drop));
58 //----------------------------------------------------------------------
60 int split(std::string data, const char delimiter, std::vector<string>& tokens)
62 std::stringstream data_stream(data);
63 for(std::string token; std::getline(data_stream, token, delimiter); tokens.push_back(trim(token)));
66 //----------------------------------------------------------------------
68 bool split_key_value(std::string data, std::string delimiter, std::string &key, std::string &value)
70 int idx = data.find(delimiter);
71 if (idx == string::npos) {
72 WARNING("split key & value (data : %s, delimiter : %s)", data.c_str(), delimiter.c_str());
75 key = data.substr(0, idx);
76 value = data.substr(idx+1, data.length()-idx);
79 //----------------------------------------------------------------------
81 std::string read_request()
83 std::string request = "";
85 char buffer[128] = {0};
86 fgets(buffer, 127, stdin);
89 if(request.find("\r\n\r\n") != string::npos)
94 //----------------------------------------------------------------------
96 bool RequestHeader::parse_header(std::string header)
98 std::vector<string> lines;
99 split(header, '\n', lines);
101 DEBUG("header lines count : %d", lines.size());
102 std::vector<string>::iterator iter = lines.begin();
103 std::vector<string> infos;
104 if (split(*iter, ' ', infos) != 3) {
105 ERROR("fail to parse info : %d", infos.size());
109 type = REQ_TYPE_TRANSCODING_LIVE;
114 if (strncmp(path.c_str(), "/file", 5) == 0) {
115 std::vector<std::string> tokens;
116 if (split(path.substr(6), '&', tokens) > 0) {
117 for (int i = 0; i < tokens.size(); ++i) {
118 std::string data = tokens[i];
119 std::string key = "", value = "";
120 if (!split_key_value(data, "=", key, value)) {
121 ERROR("fail to request : %s", data.c_str());
125 extension[key] = UriDecoder().decode(value.c_str());;
128 extension[key] = value;
131 type = REQ_TYPE_TRANSCODING_FILE;
133 // DEBUG(":: HEADER :: %s", extension["file"].c_str());
134 // std::map<std::string, std::string>::iterator iter = extension.begin();
135 // for (; iter != extension.end(); ++iter) {
136 // std::string key = iter->first;
137 // std::string value = iter->second;
138 // DEBUG("[%s] -> [%s]", key.c_str(), value.c_str());
141 DEBUG("info (%d) -> type : [%s], path : [%s], version : [%s]", infos.size(), method.c_str(), path.c_str(), version.c_str());
143 for (++iter; iter != lines.end(); ++iter) {
144 std::string key = "", value = "";
145 if (!split_key_value(*iter, ":", key, value))
152 if (key.length() > 0) {
154 DEBUG("add params : %s -> %s", key.c_str(), value.c_str());
159 //----------------------------------------------------------------------
161 off_t make_response(ThreadParams *params, std::string& response)
167 off_t byte_offset = 0;
168 RequestHeader *header = ((ThreadParams*) params)->request;
169 switch(header->type) {
170 case REQ_TYPE_TRANSCODING_FILE: {
171 MpegTS *source = (MpegTS*)((ThreadParams*) params)->source;
173 std::string range = header->params["Range"];
174 if((range.length() > 7) && (range.substr(0, 6) == "bytes=")) {
175 range = range.substr(6);
176 if(range.find('-') == (range.length() - 1)) {
177 byte_offset = strtollu(range);
181 off_t content_length = source->stream_length - byte_offset;
182 if (byte_offset > 0) {
184 response += HTTP_PARTIAL;
189 response += HTTP_PARAMS;
190 response += "Accept-Ranges: bytes\r\n"
191 "Content-Length: " + ultostr(content_length) + "\r\n";
192 response += string("Content-Range: bytes ") +
193 ultostr(byte_offset) + "-" +
194 ultostr(source->stream_length - 1) + "/" +
195 ultostr(source->stream_length) + "\r\n";
196 response += HTTP_DONE;
199 case REQ_TYPE_TRANSCODING_LIVE: {
201 response += HTTP_PARAMS;
202 response += HTTP_DONE;
209 //----------------------------------------------------------------------
211 void Util::vlog(const char * format, ...) throw()
213 static char vlog_buffer[MAX_PRINT_LEN];
214 memset(vlog_buffer, 0, MAX_PRINT_LEN);
217 va_start(args, format);
218 vsnprintf(vlog_buffer, MAX_PRINT_LEN-1, format, args);
221 WARNING("%s", vlog_buffer);
223 //----------------------------------------------------------------------
225 std::string get_host_addr()
227 std::stringstream ss;
228 struct sockaddr_in addr;
229 socklen_t addrlen = sizeof(addr);
231 getpeername(0, (struct sockaddr*)&addr, &addrlen);
232 ss << inet_ntoa(addr.sin_addr);
236 //-------------------------------------------------------------------------------
238 std::vector<int> find_process_by_name(std::string name, int mypid)
240 std::vector<int> pidlist;
241 char cmdlinepath[256] = {0};
242 DIR* d = opendir("/proc");
245 while ((de = readdir(d)) != 0) {
246 int pid = atoi(de->d_name);
248 sprintf(cmdlinepath, "/proc/%s/cmdline", de->d_name);
251 std::ifstream cmdlinefile(cmdlinepath);
252 std::getline(cmdlinefile, cmdline);
253 if (!cmdline.empty()) {
254 size_t pos = cmdline.find('\0');
255 if (pos != string::npos)
256 cmdline = cmdline.substr(0, pos);
257 pos = cmdline.rfind('/');
258 if (pos != string::npos)
259 cmdline = cmdline.substr(pos + 1);
260 if ((name == cmdline) && ((mypid != pid) || (mypid == 0))) {
261 pidlist.push_back(pid);
270 //-------------------------------------------------------------------------------
272 void kill_process(int pid)
274 int result = kill(pid, SIGINT);
275 DEBUG("SEND SIGINT to %d, result : %d", pid, result);
278 //----------------------------------------------------------------------