void CMuxCodec::fiboCode(unsigned int nb)
{
	if ( nbBits >= 8 )
		emptyBuffer();

	int i = 1, t;
	for( ; nbFibo[i] <= nb; i++){
	}
	int l = i + 1;
	i--;
	nb -= nbFibo[i];

	register unsigned int r = 0xC0000000;
	t = i;
	i--;
	while( nb > 0 ){
		i--;
		if (nbFibo[i] <= nb){
			nb -= nbFibo[i];
			r >>= t-i;
			r |= 0x80000000;
			t = i;
			i--;
		}
	}
// Handles an incoming message (from the message queue).
UtlBoolean SipClientWriteBuffer::handleMessage(OsMsg& eventMessage)
{
   UtlBoolean messageProcessed = FALSE;

   int msgType = eventMessage.getMsgType();
   int msgSubType = eventMessage.getMsgSubType();

   if (msgType == OsMsg::OS_SHUTDOWN)
   {
      // When shutting down, have to return all queued outgoing messages
      // with transport errors.
      emptyBuffer(TRUE);

      // Continue with shutdown processing.
      messageProcessed = FALSE;
   }
   else if (msgType == OsMsg::OS_EVENT
           &&  (msgSubType == SipClientSendMsg::SIP_CLIENT_SEND
             || msgSubType == SipClientSendMsg::SIP_CLIENT_SEND_KEEP_ALIVE))
   {
      // Queued SIP message to send - normal path.
      if (msgSubType == SipClientSendMsg::SIP_CLIENT_SEND)
      {
          // Insert the SIP message into the queue, detaching it from
          // the incoming eventMessage.
          SipClientSendMsg* sendMsg =
             dynamic_cast <SipClientSendMsg*> (&eventMessage);
          if (sendMsg)
          {
             insertMessage(sendMsg->detachMessage());
             messageProcessed = TRUE;
          }
          else
          {
             Os::Logger::instance().log(FAC_SIP, PRI_CRIT,
                           "SipClientWriteBuffer[%s]::handleMessage "
                           "message is not a SipClientSendMsg",
                           mName.data());
          }
      }
      else // send Keep Alive
      {
          Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                        "SipClientWriteBuffer[%s]::handleMessage send TCP keep-alive CR-LF response",
                        mName.data());
          UtlString* pKeepAlive;
          pKeepAlive = new UtlString("\r\n");
          insertMessage(pKeepAlive);
          messageProcessed = TRUE;
      }

      // Write what we can.
      writeMore();

      // sendMsg will be deleted by ::run(), as usual.
      // Its destructor will free any storage owned by it.
   }

   return (messageProcessed);
}
Beispiel #3
0
int getUserOkay() {
    int ok = 0;
    char c = 0;
    do {
        ok = scanf("%c", &c);
        emptyBuffer();
    } while (!ok);

    if (c == 'y') {
        return 1;
    }
    return 0;
}
Beispiel #4
0
/**
 * Get the number from the user.
 * Ensures it will return a positive integer.
 * Will loop until it gets a correct number from the user.
 *
 * 123foo is considered as 123.
 * foo123 is refused.
 * <space>123 is considered as 123.
 */
