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 RTSP_Server::RTSP_Server(void (*h)(void *, RTSP_Server *, RTSP_Server::event), void *handler_data, Session *_session) {
00098 handler_f = h;
00099 this->handler_data = handler_data;
00100 session = _session;
00101 _busy = NULL;
00102 }
00103
00104 void RTSP_Server::main(void) {
00105 list <Socket *> s;
00106
00107
00108 Socket *socket_main = new Socket("", 554);
00109
00110
00111
00112 s.push_back(socket_main);
00113 socket_main->listen(2);
00114
00115 while(1) {
00116
00117 Socket::poll(s);
00118 D(cerr << "incoming..." << endl;)
00119 refresh:
00120 D(cerr << "refresh..." << endl;)
00121 for(list<Socket *>::iterator it = s.begin(); it != s.end(); it++) {
00122 Socket::state state = (*it)->state_refresh();
00123 if(state == Socket::STATE_IN) {
00124 if(*it == socket_main) {
00125 Socket *in = socket_main->accept();
00126 if(in)
00127 s.push_back(in);
00128 } else {
00129
00130 if(!process(*it)) {
00131 s.remove(*it);
00132 goto refresh;
00133 }
00134 }
00135 }
00136 }
00137 }
00138 }
00139
00140 bool RTSP_Server::process(Socket *s) {
00141 string req;
00142 _Request *request;
00143 _Responce *responce = NULL;
00144 bool r = true;
00145 _Responce::status status = _Responce::STATUS_EMPTY;
00146
00147
00148
00149 if(!s->recv(req))
00150 return false;
00151 if(req == "") {
00152 D(cerr << "request is empty, close client..." << endl;)
00153 return false;
00154 }
00155 if(!session->rtp_out.multicast) {
00156 if(req == "") {
00157 if(_busy == s) {
00158 handler(TEARDOWN);
00159 _busy = NULL;
00160 }
00161 return false;
00162 D( cerr << "--==-->> reset _busy !!! <<--==--" << endl;)
00163 }
00164 }
00165 D(cerr << "part_REQUEST: " << endl << "\"" << req << "\"" << endl;)
00166
00167 part_of_request += req;
00168 req = part_of_request;
00169 const char *c = req.c_str();
00170 string end;
00171 int e = req.length();
00172 e -= 4;
00173 if(e <= 0)
00174 e = 0;
00175 for(int i = req.length() - 1; i >= e; i--) {
00176 end += c[i];
00177
00178 }
00179 if(end.find("\n\n") != 0 && end.find("\n\r\n\r") != 0) {
00180
00181 return true;
00182 } else
00183 part_of_request = "";
00184
00185
00186 D( cerr << "\tREQUEST: " << endl << "\"" << req << "\"" << endl;)
00187 request = new _Request(req);
00188
00189 responce = new _Responce();
00190 responce->add_field("CSeq", (*request->get_fields().find("CSeq")).second);
00191
00192 if(request->get_method() == "OPTIONS") {
00193 status = _Responce::STATUS_OK;
00194 responce->add_field("Public", "DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
00195
00196 if(!session->rtp_out.multicast)
00197 session->rtp_out.ip = s->source_ip();
00198 }
00199 if(request->get_method() == "DESCRIBE") {
00200 if(session->rtp_out.multicast || !_busy) {
00201 status = _Responce::STATUS_OK;
00202 char buf[8];
00203 string sdp = make_sdp(request->get_uri());
00204 responce->add_field("Content-Type", "application/sdp");
00205 sprintf(buf, "%d", (int)sdp.length());
00206 responce->add_field("Content-Length", buf);
00207 responce->add_include(sdp);
00208 } else {
00209 status = _Responce::STATUS_BUSY;
00210 }
00211 }
00212 if(request->get_method() == "SETUP") {
00213 if(session->rtp_out.multicast || !_busy) {
00214 status = _Responce::STATUS_OK;
00215 responce->add_field("Session", "47112344");
00216 responce->add_field("Transport", make_transport((*request->get_fields().find("Transport")).second));
00217 } else
00218 status = _Responce::STATUS_BUSY;
00219 }
00220 if(request->get_method() == "TEARDOWN") {
00221 status = _Responce::STATUS_OK;
00222 handler(TEARDOWN);
00223 _busy = NULL;
00224 }
00225 if(request->get_method() == "PLAY") {
00226 D(cerr << "--==-->> transport: " << session->rtp_out.multicast << "; _busy == " << (unsigned long)_busy << endl;)
00227 if(session->rtp_out.multicast || !_busy) {
00228 status = _Responce::STATUS_OK;
00229 handler(PLAY);
00230 if(!session->rtp_out.multicast)
00231 _busy = s;
00232 } else
00233 status = _Responce::STATUS_BUSY;
00234 D(cerr << "--==-->> transport: " << session->rtp_out.multicast << "; _busy == " << (unsigned long)_busy << endl;)
00235 }
00236 if(request->get_method() == "PAUSE") {
00237 status = _Responce::STATUS_OK;
00238 handler(PAUSE);
00239 }
00240 delete request;
00241 responce->set_status(status);
00242 D( cerr << "\tRESPONCE: " << endl << "\"" << responce->serialize() << "\"" << endl;)
00243 r = s->send(responce->serialize());
00244 delete responce;
00245 return r;
00246 }
00247
00248 string RTSP_Server::make_sdp(string uri) {
00249 char buf[256];
00250
00251 D(cerr << "make SDP" << endl;)
00252
00253
00254 string rez = "m=video ";
00255 D(cerr << "_____________________" << endl;)
00256 D(cerr << "_____________________" << endl;)
00257 D(cerr << "_____________________" << endl;)
00258 sprintf(buf, "%d", session->rtp_out.port_video);
00259 if(session->process_audio == false) {
00260 D(cerr << "+++++++++++++++++++++" << endl;)
00261 if(session->rtp_out.multicast) {
00262 rez += buf;
00263 } else {
00264 rez += "0";
00265 }
00266 } else {
00267 rez += buf;
00268 }
00269 rez += " RTP/AVP ";
00270 sprintf(buf, "%d", session->video.type);
00271 rez += buf;
00272 rez += "\r\n";
00273 if(session->rtp_out.multicast) {
00274 rez += "a=type:multicast\r\n";
00275 rez += "c=IN IP4 " + session->rtp_out.ip + "/" + session->rtp_out.ttl + "\r\n";
00276 } else {
00277 rez += "a=type:unicast\r\n";
00278 rez += "c=IN IP4 0.0.0.0\r\n";
00279 }
00280 sprintf(buf, "%.4f", session->video.fps);
00281 rez += "a=framerate:";
00282 rez += buf;
00283 rez += "\r\na=x-framerate:";
00284 rez += buf;
00285 if(session->video.width > 0) {
00286 sprintf(buf, "%d", session->video.width);
00287 rez += "\r\na=width:";
00288 rez += buf;
00289 rez += "\r\na=x-width:";
00290 rez += buf;
00291 }
00292 if(session->video.height > 0) {
00293 sprintf(buf, "%d", session->video.height);
00294 rez += "\r\na=height:";
00295 rez += buf;
00296 rez += "\r\na=x-height:";
00297 rez += buf;
00298 }
00299 if(session->video.width > 0 && session->video.height > 0) {
00300 sprintf(buf, "%d,%d", session->video.width, session->video.height);
00301 rez += "\r\na=x-dimensions:";
00302 rez += buf;
00303 }
00304
00305 rez += "\r\n";
00306
00307 if(session->process_audio) {
00308
00309 sprintf(buf, "m=audio %d RTP/AVP %d\r\n", session->rtp_out.port_audio, session->audio.type);
00310 rez += buf;
00311 sprintf(buf, "a=rtpmap:%d L16/%d/%d\r\n", session->audio.type, session->audio.sample_rate, session->audio.channels);
00312 rez += buf;
00313 }
00314 rez += "a=control:" + uri + "\r\n";
00315 D(cerr << "make SDP - ok!" << endl;)
00316 return rez;
00317 }
00318
00319 string RTSP_Server::make_transport(string req) {
00320 map<string, string> m = String::split_list_to_map(String::split_to_list(req, ';'), '=');
00321 string client_port = m["client_port"];
00322 int port_req = session->rtp_out.port_video;
00323
00324 if(client_port != "") {
00325 string first, second;
00326 String::split(client_port, '-', first, second);
00327 port_req = atol(first.c_str());
00328
00329
00330 }
00331
00332 if(!session->rtp_out.multicast) {
00333 if(!session->process_audio) {
00334 session->rtp_out.port_video = port_req;
00335 }
00336 }
00337
00338 string rez = "RTP/AVP;";
00339 if(session->rtp_out.multicast)
00340 rez += "multicast;";
00341 else
00342 rez += "unicast;";
00343 char buf[128];
00344 sprintf(buf, "%d", port_req);
00345 rez += "destination=" + session->rtp_out.ip + ";port=" + buf;
00346 if(session->process_audio) {
00347 sprintf(buf, "-%d", port_req + 1);
00348
00349
00350
00351
00352 rez += buf;
00353 }
00354 if(session->rtp_out.multicast)
00355 rez += ";ttl=" + session->rtp_out.ttl;
00356
00357
00358
00359 return rez;
00360
00361
00362
00363
00364
00365
00366
00367
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 RTSP_Server::~RTSP_Server() {
00407
00408
00409 }
00410