00001
00002
00003
00004
00005
00006
00007 #include <qapplication.h>
00008 #include <qfile.h>
00009 #include <qsocket.h>
00010 #include <qsocketdevice.h>
00011 #include <qdatetime.h>
00012 #include <qurl.h>
00013
00014 #include <stdlib.h>
00015 #include <stdio.h>
00016 #include <iostream>
00017 #include <sys/types.h>
00018 #include <sys/stat.h>
00019 #include <fcntl.h>
00020
00021 #ifndef WIN32
00022 #include <sys/ioctl.h>
00023 #include <unistd.h>
00024 #include <pthread.h>
00025 #include <netdb.h>
00026 #include <netinet/in.h>
00027 #include <net/if.h>
00028 #include <linux/sockios.h>
00029 #include <linux/videodev.h>
00030 #include <mythtv/mythcontext.h>
00031 #include "config.h"
00032 #endif
00033
00034 #ifdef WIN32
00035 #include <winsock2.h>
00036 #include "gcontext.h"
00037 #endif
00038
00039 using namespace std;
00040
00041 #include "sipfsm.h"
00042
00043
00044
00045 QFile *debugFile;
00046 QTextStream *debugStream;
00047 QObject *eventWindow;
00048 QStringList EventQ;
00049 QStringList NotifyQ;
00050 QMutex EventQLock;
00051 QString localIp;
00052 QString natIp;
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 SipContainer::SipContainer()
00067 {
00068 killSipThread = false;
00069 CallState = -1;
00070 eventWindow = 0;
00071
00072 sipThread = new SipThread(this);
00073 sipThread->start();
00074 }
00075
00076 SipContainer::~SipContainer()
00077 {
00078 killSipThread = true;
00079 sipThread->wait();
00080 delete sipThread;
00081 }
00082
00083 void SipContainer::PlaceNewCall(QString Mode, QString uri, QString name, bool disableNat)
00084 {
00085 EventQLock.lock();
00086 EventQ.append("PLACECALL");
00087 EventQ.append(Mode);
00088 EventQ.append(uri);
00089 EventQ.append(name);
00090 EventQ.append(disableNat ? "DisableNAT" : "EnableNAT");
00091 EventQLock.unlock();
00092 }
00093
00094 void SipContainer::AnswerRingingCall(QString Mode, bool disableNat)
00095 {
00096 EventQLock.lock();
00097 EventQ.append("ANSWERCALL");
00098 EventQ.append(Mode);
00099 EventQ.append(disableNat ? "DisableNAT" : "EnableNAT");
00100 EventQLock.unlock();
00101 }
00102
00103 void SipContainer::HangupCall()
00104 {
00105 EventQLock.lock();
00106 EventQ.append("HANGUPCALL");
00107 EventQLock.unlock();
00108 }
00109
00110 void SipContainer::ModifyCall(QString audCodec, QString vidCodec)
00111 {
00112 EventQLock.lock();
00113 EventQ.append("MODIFYCALL");
00114 EventQ.append(audCodec);
00115 EventQ.append(vidCodec);
00116 EventQLock.unlock();
00117 }
00118
00119 void SipContainer::UiOpened(QObject *callingApp)
00120 {
00121 EventQLock.lock();
00122 eventWindow = callingApp;
00123 EventQ.append("UIOPENED");
00124 EventQLock.unlock();
00125 }
00126
00127 void SipContainer::UiClosed()
00128 {
00129 EventQLock.lock();
00130 eventWindow = 0;
00131 EventQ.append("UICLOSED");
00132 EventQLock.unlock();
00133 }
00134
00135 void SipContainer::UiWatch(QStrList uriList)
00136 {
00137 QStrListIterator it(uriList);
00138
00139 EventQLock.lock();
00140 EventQ.append("UIWATCH");
00141 for (; it.current(); ++it)
00142 EventQ.append(it.current());
00143 EventQ.append("");
00144 EventQLock.unlock();
00145 }
00146
00147 void SipContainer::UiWatch(QString uri)
00148 {
00149 EventQLock.lock();
00150 EventQ.append("UIWATCH");
00151 EventQ.append(uri);
00152 EventQ.append("");
00153 EventQLock.unlock();
00154 }
00155
00156 void SipContainer::UiStopWatchAll()
00157 {
00158 EventQLock.lock();
00159 EventQ.append("UISTOPWATCHALL");
00160 EventQLock.unlock();
00161 }
00162
00163 QString SipContainer::UiSendIMMessage(QString DestUrl, QString CallId, QString Msg)
00164 {
00165 SipCallId sipCallId;
00166
00167 if (CallId.length() == 0)
00168 {
00169 sipCallId.Generate(localIp);
00170 CallId = sipCallId.string();
00171 }
00172
00173 EventQLock.lock();
00174 EventQ.append("SENDIM");
00175 EventQ.append(DestUrl);
00176 EventQ.append(CallId);
00177 EventQ.append(Msg);
00178 EventQLock.unlock();
00179 return CallId;
00180 }
00181
00182
00183 int SipContainer::GetSipState()
00184 {
00185 int tempState;
00186 EventQLock.lock();
00187 tempState = CallState;
00188 EventQLock.unlock();
00189 return tempState;
00190 }
00191
00192 bool SipContainer::GetNotification(QString &type, QString &url, QString ¶m1, QString ¶m2)
00193 {
00194 bool notifyFlag = false;
00195 EventQLock.lock();
00196
00197 if (!NotifyQ.empty())
00198 {
00199 QStringList::Iterator it;
00200 notifyFlag = true;
00201 it = NotifyQ.begin();
00202 type = *it;
00203 it = NotifyQ.remove(it);
00204 url = *it;
00205 it = NotifyQ.remove(it);
00206 param1 = *it;
00207 it = NotifyQ.remove(it);
00208 param2 = *it;
00209 NotifyQ.remove(it);
00210 }
00211
00212 EventQLock.unlock();
00213 return notifyFlag;
00214 }
00215
00216 void SipContainer::GetRegistrationStatus(bool &Registered, QString &RegisteredTo, QString &RegisteredAs)
00217 {
00218 EventQLock.lock();
00219 Registered = regStatus;
00220 RegisteredTo = regTo;
00221 RegisteredAs = regAs;
00222 EventQLock.unlock();
00223 }
00224
00225 void SipContainer::GetIncomingCaller(QString &u, QString &d, QString &l, bool &a)
00226 {
00227 EventQLock.lock();
00228 u = callerUser;
00229 d = callerName;
00230 l = callerUrl;
00231 a = inAudioOnly;
00232 EventQLock.unlock();
00233 }
00234
00235 void SipContainer::GetSipSDPDetails(QString &ip, int &aport, int &audPay, QString &audCodec, int &dtmfPay, int &vport, int &vidPay, QString &vidCodec, QString &vidRes)
00236 {
00237 EventQLock.lock();
00238 ip = remoteIp;
00239 aport = remoteAudioPort;
00240 vport = remoteVideoPort;
00241 audPay = audioPayload;
00242 audCodec = audioCodec;
00243 dtmfPay = dtmfPayload;
00244 vidPay = videoPayload;
00245 vidCodec = videoCodec;
00246 vidRes = videoRes;
00247 EventQLock.unlock();
00248 }
00249
00250 QString SipContainer::getLocalIpAddress()
00251 {
00252 return localIp;
00253 }
00254
00255 QString SipContainer::getNatIpAddress()
00256 {
00257 return natIp;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 void SipThread::run()
00269 {
00270 SipThreadWorker();
00271 }
00272
00273 void SipThread::SipThreadWorker()
00274 {
00275 FrontEndActive = false;
00276 rnaTimer = -1;
00277 vxmlCallActive = false;
00278 #ifndef WIN32
00279 vxml = new vxmlParser();
00280 Rtp = 0;
00281 #endif
00282
00283
00284 #ifndef WIN32
00285 QString debugFileName = MythContext::GetConfDir() + "/MythPhone/siplog.txt";
00286 debugFile = new QFile(debugFileName);
00287 if (debugFile->open(IO_WriteOnly))
00288 debugStream = new QTextStream (debugFile);
00289 #else
00290 debugStream = 0;
00291 #endif
00292
00293 SipFsm *sipFsm = new SipFsm();
00294
00295 if (sipFsm->SocketOpenedOk())
00296 {
00297 while(!sipContainer->killThread())
00298 {
00299 int OldCallState = CallState;
00300
00301
00302 CheckNetworkEvents(sipFsm);
00303 CheckUIEvents(sipFsm);
00304 CheckRegistrationStatus(sipFsm);
00305 sipFsm->HandleTimerExpiries();
00306 ChangePrimaryCallState(sipFsm, sipFsm->getPrimaryCallState());
00307
00308
00309 #ifndef WIN32
00310 if ((CallState == SIP_ICONNECTING) && (rnaTimer != -1))
00311 {
00312 if (--rnaTimer < 0)
00313 {
00314 rnaTimer = -1;
00315 vxmlCallActive = true;
00316 sipFsm->Answer(true, "", false);
00317 }
00318 }
00319 #endif
00320
00321 ChangePrimaryCallState(sipFsm, sipFsm->getPrimaryCallState());
00322
00323 EventQLock.lock();
00324 if ((OldCallState != CallState) && (eventWindow))
00325 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStateChange));
00326 EventQLock.unlock();
00327 }
00328 }
00329
00330 delete sipFsm;
00331 if (debugStream)
00332 delete debugStream;
00333 if (debugFile)
00334 {
00335 debugFile->close();
00336 delete debugFile;
00337 }
00338 #ifndef WIN32
00339 delete vxml;
00340 #endif
00341 }
00342
00343 void SipThread::CheckUIEvents(SipFsm *sipFsm)
00344 {
00345 QString event;
00346 QStringList::Iterator it;
00347
00348
00349 event = "";
00350 EventQLock.lock();
00351 if (!EventQ.empty())
00352 {
00353 it = EventQ.begin();
00354 event = *it;
00355 EventQ.remove(it);
00356 }
00357 EventQLock.unlock();
00358
00359 if (event == "PLACECALL")
00360 {
00361 EventQLock.lock();
00362 it = EventQ.begin();
00363 QString Mode = *it;
00364 it = EventQ.remove(it);
00365 QString Uri = *it;
00366 it = EventQ.remove(it);
00367 QString Name = *it;
00368 it = EventQ.remove(it);
00369 QString UseNat = *it;
00370 EventQ.remove(it);
00371 EventQLock.unlock();
00372 sipFsm->NewCall(Mode == "AUDIOONLY" ? true : false, Uri, Name, Mode, UseNat == "DisableNAT" ? true : false);
00373 }
00374 else if (event == "ANSWERCALL")
00375 {
00376 EventQLock.lock();
00377 it = EventQ.begin();
00378 QString Mode = *it;
00379 it = EventQ.remove(it);
00380 QString UseNat = *it;
00381 EventQ.remove(it);
00382 EventQLock.unlock();
00383 sipFsm->Answer(Mode == "AUDIOONLY" ? true : false, Mode, UseNat == "DisableNAT" ? true : false);
00384 }
00385 else if (event == "HANGUPCALL")
00386 sipFsm->HangUp();
00387 else if (event == "MODIFYCALL")
00388 {
00389 EventQLock.lock();
00390 it = EventQ.begin();
00391 QString audioCodec = *it;
00392 it = EventQ.remove(it);
00393 QString videoCodec = *it;
00394 EventQ.remove(it);
00395 EventQLock.unlock();
00396 sipFsm->ModifyCall(audioCodec, videoCodec);
00397 }
00398 else if (event == "UIOPENED")
00399 {
00400 sipFsm->StatusChanged("OPEN");
00401 FrontEndActive = true;
00402 }
00403 else if (event == "UICLOSED")
00404 {
00405 sipFsm->StatusChanged("CLOSED");
00406 FrontEndActive = false;
00407 }
00408 else if (event == "UIWATCH")
00409 {
00410 QString uri;
00411 do
00412 {
00413 EventQLock.lock();
00414 it = EventQ.begin();
00415 uri = *it;
00416 EventQ.remove(it);
00417 EventQLock.unlock();
00418 if (uri.length() > 0)
00419 sipFsm->CreateWatcherFsm(uri);
00420 }
00421 while (uri.length() > 0);
00422 }
00423 else if (event == "UISTOPWATCHALL")
00424 sipFsm->StopWatchers();
00425 else if (event == "SENDIM")
00426 {
00427 EventQLock.lock();
00428 it = EventQ.begin();
00429 QString DestUrl = *it;
00430 it = EventQ.remove(it);
00431 QString CallId = *it;
00432 it = EventQ.remove(it);
00433 QString imMsg = *it;
00434 EventQ.remove(it);
00435 EventQLock.unlock();
00436 sipFsm->SendIM(DestUrl, CallId, imMsg);
00437 }
00438
00439 ChangePrimaryCallState(sipFsm, sipFsm->getPrimaryCallState());
00440 }
00441
00442 void SipThread::CheckRegistrationStatus(SipFsm *sipFsm)
00443 {
00444 sipContainer->notifyRegistrationStatus(sipFsm->isRegistered(), sipFsm->registeredTo(),
00445 sipFsm->registeredAs());
00446 }
00447
00448 void SipThread::CheckNetworkEvents(SipFsm *sipFsm)
00449 {
00450
00451 sipFsm->CheckRxEvent();
00452
00453
00454
00455 ChangePrimaryCallState(sipFsm, sipFsm->getPrimaryCallState());
00456 }
00457
00458
00459 void SipThread::ChangePrimaryCallState(SipFsm *sipFsm, int NewState)
00460 {
00461 int OldState = CallState;
00462 CallState = NewState;
00463 if ((CallState == SIP_CONNECTED) && (vxmlCallActive))
00464 sipContainer->notifyCallState(SIP_CONNECTED_VXML);
00465 else
00466 sipContainer->notifyCallState(CallState);
00467
00468 if (OldState != CallState)
00469 {
00470 if (CallState == SIP_IDLE)
00471 {
00472 callerUser = "";
00473 callerName = "";
00474 callerUrl = "";
00475 inAudioOnly = true;
00476 sipContainer->notifyCallerDetails(callerUser, callerName, callerUrl, inAudioOnly);
00477 remoteIp = "0.0.0.0";
00478 remoteAudioPort = -1;
00479 remoteVideoPort = -1;
00480 audioPayload = -1;
00481 dtmfPayload = -1;
00482 videoPayload = -1;
00483 audioCodec = "";
00484 videoCodec = "";
00485 videoRes = "";
00486 sipContainer->notifySDPDetails(remoteIp, remoteAudioPort, audioPayload, audioCodec, dtmfPayload, remoteVideoPort, videoPayload, videoCodec, videoRes);
00487 }
00488
00489 if (CallState == SIP_ICONNECTING)
00490 {
00491
00492 EventQLock.lock();
00493 SipCall *call = sipFsm->MatchCall(sipFsm->getPrimaryCall());
00494 if (call != 0)
00495 {
00496 call->GetIncomingCaller(callerUser, callerName, callerUrl, inAudioOnly);
00497 sipContainer->notifyCallerDetails(callerUser, callerName, callerUrl, inAudioOnly);
00498 }
00499 EventQLock.unlock();
00500
00501 rnaTimer = atoi((const char *)gContext->GetSetting("TimeToAnswer")) * SIP_POLL_PERIOD;
00502 if (rnaTimer == 0)
00503 rnaTimer = -1;
00504 }
00505 else
00506 rnaTimer = -1;
00507
00508
00509 if (CallState == SIP_CONNECTED)
00510 {
00511
00512 EventQLock.lock();
00513 SipCall *call = sipFsm->MatchCall(sipFsm->getPrimaryCall());
00514 if (call != 0)
00515 {
00516 call->GetSdpDetails(remoteIp, remoteAudioPort, audioPayload, audioCodec, dtmfPayload, remoteVideoPort, videoPayload, videoCodec, videoRes);
00517 sipContainer->notifySDPDetails(remoteIp, remoteAudioPort, audioPayload, audioCodec, dtmfPayload, remoteVideoPort, videoPayload, videoCodec, videoRes);
00518
00519 }
00520 EventQLock.unlock();
00521
00522 #ifndef WIN32
00523 if (vxmlCallActive)
00524 {
00525 int lPort = atoi((const char *)gContext->GetSetting("AudioLocalPort"));
00526 int playout = atoi((const char *)gContext->GetSetting("PlayoutAudioCall"));
00527 QString spk = gContext->GetSetting("AudioOutputDevice");
00528 Rtp = new rtp(0, lPort, remoteIp, remoteAudioPort, audioPayload, playout, dtmfPayload, "None", spk, RTP_TX_AUDIO_SILENCE, RTP_RX_AUDIO_DISCARD);
00529 vxml->beginVxmlSession(Rtp, callerName.length() != 0 ? callerName : callerUser);
00530 }
00531 #endif
00532 }
00533
00534 #ifndef WIN32
00535 if ((CallState == SIP_ICONNECTING) && (FrontEndActive == false))
00536 {
00537
00538
00539 SipNotify *notify = new SipNotify();
00540 notify->Display(callerName, callerUrl);
00541 delete notify;
00542 }
00543 #endif
00544
00545 #ifndef WIN32
00546
00547 if ((OldState == SIP_CONNECTED) && vxmlCallActive)
00548 {
00549 vxmlCallActive = false;
00550 vxml->endVxmlSession();
00551 if (Rtp != 0)
00552 delete Rtp;
00553 Rtp = 0;
00554 }
00555 #endif
00556 }
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 SipFsm::SipFsm(QWidget *parent, const char *name)
00568 : QWidget( parent, name )
00569 {
00570 callCount = 0;
00571 primaryCall = -1;
00572 PresenceStatus = "CLOSED";
00573
00574 sipSocket = 0;
00575 localPort = atoi((const char *)gContext->GetSetting("SipLocalPort"));
00576 if (localPort == 0)
00577 localPort = 5060;
00578 localIp = OpenSocket(localPort);
00579 natIp = DetermineNatAddress();
00580 if (natIp.length() == 0)
00581 natIp = localIp;
00582 SipFsm::Debug(SipDebugEvent::SipDebugEv, QString("SIP listening on IP Address ") + localIp + ":" + QString::number(localPort) + " NAT address " + natIp + "\n\n");
00583 cout << "SIP listening on IP Address " << localIp << ":" << localPort << " NAT address " << natIp << endl;
00584
00585
00586 timerList = new SipTimer;
00587
00588
00589 sipRegistrar = new SipRegistrar(this, "volkaerts", localIp, localPort);
00590
00591
00592 bool RegisterWithProxy = gContext->GetNumSetting("SipRegisterWithProxy",1);
00593 sipRegistration = 0;
00594 if (RegisterWithProxy)
00595 {
00596 QString ProxyDNS = gContext->GetSetting("SipProxyName");
00597 QString ProxyUsername = gContext->GetSetting("SipProxyAuthName");
00598 QString ProxyPassword = gContext->GetSetting("SipProxyAuthPassword");
00599 if ((ProxyDNS.length() > 0) && (ProxyUsername.length() > 0) && (ProxyPassword.length() > 0))
00600 {
00601 sipRegistration = new SipRegistration(this, natIp, localPort, ProxyUsername, ProxyPassword, ProxyDNS, 5060);
00602 FsmList.append(sipRegistration);
00603 }
00604 else
00605 cout << "SIP: Cannot register; proxy, username or password not set\n";
00606 }
00607 }
00608
00609
00610 SipFsm::~SipFsm()
00611 {
00612 cout << "Destroying SipFsm object " << endl;
00613 delete sipRegistrar;
00614 if (sipRegistration)
00615 delete sipRegistration;
00616 delete timerList;
00617 CloseSocket();
00618 }
00619
00620 void SipFsm::Debug(SipDebugEvent::Type t, QString dbg)
00621 {
00622 #ifdef WIN32
00623 if (eventWindow)
00624 QApplication::postEvent(eventWindow, new SipDebugEvent(t, dbg));
00625 #else
00626 if ((debugStream) && ((t == SipDebugEvent::SipTraceRxEv) || (t == SipDebugEvent::SipTraceTxEv) || (t == SipDebugEvent::SipDebugEv)))
00627 *debugStream << dbg;
00628 #endif
00629 }
00630
00631 QString SipFsm::OpenSocket(int Port)
00632 {
00633 sipSocket = new QSocketDevice (QSocketDevice::Datagram);
00634 sipSocket->setBlocking(false);
00635
00636 #ifndef WIN32
00637 QString ifName = gContext->GetSetting("SipBindInterface");
00638 struct ifreq ifreq;
00639 strcpy(ifreq.ifr_name, ifName);
00640 if (ioctl(sipSocket->socket(), SIOCGIFADDR, &ifreq) != 0)
00641 {
00642 cerr << "Failed to find network interface " << ifName << endl;
00643 delete sipSocket;
00644 sipSocket = 0;
00645 return "";
00646 }
00647 struct sockaddr_in * sptr = (struct sockaddr_in *)&ifreq.ifr_addr;
00648 QHostAddress myIP;
00649 myIP.setAddress(htonl(sptr->sin_addr.s_addr));
00650 #endif
00651
00652 #ifdef WIN32 // SIOCGIFADDR not supported on Windows
00653 char hostname[100];
00654 HOSTENT FAR *hostAddr;
00655 int ifNum = atoi(gContext->GetSetting("SipBindInterface"));
00656 if ((gethostname(hostname, 100) != 0) || ((hostAddr = gethostbyname(hostname)) == NULL))
00657 {
00658 cerr << "Failed to find network interface " << endl;
00659 delete sipSocket;
00660 sipSocket = 0;
00661 return "";
00662 }
00663 QHostAddress myIP;
00664 for (int ifTotal=0; hostAddr->h_addr_list[ifTotal] != 0; ifTotal++)
00665 ;
00666 if (ifNum >= ifTotal)
00667 ifNum = 0;
00668 myIP.setAddress(htonl(((struct in_addr *)hostAddr->h_addr_list[ifNum])->S_un.S_addr));
00669 #endif
00670
00671 if (!sipSocket->bind(myIP, Port))
00672 {
00673 cerr << "Failed to bind for SIP connection " << myIP.toString() << endl;
00674 delete sipSocket;
00675 sipSocket = 0;
00676 return "";
00677 }
00678 return myIP.toString();
00679 }
00680
00681 void SipFsm::CloseSocket()
00682 {
00683 if (sipSocket)
00684 {
00685 sipSocket->close();
00686 delete sipSocket;
00687 sipSocket = 0;
00688 }
00689 }
00690
00691
00692 QString SipFsm::DetermineNatAddress()
00693 {
00694 QString natIP = "";
00695 QString NatTraversalMethodStr = gContext->GetSetting("NatTraversalMethod");
00696
00697 if (NatTraversalMethodStr == "Manual")
00698 {
00699 natIP = gContext->GetSetting("NatIpAddress");
00700 }
00701
00702
00703
00704 else if (NatTraversalMethodStr == "Web Server")
00705 {
00706
00707 QString natWebServer = gContext->GetSetting("NatIpAddress");
00708 QUrl Url(natWebServer);
00709 QString httpGet = QString("GET %1 HTTP/1.0\r\n"
00710 "User-Agent: MythPhone/1.0\r\n"
00711 "\r\n").arg(Url.path());
00712 QSocketDevice *httpSock = new QSocketDevice(QSocketDevice::Stream);
00713 QHostAddress hostIp;
00714 int port = Url.port();
00715 if (port == -1)
00716 port = 80;
00717
00718
00719 hostIp.setAddress(Url.host());
00720 if (hostIp.toString() != Url.host())
00721 {
00722
00723 struct hostent *h;
00724 h = gethostbyname((const char *)Url.host());
00725 if (h)
00726 hostIp.setAddress(ntohl(*(long *)h->h_addr));
00727 else
00728 {
00729 cout << "SIP: Failed to detect your NAT settings\n";
00730 return "";
00731 }
00732 }
00733
00734
00735 if (httpSock->connect(hostIp, port))
00736 {
00737 int bytesAvail;
00738 if (httpSock->writeBlock(httpGet, httpGet.length()) != -1)
00739 {
00740 while ((bytesAvail = httpSock->waitForMore(3000)) != -1)
00741 {
00742 char *httpResponse = new char[bytesAvail+1];
00743 int len = httpSock->readBlock(httpResponse, bytesAvail);
00744 if (len >= 0)
00745 {
00746
00747
00748 httpResponse[len] = 0;
00749 QString resp(httpResponse);
00750
00751 if (resp.contains("200 OK") && !resp.contains("</body"))
00752 {
00753 delete httpResponse;
00754 continue;
00755 }
00756 QString temp1 = resp.section("<body>", 1, 1);
00757 QString temp2 = temp1.section("</body>", 0, 0);
00758 QString temp3 = temp2.section("Current IP Address: ", 1, 1);
00759
00760 natIP = temp3.stripWhiteSpace();
00761 }
00762 else
00763 cout << "SIP: Got invalid HTML response whilst detecting your NAT settings " << endl;
00764 delete httpResponse;
00765 break;
00766 }
00767 }
00768 else
00769 cerr << "Error sending NAT discovery packet to socket\n";
00770 }
00771 else
00772 cout << "SIP: Could not connect to NAT discovery host " << Url.host() << ":" << Url.port() << endl;
00773 httpSock->close();
00774 delete httpSock;
00775 }
00776
00777 return natIP;
00778 }
00779
00780 void SipFsm::Transmit(QString Msg, QString destIP, int destPort)
00781 {
00782 if ((sipSocket) && (destIP.length()>0))
00783 {
00784 QHostAddress dest;
00785 dest.setAddress(destIP);
00786 SipFsm::Debug(SipDebugEvent::SipTraceTxEv, QDateTime::currentDateTime().toString() + " Sent to " + destIP + ":" + QString::number(destPort) + "...\n" + Msg + "\n");
00787 sipSocket->writeBlock((const char *)Msg, Msg.length(), dest, destPort);
00788 }
00789 else
00790 cerr << "SIP: Cannot transmit SIP message to " << destIP << endl;
00791 }
00792
00793 bool SipFsm::Receive(SipMsg &sipMsg)
00794 {
00795 if (sipSocket)
00796 {
00797 char rxMsg[1501];
00798 int len = sipSocket->readBlock(rxMsg, sizeof(rxMsg)-1);
00799 if (len > 0)
00800 {
00801 rxMsg[len] = 0;
00802 SipFsm::Debug(SipDebugEvent::SipTraceRxEv, QDateTime::currentDateTime().toString() + " Received: Len " + QString::number(len) + "\n" + rxMsg + "\n");
00803 sipMsg.decode(rxMsg);
00804 return true;
00805 }
00806 }
00807 return false;
00808 }
00809
00810 void SipFsm::NewCall(bool audioOnly, QString uri, QString DispName, QString videoMode, bool DisableNat)
00811 {
00812 int cr = -1;
00813 if ((numCalls() == 0) || (primaryCall != -1))
00814 {
00815 SipCall *Call;
00816 primaryCall = cr = callCount++;
00817 Call = new SipCall(localIp, natIp, localPort, cr, this);
00818 FsmList.append(Call);
00819
00820
00821
00822 if ((!uri.contains('@')) && (sipRegistration != 0) && (sipRegistration->isRegistered()))
00823 uri.append(QString("@") + gContext->GetSetting("SipProxyName"));
00824
00825 Call->dialViaProxy(sipRegistration);
00826 Call->to(uri, DispName);
00827 Call->setDisableNat(DisableNat);
00828 Call->setAllowVideo(audioOnly ? false : true);
00829 Call->setVideoResolution(videoMode);
00830 if (Call->FSM(SIP_OUTCALL) == SIP_IDLE)
00831 DestroyFsm(Call);
00832 }
00833 else
00834 cerr << "SIP Call attempt with call in progress\n";
00835 }
00836
00837
00838 void SipFsm::HangUp()
00839 {
00840 SipCall *Call = MatchCall(primaryCall);
00841 if (Call)
00842 if (Call->FSM(SIP_HANGUP) == SIP_IDLE)
00843 DestroyFsm(Call);
00844 }
00845
00846
00847 void SipFsm::ModifyCall(QString audioCodec, QString videoCodec)
00848 {
00849 SipCall *Call = MatchCall(primaryCall);
00850 if (Call)
00851 {
00852 if ((Call->ModifyCodecs(audioCodec, videoCodec)) &&
00853 (Call->FSM(SIP_MODIFYSESSION) == SIP_IDLE))
00854 DestroyFsm(Call);
00855 }
00856 }
00857
00858
00859 void SipFsm::Answer(bool audioOnly, QString videoMode, bool DisableNat)
00860 {
00861 SipCall *Call = MatchCall(primaryCall);
00862 if (Call)
00863 {
00864 if (audioOnly)
00865 Call->setVideoPayload(-1);
00866 else
00867 Call->setVideoResolution(videoMode);
00868 Call->setDisableNat(DisableNat);
00869 if (Call->FSM(SIP_ANSWER) == SIP_IDLE)
00870 DestroyFsm(Call);
00871 }
00872 }
00873
00874
00875 void SipFsm::HandleTimerExpiries()
00876 {
00877 SipFsmBase *Instance;
00878 int Event;
00879 void *Value;
00880 while ((Instance = timerList->Expired(&Event, &Value)) != 0)
00881 {
00882 if (Instance->FSM(Event, 0, Value) == SIP_IDLE)
00883 DestroyFsm(Instance);
00884 }
00885 }
00886
00887
00888 void SipFsm::DestroyFsm(SipFsmBase *Fsm)
00889 {
00890 if (Fsm != 0)
00891 {
00892 timerList->StopAll(Fsm);
00893 if (Fsm->type() == "CALL")
00894 {
00895 if (Fsm->getCallRef() == primaryCall)
00896 primaryCall = -1;
00897 }
00898 FsmList.remove(Fsm);
00899 delete Fsm;
00900 }
00901 }
00902
00903 int SipFsm::getPrimaryCallState()
00904 {
00905 if (primaryCall == -1)
00906 return SIP_IDLE;
00907
00908 SipCall *call = MatchCall(primaryCall);
00909 if (call == 0)
00910 {
00911 primaryCall = -1;
00912 cerr << "Seemed to lose a call here\n";
00913 return SIP_IDLE;
00914 }
00915
00916 return call->getState();
00917 }
00918
00919
00920 void SipFsm::CheckRxEvent()
00921 {
00922 SipMsg sipRcv;
00923 if ((sipSocket->waitForMore(1000/SIP_POLL_PERIOD) > 0) && (Receive(sipRcv)))
00924 {
00925 int Event = MsgToEvent(&sipRcv);
00926
00927
00928
00929 SipFsmBase *fsm = MatchCallId(sipRcv.getCallId());
00930 if (fsm == 0)
00931 {
00932 switch (Event)
00933 {
00934 case SIP_UNKNOWN: fsm = 0; break;
00935 case SIP_REGISTER: fsm = sipRegistrar; break;
00936 case SIP_SUBSCRIBE: fsm = CreateSubscriberFsm(); break;
00937 case SIP_MESSAGE: fsm = CreateIMFsm(); break;
00938 case SIP_OPTIONS: fsm = CreateOptionsFsm(); break;
00939 default: fsm = CreateCallFsm(); break;
00940 }
00941 }
00942
00943
00944 if (fsm)
00945 {
00946 if ((fsm->FSM(Event, &sipRcv)) == SIP_IDLE)
00947 DestroyFsm(fsm);
00948 }
00949 else if (Event != SIP_UNKNOWN)
00950 cerr << "SIP: fsm should not be zero here\n";
00951 }
00952 }
00953
00954
00955 void SipFsm::SetNotification(QString type, QString uri, QString param1, QString param2)
00956 {
00957 EventQLock.lock();
00958 if (eventWindow)
00959 {
00960 NotifyQ.append(type);
00961 NotifyQ.append(uri);
00962 NotifyQ.append(param1);
00963 NotifyQ.append(param2);
00964
00965 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipNotification));
00966 }
00967 EventQLock.unlock();
00968 }
00969
00970
00971 int SipFsm::MsgToEvent(SipMsg *sipMsg)
00972 {
00973 QString Method = sipMsg->getMethod();
00974 if (Method == "INVITE") return SIP_INVITE;
00975 if (Method == "ACK") return SIP_ACK;
00976 if (Method == "BYE") return SIP_BYE;
00977 if (Method == "CANCEL") return SIP_CANCEL;
00978 if (Method == "INVITE") return SIP_INVITE;
00979 if (Method == "REGISTER") return SIP_REGISTER;
00980 if (Method == "SUBSCRIBE") return SIP_SUBSCRIBE;
00981 if (Method == "NOTIFY") return SIP_NOTIFY;
00982 if (Method == "MESSAGE") return SIP_MESSAGE;
00983 if (Method == "INFO") return SIP_INFO;
00984 if (Method == "OPTIONS") return SIP_OPTIONS;
00985
00986 if (Method == "STATUS")
00987 {
00988 QString statusMethod = sipMsg->getCSeqMethod();
00989 if (statusMethod == "REGISTER") return SIP_REGSTATUS;
00990 if (statusMethod == "SUBSCRIBE") return SIP_SUBSTATUS;
00991 if (statusMethod == "NOTIFY") return SIP_NOTSTATUS;
00992 if (statusMethod == "BYE") return SIP_BYESTATUS;
00993 if (statusMethod == "CANCEL") return SIP_CANCELSTATUS;
00994 if (statusMethod == "MESSAGE") return SIP_MESSAGESTATUS;
00995 if (statusMethod == "INFO") return SIP_INFOSTATUS;
00996
00997 if (statusMethod == "INVITE")
00998 {
00999 int statusCode = sipMsg->getStatusCode();
01000 if ((statusCode >= 200) && (statusCode < 300)) return SIP_INVITESTATUS_2xx;
01001 if ((statusCode >= 100) && (statusCode < 200)) return SIP_INVITESTATUS_1xx;
01002 if ((statusCode >= 300) && (statusCode < 700)) return SIP_INVITESTATUS_3456xx;
01003 }
01004 cerr << "SIP: Unknown STATUS method " << statusMethod << endl;
01005 }
01006 else
01007 cerr << "SIP: Unknown method " << Method << endl << sipMsg->string() << endl;
01008 return SIP_UNKNOWN;
01009 }
01010
01011 SipCall *SipFsm::MatchCall(int cr)
01012 {
01013 SipFsmBase *it;
01014 for (it=FsmList.first(); it; it=FsmList.next())
01015 if ((it->type() == "CALL") && (it->getCallRef() == cr))
01016 return (dynamic_cast<SipCall *>(it));
01017 return 0;
01018 }
01019
01020 SipFsmBase *SipFsm::MatchCallId(SipCallId *CallId)
01021 {
01022 SipFsmBase *it;
01023 SipFsmBase *match=0;
01024
01025 if (CallId != 0)
01026 {
01027 for (it=FsmList.first(); it; it=FsmList.next())
01028 {
01029 if (it->callId() == CallId->string())
01030 {
01031 if (match != 0)
01032 cerr << "SIP: Oops; we have two FSMs with the same Call Id\n";
01033 match = it;
01034 }
01035 }
01036 }
01037 return match;
01038 }
01039
01040 SipCall *SipFsm::CreateCallFsm()
01041 {
01042 int cr = callCount++;
01043 SipCall *it = new SipCall(localIp, natIp, localPort, cr, this);
01044 if (primaryCall == -1)
01045 primaryCall = cr;
01046 FsmList.append(it);
01047
01048 it->dialViaProxy(sipRegistration);
01049
01050 return it;
01051 }
01052
01053 SipSubscriber *SipFsm::CreateSubscriberFsm()
01054 {
01055 SipSubscriber *sub = new SipSubscriber(this, natIp, localPort, sipRegistration, PresenceStatus);
01056 FsmList.append(sub);
01057 return sub;
01058 }
01059
01060 SipWatcher *SipFsm::CreateWatcherFsm(QString Url)
01061 {
01062 SipWatcher *watcher = new SipWatcher(this, natIp, localPort, sipRegistration, Url);
01063 FsmList.append(watcher);
01064 return watcher;
01065 }
01066
01067 SipIM *SipFsm::CreateIMFsm(QString Url, QString callIdStr)
01068 {
01069 SipIM *im = new SipIM(this, natIp, localPort, sipRegistration, Url, callIdStr);
01070 FsmList.append(im);
01071 return im;
01072 }
01073
01074 SipOptions *SipFsm::CreateOptionsFsm(QString Url, QString callIdStr)
01075 {
01076 SipOptions *opt = new SipOptions(this, natIp, localPort, sipRegistration, callIdStr);
01077 FsmList.append(opt);
01078 return opt;
01079 }
01080
01081 void SipFsm::StopWatchers()
01082 {
01083 SipFsmBase *it=FsmList.first();
01084 while (it)
01085 {
01086
01087 SipFsmBase *thisone=it;
01088 it=FsmList.next();
01089 if ((thisone->type() == "WATCHER") && (thisone->FSM(SIP_STOPWATCH) == SIP_IDLE))
01090 DestroyFsm(thisone);
01091 }
01092 }
01093
01094 void SipFsm::KickWatcher(SipUrl *Url)
01095 {
01096 SipFsmBase *it=FsmList.first();
01097 while (it)
01098 {
01099
01100 SipFsmBase *thisone=it;
01101 it=FsmList.next();
01102 if ((thisone->type() == "WATCHER") &&
01103 (*thisone->getUrl() == *Url) &&
01104 (thisone->FSM(SIP_KICKWATCH) == SIP_IDLE))
01105 DestroyFsm(thisone);
01106 }
01107 }
01108
01109 void SipFsm::SendIM(QString destUrl, QString CallId, QString imMsg)
01110 {
01111 SipCallId sipCallId;
01112 sipCallId.setValue(CallId);
01113 SipFsmBase *Fsm = MatchCallId(&sipCallId);
01114 if ((Fsm) && (Fsm->type() == "IM"))
01115 {
01116 if ((Fsm->FSM(SIP_USER_MESSAGE, 0, &imMsg)) == SIP_IDLE)
01117 DestroyFsm(Fsm);
01118 }
01119
01120
01121 else if (Fsm == 0)
01122 {
01123 SipIM *imFsm = CreateIMFsm(destUrl, CallId);
01124 if (imFsm)
01125 {
01126 if ((imFsm->FSM(SIP_USER_MESSAGE, 0, &imMsg)) == SIP_IDLE)
01127 DestroyFsm(imFsm);
01128 }
01129 }
01130
01131
01132 else
01133 {
01134 cerr << "SIP: call-id used by non-IM FSM\n";
01135 }
01136 }
01137
01138 int SipFsm::numCalls()
01139 {
01140 SipFsmBase *it;
01141 int cnt=0;
01142 for (it=FsmList.first(); it; it=FsmList.next())
01143 if (it->type() == "CALL")
01144 cnt++;
01145 return cnt;
01146 }
01147
01148 void SipFsm::StatusChanged(char *newStatus)
01149 {
01150 PresenceStatus = newStatus;
01151 SipFsmBase *it;
01152 for (it=FsmList.first(); it; it=FsmList.next())
01153 if (it->type() == "SUBSCRIBER")
01154 it->FSM(SIP_PRESENCE_CHANGE, 0, newStatus);
01155 }
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167 SipFsmBase::SipFsmBase(SipFsm *p)
01168 {
01169 parent = p;
01170 remoteUrl = 0;
01171 toUrl = 0;
01172 contactUrl = 0;
01173 recRouteUrl = 0;
01174 myTag = "abcdef";
01175 remoteTag = "";
01176 remoteEpid = "";
01177 rxedTo = "";
01178 rxedFrom = "";
01179 MyUrl = 0;
01180 MyContactUrl = 0;
01181 rxedTimestamp = -1;
01182 sentAuthenticated = false;
01183 }
01184
01185 SipFsmBase::~SipFsmBase()
01186 {
01187 if (remoteUrl != 0)
01188 delete remoteUrl;
01189 if (toUrl != 0)
01190 delete toUrl;
01191 if (contactUrl != 0)
01192 delete contactUrl;
01193 if (recRouteUrl != 0)
01194 delete recRouteUrl;
01195 if (MyUrl != 0)
01196 delete MyUrl;
01197 if (MyContactUrl != 0)
01198 delete MyContactUrl;
01199
01200 remoteUrl = 0;
01201 toUrl = 0;
01202 contactUrl = 0;
01203 recRouteUrl = 0;
01204 MyUrl = 0;
01205 MyContactUrl = 0;
01206 }
01207
01208 bool SipFsmBase::Retransmit(bool force)
01209 {
01210 if (force || (t1 < 8000))
01211 {
01212 t1 *= 2;
01213 if ((retx.length() > 0) && (retxIp.length() > 0))
01214 {
01215 parent->Transmit(retx, retxIp, retxPort);
01216 return true;
01217 }
01218 }
01219 return false;
01220 }
01221
01222 void SipFsmBase::ParseSipMsg(int Event, SipMsg *sipMsg)
01223 {
01224
01225 remoteTag = (SIP_CMD(Event)) ? sipMsg->getFromTag() : sipMsg->getToTag();
01226 remoteEpid = (SIP_CMD(Event)) ? sipMsg->getFromEpid() : QString("");
01227
01228
01229 if (SIP_CMD(Event))
01230 {
01231 rxedTo = sipMsg->getCompleteTo();
01232 rxedFrom = sipMsg->getCompleteFrom();
01233 RecRoute = sipMsg->getCompleteRR();
01234 Via = sipMsg->getCompleteVia();
01235 CallId = *(sipMsg->getCallId());
01236 viaIp = sipMsg->getViaIp();
01237 viaPort = sipMsg->getViaPort();
01238 rxedTimestamp = sipMsg->getTimestamp();
01239 if (remoteUrl == 0)
01240 remoteUrl = new SipUrl(sipMsg->getFromUrl());
01241 if (toUrl == 0)
01242 toUrl = new SipUrl(sipMsg->getToUrl());
01243 }
01244
01245
01246 SipUrl *s;
01247 if ((s = sipMsg->getContactUrl()) != 0)
01248 {
01249 if (contactUrl)
01250 delete contactUrl;
01251 contactUrl = new SipUrl(s);
01252 }
01253
01254
01255 if ((s = sipMsg->getRecRouteUrl()) != 0)
01256 {
01257 if (recRouteUrl)
01258 delete recRouteUrl;
01259 recRouteUrl = new SipUrl(s);
01260 }
01261 }
01262
01263 void SipFsmBase::BuildSendStatus(int Code, QString Method, int statusCseq, int Option, int statusExpires, QString sdp)
01264 {
01265 if (remoteUrl == 0)
01266 {
01267 cerr << "URL variables not setup\n";
01268 return;
01269 }
01270
01271 SipMsg Status(Method);
01272 Status.addStatusLine(Code);
01273 if (RecRoute.length() > 0)
01274 Status.addRRCopy(RecRoute);
01275 if (Via.length() > 0)
01276 Status.addViaCopy(Via);
01277 Status.addFromCopy(rxedFrom);
01278 Status.addToCopy(rxedTo, myTag);
01279 Status.addCallId(CallId);
01280 Status.addCSeq(statusCseq);
01281 Status.addUserAgent();
01282
01283 if ((Option & SIP_OPT_EXPIRES) && (statusExpires >= 0))
01284 Status.addExpires(statusExpires);
01285 if (Option & SIP_OPT_TIMESTAMP)
01286 Status.addTimestamp(rxedTimestamp);
01287 if (Option & SIP_OPT_ALLOW)
01288 Status.addAllow();
01289 if (Option & SIP_OPT_CONTACT)
01290 Status.addContact(*MyContactUrl);
01291 if (Option & SIP_OPT_SDP)
01292 Status.addContent("application/sdp", sdp);
01293 else
01294 Status.addNullContent();
01295
01296
01297 parent->Transmit(Status.string(), retxIp = viaIp, retxPort = viaPort);
01298
01299 if (((Code >= 200) && (Code <= 299)) && (Method == "INVITE"))
01300 {
01301 retx = Status.string();
01302 t1 = 500;
01303 (parent->Timer())->Start(this, t1, SIP_RETX);
01304 }
01305 }
01306
01307
01308 void SipFsmBase::DebugFsm(int event, int old_state, int new_state)
01309 {
01310 SipFsm::Debug(SipDebugEvent::SipDebugEv, "SIP FSM: Event " + EventtoString(event) + " : "
01311 + StatetoString(old_state) + " -> " + StatetoString(new_state) + "\n");
01312 }
01313
01314
01315 QString SipFsmBase::EventtoString(int Event)
01316 {
01317 switch (Event)
01318 {
01319 case SIP_OUTCALL: return "OUTCALL";
01320 case SIP_REGISTER: return "REGISTER";
01321 case SIP_INVITE: return "INVITE";
01322 case SIP_INVITESTATUS_3456xx: return "INVST-3456xx";
01323 case SIP_INVITESTATUS_2xx: return "INVSTAT-2xx";
01324 case SIP_INVITESTATUS_1xx: return "INVSTAT-1xx";
01325 case SIP_ANSWER: return "ANSWER";
01326 case SIP_ACK: return "ACK";
01327 case SIP_BYE: return "BYE";
01328 case SIP_CANCEL: return "CANCEL";
01329 case SIP_HANGUP: return "HANGUP";
01330 case SIP_BYESTATUS: return "BYESTATUS";
01331 case SIP_CANCELSTATUS: return "CANCSTATUS";
01332 case SIP_RETX: return "RETX";
01333 case SIP_REGISTRAR_TEXP: return "REGITRAR_T";
01334 case SIP_REGSTATUS: return "REG_STATUS";
01335 case SIP_REG_TREGEXP: return "REG_TEXP";
01336 case SIP_SUBSCRIBE: return "SUBSCRIBE";
01337 case SIP_SUBSTATUS: return "SUB_STATUS";
01338 case SIP_NOTIFY: return "NOTIFY";
01339 case SIP_NOTSTATUS: return "NOT_STATUS";
01340 case SIP_PRESENCE_CHANGE: return "PRESENCE_CHNG";
01341 case SIP_SUBSCRIBE_EXPIRE: return "SUB_EXPIRE";
01342 case SIP_WATCH: return "WATCH";
01343 case SIP_STOPWATCH: return "STOPWATCH";
01344 case SIP_MESSAGE: return "MESSAGE";
01345 case SIP_MESSAGESTATUS: return "MESSAGESTATUS";
01346 case SIP_INFO: return "INFO";
01347 case SIP_INFOSTATUS: return "INFOSTATUS";
01348 case SIP_IM_TIMEOUT: return "IM_TIMEOUT";
01349 case SIP_USER_MESSAGE: return "USER_IM";
01350 case SIP_KICKWATCH: return "KICKWATCH";
01351 case SIP_MODIFYSESSION: return "MODIFYSESS";
01352 default:
01353 break;
01354 }
01355 return "Unknown-Event";
01356 }
01357
01358
01359 QString SipFsmBase::StatetoString(int S)
01360 {
01361 switch (S)
01362 {
01363 case SIP_IDLE: return "IDLE";
01364 case SIP_OCONNECTING1: return "OCONNECT1";
01365 case SIP_OCONNECTING2: return "OCONNECT2";
01366 case SIP_ICONNECTING: return "ICONNECT";
01367 case SIP_ICONNECTING_WAITACK: return "ICONNECT_WA";
01368 case SIP_CONNECTED: return "CONNECTED";
01369 case SIP_DISCONNECTING: return "DISCONNECT ";
01370 case SIP_CONNECTED_VXML: return "CONNECT-VXML";
01371 case SIP_SUB_SUBSCRIBED: return "SUB_SUBSCRIBED";
01372 case SIP_WATCH_TRYING: return "WTCH_TRYING";
01373 case SIP_WATCH_ACTIVE: return "WTCH_ACTIVE";
01374 case SIP_WATCH_STOPPING: return "WTCH_STOPPING";
01375 case SIP_WATCH_HOLDOFF: return "WTCH_HOLDDOFF";
01376 case SIP_IM_ACTIVE: return "IM_ACTIVE";
01377 case SIP_CONNECT_MODIFYING1: return "CONN_MOD1";
01378 case SIP_CONNECT_MODIFYING2: return "CONN_MOD2";
01379
01380 default:
01381 break;
01382 }
01383 return "Unknown-State";
01384 }
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 SipCall::SipCall(QString localIp, QString natIp, int localPort, int n, SipFsm *par) : SipFsmBase(par)
01398 {
01399 callRef = n;
01400 sipLocalIP = localIp;
01401 sipNatIP = natIp;
01402 sipLocalPort = localPort;
01403 initialise();
01404 }
01405
01406 SipCall::~SipCall()
01407 {
01408 }
01409
01410
01411 void SipCall::initialise()
01412 {
01413
01414
01415 myDisplayName = gContext->GetSetting("MySipName");
01416 sipUsername = "MythPhone";
01417
01418
01419 sipAudioRtpPort = atoi((const char *)gContext->GetSetting("AudioLocalPort"));
01420 sipVideoRtpPort = atoi((const char *)gContext->GetSetting("VideoLocalPort"));
01421
01422 sipRtpPacketisation = 20;
01423 State = SIP_IDLE;
01424 remoteAudioPort = 0;
01425 remoteVideoPort = 0;
01426 remoteIp = "";
01427 audioPayloadIdx = -1;
01428 videoPayload = -1;
01429 dtmfPayload = -1;
01430 remoteIp = "";
01431 allowVideo = true;
01432 disableNat = false;
01433 rxVideoResolution = "CIF";
01434 txVideoResolution = "CIF";
01435 viaRegProxy = 0;
01436 ModifyAudioCodec = -1;
01437
01438 MyUrl = 0;
01439 MyContactUrl = 0;
01440
01441
01442 CodecList[0].Payload = 0;
01443 CodecList[0].Encoding = "PCMU";
01444 int n=0;
01445 QString CodecListString = gContext->GetSetting("CodecPriorityList");
01446 while ((CodecListString.length() > 0) && (n < MAX_AUDIO_CODECS-1))
01447 {
01448 int sep = CodecListString.find(';');
01449 QString CodecStr = CodecListString;
01450 if (sep != -1)
01451 CodecStr = CodecListString.left(sep);
01452 if (CodecStr == "G.711u")
01453 {
01454 CodecList[n].Payload = 0;
01455 CodecList[n++].Encoding = "PCMU";
01456 }
01457 else if (CodecStr == "G.711a")
01458 {
01459 CodecList[n].Payload = 8;
01460 CodecList[n++].Encoding = "PCMA";
01461 }
01462 #ifdef VA_G729
01463 else if (CodecStr == "G.729")
01464 {
01465 CodecList[n].Payload = 18;
01466 CodecList[n++].Encoding = "G729";
01467 }
01468 #endif
01469 else if (CodecStr == "GSM")
01470 {
01471 CodecList[n].Payload = 3;
01472 CodecList[n++].Encoding = "GSM";
01473 }
01474 else
01475 cout << "Unknown codec " << CodecStr << " in Codec Priority List\n";
01476 if (sep != -1)
01477 {
01478 QString tempStr = CodecListString.mid(sep+1);
01479 CodecListString = tempStr;
01480 }
01481 else
01482 break;
01483 }
01484 CodecList[n].Payload = -1;
01485 }
01486
01487
01488 bool SipCall::ModifyCodecs(QString audioCodec, QString videoCodec)
01489 {
01490 ModifyAudioCodec = -1;
01491 for (int n=0; n<MAX_AUDIO_CODECS; n++)
01492 {
01493 if (CodecList[n].Encoding == audioCodec)
01494 ModifyAudioCodec = n;
01495 }
01496
01497 if (ModifyAudioCodec == -1)
01498 return false;
01499
01500 if (videoCodec == "H.263")
01501 allowVideo = true;
01502 else if (videoCodec != "UNCHANGED")
01503 allowVideo = false;
01504
01505 return true;
01506 }
01507
01508
01509 int SipCall::FSM(int Event, SipMsg *sipMsg, void *Value)
01510 {
01511 (void)Value;
01512 int oldState = State;
01513
01514
01515 if (sipMsg != 0)
01516 ParseSipMsg(Event, sipMsg);
01517
01518 if (State == SIP_IDLE)
01519 {
01520 if (UseNat())
01521 sipLocalIP = sipNatIP;
01522 MyContactUrl = new SipUrl(myDisplayName, sipUsername, sipLocalIP, sipLocalPort);
01523 if (viaRegProxy == 0)
01524 MyUrl = new SipUrl(myDisplayName, sipUsername, sipLocalIP, sipLocalPort);
01525 else
01526 MyUrl = new SipUrl(myDisplayName, viaRegProxy->registeredAs(), viaRegProxy->registeredTo(), viaRegProxy->registeredPort());
01527 }
01528
01529 switch(Event | State)
01530 {
01531 case SIP_IDLE_BYE:
01532 BuildSendStatus(481, "BYE", sipMsg->getCSeqValue());
01533 State = SIP_IDLE;
01534 break;
01535 case SIP_IDLE_INVITESTATUS_1xx:
01536 case SIP_IDLE_INVITESTATUS_2xx:
01537 case SIP_IDLE_INVITESTATUS_3456:
01538
01539 if (sipMsg->getViaIp() == sipLocalIP)
01540 {
01541 ForwardMessage(sipMsg);
01542 State = SIP_IDLE;
01543 }
01544 break;
01545 case SIP_IDLE_OUTCALL:
01546 cseq = 1;
01547 remoteUrl = new SipUrl(DestinationUri, "");
01548 if ((remoteUrl->getHostIp()).length() == 0)
01549 {
01550 cout << "SIP: Tried to call " << DestinationUri << " but can't get destination IP address\n";
01551 State = SIP_IDLE;
01552 break;
01553 }
01554
01555 #ifdef SIPREGISTRAR
01556
01557 if ((remoteUrl->getHost() == "volkaerts") &&
01558 (!(parent->getRegistrar())->getRegisteredContact(remoteUrl)))
01559 {
01560 cout << DestinationUri << " is not registered here\n";
01561 break;
01562 }
01563 #endif
01564 BuildSendInvite(0);
01565 State = SIP_OCONNECTING1;
01566 break;
01567 case SIP_IDLE_INVITE:
01568 cseq = sipMsg->getCSeqValue();
01569 #ifdef SIPREGISTRAR
01570 if ((toUrl->getUser() == sipUsername)) && (toUrl->getHost() == "Volkaerts"))
01571 #endif
01572 {
01573 if (parent->numCalls() > 1)
01574 {
01575 BuildSendStatus(486, "INVITE", sipMsg->getCSeqValue());
01576 State = SIP_DISCONNECTING;
01577 }
01578 else
01579 {
01580 GetSDPInfo(sipMsg);
01581 if (audioPayloadIdx != -1)
01582 {
01583 AlertUser(sipMsg);
01584 BuildSendStatus(100, "INVITE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT | SIP_OPT_TIMESTAMP);
01585 BuildSendStatus(180, "INVITE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
01586 State = SIP_ICONNECTING;
01587 }
01588 else
01589 {
01590 BuildSendStatus(488, "INVITE", sipMsg->getCSeqValue());
01591 State = SIP_DISCONNECTING;
01592 }
01593 }
01594 }
01595
01596 #ifdef SIPREGISTRAR
01597
01598 else if ((toUrl->getHost() == "volkaerts") && ((parent->getRegistrar())->getRegisteredContact(toUrl)))
01599 {
01600 ForwardMessage(sipMsg);
01601 State = SIP_IDLE;
01602 }
01603
01604
01605 else
01606 {
01607 BuildSendStatus(404, "INVITE", sipMsg->getCSeqValue());
01608 State = SIP_DISCONNECTING;
01609 }
01610 #endif
01611 break;
01612 case SIP_OCONNECTING1_INVITESTATUS_1xx:
01613 (parent->Timer())->Stop(this, SIP_RETX);
01614 if ((sipMsg->getStatusCode() == 180) && (eventWindow))
01615 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipRingbackTone));
01616 parent->SetNotification("CALLSTATUS", "", QString::number(sipMsg->getStatusCode()), sipMsg->getReasonPhrase());
01617 State = SIP_OCONNECTING2;
01618 break;
01619 case SIP_OCONNECTING1_INVITESTATUS_3456:
01620 (parent->Timer())->Stop(this, SIP_RETX);
01621 parent->SetNotification("CALLSTATUS", "", QString::number(sipMsg->getStatusCode()), sipMsg->getReasonPhrase());
01622
01623 case SIP_OCONNECTING2_INVITESTATUS_3456:
01624 if (((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401)) &&
01625 (viaRegProxy != 0) && (viaRegProxy->isRegistered()))
01626 {
01627 if (!sentAuthenticated)
01628 {
01629 BuildSendAck();
01630 BuildSendInvite(sipMsg);
01631 State = SIP_OCONNECTING1;
01632 }
01633 }
01634 else
01635 {
01636 BuildSendAck();
01637 State = SIP_IDLE;
01638 }
01639 break;
01640
01641 case SIP_OCONNECTING2_INVITESTATUS_1xx:
01642 if ((sipMsg->getStatusCode() == 180) && (eventWindow))
01643 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipRingbackTone));
01644 parent->SetNotification("CALLSTATUS", "", QString::number(sipMsg->getStatusCode()), sipMsg->getReasonPhrase());
01645 break;
01646
01647 case SIP_OCONNECTING1_INVITESTATUS_2xx:
01648 (parent->Timer())->Stop(this, SIP_RETX);
01649
01650 case SIP_OCONNECTING2_INVITESTATUS_2xx:
01651 GetSDPInfo(sipMsg);
01652 if (audioPayloadIdx != -1)
01653 {
01654 BuildSendAck();
01655 if (eventWindow)
01656 {
01657 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01658 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStartMedia,
01659 remoteIp,
01660 CodecList[audioPayloadIdx].Payload,
01661 CodecList[audioPayloadIdx].Encoding,
01662 videoPayload,
01663 (videoPayload == 34 ? "H263" : ""),
01664 dtmfPayload,
01665 remoteAudioPort,
01666 remoteVideoPort,
01667 rxVideoResolution));
01668 }
01669 State = SIP_CONNECTED;
01670 }
01671 else
01672 {
01673 cerr << "2xx STATUS did not contain a valid Audio codec\n";
01674 BuildSendAck();
01675 BuildSendBye(0);
01676 if (eventWindow)
01677 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01678 State = SIP_DISCONNECTING;
01679 }
01680 break;
01681 case SIP_OCONNECTING1_INVITE:
01682
01683 (parent->Timer())->Stop(this, SIP_RETX);
01684 BuildSendCancel(0);
01685 if (eventWindow)
01686 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01687 State = SIP_DISCONNECTING;
01688 break;
01689 case SIP_OCONNECTING1_HANGUP:
01690 (parent->Timer())->Stop(this, SIP_RETX);
01691 BuildSendCancel(0);
01692 if (eventWindow)
01693 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01694 State = SIP_IDLE;
01695 break;
01696 case SIP_OCONNECTING1_RETX:
01697 if (Retransmit(false))
01698 (parent->Timer())->Start(this, t1, SIP_RETX);
01699 else
01700 {
01701 if (eventWindow)
01702 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01703 State = SIP_IDLE;
01704 }
01705 break;
01706 case SIP_OCONNECTING2_HANGUP:
01707 BuildSendCancel(0);
01708 if (eventWindow)
01709 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseRingbackTone));
01710 State = SIP_DISCONNECTING;
01711 break;
01712 case SIP_ICONNECTING_INVITE:
01713 BuildSendStatus(180, "INVITE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
01714 break;
01715 case SIP_ICONNECTING_ANSWER:
01716 BuildSendStatus(200, "INVITE", cseq, SIP_OPT_SDP | SIP_OPT_CONTACT, -1, BuildSdpResponse());
01717 if (eventWindow)
01718 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseAlertUser));
01719 State = SIP_ICONNECTING_WAITACK;
01720 break;
01721 case SIP_ICONNECTING_CANCEL:
01722 if (eventWindow)
01723 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipCeaseAlertUser));
01724 case SIP_ICONNECTING_WAITACK_CANCEL:
01725 BuildSendStatus(200, "CANCEL", sipMsg->getCSeqValue());
01726 State = SIP_IDLE;
01727 break;
01728 case SIP_ICONNECTING_WAITACK_ACK:
01729 (parent->Timer())->Stop(this, SIP_RETX);
01730 if (eventWindow)
01731 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStartMedia,
01732 remoteIp,
01733 CodecList[audioPayloadIdx].Payload,
01734 CodecList[audioPayloadIdx].Encoding,
01735 videoPayload,
01736 (videoPayload == 34 ? "H263" : ""),
01737 dtmfPayload,
01738 remoteAudioPort,
01739 remoteVideoPort,
01740 rxVideoResolution));
01741 State = SIP_CONNECTED;
01742 break;
01743 case SIP_ICONNECTING_WAITACK_RETX:
01744 if (Retransmit(false))
01745 (parent->Timer())->Start(this, t1, SIP_RETX);
01746 else
01747 State = SIP_IDLE;
01748 break;
01749 case SIP_ICONNECTING_WAITACK_HANGUP:
01750 BuildSendBye(0);
01751 State = SIP_DISCONNECTING;
01752 break;
01753 case SIP_CONNECTED_ACK:
01754 break;
01755 case SIP_CONNECTED_INVITESTATUS_2xx:
01756 Retransmit(true);
01757 break;
01758 case SIP_CONNECTED_RETX:
01759 if (Retransmit(false))
01760 (parent->Timer())->Start(this, t1, SIP_RETX);
01761 else
01762 {
01763 State = SIP_IDLE;
01764 if (eventWindow)
01765 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStopMedia));
01766 }
01767 break;
01768 case SIP_CONNECTED_BYE:
01769 (parent->Timer())->Stop(this, SIP_RETX);
01770 if (sipMsg->getCSeqValue() > cseq)
01771 {
01772 cseq = sipMsg->getCSeqValue();
01773 BuildSendStatus(200, "BYE", cseq);
01774 if (eventWindow)
01775 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStopMedia));
01776 State = SIP_IDLE;
01777 }
01778 else
01779 BuildSendStatus(400, "BYE", sipMsg->getCSeqValue());
01780 break;
01781 case SIP_CONNECTED_HANGUP:
01782 BuildSendBye(0);
01783 if (eventWindow)
01784 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStopMedia));
01785 State = SIP_DISCONNECTING;
01786 break;
01787 case SIP_DISCONNECTING_ACK:
01788 (parent->Timer())->Stop(this, SIP_RETX);
01789 State = SIP_IDLE;
01790 break;
01791 case SIP_DISCONNECTING_RETX:
01792 if (Retransmit(false))
01793 (parent->Timer())->Start(this, t1, SIP_RETX);
01794 else
01795 State = SIP_IDLE;
01796 break;
01797 case SIP_DISCONNECTING_CANCEL:
01798 (parent->Timer())->Stop(this, SIP_RETX);
01799 BuildSendStatus(200, "CANCEL", sipMsg->getCSeqValue());
01800 State = SIP_IDLE;
01801 break;
01802 case SIP_DISCONNECTING_BYESTATUS:
01803 (parent->Timer())->Stop(this, SIP_RETX);
01804 if (((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401)) &&
01805 (viaRegProxy != 0) && (viaRegProxy->isRegistered()))
01806 {
01807 if (!sentAuthenticated)
01808 BuildSendBye(sipMsg);
01809 }
01810 else
01811 State = SIP_IDLE;
01812 break;
01813 case SIP_DISCONNECTING_CANCELSTATUS:
01814 (parent->Timer())->Stop(this, SIP_RETX);
01815 if (((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401)) &&
01816 (viaRegProxy != 0) && (viaRegProxy->isRegistered()))
01817 {
01818 if (!sentAuthenticated)
01819 BuildSendCancel(sipMsg);
01820 }
01821 else
01822 State = SIP_IDLE;
01823 break;
01824 case SIP_DISCONNECTING_BYE:
01825 (parent->Timer())->Stop(this, SIP_RETX);
01826 BuildSendStatus(200, "BYE", sipMsg->getCSeqValue());
01827 State = SIP_IDLE;
01828 break;
01829
01830
01831 case SIP_CONNECTED_MODIFYSESSION:
01832 BuildSendReInvite(0);
01833 State = SIP_CONNECT_MODIFYING1;
01834 break;
01835 case SIP_CONNECTED_INVITE:
01836 GetSDPInfo(sipMsg);
01837 if (audioPayloadIdx != -1)
01838 {
01839 BuildSendStatus(200, "INVITE", cseq, SIP_OPT_SDP | SIP_OPT_CONTACT, -1, BuildSdpResponse());
01840 State = SIP_CONNECT_MODIFYING2;
01841 }
01842 else
01843 {
01844 BuildSendStatus(488, "INVITE", sipMsg->getCSeqValue());
01845 State = SIP_CONNECTED;
01846 }
01847 break;
01848 case SIP_CONNMOD1_INVITESTATUS_1xx:
01849 break;
01850 case SIP_CONNMOD1_INVITESTATUS_2xx:
01851 (parent->Timer())->Stop(this, SIP_RETX);
01852 GetSDPInfo(sipMsg);
01853 if (audioPayloadIdx != -1)
01854 {
01855 BuildSendAck();
01856 if (eventWindow)
01857 {
01858 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipChangeMedia,
01859 remoteIp,
01860 CodecList[audioPayloadIdx].Payload,
01861 CodecList[audioPayloadIdx].Encoding,
01862 videoPayload,
01863 (videoPayload == 34 ? "H263" : ""),
01864 dtmfPayload,
01865 remoteAudioPort,
01866 remoteVideoPort,
01867 rxVideoResolution));
01868 }
01869 State = SIP_CONNECTED;
01870 }
01871 else
01872 {
01873 cerr << "2xx STATUS on reINVITE did not contain a valid Audio codec\n";
01874 BuildSendAck();
01875 State = SIP_CONNECTED;
01876 }
01877 break;
01878 case SIP_CONNMOD1_INVITESTATUS_3456:
01879 (parent->Timer())->Stop(this, SIP_RETX);
01880 if (((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401)) &&
01881 (viaRegProxy != 0) && (viaRegProxy->isRegistered()))
01882 {
01883 if (!sentAuthenticated)
01884 {
01885 BuildSendAck();
01886 BuildSendReInvite(sipMsg);
01887 }
01888 }
01889 else
01890 {
01891 BuildSendAck();
01892 State = SIP_CONNECTED;
01893 }
01894 break;
01895 case SIP_CONNMOD1_RETX:
01896 if (Retransmit(false))
01897 (parent->Timer())->Start(this, t1, SIP_RETX);
01898 else
01899 {
01900 if (eventWindow)
01901 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStopMedia));
01902 State = SIP_IDLE;
01903 }
01904 break;
01905 case SIP_CONNMOD2_RETX:
01906 if (Retransmit(false))
01907 (parent->Timer())->Start(this, t1, SIP_RETX);
01908 else
01909 {
01910 if (eventWindow)
01911 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipStopMedia));
01912 State = SIP_IDLE;
01913 }
01914 break;
01915 case SIP_CONNMOD2_ACK:
01916 (parent->Timer())->Stop(this, SIP_RETX);
01917 if (eventWindow)
01918 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipChangeMedia,
01919 remoteIp,
01920 CodecList[audioPayloadIdx].Payload,
01921 CodecList[audioPayloadIdx].Encoding,
01922 videoPayload,
01923 (videoPayload == 34 ? "H263" : ""),
01924 dtmfPayload,
01925 remoteAudioPort,
01926 remoteVideoPort,
01927 rxVideoResolution));
01928 State = SIP_CONNECTED;
01929 break;
01930
01931
01932 default:
01933 SipFsm::Debug(SipDebugEvent::SipErrorEv, "SIP CALL FSM Error; received " + EventtoString(Event) + " in state " + StatetoString(State) + "\n\n");
01934 break;
01935 }
01936
01937 DebugFsm(Event, oldState, State);
01938 return State;
01939 }
01940
01941 bool SipCall::UseNat()
01942 {
01943 return !disableNat;
01944 }
01945
01946
01947 void SipCall::BuildSendInvite(SipMsg *authMsg)
01948 {
01949 if (authMsg == 0)
01950 CallId.Generate(sipLocalIP);
01951
01952 SipMsg Invite("INVITE");
01953 Invite.addRequestLine(*remoteUrl);
01954 Invite.addVia(sipLocalIP, sipLocalPort);
01955 Invite.addFrom(*MyUrl, myTag);
01956 Invite.addTo(*remoteUrl);
01957 Invite.addCallId(CallId);
01958 Invite.addCSeq(++cseq);
01959 Invite.addUserAgent();
01960
01961 if (authMsg)
01962 {
01963 if (authMsg->getAuthMethod() == "Digest")
01964 Invite.addAuthorization(authMsg->getAuthMethod(), viaRegProxy->registeredAs(), viaRegProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), remoteUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
01965 else
01966 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
01967 sentAuthenticated = true;
01968 }
01969 else
01970 sentAuthenticated = false;
01971
01972
01973 Invite.addContact(*MyContactUrl);
01974 addSdpToInvite(Invite, allowVideo);
01975
01976 parent->Transmit(Invite.string(), retxIp = remoteUrl->getHostIp(), retxPort = remoteUrl->getPort());
01977 retx = Invite.string();
01978 t1 = 500;
01979 (parent->Timer())->Start(this, t1, SIP_RETX);
01980 }
01981
01982
01983
01984 void SipCall::BuildSendReInvite(SipMsg *authMsg)
01985 {
01986 SipMsg Invite("INVITE");
01987 Invite.addRequestLine(*remoteUrl);
01988 Invite.addVia(sipLocalIP, sipLocalPort);
01989 Invite.addFrom(*MyUrl, myTag);
01990 Invite.addTo(*remoteUrl);
01991 Invite.addCallId(CallId);
01992 Invite.addCSeq(++cseq);
01993 Invite.addUserAgent();
01994
01995 if (authMsg)
01996 {
01997 if (authMsg->getAuthMethod() == "Digest")
01998 Invite.addAuthorization(authMsg->getAuthMethod(), viaRegProxy->registeredAs(), viaRegProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), remoteUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
01999 else
02000 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
02001 sentAuthenticated = true;
02002 }
02003 else
02004 sentAuthenticated = false;
02005
02006
02007 Invite.addContact(*MyContactUrl);
02008 addSdpToInvite(Invite, allowVideo, ModifyAudioCodec);
02009
02010 parent->Transmit(Invite.string(), retxIp = remoteUrl->getHostIp(), retxPort = remoteUrl->getPort());
02011 retx = Invite.string();
02012 t1 = 500;
02013 (parent->Timer())->Start(this, t1, SIP_RETX);
02014 }
02015
02016
02017
02018 void SipCall::ForwardMessage(SipMsg *msg)
02019 {
02020 QString toIp;
02021 int toPort;
02022
02023 if (msg->getMethod() != "STATUS")
02024 {
02025 msg->insertVia(sipLocalIP, sipLocalPort);
02026 toIp = toUrl->getHostIp();
02027 toPort = toUrl->getPort();
02028 }
02029 else
02030 {
02031 msg->removeVia();
02032 toIp = msg->getViaIp();
02033 toPort = msg->getViaPort();
02034 }
02035 parent->Transmit(msg->string(), toIp, toPort);
02036 }
02037
02038
02039
02040 void SipCall::BuildSendAck()
02041 {
02042 if ((MyUrl == 0) || (remoteUrl == 0))
02043 {
02044 cerr << "URL variables not setup\n";
02045 return;
02046 }
02047
02048 SipMsg Ack("ACK");
02049 Ack.addRequestLine(*remoteUrl);
02050 Ack.addVia(sipLocalIP, sipLocalPort);
02051 Ack.addFrom(*MyUrl, myTag);
02052 Ack.addTo(*remoteUrl, remoteTag);
02053 Ack.addCallId(CallId);
02054 Ack.addCSeq(cseq);
02055 Ack.addUserAgent();
02056 Ack.addNullContent();
02057
02058
02059
02060 parent->Transmit(Ack.string(), retxIp = remoteUrl->getHostIp(), retxPort = remoteUrl->getPort());
02061 retx = Ack.string();
02062 }
02063
02064
02065 void SipCall::BuildSendCancel(SipMsg *authMsg)
02066 {
02067 if ((MyUrl == 0) || (remoteUrl == 0))
02068 {
02069 cerr << "URL variables not setup\n";
02070 return;
02071 }
02072
02073 SipMsg Cancel("CANCEL");
02074 Cancel.addRequestLine(*remoteUrl);
02075 Cancel.addVia(sipLocalIP, sipLocalPort);
02076 Cancel.addTo(*remoteUrl, remoteTag);
02077 Cancel.addFrom(*MyUrl, myTag);
02078 Cancel.addCallId(CallId);
02079 Cancel.addCSeq(cseq);
02080 Cancel.addUserAgent();
02081
02082 if (authMsg)
02083 {
02084 if (authMsg->getAuthMethod() == "Digest")
02085 Cancel.addAuthorization(authMsg->getAuthMethod(), viaRegProxy->registeredAs(), viaRegProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), remoteUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
02086 else
02087 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
02088 sentAuthenticated = true;
02089 }
02090 else
02091 sentAuthenticated = false;
02092
02093 Cancel.addNullContent();
02094
02095
02096 if (recRouteUrl)
02097 parent->Transmit(Cancel.string(), retxIp = recRouteUrl->getHostIp(), retxPort = recRouteUrl->getPort());
02098 else if (contactUrl)
02099 parent->Transmit(Cancel.string(), retxIp = contactUrl->getHostIp(), retxPort = contactUrl->getPort());
02100 else
02101 parent->Transmit(Cancel.string(), retxIp = remoteUrl->getHostIp(), retxPort = remoteUrl->getPort());
02102 retx = Cancel.string();
02103 t1 = 500;
02104 (parent->Timer())->Start(this, t1, SIP_RETX);
02105 }
02106
02107
02108 void SipCall::BuildSendBye(SipMsg *authMsg)
02109 {
02110 if (remoteUrl == 0)
02111 {
02112 cerr << "URL variables not setup\n";
02113 return;
02114 }
02115
02116 SipMsg Bye("BYE");
02117 Bye.addRequestLine(*remoteUrl);
02118 Bye.addVia(sipLocalIP, sipLocalPort);
02119 if (rxedFrom.length() > 0)
02120 {
02121 Bye.addFromCopy(rxedFrom);
02122 Bye.addToCopy(rxedTo, myTag);
02123 }
02124 else
02125 {
02126 Bye.addFrom(*MyUrl, myTag);
02127 Bye.addTo(*remoteUrl, remoteTag);
02128 }
02129 Bye.addCallId(CallId);
02130 Bye.addCSeq(++cseq);
02131 Bye.addUserAgent();
02132
02133 if (authMsg)
02134 {
02135 if (authMsg->getAuthMethod() == "Digest")
02136 Bye.addAuthorization(authMsg->getAuthMethod(), viaRegProxy->registeredAs(), viaRegProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), remoteUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
02137 else
02138 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
02139 sentAuthenticated = true;
02140 }
02141 else
02142 sentAuthenticated = false;
02143
02144 Bye.addNullContent();
02145
02146
02147 if (recRouteUrl)
02148 parent->Transmit(Bye.string(), retxIp = recRouteUrl->getHostIp(), retxPort = recRouteUrl->getPort());
02149 else if (contactUrl)
02150 parent->Transmit(Bye.string(), retxIp = contactUrl->getHostIp(), retxPort = contactUrl->getPort());
02151 else
02152 parent->Transmit(Bye.string(), retxIp = remoteUrl->getHostIp(), retxPort = remoteUrl->getPort());
02153 retx = Bye.string();
02154 t1 = 500;
02155 (parent->Timer())->Start(this, t1, SIP_RETX);
02156 }
02157
02158 void SipCall::AlertUser(SipMsg *rxMsg)
02159 {
02160
02161
02162
02163
02164 if (rxMsg != 0)
02165 {
02166 SipUrl *from = rxMsg->getFromUrl();
02167
02168 if (from)
02169 {
02170 CallersUserid = from->getUser();
02171 if ((viaRegProxy) && (viaRegProxy->registeredTo() == from->getHost()))
02172 CallerUrl = from->getUser();
02173 else
02174 {
02175 CallerUrl = from->getUser() + "@" + from->getHost();
02176 if (from->getPort() != 5060)
02177 CallerUrl += ":" + QString::number(from->getPort());
02178 }
02179 CallersDisplayName = from->getDisplay();
02180
02181 if (eventWindow)
02182 QApplication::postEvent(eventWindow, new SipEvent(SipEvent::SipAlertUser,
02183 CallersUserid,
02184 CallerUrl,
02185 CallersDisplayName,
02186 videoPayload == -1));
02187 }
02188 else
02189 cerr << "What no from in INVITE? It is invalid then.\n";
02190 }
02191 else
02192 cerr << "What no INVITE? How did we get here then?\n";
02193 }
02194
02195 void SipCall::GetSDPInfo(SipMsg *sipMsg)
02196 {
02197 audioPayloadIdx = -1;
02198 videoPayload = -1;
02199 dtmfPayload = -1;
02200 remoteAudioPort = 0;
02201 remoteVideoPort = 0;
02202 rxVideoResolution = "AUDIOONLY";
02203
02204 SipSdp *Sdp = sipMsg->getSdp();
02205 if (Sdp != 0)
02206 {
02207 remoteIp = Sdp->getMediaIP();
02208 remoteAudioPort = Sdp->getAudioPort();
02209 remoteVideoPort = Sdp->getVideoPort();
02210
02211
02212 QPtrList<sdpCodec> *audioCodecs = Sdp->getAudioCodecList();
02213 sdpCodec *c;
02214 if (audioCodecs)
02215 {
02216 for (int n=0; (n<MAX_AUDIO_CODECS) && (CodecList[n].Payload != -1) &&
02217 (audioPayloadIdx == -1); n++)
02218 {
02219 for (c=audioCodecs->first(); c; c=audioCodecs->next())
02220 {
02221 if (CodecList[n].Payload == c->intValue())
02222 audioPayloadIdx = n;
02223
02224
02225
02226 }
02227 }
02228
02229
02230 for (c=audioCodecs->first(); c; c=audioCodecs->next())
02231 {
02232 if (c->strValue() == "telephone-event/8000")
02233 dtmfPayload = c->intValue();
02234 }
02235 }
02236
02237
02238 QPtrList<sdpCodec> *videoCodecs = Sdp->getVideoCodecList();
02239 if (videoCodecs)
02240 {
02241 for (c=videoCodecs->first(); c; c=videoCodecs->next())
02242 {
02243 if ((c->intValue() == 34) && (c->strValue() == "H263/90000"))
02244 {
02245 videoPayload = c->intValue();
02246 rxVideoResolution = (c->fmtValue()).section('=', 0, 0);
02247 break;
02248 }
02249 }
02250 }
02251
02252 SipFsm::Debug(SipDebugEvent::SipDebugEv, "SDP contains IP " + remoteIp + " A-Port " + QString::number(remoteAudioPort) + " V-Port " + QString::number(remoteVideoPort) + " Audio Codec:" + QString::number(audioPayloadIdx) + " Video Codec:" + QString::number(videoPayload) + " Format:" + rxVideoResolution + " DTMF: " + QString::number(dtmfPayload) + "\n\n");
02253 }
02254 else
02255 SipFsm::Debug(SipDebugEvent::SipDebugEv, "SIP: No SDP in message\n");
02256 }
02257
02258
02259
02260 void SipCall::addSdpToInvite(SipMsg& msg, bool advertiseVideo, int audioCodec)
02261 {
02262 SipSdp sdp(sipLocalIP, sipAudioRtpPort, advertiseVideo ? sipVideoRtpPort : 0);
02263
02264 if ((audioCodec < 0) || (audioCodec >= MAX_AUDIO_CODECS))
02265 {
02266 for (int n=0; (n<MAX_AUDIO_CODECS) && (CodecList[n].Payload != -1); n++)
02267 sdp.addAudioCodec(CodecList[n].Payload, CodecList[n].Encoding + "/8000");
02268 }
02269 else
02270 sdp.addAudioCodec(CodecList[audioCodec].Payload, CodecList[audioCodec].Encoding + "/8000");
02271
02272
02273 sdp.addAudioCodec(101, "telephone-event/8000", "0-11");
02274
02275 if (advertiseVideo)
02276 sdp.addVideoCodec(34, "H263/90000", txVideoResolution +"=2");
02277 sdp.encode();
02278 msg.addContent("application/sdp", sdp.string());
02279 }
02280
02281
02282 QString SipCall::BuildSdpResponse()
02283 {
02284 SipSdp sdp(sipLocalIP, sipAudioRtpPort, (videoPayload != -1) ? sipVideoRtpPort : 0);
02285
02286 sdp.addAudioCodec(CodecList[audioPayloadIdx].Payload, CodecList[audioPayloadIdx].Encoding + "/8000");
02287
02288
02289 if (dtmfPayload != -1)
02290 sdp.addAudioCodec(dtmfPayload, "telephone-event/8000", "0-11");
02291
02292 if (videoPayload != -1)
02293 sdp.addVideoCodec(34, "H263/90000", txVideoResolution +"=2");
02294
02295 sdp.encode();
02296 return sdp.string();
02297 }
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310 SipRegisteredUA::SipRegisteredUA(SipUrl *Url, QString cIp, int cPort)
02311 {
02312 userUrl = new SipUrl(Url);
02313 contactIp = cIp;
02314 contactPort = cPort;
02315 }
02316
02317 SipRegisteredUA::~SipRegisteredUA()
02318 {
02319 if (userUrl != 0)
02320 delete userUrl;
02321 }
02322
02323 bool SipRegisteredUA::matches(SipUrl *u)
02324 {
02325 if ((u != 0) && (userUrl != 0))
02326 {
02327 if (u->getUser() == userUrl->getUser())
02328 return true;
02329 }
02330 return false;
02331 }
02332
02333
02334 SipRegistrar::SipRegistrar(SipFsm *par, QString domain, QString localIp, int localPort) : SipFsmBase(par)
02335 {
02336 sipLocalIp = localIp;
02337 sipLocalPort = localPort;
02338 regDomain = domain;
02339 }
02340
02341 SipRegistrar::~SipRegistrar()
02342 {
02343 SipRegisteredUA *it;
02344 while ((it=RegisteredList.first()) != 0)
02345 {
02346 RegisteredList.remove();
02347 delete it;
02348 }
02349 (parent->Timer())->StopAll(this);
02350 }
02351
02352 int SipRegistrar::FSM(int Event, SipMsg *sipMsg, void *Value)
02353 {
02354 switch(Event)
02355 {
02356 case SIP_REGISTER:
02357 {
02358 SipUrl *s = sipMsg->getContactUrl();
02359 SipUrl *to = sipMsg->getToUrl();
02360 if ((to->getHost() == regDomain) || (to->getHostIp() == sipLocalIp))
02361 {
02362 if (sipMsg->getExpires() != 0)
02363 add(to, s->getHostIp(), s->getPort(), sipMsg->getExpires());
02364 else
02365 remove(to);
02366 SendResponse(200, sipMsg, s->getHostIp(), s->getPort());
02367 }
02368 else
02369 {
02370 cout << "SIP Registration rejected for domain " << (sipMsg->getToUrl())->getHost() << endl;
02371 SendResponse(404, sipMsg, s->getHostIp(), s->getPort());
02372 }
02373 }
02374 break;
02375 case SIP_REGISTRAR_TEXP:
02376 if (Value != 0)
02377 {
02378 SipRegisteredUA *it = (SipRegisteredUA *)Value;
02379 RegisteredList.remove(it);
02380 cout << "SIP Registration Expired client " << it->getContactIp() << ":" << it->getContactPort() << endl;
02381 delete it;
02382 }
02383 break;
02384 }
02385 return 0;
02386 }
02387
02388 void SipRegistrar::add(SipUrl *Url, QString hostIp, int Port, int Expires)
02389 {
02390
02391 SipRegisteredUA *it = find(Url);
02392
02393
02394 if (it == 0)
02395 {
02396 SipRegisteredUA *entry = new SipRegisteredUA(Url, hostIp, Port);
02397 RegisteredList.append(entry);
02398
02399 (parent->Timer())->Start(this, Expires*1000, SIP_REGISTRAR_TEXP, RegisteredList.current());
02400 cout << "SIP Registered client " << Url->getUser() << " at " << hostIp << endl;
02401 }
02402
02403
02404 else
02405 {
02406
02407 (parent->Timer())->Start(this, Expires*1000, SIP_REGISTRAR_TEXP, it);
02408
02409 }
02410 }
02411
02412 void SipRegistrar::remove(SipUrl *Url)
02413 {
02414
02415 SipRegisteredUA *it = find(Url);
02416
02417 if (it != 0)
02418 {
02419 RegisteredList.remove(it);
02420 (parent->Timer())->Stop(this, SIP_REGISTRAR_TEXP, it);
02421 cout << "SIP Unregistered client " << Url->getUser() << " at " << Url->getHostIp() << endl;
02422 delete it;
02423 }
02424 else
02425 cerr << "SIP Registrar could not find registered client " << Url->getUser() << endl;
02426 }
02427
02428 bool SipRegistrar::getRegisteredContact(SipUrl *Url)
02429 {
02430
02431 SipRegisteredUA *it = find(Url);
02432
02433 if (it)
02434 {
02435 Url->setHostIp(it->getContactIp());
02436 Url->setPort(it->getContactPort());
02437 return true;
02438 }
02439 return false;
02440 }
02441
02442 SipRegisteredUA *SipRegistrar::find(SipUrl *Url)
02443 {
02444
02445 if ((Url->getHost() == regDomain) || (Url->getHostIp() == sipLocalIp))
02446 {
02447
02448 SipRegisteredUA *it;
02449 for (it=RegisteredList.first(); it; it=RegisteredList.next())
02450 {
02451 if (it->matches(Url))
02452 return it;
02453 }
02454 }
02455 return 0;
02456 }
02457
02458 void SipRegistrar::SendResponse(int Code, SipMsg *sipMsg, QString rIp, int rPort)
02459 {
02460 SipMsg Status("REGISTER");
02461 Status.addStatusLine(Code);
02462 Status.addVia(sipLocalIp, sipLocalPort);
02463 Status.addFrom(*(sipMsg->getFromUrl()), sipMsg->getFromTag());
02464 Status.addTo(*(sipMsg->getFromUrl()), myTag);
02465 Status.addCallId(*sipMsg->getCallId());
02466 Status.addCSeq(sipMsg->getCSeqValue());
02467 Status.addExpires(sipMsg->getExpires());
02468 Status.addContact(sipMsg->getContactUrl());
02469 Status.addNullContent();
02470
02471 parent->Transmit(Status.string(), rIp, rPort);
02472 }
02473
02474
02475
02476
02477
02478
02479
02480
02481 SipRegistration::SipRegistration(SipFsm *par, QString localIp, int localPort, QString Username, QString Password, QString ProxyName, int ProxyPort) : SipFsmBase(par)
02482 {
02483 sipLocalIp = localIp;
02484 sipLocalPort = localPort;
02485 ProxyUrl = new SipUrl("", "", ProxyName, ProxyPort);
02486 MyUrl = new SipUrl("", Username, ProxyName, ProxyPort);
02487 MyContactUrl = new SipUrl("", Username, sipLocalIp, sipLocalPort);
02488 MyPassword = Password;
02489 cseq = 1;
02490 CallId.Generate(sipLocalIp);
02491
02492 SendRegister();
02493 State = SIP_REG_TRYING;
02494 regRetryCount = REG_RETRY_MAXCOUNT;
02495 Expires = 3600;
02496 (parent->Timer())->Start(this, REG_RETRY_TIMER, SIP_RETX);
02497 }
02498
02499 SipRegistration::~SipRegistration()
02500 {
02501 if (ProxyUrl)
02502 delete ProxyUrl;
02503 if (MyUrl)
02504 delete MyUrl;
02505 if (MyContactUrl)
02506 delete MyContactUrl;
02507 ProxyUrl = MyUrl = MyContactUrl = 0;
02508 (parent->Timer())->StopAll(this);
02509 }
02510
02511 int SipRegistration::FSM(int Event, SipMsg *sipMsg, void *Value)
02512 {
02513 (void)Value;
02514 switch (Event | State)
02515 {
02516 case SIP_REG_TRYING_STATUS:
02517 (parent->Timer())->Stop(this, SIP_RETX);
02518 switch (sipMsg->getStatusCode())
02519 {
02520 case 200:
02521 if (sipMsg->getExpires() > 0)
02522 Expires = sipMsg->getExpires();
02523 cout << "SIP Registered to " << ProxyUrl->getHost() << " for " << Expires << "s" << endl;
02524 State = SIP_REG_REGISTERED;
02525 (parent->Timer())->Start(this, (Expires-30)*1000, SIP_REG_TREGEXP);
02526 break;
02527 case 401:
02528 case 407:
02529 SendRegister(sipMsg);
02530 regRetryCount = REG_RETRY_MAXCOUNT;
02531 State = SIP_REG_CHALLENGED;
02532 (parent->Timer())->Start(this, REG_RETRY_TIMER, SIP_RETX);
02533 break;
02534 default:
02535 if (sipMsg->getStatusCode() != 100)
02536 {
02537 cout << "SIP Registration failed; Reason " << sipMsg->getStatusCode() << " " << sipMsg->getReasonPhrase() << endl;
02538 State = SIP_REG_FAILED;
02539 (parent->Timer())->Start(this, REG_FAIL_RETRY_TIMER, SIP_RETX);
02540 }
02541 break;
02542 }
02543 break;
02544
02545 case SIP_REG_CHALL_STATUS:
02546 (parent->Timer())->Stop(this, SIP_RETX);
02547 switch (sipMsg->getStatusCode())
02548 {
02549 case 200:
02550 if (sipMsg->getExpires() > 0)
02551 Expires = sipMsg->getExpires();
02552 cout << "SIP Registered to " << ProxyUrl->getHost() << " for " << Expires << "s" << endl;
02553 State = SIP_REG_REGISTERED;
02554 (parent->Timer())->Start(this, (Expires-30)*1000, SIP_REG_TREGEXP);
02555 break;
02556 default:
02557 if (sipMsg->getStatusCode() != 100)
02558 {
02559 cout << "SIP Registration failed; Reason " << sipMsg->getStatusCode() << " " << sipMsg->getReasonPhrase() << endl;
02560 State = SIP_REG_FAILED;
02561 (parent->Timer())->Start(this, REG_FAIL_RETRY_TIMER, SIP_RETX);
02562 }
02563 break;
02564 }
02565 break;
02566
02567 case SIP_REG_REGISTERED_TREGEXP:
02568 regRetryCount = REG_RETRY_MAXCOUNT+1;
02569 case SIP_REG_TRYING_RETX:
02570 case SIP_REG_CHALL_RETX:
02571 case SIP_REG_FAILED_RETX:
02572 if (--regRetryCount > 0)
02573 {
02574 State = SIP_REG_TRYING;
02575 SendRegister();
02576 (parent->Timer())->Start(this, REG_RETRY_TIMER, SIP_RETX);
02577 }
02578 else
02579 {
02580 State = SIP_REG_FAILED;
02581 cout << "SIP Registration failed; no Response from Server. Are you behind a firewall?\n";
02582 }
02583 break;
02584
02585 default:
02586 cerr << "SIP Registration: Unknown Event " << EventtoString(Event) << ", State " << State << endl;
02587 break;
02588 }
02589 return 0;
02590 }
02591
02592 void SipRegistration::SendRegister(SipMsg *authMsg)
02593 {
02594 SipMsg Register("REGISTER");
02595 Register.addRequestLine(*ProxyUrl);
02596 Register.addVia(sipLocalIp, sipLocalPort);
02597 Register.addFrom(*MyUrl, myTag);
02598 Register.addTo(*MyUrl);
02599 Register.addCallId(CallId);
02600 Register.addCSeq(++cseq);
02601
02602 if (authMsg && (authMsg->getAuthMethod() == "Digest"))
02603 {
02604 Register.addAuthorization(authMsg->getAuthMethod(), MyUrl->getUser(), MyPassword,
02605 authMsg->getAuthRealm(), authMsg->getAuthNonce(),
02606 ProxyUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
02607 sentAuthenticated = true;
02608 }
02609 else
02610 sentAuthenticated = false;
02611
02612 Register.addUserAgent();
02613 Register.addExpires(Expires=3600);
02614 Register.addContact(*MyContactUrl);
02615 Register.addNullContent();
02616
02617 parent->Transmit(Register.string(), ProxyUrl->getHostIp(), ProxyUrl->getPort());
02618 }
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628 SipSubscriber::SipSubscriber(SipFsm *par, QString localIp, int localPort, SipRegistration *reg, QString status) : SipFsmBase(par)
02629 {
02630 sipLocalIp = localIp;
02631 sipLocalPort = localPort;
02632 regProxy = reg;
02633 myStatus = status;
02634 watcherUrl = 0;
02635 State = SIP_SUB_IDLE;
02636
02637 if (regProxy)
02638 MyUrl = new SipUrl("", regProxy->registeredAs(), regProxy->registeredTo(), 5060);
02639 else
02640 MyUrl = new SipUrl("", "MythPhone", sipLocalIp, sipLocalPort);
02641 MyContactUrl = new SipUrl("", "", sipLocalIp, sipLocalPort);
02642 cseq = 2;
02643 }
02644
02645 SipSubscriber::~SipSubscriber()
02646 {
02647 (parent->Timer())->StopAll(this);
02648 if (watcherUrl)
02649 delete watcherUrl;
02650 if (MyUrl)
02651 delete MyUrl;
02652 if (MyContactUrl)
02653 delete MyContactUrl;
02654 watcherUrl = MyUrl = MyContactUrl = 0;
02655 }
02656
02657 int SipSubscriber::FSM(int Event, SipMsg *sipMsg, void *Value)
02658 {
02659 int OldState = State;
02660
02661 switch (Event | State)
02662 {
02663 case SIP_SUB_IDLE_SUBSCRIBE:
02664 ParseSipMsg(Event, sipMsg);
02665 if (watcherUrl == 0)
02666 watcherUrl = new SipUrl(sipMsg->getFromUrl());
02667 expires = sipMsg->getExpires();
02668 if (expires == -1)
02669 expires = 600;
02670 BuildSendStatus(200, "SUBSCRIBE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT | SIP_OPT_EXPIRES, expires);
02671 if (expires > 0)
02672 {
02673 (parent->Timer())->Start(this, expires*1000, SIP_SUBSCRIBE_EXPIRE);
02674 SendNotify(0);
02675 State = SIP_SUB_SUBSCRIBED;
02676
02677
02678
02679 parent->KickWatcher(watcherUrl);
02680 }
02681 break;
02682
02683 case SIP_SUB_SUBS_SUBSCRIBE:
02684 ParseSipMsg(Event, sipMsg);
02685 expires = sipMsg->getExpires();
02686 if (expires == -1)
02687 expires = 600;
02688 BuildSendStatus(200, "SUBSCRIBE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT | SIP_OPT_EXPIRES, expires);
02689 if (expires > 0)
02690 {
02691 (parent->Timer())->Start(this, expires*1000, SIP_SUBSCRIBE_EXPIRE);
02692 SendNotify(0);
02693 }
02694 else
02695 State = SIP_SUB_IDLE;
02696 break;
02697
02698 case SIP_SUB_SUBS_SUBSCRIBE_EXPIRE:
02699 break;
02700
02701 case SIP_SUB_SUBS_RETX:
02702 if (Retransmit(false))
02703 (parent->Timer())->Start(this, t1, SIP_RETX);
02704 break;
02705
02706 case SIP_SUB_SUBS_NOTSTATUS:
02707 (parent->Timer())->Stop(this, SIP_RETX);
02708 if (((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401)) &&
02709 (!sentAuthenticated))
02710 SendNotify(sipMsg);
02711 break;
02712
02713 case SIP_SUB_SUBS_PRESENCE_CHANGE:
02714 myStatus = (char *)Value;
02715 SendNotify(0);
02716 break;
02717
02718 default:
02719 SipFsm::Debug(SipDebugEvent::SipErrorEv, "SIP Subscriber FSM Error; received " + EventtoString(Event) + " in state " + StatetoString(State) + "\n\n");
02720 break;
02721 }
02722
02723 DebugFsm(Event, OldState, State);
02724 return State;
02725 }
02726
02727 void SipSubscriber::SendNotify(SipMsg *authMsg)
02728 {
02729 SipMsg Notify("NOTIFY");
02730 Notify.addRequestLine(*watcherUrl);
02731 Notify.addVia(sipLocalIp, sipLocalPort);
02732 Notify.addFrom(*MyUrl, myTag);
02733 Notify.addTo(*watcherUrl, remoteTag, remoteEpid);
02734 Notify.addCallId(CallId);
02735 Notify.addCSeq(++cseq);
02736 int expLeft = (parent->Timer())->msLeft(this, SIP_SUBSCRIBE_EXPIRE)/1000;
02737 Notify.addExpires(expLeft);
02738 Notify.addUserAgent();
02739 Notify.addContact(MyContactUrl);
02740 Notify.addSubState("active", expLeft);
02741 Notify.addEvent("presence");
02742
02743 if (authMsg)
02744 {
02745 if (authMsg->getAuthMethod() == "Digest")
02746 Notify.addAuthorization(authMsg->getAuthMethod(), regProxy->registeredAs(), regProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), watcherUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
02747 else
02748 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
02749 sentAuthenticated = true;
02750 }
02751 else
02752 sentAuthenticated = false;
02753
02754 SipXpidf xpidf(*MyUrl);
02755 if (myStatus == "CLOSED")
02756 xpidf.setStatus("inactive", "away");
02757 else if (myStatus == "ONTHEPHONE")
02758 xpidf.setStatus("inuse", "onthephone");
02759 else if (myStatus == "OPEN")
02760 xpidf.setStatus("open", "online");
02761
02762 Notify.addContent("application/xpidf+xml", xpidf.encode());
02763
02764
02765 if (recRouteUrl)
02766 parent->Transmit(Notify.string(), retxIp = recRouteUrl->getHostIp(), retxPort = recRouteUrl->getPort());
02767 else if (contactUrl)
02768 parent->Transmit(Notify.string(), retxIp = contactUrl->getHostIp(), retxPort = contactUrl->getPort());
02769 else
02770 parent->Transmit(Notify.string(), retxIp = watcherUrl->getHostIp(), retxPort = watcherUrl->getPort());
02771 retx = Notify.string();
02772 t1 = 500;
02773 (parent->Timer())->Start(this, t1, SIP_RETX);
02774 }
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784 SipWatcher::SipWatcher(SipFsm *par, QString localIp, int localPort, SipRegistration *reg, QString destUrl) : SipFsmBase(par)
02785 {
02786 sipLocalIp = localIp;
02787 sipLocalPort = localPort;
02788 regProxy = reg;
02789 watchedUrlString = destUrl;
02790
02791
02792
02793 if ((!destUrl.contains('@')) && (regProxy != 0))
02794 destUrl.append(QString("@") + gContext->GetSetting("SipProxyName"));
02795
02796 watchedUrl = new SipUrl(destUrl, "");
02797 State = SIP_WATCH_IDLE;
02798 cseq = 1;
02799 expires = -1;
02800 CallId.Generate(sipLocalIp);
02801 if (regProxy)
02802 MyUrl = new SipUrl("", regProxy->registeredAs(), regProxy->registeredTo(), 5060);
02803 else
02804 MyUrl = new SipUrl("", "MythPhone", sipLocalIp, sipLocalPort);
02805 MyContactUrl = new SipUrl("", "", sipLocalIp, sipLocalPort);
02806
02807 FSM(SIP_WATCH, 0);
02808 }
02809
02810 SipWatcher::~SipWatcher()
02811 {
02812 (parent->Timer())->StopAll(this);
02813 if (watchedUrl != 0)
02814 delete watchedUrl;
02815 if (MyUrl)
02816 delete MyUrl;
02817 if (MyContactUrl)
02818 delete MyContactUrl;
02819 watchedUrl = MyUrl = MyContactUrl = 0;
02820 }
02821
02822 int SipWatcher::FSM(int Event, SipMsg *sipMsg, void *Value)
02823 {
02824 (void)Value;
02825 int OldState = State;
02826 SipXpidf *xpidf;
02827
02828 switch (Event | State)
02829 {
02830 case SIP_WATCH_IDLE_WATCH:
02831 case SIP_WATCH_TRYING_WATCH:
02832 case SIP_WATCH_HOLDOFF_WATCH:
02833 case SIP_WATCH_HOLDOFF_KICK:
02834 if ((regProxy == 0) || (regProxy->isRegistered()))
02835 SendSubscribe(0);
02836 else
02837 (parent->Timer())->Start(this, 5000, SIP_WATCH);
02838 State = SIP_WATCH_TRYING;
02839 break;
02840
02841 case SIP_WATCH_ACTIVE_SUBSCRIBE_EXPIRE:
02842 SendSubscribe(0);
02843 break;
02844
02845 case SIP_WATCH_TRYING_RETX:
02846 case SIP_WATCH_ACTIVE_RETX:
02847 if (Retransmit(false))
02848 (parent->Timer())->Start(this, t1, SIP_RETX);
02849 else
02850 {
02851
02852 State = SIP_WATCH_HOLDOFF;
02853 parent->SetNotification("PRESENCE", watchedUrlString, "offline", "offline");
02854 (parent->Timer())->Start(this, SIP_POLL_OFFLINE_UA, SIP_WATCH);
02855 }
02856 break;
02857
02858 case SIP_WATCH_TRYING_SUBSTATUS:
02859 (parent->Timer())->Stop(this, SIP_RETX);
02860 if ((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401))
02861 {
02862 if (!sentAuthenticated)
02863 SendSubscribe(sipMsg);
02864 }
02865 else if (sipMsg->getStatusCode() == 200)
02866 {
02867 State = SIP_WATCH_ACTIVE;
02868 expires = sipMsg->getExpires();
02869 if (expires == -1)
02870 expires = 600;
02871 (parent->Timer())->Start(this, expires*1000, SIP_SUBSCRIBE_EXPIRE);
02872 parent->SetNotification("PRESENCE", watchedUrlString, "open", "undetermined");
02873 }
02874 else
02875 {
02876
02877
02878 State = SIP_WATCH_HOLDOFF;
02879 parent->SetNotification("PRESENCE", watchedUrlString, "offline", "offline");
02880 (parent->Timer())->Start(this, SIP_POLL_OFFLINE_UA, SIP_WATCH);
02881 }
02882 break;
02883
02884 case SIP_WATCH_ACTIVE_SUBSTATUS:
02885 (parent->Timer())->Stop(this, SIP_RETX);
02886 if ((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401))
02887 {
02888 if (!sentAuthenticated)
02889 SendSubscribe(sipMsg);
02890 }
02891 else if (sipMsg->getStatusCode() == 200)
02892 {
02893 expires = sipMsg->getExpires();
02894 if (expires == -1)
02895 expires = 600;
02896 (parent->Timer())->Start(this, expires*1000, SIP_SUBSCRIBE_EXPIRE);
02897 }
02898 else
02899 {
02900
02901 State = SIP_WATCH_TRYING;
02902 (parent->Timer())->Start(this, 120*1000, SIP_WATCH);
02903 }
02904 break;
02905
02906 case SIP_WATCH_ACTIVE_NOTIFY:
02907 ParseSipMsg(Event, sipMsg);
02908 xpidf = sipMsg->getXpidf();
02909 if (xpidf)
02910 {
02911 parent->SetNotification("PRESENCE", watchedUrlString, xpidf->getStatus(), xpidf->getSubstatus());
02912 BuildSendStatus(200, "NOTIFY", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
02913 }
02914 else
02915 BuildSendStatus(406, "NOTIFY", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
02916 break;
02917
02918 case SIP_WATCH_TRYING_STOPWATCH:
02919 case SIP_WATCH_ACTIVE_STOPWATCH:
02920 State = SIP_WATCH_STOPPING;
02921 SendSubscribe(0);
02922 break;
02923
02924 case SIP_WATCH_HOLDOFF_STOPWATCH:
02925 State = SIP_WATCH_IDLE;
02926 break;
02927
02928 case SIP_WATCH_STOPPING_RETX:
02929 if (Retransmit(false))
02930 (parent->Timer())->Start(this, t1, SIP_RETX);
02931 else
02932 State = SIP_WATCH_IDLE;
02933 break;
02934
02935 case SIP_WATCH_STOPPING_SUBSTATUS:
02936 (parent->Timer())->Stop(this, SIP_RETX);
02937 if ((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401))
02938 {
02939 if (!sentAuthenticated)
02940 SendSubscribe(sipMsg);
02941 }
02942 else
02943 State = SIP_WATCH_IDLE;
02944 break;
02945
02946 case SIP_WATCH_HOLDOFF_SUBSCRIBE:
02947 case SIP_WATCH_TRYING_SUBSCRIBE:
02948
02949
02950 (parent->Timer())->Stop(this, SIP_RETX);
02951 State = SIP_WATCH_HOLDOFF;
02952 break;
02953
02954 default:
02955 SipFsm::Debug(SipDebugEvent::SipErrorEv, "SIP Watcher FSM Error; received " + EventtoString(Event) + " in state " + StatetoString(State) + "\n\n");
02956 break;
02957 }
02958
02959 DebugFsm(Event, OldState, State);
02960 return State;
02961 }
02962
02963 void SipWatcher::SendSubscribe(SipMsg *authMsg)
02964 {
02965 SipMsg Subscribe("SUBSCRIBE");
02966 Subscribe.addRequestLine(*watchedUrl);
02967 Subscribe.addVia(sipLocalIp, sipLocalPort);
02968 Subscribe.addFrom(*MyUrl, myTag);
02969 Subscribe.addTo(*watchedUrl);
02970 Subscribe.addCallId(CallId);
02971 Subscribe.addCSeq(++cseq);
02972 if (State == SIP_WATCH_STOPPING)
02973 Subscribe.addExpires(0);
02974
02975 if (authMsg)
02976 {
02977 if (authMsg->getAuthMethod() == "Digest")
02978 Subscribe.addAuthorization(authMsg->getAuthMethod(), regProxy->registeredAs(), regProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), watchedUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
02979 else
02980 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
02981 sentAuthenticated = true;
02982 }
02983 else
02984 sentAuthenticated = false;
02985
02986 Subscribe.addUserAgent();
02987 Subscribe.addContact(MyContactUrl);
02988
02989 Subscribe.addEvent("presence");
02990
02991 Subscribe.addGenericLine("Accept: application/xpidf+xml, text/xml+msrtc.pidf\r\n");
02992 Subscribe.addGenericLine("Supported: com.microsoft.autoextend\r\n");
02993 Subscribe.addNullContent();
02994
02995 parent->Transmit(Subscribe.string(), retxIp = watchedUrl->getHostIp(), retxPort = watchedUrl->getPort());
02996 retx = Subscribe.string();
02997 t1 = 500;
02998 (parent->Timer())->Start(this, t1, SIP_RETX);
02999 }
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009 SipIM::SipIM(SipFsm *par, QString localIp, int localPort, SipRegistration *reg, QString destUrl, QString callIdStr) : SipFsmBase(par)
03010 {
03011 sipLocalIp = localIp;
03012 sipLocalPort = localPort;
03013 regProxy = reg;
03014
03015 State = SIP_IDLE;
03016 rxCseq = -1;
03017 txCseq = 1;
03018 if (callIdStr.length() > 0)
03019 CallId.setValue(callIdStr);
03020 else
03021 CallId.Generate(sipLocalIp);
03022 imUrl = 0;
03023 if (destUrl.length() > 0)
03024 {
03025
03026
03027 if ((!destUrl.contains('@')) && (regProxy != 0))
03028 destUrl.append(QString("@") + gContext->GetSetting("SipProxyName"));
03029
03030 imUrl = new SipUrl(destUrl, "");
03031 }
03032
03033 if (regProxy)
03034 MyUrl = new SipUrl("", regProxy->registeredAs(), regProxy->registeredTo(), 5060);
03035 else
03036 MyUrl = new SipUrl("", "MythPhone", sipLocalIp, sipLocalPort);
03037 MyContactUrl = new SipUrl("", "", sipLocalIp, sipLocalPort);
03038 }
03039
03040 SipIM::~SipIM()
03041 {
03042 (parent->Timer())->StopAll(this);
03043 if (imUrl)
03044 delete imUrl;
03045 if (MyUrl)
03046 delete MyUrl;
03047 if (MyContactUrl)
03048 delete MyContactUrl;
03049 MyUrl = MyContactUrl = 0;
03050 }
03051
03052 int SipIM::FSM(int Event, SipMsg *sipMsg, void *Value)
03053 {
03054 int OldState = State;
03055 QString textContent;
03056
03057 switch (Event)
03058 {
03059 case SIP_USER_MESSAGE:
03060 msgToSend = *((QString *)Value);
03061 SendMessage(0, msgToSend);
03062 State = SIP_IM_ACTIVE;
03063 break;
03064
03065 case SIP_MESSAGE:
03066 ParseSipMsg(Event, sipMsg);
03067 if (rxCseq != sipMsg->getCSeqValue())
03068 {
03069 rxCseq = sipMsg->getCSeqValue();
03070 textContent = sipMsg->getPlainText();
03071 parent->SetNotification("IM", remoteUrl->getUser(), CallId.string(), textContent);
03072 }
03073 if (imUrl == 0)
03074 imUrl = new SipUrl(sipMsg->getFromUrl());
03075 BuildSendStatus(200, "MESSAGE", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
03076 State = SIP_IM_ACTIVE;
03077 (parent->Timer())->Start(this, 30*60*1000, SIP_IM_TIMEOUT);
03078 break;
03079
03080 case SIP_INFO:
03081 ParseSipMsg(Event, sipMsg);
03082 BuildSendStatus(200, "INFO", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
03083 State = SIP_IM_ACTIVE;
03084 (parent->Timer())->Start(this, 30*60*1000, SIP_IM_TIMEOUT);
03085 break;
03086
03087 case SIP_MESSAGESTATUS:
03088 (parent->Timer())->Stop(this, SIP_RETX);
03089 if ((sipMsg->getStatusCode() == 407) || (sipMsg->getStatusCode() == 401))
03090 {
03091 if (!sentAuthenticated)
03092 SendMessage(sipMsg, msgToSend);
03093 }
03094 else if (sipMsg->getStatusCode() != 200)
03095 cout << "SIP: Send IM got status code " << sipMsg->getStatusCode() << endl;
03096 (parent->Timer())->Start(this, 30*60*1000, SIP_IM_TIMEOUT);
03097 break;
03098
03099 case SIP_RETX:
03100 if (Retransmit(false))
03101 (parent->Timer())->Start(this, t1, SIP_RETX);
03102 else
03103 cout << "SIP: Send IM failed to get a response\n";
03104 break;
03105
03106 case SIP_IM_TIMEOUT:
03107 State = SIP_IM_IDLE;
03108 break;
03109
03110 default:
03111 SipFsm::Debug(SipDebugEvent::SipErrorEv, "SIP IM FSM Error; received " + EventtoString(Event) + " in state " + StatetoString(State) + "\n\n");
03112 break;
03113 }
03114
03115 DebugFsm(Event, OldState, State);
03116 return State;
03117 }
03118
03119 void SipIM::SendMessage(SipMsg *authMsg, QString Text)
03120 {
03121 SipMsg Message("MESSAGE");
03122 Message.addRequestLine(*imUrl);
03123 Message.addVia(sipLocalIp, sipLocalPort);
03124 Message.addFrom(*MyUrl, myTag);
03125 Message.addTo(*imUrl, remoteTag, remoteEpid);
03126 Message.addCallId(CallId);
03127 Message.addCSeq(++txCseq);
03128
03129 if (authMsg)
03130 {
03131 if (authMsg->getAuthMethod() == "Digest")
03132 Message.addAuthorization(authMsg->getAuthMethod(), regProxy->registeredAs(), regProxy->registeredPasswd(), authMsg->getAuthRealm(), authMsg->getAuthNonce(), imUrl->formatReqLineUrl(), authMsg->getStatusCode() == 407);
03133 else
03134 cout << "SIP: Unknown Auth Type: " << authMsg->getAuthMethod() << endl;
03135 sentAuthenticated = true;
03136 }
03137 else
03138 sentAuthenticated = false;
03139
03140 Message.addUserAgent();
03141 Message.addContact(MyContactUrl);
03142
03143 Message.addContent("text/plain", Text);
03144
03145 if (recRouteUrl != 0)
03146 parent->Transmit(Message.string(), retxIp = recRouteUrl->getHostIp(),
03147 retxPort = recRouteUrl->getPort());
03148 else
03149 parent->Transmit(Message.string(), retxIp = imUrl->getHostIp(),
03150 retxPort = imUrl->getPort());
03151 retx = Message.string();
03152 t1 = 500;
03153 (parent->Timer())->Start(this, t1, SIP_RETX);
03154 }
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164 SipOptions::SipOptions(SipFsm *par, QString localIp, int localPort, SipRegistration *reg, QString callIdStr) : SipFsmBase(par)
03165 {
03166 sipLocalIp = localIp;
03167 sipLocalPort = localPort;
03168 regProxy = reg;
03169
03170 rxCseq = -1;
03171 txCseq = 1;
03172 if (callIdStr.length() > 0)
03173 CallId.setValue(callIdStr);
03174 else
03175 CallId.Generate(sipLocalIp);
03176
03177 if (regProxy)
03178 MyUrl = new SipUrl("", regProxy->registeredAs(), regProxy->registeredTo(), 5060);
03179 else
03180 MyUrl = new SipUrl("", "MythPhone", sipLocalIp, sipLocalPort);
03181 MyContactUrl = new SipUrl("", "", sipLocalIp, sipLocalPort);
03182 }
03183
03184 SipOptions::~SipOptions()
03185 {
03186 if (MyUrl)
03187 delete MyUrl;
03188 if (MyContactUrl)
03189 delete MyContactUrl;
03190 MyUrl = MyContactUrl = 0;
03191 }
03192
03193 int SipOptions::FSM(int Event, SipMsg *sipMsg, void *Value)
03194 {
03195
03196 ParseSipMsg(Event, sipMsg);
03197 BuildSendStatus(200, "OPTIONS", sipMsg->getCSeqValue(), SIP_OPT_CONTACT);
03198
03199 return SIP_IDLE;
03200 }
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 SipNotify::SipNotify()
03212 {
03213 notifySocket = new QSocketDevice (QSocketDevice::Datagram);
03214 notifySocket->setBlocking(false);
03215 QHostAddress thisIP;
03216 thisIP.setAddress("127.0.0.1");
03217 if (!notifySocket->bind(thisIP, 6951))
03218 {
03219 cerr << "Failed to bind for CLI NOTIFY connection\n";
03220 delete notifySocket;
03221 notifySocket = 0;
03222 }
03223
03224 }
03225
03226 SipNotify::~SipNotify()
03227 {
03228 if (notifySocket)
03229 {
03230 delete notifySocket;
03231 notifySocket = 0;
03232 }
03233
03234 }
03235
03236 void SipNotify::Display(QString name, QString number)
03237 {
03238 if (notifySocket)
03239 {
03240 QString text;
03241 text = "<mythnotify version=\"1\">"
03242 " <container name=\"notify_cid_info\">"
03243 " <textarea name=\"notify_cid_name\">"
03244 " <value>NAME : ";
03245 text += name;
03246 text += " </value>"
03247 " </textarea>"
03248 " <textarea name=\"notify_cid_num\">"
03249 " <value>NUM : ";
03250 text += number;
03251 text += " </value>"
03252 " </textarea>"
03253 " </container>"
03254 "</mythnotify>";
03255
03256 QHostAddress RemoteIP;
03257 RemoteIP.setAddress("127.0.0.1");
03258
03259 int udp_port = gContext->GetNumSetting("UDPNotifyPort", 6948);
03260 if (udp_port > 0)
03261 notifySocket->writeBlock(text.ascii(), text.length(), RemoteIP,
03262 udp_port);
03263 }
03264 }
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275 SipTimer::SipTimer():QPtrList<aSipTimer>()
03276 {
03277 }
03278
03279 SipTimer::~SipTimer()
03280 {
03281 aSipTimer *p;
03282 while ((p = first()) != 0)
03283 {
03284 remove();
03285 delete p;
03286 }
03287 }
03288
03289 void SipTimer::Start(SipFsmBase *Instance, int ms, int expireEvent, void *Value)
03290 {
03291 Stop(Instance, expireEvent, Value);
03292 QDateTime expire = (QDateTime::currentDateTime()).addSecs(ms/1000);
03293 aSipTimer *t = new aSipTimer(Instance, expire, expireEvent, Value);
03294 inSort(t);
03295 }
03296
03297 int SipTimer::compareItems(QPtrCollection::Item s1, QPtrCollection::Item s2)
03298 {
03299 QDateTime t1 = ((aSipTimer *)s1)->getExpire();
03300 QDateTime t2 = ((aSipTimer *)s2)->getExpire();
03301
03302 return (t1==t2 ? 0 : (t1>t2 ? 1 : -1));
03303 }
03304
03305 void SipTimer::Stop(SipFsmBase *Instance, int expireEvent, void *Value)
03306 {
03307 aSipTimer *it;
03308 for (it=first(); it; it=next())
03309 {
03310 if (it->match(Instance, expireEvent, Value))
03311 {
03312 remove();
03313 delete it;
03314 }
03315 }
03316 }
03317
03318 int SipTimer::msLeft(SipFsmBase *Instance, int expireEvent, void *Value)
03319 {
03320 aSipTimer *it;
03321 for (it=first(); it; it=next())
03322 {
03323 if (it->match(Instance, expireEvent, Value))
03324 {
03325 int secsLeft = (QDateTime::currentDateTime()).secsTo(it->getExpire());
03326 return ((secsLeft > 0 ? secsLeft : 0)*1000);
03327 }
03328 }
03329 return 0;
03330 }
03331
03332 void SipTimer::StopAll(SipFsmBase *Instance)
03333 {
03334 Stop(Instance, -1);
03335 }
03336
03337 SipFsmBase *SipTimer::Expired(int *Event, void **Value)
03338 {
03339 aSipTimer *it = first();
03340 if ((it) && (it->Expired()))
03341 {
03342 SipFsmBase *c = it->getInstance();
03343 *Event = it->getEvent();
03344 *Value = it->getValue();
03345 remove();
03346 delete it;
03347 return c;
03348 }
03349 *Event = 0;
03350 return 0;
03351 }
03352
03353
03354
03355
03356