live555 源码分析(三:UsageEnvironment分析)

标题不写中文,因为搜索的时候都会用英文搜索的。中文是使用环境,这个稍微浏览了一下还挺多内容的,有3个类,希望一篇能解决。

3.1 基本关系

继承图:
在这里插入图片描述
这个继承图,有3个类,我们这篇应该会把这个3个类分析完,希望不要太长。

协作图:
在这里插入图片描述
这个调度有关的也需要UsageEnvironment,不过这个是下一篇分析,这里就分析上面3个类。

3.1.1 UsageEnvironment类

class UsageEnvironment {
public:
  Boolean reclaim();
      // returns True iff we were actually able to delete our object

  // task scheduler:
  TaskScheduler& taskScheduler() const {return fScheduler;}

  // result message handling:
  typedef char const* MsgString;
  virtual MsgString getResultMsg() const = 0;

  virtual void setResultMsg(MsgString msg) = 0;
  virtual void setResultMsg(MsgString msg1, MsgString msg2) = 0;
  virtual void setResultMsg(MsgString msg1, MsgString msg2, MsgString msg3) = 0;
  virtual void setResultErrMsg(MsgString msg, int err = 0) = 0;
	// like setResultMsg(), except that an 'errno' message is appended.  (If "err == 0", the "getErrno()" code is used instead.)

  virtual void appendToResultMsg(MsgString msg) = 0;

  virtual void reportBackgroundError() = 0;
	// used to report a (previously set) error message within
	// a background event

  virtual void internalError(); // used to 'handle' a 'should not occur'-type error condition within the library.

  // 'errno'
  virtual int getErrno() const = 0;

  // 'console' output:
  virtual UsageEnvironment& operator<<(char const* str) = 0;
  virtual UsageEnvironment& operator<<(int i) = 0;
  virtual UsageEnvironment& operator<<(unsigned u) = 0;
  virtual UsageEnvironment& operator<<(double d) = 0;
  virtual UsageEnvironment& operator<<(void* p) = 0;

  // a pointer to additional, optional, client-specific state
  void* liveMediaPriv;
  void* groupsockPriv;

protected:
  UsageEnvironment(TaskScheduler& scheduler); // abstract base class
  virtual ~UsageEnvironment(); // we are deleted only by reclaim()

private:
  TaskScheduler& fScheduler;
};

UsageEnvironment 类持有 TaskScheduler 的引用,并提供文本的输出操作,用于输出信息,其它还提供了获取 errno 的操作,在发生内部错误时的处理程序 internalError(),以及销毁自身的操作。

3.1.2 BasicUsageEnvironment0类

class BasicUsageEnvironment0: public UsageEnvironment {
public:
  // redefined virtual functions:
  virtual MsgString getResultMsg() const;

  virtual void setResultMsg(MsgString msg);
  virtual void setResultMsg(MsgString msg1,
		    MsgString msg2);
  virtual void setResultMsg(MsgString msg1,
		    MsgString msg2,
		    MsgString msg3);
  virtual void setResultErrMsg(MsgString msg, int err = 0);

  virtual void appendToResultMsg(MsgString msg);

  virtual void reportBackgroundError();

protected:
  BasicUsageEnvironment0(TaskScheduler& taskScheduler);
  virtual ~BasicUsageEnvironment0();

private:
  void reset();

  char fResultMsgBuffer[RESULT_MSG_BUFFER_MAX];
  unsigned fCurBufferSize;
  unsigned fBufferMaxSize;
};

3.1.3 BasicUsageEnvironment类

class BasicUsageEnvironment: public BasicUsageEnvironment0 {
public:
  static BasicUsageEnvironment* createNew(TaskScheduler& taskScheduler);

  // redefined virtual functions:
  virtual int getErrno() const;

  virtual UsageEnvironment& operator<<(char const* str);
  virtual UsageEnvironment& operator<<(int i);
  virtual UsageEnvironment& operator<<(unsigned u);
  virtual UsageEnvironment& operator<<(double d);
  virtual UsageEnvironment& operator<<(void* p);

protected:
  BasicUsageEnvironment(TaskScheduler& taskScheduler);
      // called only by "createNew()" (or subclass constructors)
  virtual ~BasicUsageEnvironment();
};

3个类的定义就在这里了,接下来了解一下实现。

3.2 创建函数

不知道为什么这么喜欢把构造函数私有化,然后又一个创建函数,留一个创建函数让我们直接创建一个对象,其实创建对象也是直接new一个对象。

BasicUsageEnvironment*
BasicUsageEnvironment::createNew(TaskScheduler& taskScheduler) {
  return new BasicUsageEnvironment(taskScheduler);
}

参数是TaskScheduler类的引用,这个类明天再分析。

3.3 构造函数

3.3.1 BasicUsageEnvironment()

BasicUsageEnvironment::BasicUsageEnvironment(TaskScheduler& taskScheduler)
: BasicUsageEnvironment0(taskScheduler) {
#if defined(__WIN32__) || defined(_WIN32)
  if (!initializeWinsockIfNecessary()) {
    setResultErrMsg("Failed to initialize 'winsock': ");
    reportBackgroundError();
    internalError();
  }
#endif
}

调用BasicUsageEnvironment0类的构造函数,还有win下还要初始化Winsock,这个win下就不清楚了,我们看linux下的,linux下好像没啥。

3.3.2 BasicUsageEnvironment0()

#define RESULT_MSG_BUFFER_MAX 1000
BasicUsageEnvironment0::BasicUsageEnvironment0(TaskScheduler& taskScheduler)
  : UsageEnvironment(taskScheduler),
    fBufferMaxSize(RESULT_MSG_BUFFER_MAX) {
  reset();
}

