SessionList.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: SessionList.cpp * 00006 * * 00007 * * 00008 * * 00009 * ITEC institute of the University of Klagenfurt (Austria) * 00010 * http://www.itec.uni-klu.ac.at * 00011 * * 00012 * * 00013 * For more information visit the ViTooKi homepage: * 00014 * http://ViTooKi.sourceforge.net * 00015 * vitooki-user@lists.sourceforge.net * 00016 * vitooki-devel@lists.sourceforge.net * 00017 * * 00018 * This file is part of ViTooKi, a free video toolkit. * 00019 * ViTooKi is free software; you can redistribute it and/or * 00020 * modify it under the terms of the GNU General Public License * 00021 * as published by the Free Software Foundation; either version 2 * 00022 * of the License, or (at your option) any later version. * 00023 * * 00024 * This program is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU General Public License * 00030 * along with this program; if not, write to the Free Software * 00031 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * 00032 * MA 02111-1307, USA. * 00033 * * 00034 ***********************************************************************/ 00035 00036 /*********************************************************************** 00037 * * 00038 * REVISION HISTORY: * 00039 * * 00040 * * 00041 * * 00042 ***********************************************************************/ 00043 00044 /*********************************************************************** 00045 * Video Session Migration System, 2004 * 00046 * Author: Klaus Schoeffmann * 00047 ************************************************************************/ 00048 00049 00050 #include "SessionList.hpp" 00051 00052 00053 /***********************************************************************/ 00054 SessionList::SessionList(char *host, int port, Profile *profile) 00055 { 00056 this->host = host; 00057 this->port = port; 00058 this->profile = profile; 00059 00060 if (createResponderSocket() == 0) 00061 { 00062 proxyConnected = true; 00063 } 00064 else 00065 { 00066 proxyConnected = false; 00067 } 00068 } 00069 00070 /***********************************************************************/ 00071 SessionList::~SessionList() 00072 { 00073 list.clear(); 00074 } 00075 00076 00077 /***********************************************************************/ 00078 int SessionList::createResponderSocket() 00079 { 00080 struct hostent *hp; 00081 struct sockaddr_in sin; 00082 00083 cout << "<!--"; 00084 cout << "Trying to connect to " << host << " on port " << port << "..."; 00085 00086 if (!(hp = gethostbyname(host))) 00087 { 00088 cerr << "SessionList::createResponderSocket: Error: cannot resolve host \"" << host << "\"\r\n"; 00089 return 1; 00090 } 00091 00092 sin.sin_family = AF_INET; 00093 memcpy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); 00094 //bcopy (hp->h_addr, (char*) &sin.sin_addr, hp->h_length); 00095 sin.sin_port = htons(port); 00096 00097 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) 00098 { 00099 cerr << "SessionList::createResponderSocket: Error: ServerSocket-Create\r\n"; 00100 return 1; 00101 } 00102 00103 if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) < 0) 00104 { 00105 cerr << "SessionList::createResponderSocket: Error: ServerSocket-Connect\r\n"; 00106 #ifndef WIN32 00107 close(sock); 00108 #else 00109 closesocket(sock); 00110 #endif 00111 return 1; 00112 } 00113 00114 cout << "success!\r\n"; 00115 cout << "-->"; 00116 return 0; 00117 } 00118 00119 /***********************************************************************/ 00120 void SessionList::retrieveSessions() 00121 { 00122 if (proxyConnected) 00123 { 00124 cout << "<!--"; 00125 cout << endl << "readActiveSessions"; cout.flush(); 00126 list.clear(); 00127 00128 int entries; 00129 #ifndef WIN32 00130 recv(sock, (int *) &entries, sizeof(int), 0); 00131 #else 00132 recv(sock, (char *) &entries, sizeof(int), 0); 00133 #endif 00134 00135 cout << "..." << entries << " item(s)"; cout.flush(); 00136 00137 for (int i=0; i < entries; i++) 00138 { 00139 uint sessionId, URLlen, clientAdrlen, movieIdlen; 00140 uint sessionTOId, state, tsCount; 00141 ulong msecsElapsed, duration, prevDuration, tsCreation, tsClosed; 00142 char *URL, *clientAdr, *movieId; 00143 00144 #ifndef WIN32 00145 recv(sock, (uint *) &sessionId, sizeof(uint), 0); 00146 recv(sock, (uint *) &URLlen, sizeof(uint), 0); 00147 URL = (char *) malloc(sizeof(char) * (URLlen + 1)); 00148 recv(sock, URL, sizeof(char) * (URLlen + 1), 0); 00149 recv(sock, (uint *) &clientAdrlen, sizeof(uint), 0); 00150 clientAdr = (char *) malloc(sizeof(char) * (clientAdrlen + 1)); 00151 recv(sock, clientAdr, sizeof(char) * (clientAdrlen + 1), 0); 00152 recv(sock, (uint *) &movieIdlen, sizeof(uint), 0); 00153 movieId = (char *) malloc(sizeof(char) * (movieIdlen + 1)); 00154 recv(sock, (char *) movieId, sizeof(char) * (movieIdlen + 1), 0); 00155 recv(sock, (uint *) &sessionTOId, sizeof(uint), 0); 00156 recv(sock, (ulong *) &msecsElapsed, sizeof(ulong), 0); 00157 recv(sock, (ulong *) &duration, sizeof(ulong), 0); 00158 recv(sock, (ulong *) &prevDuration, sizeof(ulong), 0); 00159 recv(sock, (uint *) &tsCount, sizeof(uint), 0); 00160 recv(sock, (uint *) &state, sizeof(uint), 0); 00161 recv(sock, (ulong *) &tsCreation, sizeof(ulong), 0); 00162 recv(sock, (ulong *) &tsClosed, sizeof(ulong), 0); 00163 #else 00164 recv(sock, (char *) &sessionId, sizeof(uint), 0); 00165 recv(sock, (char *) &URLlen, sizeof(uint), 0); 00166 URL = (char *) malloc(sizeof(char) * (URLlen + 1)); 00167 recv(sock, URL, sizeof(char) * (URLlen + 1), 0); 00168 recv(sock, (char *) &clientAdrlen, sizeof(uint), 0); 00169 clientAdr = (char *) malloc(sizeof(char) * (clientAdrlen + 1)); 00170 recv(sock, clientAdr, sizeof(char) * (clientAdrlen + 1), 0); 00171 recv(sock, (char *) &movieIdlen, sizeof(uint), 0); 00172 movieId = (char *) malloc(sizeof(char) * (movieIdlen + 1)); 00173 recv(sock, (char *) movieId, sizeof(char) * (movieIdlen + 1), 0); 00174 recv(sock, (char *) &sessionTOId, sizeof(uint), 0); 00175 recv(sock, (char *) &msecsElapsed, sizeof(ulong), 0); 00176 recv(sock, (char *) &duration, sizeof(ulong), 0); 00177 recv(sock, (char *) &prevDuration, sizeof(ulong), 0); 00178 recv(sock, (char *) &tsCount, sizeof(uint), 0); 00179 recv(sock, (char *) &state, sizeof(uint), 0); 00180 recv(sock, (char *) &tsCreation, sizeof(ulong), 0); 00181 recv(sock, (char *) &tsClosed, sizeof(ulong), 0); 00182 00183 #endif 00184 00185 SSession *asess = new SSession(sessionId, URL, clientAdr, movieId, sessionTOId, 00186 msecsElapsed, state, duration, prevDuration, tsCount, tsCreation, tsClosed); 00187 cout << "<br>" << " received SSession: " << asess->getRtspSessionId(); cout.flush(); 00188 cout << "<br>" << " " << asess->getUrl(); cout.flush(); 00189 cout << "<br>" << " " << asess->getClientAdr() << endl; cout.flush(); 00190 cout << "<br>" << " " << asess->getSemiMovieId(); cout.flush(); 00191 cout << "<br>" << " " << asess->getOriginRtspSessionId() << endl; cout.flush(); 00192 cout << "<br>" << " " << asess->getElapsedMsecs(0,0) << endl; cout.flush(); 00193 cout << "<br>" << " " << asess->getDuration() << endl; cout.flush(); 00194 cout << "<br>" << " " << asess->getPreviousSessionDuration() << endl; cout.flush(); 00195 cout << "<br>" << " " << asess->getTimeSectionCount() << endl; cout.flush(); 00196 cout << "<br>" << " " << asess->getState() << endl; cout.flush(); 00197 cout << "<br>" << " " << asess->getTimestampCreated() << endl; cout.flush(); 00198 cout << "<br>" << " " << asess->getTimestampClosed() << endl; cout.flush(); 00199 00200 list.push_back(asess); 00201 } 00202 00203 cout << "-->"; 00204 } 00205 } 00206 00207 /***********************************************************************/ 00208 vector<SSession*>* SessionList::getList() 00209 { 00210 return &list; 00211 } 00212 00213 /***********************************************************************/ 00214 void SessionList::writeHTMLRepresentation(CGIParser *cgiparser, bool showActiveSessions, 00215 bool showClosedSessions, bool fakeRtspServer) 00216 { 00217 cout << "<tr><td colspan=\"2\" align=\"center\">"; 00218 00219 00220 if (list.size() == 0) 00221 { 00222 cout << "Currently, there are no existing sessions!<br><br>" << endl; 00223 } 00224 else 00225 { 00226 00227 //generate checkbox which can be used to display closed sessions to 00228 cout << cgiparser->createOpenForm("frmShowParams", "logon.cgi", "post", "showAS,showCS,showMS"); 00229 cout << "Show:"; 00230 //param: active sessions 00231 cout << "<input type=\"checkbox\" name=\"showAS\" "; 00232 if (showActiveSessions) cout << " checked "; 00233 cout << "onClick=\"document.forms['frmShowParams'].submit();\">active sessions"; 00234 //param: closed sessions 00235 cout << "<input type=\"checkbox\" name=\"showCS\" "; 00236 if (showClosedSessions) cout << " checked "; 00237 cout << "onClick=\"document.forms['frmShowParams'].submit();\">closed sessions"; 00238 cout << "</form>" << endl; 00239 00240 00241 cout << "List of currently active sessions:" << endl; 00242 00243 uint userId = atoi(cgiparser->getFieldValue("userid").c_str()); 00244 uint profileId = atoi(cgiparser->getFieldValue("proid").c_str()); 00245 uint linktype = atoi(cgiparser->getFieldValue("linktype").c_str()); 00246 int subtractSecs = atoi(cgiparser->getFieldValue("subtractSecs").c_str()); 00247 char *sphost = semifunc::newStrCpy((char*)cgiparser->getFieldValue("sphost").c_str()); 00248 char *spport = semifunc::newStrCpy((char*)cgiparser->getFieldValue("spport").c_str()); 00249 00250 cout << "<table width=\"95%\" class=\"activeSessions\">" << endl; 00251 00252 //iterate through session list 00253 vector<SSession*>::reverse_iterator iter = list.rbegin(); 00254 for (;iter != list.rend(); iter++) 00255 { 00256 SSession *as = *iter; 00257 00258 bool showSession = false; 00259 00260 if (!as->isClosed() && showActiveSessions) showSession = true; 00261 if (as->isClosed() && (as->getTimeSectionCount() > 1) && showClosedSessions) showSession = true; 00262 00263 if (showSession) 00264 { 00265 00266 //output name of video 00267 cout << "<tr><td "; 00268 if (as->isClosed()) cout << " style=\"background-color:#C6C6C6;\" "; 00269 cout << "><a href=\"#" << as->getSemiMovieId() << "\">" << endl; 00270 //if program crashes here... restart proxy! 00271 //(this may happen, if old sessions from another server exists in proxy) 00272 assert(MovieList::getMovieById(as->getSemiMovieId()) != NULL); 00273 00274 cout << MovieList::getMovieById(as->getSemiMovieId())->getName() 00275 << "</a></td>" << endl; 00276 00277 //generate links for migrate or copy 00278 Movie *movie = MovieList::getMovieById(as->getSemiMovieId()); 00279 if (movie != NULL) 00280 { 00281 //generate URI 00282 string movieUri = movie->getUrl(userId, profile->getProfileId()); 00283 unsigned int hostStart = movieUri.find("rtsp://") + 7; 00284 unsigned int hostEnd = movieUri.find("/", hostStart); 00285 unsigned int filePathStart = hostEnd; 00286 unsigned int portStart = movieUri.find(":", hostStart) + 1; 00287 if (portStart != string::npos && portStart < hostEnd) hostEnd = portStart-1; 00288 if (fakeRtspServer) { 00289 if (portStart != string::npos) { 00290 unsigned int slashPos = filePathStart; 00291 string portNr = movieUri.substr(portStart, slashPos-portStart); 00292 movieUri.insert(filePathStart,"/port="); 00293 movieUri.insert(filePathStart+strlen("/port="),portNr); 00294 movieUri.erase(portStart, slashPos-portStart); 00295 movieUri.insert(portStart, spport); 00296 } 00297 00298 //change host 00299 string hostAdr = movieUri.substr(hostStart, hostEnd-hostStart); 00300 if (hostAdr.compare(sphost) != 0) { 00301 movieUri.erase(hostStart, hostEnd-hostStart); 00302 movieUri.insert(hostStart, sphost); 00303 filePathStart = movieUri.find("/", hostStart); //may have changed 00304 movieUri.insert(filePathStart, "/host="); 00305 movieUri.insert(filePathStart+strlen("/host="), hostAdr); 00306 } 00307 } 00308 00309 filePathStart = movieUri.find("/", hostStart); 00310 string movieUri1 = movieUri.substr(0, filePathStart); 00311 string movieUri2 = movieUri.substr(filePathStart+1); 00312 00313 ostringstream rtspUriMigrate, rtspUriCopy; 00314 rtspUriMigrate << movieUri1 00315 << "/action=" << ACTION_MIGRATE 00316 << "/sub=" << (subtractSecs) 00317 << "/sid=" << as->getRtspSessionId() << "/" << movieUri2; 00318 rtspUriCopy << movieUri1 00319 << "/action=" << ACTION_COPY 00320 << "/sub=" << (subtractSecs) 00321 << "/sid=" << as->getRtspSessionId() << "/" << movieUri2; 00322 00323 //************* output links for migrate ****************** 00324 cout << "<td>" << endl; 00325 if (as->isClosed()) 00326 { 00327 cout << "&nbsp;"; //do not show migrate links for closed sessions 00328 } 00329 else 00330 { 00331 if (linktype == LINK_QTE) 00332 { 00333 00334 string frmName = "frmMigrate" + semifunc::toString(as->getRtspSessionId()); 00335 html::createQTEForm(frmName, rtspUriMigrate.str(), 00336 profile->getWidth(), profile->getHeight()); 00337 cout << "<a href=\"javascript:submitFormInWindow('" 00338 << frmName << "');\">Migrate</a>*</td>" << endl; 00339 00340 } 00341 else if (linktype == LINK_RTSP) 00342 { 00343 00344 cout << "<a href=\"" << rtspUriMigrate.str() << "\">Migrate</a>*" << endl; 00345 00346 } 00347 else if (linktype == LINK_SDP) 00348 { 00349 00350 ostringstream tmpName; 00351 //add user_id and profile_id (otherwise files from different users would be overwritten) 00352 tmpName << as->getRtspSessionId() << "_m" << "_u" 00353 << userId << "_p" << profileId; 00354 cout << "<a href=\"" 00355 << semifunc::createSDPFile(tmpName.str(), 00356 rtspUriMigrate.str(), 00357 Globals::getRelativeSDPFilePath(), 00358 Globals::getAbsoluteSDPFilePath()) 00359 << "\">Migrate</a>*" << endl; 00360 00361 } 00362 } 00363 cout << "</td>" << endl; 00364 00365 //************* output links for copy ****************** 00366 cout << "<td>" << endl; 00367 if (as->isClosed()) 00368 { 00369 cout << "&nbsp;"; //do not show copy links for closed sessions 00370 } 00371 else 00372 { 00373 if (linktype == LINK_QTE) 00374 { 00375 00376 string frmName = "frmCopy" + semifunc::toString(as->getRtspSessionId()); 00377 html::createQTEForm(frmName, rtspUriCopy.str(), 00378 profile->getWidth(), profile->getHeight()); 00379 cout << "<a href=\"javascript:submitFormInWindow('" 00380 << frmName << "');\">Copy</a>*</td>" << endl; 00381 00382 } 00383 else if (linktype == LINK_RTSP) 00384 { 00385 00386 cout << "<a href=\"" << rtspUriCopy.str() << "\">Copy</a>*"; 00387 00388 } 00389 else if (linktype == LINK_SDP) 00390 { 00391 00392 ostringstream tmpName; 00393 //add user_id and profile_id (otherwise files from different users would be overwritten) 00394 tmpName << as->getRtspSessionId() << "_c" << "_u" 00395 << userId << "_p" << profileId; 00396 cout << "<a href=\"" 00397 << semifunc::createSDPFile(tmpName.str(), 00398 rtspUriCopy.str(), 00399 Globals::getRelativeSDPFilePath(), 00400 Globals::getAbsoluteSDPFilePath()) 00401 << "\">Copy</a>*" << endl; 00402 00403 } 00404 } 00405 cout << "</td>" << endl; 00406 // } 00407 cout << "</tr>" << endl; 00408 00409 //************* output client address ****************** 00410 cout << "<tr><td colspan=\"1\">Client:" 00411 << as->getClientAdr() << "</td>" << endl; 00412 00413 //************* output links for section copy ****************** 00414 cout << "<td colspan=\"2\" rowspan=\"3\" align=\"center\"" 00415 << " valign=\"middle\">" << endl; 00416 if (as->getTimeSectionCount() > 1) 00417 { 00418 cout << "Copy from section*: "; 00419 00420 ostringstream selectBox; 00421 00422 selectBox << "<select size=\"1\" onchange=\"" 00423 << " if (this.value != '') eval(this.value);\">" << endl 00424 << "<option value="">#</option>" << endl; 00425 00426 ostringstream rtspUriContinue; 00427 // rtspUriContinue << movieUri1 00428 rtspUriContinue << "/action=" << ACTION_CONTINUE 00429 << "/sub=" << (subtractSecs) 00430 << "/sid=" << as->getRtspSessionId() << "/" << movieUri2; 00431 00432 for (uint j=1; j < as->getTimeSectionCount(); j++) 00433 { 00434 if (linktype == LINK_QTE) 00435 { 00436 00437 ostringstream frmName, tmpLink; 00438 frmName << "frmCont" << as->getRtspSessionId() << "_" << j; 00439 tmpLink << movieUri1 << "/section=" << j << rtspUriContinue.str(); 00440 html::createQTEForm(frmName.str(), tmpLink.str(), profile->getWidth(), profile->getHeight()); 00441 00442 selectBox << "<option value=\"javascript:submitFormInWindow('" 00443 << frmName.str() << "');\">" << j <<"</option>" << endl; 00444 00445 } 00446 else if (linktype == LINK_RTSP) 00447 { 00448 00449 selectBox << "<option value=\"window.open('" << movieUri1 00450 << "/section=" << j << rtspUriContinue.str() << "')\">" << j << "</option>" << endl; 00451 00452 } 00453 else if (linktype == LINK_SDP) 00454 { 00455 00456 ostringstream tmpLink, tmpName; 00457 tmpLink << movieUri1 << "/section=" << j << rtspUriContinue.str(); 00458 //add user_id and profile_id (otherwise files from different users would be overwritten) 00459 tmpName << as->getRtspSessionId() << "_" << j << "_u" << userId << "_p" << profileId; 00460 00461 selectBox << "<option value=\"window.open('" 00462 << semifunc::createSDPFile(tmpName.str(), 00463 tmpLink.str(), 00464 Globals::getRelativeSDPFilePath(), 00465 Globals::getAbsoluteSDPFilePath()) 00466 << "')\">" << j << "</option>" << endl; 00467 00468 } 00469 } 00470 00471 selectBox << "</select>" << endl; 00472 cout << selectBox.str(); 00473 00474 } 00475 else 00476 { 00477 cout << "&nbsp;"; 00478 } 00479 cout << "</td></tr>" << endl; 00480 } 00481 00482 //************* output state ****************** 00483 cout << "<tr><td colspan=\"1\">State: " << endl; 00484 switch (as->getState()) 00485 { 00486 case STATE_RUNNING: 00487 cout << "<font color=\"#00FF00\">active</font>"; 00488 break; 00489 case STATE_PAUSED: 00490 cout << "<font color=\"#0000FF\">paused</font>"; 00491 break; 00492 case STATE_CLOSED: 00493 cout << "<font color=\"#000000\">closed</font>"; 00494 break; 00495 default: 00496 cout << "unknown"; 00497 } 00498 cout << "</td><tr>" << endl; 00499 00500 //************* output elapsed time and duration ****************** 00501 cout << "<tr><td colspan=\"1\">Seconds: " << endl; 00502 char *msecs = semifunc::newStrCpy(semifunc::formatTime(as->getElapsedMsecs(0,0))); 00503 char *dur = semifunc::newStrCpy(semifunc::formatTime(as->getDuration())); 00504 cout << msecs << " / "; 00505 cout << dur << "</td></tr>" << endl; 00506 00507 //************* output elapsed time of previous session(s) ****************** 00508 if (as->getOriginRtspSessionId() != 0) 00509 { 00510 cout << "<tr><td colspan=\"3\"><font color=\"#979797\">"; 00511 cout << "Elapsed time of prev. session(s): " << semifunc::newStrCpy(semifunc::formatTime(as->getPreviousSessionDuration())); 00512 cout << "</font></td></tr>" << endl; 00513 } 00514 00515 //************* output timestamps ****************** 00516 cout << "<tr><td colspan=\"3\"><font color=\"#979797\">"; 00517 cout << "Created on: " << semifunc::newStrCpy(semifunc::formatTimeSecs(as->getTimestampCreated())); 00518 if (as->getState() == STATE_CLOSED) 00519 { 00520 cout << "&nbsp;&nbsp;&nbsp;&nbsp;"; 00521 cout << "Closed on: " << semifunc::newStrCpy(semifunc::formatTimeSecs(as->getTimestampClosed())); 00522 } 00523 cout << "</font></td></tr>" << endl; 00524 00525 cout << "<tr><td colspan=\"3\" style=\"border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#000000;\"><br></td></tr>"; 00526 00527 } 00528 00529 } 00530 cout << "</table>" << endl; 00531 00532 00533 //************* output selection of subtract-seconds ****************** 00534 cout << cgiparser->createOpenForm("subtractSelect", "logon.cgi", "post", ""); 00535 cout << "<table width=\"100%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">" << endl; 00536 cout << "<tr><td align=\"center\">"; 00537 cout << "*Start "; 00538 cout << "<select name=\"subtractSecs\" onchange=\"document.forms['subtractSelect'].submit();\" size=1>" << endl; 00539 int runTo = 20; 00540 int step = 2; 00541 for (int i=-runTo; i <= runTo; i+=step) 00542 { 00543 cout << "<option "; 00544 if (i == subtractSecs) cout << " selected "; 00545 cout << "value=\"" << i << "\">"; 00546 if (i > 0) 00547 { 00548 if (i >= 0 && i < 10) cout << "&nbsp;&nbsp;" << i; 00549 else cout << "&nbsp;" << i; 00550 cout << " seconds earlier"; 00551 } 00552 else if (i < 0) 00553 { 00554 if (i < 0 && i > -10) cout << "&nbsp;&nbsp;" << (i*-1); 00555 else cout << "&nbsp;" << (i*-1); 00556 cout << " seconds later"; 00557 } 00558 else 00559 { 00560 cout << "on EXACT POSITION"; 00561 } 00562 cout <<"</option>" << endl; 00563 } 00564 cout << "</select>" << endl; 00565 cout << "</form>" << endl; 00566 cout << "</td></tr></table>"; 00567 00568 cout << "<br><br>"; 00569 } 00570 cout << "</td></tr>"; 00571 00572 }