long getNumber(const char* nom, long min, long max) {
    int ok = 0;
    long n = 0;
    int checkMax = 1;
    if (max <= min) {
        checkMax = 0;
    }
    do {
        if (checkMax) {
            printf("Input %ld < %s < %ld : ", min - 1, nom, max + 1);
        }
        else {
            printf("Input %s > %ld : ", nom, min - 1);
        }
        ok = scanf("%ld", &n);
        emptyBuffer();
    } while (!ok || n < min || (checkMax && n > max));

    return n;
}
void AudioInputConfig::on_Tick_timeout() {
        if (!inputProcessor) {
            inputProcessor = new QtSpeex::SpeexInputProcessor();
            inputProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered);

            if (!inputDevice) {
                inputDevice = AudioDeviceHelper::getPreferedInputDevice();
            }
            inputDevice->start(inputProcessor);
            connect(inputProcessor, SIGNAL(networkPacketReady()), this, SLOT(emptyBuffer()));
        }

        abSpeech->iBelow = ui.qsTransmitMin->value();
        abSpeech->iAbove = ui.qsTransmitMax->value();
        if (loaded) {
            rsVoip->setVoipfVADmin(ui.qsTransmitMin->value());
            rsVoip->setVoipfVADmax(ui.qsTransmitMax->value());
        }

        abSpeech->iValue = iroundf(inputProcessor->dVoiceAcivityLevel * 32767.0f + 0.5f);

        abSpeech->update();
}
Beispiel #6
0
void *oompaChild(void *boxSize) {
	int size = ((candy_struct *)boxSize)->num;
	candy_struct* box = malloc(size * sizeof(candy_struct));
	while (1){
		//grab the stuff off the assembly line
		for (int i = 0; i < size; ++i) {
			pthread_mutex_lock(&mutex);
			if (!emptyBuffer()) {
				box[i] = removeCandy();
			}
			else {
				--i;
			}
			// pthread_mutex_unlock(&mutex);
			// print the contents of the box
			if (i == size - 1) {
				// pthread_mutex_lock(&mu`tex);
				printBox(box, size);
			}
			pthread_mutex_unlock(&mutex);
		}
	}
	pthread_exit(NULL);
}
Beispiel #7
0
int main(void)
{
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif

    SOCKET sock;
    SOCKADDR_IN sin;
    int loop=1,i=0;
    unsigned short buffer[LG_BUF],repServ=0;
    unsigned long nb=0;
    client infoClient;

    //initialisation du buffer
    for(i=0;i<LG_BUF;i++)
        buffer[i]=0;

    /* Si les sockets Windows fonctionnent */
    if(!erreur)
    {
        printf("Entrer l'adresse IP du serveur de communication :");
        scanf("%s",buffer);
        emptyBuffer();

        /* Création de la socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);

        /* Configuration de la connexion */
        sin.sin_addr.s_addr = inet_addr(buffer);
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);

        /* Si l'on a réussi à se connecter */
        if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
        {
            printf("Connection a %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));

            infoClient=autoten(sock);

            do{
                printf("%s :",infoClient.login);
                message(buffer);

                nb=strlen(buffer)*2+2;
                nb=htonl(nb);

                if(send(sock, &nb, 4, 0)==SOCKET_ERROR)
                    printf("Envoie de la chaine echouer.\n");

                for(i=0;i<LG_BUF;i++)
                    buffer[i]=htons(buffer[i]);
                nb=ntohl(nb);
                if(send(sock, buffer, nb, 0) == SOCKET_ERROR)
                    printf("Erreur de transmission\n");
                for(i=0;i<LG_BUF;i++)
                    buffer[i]=ntohs(buffer[i]);

                if(!(strcmp(buffer,"exit")) || !(strcmp(buffer,"shutdown")) )
                    loop=0;

                recv(sock,&repServ,2,0);
                repServ=ntohs(repServ);
                if(repServ==1)
                {
                    if(recv(sock, &nb, 4, 0) == SOCKET_ERROR)
                        printf("Erreur de la reception de la taille\n");
                    nb=ntohl(nb);

                    if(recv(sock, buffer, nb, 0) != SOCKET_ERROR){
                        for(i=0;i<LG_BUF;i++)
                            buffer[i]=ntohs(buffer[i]);
                        printf("Reponse serveur: %s\n", buffer);
                    }
                    else
                        printf("Erreur de la reception de la chaine de caractere.\n");
                }
                else if(repServ==2)
                {
                    if(recv(sock, &nb, 4, 0) == SOCKET_ERROR)
                        printf("Erreur de la reception du numero de la commande ADMIN\n");

                    else
                    {
                        nb=ntohl(nb);
                        if(nb==COMMANDE_SEND_ADMIN){
                            repServ=htons(1);
                            if(send(sock, &repServ, 2, 0)==SOCKET_ERROR)
                                printf("Envoie du signal echouer.\n");
                            envoitFichier(sock,buffer);
                        }
                        else if(nb==COMMANDE_LS_ADMIN){
                            repServ=htons(1);
                            if(send(sock, &repServ, 2, 0)==SOCKET_ERROR)
                                printf("Envoie du signal echouer.\n");
                            cmdLS(sock);
                        }
                        else
                        {
                            printf("Le client ne connait pas cette commande ADMIN. Mettez a jour votre logiciel.\n");
                            repServ=htons(0);
                            if(send(sock, &repServ, 2, 0)==SOCKET_ERROR)
                                printf("Envoie du signal echouer.\n");
                        }

                        if(recv(sock, &nb, 4, 0) == SOCKET_ERROR)
                            printf("Erreur de la reception de la taille\n");
                        nb=ntohl(nb);

                        if(recv(sock, buffer, nb, 0) != SOCKET_ERROR){
                            for(i=0;i<LG_BUF;i++)
                                buffer[i]=ntohs(buffer[i]);
                            printf("Reponse serveur: %s\n", buffer);
                        }
                        else
                            printf("Erreur de la reception de la chaine de caractere.\n");
                        }
                }
                repServ=0;
            }while(loop);
        }
        /* sinon, on affiche "Impossible de se connecter" */
        else
        {
            printf("Impossible de se connecter\n");
        }

        /* On ferme la socket */
        closesocket(sock);

        #if defined (WIN32)
            WSACleanup();
        #endif
    }

    /* On attend que l'utilisateur tape sur une touche, puis on ferme */
    getchar();

    return EXIT_SUCCESS;
}
Beispiel #8
0
status_t BnOMX::onTransact(
    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    switch (code) {
        case LIVES_LOCALLY:
        {
            CHECK_INTERFACE(IOMX, data, reply);
            reply->writeInt32(livesLocally((pid_t)data.readInt32()));

            return OK;
        }

        case LIST_NODES:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            List<ComponentInfo> list;
            listNodes(&list);

            reply->writeInt32(list.size());
            for (List<ComponentInfo>::iterator it = list.begin();
                 it != list.end(); ++it) {
                ComponentInfo &cur = *it;

                reply->writeString8(cur.mName);
                reply->writeInt32(cur.mRoles.size());
                for (List<String8>::iterator role_it = cur.mRoles.begin();
                     role_it != cur.mRoles.end(); ++role_it) {
                    reply->writeString8(*role_it);
                }
            }

            return NO_ERROR;
        }

        case ALLOCATE_NODE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

            status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
            if (err == OK) {
                reply->writeIntPtr((intptr_t)node);
            }

            return NO_ERROR;
        }

        case FREE_NODE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();

            reply->writeInt32(freeNode(node));

            return NO_ERROR;
        }

        case SEND_COMMAND:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();

            OMX_COMMANDTYPE cmd =
                static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

            return NO_ERROR;
        }

        case GET_PARAMETER:
        case SET_PARAMETER:
        case GET_CONFIG:
        case SET_CONFIG:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

            size_t size = data.readInt32();

            void *params = malloc(size);
            data.read(params, size);

            status_t err;
            switch (code) {
                case GET_PARAMETER:
                    err = getParameter(node, index, params, size);
                    break;
                case SET_PARAMETER:
                    err = setParameter(node, index, params, size);
                    break;
                case GET_CONFIG:
                    err = getConfig(node, index, params, size);
                    break;
                case SET_CONFIG:
                    err = setConfig(node, index, params, size);
                    break;
                default:
                    TRESPASS();
            }

            reply->writeInt32(err);

            if ((code == GET_PARAMETER || code == GET_CONFIG) && err == OK) {
                reply->write(params, size);
            }

            free(params);
            params = NULL;

            return NO_ERROR;
        }

        case GET_STATE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_STATETYPE state = OMX_StateInvalid;

            status_t err = getState(node, &state);
            reply->writeInt32(state);
            reply->writeInt32(err);

            return NO_ERROR;
        }

        case ENABLE_GRAPHIC_BUFFERS:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

            status_t err = enableGraphicBuffers(node, port_index, enable);
            reply->writeInt32(err);

            return NO_ERROR;
        }

        case GET_GRAPHIC_BUFFER_USAGE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();

            OMX_U32 usage = 0;
            status_t err = getGraphicBufferUsage(node, port_index, &usage);
            reply->writeInt32(err);
            reply->writeInt32(usage);

            return NO_ERROR;
        }

        case USE_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
            status_t err = useBuffer(node, port_index, params, &buffer);
            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case USE_GRAPHIC_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            sp<GraphicBuffer> graphicBuffer = new GraphicBuffer();
            data.read(*graphicBuffer);

            buffer_id buffer;
            status_t err = useGraphicBuffer(
                    node, port_index, graphicBuffer, &buffer);
            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case STORE_META_DATA_IN_BUFFERS:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            OMX_BOOL enable = (OMX_BOOL)data.readInt32();

            status_t err = storeMetaDataInBuffers(node, port_index, enable);
            reply->writeInt32(err);

            return NO_ERROR;
        }

        case ALLOC_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            size_t size = data.readInt32();

            buffer_id buffer;
            void *buffer_data;
            status_t err = allocateBuffer(
                    node, port_index, size, &buffer, &buffer_data);
            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
                reply->writeIntPtr((intptr_t)buffer_data);
            }

            return NO_ERROR;
        }

        case ALLOC_BUFFER_WITH_BACKUP:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
            status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer);

            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case FREE_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (void*)data.readIntPtr();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

            return NO_ERROR;
        }

        case FILL_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            buffer_id buffer = (void*)data.readIntPtr();
            reply->writeInt32(fillBuffer(node, buffer));

            return NO_ERROR;
        }

        case EMPTY_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            buffer_id buffer = (void*)data.readIntPtr();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();

            reply->writeInt32(
                    emptyBuffer(
                        node, buffer, range_offset, range_length,
                        flags, timestamp));

            return NO_ERROR;
        }

        case GET_EXTENSION_INDEX:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            const char *parameter_name = data.readCString();

            OMX_INDEXTYPE index;
            status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

            if (err == OK) {
                reply->writeInt32(index);
            }

            return OK;
        }

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
Beispiel #9
0
/*!
 * \brief Get the next token in the stream
 */
