/* * 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; }
/* * 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; }