📄 testtransactionfsm.cxx
字号:
// 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.intsendto(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;}// --------------------------------------------------voidexitusage(){ cerr << "Usage: " << ProgramName << " "; cerr << "<testfileofsipmessagesandstuff>" << endl; exit(1);}voidprocessTimeouts(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);}voidprocessInject(){ const char* start = TestSpecParseBuf->position();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -