All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.filesys.oncrpc.TcpRpcPacketHandler Maven / Gradle / Ivy

Go to download

Java file server with SMB, FTP/FTPS and NFS support, virtual filesystems, database filesystems

There is a newer version: 1.4.0
Show newest version
/*
 * Copyright (C) 2006-2010 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see .
 */

package org.filesys.oncrpc;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketException;

import org.filesys.debug.Debug;
import org.filesys.server.SocketPacketHandler;
import org.filesys.server.core.NoPooledMemoryException;
import org.filesys.util.DataPacker;

/**
 * TCP RPC Packet Handler Class
 *
 * 

Processes RPC requests received via TCP session. * * @author gkspencer */ public class TcpRpcPacketHandler extends SocketPacketHandler implements Runnable { // Session handler that owns this session private TcpRpcSessionHandler m_handler; // RPC server implementation used to process the requests private RpcProcessor m_rpcProcessor; // Session id private int m_sessId; // RPC processing thread shutdown flag private boolean m_shutdown; // Maximum RPC size accepted private int m_maxRpcSize; // Packet buffer for receiving incoming RPC requests private RpcPacket m_rxPkt; // Fragment header buffer private byte[] m_fragBuf; /** * Class constructor to create a TCP RPC handler for a server. * * @param handler TcpRpcSessionHandler * @param sessId int * @param server RpcProcessor * @param socket Socket * @param maxRpcSize int * @exception IOException Socket error */ public TcpRpcPacketHandler(TcpRpcSessionHandler handler, int sessId, RpcProcessor server, Socket socket, int maxRpcSize) throws IOException { super(socket); // Set the session handler that owns this session m_handler = handler; // set the session id m_sessId = sessId; // Set the RPC server to be used to process requests m_rpcProcessor = server; // Set the maximum RPC size accepted m_maxRpcSize = maxRpcSize; // Allocate the RPC fragment header buffer m_fragBuf = new byte[4]; // Create a thread to run the RPC processing for this session Thread th = new Thread(this); th.setName(handler.getProtocolName() + "_" + getSessionId()); th.start(); } /** * Class constructor to create a TCP RPC handler for a client. * * @param socket Socket * @param maxRpcSize int * @exception IOException Socket error */ public TcpRpcPacketHandler(Socket socket, int maxRpcSize) throws IOException { super(socket); // Allocate the RPC fragment header buffer m_maxRpcSize = maxRpcSize; m_fragBuf = new byte[4]; } /** * Return the protocol name * * @return String */ public String getProtocolName() { return "TCP RPC"; } /** * Return the session id * * @return int */ public final int getSessionId() { return m_sessId; } /** * Return the maximum RPC size accepted * * @return int */ public final int getMaximumRpcSize() { return m_maxRpcSize; } /** * Return the associated session handler * * @return TcpRpcSessionHandler */ protected final TcpRpcSessionHandler getHandler() { return m_handler; } /** * Return the associated RPC processor * * @return RpcProcessor */ protected final RpcProcessor getRpcProcessor() { return m_rpcProcessor; } /** * Thread to read and process the RPC requests for this session */ public void run() { // Loop until shutdown int rxLen = 0; RpcPacket rpcPkt = null; while (m_shutdown == false) { try { // allocate an RPC packet to receive an incoming request rpcPkt = allocateRpcPacket(getMaximumRpcSize()); // Read an RPC request rxLen = receiveRpc(rpcPkt); if (rxLen == -1) { // Release the packet deallocateRpcPacket(rpcPkt); // Receive error, client has closed the socket m_handler.closeSession(getSessionId()); break; } } catch (SocketException ex) { // Release the packet if (rpcPkt != null) deallocateRpcPacket(rpcPkt); // Socket error, close the session m_handler.closeSession(getSessionId()); break; } catch (IOException ex) { // Only dump errors if not shutting down if (m_shutdown == false) Debug.println(ex); } // Process the RPC request try { // Validate the RPC header if (rpcPkt.getRpcVersion() != Rpc.RpcVersion) { // Build/send an error response rpcPkt.buildRpcMismatchResponse(); sendRpc(rpcPkt); } else { // Process the RPC request processRpc(rpcPkt); } } catch (IOException ex) { // Only dump errors if not shutting down if (m_shutdown == false) Debug.println(ex); } } } /** * Close the session */ public void closePacketHandler() { // Request the RPC processing thread to shutdown m_shutdown = true; // Close the input/output streams and socket super.closePacketHandler(); } /** * Send an RPC request/response packet * * @param rpc RpcPacket * @exception IOException Socket error */ protected final void sendRpc(RpcPacket rpc) throws IOException { // Write the RPC response, this includes the fragment header // // If the fragment header is written seperately to the main RPC response packet trace tools // such as Ethereal will not display the details properly. writePacket(rpc.getBuffer(), 0, rpc.getTxLength()); } /** * Read an RPC request/response * * @param rpc RpcPacket * @return int * @exception IOException Socket error */ protected final int receiveRpc(RpcPacket rpc) throws IOException { // Use the main receive method int rxLen = receiveRpc(rpc.getBuffer(), RpcPacket.FragHeaderLen, rpc.getBuffer().length - RpcPacket.FragHeaderLen); if (rxLen > 0) { // Set the received length rpc.setBuffer(RpcPacket.FragHeaderLen, rxLen + RpcPacket.FragHeaderLen); // Set the client details rpc.setClientDetails(getSocket().getInetAddress(), getSocket().getPort(), Rpc.ProtocolId.TCP); } // Return the received data length return rxLen; } /** * Read an RPC request/response * * @param buffer byte[] * @param offset int * @param maxLen int * @return int * @exception IOException Socket error */ protected final int receiveRpc(byte[] buffer, int offset, int maxLen) throws IOException { // Fill the buffer until the last fragment is received int rxLen = 0; int totLen = 0; int rxOffset = offset; int fragLen = 0; boolean lastFrag = false; while (lastFrag == false) { // Read in a header to get the fragment length rxLen = readPacket(m_fragBuf, 0, 4); if (rxLen == -1) return rxLen; // Check if we received the last fragment fragLen = DataPacker.getInt(m_fragBuf, 0); if ((fragLen & Rpc.LastFragment) != 0) { lastFrag = true; fragLen = fragLen & Rpc.LengthMask; } // Check if the buffer is large enough to receive the request if (fragLen > (buffer.length - rxOffset)) throw new IOException("Receive RPC buffer overflow, fragment len = " + fragLen); // Read the data part of the packet into the users buffer, this may take // several reads while (fragLen > 0) { // Read the data rxLen = readPacket(buffer, offset, fragLen); // Check if the connection has been closed if (rxLen == -1) return -1; // Update the received length and remaining data length totLen += rxLen; fragLen -= rxLen; // Update the user buffer offset as more reads will be required // to complete the data read offset += rxLen; } // end while reading data } // end while fragments // Return the total length read return totLen; } /** * Allocate an RPC packet for receiving an incoming request. This method must be overridden for * multi-threaded implementations. * * @param maxSize int * @return RpcPacket * @exception NoPooledMemoryException No pooled memory available */ protected RpcPacket allocateRpcPacket(int maxSize) throws NoPooledMemoryException { // Check if the receive packet has been allocated if (m_rxPkt == null) m_rxPkt = new RpcPacket(maxSize); // Return the RPC receive packet return m_rxPkt; } /** * Deallocate an RPC packet, default method does nothing but a pooled implementation may * return the packet to the pool. * * @param pkt RpcPacket */ protected void deallocateRpcPacket(RpcPacket pkt) { } /** * Process an RPC request. This method must be overridden for multi-threaded implementations. * * @param rpc RpcPacket * @exception IOException Socket error */ protected void processRpc(RpcPacket rpc) throws IOException { // Process the RPC request in the current thread RpcPacket response = m_rpcProcessor.processRpc(rpc); // Send the RPC response if (response != null) sendRpc(response); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy