sdp_encode.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:18k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * sdp_encode.c
  23.  *
  24.  * Encodes session_desc_t structure into an SDP file.
  25.  *
  26.  * October, 2000
  27.  * Bill May (wmay@cisco.com)
  28.  * Cisco Systems, Inc.
  29.  */
  30. #include "sdp.h"
  31. #include "sdp_decode_private.h"
  32. typedef struct sdp_encode_t {
  33.   char *buffer;
  34.   uint32_t used;
  35.   uint32_t buflen;
  36. } sdp_encode_t;
  37. static int prepare_sdp_encode (sdp_encode_t *se)
  38. {
  39.   se->buffer = malloc(2048);
  40.   if (se->buffer == NULL) return ENOMEM;
  41.   se->buffer[0] = '';
  42.   se->used = 0;
  43.   se->buflen = 2048;
  44.   return (0);
  45. }
  46. static int add_string_to_encode (sdp_encode_t *sptr, const char *buf)
  47. {
  48.   uint32_t len;
  49.   char *temp;
  50.   
  51.   if (buf == NULL) return (EINVAL);
  52.   len = strlen(buf);
  53.   if (len == 0) return (0);
  54.   
  55.   if (len + 1 + sptr->used > sptr->buflen) {
  56.     temp = realloc(sptr->buffer, sptr->buflen + 1024);
  57.     if (temp == NULL)
  58.       return (ENOMEM);
  59.     sptr->buffer = temp;
  60.     sptr->buflen += 1024;
  61.   }
  62.   strcpy(sptr->buffer + sptr->used, buf);
  63.   sptr->used += len;
  64.   return (0);
  65. }
  66. #define ADD_STR_TO_ENCODE_WITH_RETURN(se, string) 
  67.  { int ret; ret = add_string_to_encode(se, string); if (ret != 0) return(ret);}
  68. #define CHECK_RETURN(a) {int ret; ret = (a); if (ret != 0) return (ret); }
  69. static int encode_a_ints (int recvonly,
  70.    int sendrecv,
  71.    int sendonly,
  72.    sdp_encode_t *se)
  73. {
  74.   if (recvonly)
  75.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=recvonlyn");
  76.   if (sendrecv)
  77.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=sendrecvn");
  78.   if (sendonly)
  79.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=sendonlyn");
  80.   return(0);
  81. }
  82. static int encode_string_list (string_list_t *sptr,
  83.        sdp_encode_t *se,
  84.        char* code,
  85.        int *cnt)
  86. {
  87.   int val;
  88.   val = 0;
  89.   while (sptr != NULL) {
  90.     ADD_STR_TO_ENCODE_WITH_RETURN(se, code);
  91.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->string_val);
  92.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  93.     val++;
  94.     sptr = sptr->next;
  95.   }
  96.   if (cnt != NULL) *cnt = val;
  97.   return (0);
  98. }
  99. static int encode_bandwidth (bandwidth_t *bptr, sdp_encode_t *se)
  100. {
  101.   char buffer[20];
  102.   while (bptr != NULL) {
  103.     if (bptr->modifier == BANDWIDTH_MODIFIER_NONE)
  104.       return (0);
  105.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "b=");
  106.     ADD_STR_TO_ENCODE_WITH_RETURN(se, 
  107.   bptr->modifier == BANDWIDTH_MODIFIER_USER ? 
  108.   bptr->user_band :
  109.   bptr->modifier == BANDWIDTH_MODIFIER_CT ?
  110.      "CT" : "AS");
  111.     sprintf(buffer, ":%ldn", bptr->bandwidth);
  112.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  113.     bptr = bptr->next;
  114.   }
  115.   return (0);
  116. }
  117. static int encode_category (category_list_t *cptr, sdp_encode_t *se)
  118. {
  119.   int first;
  120.   char buffer[40];
  121.   
  122.   first = FALSE;
  123.   while (cptr != NULL) {
  124.     if (first == FALSE) {
  125.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=cat:");
  126.       sprintf(buffer, "%llu", cptr->category);
  127.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  128.       first = TRUE;
  129.     } else {
  130.       sprintf(buffer, ".%llu", cptr->category);
  131.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  132.     }
  133.     cptr = cptr->next;
  134.   }
  135.   if (first == TRUE)
  136.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  137.   return(0);
  138. }
  139. static int encode_conf_type (session_desc_t *sptr, sdp_encode_t *se)
  140. {
  141.   const char *temp;
  142.   switch (sptr->conf_type) {
  143.   case CONFERENCE_TYPE_NONE:
  144.   default:
  145.     return (0);
  146.   case CONFERENCE_TYPE_OTHER:
  147.     temp = sptr->conf_type_user;
  148.     break;
  149.   case CONFERENCE_TYPE_BROADCAST:
  150.     temp = "broadcast";
  151.     break;
  152.   case CONFERENCE_TYPE_MEETING:
  153.     temp = "meeting";
  154.     break;
  155.   case CONFERENCE_TYPE_MODERATED:
  156.     temp = "moderated";
  157.     break;
  158.   case CONFERENCE_TYPE_TEST:
  159.     temp = "test";
  160.     break;
  161.   case CONFERENCE_TYPE_H332:
  162.     temp = "H322";
  163.     break;
  164.   }
  165.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=type:");
  166.   ADD_STR_TO_ENCODE_WITH_RETURN(se, temp);
  167.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  168.   return (0);
  169. }
  170. static int encode_connect (connect_desc_t *cptr, sdp_encode_t *se)
  171. {
  172.   char buffer[20];
  173.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "c=IN ");
  174.   ADD_STR_TO_ENCODE_WITH_RETURN(se, cptr->conn_type);
  175.   ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  176.   ADD_STR_TO_ENCODE_WITH_RETURN(se, cptr->conn_addr);
  177.   if (cptr->ttl) {
  178.     sprintf(buffer, "/%d", cptr->ttl);
  179.     ADD_STR_TO_ENCODE_WITH_RETURN(se,buffer);
  180.     if (cptr->num_addr) {
  181.       sprintf(buffer, "/%d", cptr->num_addr);
  182.       ADD_STR_TO_ENCODE_WITH_RETURN(se,buffer);
  183.     }
  184.   }
  185.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  186.   return (0);
  187. }
  188. static int encode_key (key_desc_t *kptr, sdp_encode_t *se)
  189. {
  190.   const char *temp;
  191.   
  192.   switch (kptr->key_type) {
  193.   case KEY_TYPE_NONE:
  194.   default:
  195.     return (0);
  196.   case KEY_TYPE_PROMPT:
  197.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "k=promptn");
  198.     return(0);
  199.   case KEY_TYPE_CLEAR:
  200.     temp ="clear";
  201.     break;
  202.   case KEY_TYPE_BASE64:
  203.     temp = "base64";
  204.     break;
  205.   case KEY_TYPE_URI:
  206.     temp = "uri";
  207.     break;
  208.   }
  209.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "k=");
  210.   ADD_STR_TO_ENCODE_WITH_RETURN(se, temp);
  211.   ADD_STR_TO_ENCODE_WITH_RETURN(se, ":");
  212.   ADD_STR_TO_ENCODE_WITH_RETURN(se, kptr->key);
  213.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  214.   return (0);
  215. }
  216. static int encode_range (range_desc_t *rptr, sdp_encode_t *se)
  217. {
  218.   char buffer[80];
  219.   if (rptr->have_range) {
  220.     if (rptr->range_is_npt) {
  221.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=npt:");
  222.       sprintf(buffer, "%g-", rptr->range_start);
  223.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  224.       if (rptr->range_end_infinite == FALSE) {
  225. sprintf(buffer,"%g", rptr->range_end);
  226. ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  227.       }
  228.     } else {
  229.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=smpte");
  230.       if (rptr->range_smpte_fps != 0) {
  231. sprintf(buffer, "-%d", rptr->range_smpte_fps);
  232. ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  233.       }
  234.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "=");
  235.       sdp_smpte_to_str(rptr->range_start, rptr->range_smpte_fps, buffer);
  236.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  237.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "-");
  238.       if (rptr->range_end_infinite == FALSE) {
  239. sdp_smpte_to_str(rptr->range_end, rptr->range_smpte_fps, buffer);
  240. ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  241.       }
  242.     }
  243.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  244.   }
  245.   return (0);
  246. }
  247. static int encode_time (session_time_desc_t *tptr, sdp_encode_t *se)
  248. {
  249.   uint64_t start, end;
  250.   time_repeat_desc_t *rptr;
  251.   uint32_t ix;
  252.   char buffer[80];
  253.   
  254.   while (tptr != NULL) {
  255.     start = tptr->start_time;
  256.     if (start != 0) start += NTP_TO_UNIX_TIME;
  257.     end = tptr->end_time;
  258.     if (end != 0) end += NTP_TO_UNIX_TIME;
  259.     sprintf(buffer, "t=%llu %llun", start, end);
  260.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  261.     rptr = tptr->repeat;
  262.     while (rptr != NULL) {
  263.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "r=");
  264.       sdp_time_offset_to_str(rptr->repeat_interval, buffer, sizeof(buffer));
  265.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  266.       ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  267.       sdp_time_offset_to_str(rptr->active_duration, buffer, sizeof(buffer));
  268.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  269.       for (ix = 0; ix < rptr->offset_cnt; ix++) {
  270. sprintf(buffer, " %d", rptr->offsets[ix]);
  271. ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  272.       }
  273.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  274.       rptr = rptr->next;
  275.     }
  276.     tptr = tptr->next;
  277.   }
  278.   return (0);
  279. }
  280. static int encode_time_adj (time_adj_desc_t *aptr, sdp_encode_t *se)
  281. {
  282.   uint64_t time;
  283.   uint32_t offset;
  284.   uint32_t len;
  285.   char buffer[40], *buff;
  286.   int dohead;
  287.   if (aptr == NULL) return (0);
  288.   
  289.   dohead = TRUE;
  290.   while (aptr != NULL) {
  291.     ADD_STR_TO_ENCODE_WITH_RETURN(se, dohead ? "z=" : " ");
  292.     time = aptr->adj_time + NTP_TO_UNIX_TIME;
  293.     sprintf(buffer, "%llu ", time);
  294.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  295.     if (aptr->offset < 0) {
  296.       offset = (0 - aptr->offset);
  297.       buffer[0] = '-';
  298.       buff = &buffer[1];
  299.       len = sizeof(buffer) - 1;
  300.     } else {
  301.       offset = aptr->offset;
  302.       buff = buffer;
  303.       len = sizeof(buffer);
  304.     }
  305.     sdp_time_offset_to_str(offset, buff, len);
  306.     
  307.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  308.     if (dohead == FALSE)
  309.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  310.     dohead = !dohead;
  311.     aptr = aptr->next;
  312.   }
  313.   if (dohead == FALSE)
  314.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  315.   return (0);
  316. }
  317. static int encode_orient (media_desc_t *mptr, sdp_encode_t *se)
  318. {
  319.   const char *temp;
  320.   switch (mptr->orient_type) {
  321.   case ORIENT_TYPE_NONE:
  322.   default:
  323.     return (0);
  324.     
  325.   case ORIENT_TYPE_PORTRAIT:
  326.     temp = "portrait";
  327.     break;
  328.   case ORIENT_TYPE_LANDSCAPE:
  329.     temp = "landscape";
  330.     break;
  331.   case ORIENT_TYPE_SEASCAPE:
  332.     temp = "seascape";
  333.     break;
  334.   case ORIENT_TYPE_USER:
  335.     temp = mptr->orient_user_type;
  336.     break;
  337.   }
  338.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=orient:");
  339.   ADD_STR_TO_ENCODE_WITH_RETURN(se, temp);
  340.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  341.   return(0);
  342. }
  343. static int encode_media (media_desc_t *mptr, sdp_encode_t *se)
  344. {
  345.   format_list_t *fptr;
  346.   char buffer[80];
  347.   
  348.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "m=");
  349.   ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->media);
  350.   
  351.   sprintf(buffer, " %u", mptr->port);
  352.   ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  353.   if (mptr->num_ports) {
  354.     sprintf(buffer,"/%u", mptr->num_ports);
  355.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  356.   }
  357.   ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  358.   ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->proto);
  359.   fptr = mptr->fmt;
  360.   while (fptr != NULL) {
  361.     ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  362.     ADD_STR_TO_ENCODE_WITH_RETURN(se, fptr->fmt);
  363.     fptr = fptr->next;
  364.   }
  365.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  366.   if (mptr->media_desc) {
  367.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "i=");
  368.     ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->media_desc);
  369.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  370.   }
  371.   if (mptr->media_connect.used) {
  372.     CHECK_RETURN(encode_connect(&mptr->media_connect, se));
  373.   }
  374.   CHECK_RETURN(encode_bandwidth(mptr->media_bandwidth, se));
  375.   CHECK_RETURN(encode_key(&mptr->key, se));
  376.   
  377.   if (mptr->ptime_present) {
  378.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=ptime:");
  379.     sprintf(buffer, "%un", mptr->ptime);
  380.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  381.   }
  382.   if (mptr->quality_present) {
  383.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=quality:");
  384.     sprintf(buffer, "%un", mptr->quality);
  385.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  386.   }
  387.   if (mptr->framerate_present) {
  388.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=framerate:");
  389.     sprintf(buffer, "%gn", mptr->framerate);
  390.     ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  391.   }
  392.   
  393.   if (mptr->control_string) {
  394.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=control:");
  395.     ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->control_string);
  396.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  397.   }
  398.   if (mptr->sdplang) {
  399.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=sdplang:");
  400.     ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->sdplang);
  401.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  402.   }
  403.   if (mptr->lang) {
  404.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=lang:");
  405.     ADD_STR_TO_ENCODE_WITH_RETURN(se, mptr->lang);
  406.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  407.   }
  408.   fptr = mptr->fmt;
  409.   while (fptr != NULL) {
  410.     if (fptr->rtpmap != NULL) {
  411.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=rtpmap:");
  412.       ADD_STR_TO_ENCODE_WITH_RETURN(se, fptr->fmt);
  413.       ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  414.       ADD_STR_TO_ENCODE_WITH_RETURN(se, fptr->rtpmap->encode_name);
  415.       sprintf(buffer, "/%u", fptr->rtpmap->clock_rate);
  416.       ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  417.       if (fptr->rtpmap->encode_param != 0) {
  418. sprintf(buffer, "/%u", fptr->rtpmap->encode_param);
  419. ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  420.       }
  421.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  422.     }
  423.     if (fptr->fmt_param != NULL) {
  424.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=fmtp:");
  425.       ADD_STR_TO_ENCODE_WITH_RETURN(se, fptr->fmt);
  426.       ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  427.       ADD_STR_TO_ENCODE_WITH_RETURN(se, fptr->fmt_param);
  428.       ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  429.     }
  430.     fptr = fptr->next;
  431.   }
  432.   CHECK_RETURN(encode_a_ints(mptr->recvonly,
  433.       mptr->sendrecv,
  434.       mptr->sendonly,
  435.       se));
  436.   CHECK_RETURN(encode_orient(mptr, se));
  437.   CHECK_RETURN(encode_range(&mptr->media_range, se));
  438.   CHECK_RETURN(encode_string_list(mptr->unparsed_a_lines, se, "", NULL));
  439.   return (0);
  440.   
  441. static int sdp_encode (session_desc_t *sptr, sdp_encode_t *se)
  442. {
  443.   int temp, temp1;
  444.   media_desc_t *mptr;
  445.   char buffer[80];
  446.   if (sptr->create_addr_type == NULL ||
  447.       sptr->create_addr == NULL) {
  448.     return (ESDP_ORIGIN);
  449.   }
  450.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "v=0no=");
  451.   ADD_STR_TO_ENCODE_WITH_RETURN(se,
  452. sptr->orig_username == NULL ?
  453. "-" : sptr->orig_username);
  454.   sprintf(buffer, " %lld %lld IN ",
  455.   sptr->session_id,
  456.   sptr->session_version);
  457.   ADD_STR_TO_ENCODE_WITH_RETURN(se, buffer);
  458.   ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->create_addr_type);
  459.   ADD_STR_TO_ENCODE_WITH_RETURN(se, " ");
  460.   ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->create_addr);
  461.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "ns=");
  462.   ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->session_name);
  463.   ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  464.   if (sptr->session_desc != NULL) {
  465.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "i=");
  466.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->session_desc);
  467.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  468.   }
  469.   if (sptr->uri != NULL) {
  470.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "u=");
  471.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->uri);
  472.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  473.   }
  474.   CHECK_RETURN(encode_string_list(sptr->admin_email, se, "e=", &temp));
  475.   CHECK_RETURN(encode_string_list(sptr->admin_phone, se, "p=", &temp1));
  476.   if (temp + temp1 == 0) {
  477.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "e=NONEn");
  478.   }
  479.   if (sptr->session_connect.used) {
  480.     CHECK_RETURN(encode_connect(&sptr->session_connect, se));
  481.   }
  482.   CHECK_RETURN(encode_bandwidth(sptr->session_bandwidth, se));
  483.   CHECK_RETURN(encode_time(sptr->time_desc, se));
  484.   CHECK_RETURN(encode_time_adj(sptr->time_adj_desc, se));
  485.   CHECK_RETURN(encode_key(&sptr->key, se));
  486.   if (sptr->control_string) {
  487.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=control:");
  488.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->control_string);
  489.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  490.   }
  491.   CHECK_RETURN(encode_category(sptr->category_list, se));
  492.   if (sptr->keywds) {
  493.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "u=");
  494.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->uri);
  495.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  496.   }
  497.   CHECK_RETURN(encode_conf_type(sptr, se));
  498.   if (sptr->tool) {
  499.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=tool:");
  500.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->tool);
  501.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  502.   }
  503.   if (sptr->charset) {
  504.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=charset:");
  505.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->charset);
  506.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  507.   }
  508.   if (sptr->sdplang) {
  509.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=sdplang:");
  510.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->sdplang);
  511.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  512.   }
  513.   if (sptr->lang) {
  514.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=lang:");
  515.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->lang);
  516.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  517.   }
  518.   if (sptr->etag) {
  519.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "a=etag:");
  520.     ADD_STR_TO_ENCODE_WITH_RETURN(se, sptr->etag);
  521.     ADD_STR_TO_ENCODE_WITH_RETURN(se, "n");
  522.   }
  523.   
  524.   CHECK_RETURN(encode_range(&sptr->session_range, se));
  525.   CHECK_RETURN(encode_a_ints(sptr->recvonly,
  526.       sptr->sendrecv,
  527.       sptr->sendonly,
  528.       se));
  529.   CHECK_RETURN(encode_string_list(sptr->unparsed_a_lines, se, "", NULL));
  530.   mptr = sptr->media;
  531.   while (mptr != NULL) {
  532.     CHECK_RETURN(encode_media(mptr, se));
  533.     mptr = mptr->next;
  534.   }
  535.   return (0);
  536. }  
  537.   
  538. int sdp_encode_one_to_file (session_desc_t *sptr,
  539.     const char *filename,
  540.     int append)
  541. {
  542.   FILE *ofile;
  543.   sdp_encode_t sdp;
  544.   CHECK_RETURN(prepare_sdp_encode(&sdp));
  545.   CHECK_RETURN(sdp_encode(sptr, &sdp));
  546.   ofile = fopen(filename, append ? "a" : "w");
  547.   if (ofile == NULL) {
  548.     free(sdp.buffer);
  549. return (-1);
  550.   }
  551.   fputs(sdp.buffer, ofile);
  552.   fclose(ofile);
  553.   free(sdp.buffer);
  554.   return (0);
  555. }
  556. int sdp_encode_list_to_file (session_desc_t *sptr,
  557.       const char *filename,
  558.       int append)
  559. {
  560.   FILE *ofile;
  561.   sdp_encode_t sdp;
  562.   int ret;
  563.   
  564.   CHECK_RETURN(prepare_sdp_encode(&sdp));
  565.   ofile = fopen(filename, append ? "a" : "w");
  566.   if (ofile == NULL) {
  567.     free(sdp.buffer);
  568. return (-1);
  569.   }
  570.   while (sptr != NULL) {
  571.     sdp.used = 0;
  572.     ret = sdp_encode(sptr, &sdp);
  573.     if (ret != 0) {
  574.       break;
  575.     }
  576.     fputs(sdp.buffer, ofile);
  577.     sptr = sptr->next;
  578.   }
  579.   fclose(ofile);
  580.   free(sdp.buffer);
  581.   return (0);
  582. }
  583. int sdp_encode_one_to_memory (session_desc_t *sptr, char **mem)
  584. {
  585.   sdp_encode_t sdp;
  586.   int ret;
  587.   
  588.   *mem = NULL;
  589.   CHECK_RETURN(prepare_sdp_encode(&sdp));
  590.   ret = sdp_encode(sptr, &sdp);
  591.   if (ret != 0) {
  592.     free(sdp.buffer);
  593.     return (ret);
  594.   }
  595.   *mem = sdp.buffer;
  596.   return (0);
  597. }
  598. int sdp_encode_list_to_memory (session_desc_t *sptr, char **mem, int *count)
  599. {
  600.   sdp_encode_t sdp;
  601.   int ret;
  602.   int cnt;
  603.   
  604.   *mem = NULL;
  605.   CHECK_RETURN(prepare_sdp_encode(&sdp));
  606.   cnt = 0;
  607.   ret = 0;
  608.   while (sptr != NULL && ret == 0) {
  609.     ret = sdp_encode(sptr, &sdp);
  610.     if (ret == 0)
  611.       cnt++;
  612.     sptr = sptr->next;
  613.   }
  614.   *mem = sdp.buffer;
  615.   if (count != NULL)
  616.     *count = cnt;
  617.   return (ret);
  618. }