⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testtransactionfsm.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 2 页
字号:
// How this works:
//
// The first argument to this program needs to be a file that has a test in it.
//
// Clauses in this file can be: inject_wire, expect_wire, expect_tu,
// inject_tu, and delay.  A keyword needs to be by itself on a line.  They
// need to be in this form
//
// inject_wire (or inject_tu)
// {
// ...put a SIP message here that has a CRLF after each line...
// }
//
// expect_wire (or expect_tu)
// {
// status=100 (or method=REGISTER)
// timeout=32
// }
//
// delay
// {
// timeout=48
// }
//
// The inject_* clauses inject the SIP message described at the "wire"
// or the "tu" level.  The expect_* clauses indicate that the test
// specification expects to read a certain response (distinguished only
// by its response code) or request (distinguished only by its method
// name).  The expect_* clauses don't block but will queue the
// expectation for the duration of the timeout specified.  When you
// really want to sit and wait for a message, insert a delay clause.
// This is used as a "barrier" at which you want all the above timeouts
// to happen.  You'll want one at the end of your test, for example.

#ifndef __MINGW32__

#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <list>
#include <iostream>
#include <fstream>
#include <string>

#include "rutil/Data.hxx"
#include "rutil/DataStream.hxx"
#include "rutil/Logger.hxx"
#include "rutil/Socket.hxx"

#include "resip/stack/test/TestSupport.hxx"
#include "resip/stack/MethodTypes.hxx"
#include "resip/stack/SipStack.hxx"
#include "resip/stack/SipMessage.hxx"
#include "resip/stack/Symbols.hxx"
#include "resip/stack/Transport.hxx"
#include "rutil/ParseBuffer.hxx"

using namespace resip;
using namespace std;

#define RESIPROCATE_SUBSYSTEM Subsystem::TEST
#define PORT 5060


// --------------------------------------------------

namespace resip 
{
class TestFSM  // this class is a friend of the SipStack and can directly access private stuff
{
   public:
      static void addMessage(SipStack* stack,SipMessage* message)
      {
         stack->mTransactionController.mStateMacFifo.add(message);
      }
};
}

typedef struct {
      struct timeval mExpiry;
      bool mIsRequest;
      bool mIsTransport;
      int mResponseCode;
      MethodTypes mMethod;
} WaitNode;

// --------------------------------------------------

char* ProgramName = 0;
char* TestSpecBuf = 0;
ParseBuffer* TestSpecParseBuf = 0;
list<WaitNode*> WaitQueue;
SipStack* client = 0;
FdSet clientFdSet;
struct sockaddr_in clientSa;
int clientFd;
Fifo<SipMessage> fakeTxFifo;
int errorCount = 0;

// --------------------------------------------------

// This is pure evil.  We interpose our own version of sendto
// so that this gets called by the UDP transport instead of the libc
// version.
int
sendto(int s, const void *msg, size_t len, int flags,
       const struct sockaddr *to, int tolen)
{
    fakeTxFifo.add(TestSupport::makeMessage(Data((const char *)msg, (int)len), true));
    return len;
}

// --------------------------------------------------


void
exitusage()
{
	cerr << "Usage: " << ProgramName << " ";
	cerr << "<testfileofsipmessagesandstuff>" << endl;
	exit(1);
}

