#include #include #include #include #include #include "iiimp-dataP.h" IIIMP_message * iiimp_connect_new( IIIMP_data_s * data_s, IIIMP_string * user_name, IIIMP_string * auth) { IIIMP_message * m; int i; m = (IIIMP_message *)malloc(sizeof (IIIMP_message)); if (NULL == m) { data_s->status = IIIMP_DATA_MALLOC_ERROR; return NULL; } m->opcode = IM_CONNECT; m->im_id = -1; m->ic_id = -1; i = 1; m->v.connect.byte_order = ((0x01 == *((char *)(&i))) ? IM_CONNECT_LITTLE_ENDIAN : IM_CONNECT_BIG_ENDIAN); m->v.connect.protocol_version = data_s->protocol_version; m->v.connect.user_name = user_name; m->v.connect.auth = auth; return m; } void iiimp_connect_delete(IIIMP_data_s * data_s, IIIMP_message * m) { if (NULL == m) return; iiimp_string_delete(data_s, m->v.connect.user_name); iiimp_string_list_delete(data_s, m->v.connect.auth); free(m); return; } uchar_t * iiimp_connect_pack( IIIMP_data_s * data_s, IIIMP_string * user_name, IIIMP_string * auth_protocol, size_t * buf_size) { size_t nbyte; int length; uchar_t * buf; size_t rest; uchar_t * p; IIIMP_card8 byte_order; int i; IIIMP_string * a; size_t auth_nbyte; nbyte = 0; nbyte += (1 + 1); /* byte order + protocol version */ nbyte += user_name->nbyte; /* user name */ nbyte += 2; /* byte length of client auth protocol names */ for (auth_nbyte = 0, a = auth_protocol; NULL != a; a = a->next) { auth_nbyte += a->nbyte; } nbyte += auth_nbyte; /* client auth protocol names */ length = (nbyte >> 2); *buf_size = (1 + 3 + nbyte); buf = (uchar_t *)malloc(1 + 3 + nbyte); if (NULL == buf) { data_s->status = IIIMP_DATA_MALLOC_ERROR; return NULL; } PUT_PACKET_HEADER(buf, IM_CONNECT, length); rest = nbyte; p = (buf + 4); i = 1; byte_order = ((0x01 == *((char *)(&i))) ? IM_CONNECT_LITTLE_ENDIAN : IM_CONNECT_BIG_ENDIAN); PUTU8(byte_order, rest, p, data_s->byte_swap); PUTU8(data_s->protocol_version, rest, p, data_s->byte_swap); iiimp_string_pack(data_s, user_name, &rest, &p); PUTU16(auth_nbyte, rest, p, data_s->byte_swap); iiimp_string_list_pack(data_s, auth_protocol, &rest, &p); return buf; } IIIMP_message * iiimp_connect_unpack( IIIMP_data_s * data_s, IIIMP_card7 opcode, size_t * nbyte, const uchar_t ** ptr) { IIIMP_message * m; IIIMP_connect_v * v; size_t rest; const uchar_t * p; int len; int endian; int protocol_version; rest = *nbyte; p = *ptr; if (rest < (1 + 1 + 4 + 2)) { data_s->status = IIIMP_DATA_INVALID; return NULL; } m = (IIIMP_message *)malloc(sizeof (IIIMP_message)); if (NULL == m) { data_s->status = IIIMP_DATA_MALLOC_ERROR; return NULL; } v = &(m->v.connect); m->opcode = opcode; m->im_id = -1; m->ic_id = -1; v->user_name = NULL; v->auth = NULL; GETU8(v->byte_order, rest, p, 0); endian = 0x01; if (0x01 == (*(uchar_t *)(&endian))) { /* little endian */ if (IM_CONNECT_BIG_ENDIAN == v->byte_order) { data_s->byte_swap = 1; } else { data_s->byte_swap = 0; } } else { /* big endian */ if (IM_CONNECT_BIG_ENDIAN == v->byte_order) { data_s->byte_swap = 0; } else { data_s->byte_swap = 1; } } if ((IM_CONNECT_BIG_ENDIAN != v->byte_order) && (IM_CONNECT_LITTLE_ENDIAN != v->byte_order)) { free(m); data_s->status = IIIMP_DATA_INVALID; return NULL; } GETU8(v->protocol_version, rest, p, data_s->byte_swap); if (v->protocol_version == 0x31) { /* Unfortunately, some old client sends '1'(0x31) as a version number. We regard it as version 1. */ protocol_version = 1; } else { protocol_version = v->protocol_version; } if (protocol_version < data_s->protocol_version) { /* If the requested version is lower than the supported version, downgrade it. */ data_s->protocol_version = protocol_version; } v->user_name = iiimp_string_unpack(data_s, &rest, &p, rest); if ((NULL == v->user_name) || (rest < 2)) { iiimp_connect_delete(data_s, m); return NULL; } GETU16(len, rest, p, data_s->byte_swap); if ((len < 0) || (rest < len)) { iiimp_connect_delete(data_s, m); data_s->status = IIIMP_DATA_INVALID; return NULL; } if (0 < len) { v->auth = iiimp_string_list_unpack(data_s, &rest, &p, len); if (NULL == v->auth) { iiimp_connect_delete(data_s, m); return NULL; } } return m; } void iiimp_connect_print( IIIMP_data_s * data_s, IIIMP_message * m) { IIIMP_connect_v * v; v = &(m->v.connect); iiimp_message_header_print(data_s, m->opcode, -1, -1); switch (v->byte_order) { case IM_CONNECT_BIG_ENDIAN: (void)fprintf(data_s->print_fp, "\t%s\n", "big endian"); break; case IM_CONNECT_LITTLE_ENDIAN: (void)fprintf(data_s->print_fp, "\t%s\n", "little endian"); break; default: (void)fprintf(data_s->print_fp, "\t%s\n", "unknown endian"); break; } (void)fprintf(data_s->print_fp, "\tprotocol_version = 0x%02x\n", v->protocol_version); (void)fprintf(data_s->print_fp, "\tuser name = "); iiimp_string_print(data_s, v->user_name); (void)fputc('\n', data_s->print_fp); (void)fprintf(data_s->print_fp, "\tauth protocol name = "); iiimp_string_list_print(data_s, v->auth); (void)fputc('\n', data_s->print_fp); } /* Local Variables: */ /* c-file-style: "iiim-project" */ /* End: */