Beispiel #1
0
/*
 * Write to the remote end of the channel
 */
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
                    DWORD addendLength, PUCHAR buffer, ULONG length,
                    ChannelCompletionRoutine *completionRoutine)
{
    PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
    ChannelCompletionRoutine *dupe = NULL;
    DWORD res = ERROR_SUCCESS;
    LPCSTR method = "core_channel_write";
    Packet *request;
    Tlv methodTlv;

    do
    {
        // Allocate a request packet
        if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
        {
            res = ERROR_NOT_ENOUGH_MEMORY;
            break;
        }

        // Add the supplied TLVs
        packet_add_tlvs(request, addend, addendLength);

        // If no method TLV as added, add the default one.
        if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
            packet_add_tlv_string(request, TLV_TYPE_METHOD, method);

        // Add the channel identifier and the length to write
        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));

        // if the channel data is ment to be compressed, compress it!
        if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length);
        else
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length);

        packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel));

        // Initialize the packet completion routine
        if (completionRoutine)
        {
            // Duplicate the completion routine
            dupe = channel_duplicate_completion_routine(completionRoutine);

            requestCompletion.context = dupe;
            requestCompletion.routine = _channel_packet_completion_routine;
            realRequestCompletion     = &requestCompletion;
        }

        // Transmit the packet with the supplied completion routine, if any.
        res = packet_transmit(remote, request, realRequestCompletion);

    } while (0);

    return res;
}
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
        DWORD addendLength, PUCHAR buffer, ULONG length, 
        ChannelCompletionRoutine *completionRoutine)
{
    PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
    ChannelCompletionRoutine *dupe = NULL;
    DWORD res = ERROR_SUCCESS;
    LPCSTR method = "core_channel_write";
    Packet *request;
    Tlv methodTlv;

    do
    {
        if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
        {
            res = ERROR_NOT_ENOUGH_MEMORY;
            break;
        }

        packet_add_tlvs(request, addend, addendLength);

        if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
            packet_add_tlv_string(request, TLV_TYPE_METHOD, method);

        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));

        if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length);
        else
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length);

        packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel));

        if (completionRoutine)
        {
            dupe = channel_duplicate_completion_routine(completionRoutine);

            requestCompletion.context = dupe;
            requestCompletion.routine = _channel_packet_completion_routine;
            realRequestCompletion     = &requestCompletion;
        }

        res = packet_transmit(remote, request, realRequestCompletion);

    } while (0);

    return res;
}
Beispiel #3
0
/*
 * Write the supplied buffer to the remote endpoint of the channel.
 *
 * This will cause the passed buffer to be written in channel->ops.buffered on the
 * remote endpoint.
 */
DWORD channel_write_to_remote(Remote *remote, Channel *channel, PUCHAR chunk,
                              ULONG chunkLength, PULONG bytesWritten)
{
    Packet *request = packet_create(PACKET_TLV_TYPE_REQUEST,
                                    "core_channel_write");
    DWORD res = ERROR_SUCCESS;
    Tlv entries[2];
    DWORD idNbo;

    do
    {
        // Did the allocation fail?
        if (!request)
        {
            res = ERROR_NOT_ENOUGH_MEMORY;
            break;
        }

        idNbo = htonl(channel_get_id(channel));

        entries[0].header.type   = TLV_TYPE_CHANNEL_ID;
        entries[0].header.length = sizeof(DWORD);
        entries[0].buffer        = (PUCHAR)&idNbo;

        // if the channel data is ment to be compressed, compress it!
        if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
            entries[1].header.type = TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED;
        else
            entries[1].header.type = TLV_TYPE_CHANNEL_DATA;

        entries[1].header.length = chunkLength;
        entries[1].buffer        = chunk;

        // Add the TLV data
        if ((res = packet_add_tlv_group(request, TLV_TYPE_CHANNEL_DATA_GROUP, entries, 2)) != ERROR_SUCCESS)
            break;

        // Transmit the packet
        res = packet_transmit(remote, request, NULL);

    } while (0);

    return res;
}
/*
 * core_channel_read
 * -----------------
 *
 * From from the local buffer and write back to the requester
 *
 * Takes TLVs:
 *
 * req: TLV_TYPE_CHANNEL_ID -- The channel identifier to read from
 * req: TLV_TYPE_LENGTH     -- The number of bytes to read
 */
DWORD remote_request_core_channel_read(Remote *remote, Packet *packet)
{
	DWORD res = ERROR_SUCCESS, bytesToRead, bytesRead, channelId;
	Packet *response = packet_create_response(packet);
	PUCHAR temporaryBuffer = NULL;
	Channel *channel = NULL;

	do
	{
		if (!response)
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Get the number of bytes to read
		bytesToRead = packet_get_tlv_value_uint(packet, TLV_TYPE_LENGTH);
		channelId   = packet_get_tlv_value_uint(packet, TLV_TYPE_CHANNEL_ID);

		// Try to locate the specified channel
		if (!(channel = channel_find_by_id(channelId)))
		{
			res = ERROR_NOT_FOUND;
			break;
		}

		lock_acquire( channel->lock );

		// Allocate temporary storage
		if (!(temporaryBuffer = (PUCHAR)malloc(bytesToRead)))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		switch (channel_get_class(channel))
		{
			// If it's buffered, read from the local buffer and either transmit 
			// the buffer in the response or write it back asynchronously
			// depending on the mode of the channel.
			case CHANNEL_CLASS_BUFFERED:
				// Read in from local
				res = channel_read_from_buffered(channel, temporaryBuffer, 
				    bytesToRead, (PULONG)&bytesRead);
				break;
			// Handle read I/O for the pool class
			case CHANNEL_CLASS_POOL:
				// If the channel has a read handler
				if (channel->ops.pool.read)
					res = channel->ops.pool.read(channel, packet, 
							channel->ops.pool.native.context, temporaryBuffer, 
							bytesToRead, &bytesRead);
				else
					res = ERROR_NOT_SUPPORTED;
				break;
			default:
				res = ERROR_NOT_SUPPORTED;
		}

		// If we've so far been successful and we have a temporary buffer...
		if ((res == ERROR_SUCCESS) &&(temporaryBuffer) && (bytesRead))
		{
			// If the channel should operate synchronously, add the data to theresponse
			if (channel_is_flag(channel, CHANNEL_FLAG_SYNCHRONOUS))
			{
				// if the channel data is ment to be compressed, compress it!
				if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
					packet_add_tlv_raw(response, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, temporaryBuffer, bytesRead);
				else
					packet_add_tlv_raw(response, TLV_TYPE_CHANNEL_DATA, temporaryBuffer, bytesRead);

				res = ERROR_SUCCESS;
			}
			// Otherwise, asynchronously write the buffer to the remote endpoint
			else
			{
				if ((res = channel_write(channel, remote, NULL, 0, temporaryBuffer, bytesRead, NULL)) != ERROR_SUCCESS)
					break;
			}
		}

	} while (0);
	
	if( channel )
		lock_release( channel->lock );

	if (temporaryBuffer)
		free(temporaryBuffer);

	// Transmit the acknowledgement
	if (response)
	{
		packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
		packet_add_tlv_uint(response, TLV_TYPE_LENGTH, bytesRead);
		packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channelId);

		res = packet_transmit(remote, response, NULL);
	}

	return res;
}