SocketDescriptor Class Reference

Collaboration diagram for SocketDescriptor:

Collaboration graph
[legend]

Public Member Functions

 SocketDescriptor (UsageEnvironment &env, int socketNum)
virtual ~SocketDescriptor ()
void registerRTPInterface (unsigned char streamChannelId, RTPInterface *rtpInterface)
RTPInterfacelookupRTPInterface (unsigned char streamChannelId)
void deregisterRTPInterface (unsigned char streamChannelId)
void setServerRequestAlternativeByteHandler (ServerRequestAlternativeByteHandler *handler, void *clientData)

Private Types

enum  {
  AWAITING_DOLLAR, AWAITING_STREAM_CHANNEL_ID, AWAITING_SIZE1, AWAITING_SIZE2,
  AWAITING_PACKET_DATA
}

Private Member Functions

Boolean tcpReadHandler1 (int mask)

Static Private Member Functions

static void tcpReadHandler (SocketDescriptor *, int mask)

Private Attributes

UsageEnvironmentfEnv
int fOurSocketNum
HashTablefSubChannelHashTable
ServerRequestAlternativeByteHandlerfServerRequestAlternativeByteHandler
void * fServerRequestAlternativeByteHandlerClientData
u_int8_t fStreamChannelId
u_int8_t fSizeByte1
Boolean fReadErrorOccurred
Boolean fDeleteMyselfNext
enum SocketDescriptor:: { ... }  fTCPReadingState

Detailed Description

Definition at line 48 of file RTPInterface.cpp.


Member Enumeration Documentation

anonymous enum [private]

Enumerator:
AWAITING_DOLLAR 
AWAITING_STREAM_CHANNEL_ID 
AWAITING_SIZE1 
AWAITING_SIZE2 
AWAITING_PACKET_DATA 

Definition at line 75 of file RTPInterface.cpp.


Constructor & Destructor Documentation

SocketDescriptor::SocketDescriptor ( UsageEnvironment env,
int  socketNum 
)

Definition at line 342 of file RTPInterface.cpp.

SocketDescriptor::~SocketDescriptor (  )  [virtual]

Definition at line 349 of file RTPInterface.cpp.

References fEnv, fOurSocketNum, fReadErrorOccurred, fServerRequestAlternativeByteHandler, fServerRequestAlternativeByteHandlerClientData, fSubChannelHashTable, NULL, HashTable::RemoveNext(), removeSocketDescription(), UsageEnvironment::taskScheduler(), and TaskScheduler::turnOffBackgroundReadHandling().

00349                                     {
00350   fEnv.taskScheduler().turnOffBackgroundReadHandling(fOurSocketNum);
00351   if (fServerRequestAlternativeByteHandler != NULL) {
00352     // Hack: Pass a special character to our alternative byte handler, to tell it that either
00353     // - an error occurred when reading the TCP socket, or
00354     // - no error occurred, but it needs to take over control of the TCP socket once again.
00355     u_int8_t specialChar = fReadErrorOccurred ? 0xFF : 0xFE;
00356     (*fServerRequestAlternativeByteHandler)(fServerRequestAlternativeByteHandlerClientData, specialChar);
00357   }
00358   removeSocketDescription(fEnv, fOurSocketNum);
00359 
00360   if (fSubChannelHashTable != NULL) {
00361     while (fSubChannelHashTable->RemoveNext() != NULL) {} // remove the "RTPInterface"s from the table, but don't delete them
00362     delete fSubChannelHashTable;
00363   }
00364 }


Member Function Documentation

void SocketDescriptor::registerRTPInterface ( unsigned char  streamChannelId,
RTPInterface rtpInterface 
)

Definition at line 366 of file RTPInterface.cpp.

References HashTable::Add(), fEnv, fOurSocketNum, fSubChannelHashTable, HashTable::IsEmpty(), SOCKET_EXCEPTION, SOCKET_READABLE, UsageEnvironment::taskScheduler(), and tcpReadHandler().

Referenced by RTPInterface::startNetworkReading().

00367                                                                         {
00368   Boolean isFirstRegistration = fSubChannelHashTable->IsEmpty();
00369 #if defined(DEBUG_SEND)||defined(DEBUG_RECEIVE)
00370   fprintf(stderr, "SocketDescriptor(socket %d)::registerRTPInterface(channel %d): isFirstRegistration %d\n", fOurSocketNum, streamChannelId, isFirstRegistration);
00371 #endif
00372   fSubChannelHashTable->Add((char const*)(long)streamChannelId,
00373                             rtpInterface);
00374 
00375   if (isFirstRegistration) {
00376     // Arrange to handle reads on this TCP socket:
00377     TaskScheduler::BackgroundHandlerProc* handler
00378       = (TaskScheduler::BackgroundHandlerProc*)&tcpReadHandler;
00379     fEnv.taskScheduler().
00380       setBackgroundHandling(fOurSocketNum, SOCKET_READABLE|SOCKET_EXCEPTION, handler, this);
00381   }
00382 }

RTPInterface * SocketDescriptor::lookupRTPInterface ( unsigned char  streamChannelId  ) 

Definition at line 385 of file RTPInterface.cpp.

References fSubChannelHashTable, and HashTable::Lookup().

Referenced by tcpReadHandler1().

00385                                                   {
00386   char const* lookupArg = (char const*)(long)streamChannelId;
00387   return (RTPInterface*)(fSubChannelHashTable->Lookup(lookupArg));
00388 }

void SocketDescriptor::deregisterRTPInterface ( unsigned char  streamChannelId  ) 

Definition at line 391 of file RTPInterface.cpp.

References fDeleteMyselfNext, fOurSocketNum, fSubChannelHashTable, HashTable::IsEmpty(), HashTable::Remove(), and True.

Referenced by deregisterSocket().

00391                                                       {
00392 #if defined(DEBUG_SEND)||defined(DEBUG_RECEIVE)
00393   fprintf(stderr, "SocketDescriptor(socket %d)::deregisterRTPInterface(channel %d)\n", fOurSocketNum, streamChannelId);
00394 #endif
00395   fSubChannelHashTable->Remove((char const*)(long)streamChannelId);
00396 
00397   if (fSubChannelHashTable->IsEmpty()) {
00398     // No more interfaces are using us, so it's curtains for us now:
00399     fDeleteMyselfNext = True; // hack to cause ourself to be deleted from "tcpReadHandler()" below
00400   }
00401 }

void SocketDescriptor::setServerRequestAlternativeByteHandler ( ServerRequestAlternativeByteHandler handler,
void *  clientData 
) [inline]

Definition at line 58 of file RTPInterface.cpp.

References fServerRequestAlternativeByteHandler, and fServerRequestAlternativeByteHandlerClientData.

Referenced by RTPInterface::setServerRequestAlternativeByteHandler().

00058                                                                                                               {
00059     fServerRequestAlternativeByteHandler = handler;
00060     fServerRequestAlternativeByteHandlerClientData = clientData;
00061   }

void SocketDescriptor::tcpReadHandler ( SocketDescriptor ,
int  mask 
) [static, private]

Definition at line 403 of file RTPInterface.cpp.

References fDeleteMyselfNext, and tcpReadHandler1().

Referenced by registerRTPInterface().

00403                                                                                   {
00404   // Call the read handler until it returns false, with a limit to avoid starving other sockets
00405   unsigned count = 2000;
00406   while (!socketDescriptor->fDeleteMyselfNext && socketDescriptor->tcpReadHandler1(mask) && --count > 0) {}
00407   if (socketDescriptor->fDeleteMyselfNext) delete socketDescriptor;
00408 }

Boolean SocketDescriptor::tcpReadHandler1 ( int  mask  )  [private]

Definition at line 410 of file RTPInterface.cpp.

References AWAITING_DOLLAR, AWAITING_PACKET_DATA, AWAITING_SIZE1, AWAITING_SIZE2, AWAITING_STREAM_CHANNEL_ID, False, fDeleteMyselfNext, fEnv, RTPInterface::fNextTCPReadSize, RTPInterface::fNextTCPReadStreamChannelId, RTPInterface::fNextTCPReadStreamSocketNum, fOurSocketNum, RTPInterface::fOwner, fReadErrorOccurred, RTPInterface::fReadHandlerProc, fServerRequestAlternativeByteHandler, fServerRequestAlternativeByteHandlerClientData, fSizeByte1, fStreamChannelId, fTCPReadingState, lookupRTPInterface(), NULL, readSocket(), size, and True.

