From: <chr...@us...> - 2009-04-29 21:56:58
|
Revision: 5362 http://jnode.svn.sourceforge.net/jnode/?rev=5362&view=rev Author: chrisboertien Date: 2009-04-29 21:56:54 +0000 (Wed, 29 Apr 2009) Log Message: ----------- Refactor of org.jnode.net.command to org.jnode.command.net Signed-off-by: chrisboertien <chr...@gm...> Modified Paths: -------------- trunk/all/conf/default-plugin-list.xml Added Paths: ----------- trunk/cli/coreutils/ trunk/cli/coreutils/descriptors/ trunk/cli/coreutils/descriptors/org.jnode.command.net.xml trunk/cli/coreutils/src/ trunk/cli/coreutils/src/commands/ trunk/cli/coreutils/src/commands/org/ trunk/cli/coreutils/src/commands/org/jnode/ trunk/cli/coreutils/src/commands/org/jnode/command/ trunk/cli/coreutils/src/commands/org/jnode/command/net/ trunk/cli/coreutils/src/commands/org/jnode/command/net/ArpCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/BootpCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/DhcpCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/IfconfigCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/NetstatCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/PingCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/ResolverCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/RouteCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/RpcInfoCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/TcpInoutCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/TftpCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/WLanCtlCommand.java trunk/cli/coreutils/src/commands/org/jnode/command/net/WgetCommand.java Removed Paths: ------------- trunk/net/descriptors/org.jnode.net.command.xml trunk/net/src/net/org/jnode/net/command/ArpCommand.java trunk/net/src/net/org/jnode/net/command/BootpCommand.java trunk/net/src/net/org/jnode/net/command/DhcpCommand.java trunk/net/src/net/org/jnode/net/command/IfconfigCommand.java trunk/net/src/net/org/jnode/net/command/NetstatCommand.java trunk/net/src/net/org/jnode/net/command/PingCommand.java trunk/net/src/net/org/jnode/net/command/ResolverCommand.java trunk/net/src/net/org/jnode/net/command/RouteCommand.java trunk/net/src/net/org/jnode/net/command/RpcInfoCommand.java trunk/net/src/net/org/jnode/net/command/TcpInoutCommand.java trunk/net/src/net/org/jnode/net/command/TftpCommand.java trunk/net/src/net/org/jnode/net/command/WLanCtlCommand.java trunk/net/src/net/org/jnode/net/command/WgetCommand.java Modified: trunk/all/conf/default-plugin-list.xml =================================================================== --- trunk/all/conf/default-plugin-list.xml 2009-04-29 21:55:50 UTC (rev 5361) +++ trunk/all/conf/default-plugin-list.xml 2009-04-29 21:56:54 UTC (rev 5362) @@ -52,6 +52,7 @@ <plugin id="org.apache.tools.archive" /> <plugin id="org.jnode.command.archive"/> <plugin id="org.jnode.command.file"/> + <plugin id="org.jnode.command.net"/> <plugin id="org.jnode.command.util"/> <plugin id="org.jnode.debug"/> @@ -152,7 +153,6 @@ <plugin id="org.jnode.net"/> <plugin id="org.jnode.net.arp"/> - <plugin id="org.jnode.net.command"/> <plugin id="org.jnode.net.ipv4"/> <plugin id="org.jnode.net.ipv4.config"/> <plugin id="org.jnode.net.ipv4.core"/> Copied: trunk/cli/coreutils/descriptors/org.jnode.command.net.xml (from rev 5361, trunk/net/descriptors/org.jnode.net.command.xml) =================================================================== --- trunk/cli/coreutils/descriptors/org.jnode.command.net.xml (rev 0) +++ trunk/cli/coreutils/descriptors/org.jnode.command.net.xml 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plugin SYSTEM "jnode.dtd"> + +<plugin id="org.jnode.command.net" + name="JNode net commands" + version="@VERSION@" + provider-name="@PROVIDER@" + license-name="lgpl"> + + <requires> + <import plugin="org.jnode.net"/> + <import plugin="org.jnode.net.arp"/> + <import plugin="org.jnode.net.ipv4"/> + <import plugin="org.jnode.net.ipv4.config"/> + <import plugin="org.jnode.shell.help"/> + <import plugin="org.acplt.oncrpc"/> + </requires> + + <runtime> + <library name="jnode-net.jar"> + <export name="org.jnode.net.syntax.*"/> + </library> + <library name="jnode-coreutils.jar"> + <export name="org.jnode.command.net.*"/> + </library> + </runtime> + + <extension point="org.jnode.shell.aliases"> + <alias name="arp" class="org.jnode.command.net.ArpCommand"/> + <alias name="bootp" class="org.jnode.command.net.BootpCommand"/> + <alias name="dhcp" class="org.jnode.command.net.DhcpCommand"/> + <alias name="ifconfig" class="org.jnode.command.net.IfconfigCommand"/> + <alias name="netstat" class="org.jnode.command.net.NetstatCommand"/> + <alias name="ping" class="org.jnode.command.net.PingCommand"/> + <alias name="route" class="org.jnode.command.net.RouteCommand"/> + <alias name="resolver" class="org.jnode.command.net.ResolverCommand"/> + <alias name="resolve" class="org.jnode.command.net.ResolveCommand"/> + <alias name="tftp" class="org.jnode.command.net.TftpCommand"/> + <alias name="wlanctl" class="org.jnode.command.net.WLanCtlCommand"/> + <alias name="tcpinout" class="org.jnode.command.net.TcpInoutCommand"/> + <alias name="rpcinfo" class="org.jnode.command.net.RpcInfoCommand"/> + <alias name="wget" class="org.jnode.command.net.WgetCommand"/> + </extension> + + <extension point="org.jnode.shell.syntaxes"> + <syntax alias="arp"> + <empty description="List the ARP cache"/> + <option argLabel="clear" shortName="c" longName="clear" description="Clear the ARP cache"/> + </syntax> + <syntax alias="bootp"> + <argument argLabel="device" description="Configure a network interface using BOOTP"/> + </syntax> + <syntax alias="dhcp"> + <argument argLabel="device" description="Configure a network interface using DHCP"/> + </syntax> + <syntax alias="ifconfig"> + <empty description="Print network addresses for all network devices"/> + <argument argLabel="device" description="Print network addresses for a given device"/> + <sequence description="Bind a given device to an IPv4 address"> + <argument argLabel="device"/> + <argument argLabel="ipAddress"/> + <optional><argument argLabel="subnetMask"/></optional> + </sequence> + </syntax> + <syntax alias="netstat"> + <empty description="Print statistics for all network devices"/> + </syntax> + <syntax alias="ping"> + <argument argLabel="host" description="Ping a remote host"/> + </syntax> + <syntax alias="resolver"> + <empty description="List the DNS servers used by the resolver's list"/> + <sequence description="Add a DNS server to the resolver"> + <option argLabel="add" shortName="a" longName="add"/> + <argument argLabel="server"/> + </sequence> + <sequence description="Remove a DNS server from the resolver's list"> + <option argLabel="del" shortName="d" longName="del"/> + <argument argLabel="server"/> + </sequence> + </syntax> + <syntax alias="route"> + <empty description="Print the routing table"/> + <sequence description="Add or remove a route"> + <alternatives> + <option argLabel="add" shortName="a" longName="add"/> + <option argLabel="del" shortName="d" longName="del"/> + </alternatives> + <argument argLabel="target"/> + <argument argLabel="device"/> + <optional><argument argLabel="gateway"/></optional> + </sequence> + </syntax> + <syntax alias="rpcinfo"> + <argument argLabel="host" description="Probe a remote host's portmapper service"/> + </syntax> + <syntax alias="tcpinout"> + <argument argLabel="localPort" description="Run tcpinout in server mode"/> + <sequence description="Run tcpinout in client mode"> + <argument argLabel="host"/> + <argument argLabel="port"/> + </sequence> + </syntax> + <syntax alias="tftp"> + <optional description="Run an interactive TFTP client"><argument argLabel="host"/></optional> + <sequence description="Do a non-interactive TFTP 'get' or 'put'"> + <alternatives> + <option argLabel="get" longName="get"/> + <option argLabel="put" longName="put"/> + </alternatives> + <argument argLabel="host"/> + <argument argLabel="filename"/> + </sequence> + </syntax> + <syntax alias="wlanctl"> + <sequence description="Set the ESSID for a WLan device"> + <option argLabel="setEssid" longName="setessid"/> + <argument argLabel="device"/> + <argument argLabel="value"/> + </sequence> + </syntax> + <syntax alias="wget"> + <sequence description="Fetch the contents of one or more URLs"> + <optional><option argLabel="debug" shortName="d" longName="debug"/></optional> + <repeat minCount="1"><argument argLabel="url"/></repeat> + </sequence> + </syntax> + </extension> + + <extension point="org.jnode.security.permissions"> + <permission class="java.net.SocketPermission" name="*" actions="connect,resolve"/> + <permission class="java.net.SocketPermission" name="*:1024-" actions="listen,accept"/> + <permission class="java.net.SocketPermission" name="*:53" actions="resolve,listen,connect"/> + <permission class="java.net.SocketPermission" name="*:80" actions="resolve,listen,connect"/> + <permission class="java.net.SocketPermission" name="*:8080" actions="resolve,listen,connect"/> + <permission class="java.util.PropertyPermission" name="dns.server" actions="read"/> + <permission class="java.util.PropertyPermission" name="dns.search" actions="read"/> + <permission class="java.util.PropertyPermission" name="user.dir" actions="read"/> + <permission class="org.jnode.net.NetPermission" name="bootpClient"/> + <permission class="org.jnode.net.NetPermission" name="dhcpClient"/> + <permission class="org.jnode.net.NetPermission" name="wget"/> + <permission class="java.io.FilePermission" name="<<ALL FILES>>" actions="read,write"/> + </extension> +</plugin> Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/ArpCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/ArpCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/ArpCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/ArpCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; + +import org.jnode.driver.net.NetworkException; +import org.jnode.net.NoSuchProtocolException; +import org.jnode.net.arp.ARPCacheEntry; +import org.jnode.net.arp.ARPNetworkLayer; +import org.jnode.net.ethernet.EthernetConstants; +import org.jnode.net.util.NetUtils; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.FlagArgument; + +/** + * @author epr + */ +public class ArpCommand extends AbstractCommand { + + private static final String help_clear = "if set, clear the ARP cache"; + private static final String help_super = "print or clear the ARP cache"; + private static final String str_cleared = "Cleared the ARP cache"; + + private final FlagArgument argClear; + + public ArpCommand() { + super(help_super); + argClear = new FlagArgument("clear", Argument.OPTIONAL, help_super); + registerArguments(argClear); + } + + /** + * Execute this command + */ + public static void main(String[] args) throws Exception { + new ArpCommand().execute(args); + } + + public void execute() throws NoSuchProtocolException, NetworkException { + ARPNetworkLayer arp = (ARPNetworkLayer) + NetUtils.getNLM().getNetworkLayer(EthernetConstants.ETH_P_ARP); + PrintWriter out = getOutput().getPrintWriter(); + if (argClear.isSet()) { + arp.getCache().clear(); + out.println(str_cleared); + } else { + for (ARPCacheEntry entry : arp.getCache().entries()) { + out.println(entry); + } + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/BootpCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/BootpCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/BootpCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/BootpCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,62 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import javax.naming.NameNotFoundException; + +import org.jnode.driver.Device; +import org.jnode.driver.net.NetDeviceAPI; +import org.jnode.driver.net.NetworkException; +import org.jnode.naming.InitialNaming; +import org.jnode.net.ipv4.config.IPv4ConfigurationService; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.DeviceArgument; + +/** + * @author epr + */ +public class BootpCommand extends AbstractCommand { + + private static final String help_device = ""; + private static final String help_super = "Configure a network interface using BOOTP"; + private static final String fmt_config = "Trying to configure %s...%n"; + + private final DeviceArgument argDevice; + + public BootpCommand() { + super(help_super); + argDevice = new DeviceArgument("device", Argument.MANDATORY, help_device, NetDeviceAPI.class); + registerArguments(argDevice); + } + + public static void main(String[] args) throws Exception { + new BootpCommand().execute(args); + } + + public void execute() throws NameNotFoundException, NetworkException { + final Device dev = argDevice.getValue(); + getOutput().getPrintWriter().format(fmt_config, dev.getId()); + final IPv4ConfigurationService cfg = InitialNaming.lookup(IPv4ConfigurationService.NAME); + cfg.configureDeviceBootp(dev, true); + } + +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/DhcpCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/DhcpCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/DhcpCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/DhcpCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,90 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import javax.naming.NameNotFoundException; + +import org.jnode.driver.ApiNotFoundException; +import org.jnode.driver.Device; +import org.jnode.driver.DeviceManager; +import org.jnode.driver.DeviceNotFoundException; +import org.jnode.driver.net.NetDeviceAPI; +import org.jnode.driver.net.NetworkException; +import org.jnode.naming.InitialNaming; +import org.jnode.net.ProtocolAddressInfo; +import org.jnode.net.ethernet.EthernetConstants; +import org.jnode.net.ipv4.config.IPv4ConfigurationService; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.DeviceArgument; + +/** + * @author markhale + * @author cr...@jn... + */ +public class DhcpCommand extends AbstractCommand { + + private static final String help_device = "the network interface device to be configured"; + private static final String help_super = "Configure a network interface using DHCP"; + private static final String err_loopback = "The loopback network device is not bound to IP address 127.0.0.1%n" + + "Run 'ifconfig loopback 127.0.0.1 255.255.255.255' to fix this.%n"; + private static final String fmt_config = "Configuring network device %s...%n"; + + private final DeviceArgument argDevice; + + public DhcpCommand() { + super(help_super); + argDevice = new DeviceArgument("device", Argument.MANDATORY, help_device, NetDeviceAPI.class); + registerArguments(argDevice); + } + + public static void main(String[] args) throws Exception { + new DhcpCommand().execute(args); + } + + public void execute() throws DeviceNotFoundException, NameNotFoundException, ApiNotFoundException, + UnknownHostException, NetworkException { + final Device dev = argDevice.getValue(); + + // The DHCP network configuration process will attempt to configure the DNS. This will only work if + // the IP address 127.0.0.1 is bound to the loopback network interface. And if there isn't, JNode's + // network layer is left in a state that will require a reboot to unjam it (AFAIK). + // + // So, check that loopback is correctly bound ... + Device loopback = (InitialNaming.lookup(DeviceManager.NAME)).getDevice("loopback"); + NetDeviceAPI api = loopback.getAPI(NetDeviceAPI.class); + ProtocolAddressInfo info = api.getProtocolAddressInfo(EthernetConstants.ETH_P_IP); + if (info == null || !info.contains(InetAddress.getByAddress(new byte[]{127, 0, 0, 1}))) { + PrintWriter err = getError().getPrintWriter(); + err.format(err_loopback); + exit(1); + } + + // Now it should be safe to do the DHCP configuration. + getOutput().getPrintWriter().format(fmt_config, dev.getId()); + final IPv4ConfigurationService cfg = InitialNaming.lookup(IPv4ConfigurationService.NAME); + cfg.configureDeviceDhcp(dev, true); + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/IfconfigCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/IfconfigCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/IfconfigCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/IfconfigCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,107 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; + +import javax.naming.NameNotFoundException; + +import org.jnode.driver.ApiNotFoundException; +import org.jnode.driver.Device; +import org.jnode.driver.DeviceManager; +import org.jnode.driver.net.NetDeviceAPI; +import org.jnode.driver.net.NetworkException; +import org.jnode.naming.InitialNaming; +import org.jnode.net.ethernet.EthernetConstants; +import org.jnode.net.ipv4.IPv4Address; +import org.jnode.net.ipv4.config.IPv4ConfigurationService; +import org.jnode.net.syntax.IPv4AddressArgument; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.DeviceArgument; + +/** + * This command class binds IP addresses to network devices, and displays bindings. + * + * @author epr + * @author cr...@jn... + */ +public class IfconfigCommand extends AbstractCommand { + // FIXME should support IPv6 and other address families. + + private static final String help_device = "the device"; + private static final String help_ip = "the IPv4 address to bind the device to"; + private static final String help_subnet = "the IPv4 subnet mask for the device"; + private static final String help_super = "List or manage network interface bindings"; + private static final String fmt_devices = "%s: MAC-Address %s MTU %s%n %s"; + private static final String fmt_ip = "IP address(es) for %s %s"; + private static final String fmt_set_ip = "IP Address for %s set to %s"; + + private final DeviceArgument argDevice; + private final IPv4AddressArgument argIPAddress; + private final IPv4AddressArgument argSubnetMask; + + + public IfconfigCommand() { + super(help_super); + argDevice = new DeviceArgument("device", Argument.OPTIONAL, help_device, NetDeviceAPI.class); + argIPAddress = new IPv4AddressArgument("ipAddress", Argument.OPTIONAL, help_ip); + argSubnetMask = new IPv4AddressArgument("subnetMask", Argument.OPTIONAL, help_subnet); + registerArguments(argDevice, argIPAddress, argSubnetMask); + } + + public static void main(String[] args) throws Exception { + new IfconfigCommand().execute(args); + } + + public void execute() throws NameNotFoundException, ApiNotFoundException, NetworkException { + PrintWriter out = getOutput().getPrintWriter(); + if (!argDevice.isSet()) { + // Print MAC address, MTU and IP address(es) for all network devices. + final DeviceManager dm = InitialNaming.lookup(DeviceManager.NAME); + for (Device dev : dm.getDevicesByAPI(NetDeviceAPI.class)) { + final NetDeviceAPI api = dev.getAPI(NetDeviceAPI.class); + String info = api.getProtocolAddressInfo(EthernetConstants.ETH_P_IP).toString(); + out.format(fmt_devices, dev.getId(), api.getAddress(), api.getMTU(), info); + } + } else { + final Device dev = argDevice.getValue(); + final NetDeviceAPI api = dev.getAPI(NetDeviceAPI.class); + + if (!argIPAddress.isSet()) { + // Print IP address(es) for device + out.format(fmt_ip, dev.getId(), api.getProtocolAddressInfo(EthernetConstants.ETH_P_IP)); + } else { + // Set IP address for device + final IPv4Address ip = argIPAddress.getValue(); + final IPv4Address mask = argSubnetMask.getValue(); + final IPv4ConfigurationService cfg = InitialNaming.lookup(IPv4ConfigurationService.NAME); + cfg.configureDeviceStatic(dev, ip, mask, true); + + // FIXME ... this doesn't show the device's new address because the + // IPv4 ConfigurationServiceImpl calls processor.apply with the + // waitUntilReady parameter == false. (The comment in the code + // talks about avoiding deadlocks.) + out.format(fmt_set_ip, dev.getId(), api.getProtocolAddressInfo(EthernetConstants.ETH_P_IP)); + } + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/NetstatCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/NetstatCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/NetstatCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/NetstatCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,102 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; + +import org.jnode.driver.net.NetworkException; +import org.jnode.net.NetworkLayer; +import org.jnode.net.NetworkLayerManager; +import org.jnode.net.TransportLayer; +import org.jnode.net.util.NetUtils; +import org.jnode.shell.AbstractCommand; +import org.jnode.util.Statistic; +import org.jnode.util.Statistics; + +/** + * @author epr + */ +public class NetstatCommand extends AbstractCommand { + + private static final String help_super = "Print statistics for all network devices"; + private static final String fmt_stat = "%s: ID %s"; + private static final String str_none = "none"; + + public NetstatCommand() { + super(help_super); + } + + public static void main(String[] args) throws Exception { + new NetstatCommand().execute(args); + } + + /** + * Execute this command + */ + public void execute() throws Exception { + final NetworkLayerManager nlm = NetUtils.getNLM(); + + for (NetworkLayer nl : nlm.getNetworkLayers()) { + showStats(getOutput().getPrintWriter(), nl, 80); + } + } + + private void showStats(PrintWriter out, NetworkLayer nl, int maxWidth) throws NetworkException { + out.format(fmt_stat, nl.getName(), nl.getProtocolID()); + final String prefix = " "; + out.print(prefix); + showStats(out, nl.getStatistics(), maxWidth - prefix.length(), prefix); + for (TransportLayer tl : nl.getTransportLayers()) { + out.print(prefix); + out.format(fmt_stat, tl.getName(), tl.getProtocolID()); + final String prefix2 = prefix + prefix; + out.print(prefix2); + showStats(out, tl.getStatistics(), maxWidth - prefix2.length(), prefix2); + } + out.println(); + } + + private void showStats(PrintWriter out, Statistics stat, int maxWidth, String prefix) + throws NetworkException { + final Statistic[] list = stat.getStatistics(); + if (list.length == 0) { + out.print(str_none); + } else { + int width = 0; + for (int i = 0; i < list.length; i++) { + final Statistic st = list[i]; + String msg = st.getName() + " " + st.getValue(); + if (i + 1 < list.length) { + msg = msg + ", "; + } + if (width + msg.length() > maxWidth) { + out.println(); + out.print(prefix); + width = 0; + } + out.print(msg); + width += msg.length(); + } + } + out.println(); + } + +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/PingCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/PingCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/PingCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/PingCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,281 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.HashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; + +import org.jnode.net.SocketBuffer; +import org.jnode.net.ethernet.EthernetConstants; +import org.jnode.net.ipv4.IPv4Address; +import org.jnode.net.ipv4.IPv4Constants; +import org.jnode.net.ipv4.IPv4Header; +import org.jnode.net.ipv4.icmp.ICMPEchoHeader; +import org.jnode.net.ipv4.icmp.ICMPListener; +import org.jnode.net.ipv4.icmp.ICMPProtocol; +import org.jnode.net.ipv4.layer.IPv4NetworkLayer; +import org.jnode.net.util.NetUtils; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.HostNameArgument; + +/** + * @author JPG + */ +public class PingCommand extends AbstractCommand implements ICMPListener { + + private static final String help_host = "the target host"; + private static final String help_super = "Ping the specified host"; + private static final String fmt_unknown_host = "Unknown host: %s"; + private static final String fmt_ping = "Ping %s attempt %d"; + private static final String fmt_reply = "Reply from %s: %d bytes of data ttl=%d seq=%d tim=%dms%n"; + private static final String fmt_stats = "-> Packet statistics%n%s%n"; + private static final String fmt_get_stats = "%d packets transmitted, %d packets received%nround-trip min/avg/max" + + " = %d/%d/%dms"; + + // FIXME Some of the following could be command parameters ... + private final Statistics stat = new Statistics(); + private boolean wait = true; + private int count = 4; + private boolean dontFragment = false; + private IPv4Address dst; + private boolean flood = false; + private int interval = 6000; + private int size = 64; + private long timeout = 5000; + private int ttl = 255; + + private final HostNameArgument argHost; + + public PingCommand() { + super(help_super); + argHost = new HostNameArgument("host", Argument.MANDATORY, help_host); + registerArguments(argHost); + } + + public static void main(String[] args) throws Exception { + new PingCommand().execute(args); + } + + public void execute() throws SocketException, InterruptedException { + try { + this.dst = new IPv4Address(argHost.getAsInetAddress()); + } catch (UnknownHostException ex) { + getError().getPrintWriter().format(fmt_unknown_host, ex.getLocalizedMessage()); + exit(1); + } + final PrintWriter out = getOutput().getPrintWriter(); + + final IPv4Header netHeader = + new IPv4Header(0, this.ttl, IPv4Constants.IPPROTO_ICMP, this.dst, 8); + netHeader.setDontFragment(this.dontFragment); + + final IPv4NetworkLayer netLayer = + (IPv4NetworkLayer) NetUtils.getNLM().getNetworkLayer(EthernetConstants.ETH_P_IP); + final ICMPProtocol icmpProtocol = + (ICMPProtocol) netLayer.getProtocol(ICMPProtocol.IPPROTO_ICMP); + icmpProtocol.addListener(this); + try { + int id_count = 0; + int seq_count = 0; + while (this.count != 0) { + out.format(fmt_ping, dst, seq_count); + + if (!this.flood) { + this.wait = true; + } + + SocketBuffer packet = new SocketBuffer(); + packet.insert(this.size); + ICMPEchoHeader transportHeader = new ICMPEchoHeader(8, id_count, seq_count); + transportHeader.prefixTo(packet); + + Request r = + new Request(this.stat, this.timeout, System.currentTimeMillis(), id_count, + seq_count); + registerRequest(r); + netLayer.transmit(netHeader, packet); + + while (this.wait) { + long time = System.currentTimeMillis() - r.getTimestamp(); + if (time > this.interval) { + this.wait = false; + } + Thread.sleep(500); + synchronized (this) { + if (response) { + out.format(fmt_reply, + dst.toString(), hdr1.getDataLength(), hdr1.getTtl(), hdr2.getSeqNumber(), roundt); + response = false; + } + } + } + this.count--; + seq_count++; + } + + while (!isEmpty()) { + Thread.sleep(100); + } + } finally { + icmpProtocol.removeListener(this); + } + + out.format(fmt_stats, this.stat.getStatistics()); + } + + private long match(int id, int seq, Request r) { + if (r != null && id == r.getId()) { + return r.getTimestamp(); + } else { + return -1; + } + } + + public void packetReceived(SocketBuffer skbuf) { + long received = System.currentTimeMillis(); + + IPv4Header hdr1 = (IPv4Header) skbuf.getNetworkLayerHeader(); + ICMPEchoHeader hdr2 = (ICMPEchoHeader) skbuf.getTransportLayerHeader(); + + int seq = hdr2.getSeqNumber(); + Request r = removeRequest(seq); + if (r == null || r.Obsolete()) { + return; + } + + long timestamp = match(hdr2.getIdentifier(), seq, r); + + long roundtrip = received - timestamp; + gotResponse(timestamp, hdr1, hdr2, roundtrip); + } + + private synchronized void gotResponse(long timestamp, IPv4Header hdr1, ICMPEchoHeader hdr2, + long roundtrip) { + if (timestamp != -1) { + this.hdr1 = hdr1; + this.hdr2 = hdr2; + this.roundt = roundtrip; + response = true; + } + wait = false; + this.stat.recordPacket(roundtrip); + } + + // response data + private boolean response; + private long roundt; + private IPv4Header hdr1; + private ICMPEchoHeader hdr2; + + // requests are tracked here + private Map<Integer, Request> requests = new HashMap<Integer, Request>(); + + private void registerRequest(Request r) { + requests.put(r.seq, r); + } + + private Request removeRequest(int seq) { + return requests.remove(seq); + } + + private boolean isEmpty() { + return requests.isEmpty(); + } + + class Request extends TimerTask { + private Timer timer = new Timer(); + private boolean obsolete = false; + private Statistics stat; + private long timestamp; + private int id, seq; + + Request(Statistics stat, long timeout, long timestamp, int id, int seq) { + this.stat = stat; + this.timestamp = timestamp; + this.id = id; + this.seq = seq; + + timer.schedule(this, timeout); + } + + public void run() { + if (!this.Obsolete()) { + stat.recordLost(); + removeRequest(this.seq); + } + } + + synchronized boolean Obsolete() { + if (!obsolete) { + this.obsolete = true; + this.timer.cancel(); + return false; + } else { + return true; + } + } + + long getTimestamp() { + return timestamp; + } + + int getId() { + return id; + } + + int getSeq() { + return seq; + } + } + + private class Statistics { + private int received = 0, lost = 0; + private long min = Integer.MAX_VALUE, max = 0; + private long sum; + + void recordPacket(long roundtrip) { + received++; + if (roundtrip < min) { + min = roundtrip; + } + if (roundtrip > max) { + max = roundtrip; + } + sum += roundtrip; + } + + void recordLost() { + lost++; + } + + String getStatistics() { + int packets = received + lost; + float avg = sum / packets; + return String.format(fmt_get_stats, packets, received, min, avg, max); + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/ResolverCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/ResolverCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/ResolverCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/ResolverCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,87 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.PrintWriter; +import java.util.Collection; + +import org.jnode.driver.net.NetworkException; +import org.jnode.net.ipv4.IPv4Address; +import org.jnode.net.ipv4.util.ResolverImpl; +import org.jnode.net.syntax.IPv4AddressArgument; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.FlagArgument; + +/** + * This command class manages the DNS resolver. + * + * @author hagar-wize + */ +public class ResolverCommand extends AbstractCommand { + + private static final String help_add = "If set, add a DNS server"; + private static final String help_del = "If set, remove a DNS server"; + private static final String help_server = "the DNS server's hostname or IP address"; + private static final String help_super = "Manage JNode's DNS resolver"; + private static final String str_no_servers = "No DNS servers found."; + private static final String str_servers = "DNS servers:"; + + // FIXME this should not be restricted to IPv4 addresses. + private final FlagArgument argAdd; + private final FlagArgument argDel; + private final IPv4AddressArgument argDnsServer; + + public ResolverCommand() { + super(help_super); + argAdd = new FlagArgument("add", Argument.OPTIONAL, help_add); + argDel = new FlagArgument("del", Argument.OPTIONAL, help_del); + argDnsServer = new IPv4AddressArgument("server", Argument.OPTIONAL, help_server); + registerArguments(argAdd, argDel, argDnsServer); + } + + public static void main(String[] args) throws Exception { + new ResolverCommand().execute(args); + } + + public void execute() throws NetworkException { + IPv4Address server = argDnsServer.getValue(); + PrintWriter out = getOutput().getPrintWriter(); + if (argAdd.isSet()) { + // Add a DNS server + ResolverImpl.addDnsServer(server); + } else if (argDel.isSet()) { + // Remove a DNS server + ResolverImpl.removeDnsServer(server); + } else { + // List the DNS servers that the resolver uses + Collection<String> resolvers = ResolverImpl.getDnsServers(); + if (resolvers.size() == 0) { + out.println(str_no_servers); + } else { + out.println(str_servers); + for (String dnsServer : resolvers) { + out.println(dnsServer); + } + } + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/RouteCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/RouteCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/RouteCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/RouteCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,95 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import static org.jnode.net.ethernet.EthernetConstants.ETH_P_IP; + +import java.io.PrintWriter; + +import javax.naming.NameNotFoundException; + +import org.jnode.driver.Device; +import org.jnode.driver.net.NetworkException; +import org.jnode.naming.InitialNaming; +import org.jnode.net.NoSuchProtocolException; +import org.jnode.net.ipv4.IPv4Address; +import org.jnode.net.ipv4.config.IPv4ConfigurationService; +import org.jnode.net.ipv4.layer.IPv4NetworkLayer; +import org.jnode.net.syntax.IPv4AddressArgument; +import org.jnode.net.syntax.IPv4HostArgument; +import org.jnode.net.util.NetUtils; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.DeviceArgument; +import org.jnode.shell.syntax.FlagArgument; + +/** + * @author epr + */ +public class RouteCommand extends AbstractCommand { + + private static final String help_add = "if set, add a route"; + private static final String help_del = "if set, remove a route"; + private static final String help_target = "the target network"; + private static final String help_gateway = "the gateway name or IP address"; + private static final String help_device = "the device to connect to the foreign network"; + private static final String help_super = "Manage the IPv4 network routing table"; + private static final String str_table = "Routing table:"; + + private final FlagArgument argAdd; + private final FlagArgument argDel; + private final IPv4AddressArgument argTarget; + private final IPv4HostArgument argGateway; + private final DeviceArgument argDevice; + + public RouteCommand() { + super(help_super); + argAdd = new FlagArgument("add", Argument.OPTIONAL, help_add); + argDel = new FlagArgument("del", Argument.OPTIONAL, help_del); + argTarget = new IPv4AddressArgument("target", Argument.OPTIONAL, help_target); + argGateway = new IPv4HostArgument("gateway", Argument.OPTIONAL, help_gateway); + argDevice = new DeviceArgument("device", Argument.OPTIONAL, help_device); + registerArguments(argAdd, argDel, argDevice, argGateway, argTarget); + } + + public static void main(String[] args) throws Exception { + new RouteCommand().execute(args); + } + + public void execute() throws NoSuchProtocolException, NetworkException, NameNotFoundException { + final IPv4NetworkLayer ipNL = + (IPv4NetworkLayer) NetUtils.getNLM().getNetworkLayer(ETH_P_IP); + final IPv4Address target = argTarget.getValue(); + final IPv4Address gateway = argGateway.getValue(); + final Device device = argDevice.getValue(); + final IPv4ConfigurationService cfg = InitialNaming.lookup(IPv4ConfigurationService.NAME); + + if (argAdd.isSet()) { + cfg.addRoute(target, gateway, device, true); + } else if (argDel.isSet()) { + cfg.deleteRoute(target, gateway, device); + } else { + PrintWriter out = getOutput().getPrintWriter(); + out.println(str_table); + out.println(ipNL.getRoutingTable()); + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/RpcInfoCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/RpcInfoCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/RpcInfoCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/RpcInfoCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,133 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.acplt.oncrpc.OncRpcException; +import org.acplt.oncrpc.OncRpcPortmapClient; +import org.acplt.oncrpc.OncRpcProtocols; +import org.acplt.oncrpc.OncRpcServerIdent; +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.HostNameArgument; + +/** + * rpcinfo command makes an RPC call to an RPC server and reports what it finds. + * + * @author Andrei Dore + */ +public class RpcInfoCommand extends AbstractCommand { + + private static final String help_host = "the host to be probed"; + private static final String help_super = "Probe the portmapper on host, and print a list of all registered RPS " + + "programs."; + private static final String fmt_list_serv = "%1$10s %2$10s %3$10s %4$10s %5$10s"; + private static final String str_program = "Program"; + private static final String str_version = "Version"; + private static final String str_protocol = "Protocol"; + private static final String str_port = "Port"; + private static final String str_name = "Name"; + private static final String str_portmapper = "portmapper"; + private static final String str_nfs = "nfs"; + private static final String str_mountd = "mountd"; + private static final String str_nlockmgr = "nlockmgr"; + private static final String str_status = "status"; + private static final String str_tcp = "tcp"; + private static final String str_udp = "udp"; + private static final String err_call = "Cannot make the rpc call to host %s%n"; + private static final String err_host = "Unknown hostname %s%n"; + private static final String err_connect = "Cannot connect to host %s%n"; + private static final String fmt_unknown = "unknown service (%d)"; + + private final HostNameArgument argHost = + new HostNameArgument("host", Argument.MANDATORY, help_host); + + public RpcInfoCommand() { + super(help_super); + registerArguments(argHost); + } + + public static void main(String[] args) throws Exception { + new RpcInfoCommand().execute(args); + } + + public void execute() { + OncRpcPortmapClient client = null; + String hostname = argHost.getValue(); + PrintWriter out = getOutput().getPrintWriter(); + PrintWriter err = getError().getPrintWriter(); + try { + InetAddress host = InetAddress.getByName(hostname); + client = new OncRpcPortmapClient(host, OncRpcProtocols.ONCRPC_UDP); + + OncRpcServerIdent[] servers = client.listServers(); + + out.printf(fmt_list_serv, str_program, str_version, str_protocol, str_port, str_name); + out.println(); + + for (int i = 0; i < servers.length; i++) { + OncRpcServerIdent server = servers[i]; + out.printf(fmt_list_serv, server.program, server.version, + server.protocol == 6 ? str_tcp : str_udp, + server.port, getName(server.program)); + out.println(); + } + } catch (OncRpcException e) { + err.format(err_call, hostname); + exit(1); + } catch (UnknownHostException e) { + err.format(err_host, hostname); + exit(1); + } catch (IOException e) { + err.format(err_connect, hostname); + exit(1); + } finally { + if (client != null) { + try { + client.close(); + } catch (OncRpcException e) { + // Ignore exception on close + } + } + } + } + + private String getName(int program) { + switch (program) { + case 100000: + return str_portmapper; + case 100003: + return str_nfs; + case 100005: + return str_mountd; + case 100021: + return str_nlockmgr; + case 100024: + return str_status; + default: + return String.format(fmt_unknown, program); + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/TcpInoutCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/TcpInoutCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/TcpInoutCommand.java (rev 0) +++ trunk/cli/coreutils/src/commands/org/jnode/command/net/TcpInoutCommand.java 2009-04-29 21:56:54 UTC (rev 5362) @@ -0,0 +1,166 @@ +/* + * $Id$ + * + * Copyright (C) 2003-2009 JNode.org + * + * This library 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 2.1 of the License, or + * (at your option) any later version. + * + * This library 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 this library; If not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.jnode.command.net; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; + +import javax.net.ServerSocketFactory; +import javax.net.SocketFactory; + +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.HostNameArgument; +import org.jnode.shell.syntax.PortNumberArgument; + +/** + * This command establishes a TCP connection to a remote machine, either by + * connecting to it or accepting a remote connection. Once the connection has + * been set up, it sends the command's standard input to the remote connection and + * sends the output from the connection to the command's standard output. + * + * @author quades + * @author cr...@jn... + */ +public class TcpInoutCommand extends AbstractCommand { + // FIXME this command is only useful for testing. What we Really need is + // implementations of TELNET, RSH and SSH protocols (client and + // server-side). + + private static final String help_host = "the hostname of the server to contact"; + private static final String help_port = "the port the server is listening to"; + private static final String help_lport = "the local port we should listen to"; + private static final String help_super = "Set up an interactive TCP connection to a remote machine"; + + private final HostNameArgument argHost; + private final PortNumberArgument argPort; + private final PortNumberArgument argLocalPort; + + private Socket socket; + private CopyThread toThread; + private CopyThread fromThread; + + public TcpInoutCommand() { + super(help_super); + argHost = new HostNameArgument("host", Argument.OPTIONAL, help_host); + argPort = new PortNumberArgument("port", Argument.OPTIONAL, help_port); + argLocalPort = new PortNumberArgument("localPort", Argument.OPTIONAL, help_lport); + registerArguments(argHost, argLocalPort, argPort); + } + + /** + * @param args + */ + public static void main(String[] args) throws Exception { + new TcpInoutCommand().execute(args); + } + + public void execute() throws IOException { + Socket socket; + if (argLocalPort.isSet()) { + int port = argLocalPort.getValue(); + ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(port); + socket = ss.accept(); + } else { + InetAddress host = argHost.getAsInetAddress(); + int port = argPort.getValue(); + socket = SocketFactory.getDefault().createSocket(host, port); + } + InputStream in = getInput().getInputStream(); + OutputStream out = getOutput().getOutputStream(); + PrintWriter err = getError().getPrintWriter(); + toThread = new CopyThread(in, socket.getOutputStream(), err); + fromThread = new CopyThread(socket.getInputStream(), out, err); + + synchronized (this) { + toThread.start(); + fromThread.start(); + try { + wait(); + } catch (InterruptedException e) { + close(null); + } + } + } + + private synchronized void close(CopyThread source) { + if (socket != null) { + try { + socket.close(); + } catch (IOException e) { + // We don't care ... + } + socket = null; + notifyAll(); + } + if (source != toThread) { + toThread.terminate(); + } + if (source != fromThread) { + fromThread.terminate(); + } + } + + private class CopyThread extends Thread { + private final InputStream in; + private final OutputStream out; + private final PrintWriter err; + private boolean terminated; + + CopyThread(InputStream in, OutputStream out, PrintWriter err) { + this.in = in; + this.out = out; + this.err = err; + } + + synchronized void terminate() { + if (!this.terminated) { + interrupt(); + this.terminated = true; + } + } + + public void run() { + try { + while (socket != null) { + int b = in.read(); + if (b == -1) { + break; + } + out.write(b); + } + } catch (IOException ex) { + synchronized (this) { + if (!terminated) { + err.println(ex.getLocalizedMessage()); + } + } + } finally { + close(this); + } + } + } +} Copied: trunk/cli/coreutils/src/commands/org/jnode/command/net/TftpCommand.java (from rev 5361, trunk/net/src/net/org/jnode/net/command/TftpCommand.java) =================================================================== --- trunk/cli/coreutils/src/commands/org/jnode/command/net/TftpCommand.java ... [truncated message content] |