SemiProxy.cpp

00001 /*********************************************************************** 00002 * * 00003 * ViTooKi * 00004 * * 00005 * title: SemiProxy.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 "SemiProxy.hpp" 00051 00052 00053 #include "global.hpp" 00054 #include "vitooki.hpp" 00055 00056 bool SemiProxy::semiproxyRunning; 00057 00058 /*********************************************************************** 00059 Signal handler for CTRL + C 00060 ***********************************************************************/ 00061 void sighandler(int sig) 00062 { 00063 if (sig == SIGINT) 00064 { 00065 SemiProxy::setSemiProxyRunning(false); 00066 cout << "SIGINT" << endl; 00067 Globals::sdebug.writeLogfile(); 00068 if (SemiProxy::getRefLastCreated() != NULL) SemiProxy::getRefLastCreated()->cleanup(); 00069 exit(EXIT_SUCCESS); 00070 } 00071 } 00072 00073 00074 SemiProxy *SemiProxy::refLastCreated; 00075 00076 /***********************************************************************/ 00077 SemiProxy::SemiProxy(uint proxyPort, uint responderPort) 00078 { 00079 this->proxyPort = proxyPort; 00080 addDestination = true; 00081 semiproxyRunning = true; 00082 requestServerPosition = true; 00083 requestClientPosition = true; 00084 00085 //start Session-Management on specified port 00086 //(used for the socket-communication between semi-proxy and semi-server) 00087 sessMgmt = new SessionMgmt(responderPort); 00088 sessMgmt->start(); 00089 00090 //read all users from file 00091 ul = new UserList(); 00092 ul->readUsersFromFile(Globals::getConfigFilePath()); 00093 00094 00095 //read all profiles from file 00096 //(and also add each profile to corresponding user) 00097 prol = new ProfileList(); 00098 prol->readProfilesFromFile(Globals::getConfigFilePath(), ul); 00099 00100 refLastCreated = this; 00101 } 00102 00103 /***********************************************************************/ 00104 SemiProxy::~SemiProxy() 00105 { 00106 Globals::sdebug << "\r\ncalling ~SemiProxy()"; 00107 cleanup(); 00108 } 00109 00110 /***********************************************************************/ 00111 void SemiProxy::cleanup() 00112 { 00113 Globals::sdebug << "\nSemiProxy::cleanup()..."; 00114 vector<class SemiProxySession*>::iterator iter = spsList.begin(); 00115 while (iter != spsList.end()) 00116 { 00117 SemiProxySession *sess = *iter; 00118 sess->setStateClosed(); 00119 delete sess; 00120 iter++; 00121 } 00122 spsList.clear(); 00123 00124 if (sessMgmt != NULL) delete sessMgmt; 00125 if (ul != NULL) delete ul; 00126 if (prol != NULL) delete prol; 00127 Globals::sdebug << "\nSemiProxy::cleanup() done!"; 00128 } 00129 00130 /***********************************************************************/ 00131 int SemiProxy::createRtspServerSocket(const char *host, int port) 00132 { 00133 struct hostent *hp; 00134 struct sockaddr_in sin; 00135 int sock; 00136 00137 Globals::sdebug << "\n::createRtspServerSocket(): Trying to connect to " << host << " on port " << port << "..."; 00138 00139 if (!(hp = gethostbyname(host))) 00140 { 00141 cerr << "\n::createRtspServerSocket(): Cannot resolve host '" << host << "'" << endl; 00142 return 0; 00143 } 00144 00145 sin.sin_family = AF_INET; 00146 //bcopy (hp->h_addr, (char*) &sin.sin_addr, hp->h_length); 00147 memcpy((char*) &sin.sin_addr, hp->h_addr, hp->h_length); 00148 sin.sin_port = htons(port); 00149 00150 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) 00151 { 00152 cerr << "\n::createRtspServerSocket(): Cannot create socket" << endl; 00153 return 0; 00154 } 00155 00156 if (::connect(sock, (struct sockaddr*) &sin, sizeof(sin)) < 0) 00157 { 00158 #ifdef WIN32 00159 closesocket(sock); 00160 #else 00161 close(sock); 00162 #endif 00163 cerr << "\n::createRtspServerSocket(): Cannot connect to host '" << host << "'" << endl; 00164 return 0; 00165 } 00166 00167 Globals::sdebug << "\n::createRtspServerSocket(): success!\r\n"; 00168 00169 return sock; 00170 } 00171 00172 /***********************************************************************/ 00173 int SemiProxy::openClientSocket(int proxyport) 00174 { 00175 Globals::sdebug << "\n::openClientSocket(): Trying to open passive socket on port " << proxyport; 00176 00177 struct sockaddr_in sin, caller; 00178 int sock, newsocket; 00179 socklen_t len; 00180 00181 memset((char*) &sin, 0, sizeof(sin)); 00182 sin.sin_family = AF_INET; 00183 sin.sin_addr.s_addr = INADDR_ANY; 00184 sin.sin_port = htons(proxyport); 00185 00186 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) 00187 { 00188 cerr << "\n::openClientSocket(): Cannot create Socket!" << endl; 00189 return 1; 00190 } 00191 00192 const int reuse = 1; 00193 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuse, sizeof(reuse)) < 0) 00194 { 00195 cerr << "\n::openClientSocket(): Cannot set sockOpt!" << endl; 00196 return 1; 00197 } 00198 00199 if (bind(sock, (struct sockaddr*) &sin, sizeof(sin)) < 0) 00200 { 00201 cerr << "\n::openClientSocket(): Cannot bind socket!" << endl; 00202 return 1; 00203 } 00204 00205 listen(sock, MAX_PENDING); 00206 00207 cout << "\nSemiProxy running on port " << proxyport << "..." << endl; 00208 00209 while (SemiProxy::isSemiProxyRunning()) 00210 { 00211 if ((newsocket = accept(sock, (struct sockaddr*) &caller, &len)) < 0) 00212 { 00213 cerr << "\n::openClientSocket(): Cannot accept socket!" << endl; 00214 return 1; 00215 } 00216 00217 Globals::sdebug << "\n::openClientSocket(): socket connected to " << inet_ntoa(caller.sin_addr) << " on port " << caller.sin_port << "\n"; 00218 00219 //start new proxy thread for this connection 00220 SemiProxySession *rtspthread = new SemiProxySession(newsocket, &caller, this); 00221 spsList.push_back(rtspthread); 00222 rtspthread->start(); 00223 00224 //wait 20 microseconds 00225 #ifndef WIN32 00226 usleep(20); 00227 #else 00228 Sleep(20); 00229 #endif 00230 00231 } 00232 00233 return 0; //success; 00234 } 00235 00236 00237 /***********************************************************************/ 00238 void SemiProxy::addSession(SSession *asess) 00239 { 00240 assert(asess != NULL); 00241 00242 this->sessMgmt->addSession(asess); 00243 } 00244 00245 /***********************************************************************/ 00246 void SemiProxy::removeSession(SSession *asess) 00247 { 00248 if (asess != NULL) 00249 { 00250 this->sessMgmt->removeSession(asess); 00251 } 00252 } 00253 00254 /***********************************************************************/ 00255 SSession *SemiProxy::getSession(uint RtspSessionId) 00256 { 00257 return this->sessMgmt->getSession(RtspSessionId); 00258 } 00259 00260 /***********************************************************************/ 00261 UserList *SemiProxy::getUserList() 00262 { 00263 return ul; 00264 } 00265 00266 /***********************************************************************/ 00267 ProfileList *SemiProxy::getProfileList() 00268 { 00269 return prol; 00270 } 00271 00272 /***********************************************************************/ 00273 uint SemiProxy::getProxyPort() 00274 { 00275 return proxyPort; 00276 } 00277 00278 /**********************************************************************/ 00279 void SemiProxy::setAddDestination(bool shouldAddDestination) 00280 { 00281 addDestination = shouldAddDestination; 00282 } 00283 00284 /***********************************************************************/ 00285 void SemiProxy::setAddTermCaps(bool shouldAddTermCaps) 00286 { 00287 addTermCaps = shouldAddTermCaps; 00288 } 00289 00290 /***********************************************************************/ 00291 void SemiProxy::setRequestServerPosition(bool shouldRequestServerPosition) 00292 { 00293 requestServerPosition = shouldRequestServerPosition; 00294 } 00295 00296 /***********************************************************************/ 00297 void SemiProxy::setRequestClientPosition(bool shouldRequestClientPosition) 00298 { 00299 requestClientPosition = shouldRequestClientPosition; 00300 } 00301 00302 /***********************************************************************/ 00303 bool SemiProxy::shouldAddDestination() 00304 { 00305 return addDestination; 00306 } 00307 00308 /***********************************************************************/ 00309 bool SemiProxy::shouldAddTermCaps() 00310 { 00311 return addTermCaps; 00312 } 00313 00314 /***********************************************************************/ 00315 bool SemiProxy::shouldRequestServerPosition() 00316 { 00317 return requestServerPosition; 00318 } 00319 00320 /***********************************************************************/ 00321 bool SemiProxy::shouldRequestClientPosition() 00322 { 00323 return requestClientPosition; 00324 } 00325 00326 /***********************************************************************/ 00327 bool SemiProxy::isSemiProxyRunning() 00328 { 00329 return semiproxyRunning; 00330 } 00331 00332 /***********************************************************************/ 00333 void SemiProxy::setSemiProxyRunning(bool isRunning) 00334 { 00335 semiproxyRunning = isRunning; 00336 } 00337 00338 /***********************************************************************/ 00339 SemiProxy *SemiProxy::getRefLastCreated() 00340 { 00341 return refLastCreated; 00342 } 00343 00344 /*********************************************************************** 00345 Show usage of semiproxy. 00346 ***********************************************************************/ 00347 void showUsage(char *progname) 00348 { 00349 cout << progname << " <port> [-nodest] [-debug] [-flush] [-notermcaps] [-nogetspos] [-nogetcpos] [-showconfig]\r\n\r\n"; 00350 cout << "\t<port>............Port of SemiProxy to listen\r\n"; 00351 cout << "\t-nodest...........no change of destination parameter\r\n"; 00352 cout << "\t on Describe-Msg.\r\n"; 00353 cout << "\t-debug............output detailed debug messages\r\n"; 00354 cout << "\t-flush............immediately outputs debug messages\r\n"; 00355 cout << "\t-notermcaps.......do not add terminal-capabilites to Describe-Msg\r\n"; 00356 cout << "\t-nogetspos........do not use Get-Parameter/position to obtain\r\n"; 00357 cout << "\t media-time of a session from the SERVER.\r\n"; 00358 cout << "\t-nogetcpos........do not use Get-Parameter/position to obtain\r\n"; 00359 cout << "\t media-time of a session from the CLIENT.\r\n"; 00360 cout << "\t-showconfig.......show current configuration\r\n"; 00361 cout << "\r\n"; 00362 00363 exit(1); 00364 } 00365 00366 00367 00368 /***********************************************************************/ 00369 int main(int argc, char* argv[]) 00370 { 00371 try 00372 { 00373 00374 bool addDestAllowed = true, 00375 addTermCapsAllowed = true, 00376 requestServerPositionAllowed = true, 00377 requestClientPositionAllowed = true, 00378 showConfig = false; 00379 00380 //at least the port must be specified 00381 if (argc < 2) showUsage(argv[0]); 00382 00383 //vitooki_init_all(); 00384 uint proxyPort = atoi(argv[1]); 00385 00386 00387 //look for additional options 00388 if (argc > 2) 00389 { 00390 int i = 2; 00391 while (i < argc) 00392 { 00393 if (strcmp(argv[i], "-nodest") == 0) 00394 { 00395 Globals::sdebug << "\nSP::run(): '-nodest' detected "; 00396 addDestAllowed = false; 00397 } 00398 else if (strcmp(argv[i], "-notermcaps") == 0) 00399 { 00400 Globals::sdebug << "\nSP::run(): '-notermcaps' detected "; 00401 addTermCapsAllowed = false; 00402 } 00403 else if (strcmp(argv[i], "-nogetspos") == 0) 00404 { 00405 Globals::sdebug << "\nSP::run(): '-nogetspos' detected "; 00406 requestServerPositionAllowed = false; 00407 } 00408 else if (strcmp(argv[i], "-nogetcpos") == 0) 00409 { 00410 Globals::sdebug << "\nSP::run(): '-nogetcpos' detected "; 00411 requestClientPositionAllowed = false; 00412 } 00413 else if (strcmp(argv[i], "-debug") == 0) 00414 { 00415 Globals::sdebug << "\nSP::run(): '-debug' detected "; 00416 Globals::sdebug.enableStdOut(); 00417 } 00418 else if (strcmp(argv[i], "-flush") == 0) 00419 { 00420 Globals::sdebug << "\nSP::run(): '-flush' detected "; 00421 Globals::sdebug.enableFlush(); 00422 } 00423 else if (strcmp(argv[i], "-showconfig") == 0) 00424 { 00425 showConfig = true; 00426 } 00427 else 00428 { 00429 cerr << "\nSP::run(): unrecognized option: " << argv[i] << endl; 00430 exit(1); 00431 } 00432 i++; 00433 } 00434 } 00435 00436 //register signal-handler 00437 signal(SIGINT, sighandler); 00438 00439 if (showConfig) 00440 { 00441 Globals::showCurrentConfiguration(); 00442 exit(EXIT_SUCCESS); 00443 } 00444 00445 vitooki_init_all(); 00446 00447 //start proxy 00448 SemiProxy *sp = new SemiProxy(proxyPort, Globals::getProxyComPort()); 00449 sp->setAddDestination(addDestAllowed); 00450 sp->setAddTermCaps(addTermCapsAllowed); 00451 sp->setRequestServerPosition(requestServerPositionAllowed); 00452 sp->setRequestClientPosition(requestClientPositionAllowed); 00453 sp->openClientSocket(proxyPort); 00454 delete sp; 00455 00456 } 00457 catch (...) 00458 { 00459 cerr << "\nSP::run(): Unknown exception thrown!" << endl; 00460 } 00461 00462 Globals::sdebug.writeLogfile(); 00463 00464 Globals::sdebug << "\nSP::run(): END"; 00465 00466 return 0; 00467 } 00468