00001 #include "rtsp.h"
00002 #include "helpers.h"
00003
00004 #include <string.h>
00005 #include <vector>
00006
00007 using namespace std;
00008
00009 #undef RTSP_DEBUG
00010
00011
00012 #ifdef RTSP_DEBUG
00013 #define D(a) a
00014 #else
00015 #define D(a)
00016 #endif
00017
00018 #define RTSP_PORT "554"
00019 #define RTSP_SIGN "rtsp://"
00020
00021
00022 _Request::_Request(const string &request) {
00023 string s;
00024 int prev = 0;
00025 int i = 0;
00026 int l = request.length();
00027 const char *c = request.c_str();
00028 bool first = true;
00029 string name, value;
00030
00031 while(i < l) {
00032 s = "";
00033 for(; c[i] != '\n' && c[i] != '\r' && c[i] != '\0'; i++);
00034 if(c[i] == '\n' || c[i] == '\r') {
00035 if(i == prev) {
00036 i++;
00037 prev = i;
00038 continue;
00039 }
00040 s.insert(0, request, prev, i - prev);
00041
00042 if(first) {
00043 int x = s.find(" ");
00044 method.insert(0, s, 0, x);
00045 int y = s.find(" ", x + 1);
00046 uri.insert(0, s, x + 1, y - x - 1);
00047
00048 first = false;
00049 } else {
00050 name = "";
00051 value = "";
00052 int x = s.find(": ");
00053 name.insert(0, s, 0, x);
00054 value.insert(0, s, x + 2, s.length() - x - 1);
00055 fields[name] = value;
00056
00057 }
00058 }
00059 if(c[i] == '\0')
00060 break;
00061 i++;
00062 prev = i;
00063 }
00064 }
00065
00066 void _Responce::add_field(const string &name, const string &value) {
00067 fields[name] = value;
00068 }
00069
00070 void _Responce::add_include(const string &_include) {
00071 include = _include;
00072 }
00073
00074 string _Responce::serialize() {
00075 string rez;
00076 switch(_status) {
00077 case STATUS_OK:
00078 rez = "RTSP/1.0 200 OK\r\n";
00079 break;
00080 case STATUS_BUSY:
00081 rez = "RTSP/1.0 455 Server is busy\r\n";
00082 break;
00083 case STATUS_EMPTY:
00084 rez = "";
00085 return rez;
00086 }
00087 for(map<string, string>::iterator it = fields.begin(); it != fields.end(); it++) {
00088 rez += (*it).first + ": " + (*it).second + "\r\n";
00089 }
00090 rez += "\r\n";
00091 if(include.length() != 0) {
00092 rez += include;
00093 }
00094 return rez;
00095 }
00096
00097
00098 RTSP_Server::RTSP_Server(int (*h)(void *, RTSP_Server *, RTSP_Server::event), void *handler_data, Session *_session) {
00099 handler_f = h;
00100 this->handler_data = handler_data;
00101 session = _session;
00102 _busy = NULL;
00103 }
00104
00105 void RTSP_Server::main(void) {
00106 list <Socket *> s;
00107
00108
00109 Socket *socket_main = new Socket("", 554);
00110
00111
00112
00113 s.push_back(socket_main);
00114 socket_main->listen(2);
00115
00116 while(1) {
00117
00118 Socket::poll(s);
00119 D(cerr << "incoming..." << endl;)
00120 refresh:
00121 D(cerr << "refresh..." << endl;)
00122 for(list<Socket *>::iterator it = s.begin(); it != s.end(); it++) {
00123 Socket::state state = (*it)->state_refresh();
00124 if(state == Socket::STATE_IN) {
00125 if(*it == socket_main) {
00126 Socket *in = socket_main->accept();
00127 if(in)
00128 s.push_back(in);
00129 } else {
00130
00131 if(!process(*it)) {
00132 s.remove(*it);
00133 goto refresh;
00134 }
00135 }
00136 }
00137 }
00138 }
00139 }
00140
00141 bool RTSP_Server::process(Socket *s) {
00142
00143 string req;
00144 _Request *request;
00145 _Responce *responce = NULL;
00146 bool r = true;
00147 _Responce::status status = _Responce::STATUS_EMPTY;
00148
00149
00150
00151 if(!s->recv(req))
00152 return false;
00153 if(req == "") {
00154 D(cerr << "request is empty, close client..." << endl;)
00155 return false;
00156 }
00157 if(!session->rtp_out.multicast) {
00158 if(req == "") {
00159 if(_busy == s) {
00160 handler(TEARDOWN);
00161 _busy = NULL;
00162 }
00163 return false;
00164 D( cerr << "--==-->> reset _busy !!! <<--==--" << endl;)
00165 }
00166 }
00167 D(cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << " part_REQUEST: " << endl << "\"" << req << "\"" << endl;)
00168
00169 part_of_request += req;
00170 req = part_of_request;
00171 const char *c = req.c_str();
00172 string end;
00173 int e = req.length();
00174 e -= 4;
00175 if(e <= 0)
00176 e = 0;
00177 for(int i = req.length() - 1; i >= e; i--) {
00178 end += c[i];
00179
00180 }
00181 if(end.find("\n\n") != 0 && end.find("\n\r\n\r") != 0) {
00182
00183 return true;
00184 } else
00185 part_of_request = "";
00186
00187
00188 D( cerr << __FILE__<< ":"<< __FUNCTION__ << ":" <<__LINE__ << "\tREQUEST: " << endl << "\"" << req << "\"" << endl;)
00189 request = new _Request(req);
00190
00191 responce = new _Responce();
00192 responce->add_field("CSeq", (*request->get_fields().find("CSeq")).second);
00193
00194 if(request->get_method() == "OPTIONS") {
00195 if (handler(IS_DAEMON_ENABLED)) {
00196 status = _Responce::STATUS_OK;
00197 responce->add_field("Public", "DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
00198
00199 if(!session->rtp_out.multicast)
00200 session->rtp_out.ip = s->source_ip();
00201 } else {
00202 status = _Responce::STATUS_BUSY;
00203 }
00204 }
00205 if(request->get_method() == "DESCRIBE") {
00206 if(handler(IS_DAEMON_ENABLED) && (session->rtp_out.multicast || !_busy)) {
00207 handler(DESCRIBE);
00208 status = _Responce::STATUS_OK;
00209 char buf[8];
00210 string sdp = make_sdp(request->get_uri());
00211 responce->add_field("Content-Type", "application/sdp");
00212 sprintf(buf, "%d", (int)sdp.length());
00213 responce->add_field("Content-Length", buf);
00214 responce->add_include(sdp);
00215 } else {
00216 status = _Responce::STATUS_BUSY;
00217 }
00218 }
00219 if(request->get_method() == "SETUP") {
00220 if (handler(IS_DAEMON_ENABLED) && (session->rtp_out.multicast || !_busy)) {
00221 status = _Responce::STATUS_OK;
00222 responce->add_field("Session", "47112344");
00223 responce->add_field("Transport", make_transport((*request->get_fields().find("Transport")).second));
00224 } else
00225 status = _Responce::STATUS_BUSY;
00226 }
00227 if(request->get_method() == "TEARDOWN") {
00228 status = _Responce::STATUS_OK;
00229 handler(TEARDOWN);
00230 _busy = NULL;
00231 }
00232 if(request->get_method() == "PLAY") {
00233 D(cerr << "--==-->> transport: " << session->rtp_out.multicast << "; _busy == " << (unsigned long)_busy << endl;)
00234
00235 if (handler(IS_DAEMON_ENABLED) && (session->rtp_out.multicast || !_busy)) {
00236 status = _Responce::STATUS_OK;
00237 handler(PLAY);
00238 if(!session->rtp_out.multicast)
00239 _busy = s;
00240 } else
00241 status = _Responce::STATUS_BUSY;
00242 D(cerr << "--==-->> transport: " << session->rtp_out.multicast << "; _busy == " << (unsigned long)_busy << " status=" << status << endl;)
00243 }
00244 if(request->get_method() == "PAUSE") {
00245 status = _Responce::STATUS_OK;
00246 handler(PAUSE);
00247 }
00248 delete request;
00249 responce->set_status(status);
00250 D( cerr << "\tRESPONSE: " << endl << "\"" << responce->serialize() << "\"" << endl;)
00251 r = s->send(responce->serialize());
00252 delete responce;
00253 return r;
00254 }
00255
00256 string RTSP_Server::make_sdp(string uri) {
00257 char buf[256];
00258
00259 D(cerr << "make SDP" << endl;)
00260
00261
00262 string rez = "m=video ";
00263 D(cerr << "_____________________" << endl;)
00264 D(cerr << "_____________________" << endl;)
00265 D(cerr << "_____________________" << endl;)
00266 sprintf(buf, "%d", session->rtp_out.port_video);
00267 if(session->process_audio == false) {
00268 D(cerr << "+++++++++++++++++++++" << endl;)
00269 if(session->rtp_out.multicast) {
00270 rez += buf;
00271 } else {
00272 rez += "0";
00273 }
00274 } else {
00275 rez += buf;
00276 }
00277 rez += " RTP/AVP ";
00278 sprintf(buf, "%d", session->video.type);
00279 rez += buf;
00280 rez += "\r\n";
00281 if(session->rtp_out.multicast) {
00282 rez += "a=type:multicast\r\n";
00283 rez += "c=IN IP4 " + session->rtp_out.ip + "/" + session->rtp_out.ttl + "\r\n";
00284 } else {
00285 rez += "a=type:unicast\r\n";
00286 rez += "c=IN IP4 0.0.0.0\r\n";
00287 }
00288 sprintf(buf, "%.4f", session->video.fps);
00289 rez += "a=framerate:";
00290 rez += buf;
00291 rez += "\r\na=x-framerate:";
00292 rez += buf;
00293 if(session->video.width > 0) {
00294 sprintf(buf, "%d", session->video.width);
00295 rez += "\r\na=width:";
00296 rez += buf;
00297 rez += "\r\na=x-width:";
00298 rez += buf;
00299 }
00300 if(session->video.height > 0) {
00301 sprintf(buf, "%d", session->video.height);
00302 rez += "\r\na=height:";
00303 rez += buf;
00304 rez += "\r\na=x-height:";
00305 rez += buf;
00306 }
00307 if(session->video.width > 0 && session->video.height > 0) {
00308 sprintf(buf, "%d,%d", session->video.width, session->video.height);
00309 rez += "\r\na=x-dimensions:";
00310 rez += buf;
00311 }
00312
00313 rez += "\r\n";
00314
00315 if(session->process_audio) {
00316
00317 sprintf(buf, "m=audio %d RTP/AVP %d\r\n", session->rtp_out.port_audio, session->audio.type);
00318 rez += buf;
00319 sprintf(buf, "a=rtpmap:%d L16/%d/%d\r\n", session->audio.type, session->audio.sample_rate, session->audio.channels);
00320 rez += buf;
00321 }
00322 rez += "a=control:" + uri + "\r\n";
00323 D(cerr << "make SDP - ok!" << endl;)
00324 return rez;
00325 }
00326
00327 string RTSP_Server::make_transport(string req) {
00328 map<string, string> m = String::split_list_to_map(String::split_to_list(req, ';'), '=');
00329 string client_port = m["client_port"];
00330 int port_req = session->rtp_out.port_video;
00331
00332 if(client_port != "") {
00333 string first, second;
00334 String::split(client_port, '-', first, second);
00335 port_req = atol(first.c_str());
00336
00337
00338 }
00339
00340 if(!session->rtp_out.multicast) {
00341 if(!session->process_audio) {
00342 session->rtp_out.port_video = port_req;
00343 }
00344 }
00345
00346 string rez = "RTP/AVP;";
00347 if(session->rtp_out.multicast)
00348 rez += "multicast;";
00349 else
00350 rez += "unicast;";
00351 char buf[128];
00352 sprintf(buf, "%d", port_req);
00353 rez += "destination=" + session->rtp_out.ip + ";port=" + buf;
00354 if(session->process_audio) {
00355 sprintf(buf, "-%d", port_req + 1);
00356
00357
00358
00359
00360 rez += buf;
00361 }
00362 if(session->rtp_out.multicast)
00363 rez += ";ttl=" + session->rtp_out.ttl;
00364
00365
00366
00367 return rez;
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 }
00413
00414 RTSP_Server::~RTSP_Server() {
00415 cerr << "destroy RTSP_Server object" << endl;
00416
00417
00418
00419 }
00420