HllTokenizer::Token HllTokenizer::getNext()
{
	Token next;

	// Start out by moving past any whitespace
	skipCharacters(whitespace);

	// Check if we've reached the end of the file
	if(!fillBuffer(1)) {
		next = createToken(Token::TypeEnd, "");
		return next;
	}

	// Scan through the list of literals and see if any match
	if(scanLiteral(literals, next)) {
		return next;
	}

	// If no literals matched, see if an identifier can be constructed
	if(std::isalpha(buffer()[0]) || buffer()[0] == '_') {
		size_t len = 0;
		while(std::isalpha(buffer()[len]) || buffer()[len] == '_') {
			len++;
			if(!fillBuffer(len + 1)) {
				break;
			}
		}

		TokenType type = TypeIdentifier;
		std::string string = buffer().substr(0, len);

		// Check if the string is a keyword
		for(std::string &keyword : keywords) {
			if(string == keyword) {
				type = TypeLiteral;
				break;
			}
		}

		// Construct a token out of the characters found
		next = createToken(type, string);
		emptyBuffer(len);
		return next;
	}

	// If an identifier couldn't be found, check for a number
	if(std::isdigit(buffer()[0])) {
		size_t len = 0;
		while(std::isdigit(buffer()[len])) {
			len++;
			if(!fillBuffer(len + 1)) {
				break;
			}
		}

		// Construct a token out of the characters found
		next = createToken(TypeNumber, buffer().substr(0, len));
		emptyBuffer(len);
		return next;
	}

	if(buffer()[0] == '\"') {
		size_t len = 1;
		while(true) {
			if(!fillBuffer(len + 1)) {
				setError("Unterminated string literal");
				return next;
			}

			if(buffer()[len] == '\"') {
				break;
			}
			len++;
		}

		// Construct a token out of the characters found
		std::string text = buffer().substr(1, len - 1);
		emptyBuffer(len + 1);

		if(evaluateEscapes(text)) {
			next = createToken(TypeString, text);
		}
		return next;
	}

	if(buffer()[0] == '\'') {
		size_t len = 1;
		while(true) {
			if(!fillBuffer(len + 1)) {
				setError("Unterminated character literal");
				return next;
			}

			if(buffer()[len] == '\'') {
				break;
			}
			len++;
		}

		// Construct a token out of the characters found
		std::string text = buffer().substr(1, len - 1);
		emptyBuffer(len + 1);

		if(evaluateEscapes(text)) {
			if(text.size() == 1) {
				next = createToken(TypeChar, text);
			} else {
				setError("Invalid character literal");
			}
		}
		return next;
	}

	// Nothing matched, log an error
	std::stringstream ss;
	ss << "Illegal symbol '" << buffer()[0] << "'";
	setError(ss.str());

	return next;
}
Beispiel #10
0
// Thread execution code.
int SipClient::run(void* runArg)
{
   OsMsg*    pMsg = NULL;
   OsStatus  res;
   // Buffer to hold data read from the socket but not yet parsed
   // into incoming SIP messages.
   UtlString readBuffer;
   bool      waitingToReportErr  = FALSE;    // controls whether to read-select on socket
   bool      tcpOnErrWaitForSend = TRUE;
   int       repeatedEOFs = 0;

   Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                 "SipClient[%s]::run start  "
                 "tcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d",
                 mName.data(), tcpOnErrWaitForSend, waitingToReportErr,
                 mbTcpOnErrWaitForSend, repeatedEOFs);

   // Wait structure:
   struct pollfd fds[2];
   // Incoming message on the message queue (to be sent on the socket).
   fds[0].fd = mPipeReadingFd;
   // Socket ready to write (to continue sending message).
   // Socket ready to read (message to be received).

   do
   {
      assert(repeatedEOFs < 20);
      // The file descriptor for the socket may changemsg->getSendAddress(&fromIpAddress, &fromPort);, as OsSocket's
      // can be re-opened.
      fds[1].fd = mClientSocket->getSocketDescriptor();

      // Initialize the revents members.
      // This may not be necessary (the man page is not clear), but
      // Valgrind flags 'fds[*].revents' as undefined if they aren't
      // initialized.
      fds[0].revents = 0;
      fds[1].revents = 0;

      fds[0].events = POLLIN;   // only read-select on pipe

      // For non-blocking connect failures, don't read-select on socket if
      // the initial read showed an error but we have to wait to report it.
      if (!waitingToReportErr)
      {
          // This is the normal path.
          // Read the socket only if the socket is not shared.
          // If it is shared, the ancestral SipClient will read it.
          // If multiple threads attempt to read the socket, poll() may
          // succeed but another may read the data, leaving us to block on
          // read.
          fds[1].events = mbSharedSocket ? 0 : POLLIN;

          // Set wait for writing the socket if there is queued messages to
          // send.
          if (mWriteQueued)
          {
             // Wait for output on the socket to not block.
             fds[1].events |= POLLOUT;
          }

      }
      else
      {
          // just waiting to report error, ignore the socket
          fds[1].fd =-1;
          fds[1].events = 0;
      }

      // If there is residual data in the read buffer,
      // pretend the socket is ready to read.
      if (!readBuffer.isNull())
      {
         fds[1].revents = POLLIN;
      }
      else
      {
         // Otherwise, call poll() to wait.
         int resPoll = poll(&fds[0], sizeof (fds) / sizeof (fds[0]),
                        POLL_TIMEOUT);
         assert(resPoll >= 0 || (resPoll == -1 && errno == EINTR));
         if (resPoll != 0)
         {
             Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                           "SipClient[%s]::run "
                           "resPoll= %d revents: fd[0]= %x fd[1]= %x",
                           mName.data(),
                           resPoll, fds[0].revents, fds[1].revents );
         }
      }

      if ((fds[1].revents & (POLLERR | POLLHUP)) != 0)
      {
          Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                        "SipClient[%s]::run "
                        "SipMessage::poll error(%d) ",
                        mName.data(), errno);

          if (OsSocket::isFramed(mClientSocket->getIpProtocol()))
          {
              Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                            "SipClient[%s]::run "
                            "SipMessage::poll error(%d) got POLLERR | POLLHUP on UDP socket",
                            mName.data(), errno);

          }
          else	// eg. tcp socket
          // This client's socket is a connection-oriented protocol and the
          // connection has been terminated (probably by the remote end).
          // We must terminate the SipClient.
          // We drop the queued messages, but we do not report them to
          // SipUserAgent as failed sends.  This will cause SipUserAgent to
          // retry the send using the same transport (rather than continuing
          // to the next transport), which should cause a new connection to
          // be made to the remote end.
          {
              // On non-blocking connect failures, we need to get the first send message
              // in order to successfully trigger the protocol fallback mechanism
              if (!tcpOnErrWaitForSend)
              {
                 // Return all buffered messages with a transport error indication.
                 emptyBuffer(TRUE);
                 clientStopSelf();
              }
              else
              {
                 fds[1].revents &= ~(POLLERR | POLLHUP);  // clear error bit if waiting
                 waitingToReportErr = TRUE;
              }
          }
      }

      // Check for message queue messages (fds[0]) before checking the socket(fds[1]),
      // to make sure that we process shutdown messages promptly, even
      // if we would be spinning trying to service the socket.
      else if ((fds[0].revents & POLLIN) != 0)
      {
         // Poll finished because the pipe is ready to read.
         // (One byte in pipe means message available in queue.)
         // Only a SipClient with a derived SipClientWriteBuffer
         // uses the pipe in the Sip message send process

         // Check to see how many messages are in the queue.
         int numberMsgs = (getMessageQueue())->numMsgs();
         Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                       "SipClient[%s]::run got pipe-select  "
                       "Number of Messages waiting: %d",
                       mName.data(),
                       numberMsgs);
         int i;
         char buffer[1];
         for (i = 0; i < numberMsgs; i++)
         {
            // Receive the messages.
            res = receiveMessage((OsMsg*&) pMsg, OsTime::NO_WAIT);
            assert(res == OS_SUCCESS);

            // Normally, this is a SIP message for the write buffer.  Once we have gotten
            // here, we are able to report any initial non-blocking connect error.
            mbTcpOnErrWaitForSend = FALSE;
            tcpOnErrWaitForSend = FALSE;
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run got pipe-select  "
                          "mbTcpOnErrWaitForSend-%d waitingToReportErr-%d mbTcpOnErrWaitForSend-%d repeatedEOFs-%d",
                          mName.data(), mbTcpOnErrWaitForSend, waitingToReportErr,
                          mbTcpOnErrWaitForSend, repeatedEOFs);

            // Read 1 byte from the pipe to clear it for this message.  One byte is
            // inserted into the pipe for each message.
            assert(read(mPipeReadingFd, &buffer, 1) == 1);

            if (!handleMessage(*pMsg))            // process the message (from queue)
            {
               OsServerTask::handleMessage(*pMsg);
            }

            if (!pMsg->getSentFromISR())
            {
               pMsg->releaseMsg();                         // free the message
            }

            // In order to report an unframed(eg TCP) socket error to SipUserAgent dispatcher,
            // the error must be carried in a sip message from the client's message queue.
            // The message holds all the identifying information.
            if (waitingToReportErr)
            {
                // Return all buffered messages with a transport error indication.
                emptyBuffer(TRUE);
                clientStopSelf();
            }
         }
      } // end reading msg-available-for-output-queue pipe

      else if ((fds[1].revents & POLLOUT) != 0)
      {
         // Poll finished because socket is ready to write.

         // Call method to continue writing data.
         writeMore();
      }
      else if ((fds[1].revents & POLLIN) != 0)
      {
         // Poll finished because socket is ready to read.

         // Read message.
         // Must allocate a new message because SipUserAgent::dispatch will
         // take ownership of it.

         SipMessage* msg = new SipMessage;
         int res = msg->read(mClientSocket,
                             HTTP_DEFAULT_SOCKET_BUFFER_SIZE,
                             &readBuffer);

         if (res >= 65536)
         {
           //
           // This is more than the allowable size of a SIP message.  Discard!
           //
            UtlString remoteHostAddress;
            int remoteHostPort;
            msg->getSendAddress(&remoteHostAddress, &remoteHostPort);
            OS_LOG_WARNING(FAC_SIP, "Received a SIP Message ("
             << res << " bytes) beyond the maximum allowable size from host "
             << remoteHostAddress.data() << ":" << remoteHostPort);
            delete msg;
            readBuffer.remove(0);
            continue;
         }

         // Use readBuffer to hold any unparsed data after the message
         // we read.
         // Note that if a message was successfully parsed, readBuffer
         // still contains as its prefix the characters of that message.
         // We save them for logging purposes below and will delete them later.

         UtlString remoteHostAddress;
         int remoteHostPort;
         msg->getSendAddress(&remoteHostAddress, &remoteHostPort);
         if (!mClientSocket->isSameHost(remoteHostAddress.data(), mLocalHostAddress.data()))
         {
           try
           {
             if (!remoteHostAddress.isNull())
             {
               boost::asio::ip::address remoteIp = boost::asio::ip::address::from_string(remoteHostAddress.data());

               if (rateLimit().isBannedAddress(remoteIp))
               {
                  delete msg;
                  readBuffer.remove(0);
                  continue;
               }

               rateLimit().logPacket(remoteIp, 0);
             }
           }
           catch(const std::exception& e)
           {
             Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_CRIT, 
               "SipClient[%s]::run rate limit exception: %s",  mName.data(), e.what());
           }
         }


         // Note that input was processed at this time.
         touch();

         //
         // Count the CR/LF to see if this is a keep-alive
         //
         int crlfCount = 0;
         for (int i = 0; i < res; i++)
         {
           if (readBuffer(i) == '\r' || readBuffer(i) == '\n')
           {
             crlfCount++;
           } else
           {
             break;
           }
         }

         if (res == crlfCount)
         {
             repeatedEOFs = 0;
             // The 'message' was a keepalive (CR-LF or CR-LF-CR-LF).
             UtlString fromIpAddress;
             int fromPort;
             UtlString buffer;
             int bufferLen;

             // send one CRLF set in the reply
             buffer.append("\r\n");
             bufferLen = buffer.length();

             // Get the send address for response.
             msg->getSendAddress(&fromIpAddress, &fromPort);
             if ( !portIsValid(fromPort))
             {
                 fromPort = defaultPort();
             }

            // Log the message at DEBUG level.
            // Only bother processing if the logs are enabled
            if (   mpSipUserAgent->isMessageLoggingEnabled()
                   || Os::Logger::instance().willLog(FAC_SIP_INCOMING, PRI_DEBUG)
               )
            {
               UtlString logMessage;
               logMessage.append("Read keepalive message:\n");
               logMessage.append("----Local Host:");
               logMessage.append(mLocalHostAddress);
               logMessage.append("---- Port: ");
               logMessage.appendNumber(
                  portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort());
               logMessage.append("----\n");
               logMessage.append("----Remote Host:");
               logMessage.append(fromIpAddress);
               logMessage.append("---- Port: ");
               logMessage.appendNumber(
                  portIsValid(fromPort) ? fromPort : defaultPort());
               logMessage.append("----\n");

               logMessage.append(readBuffer.data(), res);
               UtlString messageString;
               logMessage.append(messageString);
               logMessage.append("====================END====================\n");

               // Don't bother to send the message to the SipUserAgent for its internal log.

               // Write the message to the syslog.
               Os::Logger::instance().log(FAC_SIP_INCOMING, PRI_DEBUG, "%s", logMessage.data());
            }

            // send the CR-LF response message
            switch (mSocketType)
            {
            case OsSocket::TCP:
            {
               Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                             "SipClient[%s]::run send TCP keep-alive CR-LF response, ",
                             mName.data());
               SipClientSendMsg sendMsg(OsMsg::OS_EVENT,
                                        SipClientSendMsg::SIP_CLIENT_SEND_KEEP_ALIVE,
                                        fromIpAddress,
                                        fromPort);
                handleMessage(sendMsg);     // add newly created keep-alive to write buffer
            }
               break;
            case OsSocket::UDP:
            {
                Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                              "SipClient[%s]::run send UDP keep-alive CR-LF response, ",
                              mName.data());
               (dynamic_cast <OsDatagramSocket*> (mClientSocket))->write(buffer.data(),
                                                                         bufferLen,
                                                                         fromIpAddress,
                                                                         fromPort);
            }
               break;
            default:
               break;
            }

            // Delete the SipMessage allocated above, which is no longer needed.
            delete msg;

            // Now that logging is done, remove the parsed bytes and
            // remember any unparsed input for later use.
            readBuffer.remove(0, res);
         }  // end keep-alive msg

         else if (res > 0)      // got message, but not keep-alive
         {
            // Message successfully read.
            repeatedEOFs = 0;

            // Do preliminary processing of message to log it,
            // clean up its data, and extract any needed source address.
            preprocessMessage(*msg, readBuffer, res);

            // Dispatch the message.
            // dispatch() takes ownership of *msg.
            mpSipUserAgent->dispatch(msg);

            // Now that logging is done, remove the parsed bytes and
            // remember any unparsed input for later use.
            readBuffer.remove(0, res);
         }  // end process read of >0 bytes
         else
         {
            // Something went wrong while reading the message.
            // (Possibly EOF on a connection-oriented socket.)
            repeatedEOFs++;

            // Delete the SipMessage allocated above, which is no longer needed.
            delete msg;
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run SipMessage::read returns %d (error(%d) or EOF), "
                          "readBuffer = '%.1000s'",
                          mName.data(), res, errno, readBuffer.data());

            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "SipClient[%s]::run error wait status  "
                          "tcpOnErrWaitForSend-%d waitingToReportErr-%d "
                          "mbTcpOnErrWaitForSend-%d repeatedEOFs-%d "
                          "protocol %d framed %d",
                          mName.data(),
                          tcpOnErrWaitForSend, waitingToReportErr,
                          mbTcpOnErrWaitForSend, repeatedEOFs,
                          mClientSocket->getIpProtocol(),
                          OsSocket::isFramed(mClientSocket->getIpProtocol()));

            // If the socket is not framed (is connection-oriented),
            // we need to abort the connection and post a message
            // :TODO: This doesn't work right for framed connection-oriented
            // protocols (like SCTP), but OsSocket doesn't have an EOF-query
            // method -- we need to close all connection-oriented
            // sockets as well in case it was an EOF.
            // Define a virtual function that returns the correct bit.
            if (!OsSocket::isFramed(mClientSocket->getIpProtocol()))
            {
                // On non-blocking connect failures, we need to get the first send message
                // in order to successfully trigger the protocol fallback mechanism
                if (!tcpOnErrWaitForSend)
                {
                   // Return all buffered messages with a transport error indication.
                   emptyBuffer(TRUE);
                   clientStopSelf();
                }
                else
                {
                   fds[1].revents &= ~(POLLERR | POLLHUP);  // clear error bit if waiting
                   waitingToReportErr = TRUE;
                }
            }
            // Delete the data read so far, which will not have been
            // deleted by HttpMessage::read.
            readBuffer.remove(0);
         }
      } // end POLLIN reading socket
   }
   while (isStarted());

   return 0;        // and then exit
}
Beispiel #11
0
status_t BnOMX::onTransact(
    uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) {
    switch (code) {
        case LIST_NODES:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            List<String8> list;
            listNodes(&list);

            reply->writeInt32(list.size());
            for (List<String8>::iterator it = list.begin();
                 it != list.end(); ++it) {
                reply->writeString8(*it);
            }

            return NO_ERROR;
        }

        case ALLOCATE_NODE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            const char *name = data.readCString();

            sp<IOMXObserver> observer =
                interface_cast<IOMXObserver>(data.readStrongBinder());

            node_id node;

            status_t err = allocateNode(name, observer, &node);
            reply->writeInt32(err);
            if (err == OK) {
                reply->writeIntPtr((intptr_t)node);
            }
                
            return NO_ERROR;
        }

        case FREE_NODE:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();

            reply->writeInt32(freeNode(node));
                
            return NO_ERROR;
        }

        case SEND_COMMAND:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();

            OMX_COMMANDTYPE cmd =
                static_cast<OMX_COMMANDTYPE>(data.readInt32());

            OMX_S32 param = data.readInt32();
            reply->writeInt32(sendCommand(node, cmd, param));

            return NO_ERROR;
        }

        case GET_PARAMETER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

            size_t size = data.readInt32();

            // XXX I am not happy with this but Parcel::readInplace didn't work.
            void *params = malloc(size);
            data.read(params, size);

            status_t err = getParameter(node, index, params, size);

            reply->writeInt32(err);

            if (err == OK) {
                reply->write(params, size);
            }

            free(params);
            params = NULL;

            return NO_ERROR;
        }

        case SET_PARAMETER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

            size_t size = data.readInt32();
            void *params = const_cast<void *>(data.readInplace(size));

            reply->writeInt32(setParameter(node, index, params, size));

            return NO_ERROR;
        }

        case GET_CONFIG:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

            size_t size = data.readInt32();

            // XXX I am not happy with this but Parcel::readInplace didn't work.
            void *params = malloc(size);
            data.read(params, size);

            status_t err = getConfig(node, index, params, size);

            reply->writeInt32(err);

            if (err == OK) {
                reply->write(params, size);
            }

            free(params);
            params = NULL;

            return NO_ERROR;
        }

        case SET_CONFIG:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());

            size_t size = data.readInt32();
            void *params = const_cast<void *>(data.readInplace(size));

            reply->writeInt32(setConfig(node, index, params, size));

            return NO_ERROR;
        }

        case USE_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
            status_t err = useBuffer(node, port_index, params, &buffer);
            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case ALLOC_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            size_t size = data.readInt32();

            buffer_id buffer;
            status_t err = allocateBuffer(node, port_index, size, &buffer);
            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case ALLOC_BUFFER_WITH_BACKUP:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            sp<IMemory> params =
                interface_cast<IMemory>(data.readStrongBinder());

            buffer_id buffer;
            status_t err = allocateBufferWithBackup(
                    node, port_index, params, &buffer);

            reply->writeInt32(err);

            if (err == OK) {
                reply->writeIntPtr((intptr_t)buffer);
            }

            return NO_ERROR;
        }

        case FREE_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            OMX_U32 port_index = data.readInt32();
            buffer_id buffer = (void*)data.readIntPtr();
            reply->writeInt32(freeBuffer(node, port_index, buffer));

            return NO_ERROR;
        }

        case FILL_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            buffer_id buffer = (void*)data.readIntPtr();
            reply->writeInt32(fillBuffer(node, buffer));

            return NO_ERROR;
        }

        case EMPTY_BUFFER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            buffer_id buffer = (void*)data.readIntPtr();
            OMX_U32 range_offset = data.readInt32();
            OMX_U32 range_length = data.readInt32();
            OMX_U32 flags = data.readInt32();
            OMX_TICKS timestamp = data.readInt64();

            reply->writeInt32(
                    emptyBuffer(
                        node, buffer, range_offset, range_length,
                        flags, timestamp));

            return NO_ERROR;
        }

        case GET_EXTENSION_INDEX:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            node_id node = (void*)data.readIntPtr();
            const char *parameter_name = data.readCString();
            
            OMX_INDEXTYPE index;
            status_t err = getExtensionIndex(node, parameter_name, &index);

            reply->writeInt32(err);

            if (err == OK) {
                reply->writeInt32(index);
            }

            return OK;
        }

        case CREATE_RENDERER:
        {
            CHECK_INTERFACE(IOMX, data, reply);

            sp<ISurface> isurface =
                interface_cast<ISurface>(data.readStrongBinder());

            const char *componentName = data.readCString();

            OMX_COLOR_FORMATTYPE colorFormat =
                static_cast<OMX_COLOR_FORMATTYPE>(data.readInt32());

            size_t encodedWidth = (size_t)data.readInt32();
            size_t encodedHeight = (size_t)data.readInt32();
            size_t displayWidth = (size_t)data.readInt32();
            size_t displayHeight = (size_t)data.readInt32();

            sp<IOMXRenderer> renderer =
                createRenderer(isurface, componentName, colorFormat,
                               encodedWidth, encodedHeight,
                               displayWidth, displayHeight);

            reply->writeStrongBinder(renderer->asBinder());

            return OK;
        }

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
void EliminateDuplicates(char *infile, unsigned char field, block_t *buffer, unsigned int nmem_blocks, char *outfile, unsigned int *nunique, unsigned int *nios) {

    if (nmem_blocks < 3) {
        printf("At least 3 blocks are required.");
        return;
    }

    // empties the buffer
    emptyBuffer(buffer, nmem_blocks);
    uint memSize = nmem_blocks - 1;
    *nunique = 0;
    *nios = 0;

    uint fileSize = getSize(infile);

    // if the relation fits on the buffer and leaves one block free for output,
    // loads it to the buffer and eliminates duplicates using hashing
    if (fileSize <= memSize) {
        hashElimination(infile, fileSize, outfile, field, buffer, memSize, nunique, nios);
    } else if (fileSize == nmem_blocks) {
        // if the relation completely fits the buffer, calls useFirstBlock
        useFirstBlock(infile, outfile, field, buffer, nmem_blocks, nunique, nios);
    } else {
        // if the relation is larger than the buffer, then sort it using mergesort,
        // BUT during the final merging (during last pass) write to the output
        // only one time each value

        // the following code is similar to that of MergeSort:

        int input, output;
        char tmpFile1[] = ".ed1";
        char tmpFile2[] = ".ed2";

        uint fullSegments = fileSize / nmem_blocks;
        uint remainingSegment = fileSize % nmem_blocks;

        input = open(infile, O_RDONLY, S_IRWXU);
        output = open(tmpFile1, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);

        uint nSortedSegs = 0;
        uint segmentSize = nmem_blocks;
        for (uint i = 0; i <= fullSegments; i++) {
            if (fullSegments == i) {
                if (remainingSegment != 0) {
                    segmentSize = remainingSegment;
                } else {
                    break;
                }
            }
            (*nios) += readBlocks(input, buffer, segmentSize);
            if (sortBuffer(buffer, segmentSize, field)) {
                (*nios) += writeBlocks(output, buffer, segmentSize);
                nSortedSegs += 1;
            }
        }
        close(input);
        close(output);

        segmentSize = nmem_blocks;
        uint lastSegmentSize;
        if (remainingSegment == 0) {
            lastSegmentSize = nmem_blocks;
        } else {
            lastSegmentSize = remainingSegment;
        }

        buffer[memSize].valid = true;
        while (nSortedSegs != 1) {
            input = open(tmpFile1, O_RDONLY, S_IRWXU);
            output = open(tmpFile2, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);

            uint newSortedSegs = 0;
            uint fullMerges = nSortedSegs / memSize;
            uint lastMergeSegs = nSortedSegs % memSize;
            uint *blocksLeft = (uint*) malloc(memSize * sizeof (uint));
            uint segsToMerge = memSize;
            bool lastMerge = false;

            for (uint mergeCounter = 0; mergeCounter <= fullMerges; mergeCounter++) {
                uint firstSegOffset = mergeCounter * memSize * segmentSize;

                if (mergeCounter == fullMerges - 1 && lastMergeSegs == 0) {
                    lastMerge = true;
                } else if (mergeCounter == fullMerges) {
                    if (lastMergeSegs != 0) {
                        segsToMerge = lastMergeSegs;
                        lastMerge = true;
                    } else {
                        break;
                    }
                }

                for (uint i = 0; i < segsToMerge; i++) {
                    (*nios) += preadBlocks(input, buffer + i, (firstSegOffset + i * segmentSize), 1);
                    blocksLeft[i] = segmentSize - 1;
                }

                if (lastMerge) {
                    blocksLeft[segsToMerge - 1] = lastSegmentSize - 1;
                }

                (*nios) += mergeElimination(input, output, buffer, memSize, segsToMerge, blocksLeft, segmentSize, firstSegOffset, field, nSortedSegs <= memSize, lastMerge, nunique);
                newSortedSegs += 1;
            }
            free(blocksLeft);

            if (lastMergeSegs == 0) {
                lastSegmentSize = (memSize - 1) * segmentSize + lastSegmentSize;
            } else {
                lastSegmentSize = (lastMergeSegs - 1) * segmentSize + lastSegmentSize;
            }
            segmentSize *= memSize;
            nSortedSegs = newSortedSegs;
            close(input);
            close(output);

            char tmp = tmpFile1[3];
            tmpFile1[3] = tmpFile2[3];
            tmpFile2[3] = tmp;
        }
        rename(tmpFile1, outfile);
        remove(tmpFile2);
    }
}
/// Write as much of the buffered messages as can be written.
// Executed by the thread.
void SipClientWriteBuffer::writeMore()
{
   // 'exit_loop' will be set to TRUE if an attempt to write does
   // not write any bytes, and we will then return.
   UtlBoolean exit_loop = FALSE;

   while (mWriteQueued && !exit_loop)
   {
      if (mWritePointer >= mWriteString.length())
      {
         // We have written all of the first message.
         // Pop it and set up to write the next message.
         delete mWriteBuffer.get();
         mWriteString.remove(0);
         mWritePointer = 0;
         mWriteQueued = ! mWriteBuffer.isEmpty();
         if (mWriteQueued)
         {
            // get the message on the head of the queue, and figure out which kind it is
            UtlContainable* nextMsg = mWriteBuffer.first();
            SipMessage* sipMsg;
            UtlString* keepAliveMsg;
            if ((sipMsg = dynamic_cast<SipMessage*>(nextMsg))) // a SIP message
            {
               ssize_t length;
               sipMsg->getBytes(&mWriteString, &length);
            }
            else if ((keepAliveMsg = dynamic_cast<UtlString*>(nextMsg))) // a keepalive CRLF
            {
               mWriteString.append(*keepAliveMsg);
            }
            else
            {
               Os::Logger::instance().log(FAC_SIP, PRI_CRIT,
                             "SipClientWriteBuffer[%s]::writeMore "
                             "unrecognized message type in queue",
                             mName.data());
               assert(false);
               delete mWriteBuffer.get();
               mWriteQueued = mWriteBuffer.isEmpty();
            }
         }
      }
      else
      {
         // Some portion of the first message remains to be written.

         // If the socket has failed, attempt to reconnect it.
         // :NOTE: OsConnectionSocket::reconnect isn't implemented.
         if (!mClientSocket->isOk())
         {
            mClientSocket->reconnect();
         }

         // Calculate the length to write.
         int length = mWriteString.length() - mWritePointer;

         // ret is the value returned from write attempt.
         // -1 means an error was seen.
         int ret;
         if (mClientSocket->isOk())
         {
            // Write what we can.
            ret = mClientSocket->write(mWriteString.data() + mWritePointer, length);
            // Theoretically, ret > 0, since the socket is ready for writing,
            // but it appears that that ret can be 0.
         }
         else
         {
            // Record the error.
            ret = -1;
            // Set a special errno value, which hopefully is not a real value.
            errno = 1000;
         }

         if (ret > 0)
         {
            // We successfully sent some data, perhaps all of the
            // remainder of the first message.
            // Update the last-activity time.
            touch();
            // Update the state variables.
            mWritePointer += ret;
         }
         else if (ret == 0)
         {
            // No data sent, even though (in our caller) poll()
            // reported the socket was ready to write.
            exit_loop = TRUE;
         }
         else
         {
            // Error while writing.
            Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                          "SipClientWriteBuffer[%s]::writeMore "
                          "OsSocket::write() returned %d, errno = %d",
                          getName().data(), ret, errno);
            // Return all buffered messages with a transport error indication.
            emptyBuffer(TRUE);
            // Because TCP is a connection protocol, we know that we cannot
            // send successfully any more and so should shut down this client.
            clientStopSelf();
            // Exit the loop so handleMessage() can process the stop request.
            exit_loop = TRUE;
         }
      }
   }
}
/// Insert a message into the buffer.
void SipClientWriteBuffer::insertMessage(SipMessage* message)
{
   UtlBoolean wasEmpty = mWriteBuffer.isEmpty();

    //
    // Let all outbound processors know about this message
    //
    if (message && mpSipUserAgent && mClientSocket && mClientSocket->isOk())
    {
      UtlString remoteHostAddress;
      int remotePort;
      mClientSocket->getRemoteHostIp(&remoteHostAddress, &remotePort);
      // We are about to post a message that will cause the
      // SIP message to be sent.  Notify the user agent so
      // that it can offer the message to all its registered
      // output processors.


      ssize_t msgLength = 0;
      UtlString msgText;
      message->getBytes(&msgText, &msgLength, true);
      if (msgLength)
      {
        system_tap_sip_tx(
             mLocalHostAddress.data(), portIsValid(mLocalHostPort) ? mLocalHostPort : defaultPort(),
             remoteHostAddress.data(), remotePort == PORT_NONE ? defaultPort() : remotePort,
             msgText.data(), msgLength);

        mpSipUserAgent->executeAllBufferedSipOutputProcessors(*message, remoteHostAddress.data(),
               remotePort == PORT_NONE ? defaultPort() : remotePort);
      }
    }

   // Add the message to the queue.
   mWriteBuffer.insert(message);

   // If the buffer was empty, we need to set mWriteString and
   // mWritePointer.
   if (wasEmpty)
   {
      ssize_t length;
      message->getBytes(&mWriteString, &length);
      mWritePointer = 0;
   }

   mWriteQueued = TRUE;

   // Check to see if our internal queue is getting too big, which means
   // that the socket has been blocked for writing for a long time.
   // We use the message queue length of this task as the limit, since
   // both queues are affected by the same traffic load factors.
   if (mWriteBuffer.entries() > (size_t) (getMessageQueue()->maxMsgs()))
   {
      // If so, abort all unsent messages and terminate this client (so
      // as to clear any state of the socket).
      Os::Logger::instance().log(FAC_SIP, PRI_ERR,
                    "SipClientWriteBuffer[%s]::insertMessage "
                    "mWriteBuffer has '%d' entries, exceeding the limit of maxMsgs '%d'",
                    getName().data(), (int) mWriteBuffer.entries(),
                    getMessageQueue()->maxMsgs());
      emptyBuffer(TRUE);
      clientStopSelf();
   }
}