📄 pgpprsasc.c
字号:
return NULL;
while (*msg) {
if (name && (*msg)->name && !memcmp (name, (*msg)->name,
strlen (name))) {
/* Update the message size if we know it */
if (!(*msg)->size && size)
(*msg)->size = size;
return *msg;
}
if (!name && !(*msg)->name && size == (*msg)->size &&
size != 1)
return *msg;
msg = &((*msg)->next);
}
*msg = (Message *)pgpContextMemAlloc( cdkContext,
sizeof (**msg), kPGPMemoryMgrFlags_Clear);
if (! *msg)
return NULL;
(*msg)->cdkContext = cdkContext;
if (name) {
newname = (char *)pgpContextMemAlloc( cdkContext,
strlen (name) + 1, kPGPMemoryMgrFlags_Clear);
if (!newname) {
pgpContextMemFree( cdkContext, *msg);
*msg = NULL;
return NULL;
}
memcpy (newname, name, strlen (name) + 1);
} else
newname = NULL;
(*msg)->name = newname;
(*msg)->size = size;
(*msg)->msg_number = ++(ctx->msg_count);
return *msg;
}
/*
* We're done with this message so we can remove it from our queue
* of pending messages. Free any remaining message parts in the process.
* We can also turn buffering off now.
*/
static void
freeMessage (PrsAscContext *ctx, Message *msg)
{
Message **msgp = &ctx->msgs;
MsgPart *part, *temp;
PGPContextRef cdkContext = ctx->pipe.cdkContext;
while (*msgp) {
if (*msgp == msg) {
*msgp = msg->next;
part = msg->parts;
if (msg->tail)
/* Disconnect join module */
*(msg->tail) = NULL;
while (part) {
temp = part;
part = part->next;
freePart (temp);
}
if (msg->name)
pgpContextMemFree( cdkContext, msg->name);
ctx->buffering = 0;
pgpClearMemory( msg, sizeof (*msg));
pgpContextMemFree( cdkContext, msg);
return;
}
}
/* no match found */
return;
}
/*
* Buffer a command at the current spot in the data stream. This is only
* called when ctx->buffering is true. What it does is find the delta
* of this command in the data fifo from the last command in order to replay
* the commands at the proper place. It saves off context->written as
* the offset and then resets the value to 0.
*
* The return value is 0 on success or an error code.
*
* Command Byte Syntax: <offset><cmd><arglen><arg>
*/
static PGPError
bufferCommand (
PrsAscContext *ctx, PGPByte cmd, const PGPByte *arg, unsigned arglen)
{
/* Make sure the command argument fits the buffer size */
if (arglen > sizeof (ctx->cmdarg))
return kPGPError_BadParams;
if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&ctx->written,
sizeof (ctx->written)) != sizeof (ctx->written))
return kPGPError_OutOfMemory;
if (pgpFifoWrite (ctx->fifod, ctx->ann, &cmd, sizeof (cmd))
!= sizeof (cmd))
return kPGPError_OutOfMemory;
if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&arglen,
sizeof (arglen)) != sizeof (arglen))
return kPGPError_OutOfMemory;
if (pgpFifoWrite (ctx->fifod, ctx->ann, arg, arglen) != arglen)
return kPGPError_OutOfMemory;
ctx->written = 0;
return( kPGPError_NoErr );
}
/* Buffer up a write command for a particular message */
static PGPError
bufferWriteCommand (PrsAscContext *ctx, Message *msg)
{
PGPByte arg[sizeof (msg)];
memcpy (arg, (PGPByte const *)&msg, sizeof (arg));
return bufferCommand (ctx, CMD_WRITE, arg, sizeof (arg));
}
/* Process a buffered Write command for a particular message */
static PGPError
parseWriteCommand (PrsAscContext *ctx)
{
Message *msg;
pgpAssert (ctx->cmdlen == sizeof (msg));
memcpy ((PGPByte *)&msg, ctx->cmdarg, sizeof (msg));
return writeMessage (ctx, msg);
}
/* Buffer up an annotation */
static PGPError
bufferAnnotation (PrsAscContext *ctx, PGPPipeline *origin, int type,
PGPByte const *string, size_t size)
{
PGPByte *arg;
PGPByte *argp;
PGPError retval;
PGPContextRef cdkContext = ctx->pipe.cdkContext;
arg = argp = (PGPByte *)pgpContextMemAlloc( cdkContext,
sizeof (origin) + sizeof (type) + size + sizeof (size),
kPGPMemoryMgrFlags_Clear );
if (!arg)
return kPGPError_OutOfMemory;
memcpy (argp, (PGPByte const *)&origin, sizeof (origin));
argp += sizeof (origin);
memcpy (argp, (PGPByte const *)&type, sizeof (type));
argp += sizeof (type);
memcpy (argp, (PGPByte const *)&size, sizeof (size));
argp += sizeof (size);
memcpy (argp, string, size);
argp += size;
retval = bufferCommand (ctx, CMD_ANNOTATE, arg, argp-arg);
pgpContextMemFree( cdkContext, arg);
return retval;
}
static PGPError
parseAnnotation (PrsAscContext *ctx)
{
PGPPipeline *origin;
int type;
size_t size;
PGPByte *string, *argp = ctx->cmdarg;
PGPError retval;
PGPContextRef cdkContext = ctx->pipe.cdkContext;
pgpAssert (ctx->cmdlen >= sizeof (origin) + sizeof (type) +
sizeof (size));
memcpy ((PGPByte *)&origin, argp, sizeof (origin));
argp += sizeof (origin);
memcpy ((PGPByte *)&type, argp, sizeof (type));
argp += sizeof (type);
memcpy ((PGPByte *)&size, argp, sizeof (size));
argp += sizeof (size);
/* make sure we have the right number of bytes remaining */
pgpAssert ((ctx->cmdlen - size) == (unsigned)(argp - ctx->cmdarg));
string = (PGPByte *)pgpContextMemAlloc( cdkContext,
size, kPGPMemoryMgrFlags_Clear);
if (string == NULL)
return kPGPError_OutOfMemory;
pgpCopyMemory (argp, string, size);
retval = sendAnnotate (ctx, origin, type, string, size);
pgpContextMemFree( cdkContext, string);
return retval;
}
/*
* Given a buffered command, process it appropriately. The cmd, args,
* and arglen are currently held in the ctx. Set arglen to 0 and
* return 0 on success, otherwise return an error.
*/
static PGPError
processCommand (PrsAscContext *ctx)
{
PGPError error = kPGPError_NoErr;
switch (ctx->command) {
case CMD_WRITE:
error = parseWriteCommand (ctx);
break;
case CMD_ANNOTATE:
error = parseAnnotation (ctx);
break;
default:
/* unknown command type. This should NEVER happen */
pgpAssert (0);
}
if (!error)
ctx->cmdlen = 0;
return error;
}
/*
* Write a buffer of data which is a message part. This will either
* write or buffer depending on what the current state of the world
* is.
*
* This will either perform a write() or a pgpJoinBuffer() depending
* on what it is and what the state is. We perform a write if this is
* the writing message, otherwise we just buffer it.
*/
static size_t
writePartData (MsgPart *part, PGPByte const *buf, size_t size, PGPError *error)
{
Message *msg = part->msg;
/* Ignore parts that we've already finished */
if (part->done)
return size;
if (part->sig)
return part->sig->write (part->sig, buf, size, error);
if (msg->writing)
return part->mod->write (part->mod, buf, size, error);
return pgpJoinBuffer (part->mod, buf, size);
}
/*
* This will write 'extra' data out. In general this is just
* non-Ascii armor data. However if we are within a "buffering
* everything" mode, then this will get buffered into the ctx->data
* fifo and ctx->written will be increased.
*/
static size_t
writeExtraData (
PrsAscContext *ctx, PGPByte const *buf, size_t size, PGPError *error)
{
size_t written;
/* Handle clearsign text */
if (ctx->part && ctx->part->text)
return ctx->part->text->write (ctx->part->text, buf, size,
error);
pgpAssert (ctx->tail);
if (ctx->buffering) {
written = pgpFifoWrite (ctx->fifod, ctx->data, buf, size);
ctx->written += written;
return written;
}
return ctx->tail->write (ctx->tail, buf, size, error);
}
/*
* This will start with the first part that we have. For each part,
* it will see if it is done. If not, return 0. If it is done, then
* see if there is another part sitting after it. If so, close this
* part, return an error if one exists, or move on to the next part if
* there was no error closing the part. If there is not another part
* after this one, then only close this one if this is the last part
* (msg->size && part->num == msg->size). Otherwise return 0.
*
* If we flushed the whole message, free it.
*/
static PGPError
flushMessage (PrsAscContext *ctx, Message *msg)
{
MsgPart *temp, *part = msg->parts;
PGPError error = kPGPError_NoErr;
do {
if (!part->done)
break;
if (part->next) {
error = closePart (part);
if (error)
break;
temp = part->next;
freePart (part);
part = temp;
} else if (part->num == msg->size) {
pgpAssert (!part->next);
error = closePart (part);
if (error)
break;
error = ctx->tail->annotate (ctx->tail, ctx->myself,
PGPANN_ARMOR_END, NULL,
0);
if (error)
break;
freeMessage (ctx, msg);
/* freeMessage will free the last part */
break;
} else
break;
} while (part);
return error;
}
/*
* Set the state so that we are writing out this message. It means that
* we are probably going to be buffering everything else until this message
* is done. If we are already "buffering" everything, then buffer up this
* command for later execution.
*/
static PGPError
writeMessage (PrsAscContext *ctx, Message *msg)
{
PGPError error;
msg->foundpart1 = 1;
if (ctx->buffering)
return bufferWriteCommand (ctx, msg);
error = ctx->tail->annotate (ctx->tail,
ctx->myself, PGPANN_ARMOR_BEGIN,
(PGPByte *)&ctx->sectoff, sizeof(ctx->sectoff));
if (error)
return error;
ctx->buffering = 1;
msg->writing = 1;
/* Start flushing the message now */
return flushMessage (ctx, msg);
}
/*
* This is the main logic in flushing out the buffered data. This
* function will try to flush the data fifo and command fifo in order
* to create the appropriate output stream.
*
* There are two streams which need to be merged. Since the command
* stream gives deltas into the datastream, we need to use the command
* stream as the control. No problem.
*
* First, we flush out any data in the data stream until the next
* command, until ctx->left == 0. Next, if ctx->cmdlen != 0 we
* process the command in the ctx command buffer. If that returns
* without error we read in the next command/offset into ctx (->left
* and ->cmdlen) and then repeat. It at any time an error occurs,
* stop and return the error code.
*/
static PGPError
flushBuffers (PrsAscContext *ctx)
{
PGPSize datalen, cmdlen, len;
PGPByte const *ptr;
PGPError error = kPGPError_NoErr;
size_t written;
pgpAssert (! ctx->buffering);
datalen = pgpFifoSize (ctx->fifod, ctx->data);
cmdlen = pgpFifoSize (ctx->fifod, ctx->ann);
/* If nothing is buffered, just return ok */
if (!datalen && !cmdlen)
return( kPGPError_NoErr );
/* Now try to flush the buffers... */
do {
/*
* If buffering gets turned on processing a command,
* just exit this function so more data can be read in.
*/
if (ctx->buffering)
return( kPGPError_NoErr );
/* First flush any data until the next command */
while (ctx->left) {
ptr = pgpFifoPeek (ctx->fifod, ctx->data, &len);
pgpAssert (len);
pgpAssert (ptr);
if (len > ctx->left)
len = ctx->left;
written = writeExtraData (ctx, ptr, len, &error);
pgpFifoSeek (ctx->fifod, ctx->data, written);
ctx->left -= written;
datalen -= written;
if (error)
return error;
}
/* Process the buffered command, if any */
if (ctx->cmdlen) {
error = processCommand (ctx);
if (error)
return error;
}
/*
* Now, read in the data for the next command. The
* syntax is: <offset><cmd><arglen><arg>
*/
if (cmdlen) {
if (pgpFifoRead (ctx->fifod, ctx->ann,
(PGPByte *)&ctx->left,
sizeof (ctx->left)) !=
sizeof (ctx->left))
return kPGPError_FIFOReadError;
cmdlen -= sizeof (ctx->left);
if (pgpFifoRead (ctx->fifod, ctx->ann, &ctx->command,
sizeof (ctx->command)) !=
sizeof (ctx->command))
return kPGPError_FIFOReadError;
cmdlen -= sizeof (ctx->command);
if (pgpFifoRead (ctx->fifod, ctx->ann,
(PGPByte *)&ctx->cmdlen,
sizeof (ctx->cmdlen)) !=
sizeof (ctx->cmdlen))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -