D:/Storage/CVS_Head/h323plus/src/h224.cxx

00001 /*
00002  * h224.cxx
00003  *
00004  * H.224 implementation for the OpenH323 Project.
00005  *
00006  * Copyright (c) 2006 Network for Educational Technology, ETH Zurich.
00007  * Written by Hannes Friederich.
00008  *
00009  * The contents of this file are subject to the Mozilla Public License
00010  * Version 1.0 (the "License"); you may not use this file except in
00011  * compliance with the License. You may obtain a copy of the License at
00012  * http://www.mozilla.org/MPL/
00013  *
00014  * Software distributed under the License is distributed on an "AS IS"
00015  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00016  * the License for the specific language governing rights and limitations
00017  * under the License.
00018  *
00019  * Contributor(s): ______________________________________.
00020  *
00021  * $Log: h224.cxx,v $
00022  * Revision 1.1  2007/08/06 20:51:05  shorne
00023  * First commit of h323plus
00024  *
00025  * Revision 1.1  2006/06/22 11:07:23  shorne
00026  * Backport of FECC (H.224) from Opal
00027  *
00028  * Revision 1.3  2006/05/01 10:29:50  csoutheren
00029  * Added pragams for gcc < 4
00030  *
00031  * Revision 1.2  2006/04/24 12:53:50  rjongbloed
00032  * Port of H.224 Far End Camera Control to DevStudio/Windows
00033  *
00034  * Revision 1.1  2006/04/20 16:48:17  hfriederich
00035  * Initial version of H.224/H.281 implementation.
00036  *
00037  */
00038 
00039 #include <ptlib.h>
00040 #include <h323.h>
00041 
00042 #ifdef H323_H224
00043 
00044 #ifdef __GNUC__
00045 #pragma implementation "h224.h"
00046 #pragma implementation "h224handler.h"
00047 #endif
00048 
00049 #ifdef _MSC_VER
00050 #pragma warning(disable : 4244)
00051 #endif
00052 
00053 #include <h224.h>
00054 #include <h224handler.h>
00055 #include <h323con.h>
00056 #include <h245.h>
00057 
00058 
00059 H224_Frame::H224_Frame(PINDEX size)
00060 : Q922_Frame(H224_HEADER_SIZE + size)
00061 {
00062   SetHighPriority(FALSE);
00063         
00064   SetControlFieldOctet(0x03);
00065         
00066   BYTE *data = GetInformationFieldPtr();
00067         
00068   // setting destination & source terminal address to BROADCAST
00069   data[0] = 0;
00070   data[1] = 0;
00071   data[2] = 0;
00072   data[3] = 0;
00073         
00074   // setting Client ID to CME
00075   data[4] = 0;
00076         
00077   // setting ES / BS / C1 / C0 / Segment number to zero
00078   data[5] = 0;
00079 }
00080 
00081 H224_Frame::~H224_Frame()
00082 {
00083 }
00084 
00085 void H224_Frame::SetHighPriority(BOOL flag)
00086 {
00087   SetHighOrderAddressOctet(0x00);
00088         
00089   if(flag) {
00090     SetLowOrderAddressOctet(0x71);
00091   } else {
00092     SetLowOrderAddressOctet(0x061);
00093   }
00094 }
00095 
00096 WORD H224_Frame::GetDestinationTerminalAddress() const
00097 {
00098   BYTE *data = GetInformationFieldPtr();
00099   return (WORD)((data[0] << 8) | data[1]);
00100 }
00101 
00102 void H224_Frame::SetDestinationTerminalAddress(WORD address)
00103 {
00104   BYTE *data = GetInformationFieldPtr();
00105   data[0] = (BYTE)(address >> 8);
00106   data[1] = (BYTE) address;
00107 }
00108 
00109 WORD H224_Frame::GetSourceTerminalAddress() const
00110 {
00111   BYTE *data = GetInformationFieldPtr();
00112   return (WORD)((data[2] << 8) | data[3]);
00113 }
00114 
00115 void H224_Frame::SetSourceTerminalAddress(WORD address)
00116 {
00117   BYTE *data = GetInformationFieldPtr();
00118   data[2] = (BYTE)(address >> 8);
00119   data[3] = (BYTE) address;
00120 }
00121 
00122 BYTE H224_Frame::GetClientID() const
00123 {
00124   BYTE *data = GetInformationFieldPtr();
00125         
00126   return data[4] & 0x7f;
00127 }
00128 
00129 void H224_Frame::SetClientID(BYTE clientID)
00130 {
00131   // At the moment, only H.281 (client ID 0x01)
00132   // is supported
00133   PAssert(clientID <= 0x01, "Invalid client ID");
00134         
00135   BYTE *data = GetInformationFieldPtr();
00136         
00137   data[4] = clientID;
00138 }
00139 
00140 BOOL H224_Frame::GetBS() const
00141 {
00142   BYTE *data = GetInformationFieldPtr();
00143         
00144   return (data[5] & 0x80) != 0;
00145 }
00146 
00147 void H224_Frame::SetBS(BOOL flag)
00148 {
00149   BYTE *data = GetInformationFieldPtr();
00150         
00151   if(flag) {
00152     data[5] |= 0x80;
00153   }     else {
00154     data[5] &= 0x7f;
00155   }
00156 }
00157 
00158 BOOL H224_Frame::GetES() const
00159 {
00160   BYTE *data = GetInformationFieldPtr();
00161         
00162   return (data[5] & 0x40) != 0;
00163 }
00164 
00165 void H224_Frame::SetES(BOOL flag)
00166 {
00167   BYTE *data = GetInformationFieldPtr();
00168         
00169   if(flag) {
00170     data[5] |= 0x40;
00171   } else {
00172     data[5] &= 0xbf;
00173   }
00174 }
00175 
00176 BOOL H224_Frame::GetC1() const
00177 {
00178   BYTE *data = GetInformationFieldPtr();
00179         
00180   return (data[5] & 0x20) != 0;
00181 }
00182 
00183 void H224_Frame::SetC1(BOOL flag)
00184 {
00185   BYTE *data = GetInformationFieldPtr();
00186         
00187   if(flag) {
00188     data[5] |= 0x20;
00189   } else {
00190     data[5] &= 0xdf;
00191   }
00192 }
00193 
00194 BOOL H224_Frame::GetC0() const
00195 {
00196   BYTE *data = GetInformationFieldPtr();
00197         
00198   return (data[5] & 0x10) != 0;
00199 }
00200 
00201 void H224_Frame::SetC0(BOOL flag)
00202 {
00203   BYTE *data = GetInformationFieldPtr();
00204         
00205   if(flag) {
00206     data[5] |= 0x10;
00207   }     else {
00208     data[5] &= 0xef;
00209   }
00210 }
00211 
00212 BYTE H224_Frame::GetSegmentNumber() const
00213 {
00214   BYTE *data = GetInformationFieldPtr();
00215         
00216   return (data[5] & 0x0f);
00217 }
00218 
00219 void H224_Frame::SetSegmentNumber(BYTE segmentNumber)
00220 {
00221   BYTE *data = GetInformationFieldPtr();
00222         
00223   data[5] &= 0xf0;
00224   data[5] |= (segmentNumber & 0x0f);
00225 }
00226 
00227 BOOL H224_Frame::Decode(const BYTE *data, 
00228                                                 PINDEX size)
00229 {
00230   BOOL result = Q922_Frame::Decode(data, size);
00231         
00232   if(result == FALSE) {
00233         return FALSE;
00234   }
00235         
00236   // doing some validity check for H.224 frames
00237   BYTE highOrderAddressOctet = GetHighOrderAddressOctet();
00238   BYTE lowOrderAddressOctet = GetLowOrderAddressOctet();
00239   BYTE controlFieldOctet = GetControlFieldOctet();
00240         
00241   if((highOrderAddressOctet != 0x00) ||
00242      (!(lowOrderAddressOctet == 0x61 || lowOrderAddressOctet == 0x71)) ||
00243      (controlFieldOctet != 0x03) ||
00244      (GetClientID() > 0x02))
00245   {             
00246           return FALSE;
00247   }
00248         
00249   return TRUE;
00250 }
00251 
00253 
00254 OpalH224Handler::OpalH224Handler(H323Connection & connection,
00255                                                                  unsigned sessionID)
00256 : transmitMutex()
00257 {
00258   // Really need to check this?
00259 
00260   RTP_Session *session;
00261   H245_TransportAddress addr;
00262   connection.GetControlChannel().SetUpTransportPDU(addr, H323Transport::UseLocalTSAP);
00263   session = connection.UseSession(sessionID,addr,H323Channel::IsBidirectional);
00264 
00265   h281Handler = connection.CreateH281ProtocolHandler(*this);
00266   receiverThread = NULL;
00267         
00268 }
00269 
00270 OpalH224Handler::~OpalH224Handler()
00271 {
00272   delete h281Handler;
00273 }
00274 
00275 void OpalH224Handler::StartTransmit()
00276 {
00277   PWaitAndSignal m(transmitMutex);
00278         
00279   if(canTransmit == TRUE) {
00280     return;
00281   }
00282         
00283   canTransmit = TRUE;
00284         
00285   transmitFrame = new RTP_DataFrame(300);
00286   
00287   // Use payload code 100 as this seems to be common to other implementations
00288   transmitFrame->SetPayloadType((RTP_DataFrame::PayloadTypes)100);
00289   transmitBitIndex = 7;
00290   transmitStartTime = new PTime();
00291         
00292   SendClientList();
00293   SendExtraCapabilities();
00294 }
00295 
00296 void OpalH224Handler::StopTransmit()
00297 {
00298   PWaitAndSignal m(transmitMutex);
00299         
00300   delete transmitStartTime;
00301   transmitStartTime = NULL;
00302         
00303   canTransmit = FALSE;
00304 }
00305 
00306 void OpalH224Handler::StartReceive()
00307 {
00308   if(receiverThread != NULL) {
00309     PTRACE(5, "H.224 handler is already receiving");
00310     return;
00311   }
00312         
00313   receiverThread = CreateH224ReceiverThread();
00314   receiverThread->Resume();
00315 }
00316 
00317 void OpalH224Handler::StopReceive()
00318 {
00319   if(receiverThread != NULL) {
00320     receiverThread->Close();
00321   }
00322 }
00323 
00324 BOOL OpalH224Handler::SendClientList()
00325 {
00326   PWaitAndSignal m(transmitMutex);
00327         
00328   if(canTransmit == FALSE) {
00329     return FALSE;
00330   }
00331         
00332   H224_Frame h224Frame = H224_Frame(4);
00333   h224Frame.SetHighPriority(TRUE);
00334   h224Frame.SetDestinationTerminalAddress(H224_BROADCAST);
00335   h224Frame.SetSourceTerminalAddress(H224_BROADCAST);
00336         
00337   // CME frame
00338   h224Frame.SetClientID(0x00);
00339         
00340   // Begin and end of sequence
00341   h224Frame.SetBS(TRUE);
00342   h224Frame.SetES(TRUE);
00343   h224Frame.SetC1(FALSE);
00344   h224Frame.SetC0(FALSE);
00345   h224Frame.SetSegmentNumber(0);
00346         
00347   BYTE *ptr = h224Frame.GetClientDataPtr();
00348         
00349   ptr[0] = 0x01; // Client list code
00350   ptr[1] = 0x00; // Message code
00351   ptr[2] = 0x01; // one client
00352   ptr[3] = (0x80 | H281_CLIENT_ID); // H.281 with etra capabilities
00353         
00354   TransmitFrame(h224Frame);
00355         
00356   return TRUE;
00357 }
00358 
00359 BOOL OpalH224Handler::SendExtraCapabilities()
00360 {
00361   PWaitAndSignal m(transmitMutex);
00362         
00363   if(canTransmit == FALSE) {
00364     return FALSE;
00365   }
00366         
00367   h281Handler->SendExtraCapabilities();
00368         
00369   return TRUE;
00370 }
00371 
00372 BOOL OpalH224Handler::SendClientListCommand()
00373 {
00374   PWaitAndSignal m(transmitMutex);
00375         
00376   if(canTransmit == FALSE) {
00377     return FALSE;
00378   }
00379         
00380   H224_Frame h224Frame = H224_Frame(2);
00381   h224Frame.SetHighPriority(TRUE);
00382   h224Frame.SetDestinationTerminalAddress(H224_BROADCAST);
00383   h224Frame.SetSourceTerminalAddress(H224_BROADCAST);
00384         
00385   // CME frame
00386   h224Frame.SetClientID(0x00);
00387         
00388   // Begin and end of sequence
00389   h224Frame.SetBS(TRUE);
00390   h224Frame.SetES(TRUE);
00391   h224Frame.SetC1(FALSE);
00392   h224Frame.SetC0(FALSE);
00393   h224Frame.SetSegmentNumber(0);
00394         
00395   BYTE *ptr = h224Frame.GetClientDataPtr();
00396         
00397   ptr[0] = 0x01; // Client list code
00398   ptr[1] = 0xff; // Command code
00399         
00400   TransmitFrame(h224Frame);
00401         
00402   return TRUE;
00403 }
00404 
00405 BOOL OpalH224Handler::SendExtraCapabilitiesCommand(BYTE clientID)
00406 {
00407   PWaitAndSignal m(transmitMutex);
00408         
00409   if(canTransmit == FALSE) {
00410     return FALSE;
00411   }
00412         
00413   if(clientID != H281_CLIENT_ID) {
00414     return FALSE;
00415   }
00416         
00417   H224_Frame h224Frame = H224_Frame(4);
00418   h224Frame.SetHighPriority(TRUE);
00419   h224Frame.SetDestinationTerminalAddress(H224_BROADCAST);
00420   h224Frame.SetSourceTerminalAddress(H224_BROADCAST);
00421         
00422   // CME frame
00423   h224Frame.SetClientID(0x00);
00424         
00425   // Begin and end of sequence
00426   h224Frame.SetBS(TRUE);
00427   h224Frame.SetES(TRUE);
00428   h224Frame.SetC1(FALSE);
00429   h224Frame.SetC0(FALSE);
00430   h224Frame.SetSegmentNumber(0);
00431         
00432   BYTE *ptr = h224Frame.GetClientDataPtr();
00433         
00434   ptr[0] = 0x01; // Client list code
00435   ptr[1] = 0xFF; // Response code
00436   ptr[2] = (0x80 | clientID); // clientID with extra capabilities
00437         
00438   TransmitFrame(h224Frame);
00439         
00440   return TRUE;
00441 }
00442 
00443 BOOL OpalH224Handler::SendExtraCapabilitiesMessage(BYTE clientID, 
00444                                                                                                    BYTE *data, PINDEX length)
00445 {       
00446   PWaitAndSignal m(transmitMutex);
00447         
00448   // only H.281 supported at the moment
00449   if(clientID != H281_CLIENT_ID) {
00450         
00451     return FALSE;
00452   }
00453         
00454   if(canTransmit == FALSE) {
00455     return FALSE;
00456   }
00457         
00458   H224_Frame h224Frame = H224_Frame(length+3);
00459   h224Frame.SetHighPriority(TRUE);
00460   h224Frame.SetDestinationTerminalAddress(H224_BROADCAST);
00461   h224Frame.SetSourceTerminalAddress(H224_BROADCAST);
00462         
00463   // use clientID zero to indicate a CME frame
00464   h224Frame.SetClientID(0x00);
00465         
00466   // Begin and end of sequence, rest is zero
00467   h224Frame.SetBS(TRUE);
00468   h224Frame.SetES(TRUE);
00469   h224Frame.SetC1(FALSE);
00470   h224Frame.SetC0(FALSE);
00471   h224Frame.SetSegmentNumber(0);
00472         
00473   BYTE *ptr = h224Frame.GetClientDataPtr();
00474         
00475   ptr[0] = 0x02; // Extra Capabilities code
00476   ptr[1] = 0x00; // Response Code
00477   ptr[2] = (0x80 | clientID); // EX CAPS and ClientID
00478         
00479   memcpy(ptr+3, data, length);
00480         
00481   TransmitFrame(h224Frame);
00482         
00483   return TRUE;  
00484 }
00485 
00486 BOOL OpalH224Handler::TransmitClientFrame(BYTE clientID, H224_Frame & frame)
00487 {
00488   PWaitAndSignal m(transmitMutex);
00489         
00490   // only H.281 is supported at the moment
00491   if(clientID != H281_CLIENT_ID) {
00492     return FALSE;
00493   }
00494         
00495   frame.SetClientID(clientID);
00496         
00497   TransmitFrame(frame);
00498         
00499   return TRUE;
00500 }
00501 
00502 BOOL OpalH224Handler::OnReceivedFrame(H224_Frame & frame)
00503 {
00504   if(frame.GetDestinationTerminalAddress() != H224_BROADCAST) {
00505     // only broadcast frames are handled at the moment
00506         PTRACE(3, "Received H.224 frame with non-broadcast address");
00507     return TRUE;
00508   }
00509   BYTE clientID = frame.GetClientID();
00510         
00511   if(clientID == 0x00) {
00512     return OnReceivedCMEMessage(frame);
00513   }
00514         
00515   if(clientID == H281_CLIENT_ID)        {
00516     h281Handler->OnReceivedMessage((const H281_Frame &)frame);
00517   }
00518         
00519   return TRUE;
00520 }
00521 
00522 BOOL OpalH224Handler::OnReceivedCMEMessage(H224_Frame & frame)
00523 {
00524   BYTE *data = frame.GetClientDataPtr();
00525         
00526   if(data[0] == 0x01) { // Client list code
00527         
00528     if(data[1] == 0x00) { // Message
00529       return OnReceivedClientList(frame);
00530                 
00531     } else if(data[1] == 0xff) { // Command
00532       return OnReceivedClientListCommand();
00533     }
00534           
00535   } else if(data[0] == 0x02) { // Extra Capabilities code
00536           
00537     if(data[1] == 0x00) { // Message
00538       return OnReceivedExtraCapabilities(frame);
00539                 
00540     } else if(data[1] == 0xff) {// Command
00541       return OnReceivedExtraCapabilitiesCommand();
00542     }
00543   }
00544         
00545   // incorrect frames are simply ignored
00546   return TRUE;
00547 }
00548 
00549 BOOL OpalH224Handler::OnReceivedClientList(H224_Frame & frame)
00550 {
00551   BYTE *data = frame.GetClientDataPtr();
00552         
00553   BYTE numberOfClients = data[2];
00554         
00555   PINDEX i = 3;
00556         
00557   BOOL remoteHasH281 = FALSE;
00558         
00559   while(numberOfClients > 0) {
00560           
00561         BYTE clientID = (data[i] & 0x7f);
00562                 
00563         if(clientID == H281_CLIENT_ID) {
00564           remoteHasH281 = TRUE;
00565           i++;
00566         } else if(clientID == 0x7e) { // extended client ID
00567       i += 2;
00568     } else if(clientID == 0x7f) { // non-standard client ID
00569       i += 6;
00570     } else { // other standard client ID such as T.140
00571       i++;
00572     }
00573     numberOfClients--;
00574   }
00575         
00576   h281Handler->SetRemoteHasH281(remoteHasH281);
00577         
00578   return TRUE;
00579 }
00580 
00581 BOOL OpalH224Handler::OnReceivedClientListCommand()
00582 {
00583   SendClientList();
00584   return TRUE;
00585 }
00586 
00587 BOOL OpalH224Handler::OnReceivedExtraCapabilities(H224_Frame & frame)
00588 {
00589   BYTE *data = frame.GetClientDataPtr();
00590         
00591   BYTE clientID = (data[2] & 0x7f);
00592         
00593   if(clientID == H281_CLIENT_ID) {
00594     PINDEX size = frame.GetClientDataSize() - 3;
00595     h281Handler->OnReceivedExtraCapabilities((data + 3), size);
00596   }
00597         
00598   return TRUE;
00599 }
00600 
00601 BOOL OpalH224Handler::OnReceivedExtraCapabilitiesCommand()
00602 {
00603   SendExtraCapabilities();
00604   return TRUE;
00605 }
00606 
00607 OpalH224ReceiverThread * OpalH224Handler::CreateH224ReceiverThread()
00608 {
00609   return new OpalH224ReceiverThread(this, *session);
00610 }
00611 
00612 void OpalH224Handler::TransmitFrame(H224_Frame & frame)
00613 {       
00614   PINDEX size = frame.GetEncodedSize();
00615         
00616   if(!frame.Encode(transmitFrame->GetPayloadPtr(), size, transmitBitIndex)) {
00617     PTRACE(3, "Failed to encode H.224 frame");
00618     return;
00619   }
00620         
00621   // determining correct timestamp
00622   PTime currentTime = PTime();
00623   PTimeInterval timePassed = currentTime - *transmitStartTime;
00624   transmitFrame->SetTimestamp((DWORD)timePassed.GetMilliSeconds() * 8);
00625   
00626   transmitFrame->SetPayloadSize(size);
00627   transmitFrame->SetMarker(TRUE);
00628         
00629   if(!session->WriteData(*transmitFrame)) {
00630     PTRACE(3, "Failed to write encoded H.224 frame");
00631   }
00632 }
00633 
00635 
00636 OpalH224ReceiverThread::OpalH224ReceiverThread(OpalH224Handler *theH224Handler, RTP_Session & session)
00637 : PThread(10000, NoAutoDeleteThread, HighestPriority, "H.224 Receiver Thread"),
00638   rtpSession(session)
00639 {
00640   h224Handler = theH224Handler;
00641   timestamp = 0;
00642   terminate = FALSE;
00643 }
00644 
00645 OpalH224ReceiverThread::~OpalH224ReceiverThread()
00646 {
00647 }
00648 
00649 void OpalH224ReceiverThread::Main()
00650 {       
00651   RTP_DataFrame packet = RTP_DataFrame(300);
00652   H224_Frame h224Frame = H224_Frame();
00653         
00654   for (;;) {
00655           
00656     inUse.Wait();
00657                 
00658     if(!rtpSession.ReadBufferedData(timestamp, packet)) {
00659       inUse.Signal();
00660       return;
00661     }
00662         
00663     timestamp = packet.GetTimestamp();
00664                 
00665     if(h224Frame.Decode(packet.GetPayloadPtr(), packet.GetPayloadSize())) {
00666       BOOL result = h224Handler->OnReceivedFrame(h224Frame);
00667 
00668       if(result == FALSE) {
00669         // FALSE indicates a serious problem, therefore the thread is closed
00670         return;
00671       }
00672     } else {
00673           PTRACE(3, "Decoding of H.224 frame failed");
00674     }
00675                 
00676     inUse.Signal();
00677                 
00678     if(terminate == TRUE) {
00679       return;
00680     }
00681   }
00682 }
00683 
00684 void OpalH224ReceiverThread::Close()
00685 {
00686   rtpSession.Close(TRUE);
00687         
00688   inUse.Wait();
00689         
00690   terminate = TRUE;
00691         
00692   inUse.Signal();
00693         
00694   PAssert(WaitForTermination(10000), "H224 receiver thread not terminated");
00695 }
00696 
00697 #endif // H323_H224

Generated on Thu Oct 25 13:42:43 2007 for h323plus by  doxygen 1.5.2