status_t ConvertToAMessage(const Message & from, os::Message & to) { to.MakeEmpty(); to.SetCode(from.what); uint32 type; uint32 count; bool fixedSize; for (MessageFieldNameIterator it = from.GetFieldNameIterator(B_ANY_TYPE, HTIT_FLAG_NOREGISTER); it.HasData(); it++) { const String & n = it.GetFieldName(); if (from.GetInfo(n, &type, &count, &fixedSize) != B_NO_ERROR) return B_ERROR; for (uint32 j=0; j<count; j++) { const void * nextItem; uint32 itemSize; if (from.FindData(n, type, j, &nextItem, &itemSize) != B_NO_ERROR) return B_ERROR; // do any necessary translation from the Muscle data types to Be data types switch(type) { case B_POINT_TYPE: { const Point * p = static_cast<const Point *>(nextItem); os::Point bpoint(p->x(), p->y()); if (to.AddPoint(n, bpoint) != B_NO_ERROR) return B_ERROR; } break; case B_RECT_TYPE: { const Rect * r = static_cast<const Rect *>(nextItem); os::Rect brect(r->left(), r->top(), r->right(), r->bottom()); if (to.AddRect(n, brect) != B_NO_ERROR) return B_ERROR; } break; case B_MESSAGE_TYPE: { const MessageRef * msgRef = static_cast<const MessageRef *>(nextItem); os::Message amsg; if (msgRef->GetItemPointer() == NULL) return B_ERROR; if (ConvertToAMessage(*msgRef->GetItemPointer(), amsg) != B_NO_ERROR) return B_ERROR; if (to.AddMessage(n, &amsg) != B_NO_ERROR) return B_ERROR; } break; default: if (to.AddData(n, type, nextItem, itemSize, fixedSize, count) != B_NO_ERROR) return B_ERROR; break; } } } return B_NO_ERROR; }
static status_t WriteZipFileAux(zipFile zf, const String & baseName, const Message & msg, int compressionLevel, zip_fileinfo * fileInfo) { for (MessageFieldNameIterator iter = msg.GetFieldNameIterator(); iter.HasData(); iter++) { const String & fn = iter.GetFieldName(); uint32 fieldType; if (msg.GetInfo(fn, &fieldType) != B_NO_ERROR) return B_ERROR; switch(fieldType) { case B_MESSAGE_TYPE: { String newBaseName = baseName; if ((newBaseName.HasChars())&&(newBaseName.EndsWith('/') == false)) newBaseName += '/'; newBaseName += fn; // Message fields we treat as sub-directories MessageRef subMsg; for (int32 i=0; msg.FindMessage(fn, i, subMsg) == B_NO_ERROR; i++) if (WriteZipFileAux(zf, newBaseName, *subMsg(), compressionLevel, fileInfo) != B_NO_ERROR) return B_ERROR; } break; case B_RAW_TYPE: { String fileName = baseName; if ((fileName.HasChars())&&(fileName.EndsWith('/') == false)) fileName += '/'; fileName += fn; const void * data; uint32 numBytes; for (int32 i=0; msg.FindData(fn, B_RAW_TYPE, i, &data, &numBytes) == B_NO_ERROR; i++) { if (zipOpenNewFileInZip2(zf, fileName(), // file name fileInfo, // file info NULL, // const void* extrafield_local, 0, // uInt size_extrafield_local, NULL, // const void* extrafield_global, 0, // uInt size_extrafield_global, NULL, // const char* comment, (compressionLevel>0)?Z_DEFLATED:0, // int method, compressionLevel, // int compressionLevel 0) != ZIP_OK) return B_ERROR; if (zipWriteInFileInZip(zf, data, numBytes) != ZIP_OK) return B_ERROR; if (zipCloseFileInZip(zf) != ZIP_OK) return B_ERROR; } } break; } } return B_NO_ERROR; }
// This program exercises the Message class. int main(void) { Message m1; m1.AddFloat("va", 1.0f); printf("m1=" UINT32_FORMAT_SPEC "\n", m1.FlattenedSize()); m1.AddInt32("co", 32); printf("m2=" UINT32_FORMAT_SPEC "\n", m1.FlattenedSize()); printSep("Testing Replace*() with okayToAdd..."); Message butter; butter.ReplaceInt8(true, "int8", 8); butter.ReplaceInt16(true, "int16", 16); butter.ReplaceInt32(true, "int32", 32); butter.ReplaceInt64(true, "int64", 64); butter.ReplaceFloat(true, "float", 3.14f); butter.ReplaceDouble(true, "double", 6.28); butter.ReplacePoint(true, "point", Point(5,4)); butter.ReplaceRect(true, "rect", Rect(5,6,7,8)); butter.ReplacePointer(true, "pointer", &butter); butter.PrintToStream(); butter.ReplaceInt16(true, "int16", 0, 17); butter.ReplaceInt16(true, "int16", 1, 18); butter.ReplaceInt8(true, "int8", 25, 25); // should work the same as AddInt8("int8", 25); butter.AddTag("Tag", RefCountableRef(GetMessageFromPool(6666)())); butter.AddTag("Tag", RefCountableRef(GetMessageFromPool(7777)())); butter.PrintToStream(); printf("(butter==m1) == %i\n", butter == m1); printf("(butter==butter) == %i\n", butter == butter); printSep("Testing Add*()..."); Message msg(COMMAND_HELLO); TEST(msg.AddString("Friesner", "Jeremy")); TEST(msg.AddString("Friesner", "Joanna")); TEST(msg.AddString("Friesner", "Joellen")); TEST(msg.AddString("Chicken", "Soup")); TEST(msg.AddString("Chicken", "Vegetable")); TEST(msg.AddString("Chicken", "Lips")); TEST(msg.AddString("Fred", "Flintstone")); TEST(msg.AddString("Buddha", "Bark")); TEST(msg.AddPoint("point12", Point(1,2))); TEST(msg.AddPoint("point12", Point(2,1))); TEST(msg.AddRect("rect1234", Rect(1,2,3,4))); TEST(msg.AddRect("rect2345", Rect(2,3,4,5))); TEST(msg.AddData("Data", B_RAW_TYPE, "ABCDEFGHIJKLMNOPQRS", 12)); TEST(msg.AddData("Data", B_RAW_TYPE, "Mouse", 3)); Message subMessage(1); TEST(subMessage.AddString("I am a", "sub message!")); TEST(subMessage.AddInt32("My age is", 32)); Message subsubMessage(2); TEST(subsubMessage.AddBool("Wow, that's deep!", true)); TEST(subsubMessage.AddMessage("This is actually okay to do!", subsubMessage)); TEST(subMessage.AddMessage("subsubMessage", subsubMessage)); TEST(msg.AddMessage("subMessage", subMessage)); {for (int i=0; i<10; i++) TEST(msg.AddInt8("TestInt8", i)); } {for (int i=0; i<10; i++) TEST(msg.AddInt16("TestInt16", i)); } {for (int i=0; i<10; i++) TEST(msg.AddInt32("TestInt32", i)); } {for (int i=0; i<10; i++) TEST(msg.AddInt64("TestInt64", i)); } {for (int i=0; i<10; i++) TEST(msg.AddDouble("TestDouble", i));} {for (int i=0; i<10; i++) TEST(msg.AddFloat("TestFloat", i)); } {for (int i=0; i<10; i++) TEST(msg.AddBool("TestBool", i)); } printf("Finished message:\n"); msg.PrintToStream(); printSep("Testing RemoveName, RemoveData, Replace*()..."); TEST(msg.RemoveData("TestInt8", 5)); TEST(msg.RemoveName("Buddha")); TEST(msg.RemoveData("Fred", 0)); TEST(msg.RemoveData("Friesner", 1)); NEGATIVETEST(msg.RemoveData("Glorp", 0)); NEGATIVETEST(msg.RemoveData("Chicken", 5)); TEST(msg.ReplaceString(false, "Friesner", 0, "Jorge")); TEST(msg.ReplaceString(false, "Chicken", 1, "Feet")); TEST(msg.ReplaceString(false, "Chicken", 2, "Breast")); NEGATIVETEST(msg.ReplaceString(false, "Chicken", 3, "Soul")); TEST(msg.ReplaceDouble(true, "TestDouble", 2, 222.222)); TEST(msg.ReplaceFloat(true, "TestFloat", 3, 333.333)); NEGATIVETEST(msg.ReplaceFloat(false, "RootBeerFloat", 0, 444.444f)); TEST(msg.ReplaceBool(false, "TestBool", 5)); TEST(msg.ReplaceRect(false, "rect2345", Rect(2,3,4,5))); Message eqMsg = msg; printf("EQMSG=msg == %i\n", eqMsg==msg); printf("Replaced message:\n"); msg.PrintToStream(); printSep("Testing the Find() commands..."); String strResult; TEST(msg.FindString("Friesner", strResult)); printf("Friesner(0) = %s\n", strResult.Cstr()); const char * res; TEST(msg.FindString("Friesner", 1, &res)); printf("Friesner(1) = %s\n", res); NEGATIVETEST(msg.FindString("Friesner", 2, strResult)); NEGATIVETEST(msg.FindString("Friesner", 3, strResult)); int8 int8Result; TEST(msg.FindInt8("TestInt8", 5, int8Result)); printf("TestInt8(5) = %i\n",int8Result); int16 int16Result; TEST(msg.FindInt16("TestInt16", 4, int16Result)); printf("TestInt16(4) = %i\n",int16Result); int32 int32Result; TEST(msg.FindInt32("TestInt32", 4, int32Result)); printf("TestInt32(4) = " INT32_FORMAT_SPEC "\n",int32Result); int64 int64Result; TEST(msg.FindInt64("TestInt64", 4, int64Result)); printf("TestInt64(4) = " INT64_FORMAT_SPEC "\n",int64Result); float floatResult; TEST(msg.FindFloat("TestFloat", 4, floatResult)); printf("TestFloat(4) = %f\n",floatResult); double doubleResult; TEST(msg.FindDouble("TestDouble", 4, doubleResult)); printf("TestDouble(4) = %f\n",doubleResult); Rect rectResult; TEST(msg.FindRect("rect2345", rectResult)); printf("TestRect: "); rectResult.PrintToStream(); Point pointResult; TEST(msg.FindPoint("point12", 1, pointResult)); printf("TestPoint: "); pointResult.PrintToStream(); msg.AddTag("ThisShouldn'tBeBackAfterUnflatten", RefCountableRef(NULL)); const void * gd; uint32 getDataSize; TEST(msg.FindData("Data", B_RAW_TYPE, &gd, &getDataSize)); String dataStr((const char *) gd, getDataSize); printf("data=[%s], size=" UINT32_FORMAT_SPEC "\n", dataStr(), getDataSize); TEST(msg.FindData("Data", B_RAW_TYPE, 1, (const void **) &gd, &getDataSize)); dataStr.SetCstr((const char *) gd, getDataSize); printf("data(1)=[%s], size=" UINT32_FORMAT_SPEC "\n", dataStr(), getDataSize); printSep("Testing misc"); printf("There are " UINT32_FORMAT_SPEC " string entries\n", msg.GetNumNames(B_STRING_TYPE)); msg.PrintToStream(); Message tryMe = msg; printf("Msg is " UINT32_FORMAT_SPEC " bytes.\n",msg.FlattenedSize()); msg.AddTag("anothertag", RefCountableRef(GetMessageFromPool()())); printf("After adding tag, msg is (hopefully still) " UINT32_FORMAT_SPEC " bytes.\n",msg.FlattenedSize()); tryMe.PrintToStream(); printf("Extracting...\n"); Message extract; TEST(tryMe.FindMessage("subMessage", extract)); printSep("Extracted subMessage!\n"); extract.PrintToStream(); Message subExtract; TEST(extract.FindMessage("subsubMessage", subExtract)); printSep("Extracted subsubMessage!\n"); subExtract.PrintToStream(); const uint32 flatSize = msg.FlattenedSize(); printf("FlatSize=" UINT32_FORMAT_SPEC "\n",flatSize); uint8 * buf = new uint8[flatSize*10]; {for (uint32 i=flatSize; i<flatSize*10; i++) buf[i] = 'J';} msg.Flatten(buf); {for (uint32 i=flatSize; i<flatSize*10; i++) if (buf[i] != 'J') printf("OVERWRITE ON BYTE " UINT32_FORMAT_SPEC "\n",i);} printf("\n====\n"); Message copy; if (copy.Unflatten(buf, flatSize) == B_NO_ERROR) { printf("****************************\n"); copy.PrintToStream(); printf("***************************2\n"); Message dup(copy); dup.PrintToStream(); } else printf("Rats, Unflatten did not work. :^(\n"); { printf("Testing field name iterator... B_ANY_TYPE\n"); for (MessageFieldNameIterator it = copy.GetFieldNameIterator(B_ANY_TYPE); it.HasData(); it++) printf("--> [%s] (%i)\n", it.GetFieldName()(), it.HasData()); } { printf("Testing field name iterator... B_STRING_TYPE\n"); for (MessageFieldNameIterator it = copy.GetFieldNameIterator(B_STRING_TYPE); it.HasData(); it++) printf("--> [%s] (%i)\n", it.GetFieldName()(), it.HasData()); } { printf("Testing field name iterator... B_INT8_TYPE\n"); for (MessageFieldNameIterator it = copy.GetFieldNameIterator(B_INT8_TYPE); it.HasData(); it++) printf("--> [%s] (%i)\n", it.GetFieldName()(), it.HasData()); } { printf("Testing field name iterator... B_OBJECT_TYPE (should have no results)\n"); for (MessageFieldNameIterator it = copy.GetFieldNameIterator(B_OBJECT_TYPE); it.HasData(); it++) printf("--> [%s] (%i)\n", it.GetFieldName()(), it.HasData()); } return 0; }
App::App(void) : BApplication(STR_MUSCLE_DEAMON_NAME) , maxBytes(MUSCLE_NO_LIMIT) , maxNodesPerSession(MUSCLE_NO_LIMIT) , maxReceiveRate(MUSCLE_NO_LIMIT) , maxSendRate(MUSCLE_NO_LIMIT) , maxCombinedRate(MUSCLE_NO_LIMIT) , maxMessageSize(MUSCLE_NO_LIMIT) , maxSessions(MUSCLE_NO_LIMIT) , maxSessionsPerHost(MUSCLE_NO_LIMIT) , fprivateKeyFilePath(NULL) , retVal(0) , okay(true) { CompleteSetupSystem css; TCHECKPOINT; #ifdef MUSCLE_ENABLE_MEMORY_TRACKING printf("MUSCLE_ENABLE_MEMORY_TRACKING\n"); // Set up memory allocation policies for our server. These policies will make sure // that the server can't allocate more than a specified amount of memory, and if it tries, // some emergency callbacks will be called to free up cached info. FunctionCallback fcb(AbstractObjectRecycler::GlobalFlushAllCachedObjects); MemoryAllocatorRef nullRef; AutoCleanupProxyMemoryAllocator cleanupAllocator(nullRef); cleanupAllocator.GetCallbacksQueue().AddTail(GenericCallbackRef(&fcb, false)); UsageLimitProxyMemoryAllocator usageLimitAllocator(MemoryAllocatorRef(&cleanupAllocator, false)); SetCPlusPlusGlobalMemoryAllocator(MemoryAllocatorRef(&usageLimitAllocator, false)); SetCPlusPlusGlobalMemoryAllocator(MemoryAllocatorRef()); // unset, so that none of our allocator objects will be used after they are gone if ((maxBytes != MUSCLE_NO_LIMIT) && (&usageLimitAllocator)) usageLimitAllocator.SetMaxNumBytes(maxBytes); #endif TCHECKPOINT; server.GetAddressRemappingTable() = tempRemaps; if (maxNodesPerSession != MUSCLE_NO_LIMIT) server.GetCentralState().AddInt32(PR_NAME_MAX_NODES_PER_SESSION, maxNodesPerSession); for (MessageFieldNameIterator iter = tempPrivs.GetFieldNameIterator(); iter.HasData(); iter++) tempPrivs.CopyName(iter.GetFieldName(), server.GetCentralState()); // If the user asked for bandwidth limiting, create Policy objects to handle that. AbstractSessionIOPolicyRef inputPolicyRef, outputPolicyRef; if (maxCombinedRate != MUSCLE_NO_LIMIT) { inputPolicyRef.SetRef(newnothrow RateLimitSessionIOPolicy(maxCombinedRate)); outputPolicyRef = inputPolicyRef; if (inputPolicyRef()) LogTime(MUSCLE_LOG_INFO, "Limiting aggregate I/O bandwidth to %.02f kilobytes/second.\n", ((float)maxCombinedRate/1024.0f)); else { WARN_OUT_OF_MEMORY; okay = false; } } else { if (maxReceiveRate != MUSCLE_NO_LIMIT) { inputPolicyRef.SetRef(newnothrow RateLimitSessionIOPolicy(maxReceiveRate)); if (inputPolicyRef()) LogTime(MUSCLE_LOG_INFO, "Limiting aggregate receive bandwidth to %.02f kilobytes/second.\n", ((float)maxReceiveRate/1024.0f)); else { WARN_OUT_OF_MEMORY; okay = false; } } if (maxSendRate != MUSCLE_NO_LIMIT) { outputPolicyRef.SetRef(newnothrow RateLimitSessionIOPolicy(maxSendRate)); if (outputPolicyRef()) LogTime(MUSCLE_LOG_INFO, "Limiting aggregate send bandwidth to %.02f kilobytes/second.\n", ((float)maxSendRate/1024.0f)); else { WARN_OUT_OF_MEMORY; okay = false; } } } // Set up the Session Factory. This factory object creates the new StorageReflectSessions // as needed when people connect, and also has a filter to keep out the riff-raff. StorageReflectSessionFactory factory; factory.SetMaxIncomingMessageSize(maxMessageSize); FilterSessionFactory filter(ReflectSessionFactoryRef(&factory, false), maxSessionsPerHost, maxSessions); filter.SetInputPolicy(inputPolicyRef); filter.SetOutputPolicy(outputPolicyRef); for (int b=bans.GetNumItems()-1; ((okay)&&(b>=0)); b--) if (filter.PutBanPattern(bans[b]()) != B_NO_ERROR) okay = false; for (int a=requires.GetNumItems()-1; ((okay)&&(a>=0)); a--) if (filter.PutRequirePattern(requires[a]()) != B_NO_ERROR) okay = false; #ifdef MUSCLE_ENABLE_SSL ByteBufferRef optCryptoBuf; if (fprivateKeyFilePath) { FileDataIO fdio(muscleFopen(fprivateKeyFilePath->Cstr(), "rb")); ByteBufferRef fileData = GetByteBufferFromPool((uint32)fdio.GetLength()); if ((fdio.GetFile())&&(fileData())&&(fdio.ReadFully(fileData()->GetBuffer(), fileData()->GetNumBytes()) == fileData()->GetNumBytes())) { LogTime(MUSCLE_LOG_INFO, "Using private key file [%s] to authenticate with connecting clients\n", fprivateKeyFilePath->Cstr()); server.SetSSLPrivateKey(fileData); } else { LogTime(MUSCLE_LOG_CRITICALERROR, "Couldn't load private key file [%s] (file not found?)\n", fprivateKeyFilePath->Cstr()); okay = false; } } #else if (fprivateKeyFilePath) { LogTime(MUSCLE_LOG_CRITICALERROR, "Can't loadp private key file [%s], SSL support is not compiled in!\n", fprivateKeyFilePath->Cstr()); okay = false; } #endif // Set up ports. We allow multiple ports, mostly just to show how it can be done; // they all get the same set of ban/require patterns (since they all do the same thing anyway). if (listenPorts.IsEmpty()) listenPorts.PutWithDefault(IPAddressAndPort(invalidIP, DEFAULT_MUSCLED_PORT)); for (HashtableIterator<IPAddressAndPort, Void> iter(listenPorts); iter.HasData(); iter++) { const IPAddressAndPort & iap = iter.GetKey(); if (server.PutAcceptFactory(iap.GetPort(), ReflectSessionFactoryRef(&filter, false), iap.GetIPAddress()) != B_NO_ERROR) { if (iap.GetIPAddress() == invalidIP) LogTime(MUSCLE_LOG_CRITICALERROR, "Error adding port %u, aborting.\n", iap.GetPort()); else LogTime(MUSCLE_LOG_CRITICALERROR, "Error adding port %u to interface %s, aborting.\n", iap.GetPort(), Inet_NtoA(iap.GetIPAddress())()); okay = false; break; } } if (okay) { retVal = (server.ServerProcessLoop() == B_NO_ERROR) ? 0 : 10; if (retVal > 0) LogTime(MUSCLE_LOG_CRITICALERROR, "Server process aborted!\n"); else LogTime(MUSCLE_LOG_INFO, "Server process exiting.\n"); } else LogTime(MUSCLE_LOG_CRITICALERROR, "Error occurred during setup, aborting!\n"); server.Cleanup(); }