void
processTimeouts(int arg)
{
    client->buildFdSet(clientFdSet);
    client->process(clientFdSet);

    if (WaitQueue.empty())
    {
	return;
    }
    SipMessage* message = 0;


#if defined(UGLY) || 1
    // This should:
    // 1. Take all messages from the "wire" and "tu" fifos
    // 2. For each message, look through the WaitQueue and see
    //    if the new message matches something we were waiting for.
    //    If yes, through away the queue entry, else raise a warning.
    // 3. When all messages from the "wire" and "tu" have been
    //    examined, see if anything in the queue has expired.
    //    If yes, warn, else just continue.

    // First go through the "wire" data
    while (fakeTxFifo.messageAvailable())
    {
	message = fakeTxFifo.getNext();
	for (list<WaitNode*>::iterator i = WaitQueue.begin();
	     i != WaitQueue.end();
	     /* don't increment */)
	{
	    if ((*i)->mIsRequest && message->isRequest())
	    {
		if ((*i)->mMethod == message->header(h_RequestLine).getMethod())
		{
		    // We matched something we expected.
		    delete message;
		    message = 0;
		    delete *i;
		    WaitQueue.erase(i++);
		    break;
		}
		else
		{
		    ++i;
		}
	    }
	    else if (!(*i)->mIsRequest && message->isResponse())
	    {
		if ((*i)->mResponseCode ==
		    message->header(h_StatusLine).responseCode())
		{
		    // We matched something we expected.
		    delete message;
		    message = 0;
		    delete *i;
		    WaitQueue.erase(i++);
		    break;
		}
		else
		{
		    ++i;
		}
	    }
	    else
	    {
		++i;
	    }
	}
	if (message)
	{
	    DebugLog( << "Warning: unexpected message seen at the transport: " 
		      << message);
	}
	else
	{
	    DebugLog( << "Success: expected message seen at the transport");
	}
	delete message;
    }

    // Now go through the data at the TU.
    while (0 != (message = client->receive()))
    {
	for (list<WaitNode*>::iterator i = WaitQueue.begin();
	     i != WaitQueue.end();
	     /* don't increment */)
	{
	    if ((*i)->mIsRequest && message->isRequest())
	    {
		if ((*i)->mMethod ==
		    message->header(h_RequestLine).getMethod())
		{
		    // We matched something we expected.
		    delete message;
		    message = 0;
		    delete *i;
		    WaitQueue.erase(i++);
		    break;
		}
		else
		{
		    ++i;
		}
	    }
	    else if (!(*i)->mIsRequest && message->isResponse())
	    {
		if ((*i)->mResponseCode ==
		    message->header(h_StatusLine).responseCode())
		{
		    // We matched something we expected.
		    delete message;
		    message = 0;
		    delete *i;
		    WaitQueue.erase(i++);
		    break;
		}
		else
		{
		    ++i;
		}
	    }
	    else
	    {
		++i;
	    }
	}
	if (message)
	{
	    DebugLog( << "Warning: unexpected message seen at the TU: "
		      << *message);
	    delete message;
	}
	else
	{
	    DebugLog( << "Success: expected message seen at TU");
	}
    }

    // Print the list of expected events that have failed to happen withing
    // the specified timeout.
    for (list<WaitNode*>::iterator i = WaitQueue.begin();
	 i != WaitQueue.end();
	 /* don't increment */)
    {
	struct timeval tv;
	gettimeofday(&tv, NULL);
	if ((*i)->mExpiry.tv_sec < tv.tv_sec ||
	   ((*i)->mExpiry.tv_sec == tv.tv_sec &&
	    (*i)->mExpiry.tv_usec < tv.tv_usec))
	{
	    if ((*i)->mIsRequest)
	    {
		DebugLog(<< "Error: timeout waiting for "
		         << getMethodName((*i)->mMethod) << " method");
		++errorCount;
	    }
	    else
	    {
		DebugLog(<< "Error: timeout waiting for "
		         << (*i)->mResponseCode << " status code");
		++errorCount;
	    }
	    delete *i;
	    WaitQueue.erase(i++);
	}
	else
	{
	    /*
	    cerr << "Still waiting for: ";
	    if ((*i)->mIsRequest)
	    {
		cerr << MethodNames[(*i)->mMethod] << " method" << endl;
	    }
	    else
	    {
		cerr << (*i)->mResponseCode << " status code" << endl;
	    }
	    */
	    ++i;
	}
    }
#endif

    signal(SIGALRM, processTimeouts);
}

void
processInject()
{
    const char* start = TestSpecParseBuf->position();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -