socket/xmlBlasterSocket.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------
00002 Name:      xmlBlasterSocket.c
00003 Project:   xmlBlaster.org
00004 Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
00005 Comment:   Contains some socket specific helper methods
00006 Author:    "Marcel Ruff" <xmlBlaster@marcelruff.info>
00007 -----------------------------------------------------------------------------*/
00008 #include <stdio.h>
00009 #include <string.h>
00010 #include <socket/xmlBlasterSocket.h>
00011 
00012 void closeSocket(int fd) {
00013 #ifdef _WINDOWS
00014    closesocket(fd);
00015 #else
00016    (void)close(fd);
00017 #endif
00018 }
00019 
00033 ssize_t writen(const int fd, const char * ptr, const size_t nbytes)
00034 {
00035    ssize_t nleft, nwritten;
00036    int flag = 0; /* MSG_WAITALL; */
00037 
00038    nleft = (ssize_t)nbytes;
00039    while(nleft > 0) {
00040       nwritten = send(fd, ptr, (int)nleft, flag); /* write() is deprecated on Win */
00041       if (nwritten <= 0) {
00042          return nwritten; /* error */
00043       }
00044       nleft -= nwritten;
00045       ptr += nwritten;
00046    }
00047    return (ssize_t)nbytes - nleft;
00048 }
00049 
00068 ssize_t readn(const int fd, char *ptr, const size_t nbytes, XmlBlasterNumReadFunc fpNumRead, void *userP)
00069 {
00070    ssize_t nread;
00071    ssize_t nleft;
00072    int flag = 0; /* MSG_WAITALL; */
00073    nleft = (ssize_t)nbytes;
00074 
00075    if (fpNumRead != 0 && nbytes > 10) { /* Ignore to report the msgLength read (first 10 bytes of a message) */
00076       fpNumRead(userP, (ssize_t)0, nbytes); /* Callback with startup status */
00077    }
00078 
00079    while(nleft > 0) {
00080       nread = recv(fd, ptr, (int)nleft, flag); /* read() is deprecated on Win */
00081       if (nread <= 0)  /* -1 is error, 0 is no more data to read which should not happen as we are blocking */
00082          break;        /* EOF is -1 */
00083       nleft -= nread;
00084 
00085       if (fpNumRead != 0 && nbytes > 10) { /* Ignore to report the msgLength read (first 10 bytes of a message) */
00086          fpNumRead(userP, (ssize_t)nbytes-nleft, nbytes); /* Callback with current status */
00087       }
00088 
00089       ptr += nread;
00090    }
00091    return (ssize_t)nbytes-nleft;
00092 }
00093 
00100 bool xbl_isOneway(XMLBLASTER_MSG_TYPE msgType, const char *const methodName) {
00101    if (msgType==MSG_TYPE_RESPONSE || msgType==MSG_TYPE_EXCEPTION)
00102       return true; /* Responses and exceptions are oneway */
00103    if (methodName == 0)
00104       return false;
00105    if (   
00106        !strcmp(XMLBLASTER_PUBLISH_ONEWAY, methodName)
00107        /*|| !strcmp(XMLBLASTER_DISCONNECT, methodName)*/ /* according to protocol.socket it returns an ACK: shall we remove it? */
00108        ) return true;
00109    return false;
00110 }
00111 
00119 Dll_Export BlobHolder encodeMsgUnit(MsgUnit *msgUnit, bool debug)
00120 {
00121    size_t qosLen=0, keyLen=0, contentLenStrLen=0;
00122    enum { SIZE = 126 };
00123    char contentLenStr[SIZE];
00124    size_t currpos = 0;
00125    BlobHolder blob;
00126    memset(&blob, 0, sizeof(BlobHolder));
00127 
00128    if (msgUnit == 0) {
00129       if (debug) printf("[xmlBlasterSocket] ERROR Invalid msgUnit=NULL in encodeMsgUnit()\n");
00130       return blob;
00131    }
00132    if (msgUnit->content == 0)
00133       msgUnit->contentLen = 0;
00134    SNPRINTF(contentLenStr, SIZE, "%ld", (long)msgUnit->contentLen);
00135    contentLenStrLen = strlen(contentLenStr);
00136 
00137    if (msgUnit->qos != 0)
00138       qosLen = strlen(msgUnit->qos);
00139    
00140    if (msgUnit->key != 0)
00141       keyLen = strlen(msgUnit->key);
00142    
00143    blob.dataLen = qosLen + 1 + keyLen + 1 + contentLenStrLen + 1 + msgUnit->contentLen;
00144 
00145    blob.data = (char *)malloc(blob.dataLen);
00146 
00147    if (msgUnit->qos != 0)
00148       memcpy(blob.data+currpos, msgUnit->qos, qosLen+1); /* inclusive '\0' */
00149    else
00150       *(blob.data+currpos) = 0;
00151    currpos += qosLen+1;
00152 
00153    if (msgUnit->key != 0)
00154       memcpy(blob.data+currpos, msgUnit->key, keyLen+1); /* inclusive '\0' */
00155    else
00156       *(blob.data+currpos) = 0;
00157    currpos += keyLen+1;
00158 
00159    memcpy(blob.data+currpos, contentLenStr, contentLenStrLen+1); /* inclusive '\0' */
00160    currpos += contentLenStrLen+1;
00161 
00162    if (msgUnit->content != 0)
00163       memcpy(blob.data+currpos, msgUnit->content, msgUnit->contentLen);
00164    /* currpos += msgUnit->contentLen; */
00165 
00166    return blob;
00167 }
00168 
00176 Dll_Export BlobHolder encodeMsgUnitArr(MsgUnitArr *msgUnitArr, bool debug)
00177 {
00178    size_t i;
00179    size_t currpos = 0;
00180 
00181    BlobHolder blob;
00182    memset(&blob, 0, sizeof(BlobHolder));
00183 
00184    if (msgUnitArr == 0) {
00185       if (debug) printf("[xmlBlasterSocket] ERROR Invalid msgUnitArr=NULL in encodeMsgUnitArr()\n");
00186       return blob;
00187    }
00188 
00189    /* First calculate total length to allocate */
00190    for (i=0; i<msgUnitArr->len; i++) {
00191       MsgUnit* msgUnit = &msgUnitArr->msgUnitArr[i];
00192       size_t qosLen=0, keyLen=0;
00193       enum { SIZE = 126 };
00194       char contentLenStr[SIZE];
00195 
00196       if (msgUnit->content == 0)
00197          msgUnit->contentLen = 0;
00198       snprintf0(contentLenStr, SIZE, "%ld", (long)msgUnit->contentLen);
00199 
00200       if (msgUnit->qos != 0)
00201          qosLen = strlen(msgUnit->qos);
00202       
00203       if (msgUnit->key != 0)
00204          keyLen = strlen(msgUnit->key);
00205    
00206       blob.dataLen += qosLen + 1 + keyLen + 1 + strlen(contentLenStr) + 1 + msgUnit->contentLen;
00207    }
00208 
00209    blob.data = (char *)malloc(blob.dataLen);
00210 
00211    /* Now dump the message ... */
00212    for (i=0; i<msgUnitArr->len; i++) {
00213       MsgUnit* msgUnit = &msgUnitArr->msgUnitArr[i];
00214       size_t qosLen=0, keyLen=0, contentLenStrLen=0;
00215       enum { SIZE = 126 };
00216       char contentLenStr[SIZE];
00217 
00218       if (msgUnit->content == 0)
00219          msgUnit->contentLen = 0;
00220       snprintf0(contentLenStr, SIZE, "%ld", (long)msgUnit->contentLen);
00221       contentLenStrLen = strlen(contentLenStr);
00222 
00223       if (msgUnit->qos != 0) {
00224          qosLen = strlen(msgUnit->qos);
00225          memcpy(blob.data+currpos, msgUnit->qos, qosLen+1); /* inclusive '\0' */
00226       }
00227       else
00228          *(blob.data+currpos) = 0;
00229       currpos += qosLen+1;
00230 
00231       if (msgUnit->key != 0) {
00232          keyLen = strlen(msgUnit->key);
00233          memcpy(blob.data+currpos, msgUnit->key, keyLen+1); /* inclusive '\0' */
00234       }
00235       else
00236          *(blob.data+currpos) = 0;
00237       currpos += keyLen+1;
00238 
00239       memcpy(blob.data+currpos, contentLenStr, contentLenStrLen+1); /* inclusive '\0' */
00240       currpos += contentLenStrLen+1;
00241 
00242       if (msgUnit->content != 0)
00243          memcpy(blob.data+currpos, msgUnit->content, msgUnit->contentLen);
00244       currpos += msgUnit->contentLen;
00245    }
00246    return blob;
00247 }
00248 
00249 char *encodeSocketMessage(
00250               enum XMLBLASTER_MSG_TYPE_ENUM msgType,
00251               const char * const requestId, 
00252               const char * const methodName,
00253               const char * const secretSessionId,
00254               const char *data,
00255               size_t dataLen,
00256               bool debug,
00257               size_t *rawMsgLen)
00258 {
00259    char *rawMsg = (char *)0;
00260    char *rawMsgStr;
00261    size_t currpos = 0;
00262    enum { SIZE = 256 };
00263    char tmp[SIZE];
00264    size_t lenUnzipped = dataLen;
00265    enum { SIZEF = 56 };
00266    char lenFormatStr[56]; /* = "%10.d"; */
00267    char lenStr[MSG_LEN_FIELD_LEN+1];
00268 
00269    if (data == 0) {
00270       data = "";
00271       dataLen = 0;
00272       lenUnzipped = 0;
00273    }
00274 
00275    rawMsg = (char *)calloc(50 + MAX_SESSIONID_LEN + MAX_METHODNAME_LEN + dataLen, sizeof(char));
00276 
00277    *(rawMsg+MSG_FLAG_POS_TYPE) = (char)msgType;   /* e.g. MSG_TYPE_INVOKE */
00278    *(rawMsg+MSG_FLAG_POS_VERSION) = XMLBLASTER_SOCKET_VERSION;
00279 
00280    currpos = MSG_POS_REQESTID;
00281    if (requestId == 0) printf("*** assert: xmlBlasterSocket.c requestId is NULL!\n");
00282    memcpy(rawMsg+currpos, requestId, strlen(requestId)+1); /* inclusive '\0' */
00283    currpos += strlen(requestId)+1;
00284 
00285    if (methodName == 0) printf("*** assert: xmlBlasterSocket.c methodName is NULL!\n");
00286    memcpy(rawMsg+currpos, methodName, strlen(methodName)+1); /* inclusive '\0' */
00287    currpos += strlen(methodName)+1;
00288 
00289    if (secretSessionId == 0) printf("*** assert: xmlBlasterSocket.c secretSessionId is NULL!\n");
00290    memcpy(rawMsg+currpos, secretSessionId, strlen(secretSessionId)+1); /* inclusive '\0' */
00291    currpos += strlen(secretSessionId)+1;
00292    
00293    snprintf0(tmp, SIZE, "%lu", (unsigned long)lenUnzipped);
00294    memcpy(rawMsg+currpos, tmp, strlen(tmp)+1); /* inclusive '\0' */
00295    currpos += strlen(tmp)+1;
00296 
00297    if (data == 0) printf("*** assert: xmlBlasterSocket.c data is NULL!\n");
00298    memcpy(rawMsg+currpos, data, dataLen);      /* add the msgUnit data */
00299    *rawMsgLen = currpos+dataLen;
00300 
00301    snprintf0(lenFormatStr, SIZEF, "%%%d.d", MSG_LEN_FIELD_LEN);
00302    snprintf0(lenStr, MSG_LEN_FIELD_LEN+1, lenFormatStr, *rawMsgLen);
00303    memcpy(rawMsg, lenStr, MSG_LEN_FIELD_LEN);
00304    
00305    if (debug) {
00306       rawMsgStr = toReadableDump(rawMsg, *rawMsgLen);
00307       printf("[xmlBlasterSocket] Sending now %lu bytes -> '%s'\n", (unsigned long)*rawMsgLen, rawMsgStr);
00308       free(rawMsgStr);
00309    }
00310 
00311    return rawMsg;
00312 }
00313 
00330 bool parseSocketData(int xmlBlasterSocket, const XmlBlasterReadFromSocketFuncHolder *fpHolder,
00331        SocketDataHolder *socketDataHolder, XmlBlasterException *exception, bool *stopP, bool udp, bool debug)
00332 {
00333    char msgLenPtr[MSG_LEN_FIELD_LEN+1];
00334    char *rawMsg = 0;
00335    char tmpPtr[256];
00336    ssize_t numRead;
00337    size_t currPos = 0;
00338    unsigned long msgLenL; /* to have 64 bit portable sscanf */
00339 
00340    char packet[MAX_PACKET_SIZE];
00341    /* initialize */
00342    memset(msgLenPtr, 0, MSG_LEN_FIELD_LEN+1);
00343    memset(socketDataHolder, 0, sizeof(SocketDataHolder));
00344    memset(exception, 0, sizeof(XmlBlasterException));
00345    exception->remote = false;
00346 
00347    if (debug) printf("[xmlBlasterSocket] Blocking now for %s callback messages ...\n", (udp) ? "udp" : "tcp");
00348    if (udp)
00349       numRead = recv(xmlBlasterSocket, packet, MAX_PACKET_SIZE, 0);
00350    else
00351       /* read the first 10 bytes to determine the length */
00352       numRead = fpHolder->readFromSocketFuncP(fpHolder->userP, xmlBlasterSocket, msgLenPtr, MSG_LEN_FIELD_LEN, fpHolder->numReadFuncP, fpHolder->numReadUserP);
00353    if (numRead <= 0 || *stopP == true) {
00354       return false; /* EOF on socket */
00355    }
00356    if ((!udp && numRead != MSG_LEN_FIELD_LEN) ||
00357        ( udp && numRead < MSG_LEN_FIELD_LEN)) {
00358       strncpy0(exception->errorCode, "user.connect", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00359       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN, "[xmlBlasterSocket] ERROR Received numRead=%ld header bytes but expected %d", (long)numRead, MSG_LEN_FIELD_LEN);
00360       if (debug) { printf(exception->message); printf("\n"); }
00361       return true;
00362    }
00363    if (udp) {
00364       memcpy(msgLenPtr,  packet, MSG_LEN_FIELD_LEN);
00365    }
00366    *(msgLenPtr + MSG_LEN_FIELD_LEN) = 0; 
00367    trim(msgLenPtr);
00368    if (strToULong(&msgLenL, msgLenPtr) == false) {
00369       strncpy0(exception->errorCode, "user.connect", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00370       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN,
00371               "[xmlBlasterSocket] ERROR Received numRead=%ld header bytes with invalid message length='%s'",
00372               (long)numRead, msgLenPtr);
00373       if (debug) { printf(exception->message); printf("\n"); }
00374       return true;
00375    }
00376    socketDataHolder->msgLen = (size_t)msgLenL;
00377    if (debug) printf("[xmlBlasterSocket] Receiving message of size %lu ...\n", (unsigned long)socketDataHolder->msgLen);
00378 
00379    if (socketDataHolder->msgLen <= MSG_LEN_FIELD_LEN || socketDataHolder->msgLen > MAX_MSG_LEN) {
00380       strncpy0(exception->errorCode, "user.connect", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00381       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN,
00382               "[xmlBlasterSocket] ERROR Received numRead=%ld header bytes with invalid message length='%s' parsed to '%ld'",
00383               (long)numRead, msgLenPtr, (long)socketDataHolder->msgLen);
00384       if (debug) { printf(exception->message); printf("\n"); }
00385       return true;
00386    }
00387 
00388    /* read the complete message */
00389    rawMsg = (char *)calloc(socketDataHolder->msgLen, sizeof(char));
00390    memcpy(rawMsg, msgLenPtr, MSG_LEN_FIELD_LEN);
00391    if (udp) {
00392       memcpy(rawMsg+MSG_LEN_FIELD_LEN, packet+MSG_LEN_FIELD_LEN, socketDataHolder->msgLen-MSG_LEN_FIELD_LEN);
00393       numRead -= MSG_LEN_FIELD_LEN;
00394    }
00395    else
00396       numRead = fpHolder->readFromSocketFuncP(fpHolder->userP, xmlBlasterSocket, rawMsg+MSG_LEN_FIELD_LEN,
00397                           (int)socketDataHolder->msgLen-MSG_LEN_FIELD_LEN, fpHolder->numReadFuncP, fpHolder->numReadUserP);
00398    if (numRead <= 0 || *stopP == true) {
00399       free(rawMsg);
00400       return false; /* EOF on socket */
00401    }
00402    if ((size_t)numRead != (socketDataHolder->msgLen-MSG_LEN_FIELD_LEN)) {
00403       strncpy0(exception->errorCode, "user.response", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00404       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN, "[xmlBlasterSocket] ERROR Received numRead=%ld message bytes but expected %lu", (long)numRead, (unsigned long)(socketDataHolder->msgLen-MSG_LEN_FIELD_LEN));
00405       if (debug) { printf(exception->message); printf("\n"); }
00406       free(rawMsg);
00407       return true;
00408    }
00409 
00410    if (debug) {
00411       char *rawMsgStr = toReadableDump(rawMsg, socketDataHolder->msgLen);
00412       printf("[xmlBlasterSocket] Read %lu bytes from socket -> '%s'\n", (unsigned long)socketDataHolder->msgLen, rawMsgStr);
00413       free(rawMsgStr);
00414    }
00415 
00416    /* if (debug) {
00417       char *tmp = toReadableDump(rawMsg, socketDataHolder->msgLen);
00418       printf("[xmlBlasterSocket] Read %u bytes from socket\n%s\n", socketDataHolder->msgLen, tmp);
00419       free(tmp);
00420    }*/
00421 
00422    socketDataHolder->type = *(rawMsg+MSG_FLAG_POS_TYPE);
00423    if (socketDataHolder->type != MSG_TYPE_INVOKE &&
00424        socketDataHolder->type != MSG_TYPE_RESPONSE &&
00425        socketDataHolder->type != MSG_TYPE_EXCEPTION) {
00426       strncpy0(exception->errorCode, "user.response", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00427       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN, "[xmlBlasterSocket] ERROR Received response message of type=%c", socketDataHolder->type);
00428       if (debug) { printf(exception->message); printf("\n"); }
00429       free(rawMsg);
00430       return true;
00431    }
00432 
00433    socketDataHolder->version = *(rawMsg+MSG_FLAG_POS_VERSION);
00434    if (socketDataHolder->version != XMLBLASTER_SOCKET_VERSION) {
00435       strncpy0(exception->errorCode, "user.response", XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00436       snprintf0(exception->message, EXCEPTIONSTRUCT_MESSAGE_LEN, "[xmlBlasterSocket] ERROR Received response message of unsupported version=%c", socketDataHolder->version);
00437       if (debug) { printf(exception->message); printf("\n"); }
00438       free(rawMsg);
00439       return true;
00440    }
00441 
00442 
00443    currPos = MSG_POS_REQESTID;
00444 
00445    strncpy0(socketDataHolder->requestId, rawMsg+currPos, MAX_REQUESTID_LEN);
00446    currPos += strlen(socketDataHolder->requestId)+1;
00447 
00448    strncpy0(socketDataHolder->methodName, rawMsg+currPos, MAX_METHODNAME_LEN);
00449    currPos += strlen(socketDataHolder->methodName)+1;
00450 
00451    strncpy0(socketDataHolder->secretSessionId, rawMsg+currPos, MAX_SESSIONID_LEN);
00452    currPos += strlen(socketDataHolder->secretSessionId)+1;
00453 
00454    strncpy0(tmpPtr, rawMsg+currPos, 256);
00455    currPos += strlen(tmpPtr)+1;
00456    trim(tmpPtr);
00457    socketDataHolder->dataLenUncompressed = 0;
00458    msgLenL = 0;
00459    if (strlen(tmpPtr) > 0 && strToULong(&msgLenL, tmpPtr) != 1) {
00460       printf("[xmlBlasterSocket] WARN uncompressed data length '%s' is invalid, we continue nevertheless\n", tmpPtr);
00461    }
00462    else {
00463       socketDataHolder->dataLenUncompressed = (size_t)msgLenL;
00464    }
00465 
00466    /* Read the payload */
00467    socketDataHolder->blob.dataLen = socketDataHolder->msgLen - currPos;
00468    if (socketDataHolder->blob.dataLen > 0) {
00469       socketDataHolder->blob.data = (char *)malloc(socketDataHolder->blob.dataLen * sizeof(char));
00470       memcpy(socketDataHolder->blob.data, rawMsg+currPos, socketDataHolder->blob.dataLen);
00471    }
00472    else {
00473       /*
00474       socketDataHolder->blob.dataLen = 6;
00475       socketDataHolder->blob.data = strcpyAlloc("<qos/>");
00476       */
00477       /*
00478       Allow empty message for example for get() returns with no match
00479       socketDataHolder->blob.dataLen = 1;
00480       socketDataHolder->blob.data = (char *)malloc(1);
00481       *socketDataHolder->blob.data = 0;
00482       */
00483    }
00484 
00485    free(rawMsg);
00486    rawMsg = 0;
00487    return true;
00488 }
00489 
00494 void convertToXmlBlasterException(const XmlBlasterBlob *blob, XmlBlasterException *exception, bool debug)
00495 {
00496    size_t currpos = 0;
00497    size_t len;
00498    /* initializeXmlBlasterException(exception); */
00499    exception->remote = true;
00500    strncpy0(exception->errorCode, blob->data+currpos, XMLBLASTEREXCEPTION_ERRORCODE_LEN);
00501    currpos += strlen(exception->errorCode) + 1;
00502    len = ((blob->dataLen-currpos) > XMLBLASTEREXCEPTION_MESSAGE_LEN) ? XMLBLASTEREXCEPTION_MESSAGE_LEN : (blob->dataLen-currpos);
00503    strncpy0(exception->message, blob->data+currpos, len);
00504    trim(exception->message);
00505    if (debug) printf("[xmlBlasterSocket] Converted to XmlBlasterException\n");
00506 }
00507 
00515 void encodeXmlBlasterException(XmlBlasterBlob *blob, const XmlBlasterException *exception, bool debug)
00516 {
00517    MsgUnit msgUnit;
00518    BlobHolder b;
00519 
00520    memset(&msgUnit, 0, sizeof(MsgUnit));
00521    msgUnit.qos = exception->errorCode;
00522    msgUnit.key = exception->message;
00523 
00524    b = encodeMsgUnit(&msgUnit, debug);
00525    blob->data = b.data;
00526    blob->dataLen = b.dataLen;
00527    if (debug) printf("[xmlBlasterSocket] Converted XmlBlasterException to SOCKET blob\n");
00528 }
00529 
00534 QosArr *parseQosArr(size_t dataLen, char *data)
00535 {
00536    size_t ii;
00537    MsgUnitArr *msgUnitArr = parseMsgUnitArr(dataLen, data);
00538    QosArr* qosArr = (QosArr *)calloc(1, sizeof(QosArr));
00539    qosArr->len = msgUnitArr->len;
00540    qosArr->qosArr = (const char **)calloc(qosArr->len, sizeof(const char *));
00541    for (ii=0; ii<msgUnitArr->len; ii++) {
00542       qosArr->qosArr[ii] = strcpyAlloc(msgUnitArr->msgUnitArr[ii].qos);
00543    }
00544    freeMsgUnitArr(msgUnitArr);
00545    return qosArr;
00546 }
00547 
00553 Dll_Export MsgUnitArr *parseMsgUnitArr(size_t dataLen, char *data)
00554 {
00555    MsgUnitArr *msgUnitArr = (MsgUnitArr *)calloc(1, sizeof(MsgUnitArr));
00556    size_t currpos = 0;
00557    uint32_t currIndex = 0;
00558    enum { SIZE = 56 };
00559    msgUnitArr->isOneway = false;
00560    if (dataLen <= 0) {
00561       return msgUnitArr; /* Empty messageUnit array, only a first \0 for the qos */
00562    }
00563    msgUnitArr->len = 10;
00564    msgUnitArr->msgUnitArr = (MsgUnit *)calloc(msgUnitArr->len, sizeof(MsgUnit));
00565    while (currpos < dataLen) {
00566       char ptr[SIZE];
00567 
00568       if (currIndex >= msgUnitArr->len) {
00569          msgUnitArr->len += 10;
00570          msgUnitArr->msgUnitArr = (MsgUnit *)realloc(msgUnitArr->msgUnitArr, msgUnitArr->len * sizeof(MsgUnit));
00571       }
00572 
00573       {
00574          unsigned long msgLenL; /* to have 64 bit portable sscanf */
00575          MsgUnit *msgUnit = &msgUnitArr->msgUnitArr[currIndex++];
00576          memset(msgUnit, 0, sizeof(MsgUnit));
00577         
00578          /* read QoS */
00579          msgUnit->qos = strcpyAlloc(data+currpos);
00580          currpos += strlen(msgUnit->qos)+1;
00581         
00582          /* read key */
00583          if (currpos < dataLen) {
00584             if (strlen(data+currpos) > 0) {
00585                msgUnit->key = strcpyAlloc(data+currpos);
00586                currpos += strlen(msgUnit->key)+1;
00587             }
00588             else {
00589                currpos++;
00590             }
00591          }
00592         
00593          /* read content */
00594          if (currpos < dataLen) {
00595             char *tmp;
00596             strncpy0(ptr, data+currpos, SIZE);
00597             currpos += strlen(ptr)+1;
00598             trim(ptr);
00599             msgLenL = 0;
00600             if (strToULong(&msgLenL, ptr) != 1) {
00601                printf("[xmlBlasterSocket] WARN MsgUnit content length '%s' is invalid, we continue nevertheless\n", ptr);
00602             }
00603             msgUnit->contentLen = (size_t)msgLenL;
00604         
00605             tmp = (char *)malloc(msgUnit->contentLen * sizeof(char));
00606             memcpy(tmp, data+currpos, msgUnit->contentLen);
00607             msgUnit->content = tmp;
00608             currpos += msgUnit->contentLen;
00609          }
00610       }
00611    }
00612 
00613    if (currIndex == 0) {
00614       free(msgUnitArr->msgUnitArr);
00615       msgUnitArr->len = 0;
00616    }
00617    else if (currIndex < msgUnitArr->len) {
00618       msgUnitArr->msgUnitArr = (MsgUnit *)realloc(msgUnitArr->msgUnitArr, currIndex * sizeof(MsgUnit));
00619       msgUnitArr->len = currIndex; 
00620    }
00621 
00622    return msgUnitArr;
00623 }