1. 程式人生 > >onvif 開發中的一些重要函數介紹

onvif 開發中的一些重要函數介紹

目的 uri www. ror art interface tags -c end

?soap結構中count(soap->count)成員

soap結構中count(soap->count)成員記錄的是http協議中Content-Length的數值。


?keep_alive

keep_alive既是在通訊過程中的正常鏈接的一個狀態標示也是關系到http協議中Connection:keep-alive的填寫open還是close。


?如何生成http協議部分

gsoap中生成的*.c文件中在生成xml協議信息時,是通過soap->fposthdr,soap_puthttphdr生成一些http協議部分。


?如何發送http協議

在gsoap通訊過程中,通過soap->fpost(),生成發送協議中的http協議部分。


?函數soap_set_local_namespaces(struct soap *soap)

?soap_connect()函數中把原來的soap->mode進行了修改,這樣在下次調用,同時對填入soap->buf的字符進行計數。

?soap_connect()中soap->bufidx統計的是http協議部分的字符數。

?soap_envelope_begin_out()統計envelope部分的計數,同時填寫xml中envelope部分

?soap_putheader()統計putheader部分的計數,同時填寫xml中putheader部分。

?soap_body_begin_out()統計body部分的計數,同時填寫xml中body部分。

?soap_put___tds__(*)(*標示相關功能標識,例如GetNetworkInterfaces)統計__(*)(*標示相關功能標識,例如GetNetworkInterfaces)部分的計數,同時填寫xml中__(*)(*標示相關功能標識,例如GetNetworkInterfaces)部分。

?soap_body_end_outconnect()中soap->bufidx統計的是body部分結束標簽的字符數同時把結束標簽寫入xml。

?soap_envelope_end_out()同前。

?soap_end_send()中,soap_end_send()->soap_flush()->soap_flush_raw()->soap->fsend(),在函數soap_end_send()中進行sock發送,在此函數中第一次使用soap結構(接受/發送結束),對soap->budidx,soap->count進行清零。在此之前結構中soap->buflen一次未用到,猜測次成員只在解析時使用。在這些處理過程中,如果(soap->bufidx > SOAP_BUFLEN),那麽,由於soap_connect()已經建立了socket通訊,所以只要條件滿足就用soap->flush()把buf中的協議包發送給服務器端,不會丟失協議內容,至於服務器端怎樣處理,只有讀代碼了。


?soap_element()

#ifndef PALM_2
SOAP_FMAC1
int
SOAP_FMAC2
soap_element(struct soap *soap, const char *tag, int id, const char *type)
{
#ifndef WITH_LEAN
  const char *s;
#endif
  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag=‘%s‘ level=‘%u‘ id=‘%d‘ type=‘%s‘\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
#ifdef WITH_DOM
#ifndef WITH_LEAN
  if (soap_tagsearch(soap->wsuid, tag))
  { size_t i;
    for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++)
      soap->tag[i] = *s == ‘:‘ ? ‘-‘ : *s;
    soap->tag[i] = ‘\0‘;
    if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
      return soap->error;
  }
#endif
#endif
  soap->level++;
  if (soap->level > soap->maxlevel)
    return soap->error = SOAP_LEVEL;
#ifdef WITH_DOM
#ifndef WITH_LEAN
  if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
  { if (soap->evlev >= soap->level)
      soap->evlev = 0;
    if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
    { struct soap_nlist *np;
      /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
      for (np = soap->nlist; np; np = np->next)
      { int p = soap_tagsearch(soap->c14ninclude, np->id) != NULL;
        if (np->index == 2 || p)
        { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1, 0);
          if (np1 && !p)
            np1->index = 0;
        }
      }
      soap->evlev = soap->level;
    }
  }
