Changeset cf02dd6 for libfaim/tlv.c


Ignore:
Timestamp:
Dec 10, 2003, 3:20:45 PM (17 years ago)
Author:
James M. Kretchmar <kretch@mit.edu>
Branches:
master, barnowl_perlaim, debian, owl, release-1.4, release-1.5, release-1.6, release-1.7, release-1.8, release-1.9
Children:
b1fe407
Parents:
8c46404
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfaim/tlv.c

    re374dee rcf02dd6  
    33#include <aim.h>
    44
    5 static aim_tlv_t *createtlv(void)
    6 {
    7         aim_tlv_t *newtlv;
    8 
    9         if (!(newtlv = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
     5static aim_tlv_t *createtlv(fu16_t type, fu16_t length, fu8_t *value)
     6{
     7        aim_tlv_t *ret;
     8
     9        if (!(ret = (aim_tlv_t *)malloc(sizeof(aim_tlv_t))))
    1010                return NULL;
    11         memset(newtlv, 0, sizeof(aim_tlv_t));
    12 
    13         return newtlv;
     11        ret->type = type;
     12        ret->length = length;
     13        ret->value = value;
     14
     15        return ret;
    1416}
    1517
     
    2830
    2931/**
    30  * aim_readtlvchain - Read a TLV chain from a buffer.
    31  * @param bs Input bstream
     32 * Read a TLV chain from a buffer.
    3233 *
    3334 * Reads and parses a series of TLV patterns from a data buffer; the
    3435 * returned structure is manipulatable with the rest of the TLV
    35  * routines.  When done with a TLV chain, aim_freetlvchain() should
     36 * routines.  When done with a TLV chain, aim_tlvlist_free() should
    3637 * be called to free the dynamic substructures.
    3738 *
     
    4243 * in libfaim.
    4344 *
    44  */
    45 faim_internal aim_tlvlist_t *aim_readtlvchain(aim_bstream_t *bs)
     45 * @param bs Input bstream
     46 */
     47faim_internal aim_tlvlist_t *aim_tlvlist_read(aim_bstream_t *bs)
    4648{
    4749        aim_tlvlist_t *list = NULL, *cur;
     
    7173
    7274                        if (length > aim_bstream_empty(bs)) {
    73                                 aim_freetlvchain(&list);
     75                                aim_tlvlist_free(&list);
    7476                                return NULL;
    7577                        }
     
    7779                        cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    7880                        if (!cur) {
    79                                 aim_freetlvchain(&list);
     81                                aim_tlvlist_free(&list);
    8082                                return NULL;
    8183                        }
     
    8385                        memset(cur, 0, sizeof(aim_tlvlist_t));
    8486
    85                         cur->tlv = createtlv();
     87                        cur->tlv = createtlv(type, length, NULL);
    8688                        if (!cur->tlv) {
    8789                                free(cur);
    88                                 aim_freetlvchain(&list);
     90                                aim_tlvlist_free(&list);
    8991                                return NULL;
    9092                        }
    91                         cur->tlv->type = type;
    92                         if ((cur->tlv->length = length)) {
    93                                cur->tlv->value = aimbs_getraw(bs, length);     
    94                                if (!cur->tlv->value) {
    95                                        freetlv(&cur->tlv);
    96                                        free(cur);
    97                                        aim_freetlvchain(&list);
    98                                        return NULL;
    99                                }
     93                        if (cur->tlv->length > 0) {
     94                                cur->tlv->value = aimbs_getraw(bs, length);     
     95                                if (!cur->tlv->value) {
     96                                        freetlv(&cur->tlv);
     97                                        free(cur);
     98                                        aim_tlvlist_free(&list);
     99                                        return NULL;
     100                                }
    100101                        }
    101102
     
    109110
    110111/**
    111  * aim_readtlvchain_num - Read a TLV chain from a buffer.
     112 * Read a TLV chain from a buffer.
     113 *
     114 * Reads and parses a series of TLV patterns from a data buffer; the
     115 * returned structure is manipulatable with the rest of the TLV
     116 * routines.  When done with a TLV chain, aim_tlvlist_free() should
     117 * be called to free the dynamic substructures.
     118 *
     119 * XXX There should be a flag setable here to have the tlvlist contain
     120 * bstream references, so that at least the ->value portion of each
     121 * element doesn't need to be malloc/memcpy'd.  This could prove to be
     122 * just as effecient as the in-place TLV parsing used in a couple places
     123 * in libfaim.
     124 *
    112125 * @param bs Input bstream
    113126 * @param num The max number of TLVs that will be read, or -1 if unlimited. 
     
    115128 *        but the chain is not at the end of the SNAC, and the chain is
    116129 *        preceeded by the number of TLVs.  So you can limit that with this.
     130 */
     131faim_internal aim_tlvlist_t *aim_tlvlist_readnum(aim_bstream_t *bs, fu16_t num)
     132{
     133        aim_tlvlist_t *list = NULL, *cur;
     134
     135        while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
     136                fu16_t type, length;
     137
     138                type = aimbs_get16(bs);
     139                length = aimbs_get16(bs);
     140
     141                if (length > aim_bstream_empty(bs)) {
     142                        aim_tlvlist_free(&list);
     143                        return NULL;
     144                }
     145
     146                cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
     147                if (!cur) {
     148                        aim_tlvlist_free(&list);
     149                        return NULL;
     150                }
     151
     152                memset(cur, 0, sizeof(aim_tlvlist_t));
     153
     154                cur->tlv = createtlv(type, length, NULL);
     155                if (!cur->tlv) {
     156                        free(cur);
     157                        aim_tlvlist_free(&list);
     158                        return NULL;
     159                }
     160                if (cur->tlv->length > 0) {
     161                        cur->tlv->value = aimbs_getraw(bs, length);
     162                        if (!cur->tlv->value) {
     163                                freetlv(&cur->tlv);
     164                                free(cur);
     165                                aim_tlvlist_free(&list);
     166                                return NULL;
     167                        }
     168                }
     169
     170                if (num > 0)
     171                        num--;
     172                cur->next = list;
     173                list = cur;
     174        }
     175
     176        return list;
     177}
     178
     179/**
     180 * Read a TLV chain from a buffer.
    117181 *
    118182 * Reads and parses a series of TLV patterns from a data buffer; the
    119183 * returned structure is manipulatable with the rest of the TLV
    120  * routines.  When done with a TLV chain, aim_freetlvchain() should
     184 * routines.  When done with a TLV chain, aim_tlvlist_free() should
    121185 * be called to free the dynamic substructures.
    122186 *
     
    127191 * in libfaim.
    128192 *
    129  */
    130 faim_internal aim_tlvlist_t *aim_readtlvchain_num(aim_bstream_t *bs, fu16_t num)
    131 {
    132         aim_tlvlist_t *list = NULL, *cur;
    133 
    134         while ((aim_bstream_empty(bs) > 0) && (num != 0)) {
    135                 fu16_t type, length;
    136 
    137                 type = aimbs_get16(bs);
    138                 length = aimbs_get16(bs);
    139 
    140                 if (length > aim_bstream_empty(bs)) {
    141                         aim_freetlvchain(&list);
    142                         return NULL;
    143                 }
    144 
    145                 cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    146                 if (!cur) {
    147                         aim_freetlvchain(&list);
    148                         return NULL;
    149                 }
    150 
    151                 memset(cur, 0, sizeof(aim_tlvlist_t));
    152 
    153                 cur->tlv = createtlv();
    154                 if (!cur->tlv) {
    155                         free(cur);
    156                         aim_freetlvchain(&list);
    157                         return NULL;
    158                 }
    159                 cur->tlv->type = type;
    160                 if ((cur->tlv->length = length)) {
    161                        cur->tlv->value = aimbs_getraw(bs, length);
    162                        if (!cur->tlv->value) {
    163                                freetlv(&cur->tlv);
    164                                free(cur);
    165                                aim_freetlvchain(&list);
    166                                return NULL;
    167                        }
    168                 }
    169 
    170                 num--;
    171                 cur->next = list;
    172                 list = cur;
    173         }
    174 
    175         return list;
    176 }
    177 
    178 /**
    179  * aim_readtlvchain_len - Read a TLV chain from a buffer.
    180193 * @param bs Input bstream
    181194 * @param len The max length in bytes that will be read.
     
    183196 *        but the chain is not at the end of the SNAC, and the chain is
    184197 *        preceeded by the length of the TLVs.  So you can limit that with this.
    185  *
    186  * Reads and parses a series of TLV patterns from a data buffer; the
    187  * returned structure is manipulatable with the rest of the TLV
    188  * routines.  When done with a TLV chain, aim_freetlvchain() should
    189  * be called to free the dynamic substructures.
    190  *
    191  * XXX There should be a flag setable here to have the tlvlist contain
    192  * bstream references, so that at least the ->value portion of each
    193  * element doesn't need to be malloc/memcpy'd.  This could prove to be
    194  * just as effecient as the in-place TLV parsing used in a couple places
    195  * in libfaim.
    196  *
    197  */
    198 faim_internal aim_tlvlist_t *aim_readtlvchain_len(aim_bstream_t *bs, fu16_t len)
     198 */
     199faim_internal aim_tlvlist_t *aim_tlvlist_readlen(aim_bstream_t *bs, fu16_t len)
    199200{
    200201        aim_tlvlist_t *list = NULL, *cur;
     
    207208
    208209                if (length > aim_bstream_empty(bs)) {
    209                         aim_freetlvchain(&list);
     210                        aim_tlvlist_free(&list);
    210211                        return NULL;
    211212                }
     
    213214                cur = (aim_tlvlist_t *)malloc(sizeof(aim_tlvlist_t));
    214215                if (!cur) {
    215                         aim_freetlvchain(&list);
     216                        aim_tlvlist_free(&list);
    216217                        return NULL;
    217218                }
     
    219220                memset(cur, 0, sizeof(aim_tlvlist_t));
    220221
    221                 cur->tlv = createtlv();
     222                cur->tlv = createtlv(type, length, NULL);
    222223                if (!cur->tlv) {
    223224                        free(cur);
    224                         aim_freetlvchain(&list);
     225                        aim_tlvlist_free(&list);
    225226                        return NULL;
    226227                }
    227                 cur->tlv->type = type;
    228                 if ((cur->tlv->length = length)) {
    229                        cur->tlv->value = aimbs_getraw(bs, length);
    230                        if (!cur->tlv->value) {
    231                                freetlv(&cur->tlv);
    232                                free(cur);
    233                                aim_freetlvchain(&list);
    234                                return NULL;
    235                        }
    236                 }
    237 
    238                 len -= aim_sizetlvchain(&cur);
     228                if (cur->tlv->length > 0) {
     229                        cur->tlv->value = aimbs_getraw(bs, length);
     230                        if (!cur->tlv->value) {
     231                                freetlv(&cur->tlv);
     232                                free(cur);
     233                                aim_tlvlist_free(&list);
     234                                return NULL;
     235                        }
     236                }
     237
     238                len -= aim_tlvlist_size(&cur);
    239239                cur->next = list;
    240240                list = cur;
     
    245245
    246246/**
    247  * aim_tlvlist_copy - Duplicate a TLV chain.
    248  * @param orig
    249  *
     247 * Duplicate a TLV chain.
    250248 * This is pretty pelf exslanatory.
    251249 *
     250 * @param orig The TLV chain you want to make a copy of.
     251 * @return A newly allocated TLV chain.
    252252 */
    253253faim_internal aim_tlvlist_t *aim_tlvlist_copy(aim_tlvlist_t *orig)
     
    256256
    257257        while (orig) {
    258                 aim_addtlvtochain_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
     258                aim_tlvlist_add_raw(&new, orig->tlv->type, orig->tlv->length, orig->tlv->value);
    259259                orig = orig->next;
    260260        }
     
    275275        aim_bstream_t bs1, bs2;
    276276
    277         if (aim_sizetlvchain(&one) != aim_sizetlvchain(&two))
     277        if (aim_tlvlist_size(&one) != aim_tlvlist_size(&two))
    278278                return 1;
    279279
    280         aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_sizetlvchain(&one)*sizeof(fu8_t))), aim_sizetlvchain(&one));
    281         aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_sizetlvchain(&two)*sizeof(fu8_t))), aim_sizetlvchain(&two));
    282 
    283         aim_writetlvchain(&bs1, &one);
    284         aim_writetlvchain(&bs2, &two);
     280        aim_bstream_init(&bs1, ((fu8_t *)malloc(aim_tlvlist_size(&one)*sizeof(fu8_t))), aim_tlvlist_size(&one));
     281        aim_bstream_init(&bs2, ((fu8_t *)malloc(aim_tlvlist_size(&two)*sizeof(fu8_t))), aim_tlvlist_size(&two));
     282
     283        aim_tlvlist_write(&bs1, &one);
     284        aim_tlvlist_write(&bs2, &two);
    285285
    286286        if (memcmp(bs1.data, bs2.data, bs1.len)) {
     
    297297
    298298/**
    299  * aim_freetlvchain - Free a TLV chain structure
     299 * Free a TLV chain structure
    300300 * @list: Chain to be freed
    301301 *
     
    305305 *
    306306 */
    307 faim_internal void aim_freetlvchain(aim_tlvlist_t **list)
     307faim_internal void aim_tlvlist_free(aim_tlvlist_t **list)
    308308{
    309309        aim_tlvlist_t *cur;
     
    328328
    329329/**
    330  * aim_counttlvchain - Count the number of TLVs in a chain
    331  * @list: Chain to be counted
    332  *
    333  * Returns the number of TLVs stored in the passed chain.
    334  *
    335  */
    336 faim_internal int aim_counttlvchain(aim_tlvlist_t **list)
     330 * Count the number of TLVs in a chain.
     331 *
     332 * @param list Chain to be counted.
     333 * @return The number of TLVs stored in the passed chain.
     334 */
     335faim_internal int aim_tlvlist_count(aim_tlvlist_t **list)
    337336{
    338337        aim_tlvlist_t *cur;
     
    349348
    350349/**
    351  * aim_sizetlvchain - Count the number of bytes in a TLV chain
    352  * @list: Chain to be sized
    353  *
    354  * Returns the number of bytes that would be needed to
    355  * write the passed TLV chain to a data buffer.
    356  *
    357  */
    358 faim_internal int aim_sizetlvchain(aim_tlvlist_t **list)
     350 * Count the number of bytes in a TLV chain.
     351 *
     352 * @param list Chain to be sized
     353 * @return The number of bytes that would be needed to
     354 *         write the passed TLV chain to a data buffer.
     355 */
     356faim_internal int aim_tlvlist_size(aim_tlvlist_t **list)
    359357{
    360358        aim_tlvlist_t *cur;
     
    371369
    372370/**
    373  * aim_addtlvtochain_raw - Add a string to a TLV chain
    374  * @list: Desination chain (%NULL pointer if empty)
    375  * @t: TLV type
    376  * @l: Length of string to add (not including %NULL)
    377  * @v: String to add
    378  *
    379371 * Adds the passed string as a TLV element of the passed type
    380372 * to the TLV chain.
    381373 *
    382  */
    383 faim_internal int aim_addtlvtochain_raw(aim_tlvlist_t **list, const fu16_t t, const fu16_t l, const fu8_t *v)
     374 * @param list Desination chain (%NULL pointer if empty).
     375 * @param type TLV type.
     376 * @length Length of string to add (not including %NULL).
     377 * @value String to add.
     378 * @retun The size of the value added.
     379 */
     380faim_internal int aim_tlvlist_add_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
    384381{
    385382        aim_tlvlist_t *newtlv, *cur;
    386383
    387         if (!list)
     384        if (list == NULL)
    388385                return 0;
    389386
     
    392389        memset(newtlv, 0x00, sizeof(aim_tlvlist_t));
    393390
    394         if (!(newtlv->tlv = createtlv())) {
     391        if (!(newtlv->tlv = createtlv(type, length, NULL))) {
    395392                free(newtlv);
    396393                return 0;
    397394        }
    398         newtlv->tlv->type = t;
    399         if ((newtlv->tlv->length = l)) {
     395        if (newtlv->tlv->length > 0) {
    400396                newtlv->tlv->value = (fu8_t *)malloc(newtlv->tlv->length);
    401                 memcpy(newtlv->tlv->value, v, newtlv->tlv->length);
     397                memcpy(newtlv->tlv->value, value, newtlv->tlv->length);
    402398        }
    403399
     
    414410
    415411/**
    416  * aim_addtlvtochain8 - Add a 8bit integer to a TLV chain
    417  * @list: Destination chain
    418  * @type: TLV type to add
    419  * @val: Value to add
    420  *
    421  * Adds a one-byte unsigned integer to a TLV chain.
    422  *
    423  */
    424 faim_internal int aim_addtlvtochain8(aim_tlvlist_t **list, const fu16_t t, const fu8_t v)
     412 * Add a one byte integer to a TLV chain.
     413 *
     414 * @param list Destination chain.
     415 * @param type TLV type to add.
     416 * @param value Value to add.
     417 * @retun The size of the value added.
     418 */
     419faim_internal int aim_tlvlist_add_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
    425420{
    426421        fu8_t v8[1];
    427422
    428         aimutil_put8(v8, v);
    429 
    430         return aim_addtlvtochain_raw(list, t, 1, v8);
    431 }
    432 
    433 /**
    434  * aim_addtlvtochain16 - Add a 16bit integer to a TLV chain
    435  * @list: Destination chain
    436  * @t: TLV type to add
    437  * @v: Value to add
    438  *
    439  * Adds a two-byte unsigned integer to a TLV chain.
    440  *
    441  */
    442 faim_internal int aim_addtlvtochain16(aim_tlvlist_t **list, const fu16_t t, const fu16_t v)
     423        aimutil_put8(v8, value);
     424
     425        return aim_tlvlist_add_raw(list, type, 1, v8);
     426}
     427
     428/**
     429 * Add a two byte integer to a TLV chain.
     430 *
     431 * @param list Destination chain.
     432 * @param type TLV type to add.
     433 * @param value Value to add.
     434 * @retun The size of the value added.
     435 */
     436faim_internal int aim_tlvlist_add_16(aim_tlvlist_t **list, const fu16_t type, const fu16_t value)
    443437{
    444438        fu8_t v16[2];
    445439
    446         aimutil_put16(v16, v);
    447 
    448         return aim_addtlvtochain_raw(list, t, 2, v16);
    449 }
    450 
    451 /**
    452  * aim_addtlvtochain32 - Add a 32bit integer to a TLV chain
    453  * @list: Destination chain
    454  * @type: TLV type to add
    455  * @val: Value to add
    456  *
    457  * Adds a four-byte unsigned integer to a TLV chain.
    458  *
    459  */
    460 faim_internal int aim_addtlvtochain32(aim_tlvlist_t **list, const fu16_t t, const fu32_t v)
     440        aimutil_put16(v16, value);
     441
     442        return aim_tlvlist_add_raw(list, type, 2, v16);
     443}
     444
     445/**
     446 * Add a four byte integer to a TLV chain.
     447 *
     448 * @param list Destination chain.
     449 * @param type TLV type to add.
     450 * @param value Value to add.
     451 * @retun The size of the value added.
     452 */
     453faim_internal int aim_tlvlist_add_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
    461454{
    462455        fu8_t v32[4];
    463456
    464         aimutil_put32(v32, v);
    465 
    466         return aim_addtlvtochain_raw(list, t, 4, v32);
    467 }
    468 
    469 /**
    470  * aim_addtlvtochain_caps - Add a capability block to a TLV chain
    471  * @list: Destination chain
    472  * @type: TLV type to add
    473  * @caps: Bitfield of capability flags to send
    474  *
     457        aimutil_put32(v32, value);
     458
     459        return aim_tlvlist_add_raw(list, type, 4, v32);
     460}
     461
     462/**
    475463 * Adds a block of capability blocks to a TLV chain. The bitfield
    476464 * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
    477465 *
    478  *      %AIM_CAPS_BUDDYICON   Supports Buddy Icons
    479  *
    480  *      %AIM_CAPS_VOICE       Supports Voice Chat
    481  *
    482  *      %AIM_CAPS_IMIMAGE     Supports DirectIM/IMImage
    483  *
    484  *      %AIM_CAPS_CHAT        Supports Chat
    485  *
    486  *      %AIM_CAPS_GETFILE     Supports Get File functions
    487  *
    488  *      %AIM_CAPS_SENDFILE    Supports Send File functions
    489  *
    490  */
    491 faim_internal int aim_addtlvtochain_caps(aim_tlvlist_t **list, const fu16_t t, const fu32_t caps)
     466 *     %AIM_CAPS_BUDDYICON   Supports Buddy Icons
     467 *     %AIM_CAPS_VOICE       Supports Voice Chat
     468 *     %AIM_CAPS_IMIMAGE     Supports DirectIM/IMImage
     469 *     %AIM_CAPS_CHAT        Supports Chat
     470 *     %AIM_CAPS_GETFILE     Supports Get File functions
     471 *     %AIM_CAPS_SENDFILE    Supports Send File functions
     472 *
     473 * @param list Destination chain
     474 * @param type TLV type to add
     475 * @param caps Bitfield of capability flags to send
     476 * @retun The size of the value added.
     477 */
     478faim_internal int aim_tlvlist_add_caps(aim_tlvlist_t **list, const fu16_t type, const fu32_t caps)
    492479{
    493480        fu8_t buf[16*16]; /* XXX icky fixed length buffer */
     
    501488        aim_putcap(&bs, caps);
    502489
    503         return aim_addtlvtochain_raw(list, t, aim_bstream_curpos(&bs), buf);
    504 }
    505 
    506 faim_internal int aim_addtlvtochain_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *ui)
     490        return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
     491}
     492
     493/**
     494 * Adds the given userinfo struct to a TLV chain.
     495 *
     496 * @param list Destination chain.
     497 * @param type TLV type to add.
     498 * @retun The size of the value added.
     499 */
     500faim_internal int aim_tlvlist_add_userinfo(aim_tlvlist_t **list, fu16_t type, aim_userinfo_t *userinfo)
    507501{
    508502        fu8_t buf[1024]; /* bleh */
     
    511505        aim_bstream_init(&bs, buf, sizeof(buf));
    512506
    513         aim_putuserinfo(&bs, ui);
    514 
    515         return aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
    516 }
    517 
    518 /**
    519  * aim_addtlvtochain_noval - Add a blank TLV to a TLV chain
    520  * @list: Destination chain
    521  * @type: TLV type to add
    522  *
     507        aim_putuserinfo(&bs, userinfo);
     508
     509        return aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
     510}
     511
     512/**
    523513 * Adds a TLV with a zero length to a TLV chain.
    524514 *
    525  */
    526 faim_internal int aim_addtlvtochain_noval(aim_tlvlist_t **list, const fu16_t t)
    527 {
    528         return aim_addtlvtochain_raw(list, t, 0, NULL);
     515 * @param list Destination chain.
     516 * @param type TLV type to add.
     517 * @retun The size of the value added.
     518 */
     519faim_internal int aim_tlvlist_add_noval(aim_tlvlist_t **list, const fu16_t type)
     520{
     521        return aim_tlvlist_add_raw(list, type, 0, NULL);
    529522}
    530523
     
    539532 *
    540533 */
    541 faim_internal int aim_addtlvtochain_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
     534faim_internal int aim_tlvlist_add_frozentlvlist(aim_tlvlist_t **list, fu16_t type, aim_tlvlist_t **tl)
    542535{
    543536        fu8_t *buf;
     
    545538        aim_bstream_t bs;
    546539
    547         buflen = aim_sizetlvchain(tl);
     540        buflen = aim_tlvlist_size(tl);
    548541
    549542        if (buflen <= 0)
     
    555548        aim_bstream_init(&bs, buf, buflen);
    556549
    557         aim_writetlvchain(&bs, tl);
    558 
    559         aim_addtlvtochain_raw(list, type, aim_bstream_curpos(&bs), buf);
     550        aim_tlvlist_write(&bs, tl);
     551
     552        aim_tlvlist_add_raw(list, type, aim_bstream_curpos(&bs), buf);
    560553
    561554        free(buf);
     
    565558
    566559/**
    567  * aim_writetlvchain - Write a TLV chain into a data buffer.
     560 * Substitute a TLV of a given type with a new TLV of the same type.  If
     561 * you attempt to replace a TLV that does not exist, this function will
     562 * just add a new TLV as if you called aim_tlvlist_add_raw().
     563 *
     564 * @param list Desination chain (%NULL pointer if empty).
     565 * @param type TLV type.
     566 * @param length Length of string to add (not including %NULL).
     567 * @param value String to add.
     568 * @return The length of the TLV.
     569 */
     570faim_internal int aim_tlvlist_replace_raw(aim_tlvlist_t **list, const fu16_t type, const fu16_t length, const fu8_t *value)
     571{
     572        aim_tlvlist_t *cur;
     573
     574        if (list == NULL)
     575                return 0;
     576
     577        for (cur = *list; ((cur != NULL) && (cur->tlv->type != type)); cur = cur->next);
     578        if (cur == NULL)
     579                return aim_tlvlist_add_raw(list, type, length, value);
     580
     581        free(cur->tlv->value);
     582        cur->tlv->length = length;
     583        if (cur->tlv->length > 0) {
     584                cur->tlv->value = (fu8_t *)malloc(cur->tlv->length);
     585                memcpy(cur->tlv->value, value, cur->tlv->length);
     586        } else
     587                cur->tlv->value = NULL;
     588
     589        return cur->tlv->length;
     590}
     591
     592/**
     593 * Substitute a TLV of a given type with a new TLV of the same type.  If
     594 * you attempt to replace a TLV that does not exist, this function will
     595 * just add a new TLV as if you called aim_tlvlist_add_raw().
     596 *
     597 * @param list Desination chain (%NULL pointer if empty).
     598 * @param type TLV type.
     599 * @return The length of the TLV.
     600 */
     601faim_internal int aim_tlvlist_replace_noval(aim_tlvlist_t **list, const fu16_t type)
     602{
     603        return aim_tlvlist_replace_raw(list, type, 0, NULL);
     604}
     605
     606/**
     607 * Substitute a TLV of a given type with a new TLV of the same type.  If
     608 * you attempt to replace a TLV that does not exist, this function will
     609 * just add a new TLV as if you called aim_tlvlist_add_raw().
     610 *
     611 * @param list Desination chain (%NULL pointer if empty).
     612 * @param type TLV type.
     613 * @param value 8 bit value to add.
     614 * @return The length of the TLV.
     615 */
     616faim_internal int aim_tlvlist_replace_8(aim_tlvlist_t **list, const fu16_t type, const fu8_t value)
     617{
     618        fu8_t v8[1];
     619
     620        aimutil_put8(v8, value);
     621
     622        return aim_tlvlist_replace_raw(list, type, 1, v8);
     623}
     624
     625/**
     626 * Substitute a TLV of a given type with a new TLV of the same type.  If
     627 * you attempt to replace a TLV that does not exist, this function will
     628 * just add a new TLV as if you called aim_tlvlist_add_raw().
     629 *
     630 * @param list Desination chain (%NULL pointer if empty).
     631 * @param type TLV type.
     632 * @param value 32 bit value to add.
     633 * @return The length of the TLV.
     634 */
     635faim_internal int aim_tlvlist_replace_32(aim_tlvlist_t **list, const fu16_t type, const fu32_t value)
     636{
     637        fu8_t v32[4];
     638
     639        aimutil_put32(v32, value);
     640
     641        return aim_tlvlist_replace_raw(list, type, 4, v32);
     642}
     643
     644/**
     645 * Remove a TLV of a given type.  If you attempt to remove a TLV that
     646 * does not exist, nothing happens.
     647 *
     648 * @param list Desination chain (%NULL pointer if empty).
     649 * @param type TLV type.
     650 */
     651faim_internal void aim_tlvlist_remove(aim_tlvlist_t **list, const fu16_t type)
     652{
     653        aim_tlvlist_t *del;
     654
     655        if (!list || !(*list))
     656                return;
     657
     658        /* Remove the item from the list */
     659        if ((*list)->tlv->type == type) {
     660                del = *list;
     661                *list = (*list)->next;
     662        } else {
     663                aim_tlvlist_t *cur;
     664                for (cur=*list; (cur->next && (cur->next->tlv->type!=type)); cur=cur->next);
     665                if (!cur->next)
     666                        return;
     667                del = cur->next;
     668                cur->next = del->next;
     669        }
     670
     671        /* Free the removed item */
     672        free(del->tlv->value);
     673        free(del->tlv);
     674        free(del);
     675}
     676
     677/**
     678 * aim_tlvlist_write - Write a TLV chain into a data buffer.
    568679 * @buf: Destination buffer
    569680 * @buflen: Maximum number of bytes that will be written to buffer
     
    572683 * Copies a TLV chain into a raw data buffer, writing only the number
    573684 * of bytes specified. This operation does not free the chain;
    574  * aim_freetlvchain() must still be called to free up the memory used
     685 * aim_tlvlist_free() must still be called to free up the memory used
    575686 * by the chain structures.
    576687 *
    577688 * XXX clean this up, make better use of bstreams
    578689 */
    579 faim_internal int aim_writetlvchain(aim_bstream_t *bs, aim_tlvlist_t **list)
     690faim_internal int aim_tlvlist_write(aim_bstream_t *bs, aim_tlvlist_t **list)
    580691{
    581692        int goodbuflen;
     
    583694
    584695        /* do an initial run to test total length */
    585         goodbuflen = aim_sizetlvchain(list);
     696        goodbuflen = aim_tlvlist_size(list);
    586697
    587698        if (goodbuflen > aim_bstream_empty(bs))
     
    601712
    602713/**
    603  * aim_gettlv - Grab the Nth TLV of type type in the TLV list list.
    604  * @list: Source chain
    605  * @type: Requested TLV type
    606  * @nth: Index of TLV of type to get
     714 * Grab the Nth TLV of type type in the TLV list list.
    607715 *
    608716 * Returns a pointer to an aim_tlv_t of the specified type;
     
    611719 * in a chain.
    612720 *
    613  */
    614 faim_internal aim_tlv_t *aim_gettlv(aim_tlvlist_t *list, const fu16_t t, const int n)
     721 * @param list Source chain.
     722 * @param type Requested TLV type.
     723 * @param nth Index of TLV of type to get.
     724 * @return The TLV you were looking for, or NULL if one could not be found.
     725 */
     726faim_internal aim_tlv_t *aim_tlv_gettlv(aim_tlvlist_t *list, const fu16_t type, const int nth)
    615727{
    616728        aim_tlvlist_t *cur;
     
    619731        for (cur = list, i = 0; cur; cur = cur->next) {
    620732                if (cur && cur->tlv) {
    621                         if (cur->tlv->type == t)
     733                        if (cur->tlv->type == type)
    622734                                i++;
    623                         if (i >= n)
     735                        if (i >= nth)
    624736                                return cur->tlv;
    625737                }
     
    630742
    631743/**
    632  * aim_gettlv_str - Retrieve the Nth TLV in chain as a string.
    633  * @list: Source TLV chain
    634  * @type: TLV type to search for
    635  * @nth: Index of TLV to return
    636  *
    637  * Same as aim_gettlv(), except that the return value is a %NULL-
    638  * terminated string instead of an aim_tlv_t.  This is a
    639  * dynamic buffer and must be freed by the caller.
    640  *
    641  */
    642 faim_internal char *aim_gettlv_str(aim_tlvlist_t *list, const fu16_t t, const int n)
     744 * Retrieve the data from the nth TLV in the given TLV chain as a string.
     745 *
     746 * @param list Source TLV chain.
     747 * @param type TLV type to search for.
     748 * @param nth Index of TLV to return.
     749 * @return The value of the TLV you were looking for, or NULL if one could
     750 *         not be found.  This is a dynamic buffer and must be freed by the
     751 *         caller.
     752 */
     753faim_internal char *aim_tlv_getstr(aim_tlvlist_t *list, const fu16_t type, const int nth)
    643754{
    644755        aim_tlv_t *tlv;
    645756        char *newstr;
    646757
    647         if (!(tlv = aim_gettlv(list, t, n)))
     758        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    648759                return NULL;
    649760
    650761        newstr = (char *) malloc(tlv->length + 1);
    651762        memcpy(newstr, tlv->value, tlv->length);
    652         *(newstr + tlv->length) = '\0';
     763        newstr[tlv->length] = '\0';
    653764
    654765        return newstr;
     
    656767
    657768/**
    658  * aim_gettlv8 - Retrieve the Nth TLV in chain as a 8bit integer.
    659  * @list: Source TLV chain
    660  * @type: TLV type to search for
    661  * @nth: Index of TLV to return
    662  *
    663  * Same as aim_gettlv(), except that the return value is a
    664  * 8bit integer instead of an aim_tlv_t.
    665  *
    666  */
    667 faim_internal fu8_t aim_gettlv8(aim_tlvlist_t *list, const fu16_t t, const int n)
     769 * Retrieve the data from the nth TLV in the given TLV chain as an 8bit
     770 * integer.
     771 *
     772 * @param list Source TLV chain.
     773 * @param type TLV type to search for.
     774 * @param nth Index of TLV to return.
     775 * @return The value the TLV you were looking for, or 0 if one could
     776 *         not be found.
     777 */
     778faim_internal fu8_t aim_tlv_get8(aim_tlvlist_t *list, const fu16_t type, const int nth)
    668779{
    669780        aim_tlv_t *tlv;
    670781
    671         if (!(tlv = aim_gettlv(list, t, n)))
     782        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    672783                return 0; /* erm */
    673784        return aimutil_get8(tlv->value);
     
    675786
    676787/**
    677  * aim_gettlv16 - Retrieve the Nth TLV in chain as a 16bit integer.
    678  * @list: Source TLV chain
    679  * @type: TLV type to search for
    680  * @nth: Index of TLV to return
    681  *
    682  * Same as aim_gettlv(), except that the return value is a
    683  * 16bit integer instead of an aim_tlv_t.
    684  *
    685  */
    686 faim_internal fu16_t aim_gettlv16(aim_tlvlist_t *list, const fu16_t t, const int n)
     788 * Retrieve the data from the nth TLV in the given TLV chain as a 16bit
     789 * integer.
     790 *
     791 * @param list Source TLV chain.
     792 * @param type TLV type to search for.
     793 * @param nth Index of TLV to return.
     794 * @return The value the TLV you were looking for, or 0 if one could
     795 *         not be found.
     796 */
     797faim_internal fu16_t aim_tlv_get16(aim_tlvlist_t *list, const fu16_t type, const int nth)
    687798{
    688799        aim_tlv_t *tlv;
    689800
    690         if (!(tlv = aim_gettlv(list, t, n)))
     801        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    691802                return 0; /* erm */
    692803        return aimutil_get16(tlv->value);
     
    694805
    695806/**
    696  * aim_gettlv32 - Retrieve the Nth TLV in chain as a 32bit integer.
    697  * @list: Source TLV chain
    698  * @type: TLV type to search for
    699  * @nth: Index of TLV to return
    700  *
    701  * Same as aim_gettlv(), except that the return value is a
    702  * 32bit integer instead of an aim_tlv_t.
    703  *
    704  */
    705 faim_internal fu32_t aim_gettlv32(aim_tlvlist_t *list, const fu16_t t, const int n)
     807 * Retrieve the data from the nth TLV in the given TLV chain as a 32bit
     808 * integer.
     809 *
     810 * @param list Source TLV chain.
     811 * @param type TLV type to search for.
     812 * @param nth Index of TLV to return.
     813 * @return The value the TLV you were looking for, or 0 if one could
     814 *         not be found.
     815 */
     816faim_internal fu32_t aim_tlv_get32(aim_tlvlist_t *list, const fu16_t type, const int nth)
    706817{
    707818        aim_tlv_t *tlv;
    708819
    709         if (!(tlv = aim_gettlv(list, t, n)))
     820        if (!(tlv = aim_tlv_gettlv(list, type, nth)))
    710821                return 0; /* erm */
    711822        return aimutil_get32(tlv->value);
    712823}
    713 
    714 #if 0
    715 /**
    716  * aim_puttlv_8 - Write a one-byte TLV.
    717  * @buf: Destination buffer
    718  * @t: TLV type
    719  * @v: Value
    720  *
    721  * Writes a TLV with a one-byte integer value portion.
    722  *
    723  */
    724 faim_export int aim_puttlv_8(fu8_t *buf, const fu16_t t, const fu8_t v)
    725 {
    726         fu8_t v8[1];
    727 
    728         aimutil_put8(v8, v);
    729 
    730         return aim_puttlv_raw(buf, t, 1, v8);
    731 }
    732 
    733 /**
    734  * aim_puttlv_16 - Write a two-byte TLV.
    735  * @buf: Destination buffer
    736  * @t: TLV type
    737  * @v: Value
    738  *
    739  * Writes a TLV with a two-byte integer value portion.
    740  *
    741  */
    742 faim_export int aim_puttlv_16(fu8_t *buf, const fu16_t t, const fu16_t v)
    743 {
    744         fu8_t v16[2];
    745 
    746         aimutil_put16(v16, v);
    747 
    748         return aim_puttlv_raw(buf, t, 2, v16);
    749 }
    750 
    751 
    752 /**
    753  * aim_puttlv_32 - Write a four-byte TLV.
    754  * @buf: Destination buffer
    755  * @t: TLV type
    756  * @v: Value
    757  *
    758  * Writes a TLV with a four-byte integer value portion.
    759  *
    760  */
    761 faim_export int aim_puttlv_32(fu8_t *buf, const fu16_t t, const fu32_t v)
    762 {
    763         fu8_t v32[4];
    764 
    765         aimutil_put32(v32, v);
    766 
    767         return aim_puttlv_raw(buf, t, 4, v32);
    768 }
    769 
    770 /**
    771  * aim_puttlv_raw - Write a raw TLV.
    772  * @buf: Destination buffer
    773  * @t: TLV type
    774  * @l: Length of string
    775  * @v: String to write
    776  *
    777  * Writes a TLV with a raw value portion.  (Only the first @l
    778  * bytes of the passed buffer will be written, which should not
    779  * include a terminating NULL.)
    780  *
    781  */
    782 faim_export int aim_puttlv_raw(fu8_t *buf, const fu16_t t, const fu16_t l, const fu8_t *v)
    783 {
    784         int i;
    785 
    786         i = aimutil_put16(buf, t);
    787         i += aimutil_put16(buf+i, l);
    788         if (l)
    789                 memcpy(buf+i, v, l);
    790         i += l;
    791 
    792         return i;
    793 }
    794 #endif
Note: See TracChangeset for help on using the changeset viewer.