Referenced by tcpReadHandler().

00410                                                   {
00411   // We expect the following data over the TCP channel:
00412   //   optional RTSP command or response bytes (before the first '$' character)
00413   //   a '$' character
00414   //   a 1-byte channel id
00415   //   a 2-byte packet size (in network byte order)
00416   //   the packet data.
00417   // However, because the socket is being read asynchronously, this data might arrive in pieces.
00418   
00419   u_int8_t c;
00420   struct sockaddr_in fromAddress;
00421   if (fTCPReadingState != AWAITING_PACKET_DATA) {
00422     int result = readSocket(fEnv, fOurSocketNum, &c, 1, fromAddress);
00423     if (result == 0) { // There was no more data to read
00424       return False;
00425     } else if (result != 1) { // error reading TCP socket, so we will no longer handle it
00426 #ifdef DEBUG_RECEIVE
00427       fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): readSocket(1 byte) returned %d (error)\n", fOurSocketNum, result);
00428 #endif
00429       fReadErrorOccurred = True;
00430       fDeleteMyselfNext = True;
00431       return False;
00432     }
00433   }
00434 
00435   Boolean callAgain = True;
00436   switch (fTCPReadingState) {
00437     case AWAITING_DOLLAR: {
00438       if (c == '$') {
00439 #ifdef DEBUG_RECEIVE
00440         fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): Saw '$'\n", fOurSocketNum);
00441 #endif
00442         fTCPReadingState = AWAITING_STREAM_CHANNEL_ID;
00443       } else {
00444         // This character is part of a RTSP request or command, which is handled separately:
00445         if (fServerRequestAlternativeByteHandler != NULL && c != 0xFF && c != 0xFE) {
00446           // Hack: 0xFF and 0xFE are used as special signaling characters, so don't send them
00447           (*fServerRequestAlternativeByteHandler)(fServerRequestAlternativeByteHandlerClientData, c);
00448         }
00449       }
00450       break;
00451     }
00452     case AWAITING_STREAM_CHANNEL_ID: {
00453       // The byte that we read is the stream channel id.
00454       if (lookupRTPInterface(c) != NULL) { // sanity check
00455         fStreamChannelId = c;
00456         fTCPReadingState = AWAITING_SIZE1;
00457       } else {
00458         // This wasn't a stream channel id that we expected.  We're (somehow) in a strange state.  Try to recover:
00459 #ifdef DEBUG_RECEIVE
00460         fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): Saw nonexistent stream channel id: 0x%02x\n", fOurSocketNum, c);
00461 #endif
00462         fTCPReadingState = AWAITING_DOLLAR;
00463       }
00464       break;
00465     }
00466     case AWAITING_SIZE1: {
00467       // The byte that we read is the first (high) byte of the 16-bit RTP or RTCP packet 'size'.
00468       fSizeByte1 = c;
00469       fTCPReadingState = AWAITING_SIZE2;
00470       break;
00471     }
00472     case AWAITING_SIZE2: {
00473       // The byte that we read is the second (low) byte of the 16-bit RTP or RTCP packet 'size'.
00474       unsigned short size = (fSizeByte1<<8)|c;
00475       
00476       // Record the information about the packet data that will be read next:
00477       RTPInterface* rtpInterface = lookupRTPInterface(fStreamChannelId);
00478       if (rtpInterface != NULL) {
00479         rtpInterface->fNextTCPReadSize = size;
00480         rtpInterface->fNextTCPReadStreamSocketNum = fOurSocketNum;
00481         rtpInterface->fNextTCPReadStreamChannelId = fStreamChannelId;
00482       }
00483       fTCPReadingState = AWAITING_PACKET_DATA;
00484       break;
00485     }
00486     case AWAITING_PACKET_DATA: {
00487       callAgain = False;
00488       fTCPReadingState = AWAITING_DOLLAR; // the next state, unless we end up having to read more data in the current state
00489       // Call the appropriate read handler to get the packet data from the TCP stream:
00490       RTPInterface* rtpInterface = lookupRTPInterface(fStreamChannelId);
00491       if (rtpInterface != NULL) {
00492         if (rtpInterface->fNextTCPReadSize == 0) {
00493           // We've already read all the data for this packet.
00494           break;
00495         }
00496         if (rtpInterface->fReadHandlerProc != NULL) {
00497 #ifdef DEBUG_RECEIVE
00498           fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): reading %d bytes on channel %d\n", fOurSocketNum, rtpInterface->fNextTCPReadSize, rtpInterface->fNextTCPReadStreamChannelId);
00499 #endif
00500           fTCPReadingState = AWAITING_PACKET_DATA;
00501           rtpInterface->fReadHandlerProc(rtpInterface->fOwner, mask);
00502         } else {
00503 #ifdef DEBUG_RECEIVE
00504           fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): No handler proc for \"rtpInterface\" for channel %d; need to skip %d remaining bytes\n", fOurSocketNum, fStreamChannelId, rtpInterface->fNextTCPReadSize);
00505 #endif
00506           int result = readSocket(fEnv, fOurSocketNum, &c, 1, fromAddress);
00507           if (result < 0) { // error reading TCP socket, so we will no longer handle it
00508 #ifdef DEBUG_RECEIVE
00509             fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): readSocket(1 byte) returned %d (error)\n", fOurSocketNum, result);
00510 #endif
00511             fReadErrorOccurred = True;
00512             fDeleteMyselfNext = True;
00513             return False;
00514           } else {
00515             fTCPReadingState = AWAITING_PACKET_DATA;
00516             if (result == 1) {
00517               --rtpInterface->fNextTCPReadSize;
00518               callAgain = True;
00519             }
00520           }
00521         }
00522       }
00523 #ifdef DEBUG_RECEIVE
00524       else fprintf(stderr, "SocketDescriptor(socket %d)::tcpReadHandler(): No \"rtpInterface\" for channel %d\n", fOurSocketNum, fStreamChannelId);
00525 #endif
00526     }
00527   }
00528 
00529   return callAgain;
00530 }