void BasicUsageEnvironment0::reset() {
  fCurBufferSize = 0;     
  fResultMsgBuffer[fCurBufferSize] = '\0';    //把buffer值初始化为‘\0’
}

这个也简单,调用UsageEnvironment的构造函数,
fBufferMaxSize:设置输出Buffer的最大值1000
fCurBufferSize : 当前buffer的大小
fResultMsgBuffer: 输出缓冲区

3.3.3 UsageEnvironment()

UsageEnvironment::UsageEnvironment(TaskScheduler& scheduler)
  : liveMediaPriv(NULL), groupsockPriv(NULL), fScheduler(scheduler) {
}

构造函数就是初始化了几个变量
liveMediaPriv
groupsockPriv
fScheduler

3.4 BasicUsageEnvironment.cpp

这个浏览了一遍,感觉确实没什么好讲的,也不知道live555为什么这么封装。所以下面改变策略,直接分析一个.cpp文件。

//返回错误
int BasicUsageEnvironment::getErrno() const {
#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_WCE)
  return WSAGetLastError();
#else
  return errno;    //linux下直接返回这个错误
#endif
}

//<< 操作符重写
UsageEnvironment& BasicUsageEnvironment::operator<<(char const* str) {
  if (str == NULL) str = "(NULL)"; // sanity check
  fprintf(stderr, "%s", str);
  return *this;
}
//<< 操作符重写
UsageEnvironment& BasicUsageEnvironment::operator<<(int i) {
  fprintf(stderr, "%d", i);
  return *this;
}
//<< 操作符重写
UsageEnvironment& BasicUsageEnvironment::operator<<(unsigned u) {
  fprintf(stderr, "%u", u);
  return *this;
}
//<< 操作符重写
UsageEnvironment& BasicUsageEnvironment::operator<<(double d) {
  fprintf(stderr, "%f", d);
  return *this;
}
//<< 操作符重写
UsageEnvironment& BasicUsageEnvironment::operator<<(void* p) {
  fprintf(stderr, "%p", p);
  return *this;
}

没什么好分析的,就是用了fprintf函数,相标准错误打印。

3.5 BasicUsageEnvironment0.cpp

// Implementation of virtual functions:

//这个用的比较多,就放在开头
//这个函数就是往fResultMsgBuffer这个缓冲区中追加内容
void BasicUsageEnvironment0::appendToResultMsg(MsgString msg) {
  char* curPtr = &fResultMsgBuffer[fCurBufferSize];
  unsigned spaceAvailable = fBufferMaxSize - fCurBufferSize;
  unsigned msgLength = strlen(msg);

  // Copy only enough of "msg" as will fit:
  if (msgLength > spaceAvailable-1) {
    msgLength = spaceAvailable-1;
  }

  memmove(curPtr, (char*)msg, msgLength);
  fCurBufferSize += msgLength;
  fResultMsgBuffer[fCurBufferSize] = '\0';
}

//直接返回缓冲区内容
char const* BasicUsageEnvironment0::getResultMsg() const {
  return fResultMsgBuffer;
}

//清空缓冲区,msg直接写入缓冲区
void BasicUsageEnvironment0::setResultMsg(MsgString msg) {
  reset();
  appendToResultMsg(msg);
}

//写两段信息
void BasicUsageEnvironment0::setResultMsg(MsgString msg1, MsgString msg2) {
  setResultMsg(msg1);
  appendToResultMsg(msg2);
}

//写三段信息
void BasicUsageEnvironment0::setResultMsg(MsgString msg1, MsgString msg2,
				       MsgString msg3) {
  setResultMsg(msg1, msg2);
  appendToResultMsg(msg3);
}

//写一段错误信息,还有一个错误码
void BasicUsageEnvironment0::setResultErrMsg(MsgString msg, int err) {
  setResultMsg(msg);

  if (err == 0) err = getErrno();
#if defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_WCE)
#ifndef _UNICODE
  char errMsg[RESULT_MSG_BUFFER_MAX] = "\0";
  if (0 != FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, errMsg, sizeof(errMsg)/sizeof(errMsg[0]), NULL)) {
    // Remove all trailing '\r', '\n' and '.'
    for (char* p = errMsg + strlen(errMsg); p != errMsg && (*p == '\r' || *p == '\n' || *p == '.' || *p == '\0'); --p) {
      *p = '\0';
    }
  } else
    snprintf(errMsg, sizeof(errMsg)/sizeof(errMsg[0]), "error %d", err);
  appendToResultMsg(errMsg);
#endif
#else
  appendToResultMsg(strerror(err));
#endif
}

//往标准错误打印信息
void BasicUsageEnvironment0::reportBackgroundError() {
  fputs(getResultMsg(), stderr);
}

看着这部分代码确实有点难受。

3.6 UsageEnvironment.cpp

//如果没有关联liveMediaPriv 和 groupsockPriv 就删除自己对象
Boolean UsageEnvironment::reclaim() {
  // We delete ourselves only if we have no remainining state:
  if (liveMediaPriv == NULL && groupsockPriv == NULL) {
    delete this;
    return True;
  }

  return False;
}

// By default, we handle 'should not occur'-type library errors by calling abort().  Subclasses can redefine this, if desired.
// (If your runtime library doesn't define the "abort()" function, then define your own (e.g., that does nothing).)
void UsageEnvironment::internalError() {
  abort();   //错误的处理方式
}

想不到这个竟然比哈希表更是软柿子,简单点分析的快一点也好,明天就分析下一个重点内容TaskScheduler,这个分析完,live555的基础已经分析了,接下来就要开始实际的代码了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值