Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.j2ssh.connection » [javadoc | source]
    1   /*
    2    *  SSHTools - Java SSH2 API
    3    *
    4    *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
    5    *
    6    *  Contributions made by:
    7    *
    8    *  Brett Smith
    9    *  Richard Pernavas
   10    *  Erwin Bolwidt
   11    *
   12    *  This program is free software; you can redistribute it and/or
   13    *  modify it under the terms of the GNU General Public License
   14    *  as published by the Free Software Foundation; either version 2
   15    *  of the License, or (at your option) any later version.
   16    *
   17    *  This program is distributed in the hope that it will be useful,
   18    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   19    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20    *  GNU General Public License for more details.
   21    *
   22    *  You should have received a copy of the GNU General Public License
   23    *  along with this program; if not, write to the Free Software
   24    *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   25    */
   26   package com.sshtools.j2ssh.connection;
   27   
   28   import com.sshtools.j2ssh.SshException;
   29   import com.sshtools.j2ssh.transport.AsyncService;
   30   import com.sshtools.j2ssh.transport.MessageStoreEOFException;
   31   import com.sshtools.j2ssh.transport.ServiceState;
   32   import com.sshtools.j2ssh.transport.SshMessage;
   33   import com.sshtools.j2ssh.transport.TransportProtocolState;
   34   
   35   import org.apache.commons.logging.Log;
   36   import org.apache.commons.logging.LogFactory;
   37   
   38   import java.io.IOException;
   39   
   40   import java.util.HashMap;
   41   import java.util.concurrent.ConcurrentHashMap;
   42   import java.util.HashSet;
   43   import java.util.Iterator;
   44   import java.util.Map;
   45   
   46   
   47   /**
   48    *
   49    *
   50    * @author $author$
   51    * @version $Revision: 1.68 $
   52    */
   53   public class ConnectionProtocol extends AsyncService {
   54       private static Log log = LogFactory.getLog(ConnectionProtocol.class);
   55       private HashSet reusableChannels = new HashSet();
   56       private Map activeChannels = new ConcurrentHashMap();
   57       private Map allowedChannels = new HashMap();
   58       private Map globalRequests = new HashMap();
   59       private long nextChannelId = 0;
   60   
   61       /**
   62        * Creates a new ConnectionProtocol object.
   63        */
   64       public ConnectionProtocol() {
   65           super("ssh-connection");
   66       }
   67   
   68       /**
   69        *
   70        *
   71        * @param channelName
   72        * @param cf
   73        *
   74        * @throws IOException
   75        */
   76       public void addChannelFactory(String channelName, ChannelFactory cf)
   77           throws IOException {
   78           allowedChannels.put(channelName, cf);
   79       }
   80   
   81       /**
   82        *
   83        *
   84        * @param channelName
   85        */
   86       public void removeChannelFactory(String channelName) {
   87           allowedChannels.remove(channelName);
   88       }
   89   
   90       /**
   91        *
   92        *
   93        * @param channelName
   94        *
   95        * @return
   96        */
   97       public boolean containsChannelFactory(String channelName) {
   98           return allowedChannels.containsKey(channelName);
   99       }
  100   
  101       /**
  102        *
  103        *
  104        * @param requestName
  105        * @param handler
  106        */
  107       public void allowGlobalRequest(String requestName,
  108           GlobalRequestHandler handler) {
  109           globalRequests.put(requestName, handler);
  110       }
  111   
  112       /**
  113        *
  114        *
  115        * @param channel
  116        *
  117        * @return
  118        *
  119        * @throws IOException
  120        */
  121       public synchronized boolean openChannel(Channel channel)
  122           throws IOException {
  123           return openChannel(channel, null);
  124       }
  125   
  126       /**
  127        *
  128        *
  129        * @return
  130        */
  131       public boolean isConnected() {
  132           return ((transport.getState().getValue() == TransportProtocolState.CONNECTED) ||
  133           (transport.getState().getValue() == TransportProtocolState.PERFORMING_KEYEXCHANGE)) &&
  134           (getState().getValue() == ServiceState.SERVICE_STARTED);
  135       }
  136   
  137       private Long getChannelId() {
  138          // synchronized (activeChannels) { 
  139               if (reusableChannels.size() <= 0) {
  140                   return new Long(nextChannelId++);
  141               } else {
  142                   return (Long) reusableChannels.iterator().next();
  143               }
  144           //}
  145       }
  146   
  147       /**
  148        *
  149        *
  150        * @param channel
  151        * @param eventListener
  152        *
  153        * @return
  154        *
  155        * @throws IOException
  156        * @throws SshException
  157        */
  158       public synchronized boolean openChannel(Channel channel,
  159           ChannelEventListener eventListener) throws IOException {
  160           //synchronized (activeChannels) {
  161               Long channelId = getChannelId();
  162   
  163               // Create the message
  164               SshMsgChannelOpen msg = new SshMsgChannelOpen(channel.getChannelType(),
  165                       channelId.longValue(),
  166                       channel.getLocalWindow().getWindowSpace(),
  167                       channel.getLocalPacketSize(), channel.getChannelOpenData());
  168   
  169               // Send the message
  170               transport.sendMessage(msg, this);
  171   
  172               // Wait for the next message to confirm the open channel (or not)
  173               int[] messageIdFilter = new int[2];
  174               messageIdFilter[0] = SshMsgChannelOpenConfirmation.SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
  175               messageIdFilter[1] = SshMsgChannelOpenFailure.SSH_MSG_CHANNEL_OPEN_FAILURE;
  176   
  177               try {
  178                   SshMessage result = messageStore.getMessage(messageIdFilter);
  179   
  180                   if (result.getMessageId() == SshMsgChannelOpenConfirmation.SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
  181                       SshMsgChannelOpenConfirmation conf = (SshMsgChannelOpenConfirmation) result;
  182                       activeChannels.put(channelId, channel);
  183                       log.debug("Initiating channel");
  184                       channel.init(this, channelId.longValue(),
  185                           conf.getSenderChannel(), conf.getInitialWindowSize(),
  186                           conf.getMaximumPacketSize(), eventListener);
  187                       channel.open();
  188                       log.info("Channel " +
  189                           String.valueOf(channel.getLocalChannelId()) +
  190                           " is open [" + channel.getName() + "]");
  191   
  192                       return true;
  193                   } else {
  194                       // Make sure the channels state is closed
  195                       channel.getState().setValue(ChannelState.CHANNEL_CLOSED);
  196   
  197                       return false;
  198                   }
  199               } catch (MessageStoreEOFException mse) {
  200                   throw new IOException(mse.getMessage());
  201               } catch (InterruptedException ex) {
  202                   throw new SshException(
  203                       "The thread was interrupted whilst waiting for a connection protocol message");
  204               }
  205           //}
  206       }
  207   
  208       /**
  209        *
  210        */
  211       protected synchronized void onStop() {
  212           log.info("Closing all active channels");
  213   	//	synchronized (activeChannels) {
  214   		log.info("thread has "+activeChannels.values().size()+" active channels to stop");
  215           try {
  216               Channel channel;
  217   
  218               for (Iterator x = activeChannels.values().iterator(); x.hasNext();) {
  219                   channel = (Channel) x.next();
  220   
  221                   if (channel != null) {
  222                       if (log.isDebugEnabled()) {
  223                           log.debug("Closing " + channel.getName() + " id=" +
  224                               String.valueOf(channel.getLocalChannelId()));
  225                       }
  226   
  227                       channel.close();
  228                   }
  229               }
  230           } catch (Throwable t) {
  231   			log.error("Unable to close all channels: "+t.getMessage(),t);
  232           }
  233   
  234           activeChannels.clear();
  235   	//	}
  236       }
  237   
  238       /**
  239        *
  240        *
  241        * @param channel
  242        * @param data
  243        *
  244        * @throws IOException
  245        */
  246       public synchronized void sendChannelData(Channel channel, byte[] data)
  247           throws IOException {
  248           synchronized (channel.getState()) {
  249               if (log.isDebugEnabled()) {
  250                   log.debug("Sending " + String.valueOf(data.length) +
  251                       " bytes for channel id " +
  252                       String.valueOf(channel.getLocalChannelId()));
  253               }
  254   
  255               int sent = 0;
  256               int block;
  257               int remaining;
  258               long max;
  259               byte[] buffer;
  260               ChannelDataWindow window = channel.getRemoteWindow();
  261   
  262               while (sent < data.length) {
  263                   remaining = data.length - sent;
  264                   max = ((window.getWindowSpace() < channel.getRemotePacketSize()) &&
  265                       (window.getWindowSpace() > 0)) ? window.getWindowSpace()
  266                                                      : channel.getRemotePacketSize();
  267                   block = (max < remaining) ? (int) max : remaining;
  268                   channel.remoteWindow.consumeWindowSpace(block);
  269                   buffer = new byte[block];
  270                   System.arraycopy(data, sent, buffer, 0, block);
  271   
  272                   SshMsgChannelData msg = new SshMsgChannelData(channel.getRemoteChannelId(),
  273                           buffer);
  274                   transport.sendMessage(msg, this);
  275   
  276                   /*                if (type != null) {
  277                        channel.sendChannelExtData(type.intValue(), buffer);
  278                                   } else {
  279                                       channel.sendChannelData(buffer);
  280                                   }*/
  281                   sent += block;
  282               }
  283           }
  284       }
  285   
  286       /**
  287        *
  288        *
  289        * @param channel
  290        *
  291        * @throws IOException
  292        */
  293       public void sendChannelEOF(Channel channel) throws IOException {
  294           //synchronized (activeChannels) {
  295               if (!activeChannels.containsValue(channel)) {
  296                   throw new IOException(
  297                       "Attempt to send EOF for a non existent channel " +
  298                       String.valueOf(channel.getLocalChannelId()));
  299               }
  300   
  301               log.info("Local computer has set channel " +
  302                   String.valueOf(channel.getLocalChannelId()) + " to EOF [" +
  303                   channel.getName() + "]");
  304   
  305               SshMsgChannelEOF msg = new SshMsgChannelEOF(channel.getRemoteChannelId());
  306               transport.sendMessage(msg, this);
  307          // }
  308       }
  309   
  310       /**
  311        *
  312        *
  313        * @param channel
  314        * @param extendedType
  315        * @param data
  316        *
  317        * @throws IOException
  318        */
  319       public synchronized void sendChannelExtData(Channel channel,
  320           int extendedType, byte[] data) throws IOException {
  321           channel.getRemoteWindow().consumeWindowSpace(data.length);
  322   
  323           int sent = 0;
  324           int block;
  325           int remaining;
  326           long max;
  327           byte[] buffer;
  328           ChannelDataWindow window = channel.getRemoteWindow();
  329   
  330           while (sent < data.length) {
  331               remaining = data.length - sent;
  332               max = ((window.getWindowSpace() < channel.getRemotePacketSize()) &&
  333                   (window.getWindowSpace() > 0)) ? window.getWindowSpace()
  334                                                  : channel.getRemotePacketSize();
  335               block = (max < remaining) ? (int) max : remaining;
  336               channel.remoteWindow.consumeWindowSpace(block);
  337               buffer = new byte[block];
  338               System.arraycopy(data, sent, buffer, 0, block);
  339   
  340               SshMsgChannelExtendedData msg = new SshMsgChannelExtendedData(channel.getRemoteChannelId(),
  341                       extendedType, buffer);
  342               transport.sendMessage(msg, this);
  343   
  344               /*                if (type != null) {
  345                               channel.sendChannelExtData(type.intValue(), buffer);
  346                           } else {
  347                               channel.sendChannelData(buffer);
  348                           }*/
  349               sent += block;
  350           }
  351       }
  352   
  353       /**
  354        *
  355        *
  356        * @param channel
  357        * @param requestType
  358        * @param wantReply
  359        * @param requestData
  360        *
  361        * @return
  362        *
  363        * @throws IOException
  364        * @throws SshException
  365        */
  366       public synchronized boolean sendChannelRequest(Channel channel,
  367           String requestType, boolean wantReply, byte[] requestData)
  368           throws IOException {
  369           boolean success = true;
  370           log.info("Sending " + requestType + " request for the " +
  371               channel.getChannelType() + " channel");
  372   
  373           SshMsgChannelRequest msg = new SshMsgChannelRequest(channel.getRemoteChannelId(),
  374                   requestType, wantReply, requestData);
  375           transport.sendMessage(msg, this);
  376   
  377           // If the user requests a reply then wait for the message and return result
  378           if (wantReply) {
  379               // Set up our message filter
  380               int[] messageIdFilter = new int[2];
  381               
  382               messageIdFilter[0] = SshMsgChannelSuccess.SSH_MSG_CHANNEL_SUCCESS;
  383               messageIdFilter[1] = SshMsgChannelFailure.SSH_MSG_CHANNEL_FAILURE;
  384               
  385               log.info("Waiting for channel request reply");
  386   
  387               try {
  388                 // Wait for either success or failure
  389                 SshMessage reply = messageStore.getMessage(messageIdFilter);
  390                 
  391                 switch (reply.getMessageId()) {
  392                 case SshMsgChannelSuccess.SSH_MSG_CHANNEL_SUCCESS: {
  393                   log.info("Channel request succeeded");
  394                   success = true;
  395                   
  396                   break;
  397                 }
  398                 
  399                 case SshMsgChannelFailure.SSH_MSG_CHANNEL_FAILURE: {
  400                   log.info("Channel request failed");
  401                   success = false;
  402                   
  403                   break;
  404                 }
  405                 } 
  406               } catch (InterruptedException ex) {
  407                   throw new SshException(
  408                       "The thread was interrupted whilst waiting for a connection protocol message");
  409               }
  410           }
  411   
  412           return success;
  413       }
  414   
  415       /**
  416        *
  417        *
  418        * @param channel
  419        *
  420        * @throws IOException
  421        */
  422       public void sendChannelRequestFailure(Channel channel)
  423           throws IOException {
  424           SshMsgChannelFailure msg = new SshMsgChannelFailure(channel.getRemoteChannelId());
  425           transport.sendMessage(msg, this);
  426       }
  427   
  428       /**
  429        *
  430        *
  431        * @param channel
  432        *
  433        * @throws IOException
  434        */
  435       public void sendChannelRequestSuccess(Channel channel)
  436           throws IOException {
  437           SshMsgChannelSuccess msg = new SshMsgChannelSuccess(channel.getRemoteChannelId());
  438           transport.sendMessage(msg, this);
  439       }
  440   
  441       /**
  442        *
  443        *
  444        * @param channel
  445        * @param bytesToAdd
  446        *
  447        * @throws IOException
  448        */
  449       public void sendChannelWindowAdjust(Channel channel, long bytesToAdd)
  450           throws IOException {
  451           log.debug("Increasing window size by " + String.valueOf(bytesToAdd) +
  452               " bytes");
  453   
  454           SshMsgChannelWindowAdjust msg = new SshMsgChannelWindowAdjust(channel.getRemoteChannelId(),
  455                   bytesToAdd);
  456           transport.sendMessage(msg, this);
  457       }
  458   
  459       /**
  460        *
  461        *
  462        * @param requestName
  463        * @param wantReply
  464        * @param requestData
  465        *
  466        * @return
  467        *
  468        * @throws IOException
  469        * @throws SshException
  470        */
  471       public synchronized byte[] sendGlobalRequest(String requestName,
  472           boolean wantReply, byte[] requestData) throws IOException {
  473           boolean success = true;
  474           SshMsgGlobalRequest msg = new SshMsgGlobalRequest(requestName, true,
  475                   requestData);
  476           transport.sendMessage(msg, this);
  477   
  478           if (wantReply) {
  479               // Set up our message filter
  480               int[] messageIdFilter = new int[2];
  481               messageIdFilter[0] = SshMsgRequestSuccess.SSH_MSG_REQUEST_SUCCESS;
  482               messageIdFilter[1] = SshMsgRequestFailure.SSH_MSG_REQUEST_FAILURE;
  483               log.debug("Waiting for global request reply");
  484   
  485               try {
  486                   // Wait for either success or failure
  487                   SshMessage reply = messageStore.getMessage(messageIdFilter);
  488   
  489                   switch (reply.getMessageId()) {
  490                   case SshMsgRequestSuccess.SSH_MSG_REQUEST_SUCCESS: {
  491                       log.debug("Global request succeeded");
  492   
  493                       return ((SshMsgRequestSuccess) reply).getRequestData();
  494                   }
  495   
  496                   case SshMsgRequestFailure.SSH_MSG_REQUEST_FAILURE: {
  497                       log.debug("Global request failed");
  498                       throw new SshException("The request failed");
  499                   }
  500                   }
  501               } catch (InterruptedException ex) {
  502                   throw new SshException(
  503                       "The thread was interrupted whilst waiting for a connection protocol message");
  504               }
  505           }
  506   
  507           return null;
  508       }
  509   
  510       /**
  511        *
  512        *
  513        * @return
  514        */
  515       protected int[] getAsyncMessageFilter() {
  516           int[] messageFilter = new int[10];
  517           messageFilter[0] = SshMsgGlobalRequest.SSH_MSG_GLOBAL_REQUEST;
  518           messageFilter[3] = SshMsgChannelOpen.SSH_MSG_CHANNEL_OPEN;
  519           messageFilter[4] = SshMsgChannelClose.SSH_MSG_CHANNEL_CLOSE;
  520           messageFilter[5] = SshMsgChannelEOF.SSH_MSG_CHANNEL_EOF;
  521           messageFilter[6] = SshMsgChannelExtendedData.SSH_MSG_CHANNEL_EXTENDED_DATA;
  522           messageFilter[7] = SshMsgChannelData.SSH_MSG_CHANNEL_DATA;
  523           messageFilter[8] = SshMsgChannelRequest.SSH_MSG_CHANNEL_REQUEST;
  524           messageFilter[9] = SshMsgChannelWindowAdjust.SSH_MSG_CHANNEL_WINDOW_ADJUST;
  525   
  526           return messageFilter;
  527       }
  528   
  529       /**
  530        *
  531        *
  532        * @param channel
  533        *
  534        * @throws IOException
  535        */
  536       protected void closeChannel(Channel channel) throws IOException {
  537           SshMsgChannelClose msg = new SshMsgChannelClose(channel.getRemoteChannelId());
  538           log.info("Local computer has closed channel " +
  539               String.valueOf(channel.getLocalChannelId()) + "[" +
  540               channel.getName() + "]");
  541           transport.sendMessage(msg, this);
  542       }
  543   
  544       /**
  545        *
  546        *
  547        * @param requestName
  548        * @param wantReply
  549        * @param requestData
  550        *
  551        * @throws IOException
  552        */
  553       protected void onGlobalRequest(String requestName, boolean wantReply,
  554           byte[] requestData) throws IOException {
  555           log.debug("Processing " + requestName + " global request");
  556   
  557           if (!globalRequests.containsKey(requestName)) {
  558               sendGlobalRequestFailure();
  559           } else {
  560               GlobalRequestHandler handler = (GlobalRequestHandler) globalRequests.get(requestName);
  561               GlobalRequestResponse response = handler.processGlobalRequest(requestName,
  562                       requestData);
  563   
  564               if (wantReply) {
  565                   if (response.hasSucceeded()) {
  566                       sendGlobalRequestSuccess(response.getResponseData());
  567                   } else {
  568                       sendGlobalRequestFailure();
  569                   }
  570               }
  571           }
  572       }
  573   
  574       /**
  575        *
  576        *
  577        * @param msg
  578        *
  579        * @throws IOException
  580        */
  581       protected void onMessageReceived(SshMessage msg) throws IOException {
  582           // Route the message to the correct handling function
  583           switch (msg.getMessageId()) {
  584           case SshMsgGlobalRequest.SSH_MSG_GLOBAL_REQUEST: {
  585               onMsgGlobalRequest((SshMsgGlobalRequest) msg);
  586   
  587               break;
  588           }
  589   
  590           case SshMsgChannelOpen.SSH_MSG_CHANNEL_OPEN: {
  591               onMsgChannelOpen((SshMsgChannelOpen) msg);
  592   
  593               break;
  594           }
  595   
  596           case SshMsgChannelClose.SSH_MSG_CHANNEL_CLOSE: {
  597               onMsgChannelClose((SshMsgChannelClose) msg);
  598   
  599               break;
  600           }
  601   
  602           case SshMsgChannelEOF.SSH_MSG_CHANNEL_EOF: {
  603               onMsgChannelEOF((SshMsgChannelEOF) msg);
  604   
  605               break;
  606           }
  607   
  608           case SshMsgChannelData.SSH_MSG_CHANNEL_DATA: {
  609               onMsgChannelData((SshMsgChannelData) msg);
  610   
  611               break;
  612           }
  613   
  614           case SshMsgChannelExtendedData.SSH_MSG_CHANNEL_EXTENDED_DATA: {
  615               onMsgChannelExtendedData((SshMsgChannelExtendedData) msg);
  616   
  617               break;
  618           }
  619   
  620           case SshMsgChannelRequest.SSH_MSG_CHANNEL_REQUEST: {
  621               onMsgChannelRequest((SshMsgChannelRequest) msg);
  622   
  623               break;
  624           }
  625   
  626           case SshMsgChannelWindowAdjust.SSH_MSG_CHANNEL_WINDOW_ADJUST: {
  627               onMsgChannelWindowAdjust((SshMsgChannelWindowAdjust) msg);
  628   
  629               break;
  630           }
  631   
  632           default: {
  633               // If we never registered it why are we getting it?
  634               log.debug("Message not handled");
  635               throw new IOException("Unregistered message received!");
  636           }
  637           }
  638       }
  639   
  640       /**
  641        *
  642        */
  643       protected void onServiceAccept() {
  644       }
  645   
  646       /**
  647        *
  648        *
  649        * @param startMode
  650        *
  651        * @throws IOException
  652        */
  653       protected void onServiceInit(int startMode) throws IOException {
  654           log.info("Registering connection protocol messages");
  655           messageStore.registerMessage(SshMsgChannelOpenConfirmation.SSH_MSG_CHANNEL_OPEN_CONFIRMATION,
  656               SshMsgChannelOpenConfirmation.class);
  657           messageStore.registerMessage(SshMsgChannelOpenFailure.SSH_MSG_CHANNEL_OPEN_FAILURE,
  658               SshMsgChannelOpenFailure.class);
  659           messageStore.registerMessage(SshMsgChannelOpen.SSH_MSG_CHANNEL_OPEN,
  660               SshMsgChannelOpen.class);
  661           messageStore.registerMessage(SshMsgChannelClose.SSH_MSG_CHANNEL_CLOSE,
  662               SshMsgChannelClose.class);
  663           messageStore.registerMessage(SshMsgChannelEOF.SSH_MSG_CHANNEL_EOF,
  664               SshMsgChannelEOF.class);
  665           messageStore.registerMessage(SshMsgChannelData.SSH_MSG_CHANNEL_DATA,
  666               SshMsgChannelData.class);
  667           messageStore.registerMessage(SshMsgChannelExtendedData.SSH_MSG_CHANNEL_EXTENDED_DATA,
  668               SshMsgChannelExtendedData.class);
  669           messageStore.registerMessage(SshMsgChannelFailure.SSH_MSG_CHANNEL_FAILURE,
  670               SshMsgChannelFailure.class);
  671           messageStore.registerMessage(SshMsgChannelRequest.SSH_MSG_CHANNEL_REQUEST,
  672               SshMsgChannelRequest.class);
  673           messageStore.registerMessage(SshMsgChannelSuccess.SSH_MSG_CHANNEL_SUCCESS,
  674               SshMsgChannelSuccess.class);
  675           messageStore.registerMessage(SshMsgChannelWindowAdjust.SSH_MSG_CHANNEL_WINDOW_ADJUST,
  676               SshMsgChannelWindowAdjust.class);
  677           messageStore.registerMessage(SshMsgGlobalRequest.SSH_MSG_GLOBAL_REQUEST,
  678               SshMsgGlobalRequest.class);
  679           messageStore.registerMessage(SshMsgRequestFailure.SSH_MSG_REQUEST_FAILURE,
  680               SshMsgRequestFailure.class);
  681           messageStore.registerMessage(SshMsgRequestSuccess.SSH_MSG_REQUEST_SUCCESS,
  682               SshMsgRequestSuccess.class);
  683       }
  684   
  685       /**
  686        *
  687        */
  688       protected void onServiceRequest() {
  689       }
  690   
  691       /**
  692        *
  693        *
  694        * @param channel
  695        *
  696        * @throws IOException
  697        */
  698       protected void sendChannelFailure(Channel channel)
  699           throws IOException {
  700           SshMsgChannelFailure msg = new SshMsgChannelFailure(channel.getRemoteChannelId());
  701           transport.sendMessage(msg, this);
  702       }
  703   
  704       /**
  705        *
  706        *
  707        * @param channel
  708        *
  709        * @throws IOException
  710        */
  711       protected void sendChannelOpenConfirmation(Channel channel)
  712           throws IOException {
  713           SshMsgChannelOpenConfirmation msg = new SshMsgChannelOpenConfirmation(channel.getRemoteChannelId(),
  714                   channel.getLocalChannelId(),
  715                   channel.getLocalWindow().getWindowSpace(),
  716                   channel.getLocalPacketSize(),
  717                   channel.getChannelConfirmationData());
  718           transport.sendMessage(msg, this);
  719       }
  720   
  721       /**
  722        *
  723        *
  724        * @param remoteChannelId
  725        * @param reasonCode
  726        * @param additionalInfo
  727        * @param languageTag
  728        *
  729        * @throws IOException
  730        */
  731       protected void sendChannelOpenFailure(long remoteChannelId,
  732           long reasonCode, String additionalInfo, String languageTag)
  733           throws IOException {
  734           SshMsgChannelOpenFailure msg = new SshMsgChannelOpenFailure(remoteChannelId,
  735                   reasonCode, additionalInfo, languageTag);
  736           transport.sendMessage(msg, this);
  737       }
  738   
  739       /**
  740        *
  741        *
  742        * @throws IOException
  743        */
  744       protected void sendGlobalRequestFailure() throws IOException {
  745           SshMsgRequestFailure msg = new SshMsgRequestFailure();
  746           transport.sendMessage(msg, this);
  747       }
  748   
  749       /**
  750        *
  751        *
  752        * @param requestData
  753        *
  754        * @throws IOException
  755        */
  756       protected void sendGlobalRequestSuccess(byte[] requestData)
  757           throws IOException {
  758           SshMsgRequestSuccess msg = new SshMsgRequestSuccess(requestData);
  759           transport.sendMessage(msg, this);
  760       }
  761   
  762       private Channel getChannel(long channelId) throws IOException {
  763           //synchronized (activeChannels) {
  764               Long l = new Long(channelId);
  765   
  766               if (!activeChannels.containsKey(l)) {
  767                   throw new IOException("Non existent channel " + l.toString() +
  768                       " requested");
  769               }
  770   			return (Channel) activeChannels.get(l);
  771           //}
  772       }
  773   
  774       private void onMsgChannelClose(SshMsgChannelClose msg)
  775           throws IOException {
  776           Channel channel = getChannel(msg.getRecipientChannel());
  777   
  778           // If we have not already closed it then inform the subclasses
  779           if (channel == null) {
  780               throw new IOException("Remote computer tried to close a " +
  781                   "non existent channel " +
  782                   String.valueOf(msg.getRecipientChannel()));
  783           }
  784   
  785           log.info("Remote computer has closed channel " +
  786               String.valueOf(channel.getLocalChannelId()) + "[" +
  787               channel.getName() + "]");
  788   
  789           // If the channel is not already closed then close it
  790           if (channel.getState().getValue() != ChannelState.CHANNEL_CLOSED) {
  791               channel.remoteClose();
  792           }
  793       }
  794   
  795       private void onMsgChannelData(SshMsgChannelData msg)
  796           throws IOException {
  797           if (log.isDebugEnabled()) {
  798               log.debug("Received " +
  799                   String.valueOf(msg.getChannelData().length) +
  800                   " bytes of data for channel id " +
  801                   String.valueOf(msg.getRecipientChannel()));
  802           }
  803   
  804           // Get the data's channel
  805           Channel channel = getChannel(msg.getRecipientChannel());
  806           channel.processChannelData(msg);
  807       }
  808   
  809       private void onMsgChannelEOF(SshMsgChannelEOF msg)
  810           throws IOException {
  811           Channel channel = getChannel(msg.getRecipientChannel());
  812   
  813           try {
  814               log.info("Remote computer has set channel " +
  815                   String.valueOf(msg.getRecipientChannel()) + " to EOF [" +
  816                   channel.getName() + "]");
  817               channel.setRemoteEOF();
  818           } catch (IOException ioe) {
  819               log.info("Failed to close the ChannelInputStream after EOF event");
  820           }
  821       }
  822   
  823       private void onMsgChannelExtendedData(SshMsgChannelExtendedData msg)
  824           throws IOException {
  825           Channel channel = getChannel(msg.getRecipientChannel());
  826   
  827           if (channel == null) {
  828               throw new IOException(
  829                   "Remote computer sent data for non existent channel");
  830           }
  831   
  832           channel.getLocalWindow().consumeWindowSpace(msg.getChannelData().length);
  833           channel.processChannelData(msg);
  834       }
  835   
  836       private void onMsgChannelOpen(SshMsgChannelOpen msg)
  837           throws IOException {
  838           //synchronized (activeChannels) {
  839               log.info("Request for " + msg.getChannelType() +
  840                   " channel recieved");
  841   
  842               // Try to get the channel implementation from the allowed channels
  843               ChannelFactory cf = (ChannelFactory) allowedChannels.get(msg.getChannelType());
  844   
  845               if (cf == null) {
  846                   sendChannelOpenFailure(msg.getSenderChannelId(),
  847                       SshMsgChannelOpenFailure.SSH_OPEN_CONNECT_FAILED,
  848                       "The channel type is not supported", "");
  849                   log.info("Request for channel type " + msg.getChannelType() +
  850                       " refused");
  851   
  852                   return;
  853               }
  854   
  855               try {
  856                   log.info("Creating channel " + msg.getChannelType());
  857   
  858                   Channel channel = cf.createChannel(msg.getChannelType(),
  859                           msg.getChannelData());
  860   
  861                   // Initialize the channel
  862                   log.info("Initiating channel");
  863   
  864                   Long channelId = getChannelId();
  865                   channel.init(this, channelId.longValue(),
  866                       msg.getSenderChannelId(), msg.getInitialWindowSize(),
  867                       msg.getMaximumPacketSize());
  868                   activeChannels.put(channelId, channel);
  869                   log.info("Sending channel open confirmation");
  870   
  871                   // Send the confirmation message
  872                   sendChannelOpenConfirmation(channel);
  873   
  874                   // Open the channel for real
  875                   channel.open();
  876               } catch (InvalidChannelException ice) {
  877                   sendChannelOpenFailure(msg.getSenderChannelId(),
  878                       SshMsgChannelOpenFailure.SSH_OPEN_CONNECT_FAILED,
  879                       ice.getMessage(), "");
  880               }
  881           //}
  882       }
  883   
  884       private void onMsgChannelRequest(SshMsgChannelRequest msg)
  885           throws IOException {
  886           Channel channel = getChannel(msg.getRecipientChannel());
  887   
  888           if (channel == null) {
  889               log.warn("Remote computer tried to make a request for " +
  890                   "a non existence channel!");
  891           }
  892   
  893           channel.onChannelRequest(msg.getRequestType(), msg.getWantReply(),
  894               msg.getChannelData());
  895       }
  896   
  897       private void onMsgChannelWindowAdjust(SshMsgChannelWindowAdjust msg)
  898           throws IOException {
  899           Channel channel = getChannel(msg.getRecipientChannel());
  900   
  901           if (channel == null) {
  902               throw new IOException("Remote computer tried to increase " +
  903                   "window space for non existent channel " +
  904                   String.valueOf(msg.getRecipientChannel()));
  905           }
  906   
  907           channel.getRemoteWindow().increaseWindowSpace(msg.getBytesToAdd());
  908   
  909           if (log.isDebugEnabled()) {
  910               log.debug(String.valueOf(msg.getBytesToAdd()) +
  911                   " bytes added to remote window");
  912               log.debug("Remote window space is " +
  913                   String.valueOf(channel.getRemoteWindow().getWindowSpace()));
  914           }
  915       }
  916   
  917       private void onMsgGlobalRequest(SshMsgGlobalRequest msg)
  918           throws IOException {
  919           onGlobalRequest(msg.getRequestName(), msg.getWantReply(),
  920               msg.getRequestData());
  921       }
  922   
  923       /**
  924        *
  925        *
  926        * @param channel
  927        */
  928       protected void freeChannel(Channel channel) {
  929           //synchronized (activeChannels) {
  930               log.info("Freeing channel " +
  931                   String.valueOf(channel.getLocalChannelId()) + " [" +
  932                   channel.getName() + "]");
  933   
  934               Long channelId = new Long(channel.getLocalChannelId());
  935               activeChannels.remove(channelId);
  936   
  937               //reusableChannels.add(channelId);
  938           //}
  939       }
  940   }

Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.j2ssh.connection » [javadoc | source]