#endif
  if (soap->mode & SOAP_XML_DOM)
  { struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
    if (!elt)
      return soap->error = SOAP_EOM;
    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding DOM element tag=‘%s‘ %p (parent=‘%s‘ %p)\n", tag, elt, soap->dom ? soap->dom->name : "(null)", soap->dom));
    elt->soap = soap;
    elt->next = NULL;
    elt->prnt = soap->dom;
    elt->elts = NULL;
    elt->atts = NULL;
    elt->nstr = NULL;
    elt->name = soap_strdup(soap, tag);
    elt->lead = NULL;
    elt->text = NULL;
    elt->code = NULL;
    elt->tail = NULL;
    elt->node = NULL;
    elt->type = 0;
    if (soap->dom)
    { struct soap_dom_element *p = soap->dom->elts;
      if (p)
      { while (p->next)
          p = p->next;
        p->next = elt;
      }
      else
        soap->dom->elts = elt;
    }
    soap->dom = elt;
    if (!elt->name)
      return soap->error = SOAP_EOM;
  }
  else
  {
#endif
#ifndef WITH_LEAN
    if (!soap->ns)
    { if (!(soap->mode & SOAP_XML_CANONICAL) && soap_send(soap, soap->prolog))
        return soap->error;
    }
    else if (soap->mode & SOAP_XML_INDENT)
    { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
        return soap->error;
      soap->body = 1;
    }
    if ((soap->mode & SOAP_XML_DEFAULTNS))
    { size_t n = 0;
      s = strchr(tag, ‘:‘);
      if (s)
        n = s++ - tag;
      else
        s = tag;
      if (soap_send_raw(soap, "<", 1)
       || soap_send(soap, s))
        return soap->error;
      if (n)
      { struct Namespace *ns = soap->local_namespaces;
        for (; ns && ns->id; ns++)
        { if (*ns->id && ns->ns && !strncmp(ns->id, tag, n) && !ns->id[n])
          { if (!soap->nlist || *soap->nlist->id || strcmp(soap->nlist->ns, ns->ns))
            { soap_push_ns(soap, SOAP_STR_EOS, ns->out ? ns->out : ns->ns, 0, 0);
              if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
                return soap->error;
            }
            break;
          }
        }
      }
      else if (!soap->nlist || *soap->nlist->id || *soap->nlist->ns)
      { soap_push_ns(soap, SOAP_STR_EOS, SOAP_STR_EOS, 0, 0);
        if (soap_attribute(soap, "xmlns", SOAP_STR_EOS))
          return soap->error;
      }
    }
    else
#endif
    if (soap_send_raw(soap, "<", 1)
     || soap_send(soap, tag))
      return soap->error;
#ifdef WITH_DOM
  }
#endif
  if (!soap->ns)
  { struct Namespace *ns = soap->local_namespaces;
    int k = -1;
    if (ns)
    { while (k-- && ns->id)
      { const char *t = ns->out;
        if (!t)
          t = ns->ns;
        if (*ns->id && t && *t)
        { (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(ns->id) + 6), "xmlns:%s", ns->id);
          if (soap_attribute(soap, soap->tmpbuf, t))
            return soap->error;
        }
        ns++;
      }
    }
  }
  soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table  */
#ifndef WITH_LEAN
  if ((soap->mode & SOAP_XML_CANONICAL))
  { if ((soap->mode & SOAP_XML_DEFAULTNS))
      soap_utilize_ns(soap, SOAP_STR_EOS, 0);
    else
      soap_utilize_ns(soap, tag, 0);
  }
#endif
  if (id > 0)
  { (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(SOAP_BASEREFNAME) + 20), SOAP_BASEREFNAME "%d", id);
    if (soap->version == 2)
    { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
        return soap->error;
    }
    else if (soap_attribute(soap, "id", soap->tmpbuf))
      return soap->error;
  }
  if (type && *type && !(soap->mode & SOAP_XML_NOTYPE))
  { const char *t = type;
#ifndef WITH_LEAN
    if ((soap->mode & SOAP_XML_CANONICAL))
      soap_utilize_ns(soap, type, 0);
#endif
    if (soap_attribute(soap, "xsi:type", t))
      return soap->error;
  }
  if (soap->null && soap->position > 0 && soap->version == 1)
  { int i;
    (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, 20), "[%d", soap->positions[0]);
    for (i = 1; i < soap->position; i++)
    { size_t l = strlen(soap->tmpbuf);
      (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l - 1, 20), ",%d", soap->positions[i]);
    }
    (void)soap_strncat(soap->tmpbuf, sizeof(soap->tmpbuf), "]", 1);
    if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
      return soap->error;
  }
  if (soap->mustUnderstand)
  { if (soap->actor && *soap->actor)
    { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
        return soap->error;
    }
    if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
      return soap->error;
    soap->mustUnderstand = 0;
  }
  if (soap->encoding)
  { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
    { if (!*soap->encodingStyle)
      { if (soap->local_namespaces[1].out)
          soap->encodingStyle = soap->local_namespaces[1].out;
        else
          soap->encodingStyle = soap->local_namespaces[1].ns;
      }
      if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
        return soap->error;
    }
    else
      soap->encodingStyle = NULL;
    soap->encoding = 0;
  }
  soap->null = 0;
  soap->position = 0;
  return SOAP_OK;
}
#endif

黑體字標示的地方,作用是吧ns2為首地址的各個成員指針指向在*.nsmap中的。


?SOAP_NMAC struct Namespace namespaces[]{...}定義成員

soap_attribute(){}函數是填寫/處理xml協議中的"<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:ter=">"類似xmlns:SOAP-ENV這些信息。


?soap_element_begin_out()

填寫/處理一個標簽的開始部分,包括它的屬性信息,例如:

xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope

{

.............

soap_element()函數填寫/處理一個xml節點標簽的從“<”開始到">"之前的所有信息,

..............

soap_element_start_end_out()函數填寫/處理同一xml節點標簽的">".

.................

}


