Back to index

lightning-sunbird  0.9+nobinonly
ipcMessage.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla IPC.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Darin Fisher <darin@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include "prlog.h"
00041 #include "ipcMessage.h"
00042 
00043 ipcMessage::~ipcMessage()
00044 {
00045     if (mMsgHdr)
00046         free(mMsgHdr);
00047 }
00048 
00049 void
00050 ipcMessage::Reset()
00051 {
00052     if (mMsgHdr) {
00053         free(mMsgHdr);
00054         mMsgHdr = NULL;
00055     }
00056 
00057     mMsgOffset = 0;
00058     mMsgComplete = PR_FALSE;
00059 }
00060 
00061 ipcMessage *
00062 ipcMessage::Clone() const
00063 {
00064     ipcMessage *clone = new ipcMessage();
00065     if (!clone)
00066         return NULL;
00067 
00068     // copy buf if non-null
00069     if (mMsgHdr) {
00070         clone->mMsgHdr = (ipcMessageHeader *) malloc(mMsgHdr->mLen);
00071         memcpy(clone->mMsgHdr, mMsgHdr, mMsgHdr->mLen);
00072     }
00073     else
00074         clone->mMsgHdr = NULL;
00075 
00076     clone->mMsgOffset = mMsgOffset;
00077     clone->mMsgComplete = mMsgComplete;
00078 
00079     return clone;
00080 }
00081 
00082 PRStatus
00083 ipcMessage::Init(const nsID &target, const char *data, PRUint32 dataLen)
00084 {
00085     if (mMsgHdr)
00086         free(mMsgHdr);
00087     mMsgComplete = PR_FALSE;
00088 
00089     // allocate message data
00090     PRUint32 msgLen = IPC_MSG_HEADER_SIZE + dataLen;
00091     mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
00092     if (!mMsgHdr) {
00093         mMsgHdr = NULL;
00094         return PR_FAILURE;
00095     }
00096 
00097     // fill in message data
00098     mMsgHdr->mLen = msgLen;
00099     mMsgHdr->mVersion = IPC_MSG_VERSION;
00100     mMsgHdr->mFlags = 0;
00101     mMsgHdr->mTarget = target;
00102 
00103     if (data)
00104         SetData(0, data, dataLen);
00105 
00106     mMsgComplete = PR_TRUE;
00107     return PR_SUCCESS;
00108 }
00109 
00110 PRStatus
00111 ipcMessage::SetData(PRUint32 offset, const char *data, PRUint32 dataLen)
00112 {
00113     PR_ASSERT(mMsgHdr != NULL);
00114 
00115     if (offset + dataLen > DataLen())
00116         return PR_FAILURE;
00117 
00118     memcpy((char *) Data() + offset, data, dataLen);
00119     return PR_SUCCESS;
00120 }
00121 
00122 PRBool
00123 ipcMessage::Equals(const nsID &target, const char *data, PRUint32 dataLen) const
00124 {
00125     return mMsgComplete && 
00126            mMsgHdr->mTarget.Equals(target) &&
00127            DataLen() == dataLen &&
00128            memcmp(Data(), data, dataLen) == 0;
00129 }
00130 
00131 PRBool
00132 ipcMessage::Equals(const ipcMessage *msg) const
00133 {
00134     PRUint32 msgLen = MsgLen();
00135     return mMsgComplete && msg->mMsgComplete &&
00136            msgLen == msg->MsgLen() &&
00137            memcmp(MsgBuf(), msg->MsgBuf(), msgLen) == 0;
00138 }
00139 
00140 PRStatus
00141 ipcMessage::WriteTo(char     *buf,
00142                     PRUint32  bufLen,
00143                     PRUint32 *bytesWritten,
00144                     PRBool   *complete)
00145 {
00146     if (!mMsgComplete)
00147         return PR_FAILURE;
00148 
00149     if (mMsgOffset == MsgLen()) {
00150         *bytesWritten = 0;
00151         *complete = PR_TRUE;
00152         return PR_SUCCESS;
00153     }
00154 
00155     PRUint32 count = MsgLen() - mMsgOffset;
00156     if (count > bufLen)
00157         count = bufLen;
00158 
00159     memcpy(buf, MsgBuf() + mMsgOffset, count);
00160     mMsgOffset += count;
00161 
00162     *bytesWritten = count;
00163     *complete = (mMsgOffset == MsgLen());
00164 
00165     return PR_SUCCESS;
00166 }
00167 
00168 PRStatus
00169 ipcMessage::ReadFrom(const char *buf,
00170                      PRUint32    bufLen,
00171                      PRUint32   *bytesRead,
00172                      PRBool     *complete)
00173 {
00174     *bytesRead = 0;
00175 
00176     if (mMsgComplete) {
00177         *complete = PR_TRUE;
00178         return PR_SUCCESS;
00179     }
00180 
00181     if (mMsgHdr) {
00182         // appending data to buffer
00183         if (mMsgOffset < sizeof(PRUint32)) {
00184             // we haven't learned the message length yet
00185             if (mMsgOffset + bufLen < sizeof(PRUint32)) {
00186                 // we still don't know the length of the message!
00187                 memcpy((char *) mMsgHdr + mMsgOffset, buf, bufLen);
00188                 mMsgOffset += bufLen;
00189                 *bytesRead = bufLen;
00190                 *complete = PR_FALSE;
00191                 return PR_SUCCESS;
00192             }
00193             else {
00194                 // we now have enough data to determine the message length
00195                 PRUint32 count = sizeof(PRUint32) - mMsgOffset;
00196                 memcpy((char *) MsgBuf() + mMsgOffset, buf, count);
00197                 mMsgOffset += count;
00198                 buf += count;
00199                 bufLen -= count;
00200                 *bytesRead = count;
00201                 
00202                 if (MsgLen() > IPC_MSG_GUESSED_SIZE) {
00203                     // realloc message buffer to the correct size
00204                     mMsgHdr = (ipcMessageHeader *) realloc(mMsgHdr, MsgLen());
00205                 }
00206             }
00207         }
00208     }
00209     else {
00210         if (bufLen < sizeof(PRUint32)) {
00211             // not enough data available in buffer to determine allocation size
00212             // allocate a partial buffer
00213             PRUint32 msgLen = IPC_MSG_GUESSED_SIZE;
00214             mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
00215             if (!mMsgHdr)
00216                 return PR_FAILURE;
00217             memcpy(mMsgHdr, buf, bufLen);
00218             mMsgOffset = bufLen;
00219             *bytesRead = bufLen;
00220             *complete = PR_FALSE;
00221             return PR_SUCCESS;
00222         }
00223         else {
00224             PRUint32 msgLen = *(PRUint32 *) buf;
00225             mMsgHdr = (ipcMessageHeader *) malloc(msgLen);
00226             if (!mMsgHdr)
00227                 return PR_FAILURE;
00228             mMsgHdr->mLen = msgLen;
00229             mMsgOffset = 0;
00230         }
00231     }
00232 
00233     // have mMsgHdr at this point
00234 
00235     PRUint32 count = MsgLen() - mMsgOffset;
00236     if (count > bufLen)
00237         count = bufLen;
00238 
00239     memcpy((char *) mMsgHdr + mMsgOffset, buf, count);
00240     mMsgOffset += count;
00241     *bytesRead += count;
00242 
00243     *complete = mMsgComplete = (mMsgOffset == MsgLen());
00244     return PR_SUCCESS;
00245 }