Mozilla/mozilla/java/xpcom/urp/src/urpMarshalToolkit.cpp
idk%eng.sun.com 08304b09e4 *not part of the build*
urpConnect update


git-svn-id: svn://10.0.0.236/trunk@99146 18797224-902f-48f8-a5cc-f745e15eee43
2001-07-12 23:27:20 +00:00

639 lines
19 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Sun Microsystems,
* Inc. Portions created by Sun are
* Copyright (C) 1999 Sun Microsystems, Inc. All
* Rights Reserved.
*
* Contributor(s):
* Sergey Lunegov <lsv@sparc.spb.su>
*/
#include "prmem.h"
#include "nsIInterfaceInfo.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIAllocator.h"
#include "nsCOMPtr.h"
#include "xptcall.h"
#include "nsCRT.h"
#include "urpMarshalToolkit.h"
#include <unistd.h>
#include "urpStub.h"
#include "urpLog.h"
#include "nsIModule.h"
class urpAllocator : public bcIAllocator { //nb make is smarter. It should deallocate allocated memory.
public:
urpAllocator(nsIAllocator *_allocator) {
allocator = _allocator;
}
virtual ~urpAllocator() {}
virtual void * Alloc(size_t size) {
return allocator->Alloc(size);
}
virtual void Free(void *ptr) {
allocator->Free(ptr);
}
virtual void * Realloc(void* ptr, size_t size) {
return allocator->Realloc(ptr,size);
}
private:
nsCOMPtr<nsIAllocator> allocator;
};
urpMarshalToolkit::urpMarshalToolkit(PRBool isclnt) {
isClient = isclnt;
}
urpMarshalToolkit::~urpMarshalToolkit() {
}
nsresult
urpMarshalToolkit::WriteElement(bcIUnMarshaler *um, nsXPTParamInfo * param, uint8 type, uint8 ind,
nsIInterfaceInfo* interfaceInfo, urpPacket* message,
PRUint16 methodIndex, const nsXPTMethodInfo *info,
bcIAllocator * allocator) {
void* data = allocator->Alloc(sizeof(void*));
nsID *id;
char* help;
PRLogModuleInfo *log = urpLog::GetLog();
nsresult r = NS_OK;
switch(type) {
case nsXPTType::T_IID :
id = new nsID();
um->ReadSimple(id,XPTType2bcXPType(type));
help = ((nsID)(*id)).ToString();
PR_LOG(log, PR_LOG_DEBUG, ("nsIID %s\n", help));
message->WriteString(help, strlen(help));
delete id;
PR_Free(help);
break;
case nsXPTType::T_I8 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteByte(*(char*)data);
break;
case nsXPTType::T_I16 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteShort(*(short*)data);
break;
case nsXPTType::T_I32 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteInt(*(int*)data);
break;
case nsXPTType::T_I64 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteLong(*(long*)data);
break;
case nsXPTType::T_U8 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteByte(*(char*)data);
break;
case nsXPTType::T_U16 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteShort(*(short*)data);
break;
case nsXPTType::T_U32 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteInt(*(int*)data);
break;
case nsXPTType::T_U64 :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteLong(*(long*)data);
break;
case nsXPTType::T_FLOAT :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteFloat(*(float*)data);
break;
case nsXPTType::T_DOUBLE :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteDouble(*(double*)data);
break;
case nsXPTType::T_CHAR :
case nsXPTType::T_WCHAR :
um->ReadSimple(data,XPTType2bcXPType(type));
message->WriteByte(*(char*)data);
break;
case nsXPTType::T_CHAR_STR :
case nsXPTType::T_WCHAR_STR :
{
size_t size;
um->ReadString(data,&size,allocator);
{
char *str = *(char**)data;
for (int i = 0; i < size && type == nsXPTType::T_WCHAR_STR; i++) {
char c = str[i];
}
}
data = *(char **)data;
size_t length = 0;
if(data != nsnull) {
if (type == nsXPTType::T_WCHAR_STR) {
length = nsCRT::strlen((const PRUnichar*)data);
length *= 2;
length +=2;
for (int i = 0; i < length && type == nsXPTType::T_WCHAR_STR; i++) {
char c = ((char*)data)[i];
}
} else {
length = nsCRT::strlen((const char*)data);
length+=1;
}
}
message->WriteString((char*)data,length);
break;
}
case nsXPTType::T_INTERFACE :
case nsXPTType::T_INTERFACE_IS :
{
nsIID iid;
bcOID oid;
um->ReadSimple(&oid,XPTType2bcXPType(type));
um->ReadSimple(&iid,bc_T_IID);
WriteOid(oid, message);
WriteType(iid, message);
break;
}
case nsXPTType::T_PSTRING_SIZE_IS:
case nsXPTType::T_PWSTRING_SIZE_IS:
case nsXPTType::T_ARRAY: //nb array of interfaces [to do]
{
size_t size;
nsXPTType datumType;
if(type != nsXPTType::T_ARRAY) {
um->ReadString(data,&size,allocator);
{
char *str = *(char**)data;
for (int i = 0; i < size && type == nsXPTType::T_WCHAR_STR; i++) {
char c = str[i];
}
}
} else {
if(NS_FAILED(interfaceInfo->GetTypeForParam(methodIndex, param, 1,&datumType))) {
allocator->Free(data);
return NS_ERROR_FAILURE;
}
PRUint32 arraySize;
PRInt16 elemSize = GetSimpleSize(datumType);
um->ReadSimple(&arraySize,bc_T_U32);
message->WriteInt(arraySize);
for (unsigned int i = 0; i < arraySize; i++) {
r = WriteElement(um,param,datumType.TagPart(),0,
interfaceInfo, message, methodIndex, info, allocator);
if(NS_FAILED(r)) {
allocator->Free(data);
return r;
}
}
}
if (type != nsXPTType::T_ARRAY) {
size_t length = 0;
if (type == nsXPTType::T_PWSTRING_SIZE_IS) {
length = size * sizeof(PRUnichar);
} else {
length = size;
}
message->WriteString((char*)data, length);
}
break;
}
default:
allocator->Free(data);
return r;
}
allocator->Free(data);
return r;
}
nsresult
urpMarshalToolkit::WriteParams(bcICall *call, PRUint32 paramCount, const nsXPTMethodInfo *info, nsIInterfaceInfo* interfaceInfo, urpPacket* message, PRUint16 methodIndex) {
int i;
nsresult rv = NS_OK;
bcIAllocator * allocator = new urpAllocator(nsAllocator::GetGlobalAllocator());
bcIUnMarshaler *um = call->GetUnMarshaler();
if(!isClient) {
nsresult result;
um->ReadSimple(&result, bc_T_U32);
message->WriteInt(result);
if(!NS_SUCCEEDED(result)) {
printf("Returned result is error on server side\n");
delete allocator;
delete um;
return rv;
}
}
for(i=0;i<paramCount;i++) {
short cache_index;
nsXPTParamInfo param = info->GetParam(i);
PRBool isOut = param.IsOut();
if ((isClient && !param.IsIn()) ||
(!isClient && !param.IsOut())) {
continue;
}
rv = WriteElement(um, &param,param.GetType().TagPart(), i, interfaceInfo, message, methodIndex, info, allocator);
if(NS_FAILED(rv)) {
delete allocator;
delete um;
return rv;
}
}
delete allocator;
delete um;
return rv;
}
nsresult
urpMarshalToolkit::ReadElement(nsXPTParamInfo * param, uint8 type,
nsIInterfaceInfo* interfaceInfo, urpPacket* message,
PRUint16 methodIndex, bcIAllocator* allocator,
bcIMarshaler* m, bcIORB *broker, urpManager* man,
urpConnection* conn) {
void* data = allocator->Alloc(sizeof(void*));
nsresult r = NS_OK;
char* str;
nsID id;
switch(type) {
case nsXPTType::T_IID :
{
int size;
str = message->ReadString(size);
id.Parse((char*)str);
m->WriteSimple((char*)&id, XPTType2bcXPType(type));
PR_Free(str);
break;
}
case nsXPTType::T_I8 :
*(char*)data = message->ReadByte();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_I16 :
*(short*)data = message->ReadShort();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_I32 :
*(int*)data = message->ReadInt();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_I64 :
*(long*)data = message->ReadLong();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_U8 :
*(char*)data = message->ReadByte();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_U16 :
*(short*)data = message->ReadShort();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_U32 :
*(int*)data = message->ReadInt();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_U64 :
*(long*)data = message->ReadLong();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_FLOAT :
*(float*)data = message->ReadFloat();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_DOUBLE :
*(double*)data = message->ReadDouble();
m->WriteSimple(data, XPTType2bcXPType(type));
break;
case nsXPTType::T_CHAR_STR :
case nsXPTType::T_WCHAR_STR :
{
int size;
/*
*(char**)data = message->ReadString(size);
data = *(char **)data;
*/
str = message->ReadString(size);
data = str;
size_t length = 0;
if (type == nsXPTType::T_WCHAR_STR) {
length = nsCRT::strlen((const PRUnichar*)data);
length *= 2;
length +=2;
for (int i = 0; i < length && type == nsXPTType::T_WCHAR_STR; i++) {
char c = ((char*)data)[i];
}
} else {
length = nsCRT::strlen((const char*)data);
length+=1;
}
m->WriteString(data,length);
PR_Free(str);
break;
}
case nsXPTType::T_INTERFACE :
case nsXPTType::T_INTERFACE_IS :
{
bcOID oid = ReadOid(message);
nsIID iid = ReadType(message);
nsISupports *proxy = NULL;
if (oid != 0) {
urpStub* stub = new urpStub(man, conn);
broker->RegisterStubWithOID(stub, &oid);
}
m->WriteSimple(&oid, XPTType2bcXPType(type));
m->WriteSimple(&iid,bc_T_IID);
break;
}
case nsXPTType::T_PSTRING_SIZE_IS:
case nsXPTType::T_PWSTRING_SIZE_IS:
case nsXPTType::T_ARRAY:
{
nsXPTType datumType;
if(NS_FAILED(interfaceInfo->GetTypeForParam(methodIndex, param, 1,&datumType))) {
allocator->Free(data);
return r;
}
PRUint32 arraySize;
PRInt16 elemSize = GetSimpleSize(datumType);
arraySize = message->ReadInt();
if(type == nsXPTType::T_ARRAY) {
m->WriteSimple(&arraySize,bc_T_U32);
char *current = *(char**)data;
for (int i = 0; i < arraySize; i++) {
ReadElement(param,datumType.TagPart(),interfaceInfo, message, methodIndex, allocator, m, broker, man, conn);
}
} else {
size_t length = 0;
if (type == nsXPTType::T_PWSTRING_SIZE_IS) {
length = arraySize * sizeof(PRUnichar);
} else {
length = arraySize;
}
m->WriteString(data, length);
}
break;
}
default:
allocator->Free(data);
return r;
}
allocator->Free(data);
return r;
}
nsresult
urpMarshalToolkit::ReadParams(PRUint32 paramCount, const nsXPTMethodInfo *info, urpPacket* message, nsIInterfaceInfo *interfaceInfo, PRUint16 methodIndex, bcICall* call, bcIORB *orb, urpManager* man, urpConnection* conn) {
bcIAllocator * allocator = new urpAllocator(nsAllocator::GetGlobalAllocator());
bcIMarshaler* m = call->GetMarshaler();
int i;
nsresult rv = NS_OK;
if(isClient) {
nsresult result = message->ReadInt();
m->WriteSimple(&result, bc_T_U32);
if (!NS_SUCCEEDED(result)) {
printf("Returned result is error on client side\n");
delete allocator;
delete m;
return rv;
}
}
for(i=0;i<paramCount;i++) {
short cache_index;
nsXPTParamInfo param = info->GetParam(i);
PRBool isOut = param.IsOut();
if ((!isClient && !param.IsIn()) ||
(isClient && !param.IsOut())) {
continue;
}
rv = ReadElement(&param, param.GetType().TagPart(), interfaceInfo,
message, methodIndex, allocator, m, orb, man, conn);
if(NS_FAILED(rv)) {
delete allocator;
delete m;
return rv;
}
}
delete allocator;
delete m;
return rv;
}
PRInt16 urpMarshalToolkit::GetSimpleSize(uint8 type) {
PRInt16 size = -1;
switch(type) {
case nsXPTType::T_I8:
case nsXPTType::T_U8:
size = sizeof(PRInt8);
break;
case nsXPTType::T_I16:
case nsXPTType::T_U16:
size = sizeof(PRInt16);
break;
case nsXPTType::T_I32:
case nsXPTType::T_U32:
size = sizeof(PRInt32);
break;
case nsXPTType::T_I64:
case nsXPTType::T_U64:
size = sizeof(PRInt64);
break;
case nsXPTType::T_FLOAT:
size = sizeof(float);
break;
case nsXPTType::T_DOUBLE:
size = sizeof(double);
break;
case nsXPTType::T_BOOL:
size = sizeof(PRBool);
break;
case nsXPTType::T_CHAR:
size = sizeof(char);
break;
case nsXPTType::T_WCHAR:
size = sizeof(PRUnichar);
break;
default:
size = sizeof(void*);
}
return size;
}
bcXPType urpMarshalToolkit::XPTType2bcXPType(uint8 type) {
switch(type) {
case nsXPTType::T_I8 :
return bc_T_I8;
case nsXPTType::T_U8 :
return bc_T_U8;
case nsXPTType::T_I16 :
return bc_T_I16;
case nsXPTType::T_U16 :
return bc_T_U16;
case nsXPTType::T_I32 :
return bc_T_I32;
case nsXPTType::T_U32 :
return bc_T_U32;
case nsXPTType::T_I64 :
return bc_T_I64;
case nsXPTType::T_U64 :
return bc_T_U64;
case nsXPTType::T_FLOAT :
return bc_T_FLOAT;
case nsXPTType::T_DOUBLE :
return bc_T_DOUBLE;
case nsXPTType::T_BOOL :
return bc_T_BOOL;
case nsXPTType::T_CHAR :
return bc_T_CHAR;
case nsXPTType::T_WCHAR :
return bc_T_WCHAR;
case nsXPTType::T_IID :
return bc_T_IID;
case nsXPTType::T_CHAR_STR :
case nsXPTType::T_PSTRING_SIZE_IS:
return bc_T_CHAR_STR;
case nsXPTType::T_WCHAR_STR :
case nsXPTType::T_PWSTRING_SIZE_IS:
return bc_T_WCHAR_STR;
case nsXPTType::T_INTERFACE :
case nsXPTType::T_INTERFACE_IS :
return bc_T_INTERFACE;
case nsXPTType::T_ARRAY:
return bc_T_ARRAY;
default:
return bc_T_UNDEFINED;
}
}
void
urpMarshalToolkit::WriteType(bcIID iid, urpPacket* message) {
short cache_index;
char typeClass = INTERFACE;
int found = 0;
if(0) //here should be checking on whether class is simple or not
printf("class is simple\n");
else {
if(0) { // here should be checking on whether cache is used
printf("cache is used\n");
cache_index = 0x0;
}
else
cache_index = (short)0xffff;
message->WriteByte((char)typeClass | (found ? 0x0 : 0x80));
message->WriteShort(cache_index);
if(!found) {
char* iidStr = iid.ToString();
message->WriteString(iidStr, strlen(iidStr));
PR_Free(iidStr);
}
}
}
bcIID
urpMarshalToolkit::ReadType(urpPacket* message) {
char byte = (char)message->ReadByte();
char typeClassValue = byte & 0xff;
short cache_index = message->ReadShort();
int size;
nsIID iid;
char* name = message->ReadString(size);
iid.Parse(name);
PR_Free(name);
return iid;
}
void
urpMarshalToolkit::WriteOid(bcOID oid, urpPacket* message) {
short cache_index;
int found = 0;
PRLogModuleInfo *log = urpLog::GetLog();
if(0) { // here should be checking on whether cache is used
PR_LOG(log, PR_LOG_DEBUG, ("cache is used\n"));
cache_index = 0x0;
}
else
cache_index = (short)0xffff;
char* str = (char*)calloc(100, sizeof(char));
sprintf(str,"%ld",oid);
message->WriteString(str, strlen(str));
free(str);
message->WriteShort(cache_index);
}
bcOID
urpMarshalToolkit::ReadOid(urpPacket* message) {
int size;
bcOID result;
char* str = message->ReadString(size);
short cache_index = message->ReadShort();
result = (bcOID)atol(str);
PR_Free(str);
return result;
}
void
urpMarshalToolkit::WriteThreadID(bcTID tid, urpPacket* message) {
short cache_index;
int found = 0;
char realTID[4]; /* this is hack: I know that bcTID is PRUint32
so it is represented by four bytes */
realTID[0] = tid>>24 & 0xff;
realTID[1] = (tid>>16) & 0xff;
realTID[2] = (tid>>8) & 0xff;
realTID[3] = tid & 0xff;
PRLogModuleInfo *log = urpLog::GetLog();
if(0) { // here should be checking on whether cache is used
PR_LOG(log, PR_LOG_DEBUG, ("cache is used\n"));
cache_index = 0x0;
}
else
cache_index = (short)0xffff;
message->WriteOctetStream(realTID, 4);
message->WriteShort(cache_index);
}
bcTID
urpMarshalToolkit::ReadThreadID(urpPacket* message) {
int size = 0;
bcTID result;
char* array = message->ReadOctetStream(size);
short cache_index = message->ReadShort();
result = ((unsigned char)array[0]<<24) + ((unsigned char)array[1]<<16) + ((unsigned char)array[2]<<8) + ((unsigned char)array[3]&0xff);
PR_Free(array);
return result;
}