?soap_putheader()

該函調用soap_out_SOAP_ENV__Header()

soap_out_SOAP_ENV__Header()
{//用於處理(填寫)xml中的soapheader部分標簽
            if (soap_element_begin_out()){//填寫/處理header的開始標簽
           }
          if (soap_out__wsa__MessageID()){
               //soap_out__wsa__MessageID()==soap_out_string(){
                //soap_outstring(){
                       //       id = soap_element_id()//該id值可以是soap->malloc動態分配的空間在soap機構中struct soap_plist *pht[SOAP_PTRHASH];鏈表中的id值
                        //
                       }
               //}
         }
}

?SOAP_FMAC5 int SOAP_FMAC6 soap_call___tds__(*)(例如GetNetworkInterfaces){

}

該函數用於最頂層的調用函數功能,具體包含實現了設備所具有的所有功能


?soap_default__<*>()

<*>代表相應的功能函數標識, 例如soap_default__tds__GetNetworkInterfacesResponse,該函數僅僅是對恢復結構進行初始化。


?soap_begin_count()

該函數在再次soap結構中一些在該請求中要用到和可能用到的量進行清零/初始化,最主要是的設置xml結構的mode信息默認情況下是soap->mode=0x20008;

?soap_begin_recv()

soap_begin_recv()
{
         .......//前面在進行一些在接收/解析過程中的用到的一些數據的初始化/清理
       c = soap_getchar(soap);/*第一次進行接收數據,然而即使這次數據量為零,也 沒有關  系,因為在後面的soap_envelope_begin_in()等函數中可以再次接收,也就是說第一次接收到數據量為0或者沒有接收完完整的協議內容也可以在後面的soap_envelope_begin_in()等這些函數中繼續接收,只要soap->socket不釋放掉就可以.其中soap->buflen中記錄了一次接收到的數據的字符統計數字,同時soap->count統計總的接收到的字符數.soap->bufidx = 0;soap->buflen = ret = soap->frecv()在每次socket接收前對soap->budidx進行清零;每次在soap_getchar(struct soap *soap){.......return soap_get1(soap);}之前對soap->ahead進行清零/處理;整理得知:soap_getchar()->soap_get1()->soap_recv()/return (unsigned char)soap->buf[soap->bufidx++];->soap_recv_raw(soap)->soap->frecv()*/
       ......//這裏是些宏選擇代碼
        while (soap_blank(c))//Ⅰ) Ⅱ)  Ⅲ) 這三句代碼目的:找到第一次接收到的數據信息中從soap->buf[0]開始的第一個不是0x00-0x20之間asii碼之間的字符
        c = soap_getchar(soap);
       .....//通過一系列的if()判斷後從接收到的buf中找打第一個符合協議的要求的字符,這個字符存儲在c變量中.然後把這個符合協議要求起始字符存儲在soap->ahead中(存儲的是ASII碼).
      soap->error = soap->fparse(soap);//解析出http協議部分.
}

?soap_envelope_begin_in()

soap_envelope_begin_in()
{//對指定的協議標識字符串進行解析, 例如SOAP-ENV:Envelope
        if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)){
            //soap_element_begin_in()=>if (!soap_peek_element(soap)){//soap_peek_element主要目的是在xml中找到相應的匹配字符串.例如SOAP-ENV:Envelope,存儲在soap->tag中
                      ..............
                      soap_unget(soap, c);//獲取到第一個xml協議的第一個"<"
                      ................
                      while (soap_blank(c))
                            c = soap_get(soap););//把xml協議的頭部信息過濾掉.即:<?xml .....?>
                    ....................
                      s = soap->tag;
                    do c = soap_get1(soap);
                      while (soap_blank(c));
                      i = sizeof(soap->tag);
                    while (c != ‘>‘ && c != ‘/‘ && soap_notblank(c) && (int)c != EOF)
                  { if (--i > 0)
                    *s++ = (char)c;
                    c = soap_get1(soap);
                    }
                      while (soap_blank(c))
                    c = soap_get1(soap);
                    *s = ‘\0‘;//這幾行把要解析的目標在xml中找到,即:"SOAP-ENV:Envelope"
                        ...........
                      soap_pop_namespace(soap);//根據soap結構定義,可能和首選什麽命名空間有關,在命令中也許和-n/-N有關,不確定.在測試中它返回值為NULL,即soap->nlist=NULL
                ........//後面緊接著是對命名空間的解析過程,同時對soap->body進行賦值if (!(soap->body = (c != ‘/‘)))            
                }
            }
}

?soap_recv_header()

把xml數據中的相應解析得到數據放置在在soap->header中

?soap_body_begin_in()

與前面的連個函數相似功能.



來自為知筆記(Wiz)

onvif 開發中的一些重要函數介紹