reSIProcate/stack  9694
limpc.cxx
Go to the documentation of this file.
00001 #if defined(HAVE_CONFIG_H)
00002 #include "config.h"
00003 #endif
00004 
00005 #include <cstring>
00006 #include <cassert>
00007 #include <stdio.h>
00008 #include <signal.h>
00009 //#define USE_CURSES
00010 
00011 #ifdef USE_CURSES
00012 #include <ncurses.h>
00013 #else
00014 #include <iostream>
00015 #include <cstdio>
00016 
00017 #ifdef WIN32
00018 #include <io.h>
00019 #else
00020 #include <unistd.h>
00021 #endif
00022 
00023 typedef void WINDOW;
00024 // !ah! Really ought to check for ncurses and be a bit better behaved than this.
00025 #if !defined(TRUE)
00026 #define TRUE true
00027 #endif
00028 #if !defined(FALSE)
00029 #define FALSE false
00030 #endif
00031 
00032 char ACS_HLINE=1;
00033 char ACS_VLINE=2;
00034 WINDOW* stdscr=0;
00035 WINDOW* newwin(...) { return NULL; };
00036 void waddstr(WINDOW*, const char* text) { std::clog << text; };
00037 char getch()
00038 {
00039    char buf[1];
00040    int r = read(fileno(stdin),&buf,1);
00041    if ( r ==1 )
00042    {
00043       return buf[0];
00044    }
00045    return 0;
00046 };
00047 
00048 void werase(WINDOW*) {};
00049 void wrefresh(...) {};
00050 void mvhline(...) {};
00051 void refresh(...) {};
00052 void getmaxyx(...) {};
00053 void clearok(...) {};
00054 void waddch(...) {};
00055 void initscr(...) {};
00056 void cbreak(...) {};
00057 void noecho(...) {};
00058 void nonl(...) {};
00059 void intrflush(...) {};
00060 void keypad(...) {};
00061 void scrollok(...) {};
00062 void wmove(...) {};
00063 void mvvline(...) {};
00064 #endif
00065 
00066 
00067 
00068 #ifndef WIN32
00069 #include <sys/time.h>
00070 #include <sys/types.h>
00071 #include <unistd.h>
00072 #include <stdlib.h>
00073 #endif
00074 
00075 #include "rutil/FdPoll.hxx"
00076 #include "rutil/Socket.hxx"
00077 #include "rutil/Logger.hxx"
00078 #include "resip/stack/SipStack.hxx"
00079 #include "resip/stack/Uri.hxx"
00080 #include "resip/stack/TuIM.hxx"
00081 
00082 #ifdef USE_SSL
00083 #include "resip/stack/ssl/Security.hxx"
00084 #endif
00085 
00086 static int myMain(int argc, char* argv[]);
00087 
00088 using namespace resip;
00089 using namespace std;
00090 
00091 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00092 
00093 static WINDOW* commandWin=0;
00094 static WINDOW* textWin=0;
00095 static WINDOW* statusWin=0;
00096 
00097 static TuIM* tuIM;
00098 static Uri   dest;
00099 
00100 void 
00101 displayPres()
00102 {
00103    werase(statusWin);
00104 
00105    for( int i=0; i<tuIM->getNumBuddies();i++)
00106    {
00107       Uri uri = tuIM->getBuddyUri(i);
00108       Data status;
00109       bool online = tuIM->getBuddyStatus(i,&status);
00110       const char* stat = (online)?"online":"offline";
00111          
00112       waddstr(statusWin,uri.getAor().c_str());
00113       waddstr(statusWin," ");
00114       waddstr(statusWin,stat);
00115       waddstr(statusWin," ");
00116       waddstr(statusWin,status.c_str());
00117       waddstr(statusWin,"\n");
00118    }
00119 
00120    wrefresh(statusWin);  
00121 }
00122 
00123 bool
00124 processStdin( Uri* dest, bool sign, bool encryp )
00125 {
00126    static unsigned int num=0;
00127    static char buf[1024];
00128 
00129    char c = getch();    
00130       
00131    if ( c == 0 )
00132    {
00133       return true;
00134    }
00135    
00136    if ( c == '\f' )
00137    {
00138       clearok(textWin,TRUE);
00139       clearok(statusWin,TRUE);
00140       clearok(commandWin,TRUE);
00141 
00142       assert( num < sizeof(buf) );
00143       buf[num] = 0;
00144       werase(commandWin);
00145       waddstr(commandWin,buf);
00146 
00147       wrefresh(textWin);
00148       wrefresh(statusWin);
00149       wrefresh(commandWin);
00150 
00151       return true;
00152    }
00153 
00154 #if 0
00155    char junk[6];
00156    junk[0]=' ';
00157    junk[1]='0'+(c/100);
00158    junk[2]='0'+((c/10)%10);
00159    junk[3]='0'+(c%10);
00160    junk[4]=' ';
00161    junk[5]=0;
00162    waddstr(commandWin,junk);
00163 #endif
00164 
00165    if (  (c == '\a') || (c == '\b') || (c == 4 ) || (c == 0x7F) )
00166    {
00167       if ( num > 0 )
00168       {
00169          num--;
00170       }
00171       buf[num]=0;
00172 
00173       werase(commandWin);
00174       waddstr(commandWin,buf);
00175       wrefresh(commandWin);
00176       
00177       return true;
00178    }
00179        
00180    if ( (c == '\r') || (c == '\n') || (num+2>=sizeof(buf)) )
00181    {
00182       buf[num] =0;
00183 
00184       if ( (num>3) && (!strncmp("to:",buf,3)) )
00185       {
00186          buf[num] = 0;
00187          *dest = Uri(Data(buf+3));
00188        
00189          //cerr << "Set destination to <" << *dest << ">";
00190          waddstr(textWin,"Set destination to ");
00191          waddstr(textWin, Data::from(*dest).c_str());
00192          waddstr(textWin,"\n");
00193          wrefresh(textWin);
00194       }
00195       else if ( (num>4) && (!strncmp("add:",buf,4)) )
00196       {
00197          buf[num] = 0;
00198          Uri uri(Data(buf+4));
00199 
00200          //cerr << "Subscribing to buddy <" << uri << ">";
00201          waddstr(textWin, "Subscribing to ");
00202          waddstr(textWin, Data::from(uri).c_str());
00203          waddstr(textWin, "\n");
00204          wrefresh(textWin);
00205          
00206          tuIM->addBuddy( uri, Data::Empty );
00207          displayPres();
00208       }
00209       else if ( (num>=7) && (!strncmp("status:",buf,7)) )
00210       {
00211          buf[num] = 0;
00212          Data stat(buf+7);
00213 
00214          //cerr << "setting presence status to  <" << stat << ">";
00215          waddstr(textWin,"Set presece status to <");
00216          waddstr(textWin,stat.c_str());
00217          waddstr(textWin,">\n");
00218          wrefresh(textWin);
00219 
00220          tuIM->setMyPresence( !stat.empty(), stat );
00221       }
00222       else if ( (num==1) && (!strncmp(".",buf,1)) )
00223       {
00224          //DebugLog( << "Got a period - end program" );
00225          return false;
00226       }
00227       else
00228       { 
00229          if ( num >= 1 )
00230          {
00231             assert( num < sizeof(buf) );
00232             buf[num] = 0;
00233             Data text(buf);
00234             
00235             Data destValue  = dest->getAor();
00236             
00237             DebugLog( << "Destination is " << destValue );
00238 
00239             Data encFor = Data::Empty;
00240             if (encryp)
00241             { 
00242                encFor = dest->getAorNoPort();
00243             }
00244 
00245             DebugLog( << "Destination encrypt for is " << encFor );
00246 
00247             if ( tuIM->haveCerts(sign,encFor) )
00248             {
00249                waddstr(textWin,"To: ");
00250                waddstr(textWin,destValue.c_str());
00251                waddstr(textWin," ");
00252                waddstr(textWin,text.c_str());
00253                waddstr(textWin,"\n");
00254                wrefresh(textWin);
00255                
00256                tuIM->sendPage( text , *dest, sign , encFor );
00257             }
00258             else
00259             {
00260                waddstr(textWin,"Don't have aproperate certificates to sign and encrypt a message to ");
00261                waddstr(textWin,destValue.c_str());
00262                waddstr(textWin,"\n");
00263                wrefresh(textWin);
00264             }
00265          }
00266       }
00267 
00268       num = 0;  
00269 
00270       werase(commandWin);
00271       wrefresh(commandWin);
00272    }
00273    else
00274    {
00275       buf[num++] = c;
00276       assert( num < sizeof(buf) );
00277       
00278       waddch(commandWin,c);
00279       wrefresh(commandWin);
00280    }
00281 
00282    return true;
00283 }
00284 
00285 class StdInWatcher : public resip::FdPollItemIf
00286 {
00287    public:
00288       StdInWatcher(Uri* dest, bool sign, bool encrypt) :
00289          mDest(dest),
00290          mSign(sign),
00291          mEncrypt(encrypt),
00292          mKeepGoing(true)
00293       {}
00294 
00295       virtual ~StdInWatcher(){}
00296 
00297       virtual void processPollEvent(FdPollEventMask mask)
00298       {
00299          mKeepGoing=processStdin(mDest, mSign, mEncrypt);
00300       }
00301 
00302       inline bool keepGoing() const {return mKeepGoing;} 
00303 
00304    private:
00305       Uri* mDest;
00306       bool mSign;
00307       bool mEncrypt;
00308       bool mKeepGoing;
00309 
00310 }; // class StdInWatcher
00311 
00312 
00313 class TestCallback: public TuIM::Callback
00314 {
00315    public:
00316       virtual void presenceUpdate(const Uri& dest, bool open, const Data& status );
00317       virtual void receivedPage( const Data& msg, const Uri& from ,
00318                                  const Data& signedBy,  SignatureStatus sigStatus,
00319                                  bool wasEncryped  );
00320       virtual void sendPageFailed( const Uri& dest,int respNumber );
00321       virtual void registrationFailed(const resip::Uri&, int respNumber); 
00322       virtual void registrationWorked(const Uri& dest );
00323       virtual void receivePageFailed(const Uri& sender);
00324 };
00325   
00326 
00327 void 
00328 TestCallback::presenceUpdate(const Uri& from, bool open, const Data& status )
00329 {
00330    const char* stat = (open)?"online":"offline";
00331    //cout << from << " set presence to " << stat << " " << status.c_str() << endl;
00332 
00333    waddstr(textWin,"Status: ");
00334    waddstr(textWin, from.getAor().c_str());
00335    waddstr(textWin," is ");
00336    waddstr(textWin,stat);
00337    waddstr(textWin," ");
00338    waddstr(textWin,status.c_str());
00339    waddstr(textWin,"\n");
00340 
00341    wrefresh(textWin);
00342 
00343    displayPres();
00344 }
00345 
00346 void 
00347 TestCallback::receivedPage( const Data& msg, const Uri& from,
00348                             const Data& signedBy,  SignatureStatus sigStatus,
00349                             bool wasEncryped  )
00350 {  
00351    //DebugLog(<< "In TestPageCallback");
00352 
00353    if ( dest != from )
00354    {
00355       dest = from;
00356       //cerr << "Set destination to <" << *mDest << ">" << endl;
00357       waddstr(textWin,"Set destination to ");
00358       waddstr(textWin, Data::from(dest).c_str());
00359       waddstr(textWin,"\n");
00360    }
00361    
00362    //cout << from;  
00363 
00364    waddstr(textWin,"From: ");
00365    waddstr(textWin,from.getAor().c_str());
00366 
00367    if ( !wasEncryped )
00368    {
00369       //cout << " -NOT SECURE- ";
00370       waddstr(textWin," -NOT SECURE-");
00371    }
00372    else
00373    {
00374       waddstr(textWin," -secure-");
00375    }
00376    switch ( sigStatus )
00377    {
00378       case  SignatureSelfSigned:
00379          //cout << " -self signed signature (bad)- ";
00380          waddstr(textWin,"bad signature");
00381          break;
00382       case  SignatureIsBad:
00383          //cout << " -bad signature- ";
00384          waddstr(textWin,"bad signature");
00385          break;
00386       case  SignatureNone:
00387          //cout << " -no signature- ";
00388          waddstr(textWin,"no signature");
00389          break;
00390       case  SignatureTrusted:
00391          //cout << " <signed  " << signedBy << " > ";
00392          waddstr(textWin,"signed ");
00393          waddstr(textWin,signedBy.c_str());
00394          break;
00395       case  SignatureCATrusted:
00396          //cout << " <ca signed  " << signedBy << " > ";
00397          waddstr(textWin,"ca signed " );
00398          waddstr(textWin,signedBy.c_str());
00399          break;
00400       case  SignatureNotTrusted:
00401          //cout << " <signed  " << signedBy << " NOT TRUSTED > ";
00402          waddstr(textWin,"untrusted signature ");
00403          waddstr(textWin,signedBy.c_str());
00404          break;
00405    }
00406    
00407    //cout << " says:" << endl;
00408    //cout << msg.escaped() << endl;  
00409    waddstr(textWin, " says: ");
00410    waddstr(textWin, msg.escaped().c_str() );
00411    waddstr(textWin, "\n");
00412    
00413    wrefresh(textWin);
00414 }
00415 
00416 
00417 void 
00418 TestCallback::sendPageFailed( const Uri& target, int respNum )
00419 {
00420    //InfoLog(<< "In TestErrCallback");  
00421    // cerr << "Message to " << dest << " failed" << endl;  
00422    Data num(respNum);
00423    
00424    waddstr(textWin,"Message to ");
00425    waddstr(textWin, Data::from(target).c_str());
00426    waddstr(textWin," failed (");
00427    waddstr(textWin,num.c_str());
00428    waddstr(textWin," response)\n");
00429    wrefresh(textWin);
00430 }
00431 
00432 
00433 void 
00434 TestCallback::receivePageFailed( const Uri& target )
00435 {
00436    //InfoLog(<< "In TestErrCallback");  
00437    // cerr << "Message to " << dest << " failed" << endl;  
00438 
00439    waddstr(textWin,"Can not understand messager from ");
00440    waddstr(textWin, Data::from(target).c_str());
00441    waddstr(textWin,"\n");
00442    wrefresh(textWin);
00443 }
00444 
00445 
00446 void 
00447 TestCallback::registrationFailed(const resip::Uri& target, int respNum )
00448 {
00449    Data num(respNum);
00450    
00451    waddstr(textWin,"Registration to ");
00452    waddstr(textWin, Data::from(target).c_str());
00453    waddstr(textWin," failed (");
00454    waddstr(textWin,num.c_str());
00455    waddstr(textWin," response)\n");
00456    wrefresh(textWin);
00457 }
00458   
00459                               
00460 void 
00461 TestCallback::registrationWorked(const resip::Uri& target)
00462 {
00463    waddstr(textWin,"Registration to ");
00464    waddstr(textWin, Data::from(target).c_str());
00465    waddstr(textWin," worked");
00466    wrefresh(textWin);
00467 }
00468   
00469                               
00470 int
00471 main(int argc, char* argv[])
00472 {
00473 #ifndef _WIN32
00474    if ( signal( SIGPIPE, SIG_IGN) == SIG_ERR)
00475    {
00476       cerr << "Couldn't install signal handler for SIGPIPE" << endl;
00477       exit(-1);
00478    }
00479 #endif
00480 
00481    int r;
00482    
00483    try
00484    {
00485       r = myMain( argc, argv );
00486    }
00487    catch( ... )
00488    {
00489       ErrLog( << "Got a exception passed all the way to the top of limp" );
00490       exit(-1);
00491    }
00492    
00493    return r;
00494 }
00495 
00496 
00497 static int
00498 myMain(int argc, char* argv[])
00499 {  
00500    Log::initialize(Log::Cerr, Log::Err, argv[0]);
00501    Log::setLevel(Log::Warning);
00502 
00503    InfoLog(<<"Test Driver for IM Starting");
00504     
00505    int port = 5060;
00506    int tlsPort = 0;
00507    int dtlsPort = 0;
00508    Uri aor;
00509    bool haveAor=false;
00510    dest = Uri("sip:nobody@example.com");
00511    Data aorPassword;
00512    Uri contact("sip:user@");
00513    bool haveContact=false;
00514    Uri outbound;
00515    bool noRegister = false;
00516    Data tlsDomain = Data::Empty;
00517 
00518    Data sendMsg = Data::Empty;
00519    
00520    int numAdd=0;
00521    Data addList[100];
00522    int numPub=0;
00523    Data pubList[100];
00524    bool encryp=false;
00525    bool sign=false;
00526    Data key("password");
00527    bool useTls = true;
00528    bool noTls = false;
00529    bool noTcp = false;
00530    bool prefUdp = false;
00531    bool prefTls = false;
00532    bool prefDtls = false;
00533    bool prefTcp = false;
00534    bool noUdp = false;
00535    bool noV6 = false;
00536    bool noV4 = false;
00537    bool genUserCert = false;
00538    
00539    for ( int i=1; i<argc; i++)
00540    {
00541       if (!strcmp(argv[i],"-vv"))
00542       {
00543          Log::setLevel(Log::Stack);
00544       }
00545       else if (!strcmp(argv[i],"-v"))
00546       {
00547          Log::setLevel(Log::Info);
00548       }
00549       else if (!strcmp(argv[i],"-encrypt"))
00550       {
00551          encryp = true;
00552       }
00553       else if (!strcmp(argv[i],"-genUserCert"))
00554       {
00555          genUserCert = true;
00556       }
00557       else if (!strcmp(argv[i],"-noRegister"))
00558       {
00559          noRegister = true;
00560       }
00561       else if (!strcmp(argv[i],"-sign"))
00562       {
00563          sign = true;
00564       }
00565       else if (!strcmp(argv[i],"-tlsDomain"))
00566       {
00567          i++;
00568          assert( i<argc );
00569          tlsDomain = Data(argv[i]);
00570       }
00571       else if (!strcmp(argv[i],"-ssl"))
00572       {
00573          useTls = false;
00574       }
00575       else if (!strcmp(argv[i],"-noTcp"))
00576       {
00577          noTcp = true;
00578       }
00579       else if (!strcmp(argv[i],"-noTls"))
00580       {
00581          noTls = true;
00582       }
00583       else if (!strcmp(argv[i],"-noUdp"))
00584       {
00585          noUdp = true;
00586       }
00587       else if (!strcmp(argv[i],"-prefTcp"))
00588       {
00589          prefTcp = true;
00590       }
00591       else if (!strcmp(argv[i],"-prefTls"))
00592       {
00593          prefTls = true;
00594       }
00595       else if (!strcmp(argv[i],"-prefUdp"))
00596       {
00597          prefUdp = true;
00598       }
00599       else if (!strcmp(argv[i],"-noV6"))
00600       {
00601          noV6 = true;
00602       }
00603       else if (!strcmp(argv[i],"-noV4"))
00604       {
00605          noV4 = true;
00606       }
00607       else if (!strcmp(argv[i],"-port"))
00608       {
00609          i++;
00610          assert( i<argc );
00611          port = atoi( argv[i] );
00612       } 
00613       else if (!strcmp(argv[i],"-tlsPort"))
00614       {
00615          i++;
00616          assert( i<argc );
00617          tlsPort = atoi( argv[i] );
00618       }
00619       else if (!strcmp(argv[i],"-dtlsPort"))
00620       {
00621          i++;
00622          assert( i<argc );
00623          dtlsPort = atoi( argv[i] );
00624       }
00625       else if (!strcmp(argv[i],"-aor"))
00626       {
00627          i++;
00628          assert( i<argc );
00629          try
00630          {
00631             aor = Uri(Data(argv[i]));
00632          }
00633          catch (...)
00634          {
00635             ErrLog( <<"AOR URI is not valid - must start with sip: ");
00636             exit(-1);
00637          }
00638          haveAor=true;
00639       } 
00640       else if (!strcmp(argv[i],"-outbound"))
00641       {
00642          i++;
00643          assert( i<argc );
00644          try
00645          {
00646             outbound = Uri(Data(argv[i]));
00647          }
00648          catch (...)
00649          {
00650             ErrLog( <<"Outbound URI is not valid - must start with sip: ");
00651             exit(-1);
00652          }
00653       } 
00654       else if (!strcmp(argv[i],"-send"))
00655       {
00656          i++;
00657          assert( i<argc );
00658          sendMsg = Data(argv[i]);
00659       } 
00660       else if (!strcmp(argv[i],"-contact"))
00661       {
00662          i++;
00663          assert( i<argc );
00664          try
00665          {
00666             contact = Uri(Data(argv[i]));
00667          }
00668          catch (...)
00669          {
00670             ErrLog( <<"Contact URI is not valid - must start with sip: ");
00671             exit(-1);
00672          }
00673          haveContact=true;
00674       } 
00675       else if (!strcmp(argv[i],"-add"))
00676       {
00677          i++;
00678          assert( i<argc );
00679          addList[numAdd++] = Data(argv[i]);
00680          assert( numAdd < 100 ); 
00681          try
00682          {
00683             // CJ TODO FIX 
00684             //Uri uri( Data(argv[i]) );
00685          }
00686          catch (...)
00687          {
00688             ErrLog( <<"URI in -add is not valid - must start with sip: ");
00689             exit(-1);
00690          }
00691       } 
00692       else if (!strcmp(argv[i],"-pub"))
00693       {
00694          i++;
00695          assert( i<argc );
00696          pubList[numPub++] = Data(argv[i]);
00697          assert( numPub < 100 ); 
00698          try
00699          {
00700             // CJ TODO FIX 
00701             //Uri uri(Data(argv[i]));
00702          }
00703          catch (...)
00704          {
00705             ErrLog( <<"Pub URI is not valid - must start with sip: ");
00706             exit(-1);
00707          }
00708       } 
00709       else if (!strcmp(argv[i],"-aorPassword"))
00710       {
00711          i++;
00712          assert( i<argc );
00713          aorPassword = Data(argv[i]);
00714       } 
00715       else if (!strcmp(argv[i],"-to"))
00716       {
00717          i++;
00718          assert( i<argc );
00719          try
00720          {
00721             dest = Uri(Data(argv[i])); 
00722          }
00723          catch (...)
00724          {
00725             ErrLog( <<"To URI is not valid - must start with sip: ");
00726             exit(-1);
00727          }
00728       } 
00729       else if (!strcmp(argv[i],"-key"))
00730       {
00731          i++;
00732          assert( i<argc );
00733          key = Data(argv[i]);
00734       } 
00735       else
00736       { 
00737          clog <<"Bad command line opion: " << argv[i] << endl;
00738          clog <<"options are: " << endl
00739               << "\t [-v] [-vv] [-tls] [-port 5060] [-tlsport 5061]" << endl
00740               << "\t [-aor sip:alice@example.com] [-aorPassword password]" << endl
00741               << "\t [-to sip:friend@example.com] [-add sip:buddy@example.com]" << endl
00742               << "\t [-sign] [-encrypt] [-key secret]" << endl
00743               << "\t [-contact sip:me@example.com] " << endl
00744               << "\t [-outbound \"sip:example.com;lr\"] " << endl
00745               << "\t [-noRegister] " << endl
00746               << "\t [-pub sip:foo.com] " << endl
00747               << "\t [-tlsDomain foo.com] " << endl
00748               << "\t [-send myMessage] " << endl; 
00749          clog << endl
00750               << " -v is verbose" << endl
00751               << " -vv is very verbose" << endl
00752               << " -noV6 don't use IPv6" << endl
00753               << " -noV4 don't use IPv4" << endl
00754               << " -noUdp don't use UDP" << endl
00755               << " -noTcp don't use TCP" << endl
00756               << " -noTls don't use TLS" << endl
00757               << " -prefUdp prefer UDP" << endl
00758               << " -prefTcp prefer TCP" << endl
00759               << " -prefTls prefer TLS" << endl
00760               << " -port sets the UDP and TCP port to listen on" << endl
00761               << " -tlsPort sets the port to listen for TLS on" << endl
00762               << " -tlsDomain domainName - sets tls and dtls to act as tls server instead of client" << endl
00763               << " -ssl - use ssl instead of tls" << endl
00764               << " -aor sets the proxy and user name to register with" << endl
00765               << " -aorPassword sets the password to use for registration" << endl
00766               << " -noRegister causes it not to register - by default the AOR is registered" << endl
00767               << " -to sets initial location to send messages to" << endl
00768               << " -outbound sets the outbound proxy" << endl
00769               << " -add adds a budy who's presence will be monitored" << endl
00770               << " -pub adds a State Agent to send publishes too" << endl
00771               << " -sign signs message you send and -encryp encrypt them " << endl
00772               << " -send takes a string (needs to be quoted if it has spaces) " 
00773               <<                                      "and sends it as an IM " << endl
00774               << "\t(You need PKI certs for this to work)" << endl
00775               << " -key allows you to enter a secret used to load your private key."<< endl
00776               << "  If you set the secret to - the system will querry you for it."<< endl
00777               << " -contact overrides your SIP contact - can be used for NAT games" << endl
00778               << "\t there can be many -add " << endl
00779               << " -genUserCert - generate a new user cert" << endl
00780               << " " << endl
00781               << "Examples" << endl
00782               << "An example command line for a user with account name alice at example.com is:" << endl
00783               << "\t" << argv[0] << " -aor \"alice@example.com\" -aorPassword \"secret\"" << endl
00784               << "to watch the presence of bob and charlie add" << endl
00785               << "\t-add \"sip:bob@bilboxi.com\" -add \"charlie@example.com\" " << endl
00786               << "If Alice was behind a NAT that had a public address of 1.2.3.4 and had forwarded" << endl
00787               << "port 5070 on this NAT to the machine Alice was using, then the following " << endl
00788               << "options would be added" << endl
00789               << "\t-contact \"sip:alice@1.2.3.4:5070\" -port 5070" << endl
00790               << "" << endl
00791               << endl;
00792          exit(1);
00793       }
00794    }
00795    
00796    //InfoLog( << "Using port " << port );
00797   
00798 #ifdef USE_SSL
00799    InfoLog( << "Setting up Security" );
00800    Security* security=NULL;
00801    try
00802    {
00803       char cert_dir[ 1024 ] ;
00804       char *home_dir = getenv( "HOME" ) ;
00805 
00806       cert_dir[ 0 ] = '\0' ;
00807       ::strcat( cert_dir, home_dir ) ;
00808       ::strcat( cert_dir, "/.sipCerts/" ) ;
00809 
00810       security = new Security( cert_dir ) ;
00811 
00812       //  ::free( home_dir ) ; // CJ TODO mem leak 
00813    }
00814    catch( ... )
00815    {
00816       security = NULL;
00817       ErrLog( << "Got a exception setting up Security" );
00818    }
00819 
00820    SipStack sipStack( security );  
00821 #else
00822    SipStack sipStack( false /*multihtread*/ );  
00823 #endif
00824 
00825    if ( key == Data("-") )
00826    {
00827       clog << "Please enter password to use to load your private key: ";
00828       char buf[1024];
00829       cin.get(buf,1024);
00830       key = Data(buf);
00831       InfoLog( << "Certificate key set to <" << key << ">" );
00832    }
00833    
00834 #ifdef USE_SSL
00835    try
00836    {
00837       Security* security = sipStack.getSecurity();
00838       assert(security != 0);
00839    }
00840    catch( ... )
00841    {
00842       ErrLog( << "Got an exception creating security object " );
00843    }
00844 
00845    try
00846    {
00847       assert(security != 0);
00848       security->preload();
00849    }
00850    catch( ... )
00851    {
00852       ErrLog( << "Got a exception pre loading certificates" );
00853    }
00854 
00855 
00856    if (genUserCert)
00857    {
00858       assert( security );
00859       security->generateUserCert(aor.getAor());
00860    }
00861 #endif
00862 
00863    DebugLog( << "About to add the transports " );   
00864    if (port!=0)
00865    {
00866       if ( noUdp != true )
00867       {
00868          if (!noV4) sipStack.addTransport(UDP, port, V4);
00869 #ifdef USE_IPV6
00870          if (!noV6) sipStack.addTransport(UDP, port, V6);
00871 #endif
00872       }
00873       if ( noTcp != true )
00874       {
00875          if (!noV4) sipStack.addTransport(TCP, port, V4);
00876 #ifdef USE_IPV6
00877          if (!noV6) sipStack.addTransport(TCP, port, V6);
00878 #endif
00879       }
00880    }
00881 #ifdef USE_SSL
00882    if ( tlsPort != 0 )
00883    {
00884       if ( noTls != true )
00885       {
00886          if (!noV4) 
00887          {
00888             sipStack.addTransport(TLS, tlsPort, V4, StunDisabled, Data::Empty, tlsDomain );
00889          }
00890          //if (!noV6) sipStack.addTlsTransport(tlsPort,Data::Empty,Data::Empty,Data::Empty,V6);
00891       }
00892    }
00893 #ifdef USE_DTLS
00894    if ( dtlsPort != 0 )
00895    {
00896       if ( noTls != true )
00897       {
00898          if (!noV4) 
00899          {
00900             sipStack.addTransport(DTLS, dtlsPort, V4, StunDisabled, Data::Empty, tlsDomain );
00901          }
00902       }
00903    }
00904 #endif
00905 #endif
00906 
00907    DebugLog( << "Done adding the transports " );   
00908 
00909    if (!haveContact)
00910    {
00911       // contact.port() = port;
00912       // contact.host() = sipStack.getHostname();
00913    }
00914    
00915    if ( haveAor )
00916    {
00917       if (!haveContact)
00918       {
00919          contact.user() = aor.user();
00920 #ifdef USE_SSL
00921          if ( aor.scheme() == "sips" )
00922          {
00923             contact.scheme() = aor.scheme();
00924             //contact.port() = tlsPort;
00925          }
00926 #endif
00927       }
00928    }
00929    else
00930    {
00931       aor.port() = port;
00932       aor.host() = sipStack.getHostname();
00933       aor.user() = Data("user");
00934    }
00935 
00936    InfoLog( << "aor is " << aor );
00937    InfoLog( << "contact is " << contact );
00938    TestCallback callback;
00939    tuIM = new TuIM(&sipStack,aor,contact,&callback);
00940 
00941    Data name("SIPimp.org/0.2.5 (curses)");
00942    tuIM->setUAName( name );
00943       
00944    if ( !outbound.host().empty() )
00945    {
00946       tuIM->setOutboundProxy( outbound );
00947    }
00948 
00949    // setup prefered outbound transport 
00950    if ( prefUdp )
00951    {
00952       tuIM->setDefaultProtocol( UDP );
00953    }
00954    if ( prefTcp )
00955    {
00956       tuIM->setDefaultProtocol( TCP );
00957    }
00958    if ( prefTls )
00959    {
00960       tuIM->setDefaultProtocol( TLS );
00961    }
00962    if ( prefDtls )
00963    {
00964       tuIM->setDefaultProtocol( DTLS );
00965    }
00966 
00967    if ( haveAor )
00968    {
00969       if ( !noRegister )
00970       {
00971          tuIM->registerAor( aor, aorPassword );
00972       }
00973    }
00974    
00975    initscr(); 
00976    cbreak(); 
00977    noecho();
00978    nonl();
00979    intrflush(stdscr, FALSE);
00980    keypad(stdscr, TRUE);
00981 
00982    int rows=0;
00983    int cols=0;
00984    getmaxyx(stdscr,rows,cols);          /* get the number of rows and columns */
00985         
00986    commandWin = newwin(2,cols,rows-2,0);
00987    scrollok(commandWin, TRUE);
00988    wmove(commandWin,0,0);
00989      
00990    textWin = newwin(rows-3,cols*3/4,0,0);
00991    scrollok(textWin, TRUE);
00992    wmove(textWin,0,0);
00993      
00994    statusWin = newwin(rows-3,cols-(cols*3/4)-1,0,1+cols*3/4);
00995    scrollok(statusWin, FALSE);
00996    wmove(statusWin,0,0);
00997 
00998    mvhline(rows-3,0,ACS_HLINE,cols);
00999    mvvline(0,(cols*3/4),ACS_VLINE,rows-3);
01000    refresh();
01001 
01002    for ( int i=0; i<numAdd; i++ )
01003    { 
01004       Uri uri(addList[i]);
01005       tuIM->addBuddy( uri, Data::Empty );
01006    }
01007 
01008    for ( int i=0; i<numPub; i++ )
01009    { 
01010       Uri uri(pubList[i]);
01011       tuIM->addStateAgent( uri );
01012    }
01013 
01014    displayPres();
01015  
01016    waddstr(textWin,"Use -help on the command line to view options\n");
01017    waddstr(textWin,"To set where your messages will get sent type\n");
01018    waddstr(textWin,"    to: sip:alice@example.com \n");
01019    waddstr(textWin,"To monitores someeone presence type\n");
01020    waddstr(textWin,"    add: sip:buddy@example.com \n");
01021    waddstr(textWin,"To change you online status type\n");
01022    waddstr(textWin,"    status: in meeting\n");
01023    waddstr(textWin,"To set yourself to offline type\n");
01024    waddstr(textWin,"   status:\n");
01025    waddstr(textWin,"To exit type a single period\n");
01026    waddstr(textWin,"\n");
01027    wrefresh(textWin);     
01028 
01029    if ( !sendMsg.empty() )
01030    {
01031          tuIM->sendPage( sendMsg , dest, sign , (encryp) ?
01032                          (dest.getAorNoPort()) : (Data::Empty) );
01033    }
01034 
01035    StdInWatcher watcher(&dest,sign,encryp);
01036    FdPollItemHandle wh=sipStack.getPollGrp()->addPollItem(fileno(stdin), FPEM_Read, &watcher);
01037 
01038    while (1)
01039    {
01040       try
01041       {
01042          sipStack.process( 50 );
01043       }
01044       catch (...)
01045       {
01046          ErrLog( << "Got a exception from sipStack::process" );
01047       }
01048 
01049       if(!watcher.keepGoing())
01050       {
01051          break;
01052       }
01053 
01054       try
01055       {
01056          tuIM->process();
01057       }
01058       catch (...)
01059       {
01060          ErrLog( << "Got a exception passed from TuIM::process" );
01061       }
01062    }
01063 
01064    sipStack.getPollGrp()->delPollItem(wh);
01065 
01066    return 0;
01067 }
01068 /* ====================================================================
01069  * The Vovida Software License, Version 1.0 
01070  * 
01071  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
01072  * 
01073  * Redistribution and use in source and binary forms, with or without
01074  * modification, are permitted provided that the following conditions
01075  * are met:
01076  * 
01077  * 1. Redistributions of source code must retain the above copyright
01078  *    notice, this list of conditions and the following disclaimer.
01079  * 
01080  * 2. Redistributions in binary form must reproduce the above copyright
01081  *    notice, this list of conditions and the following disclaimer in
01082  *    the documentation and/or other materials provided with the
01083  *    distribution.
01084  * 
01085  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
01086  *    and "Vovida Open Communication Application Library (VOCAL)" must
01087  *    not be used to endorse or promote products derived from this
01088  *    software without prior written permission. For written
01089  *    permission, please contact vocal@vovida.org.
01090  *
01091  * 4. Products derived from this software may not be called "VOCAL", nor
01092  *    may "VOCAL" appear in their name, without prior written
01093  *    permission of Vovida Networks, Inc.
01094  * 
01095  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
01096  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
01097  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
01098  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
01099  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
01100  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
01101  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
01102  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
01103  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
01104  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
01105  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
01106  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
01107  * DAMAGE.
01108  * 
01109  * ====================================================================
01110  * 
01111  * This software consists of voluntary contributions made by Vovida
01112  * Networks, Inc. and many individuals on behalf of Vovida Networks,
01113  * Inc.  For more information on Vovida Networks, Inc., please see
01114  * <http://www.vovida.org/>.
01115  *
01116  */