本文整理汇总了C++中parcBuffer_Allocate函数的典型用法代码示例。如果您正苦于以下问题:C++ parcBuffer_Allocate函数的具体用法?C++ parcBuffer_Allocate怎么用?C++ parcBuffer_Allocate使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了parcBuffer_Allocate函数的16个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的C++代码示例。
示例1: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, ccnxInterest_Equals)
{
CCNxName *nameA = ccnxName_CreateFromURI("lci:/name");
PARCBuffer *keyA = parcBuffer_Allocate(8);
parcBuffer_PutUint64(keyA, 1234L);
CCNxInterest *interestA = ccnxInterest_Create(nameA,
1000, /* lifetime */
keyA, /* KeyId */
NULL /* ContentObjectHash */
);
CCNxName *nameB = ccnxName_CreateFromURI("lci:/name");
PARCBuffer *keyB = parcBuffer_Allocate(8);
parcBuffer_PutUint64(keyB, 1234L);
CCNxInterest *interestB = ccnxInterest_Create(nameB,
1000, /* lifetime */
keyB, /* KeyId */
NULL /* ContentObjectHash */
);
assertTrue(ccnxInterest_Equals(interestA, interestB), "Expected equivalent interests to be equal.");
ccnxName_Release(&nameA);
ccnxName_Release(&nameB);
parcBuffer_Release(&keyA);
parcBuffer_Release(&keyB);
ccnxInterest_Release(&interestA);
ccnxInterest_Release(&interestB);
}
开发者ID:mword,项目名称:Libccnx-common,代码行数:30,代码来源:test_ccnx_Interest.c
示例2: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, parcSignature_Equals)
{
PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary bufer size -- not important
PARCBuffer *otherBits = parcBuffer_Allocate(strlen("hello"));
parcBuffer_PutArray(otherBits, strlen("hello"), (uint8_t *) "hello");
PARCSignature *x = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits);
PARCSignature *y = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits);
PARCSignature *z = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits);
PARCSignature *unequal1 = parcSignature_Create(PARCSigningAlgorithm_HMAC, PARC_HASH_SHA256, bits);
PARCSignature *unequal2 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_CRC32C, bits);
PARCSignature *unequal3 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, otherBits);
parcObjectTesting_AssertEqualsFunction(parcSignature_Equals, x, y, z, unequal1, unequal2, unequal3, NULL);
parcSignature_Release(&x);
parcSignature_Release(&y);
parcSignature_Release(&z);
parcSignature_Release(&unequal1);
parcSignature_Release(&unequal2);
parcSignature_Release(&unequal3);
parcBuffer_Release(&bits);
parcBuffer_Release(&otherBits);
}
开发者ID:isolis,项目名称:Libparc,代码行数:25,代码来源:test_parc_Signature.c
示例3: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, ccnxLink_Equals)
{
CCNxName *name = ccnxName_CreateFromCString("lci:/foo/bar/name");
PARCBuffer *keyId = parcBuffer_Allocate(10);
PARCBuffer *contentObjectHash = parcBuffer_Allocate(20);
CCNxLink *x = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&keyId);
parcBuffer_Release(&contentObjectHash);
name = ccnxName_CreateFromCString("lci:/foo/bar/name");
keyId = parcBuffer_Allocate(10);
contentObjectHash = parcBuffer_Allocate(20);
CCNxLink *y = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&keyId);
parcBuffer_Release(&contentObjectHash);
name = ccnxName_CreateFromCString("lci:/foo/bar/name");
keyId = parcBuffer_Allocate(10);
contentObjectHash = parcBuffer_Allocate(20);
CCNxLink *z = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&keyId);
parcBuffer_Release(&contentObjectHash);
name = ccnxName_CreateFromCString("lci:/foo/bar/othername");
keyId = parcBuffer_Allocate(10);
contentObjectHash = parcBuffer_Allocate(20);
CCNxLink *unequal1 = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&keyId);
parcBuffer_Release(&contentObjectHash);
name = ccnxName_CreateFromCString("lci:/foo/bar/name");
keyId = NULL;
contentObjectHash = parcBuffer_Allocate(20);
CCNxLink *unequal2 = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&contentObjectHash);
name = ccnxName_CreateFromCString("lci:/foo/bar/name");
keyId = parcBuffer_Allocate(10);
contentObjectHash = NULL;
CCNxLink *unequal3 = ccnxLink_Create(name, keyId, contentObjectHash);
ccnxName_Release(&name);
parcBuffer_Release(&keyId);
assertEqualsContract(ccnxLink_Equals, x, y, z, unequal1, unequal2, unequal3);
ccnxLink_Release(&x);
ccnxLink_Release(&y);
ccnxLink_Release(&z);
ccnxLink_Release(&unequal1);
ccnxLink_Release(&unequal2);
ccnxLink_Release(&unequal3);
}
开发者ID:rayyagar,项目名称:Libccnx-common,代码行数:57,代码来源:test_ccnx_Link.c
示例4: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Local, _athenaLRUContentStore_GetMatchByName)
{
AthenaLRUContentStore *impl = _createLRUContentStore();
PARCBuffer *payload = parcBuffer_Allocate(500);
CCNxName *name = ccnxName_CreateFromURI("lci:/boose/roo/pie");
CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(name, payload);
parcBuffer_Release(&payload);
bool status = _athenaLRUContentStore_PutContentObject(impl, contentObject);
assertTrue(status, "Expected to put content into the store");
PARCBuffer *payload2 = parcBuffer_Allocate(500);
CCNxName *name2 = ccnxName_CreateFromURI("lci:/roo/pie/boose");
CCNxContentObject *contentObject2 = ccnxContentObject_CreateWithDataPayload(name2, payload2);
parcBuffer_Release(&payload2);
bool status2 = _athenaLRUContentStore_PutContentObject(impl, contentObject2);
assertTrue(status2, "Expected to put content into the store");
// At this point, both objects should be in the store.
athenaLRUContentStore_Display(impl, 2);
assertTrue(impl->stats.numAdds == 2, "Expected 2 store adds");
// Now try to fetch each of them.
CCNxInterest *interest1 = ccnxInterest_CreateSimple(name);
CCNxContentObject *match = _athenaLRUContentStore_GetMatch(impl, interest1);
assertTrue(match == contentObject, "Expected to match the first content object");
CCNxInterest *interest2 = ccnxInterest_CreateSimple(name2);
CCNxContentObject *match2 = _athenaLRUContentStore_GetMatch(impl, interest2);
assertTrue(match2 == contentObject2, "Expected to match the second content object");
// Now try to match a non-existent name.
CCNxName *nameNoMatch = ccnxName_CreateFromURI("lci:/pie/roo/boose/this/should/not/match");
CCNxInterest *interest3 = ccnxInterest_CreateSimple(nameNoMatch);
CCNxContentObject *noMatch = _athenaLRUContentStore_GetMatch(impl, interest3);
assertNull(noMatch, "Expected a NULL response from an unmatchable name");
ccnxInterest_Release(&interest1);
ccnxInterest_Release(&interest2);
ccnxInterest_Release(&interest3);
ccnxName_Release(&nameNoMatch);
ccnxName_Release(&name);
ccnxName_Release(&name2);
ccnxContentObject_Release(&contentObject);
ccnxContentObject_Release(&contentObject2);
_athenaLRUContentStore_Release((AthenaContentStoreImplementation *) &impl);
}
开发者ID:chris-wood,项目名称:ghost,代码行数:53,代码来源:test_athena_LRUContentStore.c
示例5: ccnxInterestPayloadId_CreateAsSHA256Hash
CCNxInterestPayloadId *
ccnxInterestPayloadId_CreateAsSHA256Hash(const PARCBuffer *data)
{
CCNxInterestPayloadId *result = parcObject_CreateInstance(CCNxInterestPayloadId);
PARCCryptoHasher *hasher = parcCryptoHasher_Create(PARCCryptoHashType_SHA256);
parcCryptoHasher_Init(hasher);
parcCryptoHasher_UpdateBuffer(hasher, data);
PARCCryptoHash *hash = parcCryptoHasher_Finalize(hasher);
parcCryptoHasher_Release(&hasher);
PARCBuffer *hashData = parcCryptoHash_GetDigest(hash);
PARCBuffer *codedHash = parcBuffer_Allocate(parcBuffer_Capacity(hashData) + 1);
parcBuffer_PutUint8(codedHash, CCNxInterestPayloadId_TypeCode_RFC6920_SHA256);
parcBuffer_PutBuffer(codedHash, hashData);
parcBuffer_Flip(codedHash);
result->nameSegment =
ccnxNameSegment_CreateTypeValue(CCNxNameLabelType_PAYLOADID, codedHash);
parcBuffer_Release(&codedHash);
parcCryptoHash_Release(&hash);
return result;
}
开发者ID:PARC,项目名称:Libccnx-common,代码行数:25,代码来源:ccnx_InterestPayloadId.c
示例6: _darwinEthernet_SetInterfaceAddress
/**
* If the user specified a device name, set the MAC address in ether->macAddress
*
* <#Paragraphs Of Explanation#>
*
* @param [in] ether An allocated MetisGenericEther
* @param [in] devstr A C-String of the device name
*
* Example:
* @code
* <#example#>
* @endcode
*/
static void
_darwinEthernet_SetInterfaceAddress(MetisGenericEther *ether, const char *devstr)
{
if (devstr) {
struct ifaddrs *ifaddr;
int failure = getifaddrs(&ifaddr);
assertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno));
struct ifaddrs *next;
for (next = ifaddr; next != NULL; next = next->ifa_next) {
if (strcmp(next->ifa_name, devstr) == 0) {
if (next->ifa_addr->sa_family == AF_LINK) {
struct sockaddr_dl *addr_dl = (struct sockaddr_dl *) next->ifa_addr;
// addr_dl->sdl_data[12] contains the interface name followed by the MAC address, so
// need to offset in to the array past the interface name.
PARCBuffer *addr = parcBuffer_Allocate(addr_dl->sdl_alen);
parcBuffer_PutArray(addr, addr_dl->sdl_alen, (uint8_t *) &addr_dl->sdl_data[ addr_dl->sdl_nlen]);
parcBuffer_Flip(addr);
ether->macAddress = addr;
// break out of loop and freeifaddrs
break;
}
}
}
freeifaddrs(ifaddr);
}
}
开发者ID:isolis,项目名称:Metis,代码行数:42,代码来源:metis_GenericEther.c
示例7: _encodeControlPlaneInformation
static PARCBuffer *
_encodeControlPlaneInformation(const CCNxControl *cpiControlMessage)
{
PARCJSON *json = ccnxControl_GetJson(cpiControlMessage);
char *str = parcJSON_ToCompactString(json);
// include +1 because we need the NULL byte
size_t len = strlen(str) + 1;
size_t packetLength = sizeof(_MetisTlvFixedHeaderV0) + sizeof(MetisTlvType) + len;
PARCBuffer *packet = parcBuffer_Allocate(packetLength);
_MetisTlvFixedHeaderV0 hdr;
memset(&hdr, 0, sizeof(hdr));
hdr.version = 0;
hdr.packetType = METIS_PACKET_TYPE_CONTROL;
hdr.payloadLength = htons(len + sizeof(MetisTlvType));
parcBuffer_PutArray(packet, sizeof(hdr), (uint8_t *) &hdr);
MetisTlvType tlv = { .type = htons(T_CPI), .length = htons(len) };
parcBuffer_PutArray(packet, sizeof(tlv), (uint8_t *) &tlv);
parcBuffer_PutArray(packet, len, (uint8_t *) str);
parcMemory_Deallocate((void **) &str);
return parcBuffer_Flip(packet);
}
开发者ID:isolis,项目名称:Metis,代码行数:28,代码来源:metis_TlvSchemaV0.c
示例8: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Read)
{
char *fname = "tmpfile";
PARCFile *file = parcFile_Create(fname);
parcFile_CreateNewFile(file);
FILE *fp = fopen(fname, "w");
fseek(fp, 0, SEEK_SET);
uint8_t data[128];
for (int i = 0; i < 128; i++) {
data[i] = i;
}
fwrite(data, 1, 128, fp);
fclose(fp);
PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file);
parcFile_Release(&file);
PARCBuffer *buffer = parcBuffer_Allocate(128);
size_t numBytes = parcRandomAccessFile_Read(instance, buffer);
assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes);
parcBuffer_Flip(buffer);
uint8_t *bytes = parcBuffer_Overlay(buffer, parcBuffer_Remaining(buffer));
assertTrue(memcmp(data, bytes, 128) == 0, "Expected buffers to be equal");
parcBuffer_Release(&buffer);
parcRandomAccessFile_Close(instance);
parcRandomAccessFile_Release(&instance);
}
开发者ID:isolis,项目名称:Libparc,代码行数:32,代码来源:test_parc_RandomAccessFile.c
示例9: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, ccnxContentObject_GetPayloadType)
{
CCNxName *name = ccnxName_CreateFromCString("lci:/name");
PARCBuffer *payload = parcBuffer_Allocate(100);
CCNxPayloadType types[] = {
CCNxPayloadType_DATA,
CCNxPayloadType_KEY,
CCNxPayloadType_LINK,
CCNxPayloadType_MANIFEST,
};
for (int i = 0; i < sizeof(types) / sizeof(CCNxPayloadType); i++) {
CCNxPayloadType type = types[i];
CCNxContentObject *contentObject = ccnxContentObject_CreateWithDataPayload(name, NULL);
ccnxContentObject_SetPayload(contentObject, type, payload);
assertTrue(ccnxContentObject_GetPayloadType(contentObject) == type, "Unexpected PayloadType");
ccnxContentObject_Release(&contentObject);
}
parcBuffer_Release(&payload);
ccnxName_Release(&name);
}
开发者ID:GlennCScott,项目名称:Libccnx-common,代码行数:25,代码来源:test_ccnx_ContentObject.c
示例10: _createDerivedKey
static PARCBuffer *
_createDerivedKey(const char *key, size_t keylength, unsigned char *salt, unsigned int saltlen)
{
unsigned char buffer[SHA256_DIGEST_LENGTH];
HMAC(EVP_sha256(), key, (int) keylength, salt, saltlen, buffer, NULL);
return parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, buffer);
}
开发者ID:isolis,项目名称:Libparc,代码行数:7,代码来源:parc_SymmetricSignerFileStore.c
示例11: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_Buffer)
{
PARCBuffer *buffer = parcBuffer_Allocate(1024);
for (size_t i = 0; i < 32; i++) {
for (size_t j = 0; j < 32; j++) {
parcBuffer_PutUint8(buffer, i);
}
}
parcBuffer_Flip(buffer);
PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes
assertNotNull(chunker, "Expected non-NULL Chunker");
PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker);
size_t count = 0;
while (parcIterator_HasNext(itr)) {
PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr);
uint8_t *contents = parcBuffer_Overlay(payload, 0);
for (size_t i = 0; i < 32; i++) {
assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", (31 - count), i, contents[i]);
}
count++;
parcBuffer_Release(&payload);
}
assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count);
parcIterator_Release(&itr);
parcBufferChunker_Release(&chunker);
parcBuffer_Release(&buffer);
}
开发者ID:rayyagar,项目名称:Libparc,代码行数:33,代码来源:test_parc_BufferChunker.c
示例12: _SignDigest
static PARCSignature *
_SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign)
{
parcSecurity_AssertIsInitialized();
assertNotNull(signer, "Parameter must be non-null CCNxFileKeystore");
assertNotNull(digestToSign, "Buffer to sign must not be null");
// TODO: what is the best way to expose this?
PARCKeyStore *keyStore = signer->keyStore;
PARCBuffer *privateKeyBuffer = parcKeyStore_GetDEREncodedPrivateKey(keyStore);
EVP_PKEY *privateKey = NULL;
size_t keySize = parcBuffer_Remaining(privateKeyBuffer);
uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize);
privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize);
parcBuffer_Release(&privateKeyBuffer);
RSA *rsa = EVP_PKEY_get1_RSA(privateKey);
int opensslDigestType;
switch (parcCryptoHash_GetDigestType(digestToSign)) {
case PARCCryptoHashType_SHA256:
opensslDigestType = NID_sha256;
break;
case PARCCryptoHashType_SHA512:
opensslDigestType = NID_sha512;
break;
default:
trapUnexpectedState("Unknown digest type: %s",
parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(digestToSign)));
}
uint8_t *sig = parcMemory_Allocate(RSA_size(rsa));
assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa));
unsigned sigLength = 0;
PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign);
int result = RSA_sign(opensslDigestType,
(unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)),
(int) parcBuffer_Remaining(bb_digest),
sig,
&sigLength,
rsa);
assertTrue(result == 1, "Got error from RSA_sign: %d", result);
RSA_free(rsa);
PARCBuffer *bbSign = parcBuffer_Allocate(sigLength);
parcBuffer_Flip(parcBuffer_PutArray(bbSign, sigLength, sig));
parcMemory_Deallocate((void **) &sig);
PARCSignature *signature =
parcSignature_Create(_GetSigningAlgorithm(signer),
parcCryptoHash_GetDigestType(digestToSign),
bbSign
);
parcBuffer_Release(&bbSign);
return signature;
}
开发者ID:PARC,项目名称:Libparc,代码行数:59,代码来源:parc_PublicKeySigner.c
示例13: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Specialization, parcSecureRandom_CreateWithSeed)
{
PARCBuffer *seed = parcBuffer_Allocate(1024);
PARCSecureRandom *rng = parcSecureRandom_CreateWithSeed(seed);
assertTrue(parcSecureRandom_IsValid(rng), "Expected parcSecureRandom_CreateWithSeed to result in a valid instance.");
parcSecureRandom_Release(&rng);
parcBuffer_Release(&seed);
}
开发者ID:PARC,项目名称:Libparc,代码行数:10,代码来源:test_parc_SecureRandom.c
示例14: parcSymmetricSignerFileStore_CreateKey
/**
* Create a symmetric (secret) key of the given bit length (e.g. 256)
*
* Example:
* @code
* <#example#>
* @endcode
*/
PARCBuffer *
parcSymmetricSignerFileStore_CreateKey(unsigned bits)
{
assertTrue((bits & 0x07) == 0, "bits must be a multiple of 8");
unsigned keylength = bits / 8;
uint8_t buffer[keylength];
RAND_bytes(buffer, keylength);
return parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(keylength), keylength, buffer));
}
开发者ID:isolis,项目名称:Libparc,代码行数:18,代码来源:parc_SymmetricSignerFileStore.c
示例15: LONGBOW_TEST_CASE
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_FromInterestPacketType)
{
PARCBuffer *buffer = parcBuffer_Allocate(10);
CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromInterestPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer);
assertTrue(ccnxTlvDictionary_IsInterest((CCNxTlvDictionary *) message), "Wrong message type");
ccnxWireFormatMessage_Release(&message);
parcBuffer_Release(&buffer);
}
开发者ID:PARC,项目名称:Libccnx-common,代码行数:10,代码来源:test_ccnx_WireFormatMessage.c
示例16: _GetPublickKeyDigest
static PARCCryptoHash *
_GetPublickKeyDigest(PARCPkcs12KeyStore *keystore)
{
parcSecurity_AssertIsInitialized();
assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore");
if (keystore->public_key_digest == NULL) {
AUTHORITY_KEYID *akid = X509_get_ext_d2i(keystore->x509_cert, NID_authority_key_identifier, NULL, NULL);
if (akid != NULL) {
ASN1_OCTET_STRING *skid = X509_get_ext_d2i(keystore->x509_cert, NID_subject_key_identifier, NULL, NULL);
if (skid != NULL) {
keystore->public_key_digest =
parcBuffer_PutArray(parcBuffer_Allocate(skid->length), skid->length, skid->data);
parcBuffer_Flip(keystore->public_key_digest);
ASN1_OCTET_STRING_free(skid);
}
AUTHORITY_KEYID_free(akid);
}
}
// If we could not load the digest from the certificate, then calculate it from the public key.
if (keystore->public_key_digest == NULL) {
uint8_t digestBuffer[SHA256_DIGEST_LENGTH];
int result = ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY),
EVP_sha256(),
X509_get_X509_PUBKEY(keystore->x509_cert),
digestBuffer,
NULL);
if (result != 1) {
assertTrue(0, "Could not compute digest over certificate public key");
} else {
keystore->public_key_digest =
parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer);
parcBuffer_Flip(keystore->public_key_digest);
}
}
// This stores a reference, so keystore->public_key_digest will remain valid
// even if the cryptoHasher is destroyed
return parcCryptoHash_Create(PARC_HASH_SHA256, keystore->public_key_digest);
}
开发者ID:rayyagar,项目名称:Libparc,代码行数:43,代码来源:parc_Pkcs12KeyStore.c
注:本文中的parcBuffer_Allocate函数示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论