Field Documentation

UsageEnvironment& SocketDescriptor::fEnv [private]

Definition at line 68 of file RTPInterface.cpp.

Referenced by registerRTPInterface(), tcpReadHandler1(), and ~SocketDescriptor().

int SocketDescriptor::fOurSocketNum [private]

Definition at line 69 of file RTPInterface.cpp.

Referenced by deregisterRTPInterface(), registerRTPInterface(), tcpReadHandler1(), and ~SocketDescriptor().

HashTable* SocketDescriptor::fSubChannelHashTable [private]

Definition at line 70 of file RTPInterface.cpp.

Referenced by deregisterRTPInterface(), lookupRTPInterface(), registerRTPInterface(), and ~SocketDescriptor().

ServerRequestAlternativeByteHandler* SocketDescriptor::fServerRequestAlternativeByteHandler [private]

Definition at line 71 of file RTPInterface.cpp.

Referenced by setServerRequestAlternativeByteHandler(), tcpReadHandler1(), and ~SocketDescriptor().

void* SocketDescriptor::fServerRequestAlternativeByteHandlerClientData [private]

Definition at line 72 of file RTPInterface.cpp.

Referenced by setServerRequestAlternativeByteHandler(), tcpReadHandler1(), and ~SocketDescriptor().

u_int8_t SocketDescriptor::fStreamChannelId [private]

Definition at line 73 of file RTPInterface.cpp.

Referenced by tcpReadHandler1().

u_int8_t SocketDescriptor::fSizeByte1 [private]

Definition at line 73 of file RTPInterface.cpp.

Referenced by tcpReadHandler1().

Boolean SocketDescriptor::fReadErrorOccurred [private]

Definition at line 74 of file RTPInterface.cpp.

Referenced by tcpReadHandler1(), and ~SocketDescriptor().

Boolean SocketDescriptor::fDeleteMyselfNext [private]

Definition at line 74 of file RTPInterface.cpp.

Referenced by deregisterRTPInterface(), tcpReadHandler(), and tcpReadHandler1().

enum { ... } SocketDescriptor::fTCPReadingState [private]

Referenced by tcpReadHandler1().


The documentation for this class was generated from the following file:
Generated on Tue Jun 18 13:21:34 2013 for live by  doxygen 1.5.2