diff --git a/.classpath b/.classpath index 71c7d80..ead61f4 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,7 @@ + @@ -15,11 +16,13 @@ - - + + + + diff --git a/JavaTUN.dll b/JavaTUN.dll index 352922f..6174939 100644 Binary files a/JavaTUN.dll and b/JavaTUN.dll differ diff --git a/fastcopy.dll b/fastcopy.dll new file mode 100644 index 0000000..7e08bef Binary files /dev/null and b/fastcopy.dll differ diff --git a/klalbconfig.json b/klalbconfig.json index bb1b8a5..41027f4 100644 --- a/klalbconfig.json +++ b/klalbconfig.json @@ -3,7 +3,7 @@ "TCPListen" : "0.0.0.0:4565", "UDPListen" : "{UDP}0.0.0.0:4572", "VirtualSocketName" : "KLALB_Stream", - "LineTable":["cn-he-plc-2.ofalias.com:4572"] + "LineTable":["07f4acdef99b.ofalias.net:4572","{UDP}07f4acdef99b.ofalias.net:4572"] }, {"Type":"SocketBridge" , "Listen" : "0.0.0.0:4572", diff --git a/lib/JavaTUN.jar b/lib/JavaTUN.jar index e0dc66e..b954a82 100644 Binary files a/lib/JavaTUN.jar and b/lib/JavaTUN.jar differ diff --git a/lib/disruptor-4.0.0-javadoc.jar b/lib/disruptor-4.0.0-javadoc.jar new file mode 100644 index 0000000..81bc63b Binary files /dev/null and b/lib/disruptor-4.0.0-javadoc.jar differ diff --git a/lib/disruptor-4.0.0-sources.jar b/lib/disruptor-4.0.0-sources.jar new file mode 100644 index 0000000..bcde337 Binary files /dev/null and b/lib/disruptor-4.0.0-sources.jar differ diff --git a/lib/disruptor-4.0.0.jar b/lib/disruptor-4.0.0.jar new file mode 100644 index 0000000..d3ae6e4 Binary files /dev/null and b/lib/disruptor-4.0.0.jar differ diff --git a/src/org/kne/acclerate/FastLib.java b/src/org/kne/acclerate/FastLib.java deleted file mode 100644 index eb09572..0000000 --- a/src/org/kne/acclerate/FastLib.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.kne.acclerate; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; - -import org.kne.io.Task; - -public class FastLib { - private static int cores=Runtime.getRuntime().availableProcessors(); - private static ExecutorService exc=Executors.newFixedThreadPool(cores,new ThreadFactory() { - - @Override - public Thread newThread(Runnable r) { - Thread t=new Thread(r); - t.setDaemon(true); - t.setPriority(Thread.MAX_PRIORITY); - return t; - } - }); - public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) { - if(length<2000) { - System.arraycopy(src, srcPos, dest, destPos, length); - }else { - int count=length/cores; - int mod=length%cores; - Task[]tsk=new Task[cores]; - for (int i = 0; i < cores; i++) { - int j=i; - Task t=new Task() { - - @Override - protected void runTask() { - System.arraycopy(src, srcPos+count*j, dest, destPos+count*j, count); - } - }; - exc.execute(t); - tsk[i]=t; - } - System.arraycopy(src, srcPos+count*cores, dest, destPos+count*cores, mod); - for (int i = 0; i < tsk.length; i++) { - tsk[i].waitfortask(); - } - } - } -} diff --git a/src/org/kne/cloud/klalb/uitool/ButtonSettingItem.java b/src/org/kne/cloud/klalb/uitool/ButtonSettingItem.java new file mode 100644 index 0000000..7dea338 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/ButtonSettingItem.java @@ -0,0 +1,41 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Font; +import java.awt.font.TextAttribute; +import java.util.Collections; +import java.util.Map; + +import javax.swing.JButton; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import javax.swing.SwingConstants; + +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class ButtonSettingItem extends SettingItem { + protected JButton button; + + + public JButton getButton() { + return button; + } + public ButtonSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } +/** + * @wbp.parser.constructor + */ + public ButtonSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + button = new JButton(UIEnv.getRsb().getString("clicktoopen")+">>"); + button.setHorizontalAlignment(SwingConstants.RIGHT); + button.setFont(button.getFont().deriveFont(Map.of(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON))); + getPanel().add(button, BorderLayout.EAST); + button.setBorder(null); + button.setOpaque(false); + button.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + } + +} diff --git a/src/org/kne/cloud/klalb/uitool/CheckBoxSettingItem.java b/src/org/kne/cloud/klalb/uitool/CheckBoxSettingItem.java new file mode 100644 index 0000000..c7ca07c --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/CheckBoxSettingItem.java @@ -0,0 +1,37 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.SwingConstants; + +import org.kne.cloud.klalb.uitool.SettingItem; +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class CheckBoxSettingItem extends SettingItem { +protected JCheckBox button; + + + public JCheckBox getCheckBox() { + return button; + } + public CheckBoxSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } +/** + * @wbp.parser.constructor + */ + public CheckBoxSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + button = new JCheckBox(); + button.setHorizontalAlignment(SwingConstants.RIGHT); + getPanel().add(button, BorderLayout.CENTER); + button.setBorder(null); + button.setOpaque(false); + button.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/ComboSettingItem.java b/src/org/kne/cloud/klalb/uitool/ComboSettingItem.java new file mode 100644 index 0000000..3506064 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/ComboSettingItem.java @@ -0,0 +1,33 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Font; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import javax.swing.SwingConstants; +import org.kne.cloud.network.klalb.ui.UIEnv; +import javax.swing.JComboBox; + +public class ComboSettingItem extends SettingItem { + + + private JComboBox comboBox; + public JComboBox getComboBox() { + return comboBox; + } + public ComboSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w, h); + } + /** + * @wbp.parser.constructor + */ + public ComboSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + label.setForeground(Color.GRAY); + + comboBox = new JComboBox(); + comboBox.setOpaque(false); + getPanel().add(comboBox, BorderLayout.CENTER); + } + +} diff --git a/src/org/kne/cloud/klalb/uitool/CrashReport.java b/src/org/kne/cloud/klalb/uitool/CrashReport.java new file mode 100644 index 0000000..6b212b9 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/CrashReport.java @@ -0,0 +1,86 @@ +package org.kne.cloud.klalb.uitool; + +import javax.swing.JDialog; +import javax.swing.JFrame; +import java.awt.Dimension; +import java.awt.TextArea; +import java.awt.BorderLayout; +import java.awt.Panel; +import java.awt.Window; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingConstants; + +import org.kne.cloud.network.klalb.ui.UIEnv; + +import javax.swing.ImageIcon; +import java.awt.Label; +import java.awt.Color; +import java.awt.Font; +import java.awt.TextField; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Random; + +public class CrashReport extends JDialog{ + private JLabel name; + private TextField type; + private JTextArea stack; + public CrashReport(Window parent ,boolean modal) { + super(parent); + setModal(modal); + setTitle("错误"); + setIconImage(UIEnv.getIcon()); + setSize(500, 400); + setLocationRelativeTo(null); + stack = new JTextArea(); + stack.setEditable(false); + getContentPane().add(new JScrollPane(stack), BorderLayout.CENTER); + + Panel panel = new Panel(); + panel.setPreferredSize(new Dimension(500, 100)); + getContentPane().add(panel, BorderLayout.NORTH); + panel.setLayout(null); + + JLabel lblNewLabel = new JLabel(""); + lblNewLabel.setIcon(new ImageIcon(CrashReport.class.getResource("/assets/error.jpg"))); + lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER); + lblNewLabel.setBounds(10, 10, 80, 80); + panel.add(lblNewLabel); + + name = new JLabel(""); + name.setFont(new Font("宋体", Font.PLAIN, 30)); + name.setForeground(Color.RED); + name.setBounds(96, 10, 378, 33); + panel.add(name); + + type = new TextField(); + type.setEditable(false); + type.setBounds(96, 67, 378, 23); + panel.add(type); + + fny = new JLabel("...?"); + fny.setFont(new Font("MS Song", Font.PLAIN, 10)); + getContentPane().add(fny, BorderLayout.SOUTH); + } + String []s=new String[]{"鎴戜滑鍥㈤槦鍙湁涓�涓▼搴忓憳", + "鎯虫洿鏂帮紝娌¢棬", + "鎴戜滑鐨勬湇鍔″櫒鐪熺殑鏄笓涓氣�滃埌瀹垛�濅簡", + "杩炴帴宸蹭涪澶憋細涓嶅幓鍋氬惎鍔ㄥ櫒灏卞幓濂宠锛屼笉鍘诲コ瑁呭氨鍘诲仛鍚姩鍣�", + "鍦熻眴鏈嶅姟鍣ㄥ張鍙戣娊浜�" + }; + private JLabel fny; + public void report(Throwable e,String t){ + e.printStackTrace(); + name.setText(t); + type.setText(e.getClass().getName()); + StringWriter sw=new StringWriter(); + PrintWriter pw=new PrintWriter(sw); + e.printStackTrace(pw); + pw.close(); + stack.setText(sw.toString());fny.setText(s[new Random().nextInt(s.length)]); + setVisible(true); + + } +} diff --git a/src/org/kne/cloud/klalb/uitool/KNEProgressBarUI.java b/src/org/kne/cloud/klalb/uitool/KNEProgressBarUI.java new file mode 100644 index 0000000..a2b9e42 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/KNEProgressBarUI.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + +package org.kne.cloud.klalb.uitool; + +import javax.swing.*; +import javax.swing.plaf.*; +import javax.swing.plaf.basic.*; +import java.awt.*; + +/** + * The Metal implementation of ProgressBarUI. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeans™ + * has been added to the java.beans package. + * Please see {@link java.beans.XMLEncoder}. + * + * @author Michael C. Albers + */ +public class KNEProgressBarUI extends BasicProgressBarUI { + + // private Rectangle innards; + // private Rectangle box; + + public static ComponentUI createUI(JComponent c) { + return new KNEProgressBarUI(); + } + + /** + * Draws a bit of special highlighting on the progress bar. + * The core painting is deferred to the BasicProgressBar's + * paintDeterminate method. + * @since 1.4 + */ + public void paintDeterminate(Graphics g, JComponent c) { + super.paintDeterminate(g,c); + + + } + + /** + * Draws a bit of special highlighting on the progress bar + * and bouncing box. + * The core painting is deferred to the BasicProgressBar's + * paintIndeterminate method. + * @since 1.4 + */ + public void paintIndeterminate(Graphics g, JComponent c) { + super.paintIndeterminate(g, c); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/ListSettingItem.java b/src/org/kne/cloud/klalb/uitool/ListSettingItem.java new file mode 100644 index 0000000..2aa3fc7 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/ListSettingItem.java @@ -0,0 +1,150 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.ListModel; + +import java.awt.BorderLayout; +import javax.swing.SwingConstants; +import org.kne.cloud.network.klalb.ui.UIEnv; +import java.awt.FlowLayout; + +public abstract class ListSettingItem extends SettingItem { + /** + * + */ + private static final long serialVersionUID = 1L; + + protected JList list; + + private Consumer storeRecall; + public JList getList() { + return list; + } + public ListSettingItem(String text,int w,int h,XDefaultListModellm) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h,lm); + } +/** + * @wbp.parser.constructor + */ + public ListSettingItem(String text, Font deriveFont,int w,int h,XDefaultListModel lm) { + super(text,deriveFont,w,h); + list = new JList(lm); + JScrollPane js=new JScrollPane(list); + js.getViewport().setOpaque(false); + js.setOpaque(false); + js.setBackground(new Color(0,0,0,0)); + getPanel().add(js, BorderLayout.CENTER); + list.setBorder(null); + list.setOpaque(false); + list.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + + Dimension dss=new Dimension(25,25); + JButton jbt3x=new JButton(); + jbt3x.setToolTipText(UIEnv.getRsb().getString("add")); + try { + jbt3x.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/add.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH))); + } catch (IOException e) { + e.printStackTrace(); + } + jbt3x.setSize(dss); + jbt3x.setPreferredSize(dss); + jbt3x.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + T x=createEmpty(); + runEdit(x); + } + }); + JButton jbedit=new JButton(); + jbedit.setToolTipText(UIEnv.getRsb().getString("edit")); + try { + jbedit.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/edit-fill.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH))); + } catch (IOException e) { + e.printStackTrace(); + } + jbedit.setSize(dss); + jbedit.setPreferredSize(dss); + jbedit.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + T val=list.getSelectedValue(); + if(val!=null) + runEdit(val); + } + }); + + JButton jbt4x=new JButton(); + jbt4x.setToolTipText(UIEnv.getRsb().getString("remove")); + try { + jbt4x.setIcon(new ImageIcon(ImageIO .read(ListSettingItem.class.getResourceAsStream("/assets/delete-bin-fill.png")).getScaledInstance(dss.width-2, dss.height-2, Image.SCALE_SMOOTH))); + } catch (IOException e) { + e.printStackTrace(); + } + jbt4x.setSize(dss); + jbt4x.setPreferredSize(dss); + jbt4x.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + int v=list.getSelectedIndex(); + if(v>=0) { + lm.remove(v); + if(storeRecall!=null) + storeRecall.accept(list.getSelectedValue()); + } + } + }); + JPanel jp=new JPanel(); + jp.setPreferredSize(new Dimension(30, h)); + FlowLayout flowLayout = (FlowLayout) jp.getLayout(); + flowLayout.setAlignment(FlowLayout.TRAILING); + jp.setOpaque(false); + getPanel().add(jp,BorderLayout.EAST); + jp.add(jbt3x); + jp.add(jbedit); + jp.add(jbt4x); + } + abstract protected void runEdit(T val) ; +abstract protected T createEmpty() ; +public void doAdd(T v) { + boolean b=true; + for (int i = 0; i < list.getModel().getSize(); i++) { + if(list.getModel().getElementAt(i)==v) { + b=false; + break; + } + } + if(b) + ((XDefaultListModel) list.getModel()).addElement(v); + repaint(); + if(storeRecall!=null) + storeRecall.accept(list.getSelectedValue()); +} +public Consumer getStoreRecall() { + return storeRecall; +} +public void setStoreRecall(Consumer storeRecall) { + this.storeRecall = storeRecall; +} + +} diff --git a/src/org/kne/cloud/klalb/uitool/PathInput.java b/src/org/kne/cloud/klalb/uitool/PathInput.java new file mode 100644 index 0000000..d3ad8f9 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/PathInput.java @@ -0,0 +1,134 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.util.function.Consumer; +import java.util.function.Supplier; +import javax.swing.*; + +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class PathInput extends JDialog { + private JTextField textField; + private boolean checkfile=true; + private boolean isdir=false; + protected JFileChooser jfc; + private Consumer al; + public Consumer getAl() { + return al; + } + + public void setAl(Consumer al) { + this.al = al; + } + + public PathInput(Window d){ + super(d); + setResizable(false); + setModal(true); + setSize(500, 110); + setLocationRelativeTo(d); + + setIconImage(UIEnv.getIcon()); + + textField = new JTextField(); + textField.setPreferredSize(new Dimension(400,80)); + textField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + getContentPane().add(textField, BorderLayout.CENTER); + textField.setColumns(10); + + JPanel panel = new JPanel(); + getContentPane().add(panel, BorderLayout.SOUTH); + + JButton btnok = new JButton(UIEnv.getRsb().getString("ok")); + UIEnv.defbut(btnok); + panel.add(btnok); + btnok.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + File x=new File(textField.getText()); + if(!checkfile){ + if(isdir){ + x.mkdirs(); + }else{ + try { + x.createNewFile(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + al.accept(x); + setVisible(false); + return; + } + if(x.exists()){ + al.accept(x); + setVisible(false); + }else{ + JOptionPane.showMessageDialog(PathInput.this, UIEnv.getRsb().getString("filenotexist"), UIEnv.getRsb().getString("error"), JOptionPane.ERROR_MESSAGE); + } + } + }); + JButton btnNewButton_1 = new JButton(UIEnv.getRsb().getString("browse")); + UIEnv.defbut(btnNewButton_1); + panel.add(btnNewButton_1); + btnNewButton_1.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if(jfc.showOpenDialog(PathInput.this)==jfc.APPROVE_OPTION){ + textField.setText(jfc.getSelectedFile().toString()); + } + /*File f=choose.get(); + if(f!=null){ + textField.setText(f.toString()); + }*/ + } + }); + JButton button = new JButton(UIEnv.getRsb().getString("cancel")); + UIEnv.defbut(button); + panel.add(button); + button.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + + + jfc=new JFileChooser(); + jfc.setMultiSelectionEnabled(false); + } + + + public JTextField getTextField() { + return textField; + } + + public JFileChooser getJfc() { + return jfc; + } + + public boolean isCheckfile() { + return checkfile; + } + public void setCheckfile(boolean checkfile) { + this.checkfile = checkfile; + } + public boolean isIsdir() { + return isdir; + } + public void setIsdir(boolean isdir) { + this.isdir = isdir; + if(isdir) { + jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + }else { + jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); + } + } +} diff --git a/src/org/kne/cloud/klalb/uitool/RadioButtonSettingItem.java b/src/org/kne/cloud/klalb/uitool/RadioButtonSettingItem.java new file mode 100644 index 0000000..b4567ba --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/RadioButtonSettingItem.java @@ -0,0 +1,38 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JRadioButton; +import javax.swing.SwingConstants; + +import org.kne.cloud.klalb.uitool.SettingItem; +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class RadioButtonSettingItem extends SettingItem { +protected JRadioButton button; + + + public JRadioButton getRadioButton() { + return button; + } + public RadioButtonSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } +/** + * @wbp.parser.constructor + */ + public RadioButtonSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + button = new JRadioButton(); + button.setHorizontalAlignment(SwingConstants.RIGHT); + getPanel().add(button, BorderLayout.CENTER); + button.setBorder(null); + button.setOpaque(false); + button.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/SettingItem.java b/src/org/kne/cloud/klalb/uitool/SettingItem.java new file mode 100644 index 0000000..ccc2a74 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/SettingItem.java @@ -0,0 +1,52 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.border.LineBorder; + +import org.kne.cloud.network.klalb.ui.UIEnv; + +import javax.swing.SwingConstants; + +import javax.swing.SpringLayout; + +public class SettingItem extends JPanel { + protected JLabel label; + private JPanel sub; + + public JLabel getLabel() { + return label; + } + public SettingItem(String text,int w,int h){ + this(text,UIEnv.getFont().deriveFont(15.0f),w,h); + } + public JPanel getPanel(){ + return sub; + } + /** + * @wbp.parser.constructor + */ + public SettingItem(String text,Font f,int w,int h){ + setSize(w, h); + setPreferredSize(new Dimension(w, h)); + setBackground(UIEnv.getHalfTransparentDefaultColor()); + SpringLayout springLayout = new SpringLayout(); + setLayout(springLayout); + //setOpaque(false); + sub = new JPanel(); + springLayout.putConstraint(SpringLayout.NORTH, sub, 0, SpringLayout.NORTH, this); + springLayout.putConstraint(SpringLayout.WEST, sub, 20, SpringLayout.WEST, this); + springLayout.putConstraint(SpringLayout.SOUTH, sub, 0, SpringLayout.SOUTH, this); + springLayout.putConstraint(SpringLayout.EAST, sub, -20, SpringLayout.EAST, this); + sub.setOpaque(false); + add(sub); + sub.setLayout(new BorderLayout(5, 0)); + label = new JLabel(text); + label.setFont(f); + sub.add(label, BorderLayout.WEST); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/TextAreaSettingItem.java b/src/org/kne/cloud/klalb/uitool/TextAreaSettingItem.java new file mode 100644 index 0000000..9765e6c --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/TextAreaSettingItem.java @@ -0,0 +1,41 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Font; +import javax.swing.JButton; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import javax.swing.SwingConstants; +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class TextAreaSettingItem extends SettingItem { + protected JTextArea textarea; + + + public JTextArea getTextArea() { + return textarea; + } + public TextAreaSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } +/** + * @wbp.parser.constructor + */ + public TextAreaSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + textarea = new JTextArea(); + JScrollPane sp=new JScrollPane(textarea); + sp.getViewport().setOpaque(false); + sp.setOpaque(false); + sp.setBackground(new Color(0,0,0,0)); + getPanel().add(sp, BorderLayout.CENTER); + textarea.setBorder(null); + textarea.setOpaque(false); + textarea.setBackground(new Color(0,0,0,0)); + //textarea.setBackground(UIEnv.getDefaultcolor()); + label.setForeground(Color.GRAY); + } + +} diff --git a/src/org/kne/cloud/klalb/uitool/TextButtonSettingItem.java b/src/org/kne/cloud/klalb/uitool/TextButtonSettingItem.java new file mode 100644 index 0000000..c95dd6a --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/TextButtonSettingItem.java @@ -0,0 +1,49 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Font; +import java.awt.font.TextAttribute; +import java.util.Map; + +import javax.swing.JButton; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import javax.swing.SwingConstants; +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class TextButtonSettingItem extends SettingItem { + protected JTextField textField; + protected JButton button; + + public JButton getButton() { + return button; + } + public JTextField getTextField() { + return textField; + } + public TextButtonSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } + /** + * @wbp.parser.constructor + */ + public TextButtonSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + BorderLayout borderLayout = (BorderLayout) getPanel().getLayout(); + textField = new JTextField(); + textField.setHorizontalAlignment(SwingConstants.RIGHT); + getPanel().add(textField, BorderLayout.CENTER); + textField.setColumns(10); + textField.setBorder(null); + textField.setOpaque(false); + textField.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + + button = new JButton(); + getPanel().add(button, BorderLayout.EAST); + button.setFont(button.getFont().deriveFont(Map.of(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON))); + button.setBorder(null); + button.setOpaque(false); + button.setBackground(new Color(0,0,0,0)); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/TextSettingItem.java b/src/org/kne/cloud/klalb/uitool/TextSettingItem.java new file mode 100644 index 0000000..296a7eb --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/TextSettingItem.java @@ -0,0 +1,35 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Color; +import java.awt.Font; +import javax.swing.JTextField; +import java.awt.BorderLayout; +import javax.swing.SwingConstants; +import org.kne.cloud.network.klalb.ui.UIEnv; + +public class TextSettingItem extends SettingItem { + protected JTextField textField; + + + public JTextField getTextField() { + return textField; + } + public TextSettingItem(String text,int w,int h) { + this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h); + } + /** + * @wbp.parser.constructor + */ + public TextSettingItem(String text, Font deriveFont,int w,int h) { + super(text,deriveFont,w,h); + textField = new JTextField(); + textField.setHorizontalAlignment(SwingConstants.RIGHT); + getPanel().add(textField, BorderLayout.CENTER); + textField.setColumns(10); + textField.setBorder(null); + textField.setOpaque(false); + textField.setBackground(new Color(0,0,0,0)); + label.setForeground(Color.GRAY); + } + +} diff --git a/src/org/kne/cloud/klalb/uitool/XAbstractListModel.java b/src/org/kne/cloud/klalb/uitool/XAbstractListModel.java new file mode 100644 index 0000000..c91a813 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/XAbstractListModel.java @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.kne.cloud.klalb.uitool; + +import javax.swing.ListModel; +import javax.swing.event.*; +import java.io.Serializable; +import java.util.EventListener; + +/** + * The abstract definition for the data model that provides + * a List with its contents. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeans + * has been added to the java.beans package. + * Please see {@link java.beans.XMLEncoder}. + * + * @param the type of the elements of this model + * + * @author Hans Muller + * @since 1.2 + */ +@SuppressWarnings("serial") // Same-version serialization only +public abstract class XAbstractListModel implements ListModel, Serializable +{ + /** + * The listener list. + */ + protected EventListenerList listenerList = new EventListenerList(); + + /** + * Constructor for subclasses to call. + */ + protected XAbstractListModel() {} + + /** + * Adds a listener to the list that's notified each time a change + * to the data model occurs. + * + * @param l the ListDataListener to be added + */ + public void addListDataListener(ListDataListener l) { + listenerList.add(ListDataListener.class, l); + } + + + /** + * Removes a listener from the list that's notified each time a + * change to the data model occurs. + * + * @param l the ListDataListener to be removed + */ + public void removeListDataListener(ListDataListener l) { + listenerList.remove(ListDataListener.class, l); + } + + + /** + * Returns an array of all the list data listeners + * registered on this AbstractListModel. + * + * @return all of this model's ListDataListeners, + * or an empty array if no list data listeners + * are currently registered + * + * @see #addListDataListener + * @see #removeListDataListener + * + * @since 1.4 + */ + public ListDataListener[] getListDataListeners() { + return listenerList.getListeners(ListDataListener.class); + } + + + /** + * AbstractListModel subclasses must call this method + * after + * one or more elements of the list change. The changed elements + * are specified by the closed interval index0, index1 -- the endpoints + * are included. Note that + * index0 need not be less than or equal to index1. + * + * @param source the ListModel that changed, typically "this" + * @param index0 one end of the new interval + * @param index1 the other end of the new interval + * @see EventListenerList + * @see XDefaultListModel + */ + protected void fireContentsChanged(Object source, int index0, int index1) + { + Object[] listeners = listenerList.getListenerList(); + ListDataEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ListDataListener.class) { + if (e == null) { + e = new ListDataEvent(source, ListDataEvent.CONTENTS_CHANGED, index0, index1); + } + ((ListDataListener)listeners[i+1]).contentsChanged(e); + } + } + } + + + /** + * AbstractListModel subclasses must call this method + * after + * one or more elements are added to the model. The new elements + * are specified by a closed interval index0, index1 -- the enpoints + * are included. Note that + * index0 need not be less than or equal to index1. + * + * @param source the ListModel that changed, typically "this" + * @param index0 one end of the new interval + * @param index1 the other end of the new interval + * @see EventListenerList + * @see XDefaultListModel + */ + protected void fireIntervalAdded(Object source, int index0, int index1) + { + Object[] listeners = listenerList.getListenerList(); + ListDataEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ListDataListener.class) { + if (e == null) { + e = new ListDataEvent(source, ListDataEvent.INTERVAL_ADDED, index0, index1); + } + ((ListDataListener)listeners[i+1]).intervalAdded(e); + } + } + } + + + /** + * AbstractListModel subclasses must call this method + * after one or more elements are removed from the model. + * index0 and index1 are the end points + * of the interval that's been removed. Note that index0 + * need not be less than or equal to index1. + * + * @param source the ListModel that changed, typically "this" + * @param index0 one end of the removed interval, + * including index0 + * @param index1 the other end of the removed interval, + * including index1 + * @see EventListenerList + * @see XDefaultListModel + */ + protected void fireIntervalRemoved(Object source, int index0, int index1) + { + Object[] listeners = listenerList.getListenerList(); + ListDataEvent e = null; + + for (int i = listeners.length - 2; i >= 0; i -= 2) { + if (listeners[i] == ListDataListener.class) { + if (e == null) { + e = new ListDataEvent(source, ListDataEvent.INTERVAL_REMOVED, index0, index1); + } + ((ListDataListener)listeners[i+1]).intervalRemoved(e); + } + } + } + + /** + * Returns an array of all the objects currently registered as + * FooListeners + * upon this model. + * FooListeners + * are registered using the addFooListener method. + *

+ * You can specify the listenerType argument + * with a class literal, such as FooListener.class. + * For example, you can query a list model + * m + * for its list data listeners + * with the following code: + * + *

ListDataListener[] ldls = (ListDataListener[])(m.getListeners(ListDataListener.class));
+ * + * If no such listeners exist, + * this method returns an empty array. + * + * @param the type of {@code EventListener} class being requested + * @param listenerType the type of listeners requested; + * this parameter should specify an interface + * that descends from java.util.EventListener + * @return an array of all objects registered as + * FooListeners + * on this model, + * or an empty array if no such + * listeners have been added + * @exception ClassCastException if listenerType doesn't + * specify a class or interface that implements + * java.util.EventListener + * + * @see #getListDataListeners + * + * @since 1.3 + */ + public T[] getListeners(Class listenerType) { + return listenerList.getListeners(listenerType); + } +} diff --git a/src/org/kne/cloud/klalb/uitool/XButton.java b/src/org/kne/cloud/klalb/uitool/XButton.java new file mode 100644 index 0000000..8967699 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/XButton.java @@ -0,0 +1,46 @@ +package org.kne.cloud.klalb.uitool; + +import java.awt.Graphics; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; + +public class XButton extends JButton{ + /** + * + */ + public XButton() { + super(); + super.setContentAreaFilled(false); + } + + public XButton(Action a) { + super(a); + super.setContentAreaFilled(false); + } + + public XButton(Icon icon) { + super(icon); + super.setContentAreaFilled(false); + } + + public XButton(String text, Icon icon) { + super(text, icon); + super.setContentAreaFilled(false); + } + + public XButton(String text) { + super(text); + super.setContentAreaFilled(false); + } + + + + @Override + public void paint(Graphics g) { + g.setColor(getBackground()); + g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 20, 20); + super.paint(g); + } + +} diff --git a/src/org/kne/cloud/klalb/uitool/XDefaultListModel.java b/src/org/kne/cloud/klalb/uitool/XDefaultListModel.java new file mode 100644 index 0000000..4832024 --- /dev/null +++ b/src/org/kne/cloud/klalb/uitool/XDefaultListModel.java @@ -0,0 +1,584 @@ +/* + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.kne.cloud.klalb.uitool; + +import java.util.Vector; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.Collection; +import java.util.Enumeration; + + +/** + * This class loosely implements the {@code java.util.Vector} + * API, in that it implements the 1.1.x version of + * {@code java.util.Vector}, has no collection class support, + * and notifies the {@code ListDataListener}s when changes occur. + * Presently it delegates to a {@code Vector}, + * in a future release it will be a real Collection implementation. + *

+ * Warning: + * Serialized objects of this class will not be compatible with + * future Swing releases. The current serialization support is + * appropriate for short term storage or RMI between applications running + * the same version of Swing. As of 1.4, support for long term storage + * of all JavaBeans + * has been added to the {@code java.beans} package. + * Please see {@link java.beans.XMLEncoder}. + * + * @param the type of the elements of this model + * + * @author Hans Muller + * @since 1.2 + */ +@SuppressWarnings("serial") // Same-version serialization only +public class XDefaultListModel extends XAbstractListModel implements Externalizable +{ + private Vector delegate = new Vector(); + + /** + * Constructs a {@code DefaultListModel}. + */ + public XDefaultListModel() {} + + /** + * Returns the number of components in this list. + *

+ * This method is identical to {@code size}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + * This method exists in conjunction with {@code setSize} so that + * {@code size} is identifiable as a JavaBean property. + * + * @return the number of components in this list + * @see #size() + */ + public int getSize() { + return delegate.size(); + } + + /** + * Returns the component at the specified index. + *

+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code get(int)}, which implements the {@code List} + * interface defined in the 1.2 Collections framework. + *
+ * @param index an index into this list + * @return the component at the specified index + * @throws ArrayIndexOutOfBoundsException if the {@code index} + * is negative or greater than the current size of this + * list + * @see #get(int) + */ + public E getElementAt(int index) { + return delegate.elementAt(index); + } + + /** + * Copies the components of this list into the specified array. + * The array must be big enough to hold all the objects in this list, + * else an {@code IndexOutOfBoundsException} is thrown. + * + * @param anArray the array into which the components get copied + * @see Vector#copyInto(Object[]) + */ + public void copyInto(Object[] anArray) { + delegate.copyInto(anArray); + } + + /** + * Trims the capacity of this list to be the list's current size. + * + * @see Vector#trimToSize() + */ + public void trimToSize() { + delegate.trimToSize(); + } + + /** + * Increases the capacity of this list, if necessary, to ensure + * that it can hold at least the number of components specified by + * the minimum capacity argument. + * + * @param minCapacity the desired minimum capacity + * @see Vector#ensureCapacity(int) + */ + public void ensureCapacity(int minCapacity) { + delegate.ensureCapacity(minCapacity); + } + + /** + * Sets the size of this list. + * + * @param newSize the new size of this list + * @see Vector#setSize(int) + */ + public void setSize(int newSize) { + int oldSize = delegate.size(); + delegate.setSize(newSize); + if (oldSize > newSize) { + fireIntervalRemoved(this, newSize, oldSize-1); + } + else if (oldSize < newSize) { + fireIntervalAdded(this, oldSize, newSize-1); + } + } + + /** + * Returns the current capacity of this list. + * + * @return the current capacity + * @see Vector#capacity() + */ + public int capacity() { + return delegate.capacity(); + } + + /** + * Returns the number of components in this list. + * + * @return the number of components in this list + * @see Vector#size() + */ + public int size() { + return delegate.size(); + } + + /** + * Tests whether this list has any components. + * + * @return {@code true} if and only if this list has + * no components, that is, its size is zero; + * {@code false} otherwise + * @see Vector#isEmpty() + */ + public boolean isEmpty() { + return delegate.isEmpty(); + } + + /** + * Returns an enumeration of the components of this list. + * + * @return an enumeration of the components of this list + * @see Vector#elements() + */ + public Enumeration elements() { + return delegate.elements(); + } + + /** + * Tests whether the specified object is a component in this list. + * + * @param elem an object + * @return {@code true} if the specified object + * is the same as a component in this list + * @see Vector#contains(Object) + */ + public boolean contains(Object elem) { + return delegate.contains(elem); + } + + /** + * Searches for the first occurrence of {@code elem}. + * + * @param elem an object + * @return the index of the first occurrence of the argument in this + * list; returns {@code -1} if the object is not found + * @see Vector#indexOf(Object) + */ + public int indexOf(Object elem) { + return delegate.indexOf(elem); + } + + /** + * Searches for the first occurrence of {@code elem}, beginning + * the search at {@code index}. + * + * @param elem the desired component + * @param index the index from which to begin searching + * @return the index where the first occurrence of {@code elem} + * is found after {@code index}; returns {@code -1} + * if the {@code elem} is not found in the list + * @see Vector#indexOf(Object,int) + */ + public int indexOf(Object elem, int index) { + return delegate.indexOf(elem, index); + } + + /** + * Returns the index of the last occurrence of {@code elem}. + * + * @param elem the desired component + * @return the index of the last occurrence of {@code elem} + * in the list; returns {@code elem} if the object is not found + * @see Vector#lastIndexOf(Object) + */ + public int lastIndexOf(Object elem) { + return delegate.lastIndexOf(elem); + } + + /** + * Searches backwards for {@code elem}, starting from the + * specified index, and returns an index to it. + * + * @param elem the desired component + * @param index the index to start searching from + * @return the index of the last occurrence of the {@code elem} + * in this list at position less than {@code index}; + * returns {@code -1} if the object is not found + * @see Vector#lastIndexOf(Object,int) + */ + public int lastIndexOf(Object elem, int index) { + return delegate.lastIndexOf(elem, index); + } + + /** + * Returns the component at the specified index. + *
+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code get(int)}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + *
+ * + * @param index an index into this list + * @return the component at the specified index + * @throws ArrayIndexOutOfBoundsException if the index + * is negative or not less than the size of the list + * @see #get(int) + * @see Vector#elementAt(int) + */ + public E elementAt(int index) { + return delegate.elementAt(index); + } + + /** + * Returns the first component of this list. + * @return the first component of this list + * @see Vector#firstElement() + * @throws java.util.NoSuchElementException if this + * vector has no components + */ + public E firstElement() { + return delegate.firstElement(); + } + + /** + * Returns the last component of the list. + * + * @return the last component of the list + * @see Vector#lastElement() + * @throws java.util.NoSuchElementException if this vector + * has no components + */ + public E lastElement() { + return delegate.lastElement(); + } + + /** + * Sets the component at the specified {@code index} of this + * list to be the specified element. The previous component at that + * position is discarded. + *
+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code set(int,Object)}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + *
+ * + * @param element what the component is to be set to + * @param index the specified index + * @throws ArrayIndexOutOfBoundsException if the index is invalid + * @see #set(int,Object) + * @see Vector#setElementAt(Object,int) + */ + public void setElementAt(E element, int index) { + delegate.setElementAt(element, index); + fireContentsChanged(this, index, index); + } + + /** + * Deletes the component at the specified index. + *
+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code remove(int)}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + *
+ * + * @param index the index of the object to remove + * @see #remove(int) + * @see Vector#removeElementAt(int) + * @throws ArrayIndexOutOfBoundsException if the index is invalid + */ + public void removeElementAt(int index) { + delegate.removeElementAt(index); + fireIntervalRemoved(this, index, index); + } + + /** + * Inserts the specified element as a component in this list at the + * specified index. + *
+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code add(int,Object)}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + *
+ * + * @param element the component to insert + * @param index where to insert the new component + * @exception ArrayIndexOutOfBoundsException if the index was invalid + * @see #add(int,Object) + * @see Vector#insertElementAt(Object,int) + */ + public void insertElementAt(E element, int index) { + delegate.insertElementAt(element, index); + fireIntervalAdded(this, index, index); + } + + /** + * Adds the specified component to the end of this list. + * + * @param element the component to be added + * @see Vector#addElement(Object) + */ + public void addElement(E element) { + int index = delegate.size(); + delegate.addElement(element); + fireIntervalAdded(this, index, index); + } + + /** + * Removes the first (lowest-indexed) occurrence of the argument + * from this list. + * + * @param obj the component to be removed + * @return {@code true} if the argument was a component of this + * list; {@code false} otherwise + * @see Vector#removeElement(Object) + */ + public boolean removeElement(Object obj) { + int index = indexOf(obj); + boolean rv = delegate.removeElement(obj); + if (index >= 0) { + fireIntervalRemoved(this, index, index); + } + return rv; + } + + + /** + * Removes all components from this list and sets its size to zero. + *
+ * Note: Although this method is not deprecated, the preferred + * method to use is {@code clear}, which implements the + * {@code List} interface defined in the 1.2 Collections framework. + *
+ * + * @see #clear() + * @see Vector#removeAllElements() + */ + public void removeAllElements() { + int index1 = delegate.size()-1; + delegate.removeAllElements(); + if (index1 >= 0) { + fireIntervalRemoved(this, 0, index1); + } + } + + + /** + * Returns a string that displays and identifies this + * object's properties. + * + * @return a String representation of this object + */ + public String toString() { + return delegate.toString(); + } + + + /* The remaining methods are included for compatibility with the + * Java 2 platform Vector class. + */ + + /** + * Returns an array containing all of the elements in this list in the + * correct order. + * + * @return an array containing the elements of the list + * @see Vector#toArray() + */ + public Object[] toArray() { + Object[] rv = new Object[delegate.size()]; + delegate.copyInto(rv); + return rv; + } + + /** + * Returns the element at the specified position in this list. + * + * @param index index of element to return + * @return the element at the specified position in this list + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public E get(int index) { + return delegate.elementAt(index); + } + + /** + * Replaces the element at the specified position in this list with the + * specified element. + * + * @param index index of element to replace + * @param element element to be stored at the specified position + * @return the element previously at the specified position + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public E set(int index, E element) { + E rv = delegate.elementAt(index); + delegate.setElementAt(element, index); + fireContentsChanged(this, index, index); + return rv; + } + + /** + * Inserts the specified element at the specified position in this list. + * + * @param index index at which the specified element is to be inserted + * @param element element to be inserted + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index > size()}) + */ + public void add(int index, E element) { + delegate.insertElementAt(element, index); + fireIntervalAdded(this, index, index); + } + + /** + * Removes the element at the specified position in this list. + * Returns the element that was removed from the list + * + * @param index the index of the element to removed + * @return the element previously at the specified position + * @throws ArrayIndexOutOfBoundsException if the index is out of range + * ({@code index < 0 || index >= size()}) + */ + public E remove(int index) { + E rv = delegate.elementAt(index); + delegate.removeElementAt(index); + fireIntervalRemoved(this, index, index); + return rv; + } + + /** + * Removes all of the elements from this list. The list will + * be empty after this call returns (unless it throws an exception). + */ + public void clear() { + int index1 = delegate.size()-1; + delegate.removeAllElements(); + if (index1 >= 0) { + fireIntervalRemoved(this, 0, index1); + } + } + + /** + * Deletes the components at the specified range of indexes. + * The removal is inclusive, so specifying a range of (1,5) + * removes the component at index 1 and the component at index 5, + * as well as all components in between. + * + * @param fromIndex the index of the lower end of the range + * @param toIndex the index of the upper end of the range + * @throws ArrayIndexOutOfBoundsException if the index was invalid + * @throws IllegalArgumentException if {@code fromIndex > toIndex} + * @see #remove(int) + */ + public void removeRange(int fromIndex, int toIndex) { + if (fromIndex > toIndex) { + throw new IllegalArgumentException("fromIndex must be <= toIndex"); + } + for(int i = toIndex; i >= fromIndex; i--) { + delegate.removeElementAt(i); + } + fireIntervalRemoved(this, fromIndex, toIndex); + } + + /** + * Adds all of the elements present in the collection to the list. + * + * @param c the collection which contains the elements to add + * @throws NullPointerException if {@code c} is null + */ + public void addAll(Collection c) { + if (c.isEmpty()) { + return; + } + + int startIndex = getSize(); + + delegate.addAll(c); + fireIntervalAdded(this, startIndex, getSize() - 1); + } + + /** + * Adds all of the elements present in the collection, starting + * from the specified index. + * + * @param index index at which to insert the first element from the + * specified collection + * @param c the collection which contains the elements to add + * @throws ArrayIndexOutOfBoundsException if {@code index} does not + * fall within the range of number of elements currently held + * @throws NullPointerException if {@code c} is null + */ + public void addAll(int index, Collection c) { + if (index < 0 || index > getSize()) { + throw new ArrayIndexOutOfBoundsException("index out of range: " + + index); + } + + if (c.isEmpty()) { + return; + } + + delegate.addAll(index, c); + fireIntervalAdded(this, index, index + c.size() - 1); + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(delegate); + + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + delegate=(Vector) in.readObject(); + } +} diff --git a/src/org/kne/cloud/network/klalb/ByteArrayPool.java b/src/org/kne/cloud/network/ByteArrayPool.java similarity index 90% rename from src/org/kne/cloud/network/klalb/ByteArrayPool.java rename to src/org/kne/cloud/network/ByteArrayPool.java index 3923460..ce0c41d 100644 --- a/src/org/kne/cloud/network/klalb/ByteArrayPool.java +++ b/src/org/kne/cloud/network/ByteArrayPool.java @@ -1,4 +1,4 @@ -package org.kne.cloud.network.klalb; +package org.kne.cloud.network; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; diff --git a/src/org/kne/cloud/network/ByteBufferAllocator.java b/src/org/kne/cloud/network/ByteBufferAllocator.java new file mode 100644 index 0000000..b331444 --- /dev/null +++ b/src/org/kne/cloud/network/ByteBufferAllocator.java @@ -0,0 +1,133 @@ +package org.kne.cloud.network; + +import java.lang.ref.Cleaner; +import java.lang.ref.PhantomReference; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; + +import org.kne.debug.TimeDebugger; +public class ByteBufferAllocator { + private List bbfps=new ArrayList<>(); + + private ByteBufferPool[]bbfpsarr; + + + private ReferenceQueue refq=new ReferenceQueue<>(); + private boolean isDirect; + + public ByteBufferAllocator(boolean isDirect) { + this.isDirect=isDirect; + int i=1; + int maxi=0; + int mps=16; + for (int j = 0; j < 18; j++) { + int count=100; + mps+=count; + bbfps.add(new ByteBufferPool(mps, i,isDirect)); + maxi=i; + i<<=1; + } + bbfpsarr=new ByteBufferPool[maxi]; + for (int j = 0; j < bbfpsarr.length; j++) { + bbfpsarr[j]=getByteBufferPool(j); + } + + Thread t= new Thread(()->{ + while(true) { + try { + Reference ref; + ref = refq.remove(); + if(ref!=null) { + ref.clear(); + } + } catch (InterruptedException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } + } + }); + t.setPriority(Thread.MAX_PRIORITY-1); + t.start(); + } + public ByteBuffer allocate(int capacity) { + if(true) { + return allocateHeap(capacity); + } + //new Exception().printStackTrace(); + ByteBufferPool bbfp=bbfpsarr[capacity]; + ByteBuffer bbf=null; + try { + bbf=bbfp.borrow(); + }catch(OutOfMemoryError err) { + System.gc(); + Thread.yield(); + bbf=bbfp.borrow(); + } + ByteBuffer bbfs=bbf.slice(0, capacity); + + new ByteBufferPhantomReference(bbfs,refq,bbf,bbfp); + return bbfs; + } + private static ByteBuffer allocateHeap(int capacity) { + return ByteBuffer.wrap(new byte[capacity]); + } + private ByteBufferPool getByteBufferPool(int capacity) { + int elen=0; + for (int i = 0; i < bbfps.size(); i++) { + ByteBufferPool bfp=bbfps.get(i); + if(capacity<=(elen= bfp.getLength())) { + return bfp; + } + } + throw new RuntimeException("capacity:"+capacity+">"+elen); + } + private static class ByteBufferPhantomReference extends PhantomReference{ + + private static AtomicReference first=new AtomicReference<>(null); + + private AtomicReference next=new AtomicReference<>(null); + private AtomicReference prev=new AtomicReference<>(null); + + private ByteBuffer father; + private ByteBufferPool pool; + + public ByteBufferPhantomReference(ByteBuffer referent, ReferenceQueue q,ByteBuffer father,ByteBufferPool pool) { + super(referent, q); + this.father=father; + this.pool=pool; + insert(); + } + + private void insert() { + ByteBufferPhantomReference refn= first.getAndSet(this); + if(refn!=null) { + next.set(refn); + refn.prev.set(this); + } + } + + private void remove() { + ByteBufferPhantomReference prevn= prev.getAndSet(null); + ByteBufferPhantomReference nextn=next.getAndSet(null); + if(prevn!=null) + prevn.next.set(nextn); + if(nextn!=null) + nextn.prev.set(prevn); + } + + @Override + public void clear() { + //System.out.println("clear"); + pool.back(father); + remove(); + super.clear(); + } + } +} diff --git a/src/org/kne/cloud/network/ByteBufferPool.java b/src/org/kne/cloud/network/ByteBufferPool.java new file mode 100644 index 0000000..d40e705 --- /dev/null +++ b/src/org/kne/cloud/network/ByteBufferPool.java @@ -0,0 +1,79 @@ +package org.kne.cloud.network; + +import java.nio.ByteBuffer; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.kne.concurrent.SpinLock; +import org.kne.debug.TimeDebugger; + + +public class ByteBufferPool { + private AtomicReferenceArray< ByteBuffer> rec; + private volatile AtomicInteger pos=new AtomicInteger( 0); + //private Lock lock=new SpinLock(); + + private int maxcount; + private int length; + private int mcj; + private boolean direct; + public ByteBufferPool(int maxcount, int length,boolean direct) { + super(); + this.maxcount = maxcount; + this.length = length; + this.direct=direct; + rec=new AtomicReferenceArray(maxcount); + mcj= rec.length()-1; + } + public ByteBufferPool(int maxcount, int length) { + this(maxcount, length, true); + } + public void back(ByteBuffer b) { + if(b.capacity()!=length) + throw new IllegalArgumentException("wrong length"); + b.clear(); + + + if(pos.get()<=mcj) { + int d=pos.getAndIncrement(); + if(d>mcj) + d=mcj; + if(d<0) + d=0; + rec.compareAndSet(d,null,b); + } + + } + public ByteBuffer borrow() { + ByteBuffer b=null; + + if(pos.get()>0) { + int d=pos.decrementAndGet(); + if(d>mcj) + d=mcj; + if(d<0) + d=0; + b=rec.getAndSet(d,null); + } + + if(b==null) { + if(direct) + b=ByteBuffer.allocateDirect(length); + else + b=ByteBuffer.allocate(length); + } + return b; + } + public int getMaxCount() { + return maxcount; + } + public int getLength() { + return length; + } + +} diff --git a/src/org/kne/cloud/network/DatagramServerSocket.java b/src/org/kne/cloud/network/DatagramServerSocket.java index 15d6486..0b5286f 100644 --- a/src/org/kne/cloud/network/DatagramServerSocket.java +++ b/src/org/kne/cloud/network/DatagramServerSocket.java @@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Flow.Subscriber; import java.util.concurrent.locks.LockSupport; -import org.kne.cloud.network.klalb.ByteArrayPool; import org.kne.cloud.network.klalb.DATATPacket; import org.kne.cloud.network.klalb.KLALBRemoteLine; diff --git a/src/org/kne/cloud/network/IPMulticastDiscovery.java b/src/org/kne/cloud/network/IPMulticastDiscovery.java index 5f4a807..9294e3a 100644 --- a/src/org/kne/cloud/network/IPMulticastDiscovery.java +++ b/src/org/kne/cloud/network/IPMulticastDiscovery.java @@ -14,6 +14,7 @@ import java.net.NetworkInterface; import java.net.NoRouteToHostException; import java.net.SocketException; import java.net.UnknownHostException; +import java.time.Duration; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; @@ -31,6 +32,15 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose private List msas; private volatile Consumer con; + private long timeInterval; + + public long getTimeInterval() { + return timeInterval; + } + + public void setTimeInterval(long timeInterval) { + this.timeInterval = timeInterval; + } public NetworkInterface getNinterface() { return ninterface; @@ -53,13 +63,14 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose } public IPMulticastDiscovery(InetSocketAddress bind, InetSocketAddress group, NetworkInterface ninterface, - List msas) throws IOException { + List msas,long timeInterval) throws IOException { soc = new MulticastSocket(bind); soc.joinGroup(group, ninterface); this.bind = bind; this.group = group; this.ninterface = ninterface; this.msas = msas; + this.timeInterval=timeInterval; } @Override @@ -104,7 +115,7 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose } - Thread.sleep(10000L); + Thread.sleep(timeInterval); } } catch (IOException e) { e.printStackTrace(); @@ -133,11 +144,13 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose dis.close(); MultipurposeSocketAddress mpsa = new MultipurposeSocketAddress(type, dp.getAddress().getHostAddress(), port); + try { + InetAddress mpsai=mpsa.getInetAddress(); //System.out.println(mpsa); Enumeration ei = ninterface.getInetAddresses(); while (ei.hasMoreElements()) { InetAddress inetAddress = (InetAddress) ei.nextElement(); - if (inetAddress.equals(mpsa.getInetAddress())) { + if (inetAddress.equals(mpsai)) { continue loop; } } @@ -145,13 +158,16 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose if (con != null) { con.accept(mpsa); } - + }catch(UnknownHostException e) { + + } } } catch (IOException e) { System.out.println(bind + " " + group + " " + ninterface); e.printStackTrace(); } finally { try { + close(); } catch (IOException e) { e.printStackTrace(); diff --git a/src/org/kne/cloud/network/NetworkPacket.java b/src/org/kne/cloud/network/NetworkPacket.java index 00f55d4..db1b668 100644 --- a/src/org/kne/cloud/network/NetworkPacket.java +++ b/src/org/kne/cloud/network/NetworkPacket.java @@ -7,85 +7,50 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.kne.cloud.network.klalb.ByteArrayPool; -import org.kne.cloud.network.klalb.ByteBufferPool; import org.kne.cloud.network.klalb.KLALBPacket; import org.kne.debug.TimeDebugger; public abstract class NetworkPacket implements Comparable{ private static final boolean debugPassport=false; + public static final ByteBufferAllocator bufferAllocator=new ByteBufferAllocator(true); - - public static final ByteArrayPool dataarraypool_65535=new ByteArrayPool(10000, 65535); + //public static final ByteArrayPool dataarraypool_65535=new ByteArrayPool(10000, 65535); - public static final ByteBufferPool databufferpool_65535=new ByteBufferPool(10000, 65535,false); + //public static final ByteBufferPool databufferpool_65535=new ByteBufferPool(10000, 65535,false); - public static final ByteBufferPool databufferpool_2048=new ByteBufferPool(10000, 2048,false); + //public static final ByteBufferPool databufferpool_2048=new ByteBufferPool(10000, 2048,false); - public static final ByteBufferPool databufferpool_40=new ByteBufferPool(10000, 40,false); + //public static final ByteBufferPool databufferpool_40=new ByteBufferPool(10000, 40,false); - private TimeDebugger passport; + private final TimeDebugger passport; { if(debugPassport) { passport=new TimeDebugger(); passport.putTime(getClass().getSimpleName()+ "_create"); + }else { + passport=null; } } - public void putTimePassport(String label) { + public final void putTimePassport(String label) { if(passport!=null) { passport.putTime(label); } } - public void printPassport() { + public final void printPassport() { if(passport!=null) { passport.printWithTimeFilter(100000000L); } } - private volatile boolean disposeAfterSend=false; - public boolean isDisposeAfterSend() { - return disposeAfterSend; - } - public void setDisposeAfterSend(boolean disposeAfterSend) { - this.disposeAfterSend = disposeAfterSend; - } - private volatile boolean disposed=false; - private Lock disposeLock=new ReentrantLock(); - public boolean isDisposed() { - return disposed; - } - public Lock getDisposeLock() { - return disposeLock; - } + public abstract long getLength(); - public void dispose() { - /*disposeLock.lock(); - try {*/ - disposed=true; - /*}finally { - disposeLock.unlock(); - }*/ - } - - public void lockAll() { - disposeLock.lock(); - } - - public boolean isSomeDisposed() { - return disposed; - } - - public void unlockAll() { - disposeLock.unlock(); - } - public long getPriority() { return priority; @@ -118,22 +83,14 @@ public abstract class NetworkPacket implements Comparable{ } } - public void disposeAll() { - dispose(); - } - - public void doDisposeAfterSend() { - if(isDisposeAfterSend()) - dispose(); - } public void genseq() { this.sendseq=seqgen.getAndIncrement(); } - protected abstract void writeToChannel(WritableByteChannel dto) throws IOException ; - protected abstract void readFromChannel(ReadableByteChannel din,long length) throws IOException; - protected void readFromChannel(ReadableByteChannel din) throws IOException{ + public abstract void writeToChannel(WritableByteChannel dto) throws IOException ; + public abstract void readFromChannel(ReadableByteChannel din,long length) throws IOException; + public void readFromChannel(ReadableByteChannel din) throws IOException{ readFromChannel(din,-1); } protected abstract boolean needEndPosition(); diff --git a/src/org/kne/cloud/network/PacketRebuilder.java b/src/org/kne/cloud/network/PacketRebuilder.java index 88d7b6d..a317a37 100644 --- a/src/org/kne/cloud/network/PacketRebuilder.java +++ b/src/org/kne/cloud/network/PacketRebuilder.java @@ -2,6 +2,7 @@ package org.kne.cloud.network; import java.io.IOException; import java.nio.ByteBuffer; +import java.nio.channels.DatagramChannel; import java.nio.channels.ReadableByteChannel; import java.util.HashMap; import java.util.Iterator; @@ -11,14 +12,13 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.function.Supplier; -import org.kne.cloud.network.klalb.ByteBufferPool; - -public class PacketRebuilder { +public class PacketRebuilder implements ReadableByteChannel{ private static final ByteBufferPool bbfp=new ByteBufferPool(100, 65535); private long timeout; - public PacketRebuilder(long timeout) { + public PacketRebuilder(ReadableByteChannel readableChannel,long timeout) { this.timeout=timeout; + this.readableChannel=readableChannel; } @Override @@ -58,10 +58,18 @@ public class PacketRebuilder { } - public void read(ByteBuffer des,ReadableByteChannel rc) throws IOException { - while(true) { + + private ReadableByteChannel readableChannel; + + + public ReadableByteChannel getReadableChannel() { + return readableChannel; + } + + public int read(ByteBuffer des) throws IOException { + while(readableChannel.isOpen()) { ByteBuffer cac=bbfp.borrow(); - rc.read(cac); + readableChannel.read(cac); cac.flip(); int ser=cac.getInt(0); int countofpiece=cac.get(4); @@ -75,12 +83,12 @@ public class PacketRebuilder { ReceiveEntry reet=recvc.get(ser); reet.getByteBuffers()[i]=cac; if(reet.isFull()) { - rebuild(des ,reet.getByteBuffers()); + int rez= rebuild(des ,reet.getByteBuffers()); for (int j = 0; j < reet.getByteBuffers().length; j++) { bbfp.back(reet.getByteBuffers()[j]); } recvc.remove(ser); - return ; + return rez; } for (Iterator> iterator = recvc.entrySet().iterator(); iterator.hasNext();) { Entry type = (Entry) iterator.next(); @@ -94,17 +102,30 @@ public class PacketRebuilder { } } } + return -1; } - public void rebuild(ByteBuffer des, ByteBuffer[]src) { - //System.out.print("Rebuild:"); + public int rebuild(ByteBuffer des, ByteBuffer[]src) { + //StringBuilder sbd=new StringBuilder("Rebuild:"); + int oldpos=des.position(); for (int i = 0; i < src.length; i++) { src[i].getInt(); src[i].get(); src[i].get(); des.put(src[i]); - //System.out.print(src[i].limit()+" "); + // sbd.append(src[i].limit()+" "); } - //System.out.println(); + //System.out.println(sbd); + return des.position()-oldpos; + } + + @Override + public boolean isOpen() { + return readableChannel.isOpen(); + } + + @Override + public void close() throws IOException { + readableChannel.close(); } diff --git a/src/org/kne/cloud/network/PacketSpliter.java b/src/org/kne/cloud/network/PacketSpliter.java index 7ca7f6f..2ae626d 100644 --- a/src/org/kne/cloud/network/PacketSpliter.java +++ b/src/org/kne/cloud/network/PacketSpliter.java @@ -6,14 +6,12 @@ import java.nio.channels.WritableByteChannel; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.kne.cloud.network.klalb.ByteBufferPool; - public class PacketSpliter { - private int splitSize; - private static final ByteBufferPool bbfp=new ByteBufferPool(100,65535,false); + private volatile int splitSize; private AtomicInteger series=new AtomicInteger(); - - public PacketSpliter(int splitSize) { + private WritableByteChannel writableChannel; + public PacketSpliter(WritableByteChannel writableChannel,int splitSize) { + this.writableChannel=writableChannel; this.splitSize=splitSize; } @@ -21,28 +19,37 @@ public class PacketSpliter { return splitSize; } + + + public WritableByteChannel getWritableChannel() { + return writableChannel; + } + + public void setSplitSize(int splitSize) { + this.splitSize = splitSize; + } @Override public String toString() { return "PacketSpliter [splitSize=" + splitSize + "]"; } - public void write(ByteBuffer bb,WritableByteChannel wc) throws IOException{ + public void write(ByteBuffer bb) throws IOException{ ByteBuffer[]bbssp= split(bb); for (int i = 0; i < bbssp.length; i++) { - wc.write(bbssp[i]); - bbfp.back(bbssp[i]); + writableChannel.write(bbssp[i]); } } public ByteBuffer[] split(ByteBuffer bb) { - //System.out.print("Split:"); + //StringBuilder sbd=new StringBuilder("Split:"); + int splitSizex=splitSize; int lenth=bb.limit(); - int countofpiece=(lenth-1)/splitSize+1; - int remain=lenth%splitSize; + int countofpiece=(lenth-1)/splitSizex+1; + int remain=lenth%splitSizex; ByteBuffer[]pieces=new ByteBuffer[countofpiece]; for (int i = 0; i < pieces.length; i++) { - pieces[i]=bbfp.borrow(); + pieces[i]=NetworkPacket.bufferAllocator.allocate(splitSizex+6); } int sern=series.getAndIncrement(); for (int i = 0; i < pieces.length; i++) { @@ -53,10 +60,10 @@ public class PacketSpliter { bb.limit(Math.min(bb.remaining(), pieces[i].remaining())+bb.position()); pieces[i].put(bb); bb.limit(bbl); - //System.out.print(pieces[i].position()+" "); + //sbd.append(pieces[i].position()+" "); pieces[i].flip(); } - //System.out.println(); + //System.out.println(sbd); return pieces; } diff --git a/src/org/kne/cloud/network/RawSocket.java b/src/org/kne/cloud/network/RawSocket.java new file mode 100644 index 0000000..4ac51d6 --- /dev/null +++ b/src/org/kne/cloud/network/RawSocket.java @@ -0,0 +1,435 @@ + +package org.kne.cloud.network; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.net.InetAddress; +import java.net.ProtocolFamily; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.SocketException; +import java.net.SocketOptions; +import java.net.StandardProtocolFamily; +import java.net.UnknownHostException; + +import org.kne.cloud.network.klalb.KLALBVirtualRawSocketImpl; + + +public class RawSocket { + + + public static final ProtocolFamily PF_INET=StandardProtocolFamily.INET; + + + public static final ProtocolFamily PF_INET6=StandardProtocolFamily.INET6; + + private static final VarHandle STATE ; + static { + try { + MethodHandles.Lookup l = MethodHandles.lookup(); + STATE = l.findVarHandle(RawSocket.class, "state", int.class); + } catch (Exception e) { + throw new InternalError(e); + } + } +//the underlying SocketImpl, may be null, may be swapped when connecting + private RawSocketImpl impl; + + // state bits + private static final int SOCKET_CREATED = 1 << 0; // impl.create(boolean) called + private static final int BOUND = 1 << 1; + private static final int CONNECTED = 1 << 2; + private static final int CLOSED = 1 << 3; + private static final int SHUT_IN = 1 << 9; + private static final int SHUT_OUT = 1 << 10; + private volatile int state; + + // used to coordinate creating and closing underlying socket + private final Object socketLock = new Object(); + + + InetAddress connectedAddress = null; + + private boolean explicitFilter = false; + private int bytesLeftToFilter; + /** + * Atomically sets state to the result of a bitwise OR of the current value + * and the given mask. + * @return the previous state value + */ + private int getAndBitwiseOrState(int mask) { + return (int) STATE.getAndBitwiseOr(this, mask); + } + + private static boolean isBound(int s) { + return (s & BOUND) != 0; + } + + private static boolean isConnected(int s) { + return (s & CONNECTED) != 0; + } + + private static boolean isClosed(int s) { + return (s & CLOSED) != 0; + } + + private static boolean isInputShutdown(int s) { + return (s & SHUT_IN) != 0; + } + + private static boolean isOutputShutdown(int s) { + return (s & SHUT_OUT) != 0; + } + + + + protected RawSocket(RawSocketImpl impl) { + this.impl=impl; + } + + public RawSocket(RawSocketImpl impl, Inet6Address bindAddress) throws SocketException { + this.impl=impl; + bind(bindAddress); +} + +public RawSocket(KLALBVirtualRawSocketImpl impl, Inet6Address bindAddress, int bindProtocol) throws SocketException { + this.impl=impl; + bind(bindAddress,bindProtocol); +} + +public boolean isConnected() { + return isConnected(state); + } + public boolean isBound() { + return isBound(state); + } + public boolean isOpen() { + return !isClosed(state); + } + public boolean isClosed() { + return isClosed(state); + } + private void checkAddress(InetAddress addr, String op) { + if (addr == null) { + return; + } + if (!(addr instanceof Inet4Address || addr instanceof Inet6Address)) { + throw new IllegalArgumentException(op + ": invalid address type"); + } + } + + + + + + + private RawSocketImpl getImpl() throws SocketException { + if ((state & SOCKET_CREATED) == 0) { + synchronized (socketLock) { + int s = state; // re-read state + if ((s & SOCKET_CREATED) == 0) { + if (isClosed(s)) { + throw new SocketException("Socket is closed"); + } + RawSocketImpl impl = this.impl; + if (impl == null) { + this.impl = impl = createImpl(); + } + try { + impl.create(); + } catch (SocketException e) { + throw e; + } catch (IOException e) { + throw new SocketException(e.getMessage(), e); + } + getAndBitwiseOrState(SOCKET_CREATED); + } + } + } + return impl; + } + + private static RawSocketImpl createImpl() { + RawSocketImplFactory factory = RawSocket.factory; + if (factory != null) { + return factory.createRawSocketImpl(); + } else { + return null; + // RawSocketImpl delegate = RawSocketImpl.createPlatformSocketImpl(false); + // return new SocksSocketImpl(delegate); + } + } + + + private static volatile RawSocketImplFactory factory; + + static RawSocketImplFactory socketImplFactory() { + return factory; + } + + + @Deprecated(since = "17") + public static synchronized void setSocketImplFactory(RawSocketImplFactory fac) + throws IOException + { + if (factory != null) { + throw new SocketException("factory already defined"); + } + @SuppressWarnings("removal") + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkSetFactory(); + } + factory = fac; + } + public void bind(InetAddress address) throws SocketException { + bind(address,-1); + } + public void bind(InetAddress address,int protocolNumber) + throws SocketException + { + int s = state; + if (isClosed(s)) + throw new SocketException("Socket is closed"); + if (isBound(s)) + throw new SocketException("Already bound"); + + + + if (address == null) { + try { + address = Inet6Address.getByName("::0"); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + checkAddress (address, "bind"); + getImpl().bind(address,protocolNumber); + getAndBitwiseOrState(BOUND); + + + } + + + + public void bindDevice(String device) + throws UnsupportedOperationException, IllegalStateException, IOException + { + if(!isOpen()) + throw new IllegalStateException(); + + throw new UnsupportedOperationException(); + } + + + public InetAddress getLocalAddress() { + if (isClosed()) + return null; + InetAddress in; + try { + in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); + if (in.isAnyLocalAddress()) { + in = InetAddress.getByName("::0"); + } + + } catch (Exception e) { + try { + in = InetAddress.getByName("::0"); + } catch (UnknownHostException e1) { + e1.printStackTrace(); + in=null; + } + } + return in; + } + + + public void close() { + synchronized (socketLock) { + if ((state & CLOSED) == 0) { + int s = getAndBitwiseOrState(CLOSED); + if ((s & (SOCKET_CREATED | CLOSED)) == SOCKET_CREATED) { + // close underlying socket if created + impl.close(); + } + } + } + } + + public void setIPHeaderInclude(boolean on) throws IOException { + impl.setIPHeaderInclude(on); + } + + + + public boolean getIPHeaderInclude() throws IOException { + return impl.getIPHeaderInclude(); + } + + public void setSendBufferSize(int size) throws SocketException { + if (size <= 0) + throw new IllegalArgumentException("negative send size"); + if (isClosed()) + throw new SocketException("Socket is closed"); + getImpl().setOption(SocketOptions.SO_SNDBUF, size); + } + + public int getSendBufferSize() throws SocketException { + if (isClosed()) + throw new SocketException("Socket is closed"); + int result = 0; + Object o = getImpl().getOption(SocketOptions.SO_SNDBUF); + if (o instanceof Integer i) { + result = i.intValue(); + } + return result; + } + + public void setReceiveBufferSize(int size) throws SocketException { + if (size <= 0) + throw new IllegalArgumentException("invalid receive size"); + if (isClosed()) + throw new SocketException("Socket is closed"); + getImpl().setOption(SocketOptions.SO_RCVBUF, size); + } + + public int getReceiveBufferSize() throws SocketException { + if (isClosed()) + throw new SocketException("Socket is closed"); + int result = 0; + Object o = getImpl().getOption(SocketOptions.SO_RCVBUF); + if (o instanceof Integer i) { + result = i.intValue(); + } + return result; + } + + + + public void setUseSelectTimeout(boolean useSelect) throws IOException { + impl.setUseSelectTimeout(useSelect); + } + + + + public boolean getUseSelectTimeout() throws IOException { + return impl.getUseSelectTimeout(); + } + + + /* public void setSendTimeout(int timeout) throws SocketException { + impl.setSendTimeout( timeout); + } + + + public int getSendTimeout() throws SocketException { + return impl.getSendTimeout(); + }*/ + + + public void setSoTimeout(int timeout) throws SocketException { + if (isClosed()) + throw new SocketException("Socket is closed"); + if (timeout < 0) + throw new IllegalArgumentException("timeout can't be negative"); + getImpl().setOption(SocketOptions.SO_TIMEOUT, timeout); + } + + + public int getSoTimeout() throws SocketException { + if (isClosed()) + throw new SocketException("Socket is closed"); + Object o = getImpl().getOption(SocketOptions.SO_TIMEOUT); + /* extra type safety */ + if (o instanceof Integer i) { + return i.intValue(); + } else { + return 0; + } + } + + + public void send(DatagramPacket p) throws IOException { + synchronized (p) { + if (isClosed()) + throw new SocketException("Socket is closed"); + InetAddress packetAddress = p.getAddress(); + checkAddress(packetAddress, "send"); + if (isConnected()) { + // we're connected + if (packetAddress == null) { + p.setAddress(connectedAddress); + } else if ((!packetAddress.equals(connectedAddress)) ) { + throw new IllegalArgumentException("connected address " + + "and packet address" + + " differ"); + } + + } else { + if (packetAddress == null) { + throw new IllegalArgumentException("Address not set"); + } + } + // Check whether the socket is bound + if (!isBound()) + bind(InetAddress.getByName("::0")); + // call the method to send + getImpl().send(p); + } + } + + public synchronized void receive(DatagramPacket p) throws IOException { + synchronized (p) { + if (!isBound()) + bind(InetAddress.getByName("::0")); + DatagramPacket tmp = null; + if (explicitFilter) { + // We have to do the filtering the old fashioned way since + // the native impl doesn't support connect or the connect + // via the impl failed, or .. "explicitFilter" may be set when + // a socket is connected via the impl, for a period of time + // when packets from other sources might be queued on socket. + boolean stop = false; + while (!stop) { + // peek at the packet to see who it is from. + DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1); + getImpl().peekData(peekPacket); + InetAddress peekAddress = peekPacket.getAddress(); + if ((!connectedAddress.equals(peekAddress)) ) { + // throw the packet away and silently continue + tmp = new DatagramPacket( + new byte[1024], 1024); + getImpl().receive(tmp); + if (explicitFilter) { + if (checkFiltering(tmp)) { + stop = true; + } + } + } else { + stop = true; + } + } + } + // If the security check succeeds, or the datagram is + // connected then receive the packet + getImpl().receive(p); + if (explicitFilter && tmp == null) { + // packet was not filtered, account for it here + checkFiltering(p); + } + } + } + private boolean checkFiltering(DatagramPacket p) throws SocketException { + bytesLeftToFilter -= p.getLength(); + if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) { + explicitFilter = false; + return true; + } + return false; + } + +} diff --git a/src/org/kne/cloud/network/RawSocketImpl.java b/src/org/kne/cloud/network/RawSocketImpl.java new file mode 100644 index 0000000..cb3fe4c --- /dev/null +++ b/src/org/kne/cloud/network/RawSocketImpl.java @@ -0,0 +1,80 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketOptions; +import java.util.Objects; + +public abstract class RawSocketImpl implements SocketOptions{ + int dataAvailable() { + // default impl returns zero, which disables the calling + // functionality + return 0; + } + protected abstract void create()throws IOException; + + protected abstract void setIPHeaderInclude(boolean on)throws IOException; + + protected abstract boolean getIPHeaderInclude()throws IOException; + + protected abstract void setUseSelectTimeout(boolean useSelect)throws IOException; + + protected abstract boolean getUseSelectTimeout()throws IOException; + + protected abstract void setSendTimeout(int timeout)throws IOException; + + protected abstract int getSendTimeout()throws IOException; + + protected abstract void setReceiveTimeout(int timeout)throws IOException; + + protected abstract int getReceiveTimeout()throws IOException; + + protected abstract void close(); + + protected abstract void bind(InetAddress address,int protocolNumber)throws SocketException; + + protected void setOption(SocketOption name, T value) throws IOException { + Objects.requireNonNull(name); + throw new UnsupportedOperationException("'" + name + "' not supported"); + } + + protected T getOption(SocketOption name) throws IOException { + Objects.requireNonNull(name); + throw new UnsupportedOperationException("'" + name + "' not supported"); + } + + protected abstract void join(InetAddress inetaddr) throws IOException; + + + protected abstract void leave(InetAddress inetaddr) throws IOException; + + + protected abstract void joinGroup(InetAddress mcastaddr, + NetworkInterface netIf) + throws IOException; + + + protected abstract void leaveGroup(InetAddress mcastaddr, + NetworkInterface netIf) + throws IOException; + protected abstract void send(DatagramPacket p) throws IOException; + protected abstract InetAddress peek() throws IOException; + + + protected abstract void peekData(DatagramPacket p) throws IOException; + + protected abstract void receive(DatagramPacket p) throws IOException; + + protected void connect(InetAddress address) throws SocketException { + throw new SocketException("connect not implemented"); + } + + protected void disconnect() { + throw new UncheckedIOException(new SocketException("disconnect not implemented")); + } +} diff --git a/src/org/kne/cloud/network/RawSocketImplFactory.java b/src/org/kne/cloud/network/RawSocketImplFactory.java new file mode 100644 index 0000000..c77a7d4 --- /dev/null +++ b/src/org/kne/cloud/network/RawSocketImplFactory.java @@ -0,0 +1,5 @@ +package org.kne.cloud.network; + +public interface RawSocketImplFactory { + RawSocketImpl createRawSocketImpl(); +} diff --git a/src/org/kne/cloud/network/SocketChannelListener.java b/src/org/kne/cloud/network/SocketChannelListener.java index abfdc76..892d81b 100644 --- a/src/org/kne/cloud/network/SocketChannelListener.java +++ b/src/org/kne/cloud/network/SocketChannelListener.java @@ -28,7 +28,7 @@ public class SocketChannelListener implements Closeable,AutoCloseable{ while(flag){ try { SocketChannel soce=serverSocketChannel.accept(); - ThreadTool.makePThreadIfSupport("端口监听线程",()->{ + ThreadTool.makePThreadIfSupport("端口请求处理线程",()->{ if(con!=null) { try { con.accept(soce); @@ -71,7 +71,7 @@ public class SocketChannelListener implements Closeable,AutoCloseable{ if(serverSocketChannel==null) { throw new IOException(multipurposeSocketAddress.getType()+" unsupport SocketChannel"); } - new Thread(r).start(); + ThreadTool.makeVThread("端口监听线程", r).start(); } public void close() { flag=false; diff --git a/src/org/kne/cloud/network/SpeedLimiter.java b/src/org/kne/cloud/network/SpeedLimiter.java index 3e7b4de..56d52ba 100644 --- a/src/org/kne/cloud/network/SpeedLimiter.java +++ b/src/org/kne/cloud/network/SpeedLimiter.java @@ -63,6 +63,7 @@ public class SpeedLimiter { waitingtime.addAndGet(datasize*1000000000L/limitspeedx); } } + //用系统计时器的时刻相减得到经过的时间,与数据包除以限速值得到的应消耗的时间做对比,若时间还未到达发送下一个数据包的时机,则返回false public boolean checkTransmit(long datasize) { long limitspeedx=limitspeed; if(limitspeedx<=0) { diff --git a/src/org/kne/cloud/network/ThreadTool.java b/src/org/kne/cloud/network/ThreadTool.java index f32949e..c87dc30 100644 --- a/src/org/kne/cloud/network/ThreadTool.java +++ b/src/org/kne/cloud/network/ThreadTool.java @@ -3,8 +3,8 @@ package org.kne.cloud.network; import java.lang.reflect.Method; public class ThreadTool { - public static boolean first=true; public static boolean forceD=true; + public static boolean first=true; public static Thread makeVThreadIfSupport(String name,Runnable r) { if(forceD) return new Thread(r, name); @@ -64,4 +64,47 @@ public class ThreadTool { rt.setDaemon(true); return rt; } + public static Thread makeVDaemonThread(String name, Runnable r) { + try { //return new Thread(r, name); + Class c=Class.forName("java.lang.Thread"); + Method m= c.getDeclaredMethod("ofVirtual", null); + Object o=m.invoke(null, null); + Class cb=Class.forName("java.lang.Thread$Builder"); + Method mn= cb.getDeclaredMethod("name", String.class); + mn.invoke(o, name); + Method mu= cb.getDeclaredMethod("unstarted", Runnable.class); + return (Thread) mu.invoke(o, r); + //return Thread.ofVirtual().name(name).unstarted(r); + }catch(Throwable e) { + //e.printStackTrace(); + if(first) { + System.out.println("提示:请使用java21以上版本以提高本软件的数据转发性能!"); + first=false; + } + Thread rt=new Thread(r, name); + rt.setDaemon(true); + return rt; + } + } + public static Thread makeVThread(String name, Runnable r) { + + try { //return new Thread(r, name); + Class c=Class.forName("java.lang.Thread"); + Method m= c.getDeclaredMethod("ofVirtual", null); + Object o=m.invoke(null, null); + Class cb=Class.forName("java.lang.Thread$Builder"); + Method mn= cb.getDeclaredMethod("name", String.class); + mn.invoke(o, name); + Method mu= cb.getDeclaredMethod("unstarted", Runnable.class); + return (Thread) mu.invoke(o, r); + //return Thread.ofVirtual().name(name).unstarted(r); + }catch(Throwable e) { + //e.printStackTrace(); + if(first) { + System.out.println("提示:请使用java21以上版本以提高本软件的数据转发性能!"); + first=false; + } + return new Thread(r, name); + } + } } diff --git a/src/org/kne/cloud/network/VirtualRawSocket.java b/src/org/kne/cloud/network/VirtualRawSocket.java new file mode 100644 index 0000000..9e63dd3 --- /dev/null +++ b/src/org/kne/cloud/network/VirtualRawSocket.java @@ -0,0 +1,28 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.SocketException; + +import org.kne.cloud.network.klalb.KLALBVirtualRawSocketImpl; + +public class VirtualRawSocket extends RawSocket { + + private VirtualRawSocketImpl virtualImpl; + protected VirtualRawSocket(VirtualRawSocketImpl virtualImpl) { + super(virtualImpl); + this.virtualImpl =virtualImpl; + } + public VirtualRawSocket(KLALBVirtualRawSocketImpl virtualImpl, Inet6Address bindAddress) throws SocketException { + super(virtualImpl,bindAddress); + this.virtualImpl =virtualImpl; + } + public VirtualRawSocket(KLALBVirtualRawSocketImpl virtualImpl, Inet6Address bindAddress, + int bindProtocol) throws SocketException { + super(virtualImpl,bindAddress,bindProtocol); + this.virtualImpl =virtualImpl; + } + protected VirtualRawSocketImpl getVirtualImpl() { + return virtualImpl; + } +} diff --git a/src/org/kne/cloud/network/VirtualRawSocketImpl.java b/src/org/kne/cloud/network/VirtualRawSocketImpl.java new file mode 100644 index 0000000..188cce3 --- /dev/null +++ b/src/org/kne/cloud/network/VirtualRawSocketImpl.java @@ -0,0 +1,13 @@ +package org.kne.cloud.network; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; + +public abstract class VirtualRawSocketImpl extends RawSocketImpl { + + + +} diff --git a/src/org/kne/cloud/network/ipv6/IPv6NetworkLink.java b/src/org/kne/cloud/network/ipv6/IPv6NetworkLink.java index b26423c..b36b885 100644 --- a/src/org/kne/cloud/network/ipv6/IPv6NetworkLink.java +++ b/src/org/kne/cloud/network/ipv6/IPv6NetworkLink.java @@ -14,10 +14,16 @@ public interface IPv6NetworkLink { public boolean isLoopBack(); public Inet6AddressGroup getAddressGroup(); public List getNeighborsInfo(); + public List getRouteItems(); public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException; - public boolean isCongress(IPv6Packet iPv6Packet); + public boolean isCongress(IPv6Packet iPv6Packet,double scale); + public default boolean isCongress(IPv6Packet iPv6Packet) { + return isCongress(iPv6Packet, 1.0); + } public String getName(); public boolean isUp(); public boolean canSend(IPv6Packet iPv6Packet); public void setReceiveConsumer(Consumercon); + void setRerouteConsumer(Consumer rerouteConsumer); + public boolean isReachSpeedLimit(IPv6Packet iPv6Packet); } diff --git a/src/org/kne/cloud/network/ipv6/IPv6Packet.java b/src/org/kne/cloud/network/ipv6/IPv6Packet.java index 65ef23f..6da7cf6 100644 --- a/src/org/kne/cloud/network/ipv6/IPv6Packet.java +++ b/src/org/kne/cloud/network/ipv6/IPv6Packet.java @@ -2,6 +2,7 @@ package org.kne.cloud.network.ipv6; import java.io.EOFException; import java.io.IOException; +import java.io.StreamCorruptedException; import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; @@ -11,9 +12,12 @@ import java.nio.channels.WritableByteChannel; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.ipv6.IPv6Packet.IPv6ExtHeader; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader; import org.kne.cloud.network.klalb.KLALBPacket; import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV; import org.kne.cloud.network.srv6.IpV6RoutingSRHData; @@ -24,6 +28,29 @@ import org.kne.cloud.network.srv6.SRv6TLV; import org.pcap4j.packet.namednumber.IpNumber; public class IPv6Packet extends NetworkPacket { + + private long flowSeqMark=-1; + + + + public long getFlowSeqMark() { + return flowSeqMark; + } + + public void setFlowSeqMark(long flowSeqMark) { + this.flowSeqMark = flowSeqMark; + } + + + private boolean TTLdecreased=false; + + public boolean isTTLdecreased() { + return TTLdecreased; + } + + public void setTTLdecreased(boolean tTLdecreased) { + TTLdecreased = tTLdecreased; + } private volatile ByteBuffer IPv6header ; private volatile List headers = new ArrayList<>(); @@ -41,7 +68,7 @@ public class IPv6Packet extends NetworkPacket { } public IPv6Packet() { - IPv6header = NetworkPacket.databufferpool_40.borrow(); + IPv6header = NetworkPacket.bufferAllocator.allocate(40); IPv6header.limit(IPv6_HEADER_LENGTH); } @@ -76,6 +103,7 @@ public class IPv6Packet extends NetworkPacket { public void markCE() { IPv6header.put(1,(byte) (IPv6header.get(1)|0b00110000)); + //new Exception().printStackTrace(); } public boolean isCE() { @@ -114,7 +142,24 @@ public class IPv6Packet extends NetworkPacket { public void setHopLimit(int hopLimit) { IPv6header.put(7, (byte) hopLimit); } + + public void getRawSourceAddress(byte[] sourceAddress) { + IPv6header.get(8, sourceAddress, 0, sourceAddress.length); + } + public void setRawSourceAddress(byte[] sourceAddress) { + IPv6header.put(8, sourceAddress, 0, sourceAddress.length); + } + + public void getRawDestinationAddress(byte[] destinationAddress) { + IPv6header.get(24, destinationAddress, 0,destinationAddress.length); + + } + + public void setRawDestinationAddress(byte[] destinationAddress) { + IPv6header.put(24, destinationAddress, 0, destinationAddress.length); + } + public Inet6Address getSourceAddress() { byte[] b = new byte[16]; IPv6header.get(8, b, 0, b.length); @@ -163,29 +208,6 @@ public class IPv6Packet extends NetworkPacket { return calcPayloadLength()+IPv6_HEADER_LENGTH; } - @Override - public void doDisposeAfterSend() { - super.doDisposeAfterSend(); - payload.doDisposeAfterSend(); - } - - @Override - public void dispose() { - super.dispose(); - /*ByteBuffer headerx = IPv6header; - IPv6header = null; - if(headerx!=null) - NetworkPacket.databufferpool_40.back(headerx);*/ - } - - @Override - public void disposeAll() { - super.disposeAll(); - for (int i = 0; i < headers.size(); i++) { - headers.get(i).disposeAll(); - } - payload.disposeAll(); - } @Override @@ -241,7 +263,7 @@ public class IPv6Packet extends NetworkPacket { headers.add(ext); break; case 43: - ByteBuffer bbf=NetworkPacket.databufferpool_2048.borrow(); + ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(2048); bbf.limit(4); while (bbf.hasRemaining()) { if (din.read(bbf) == -1) { @@ -296,7 +318,11 @@ public class IPv6Packet extends NetworkPacket { KLALBPacket kp=KLALBPacket.readKLALBPacketFromChannel(din); this.payload=kp; break loop; - + case 253: + IPv6Payload epld=new IPv6EmptyPayload(); + epld.readFromChannel(din, payloadlength); + this.payload=epld; + break loop; default: IPv6Payload pld=new IPv6Payload(nextheader); pld.readFromChannel(din, payloadlength); @@ -376,35 +402,7 @@ public class IPv6Packet extends NetworkPacket { //System.out.println(payload); }*/ - @Override - public void lockAll() { - super.lockAll(); - for (int i = 0; i < headers.size(); i++) { - headers.get(i).lockAll(); - } - payload.lockAll(); - } - - @Override - public boolean isSomeDisposed() { - if(super.isSomeDisposed()||payload.isSomeDisposed()) - return true; - for (Iterator iterator = headers.iterator(); iterator.hasNext();) { - IPv6ExtHeader iPv6ExtHeader = (IPv6ExtHeader) iterator.next(); - if(iPv6ExtHeader.isSomeDisposed()) - return true; - } - return false; - } - - @Override - public void unlockAll() { - payload.unlockAll(); - for (int i = 0; i < headers.size(); i++) { - headers.get(i).unlockAll(); - } - super.unlockAll(); - } + @Override public String toString() { @@ -434,7 +432,7 @@ public class IPv6Packet extends NetworkPacket { this.protocolNumber = protocolNumber; this.onDefault=isonDefault; if(onDefault) - this.data=NetworkPacket.databufferpool_65535.borrow(); + this.data=NetworkPacket.bufferAllocator.allocate(65535); } public int getProtocolNumber() { @@ -446,13 +444,13 @@ public class IPv6Packet extends NetworkPacket { } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { if(onDefault) dto.write(data.slice(0,data.limit())); } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { if(onDefault) { data.limit((int) length); while (data.hasRemaining()) { @@ -463,15 +461,7 @@ public class IPv6Packet extends NetworkPacket { } } - @Override - public void dispose() { - super.dispose(); - /*if(onDefault) { - ByteBuffer datax = data; - data = null; - NetworkPacket.databufferpool_65535.back(datax); - }*/ - } + @Override protected boolean needEndPosition() { @@ -480,6 +470,28 @@ public class IPv6Packet extends NetworkPacket { } + public static class IPv6EmptyPayload extends IPv6Payload{ + + public IPv6EmptyPayload() { + super(253, false); + } + + @Override + public long getLength() { + return 0; + } + + @Override + public void writeToChannel(WritableByteChannel dto) throws IOException { + + } + + @Override + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { + + } + } + public static class IPv6ExtHeader extends NetworkPacket{ private ByteBuffer data ; @@ -505,9 +517,9 @@ public class IPv6Packet extends NetworkPacket { this.protocolNumber = protocolNumber; this.onDefault=isonDefault; if(onDefault) { - this.data=NetworkPacket.databufferpool_2048.borrow(); + this.data=NetworkPacket.bufferAllocator.allocate(2048); }else { - this.data=NetworkPacket.databufferpool_40.borrow(); + this.data=NetworkPacket.bufferAllocator.allocate(8); } } @@ -542,7 +554,7 @@ public class IPv6Packet extends NetworkPacket { } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { if(onDefault) { int ext=(data.limit()-8)/8; setExtLength(ext); @@ -553,7 +565,7 @@ public class IPv6Packet extends NetworkPacket { } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { data.limit(8); while (data.hasRemaining()) { if (din.read(data) == -1) { @@ -576,19 +588,7 @@ public class IPv6Packet extends NetworkPacket { return false; } - @Override - public void dispose() { - super.dispose(); - /*ByteBuffer bbft=data; - data=null; - if(bbft!=null) { - if(bbft.capacity()==40) { - NetworkPacket.databufferpool_40.back(bbft); - }else { - NetworkPacket.databufferpool_2048.back(bbft); - } - }*/ - } + @@ -678,27 +678,37 @@ public class IPv6Packet extends NetworkPacket { public List getAddresses() { return addresses; } + + public List getTlvs() { + return tlvs; + } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { - setExtLength(calcExtLength()/8); + public void writeToChannel(WritableByteChannel dto) throws IOException { + int exl=calcExtLength(); + if(exl%8!=0) { + throw new StreamCorruptedException("extLength % 8 !=0"); + } + + setExtLength(exl/8); setLastEntry(addresses.size()-1); super.writeToChannel(dto); - for (Iterator iterator = addresses.iterator(); iterator.hasNext();) { - Inet6Address inet6Address = (Inet6Address) iterator.next(); + + for(Inet6Address inet6Address:addresses) { dto.write(ByteBuffer.wrap(inet6Address.getAddress())); } - + for(IPv6SegmentRoutingTLV tlv:tlvs) { + IPv6SegmentRoutingTLV.writeIPv6SegmentRoutingTLVToChannel(dto, tlv); + } } private int calcExtLength() { int tlvsl=0; - for (Iterator iterator = tlvs.iterator(); iterator.hasNext();) { - IPv6SegmentRoutingTLV tlve = (IPv6SegmentRoutingTLV) iterator.next(); + for(IPv6SegmentRoutingTLV tlve:tlvs) { tlvsl+=tlve.getLength(); } return addresses.size()*16+tlvsl; } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { super.readFromChannel(din, length); int extl=getExtLength(); int laste=getLastEntry(); @@ -722,6 +732,13 @@ public class IPv6Packet extends NetworkPacket { //System.out.println("SR:"+addr); addresses.add(addr); } + tlvs.clear(); + while(usdl getHeaders() { return headers; } - + public IPv6SegmentRoutingHeader getSRHHeader() { + IPv6SegmentRoutingHeader srhh = null; + List exhs = headers; + for (int j = 0; j < exhs.size(); j++) { + IPv6ExtHeader exh = exhs.get(j); + if (exh instanceof IPv6SegmentRoutingHeader) { + if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == 4) { + srhh = (IPv6SegmentRoutingHeader) exh; + break; + } + } + } + return srhh; + } /*public IPv6DestinationHeader insertDestinationHeader(int index,int extLength) { long ptr; long lth=extLength*8+8; @@ -831,6 +861,18 @@ public class IPv6Packet extends NetworkPacket { protected boolean needEndPosition() { return false; } + private AtomicInteger rerouteCounter=new AtomicInteger(0); + public AtomicInteger getRerouteCounter() { + return rerouteCounter; + } + private volatile boolean promise=false; + public void setPromise(boolean b) { + promise=b; + } + + public boolean isPromise() { + return promise; + } diff --git a/src/org/kne/cloud/network/ipv6/IPv6TUNLoopbackNetworkLink.java b/src/org/kne/cloud/network/ipv6/IPv6TUNLoopbackNetworkLink.java index 2c7cb49..ba438e9 100644 --- a/src/org/kne/cloud/network/ipv6/IPv6TUNLoopbackNetworkLink.java +++ b/src/org/kne/cloud/network/ipv6/IPv6TUNLoopbackNetworkLink.java @@ -3,12 +3,14 @@ package org.kne.cloud.network.ipv6; import java.io.Closeable; import java.io.IOException; import java.net.Inet6Address; +import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; @@ -19,14 +21,22 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader; import org.kne.cloud.network.monitor.MonitorData; import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; +import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV; import org.kne.cloud.network.srv6.IpV6RoutingSRHData; import org.kne.cloud.network.srv6.PacketConsumer; import org.kne.cloud.network.srv6.PacketReorder; +import org.kne.cloud.network.srv6.SEQSSegmentRoutingTLV; +import org.kne.cloud.network.srv6.SRv6PacketReorder; +import org.kne.cloud.network.srv6.SRv6PacketSeqMarker; import org.kne.cloud.network.srv6.SRv6StreamSequenceTLV; import org.kne.cloud.network.srv6.SRv6TLV; +import org.kne.cloud.network.srv6.TCPTransimitAgent; import org.kne.cloud.network.tun.TUNNetworkDevice; +import org.kne.concurrent.DisruptorExecutor; +import org.kne.concurrent.HighPerformanceExecutor; import org.kne.concurrent.SpinLock; import org.kne.io.KNEChannels; @@ -42,11 +52,11 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A private Thread tr; - private ThreadPoolExecutor exc = (ThreadPoolExecutor) Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); - private Lock slok=new SpinLock(); - public IPv6TUNLoopbackNetworkLink(Inet6AddressGroup hostAddress, int mtu) throws IOException { + private SRv6PacketSeqMarker seqm=new SRv6PacketSeqMarker(); + + public IPv6TUNLoopbackNetworkLink(Inet6AddressGroup hostAddress, int mtu,Listdns) throws IOException { if (tun != null) throw new IllegalStateException("already open!"); try { @@ -56,31 +66,42 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A this.hostAddress = hostAddress; if (hostAddress != null) tun.setIPAddress(hostAddress.getAddress(), hostAddress.getPrefixLength()); + if(dns!=null) { + tun.setDNSAddress(dns); + } + try { tun.setMTU(mtu); + }catch(IOException e) { + e.printStackTrace(); + } Thread tb = new Thread(() -> { while (true) { - ByteBuffer tmp = NetworkPacket.databufferpool_65535.borrow(); + ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535); try { tun.read(tmp); tmp.flip(); + //System.out.println(tmp); if (IPv6Packet.getIPVersion(tmp.get(0)) == 6) { - while(exc.getQueue().size()>10) { - LockSupport.parkNanos(1000000); - } - exc.execute(() -> { + + HighPerformanceExecutor.defaultExecutor.execute(() -> { try { IPv6Packet ipp = new IPv6Packet(); ipp.readFromChannel(KNEChannels.newReadableChannel(tmp), mtu); - NetworkPacket.databufferpool_65535.back(tmp); + + //NetworkPacket.databufferpool_65535.back(tmp); if (con != null) { monitor.getOutPacketCounterAL().incrementAndGet(); monitor.getOutTrafficAL().addAndGet(ipp.getLength()); - ipp.setDisposeAfterSend(true); - ipp.getPayload().setDisposeAfterSend(true); + // ipp.setDisposeAfterSend(true); + // ipp.getPayload().setDisposeAfterSend(true); + ipp.setPromise(true); + if(ipp.getPayload().getProtocolNumber()==6) { + seqm.mark(ipp); + } con.accept(ipp); } else { - ipp.dispose(); + //ipp.dispose(); } } catch (IOException e) { e.printStackTrace(); @@ -88,10 +109,10 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A }); }else { - NetworkPacket.databufferpool_65535.back(tmp); + //NetworkPacket.databufferpool_65535.back(tmp); } } catch (Exception e) { - NetworkPacket.databufferpool_65535.back(tmp); + //NetworkPacket.databufferpool_65535.back(tmp); e.printStackTrace(); } } @@ -110,9 +131,16 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A e.printStackTrace(); }finally { slok.unlock(); - NetworkPacket.databufferpool_65535.back(tmp); + //NetworkPacket.databufferpool_65535.back(tmp); } } else { + for(SRv6PacketReorder spr:reorder.values()) { + try { + spr.runOrdering(); + } catch (IOException e) { + e.printStackTrace(); + } + } LockSupport.parkNanos(1000000L); } @@ -132,48 +160,84 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A private SpeedAndTrafficMonitorDataImpl monitor; + private ConcurrentHashMap reorder=new ConcurrentHashMap<>(); + @Override public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException { - if (tun != null) {/* - * AtomicLong seqs=null; try { IPv6RoutingHeader - * srhh=getRoutingHeaderFromPacket(pack); if(srhh!=null) { byte[]srd=new - * byte[(int) (srhh.getLength()-4)]; srhh.getData().get(4, srd); - * IpV6RoutingSRHData srh=IpV6RoutingSRHData.newInstance( srd,0,srd.length); - * SRv6StreamSequenceTLV ssqv= getStreamSequenceTLV(srh); if(ssqv!=null) - * seqs=new AtomicLong( ssqv.getSequence()); } }catch(IllegalRawDataException - * re) { - * - * } - */ - - // System.out.println("add"); - while(exc.getQueue().size()>10) { - LockSupport.parkNanos(1000000); - } - exc.execute(()->{ - ByteBuffer tmp = NetworkPacket.databufferpool_65535.borrow(); + if (tun != null) { + + + + try { // System.out.println("rev"); - pack.writeToChannel(KNEChannels.newWritableChannel(tmp)); - monitor.getInPacketCounterAL().incrementAndGet(); - monitor.getInTrafficAL().addAndGet(pack.getLength()); - tmp.flip(); - sendQueue.add(tmp); - LockSupport.unpark(tr); + IPv6SegmentRoutingHeader srh= pack.getSRHHeader(); + SEQSSegmentRoutingTLV seqs=null; + if(srh!=null) { + List l=srh.getTlvs(); + + for (int i = 0; i < l.size(); i++) { + IPv6SegmentRoutingTLV tlv=l.get(i); + if(tlv instanceof SEQSSegmentRoutingTLV) { + seqs=(SEQSSegmentRoutingTLV) tlv; + break; + } + } + } + + + sendPacket0(pack,seqs); } catch (IOException e) { - NetworkPacket.databufferpool_65535.back(tmp); + //NetworkPacket.databufferpool_65535.back(tmp); e.printStackTrace(); } - pack.disposeAll(); - }); + //pack.disposeAll(); + } else { - pack.disposeAll(); + //pack.disposeAll(); } } + private void sendPacket0(IPv6Packet pack,SEQSSegmentRoutingTLV seqs) throws IOException { + + if(seqs!=null&&seqs.isKeepOrder()) { + FlowSession fss=pack.getFlowSession(); + + + SRv6PacketReorder newr= new SRv6PacketReorder(new PacketConsumer() { + + @Override + public void accept(IPv6Packet packx) throws IOException { + ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535); + packx.writeToChannel(KNEChannels.newWritableChannel(tmp)); + monitor.getInPacketCounterAL().incrementAndGet(); + monitor.getInTrafficAL().addAndGet(packx.getLength()); + tmp.flip(); + sendQueue.add(tmp); + LockSupport.unpark(tr); + } + }); + SRv6PacketReorder olr=reorder.putIfAbsent(fss,newr); + if(olr==null) { + olr=newr; + } + olr.put(pack,seqs.getSequence()); + + + }else { + ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535); + pack.writeToChannel(KNEChannels.newWritableChannel(tmp)); + monitor.getInPacketCounterAL().incrementAndGet(); + monitor.getInTrafficAL().addAndGet(pack.getLength()); + tmp.flip(); + sendQueue.add(tmp); + LockSupport.unpark(tr); + } + } + private SRv6StreamSequenceTLV getStreamSequenceTLV(IpV6RoutingSRHData srh) { List stv = srh.getTlvs(); for (Iterator iterator = stv.iterator(); iterator.hasNext();) { @@ -199,8 +263,8 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A } @Override - public boolean isCongress(IPv6Packet iPv6Packet) { - return sendQueue.size() > 1000; + public boolean isCongress(IPv6Packet iPv6Packet,double scale) { + return sendQueue.size() > 1000*scale; } @Override @@ -243,6 +307,36 @@ public class IPv6TUNLoopbackNetworkLink implements IPv6NetworkLink, Closeable, A return hostAddress; } - + @Override + public void setRerouteConsumer(Consumer rerouteConsumer) { + + } + + @Override + public List getRouteItems() { + List rlist=new ArrayList<>(); + + rlist.add(new RouteItem(new Inet6AddressGroup(this.getAddressGroup().getAddress(), 128), + this.getAddressGroup().getAddress(), this, "Direct", 0, 1, null, "D",true)); + + for (Iterator iteratorx = getNeighborsInfo() + .iterator(); iteratorx.hasNext();) { + Neighbor addresses = (Neighbor) iteratorx.next(); + RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(), + this, "Direct", 0, 128, addresses.getMonitor(), "D",false); + rlist.add(ri); + + RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(), + this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false); + rlist.add(ris); + + } + return rlist; + } + + @Override + public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) { + return false; + } } diff --git a/src/org/kne/cloud/network/ipv6/Inet6AddressGroup.java b/src/org/kne/cloud/network/ipv6/Inet6AddressGroup.java index 030c13e..fea8b16 100644 --- a/src/org/kne/cloud/network/ipv6/Inet6AddressGroup.java +++ b/src/org/kne/cloud/network/ipv6/Inet6AddressGroup.java @@ -63,13 +63,43 @@ public class Inet6AddressGroup implements Comparable{ public int getPrefixLength() { return prefixLength; } + private byte[] cachedRawAddress; + public byte[] getRawAddress() { + if(cachedRawAddress==null) { + return (cachedRawAddress=address.getAddress()); + }else { + return cachedRawAddress; + } + } + private byte[] cachedAndm; + private byte[] getAndm(byte[]mask) { + if(cachedAndm==null) { + return (cachedAndm=and0(mask ,getRawAddress())); + }else { + return cachedAndm; + } + } public boolean checkMatch(Inet6Address ia) { byte[]mask=maskTransf[prefixLength]; - byte[]andj=and0(mask,ia.getAddress()); - byte[]andm=and0(mask ,address.getAddress()); - return Arrays.equals(andj,andm); + byte[]andm=getAndm(mask); + + return andeq0(mask,ia.getAddress(),andm); } - private byte[] and0(byte[] bs, byte[] address2) { + public boolean checkMatch(byte[] ia) { + byte[]mask=maskTransf[prefixLength]; + byte[]andm=getAndm(mask); + + return andeq0(mask,ia,andm); + } + private static boolean andeq0(byte[] bs, byte[] address2, byte[] andm) { + for (int i = 0; i < bs.length; i++) { + if(andm[i]!=(byte) (bs[i]&address2[i])) { + return false; + } + } + return true; + } + private static byte[] and0(byte[] bs, byte[] address2) { byte[]rez=new byte[bs.length]; for (int i = 0; i < rez.length; i++) { rez[i]=(byte) (bs[i]&address2[i]); @@ -90,4 +120,5 @@ public class Inet6AddressGroup implements Comparable{ address=(Inet6Address) Inet6Address.getByAddress(b); prefixLength=in.read(); } + } diff --git a/src/org/kne/cloud/network/ipv6/Neighbor.java b/src/org/kne/cloud/network/ipv6/Neighbor.java index e379e29..bdd53b3 100644 --- a/src/org/kne/cloud/network/ipv6/Neighbor.java +++ b/src/org/kne/cloud/network/ipv6/Neighbor.java @@ -5,11 +5,14 @@ import java.net.InetAddress; import java.util.Objects; import org.kne.cloud.network.monitor.MonitorData; +import org.kne.cloud.network.monitor.QueueingMonitorDataImpl; +import org.kne.cloud.network.te.BandwidthDistributer; public class Neighbor { private Inet6AddressGroup address; private Inet6AddressGroup locator; private MonitorData monitor; + private BandwidthDistributer bandwidthDistributer; public MonitorData getMonitor() { return monitor; } @@ -19,12 +22,21 @@ public class Neighbor { public Inet6AddressGroup getLocator() { return locator; } + + public BandwidthDistributer getBandwidthDistributer() { + return bandwidthDistributer; + } public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor) { super(); this.address = address; this.locator = locator; this.monitor = monitor; } + public Neighbor(Inet6AddressGroup peerAddress, Inet6AddressGroup remoteVaddr, QueueingMonitorDataImpl monitor2, + BandwidthDistributer bandwidthDistributer) { + this(peerAddress,remoteVaddr,monitor2); + this.bandwidthDistributer=bandwidthDistributer; + } @Override public String toString() { return "Neighbor [address=" + address + ", locator=" + locator + ", monitor=" + monitor + "]"; diff --git a/src/org/kne/cloud/network/ipv6/RouteItem.java b/src/org/kne/cloud/network/ipv6/RouteItem.java index 56ad9b4..38f6d83 100644 --- a/src/org/kne/cloud/network/ipv6/RouteItem.java +++ b/src/org/kne/cloud/network/ipv6/RouteItem.java @@ -11,7 +11,7 @@ import org.kne.cloud.network.monitor.DelayMonitorData; import org.kne.cloud.network.monitor.MonitorData; import org.kne.cloud.network.monitor.QueueingMonitorDataImpl; -public class RouteItem implements Comparable{ +public class RouteItem implements Comparable,Cloneable{ private Inet6AddressGroup destination; private Inet6Address nexthop; private IPv6NetworkLink destlink; @@ -20,6 +20,7 @@ public class RouteItem implements Comparable{ private long cost; private String flag; private MonitorData monitor; + private boolean isLoopback; public String getFlag() { return flag; } @@ -44,7 +45,7 @@ public class RouteItem implements Comparable{ && pre == other.pre && Objects.equals(proto, other.proto); } public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre, - long cost,String flag) { + long cost,String flag,boolean isLoopback) { super(); this.destination = destination; this.nexthop = nexthop; @@ -53,9 +54,10 @@ public class RouteItem implements Comparable{ this.pre = pre; this.cost = cost; this.flag=flag; + this.isLoopback=isLoopback; } public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre, - long cost,MonitorData monitor,String flag) { + long cost,MonitorData monitor,String flag,boolean isLoopback) { super(); this.destination = destination; this.nexthop = nexthop; @@ -65,6 +67,7 @@ public class RouteItem implements Comparable{ this.cost = cost; this.monitor=monitor; this.flag=flag; + this.isLoopback=isLoopback; } public Inet6AddressGroup getDestination() { return destination; @@ -81,6 +84,9 @@ public class RouteItem implements Comparable{ public int getPre() { return pre; } + public boolean isLoopback() { + return isLoopback; + } @Override public String toString() { return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop().getHostAddress()+"\t"+getDestlink().getName(); @@ -91,6 +97,9 @@ public class RouteItem implements Comparable{ public boolean checkMatch(Inet6Address ia) { return destination.checkMatch(ia); } + public boolean checkMatch(byte[] ia) { + return destination.checkMatch(ia); + } @Override public int compareTo(RouteItem o) { int v1=destination.compareTo(o.destination); @@ -105,7 +114,35 @@ public class RouteItem implements Comparable{ if(monitor==null||o.monitor==null||(!(monitor instanceof DelayMonitorData))||(!(o.monitor instanceof DelayMonitorData))) return v3; if(!(monitor instanceof QueueingMonitorDataImpl)||!(o.monitor instanceof QueueingMonitorDataImpl)) - return Long.compare(((DelayMonitorData)monitor).getOutDelay(), ((DelayMonitorData)o.monitor).getOutDelay()); - return Long.compare(((DelayMonitorData)monitor).getOutDelay()+((QueueingMonitorDataImpl)monitor).getQueueingDelay(), ((DelayMonitorData)o.monitor).getOutDelay()+((QueueingMonitorDataImpl)o.monitor).getQueueingDelay()); + return Long.compare(outDelay, o.outDelay); + return Long.compare(outDelay+queueingDelay, o.outDelay+o.queueingDelay); } + @Override + public Object clone() { + try { + RouteItem ri=(RouteItem) super.clone(); + if(monitor!=null) + ri.monitor=(MonitorData) monitor.clone(); + return ri; + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + + long outDelay; + long queueingDelay; + public void preSort() { + if(monitor!=null) { + outDelay=((DelayMonitorData)monitor).getOutDelay(); + if(monitor instanceof QueueingMonitorDataImpl) { + queueingDelay=((QueueingMonitorDataImpl)monitor).getQueueingDelay(); + } + } + } + public boolean ECMPequals(RouteItem prevr) { + return prevr.getDestination().getPrefixLength()==getDestination().getPrefixLength()&&prevr.getPre()==getPre()&&prevr.getCost()==getCost(); + + } + } diff --git a/src/org/kne/cloud/network/ipv6/TLV.java b/src/org/kne/cloud/network/ipv6/TLV.java new file mode 100644 index 0000000..1ad6d81 --- /dev/null +++ b/src/org/kne/cloud/network/ipv6/TLV.java @@ -0,0 +1,96 @@ +package org.kne.cloud.network.ipv6; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +import org.kne.cloud.network.NetworkPacket; + +public class TLV extends NetworkPacket{ + +private int headerLength=2; + + public int getHeaderLength() { + return headerLength; + } + + private boolean isDefault; + + protected volatile ByteBuffer header; + + private ByteBuffer data; + + + + public ByteBuffer getData() { + return data; + } + + @Override + public long getLength() { + return headerLength+(isDefault?data.limit():0); + } + @Override + public void writeToChannel(WritableByteChannel dto) throws IOException { + if(isDefault&&(headerLength>1)) { + setDataLength(data.limit()); + } + header.limit(headerLength); + dto.write(header.slice(0,header.limit())); + if(isDefault&&(headerLength>1)) { + dto.write(data.slice(0, data.limit())); + } + } + + @Override + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { + header.limit(1); + while (header.hasRemaining()) { + if (din.read(header) == -1) { + throw new EOFException(); + } + } + if(headerLength>1) { + header.limit(2); + while (header.hasRemaining()) { + if (din.read(header) == -1) { + throw new EOFException(); + } + } + } + header.flip(); + + if(isDefault&&(headerLength>1)) { + data.clear(); + data.limit(getDataLength()); + while(data.hasRemaining()){ + if(din.read(data)==-1) { + throw new EOFException(); + } + } + data.flip(); + } + } + + @Override + protected boolean needEndPosition() { + return false; + } + + public int getType() { + return header.get(0)&0xff; + } + public void setType(int type) { + header.put(0,(byte) type); + } + + public int getDataLength() { + return header.get(1)&0xff; + } + + public void setDataLength(int dataLength) { + header.put(1,(byte) dataLength); + } +} diff --git a/src/org/kne/cloud/network/klalb/ACKTPacket.java b/src/org/kne/cloud/network/klalb/ACKTPacket.java index 5095863..8b78f56 100644 --- a/src/org/kne/cloud/network/klalb/ACKTPacket.java +++ b/src/org/kne/cloud/network/klalb/ACKTPacket.java @@ -14,15 +14,15 @@ import java.util.concurrent.atomic.AtomicInteger; public class ACKTPacket extends KLALBPacket implements PortPacket { - private static final int HEADER_LENGTH=28; + private static final int HEADER_LENGTH=35; - public ACKTPacket(int sport,int dport,long number,boolean avaliable,boolean congress,long rcvSpeed,int sendcount) { + public ACKTPacket(int sport,int dport,long number,long avaliableRcvWindow,boolean congress,long rcvSpeed,int sendcount) { super(ACKT,HEADER_LENGTH); klalbHeader.putInt(sport); klalbHeader.putInt(dport); klalbHeader.putLong(number); klalbHeader.put((byte) sendcount); - klalbHeader.put((byte) (avaliable?1:0)); + klalbHeader.putLong(avaliableRcvWindow); klalbHeader.put((byte) (congress?1:0)); klalbHeader.putLong(rcvSpeed); } @@ -33,7 +33,7 @@ public class ACKTPacket extends KLALBPacket implements PortPacket { @Override public String toString() { - return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] "+isAvaliable(); + return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] avaliable:"+getAvaliableRcvWindow(); } public int getSport() { @@ -41,7 +41,7 @@ public class ACKTPacket extends KLALBPacket implements PortPacket { } public boolean isCongress() { - return klalbHeader.get(19)!=0; + return klalbHeader.get(26)!=0; } public int getDport() { @@ -52,8 +52,8 @@ public class ACKTPacket extends KLALBPacket implements PortPacket { return klalbHeader.getLong(9); } - public boolean isAvaliable() { - return klalbHeader.get(18)!=0; + public long getAvaliableRcvWindow() { + return klalbHeader.getLong(18); } @@ -61,6 +61,6 @@ public class ACKTPacket extends KLALBPacket implements PortPacket { return klalbHeader.getInt(17); } public long getRcvSpeed() { - return klalbHeader.getLong(20); + return klalbHeader.getLong(27); } } \ No newline at end of file diff --git a/src/org/kne/cloud/network/klalb/ADDLINESPacket.java b/src/org/kne/cloud/network/klalb/ADDLINESPacket.java index 465a302..1b4b8aa 100644 --- a/src/org/kne/cloud/network/klalb/ADDLINESPacket.java +++ b/src/org/kne/cloud/network/klalb/ADDLINESPacket.java @@ -41,7 +41,7 @@ public class ADDLINESPacket extends KLALBPacket { @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { byte[]bta=lines.getBytes(Charset.forName("UTF-8")); klalbHeader.putChar(1,(char) bta.length); super.writeToChannel(dto); @@ -49,7 +49,7 @@ public class ADDLINESPacket extends KLALBPacket { } @Override - protected void readFromChannel(ReadableByteChannel din) throws IOException { + public void readFromChannel(ReadableByteChannel din) throws IOException { super.readFromChannel(din); int lth=klalbHeader.getChar(1); byte[]b=new byte[lth]; diff --git a/src/org/kne/cloud/network/klalb/AbstractKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/AbstractKLALBPacketLink.java new file mode 100644 index 0000000..75c59e8 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/AbstractKLALBPacketLink.java @@ -0,0 +1,97 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicLong; + +import org.kne.cloud.network.NetworkPacket; +import org.kne.io.KNEChannels; + +public abstract class AbstractKLALBPacketLink implements KLALBPacketLink { + + + private AtomicLong[] inputTrafficCounters; + private AtomicLong[] outputTrafficCounters; + private AtomicLong[] inputPacketsCounters; + private AtomicLong[] outputPacketsCounters; + @Override + public void setOutputPacketsCounters(AtomicLong[] outCounter) { + outputPacketsCounters=outCounter; + } + + @Override + public void setInputPacketsCounters(AtomicLong[] inCounter) { + inputPacketsCounters=inCounter; + + } + @Override + public void setOutputTrafficCounters(AtomicLong[] outCounter) { + this.outputTrafficCounters=outCounter; + } + + @Override + public void setInputTrafficCounters(AtomicLong[] inCounter) { + this.inputTrafficCounters=inCounter; + } + + public AtomicLong[] getInputTrafficCounters() { + return inputTrafficCounters; + } + + public AtomicLong[] getOutputTrafficCounters() { + return outputTrafficCounters; + } + + public AtomicLong[] getInputPacketsCounters() { + return inputPacketsCounters; + } + + public AtomicLong[] getOutputPacketsCounters() { + return outputPacketsCounters; + } + + protected void incOutput(int packetLength) { + if(outputTrafficCounters!=null) { + for(AtomicLong al:outputTrafficCounters) { + al.addAndGet(packetLength); + } + } + if(outputPacketsCounters!=null) { + for(AtomicLong al:outputPacketsCounters) { + al.incrementAndGet(); + } + } + } + + protected void incInput(int packetLength) { + if(inputTrafficCounters!=null) { + for(AtomicLong al:inputTrafficCounters) { + al.addAndGet(packetLength); + } + } + if(inputPacketsCounters!=null) { + for(AtomicLong al:inputPacketsCounters) { + al.incrementAndGet(); + } + } + } + + @Override + public void writeKLALBPacket(KLALBPacket kp) throws IOException { + ByteBuffer dataWrite=NetworkPacket.bufferAllocator.allocate((int) kp.getLength()); + //dataWrite.clear(); + KLALBPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel( dataWrite), kp); + dataWrite.flip(); + writePacket(dataWrite); + } + + @Override + public KLALBPacket readKLALBPacket() throws IOException { + ByteBuffer buffer=readPacket(); + if(buffer==null) { + return null; + } + return KLALBPacket.readKLALBPacketFromChannel(KNEChannels.newReadableChannel(buffer)); + } +} diff --git a/src/org/kne/cloud/network/klalb/ByteBufferPool.java b/src/org/kne/cloud/network/klalb/ByteBufferPool.java deleted file mode 100644 index 71dbeee..0000000 --- a/src/org/kne/cloud/network/klalb/ByteBufferPool.java +++ /dev/null @@ -1,113 +0,0 @@ -package org.kne.cloud.network.klalb; - -import java.nio.ByteBuffer; -import java.util.Queue; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReferenceArray; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.kne.concurrent.SpinLock; -import org.kne.debug.TimeDebugger; -/* -public class ByteBufferPool { - private Queue rec; - private int maxcount; - private int length; - private boolean direct; - public ByteBufferPool(int maxcount, int length,boolean direct) { - super(); - this.maxcount = maxcount; - this.length = length; - this.direct=direct; - rec=new ConcurrentLinkedQueue(); - } - public ByteBufferPool(int maxcount, int length) { - this(maxcount, length, true); - } - public void back(ByteBuffer b) { - if(b.capacity()!=length) - throw new IllegalArgumentException("wrong length"); - b.clear(); - rec.offer(b); - } - public ByteBuffer borrow() { - ByteBuffer b=rec.poll(); - if(b==null) { - if(direct) - b=ByteBuffer.allocateDirect(length); - else - b=ByteBuffer.allocate(length); - } - return b; - } - public int getMaxCount() { - return maxcount; - } - public int getLength() { - return length; - } - -}*/ - -public class ByteBufferPool { - private ByteBuffer[]rec; - private volatile int pos=0; - private Lock lock=new SpinLock(); - - private int maxcount; - private int length; - private int mcj; - private boolean direct; - public ByteBufferPool(int maxcount, int length,boolean direct) { - super(); - this.maxcount = maxcount; - this.length = length; - this.direct=direct; - rec=new ByteBuffer[maxcount]; - mcj=rec.length-1; - } - public ByteBufferPool(int maxcount, int length) { - this(maxcount, length, true); - } - public void back(ByteBuffer b) { - if(b.capacity()!=length) - throw new IllegalArgumentException("wrong length"); - b.clear(); - lock.lock(); - try { - if(pos0) { - b=rec[pos--]; - //rec[pos--]=null; - } - }finally{ - lock.unlock(); - } - if(b==null) { - if(direct) - b=ByteBuffer.allocateDirect(length); - else - b=ByteBuffer.allocate(length); - } - return b; - } - public int getMaxCount() { - return maxcount; - } - public int getLength() { - return length; - } - -} diff --git a/src/org/kne/cloud/network/klalb/CONST.java b/src/org/kne/cloud/network/klalb/CONST.java index e0c8fea..eef23b2 100644 --- a/src/org/kne/cloud/network/klalb/CONST.java +++ b/src/org/kne/cloud/network/klalb/CONST.java @@ -2,7 +2,11 @@ package org.kne.cloud.network.klalb; public class CONST { public static final String klalb="KLALB"; - public static final String klalbver="3.0"; + public static final String klalbver="3.2"; public static final int bversion=3; - public static final int sversion=0; + public static final int sversion=1; + public static final int itemwidth = 720; + public static final int linepanelheight = 45; + public static final int settingheight = 30; + } diff --git a/src/org/kne/cloud/network/klalb/DATATPacket.java b/src/org/kne/cloud/network/klalb/DATATPacket.java index 5d3f6ea..833e786 100644 --- a/src/org/kne/cloud/network/klalb/DATATPacket.java +++ b/src/org/kne/cloud/network/klalb/DATATPacket.java @@ -39,7 +39,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{ klalbHeader.putChar((char) 0); //dataBuffer.limit(mtulimit); - dataBuffer=ByteBuffer.allocate(mtulimit); + dataBuffer=NetworkPacket.bufferAllocator.allocate(mtulimit); } public int getSendcount() { @@ -100,7 +100,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{ } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { klalbHeader.put(17, (byte) getSendCounter()); klalbHeader.putChar(18, (char) dataBuffer.limit()); super.writeToChannel(dto); @@ -109,13 +109,13 @@ public class DATATPacket extends KLALBPacket implements PortPacket{ } @Override - protected void readFromChannel(ReadableByteChannel din) throws IOException { + public void readFromChannel(ReadableByteChannel din) throws IOException { super.readFromChannel(din); numberc=Long.MIN_VALUE; int limit=klalbHeader.getChar(18); //dataBuffer.clear(); //dataBuffer.limit(); - dataBuffer=ByteBuffer.allocate(limit); + dataBuffer=NetworkPacket.bufferAllocator.allocate(limit); while(dataBuffer.hasRemaining()){ if(din.read(dataBuffer)==-1) { throw new EOFException(); @@ -124,12 +124,5 @@ public class DATATPacket extends KLALBPacket implements PortPacket{ dataBuffer.flip(); } - @Override - public void dispose() { - super.dispose(); - /*ByteBuffer datan=dataBuffer; - dataBuffer=null; - NetworkPacket.databufferpool_65535.back(datan);*/ - } } diff --git a/src/org/kne/cloud/network/klalb/DatagramKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/DatagramKLALBPacketLink.java index 37e3da4..00629fc 100644 --- a/src/org/kne/cloud/network/klalb/DatagramKLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/DatagramKLALBPacketLink.java @@ -125,12 +125,14 @@ import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.SocketException; +import java.nio.ByteBuffer; import org.kne.cloud.network.DatagramServerSocket; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.SpeedLimiter; -public class DatagramKLALBPacketLink implements KLALBPacketLink { +public class DatagramKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink { @Override public String toString() { @@ -145,17 +147,20 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink { private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535); private DataOutputStream dos=new DataOutputStream(bos); - @Override - public void writePacket(KLALBPacket kp) throws IOException { + /*@Override + public void writeKLALBPacket(KLALBPacket kp) throws IOException { //System.out.println(" TX:"+kp); KLALBPacket.writeKLALBPacketToStream(dos, kp); - + byte[]bt=bos.toByteArray(); + DatagramPacket dp=new DatagramPacket(bt,bt.length); + ds.send(dp); + bos.reset(); } private byte[]bc=new byte[65535]; DataInputStream dis; @Override - public KLALBPacket readPacket() throws IOException { + public KLALBPacket readKLALBPacket() throws IOException { KLALBPacket kp=null; do { if(dis==null) { @@ -176,8 +181,37 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink { //System.out.println(" RX:"+kp); }while(true); return kp; + }*/ + + + byte[]b=new byte[65536]; + @Override + public void writePacket(ByteBuffer kp) throws IOException { + int length=kp.remaining(); + incOutput(length); + kp.get(b,0,length); + DatagramPacket dp=new DatagramPacket(b,length); + ds.send(dp); } + byte[]c=new byte[65536]; + @Override + public ByteBuffer readPacket() throws IOException { + DatagramPacket dp; + if(ds instanceof DatagramServerSocket.SubDatagramSocket) { + dp=((DatagramServerSocket.SubDatagramSocket) ds).receive(); + }else { + dp=new DatagramPacket(c, c.length); + ds.receive(dp); + } + incInput(dp.getLength()); + ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(dp.getLength()); + bbf.put(dp.getData(),0,dp.getLength()); + bbf.flip(); + return bbf; + } + + @Override public void close() throws IOException { ds.close(); @@ -200,10 +234,7 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink { @Override public void flush() throws IOException { - byte[]bt=bos.toByteArray(); - DatagramPacket dp=new DatagramPacket(bt,bt.length); - ds.send(dp); - bos.reset(); + } @@ -211,4 +242,6 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink { public boolean isStream() { return false; } + + } diff --git a/src/org/kne/cloud/network/klalb/IPSequence.java b/src/org/kne/cloud/network/klalb/IPSequence.java new file mode 100644 index 0000000..89fa913 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/IPSequence.java @@ -0,0 +1,47 @@ +package org.kne.cloud.network.klalb; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.util.Objects; +import java.util.UUID; + +public class IPSequence { + private UUID uuid; + private boolean isPromise; + + + public IPSequence(UUID uuid, boolean isPromise) { + super(); + this.uuid = uuid; + this.isPromise = isPromise; + } + + public UUID getUuid() { + return uuid; + } + + public boolean isPromise() { + return isPromise; + } + + @Override + public String toString() { + return "IPSequence [uuid=" + uuid + ", isPromise=" + isPromise + "]"; + } + @Override + public int hashCode() { + return Objects.hash(uuid); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + IPSequence other = (IPSequence) obj; + return Objects.equals(uuid, other.uuid); + } + +} diff --git a/src/org/kne/cloud/network/klalb/IPv6OverKLALBPacket.java b/src/org/kne/cloud/network/klalb/IPv6OverKLALBPacket.java index 0b40c87..2c18c92 100644 --- a/src/org/kne/cloud/network/klalb/IPv6OverKLALBPacket.java +++ b/src/org/kne/cloud/network/klalb/IPv6OverKLALBPacket.java @@ -10,26 +10,6 @@ import org.kne.cloud.network.ipv6.IPv6Packet; public class IPv6OverKLALBPacket extends KLALBPacket { private static final int HEADER_LENGTH=9; - @Override - public boolean isSomeDisposed() { - return super.isDisposed()||ipv6Packet.isSomeDisposed(); - } - - - - @Override - public void lockAll() { - super.lockAll(); - ipv6Packet.lockAll(); - } - - - - @Override - public void unlockAll() { - ipv6Packet.unlockAll(); - super.unlockAll(); - } @Override @@ -56,12 +36,6 @@ public class IPv6OverKLALBPacket extends KLALBPacket { super(bb,HEADER_LENGTH); this.ipv6Packet=new IPv6Packet(); } - - @Override - public void disposeAll() { - super.disposeAll(); - ipv6Packet.disposeAll(); - } public IPv6Packet getIPv6Packet() { return ipv6Packet; @@ -78,24 +52,16 @@ public class IPv6OverKLALBPacket extends KLALBPacket { } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { klalbHeader.putLong(1, ipv6Packet.getLength()); super.writeToChannel(dto); ipv6Packet.writeToChannel(dto); } @Override - protected void readFromChannel(ReadableByteChannel din,long length) throws IOException { + public void readFromChannel(ReadableByteChannel din,long length) throws IOException { super.readFromChannel(din,length); ipv6Packet.readFromChannel(din, klalbHeader.getLong(1)); } - - - @Override - public void doDisposeAfterSend() { - super.doDisposeAfterSend(); - ipv6Packet.doDisposeAfterSend(); - } - } diff --git a/src/org/kne/cloud/network/klalb/KLALBController.java b/src/org/kne/cloud/network/klalb/KLALBController.java index 6c9cad2..4731719 100644 --- a/src/org/kne/cloud/network/klalb/KLALBController.java +++ b/src/org/kne/cloud/network/klalb/KLALBController.java @@ -56,14 +56,18 @@ import org.kne.cloud.network.ipv6.IPv6TUNLoopbackNetworkLink; import org.kne.cloud.network.ipv6.Inet6AddressGroup; import org.kne.cloud.network.monitor.MonitorData; import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; +import org.kne.cloud.network.srv6.KLALBRoutingProtocol; import org.kne.cloud.network.srv6.PacketConsumer; import org.kne.cloud.network.srv6.SRv6Router; import org.kne.cloud.network.te.BandwidthDistributer; import org.kne.cloud.network.te.DWRRLoadingBalanceAlgorithm; +import org.kne.concurrent.DisruptorExecutor; import org.kne.concurrent.HighPerformanceExecutor; import org.kne.io.KNEChannels; import org.pcap4j.packet.IpV6Packet.IpV6Header; +import com.google.gson.JsonElement; + public class KLALBController { @@ -80,6 +84,12 @@ public class KLALBController { private static List ipmd=new ArrayList<>(); + private ListdnsAddresses=new ArrayList<>(); + + public List getDnsAddresses() { + return dnsAddresses; + } + private Timer twk=new Timer("网卡检测扫描计时器", true); { @@ -210,48 +220,49 @@ public class KLALBController { continue; } if(networkInterface.isUp()) { - boolean b=true; + + Enumerationei= networkInterface.getInetAddresses(); + loop:while (ei.hasMoreElements()) { + InetAddress bidr = (InetAddress) ei.nextElement(); + for (Iterator iterator = ipmd.iterator(); iterator.hasNext();) { IPMulticastDiscovery ipMulticastDiscovery = (IPMulticastDiscovery) iterator.next(); - if(networkInterface.equals(ipMulticastDiscovery.getNinterface())) { - b=false; - break; + if(networkInterface.equals(ipMulticastDiscovery.getNinterface())&&bidr.equals(ipMulticastDiscovery.getBind().getAddress())) { + continue loop; } } - if(b) { - /*InetAddress bidr=null; - Enumerationei= networkInterface.getInetAddresses(); - while (ei.hasMoreElements()) { - InetAddress inetAddress = (InetAddress) ei.nextElement(); - if(inetAddress instanceof Inet6Address) { - Inet6Address i6=(Inet6Address) inetAddress; - if(i6.getHostAddress().startsWith("fe80")) { - bidr=i6; - break; - } - } - - } - if(bidr!=null)*/ + + + try { - InetAddress bidr=InetAddress.getByName("::0"); - IPMulticastDiscovery ipd=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("ff02::2486"),DISCOVERY_PORT), networkInterface,selflineTable); + //InetAddress bidr=InetAddress.getByName("::0"); + + if(bidr instanceof Inet6Address) { + IPMulticastDiscovery ipd=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("ff02::2486"),DISCOVERY_PORT), networkInterface,selflineTable,10000L); ipd.setCon((mpa)->{ //System.out.println("添加本地IPv6链路:"+mpa); - addRemoteLines(mpa); + try { + if(!checkIsSelf(mpa)) + addRemoteLines(mpa); + } catch (UnknownHostException e) { + } }); ipd.start(); ipmd.add(ipd); - - bidr=InetAddress.getByName("0.0.0.0"); - IPMulticastDiscovery ipd2=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("224.0.0.86"),DISCOVERY_PORT), networkInterface,selflineTable); + }else if(bidr instanceof Inet4Address) { + //bidr=InetAddress.getByName("0.0.0.0"); + IPMulticastDiscovery ipd2=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("224.0.0.86"),DISCOVERY_PORT), networkInterface,selflineTable,10000L); ipd2.setCon((mpa)->{ //System.out.println("添加本地IPv4链路:"+mpa); - addRemoteLines(mpa); + try { + if(!checkIsSelf(mpa)) + addRemoteLines(mpa); + } catch (UnknownHostException e) { + } }); ipd2.start(); ipmd.add(ipd2); - + } System.out.println("添加网卡:"+networkInterface); }catch(BindException e) { //e.printStackTrace(); @@ -259,8 +270,11 @@ public class KLALBController { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); - } - } + } + + + } + //} } } @@ -270,6 +284,11 @@ public class KLALBController { } } + + private boolean checkIsSelf(MultipurposeSocketAddress inetAddress) throws UnknownHostException { + + return inetAddress.getInetAddress().isAnyLocalAddress()||inetAddress.getInetAddress().isLoopbackAddress()||selflineTable.contains(inetAddress); + } }, 2000, 2000); } public SpeedAndTrafficMonitorDataImpl getLinkMonitor() { @@ -326,10 +345,10 @@ public class KLALBController { } - private Inet6AddressGroup self; + //private Inet6AddressGroup self; - public Inet6Address getSelf() { - return self.getAddress(); + public Inet6AddressGroup getSelf() { + return srv6Router.getLocator(); } private List lines=new CopyOnWriteArrayList<>(); private ReadWriteLock lineslock=new ReentrantReadWriteLock(); @@ -339,11 +358,16 @@ public class KLALBController { } private PortBinder streamPortBinder=new PortBinder(this); + + private PortBinder rawPortBinder=new PortBinder(this); protected PortBinder getStreamPortBinder() { return streamPortBinder; } - + + public PortBinder getRawPortBinder() { + return rawPortBinder; + } public void reconnectImmediately() { for (Iterator iterator = lines.iterator(); iterator.hasNext();) { @@ -380,7 +404,8 @@ public class KLALBController { } - public List addRemoteLines(MultipurposeSocketAddress target) { + public List addRemoteLines(MultipurposeSocketAddress target) {lineslock.writeLock().lock(); + try { Listadded=new ArrayList<>(); try { Enumerationeu= NetworkInterface.getNetworkInterfaces(); @@ -419,6 +444,9 @@ public class KLALBController { } return added; + }finally { + lineslock.writeLock().unlock(); + } } public List removeRemoteLines(MultipurposeSocketAddress mpsa) { @@ -477,15 +505,15 @@ public class KLALBController { } public void addRemoteLine(KLALBRemoteLine krs) { + lineslock.writeLock().lock(); + try { krs.setPacketReceiver(prc); krs.setKlalbController(this); - krs.setLocalVaddrSupplier(()->{return self;}); + krs.setLocalVaddrSupplier(()->{return getSelf();}); krs.startIO(); String selflineTable=generateSelfLineTable(); if(selflineTable!=null&&!selflineTable.equals("")) krs.sendPacket(new ADDLINESPacket(selflineTable)); - lineslock.writeLock().lock(); - try { lines.add(krs); }finally { lineslock.writeLock().unlock(); @@ -502,16 +530,12 @@ public class KLALBController { } return sbd.toString(); } - - public KLALBController(Inet6Address self) { - this.self =new Inet6AddressGroup(self, PREFIX); - loadSRv6ProtocolStack(); - } + private class KLALBProtocolPacketConsumer implements PacketConsumer{ @Override public void accept(IPv6Packet packx) throws IOException { - HighPerformanceExecutor.defaultExecutor.execute(()->{ + //HighPerformanceExecutor.defaultExecutor.execute(()->{ /*System.out.println("RCV:"+packx.getPayload().getData()); byte[]b=new byte[packx.getPayload().getData().limit()]; @@ -539,18 +563,18 @@ public class KLALBController { } } } - packx.dispose(); - }); + //packx.dispose(); + //}); } } - private void loadSRv6ProtocolStack() { - srv6Router=new SRv6Router(self); + private void loadSRv6ProtocolStack(Inet6AddressGroup selfx,boolean enableVirtualAdapter) { + srv6Router=new SRv6Router(selfx); + if(enableVirtualAdapter) try { - IPv6TUNLoopbackNetworkLink tunlink=new IPv6TUNLoopbackNetworkLink(new Inet6AddressGroup( srv6Router.getLocator().getAddress(),32),SRv6Router.MTU); + IPv6TUNLoopbackNetworkLink tunlink=new IPv6TUNLoopbackNetworkLink(new Inet6AddressGroup( srv6Router.getLocator().getAddress(),32),SRv6Router.MTU, dnsAddresses); tunlink.setMonitor(datatMonitor); srv6Router.getLinkTabel().add(tunlink); - Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } @@ -558,8 +582,19 @@ public class KLALBController { srv6Router.getProtocolNumberRegister().put(KLALBPacket.KLALB_PROTOCOL_NUMBER,new KLALBProtocolPacketConsumer()); System.out.println("SRv6协议栈已加载"); } - public KLALBController() { + this(true,null); + } + public KLALBController (Inet6Address self) { + this(self,true,null); + } + public KLALBController(Inet6Address self,boolean enableVirtualAdapter,List dnsaddr) { + this.dnsAddresses=dnsaddr; + Inet6AddressGroup selfg =new Inet6AddressGroup(self, PREFIX); + loadSRv6ProtocolStack(selfg,enableVirtualAdapter); + } + public KLALBController(boolean enableVirtualAdapter,List dnsaddr) { + this.dnsAddresses=dnsaddr; SecureRandom sc=new SecureRandom(); byte[]v=new byte[16]; sc.nextBytes(v); @@ -569,27 +604,31 @@ public class KLALBController { v[3]=1; v[14]=0; v[15]=1; + Inet6AddressGroup selfx=null; try { - this.self=new Inet6AddressGroup( (Inet6Address) InetAddress.getByAddress(v),PREFIX); + selfx=new Inet6AddressGroup( (Inet6Address) InetAddress.getByAddress(v),PREFIX); } catch (UnknownHostException e) { e.printStackTrace(); } - loadSRv6ProtocolStack(); + loadSRv6ProtocolStack(selfx,enableVirtualAdapter); + } + + public KLALBController(List daddr) { + this(true,daddr); + } + + public KLALBController(Inet6Address self, List daddr) { + this(self,true,daddr); + } + + public KLALBController(boolean enableVirtualAdapter) { + this(enableVirtualAdapter,null); } protected KLALBVirtualSocketImpl createVirtualImpl() { return new KLALBVirtualSocketImpl(this); } - - - - - protected void sendPacketToLinkAddress(Inet6Address addr, KLALBPacket packet) - throws IOException { - sendPacketToLinkAddress(addr, packet, 1); - } - private SRv6Router srv6Router; @@ -603,7 +642,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true); @Override public void run() { - Map> lines2 =new ConcurrentHashMap<>(); + //Map> lines2 =new ConcurrentHashMap<>(); for (Iterator iterator = lines.iterator(); iterator.hasNext();) { KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next(); if(klalbRemoteLine.isClosed()) { @@ -615,20 +654,20 @@ private Timer trtr=new Timer("路由表刷新计时器", true); } }else { if(klalbRemoteLine.getRemoteVaddr()!=null&&klalbRemoteLine.getMonitor().getState()==MonitorData.ONLINE) { - if(lines2.containsKey(klalbRemoteLine.getRemoteVaddr())) { + /* if(lines2.containsKey(klalbRemoteLine.getRemoteVaddr())) { lines2.get(klalbRemoteLine.getRemoteVaddr()).getEntries().add(klalbRemoteLine); }else { ArrayListal1=new ArrayList<>(); al1.add(klalbRemoteLine); lines2.put(klalbRemoteLine.getRemoteVaddr().getAddress(), new DWRRLoadingBalanceAlgorithm<>(al1)); - } + }*/ if(!srv6Router.getLinkTabel().contains(klalbRemoteLine)) { srv6Router.getLinkTabel().add(klalbRemoteLine); } } } } - for (Iterator>> iterator = lines2.entrySet().iterator(); iterator.hasNext();) { + /*for (Iterator>> iterator = lines2.entrySet().iterator(); iterator.hasNext();) { Entry> klalbRemoteLine = (Entry>) iterator.next(); List lineList=klalbRemoteLine.getValue().getEntries(); lineList.forEach((r)->{ @@ -641,7 +680,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true); } } - KLALBController.this.lines2=lines2; + KLALBController.this.lines2=lines2;*/ if(srv6Router!=null) { srv6Router.getLinkTabel().removeIf((v)->{ return (v instanceof KLALBRemoteLine)&&(!v.isUp()); @@ -649,7 +688,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true); srv6Router.updateRouteTabel(); } } - }, 1, 1); + }, 2, 2); } /*private void updateLines2(Inet6Address addr) throws SocketTimeoutException { List l=new ArrayList(); @@ -675,122 +714,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true); lines2.put(addr, l); } }*/ - private Map> lines2 = new ConcurrentHashMap<>(); - - - protected void sendPacketToLinkAddress(Inet6Address addr, KLALBPacket packet, int count) - throws IOException { - if(packet==null) - throw new NullPointerException("packet is null!"); - //TimeDebugger tdb=new TimeDebugger(); - - - //tdb.putTime("start"); - packet.genseq(); - /*loop:while(true) { - if(packet.isDisposed()) - return; - List lines2x; - - lines2x=lines2.get(addr); - - if (lines2x == null || lines2x.isEmpty()) { - throw new NoRouteToHostException("address unreachable: " + addr); - } - - int count0 = Math.min(count, lines2x.size()); - - for (int i = 0; i < lines2x.size(); i++) { - KLALBRemoteLine krst =lines2x.get(i); - if(krst.getMonitor().getState()==MonitorData.ONLINE) - if(!packet.getSendRecord().contains(krst)) { - if(krst.getQueue().size()<10) { - packet.getSendRecord().add(krst); - //System.out.println(krst); - krst.sendPacket(packet); - count0--; - if (count0 <= 0) - break loop; - } - } - } - for (int i = 0; i < lines2x.size(); i++) { - KLALBRemoteLine krst =lines2x.get(i); - if(krst.getMonitor().getState()==MonitorData.ONLINE) - if(packet.getSendRecord().contains(krst)) { - if(krst.getQueue().size()<10) { - packet.getSendRecord().add(krst); - //System.out.println(krst); - krst.sendPacket(packet); - count0--; - if (count0 <= 0) - break loop; - } - } - } - LockSupport.parkNanos(50000); - //tdb.putTime("sendfailed"); - }*/ - //tdb.putTime("sendsuccess"); - //tdb.print(); - - /* List lines2x; - lines2x=lines2.get(addr); - - if (lines2x == null || lines2x.isEmpty()) { - throw new NoRouteToHostException("address unreachable: " + addr); - } - KLALBRemoteLine kr= lines2x.get(0); - kr.sendPacket(packet); - packet.getSendRecord().add(kr);*/ - - /*loop:while(true) { - if(packet.isDisposed()) - return; - DWRRLoadingBalanceAlgorithm dwrlines2x; - - dwrlines2x=lines2.get(addr); - - if (dwrlines2x == null || dwrlines2x.getEntries().isEmpty()) { - throw new NoRouteToHostException("address unreachable: " + addr); - } - - Listlines2x=dwrlines2x.roundEntriesList(); - - int count0 = Math.min(count, lines2x.size()); - - for (int i = 0; i < lines2x.size(); i++) { - KLALBRemoteLine krst =lines2x.get(i); - if(krst.getMonitor().getState()==MonitorData.ONLINE) - if(!packet.getSendRecord().contains(krst)) { - if(krst.getQueue().size()<5) { - packet.getSendRecord().add(krst); - //System.out.println(krst); - krst.sendPacket(packet); - count0--; - if (count0 <= 0) - break loop; - } - } - } - for (int i = 0; i < lines2x.size(); i++) { - KLALBRemoteLine krst =lines2x.get(i); - if(krst.getMonitor().getState()==MonitorData.ONLINE) - if(packet.getSendRecord().contains(krst)) { - if(krst.getQueue().size()<5) { - packet.getSendRecord().add(krst); - //System.out.println(krst); - krst.sendPacket(packet); - count0--; - if (count0 <= 0) - break loop; - } - } - } - LockSupport.parkNanos(50000); - //tdb.putTime("sendfailed"); - }*/ - } + //private Map> lines2 = new ConcurrentHashMap<>(); @@ -804,11 +728,8 @@ private Timer trtr=new Timer("路由表刷新计时器", true); HighPerformanceExecutor.defaultExecutor.execute(()->{ IPv6Packet ipv=new IPv6Packet(); - packet.getDisposeLock().lock(); - try { - if(packet.isDisposed()) { - return; - } + + if(showpacket) System.out.println("KLALB_TX:"+packet); @@ -816,10 +737,15 @@ private Timer trtr=new Timer("路由表刷新计时器", true); ipv.setTrafficClass(0); ipv.setFlowLabel(flowlabel); ipv.setHopLimit(255); - ipv.setSourceAddress(self.getAddress()); + ipv.setSourceAddress(getSelf().getAddress()); ipv.setDestinationAddress(addr); ipv.setPriority(packet.getPriority()); + if(packet instanceof DATATPacket) { + ipv.setPromise(true); + } ipv.enableECN(); + /* if(b) + ipv.markCE();*/ ipv.setPayload(packet); //System.out.println(ipv.getPayload().getProtocolNumber()); /*System.out.println("SND:"+ipv.getPayload().getData()); @@ -828,13 +754,12 @@ private Timer trtr=new Timer("路由表刷新计时器", true); System.out.println(Arrays.toString(b));*/ //packet.getSendRecord().add(null); packet.incSendCounter(); - }finally { - packet.getDisposeLock().unlock(); - } + packet.putTimePassport("packedInIPv6"); packet.printPassport(); ipv.putTimePassport("packed"); - srv6Router.putProtocolNumberPacketAndInsertSRH(ipv); + srv6Router.insertSRHandRoutePacket(ipv); + //srv6Router.putProtocolNumberPacketAndInsertSRHAsync(ipv); }); } @@ -869,7 +794,11 @@ private Timer trtr=new Timer("路由表刷新计时器", true); try { BandwidthDistributer bdr= bandwidthDistrmap.get(targetaAddress); if(bdr==null) { - bandwidthDistrmap.put(targetaAddress, bdr=new BandwidthDistributer<>(1024*20000L*1024)); + bdr=new BandwidthDistributer<>(1024*20000L*1024); + bdr.setTotalRequestUpdateConsumer((treq)->{ + KLALBRoutingProtocol krp= srv6Router.getKlalbRouteProtol(); + krp.updateTotalRequestBandwidth(targetaAddress,treq);}); + bandwidthDistrmap.put(targetaAddress, bdr); } bdr.setDistrUpdateConsumer(portp, updateConsumer); @@ -920,7 +849,6 @@ private List listens=new CopyOnWriteArrayList<>(); } - /*@Override public void listen(MultipurposeSocketAddress msa) { // TODO 自动生成的方法存根 diff --git a/src/org/kne/cloud/network/klalb/KLALBInputStream.java b/src/org/kne/cloud/network/klalb/KLALBInputStream.java index 9a3f0d4..1a2a96a 100644 --- a/src/org/kne/cloud/network/klalb/KLALBInputStream.java +++ b/src/org/kne/cloud/network/klalb/KLALBInputStream.java @@ -8,10 +8,18 @@ import java.io.IOException; import java.io.InputStream; import java.io.StreamCorruptedException; import java.net.Inet6Address; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; + +import org.kne.cloud.network.NetworkPacket; +import org.kne.io.KNEChannels; public class KLALBInputStream extends DataInputStream { + private ReadableByteChannel channel; public KLALBInputStream(InputStream in) throws IOException { super(in); + channel=Channels.newChannel(in); byte[]b=new byte[5]; readFully(b); String s=new String(b,"ascii"); @@ -23,8 +31,16 @@ public class KLALBInputStream extends DataInputStream { if(bv!=CONST.bversion) throw new StreamCorruptedException("remote version is V"+bv+"."+sv+",not V"+CONST.klalbver); } - public KLALBPacket readPacket() throws IOException { + public KLALBPacket readKLALBPacket() throws IOException { + int len=readInt(); return KLALBPacket.readKLALBPacketFromStream(this); } + public ByteBuffer readPacket() throws IOException { + int len=readInt(); + ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(len); + bbf.limit(len); + KNEChannels.readFully(channel, bbf); + return bbf; + } } diff --git a/src/org/kne/cloud/network/klalb/KLALBMain.java b/src/org/kne/cloud/network/klalb/KLALBMain.java index 8c43720..8f610dc 100644 --- a/src/org/kne/cloud/network/klalb/KLALBMain.java +++ b/src/org/kne/cloud/network/klalb/KLALBMain.java @@ -20,6 +20,8 @@ import org.kne.cloud.network.ipv6.RouteItem; import org.kne.cloud.network.klalb.ui.KLALBStateGUI2; import org.kne.cloud.network.klalb.ui.UIEnv; import org.kne.cloud.network.perf.Kperf; +import org.kne.cloud.network.perf.MemcpyBenchmark; +import org.kne.cloud.network.perf.NodeBenchmark; import org.kne.debug.Debuger; public class KLALBMain { @@ -37,7 +39,7 @@ public class KLALBMain { KLALBProxySystem kpcje=new KLALBProxySystem(); kpcje.loadConfigJson(configJson); - System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getHostAddress()); + System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getAddress().getHostAddress()); try { openGUI(kpcje); }catch(RuntimeException e) { @@ -152,10 +154,40 @@ public class KLALBMain { System.out.println("请输入测速服务端地址:端口!"); } + break; + case "memcpy": + System.out.println("数组拷贝测试"); + for (int i = 0; i < 10; i++) { + MemcpyBenchmark. testArrayCopySpeed(256*1024*1024); + } + System.out.println("Bytebuffer拷贝测试"); + for (int i = 0; i < 10; i++) { + MemcpyBenchmark.testByteBufferCopySpeed(256*1024*1024); + } + System.out.println("Directbytebuffer分配测试"); + for (int i = 0; i < 10; i++) { + MemcpyBenchmark.testDirectByteBufferAllocateSpeed(65536); + } + System.out.println("Bytebuffer分配测试"); + for (int i = 0; i < 10; i++) { + MemcpyBenchmark.testByteBufferAllocateSpeed(65536); + } + System.out.println("BytebufferAllocator分配测试"); + for (int i = 0; i < 10; i++) { + MemcpyBenchmark.testByteBufferAllocatorSpeed(65536); + } break; //case "$$SYSTEM:": //System.out.println(); //break; + case "nodebenchmark": + int nodenumber=100; + if(sc.length>=2) { + nodenumber=Integer.parseInt(sc[1]); + } + NodeBenchmark nbc=new NodeBenchmark(kpcje.getKlalbController(),nodenumber); + nbc.startPerfing(); + break; default: System.out.println("未知命令,请输入help以查询命令说明"); } diff --git a/src/org/kne/cloud/network/klalb/KLALBOutputStream.java b/src/org/kne/cloud/network/klalb/KLALBOutputStream.java index 3dbf0f4..99abf2f 100644 --- a/src/org/kne/cloud/network/klalb/KLALBOutputStream.java +++ b/src/org/kne/cloud/network/klalb/KLALBOutputStream.java @@ -4,19 +4,29 @@ import java.io.DataOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.Inet6Address; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.WritableByteChannel; public class KLALBOutputStream extends DataOutputStream { + private WritableByteChannel channel; public KLALBOutputStream(OutputStream out) throws IOException { super(out); + this.channel=Channels.newChannel(out); byte[]b=new byte[] {'K','L','A','L','B'}; write(b); writeInt(CONST.bversion); writeInt(CONST.sversion); flush(); } - public void writePacket(KLALBPacket klb) throws IOException { + public void writeKLALBPacket(KLALBPacket klb) throws IOException { + writeInt((int) klb.getLength()); KLALBPacket.writeKLALBPacketToStream(this, klb); } + public void writePacket(ByteBuffer kp) throws IOException { + writeInt( kp.limit()); + channel.write(kp); + } } diff --git a/src/org/kne/cloud/network/klalb/KLALBPacket.java b/src/org/kne/cloud/network/klalb/KLALBPacket.java index d5c7302..0652e29 100644 --- a/src/org/kne/cloud/network/klalb/KLALBPacket.java +++ b/src/org/kne/cloud/network/klalb/KLALBPacket.java @@ -4,6 +4,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.IOException; +import java.io.StreamCorruptedException; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; @@ -15,6 +16,8 @@ import java.util.concurrent.atomic.AtomicLong; import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.ipv6.IPv6Packet; +import org.kne.cloud.network.perf.TEST1Packet; +import org.kne.cloud.network.perf.TESTNPacket; public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { public static final int KLALB_PROTOCOL_NUMBER=254; @@ -32,12 +35,13 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { public static final int VADDR=8; public static final int ADDLINES=9; public static final int NACKT=10; - public static final int TEST=11; + public static final int TESTN=11; public static final int VADDRACK=12; public static final int VADDRREQ=13; public static final int IPV6OVERKLALB=14; public static final int ADDR=15; public static final int ADDRREQ=16; + public static final int TEST1=17; //private static final int HEADER_CAPACITY = 32; @@ -45,7 +49,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { //public static final ByteArrayPool dataarraypool=new ByteArrayPool(5000, 8192); - protected volatile ByteBuffer klalbHeader; + protected ByteBuffer klalbHeader; protected KLALBPacket(ByteBuffer klalbHeader,int headerLength) { super(KLALB_PROTOCOL_NUMBER,false); @@ -55,7 +59,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { public KLALBPacket(int type,int headerLength) { super(KLALB_PROTOCOL_NUMBER,false); - klalbHeader=ByteBuffer.allocate(headerLength); + klalbHeader=NetworkPacket.bufferAllocator.allocate(headerLength); klalbHeader.put((byte) type); this.headerLength=headerLength; } @@ -83,7 +87,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { return joinqueuetime; } - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { sndtime=System.nanoTime(); dto.write(klalbHeader.slice(0, headerLength)); } @@ -93,7 +97,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { return false; } - protected void readFromChannel(ReadableByteChannel din,long length) throws IOException { + public void readFromChannel(ReadableByteChannel din,long length) throws IOException { klalbHeader.limit(headerLength); while(klalbHeader.hasRemaining()){ if(din.read(klalbHeader)==-1) { @@ -135,13 +139,6 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { return klalbHeader; } - public void dispose() { - super.dispose(); - /* ByteBuffer datax=klalbHeader; - klalbHeader=null; - if(datax!=null) - KLALBPacket.databufferpool_40.back(datax);*/ - } public static KLALBPacket readKLALBPacketFromStream(DataInputStream in) throws IOException { return readKLALBPacketFromChannel(Channels.newChannel(in)); @@ -149,14 +146,14 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { public static KLALBPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException { while(true) { - ByteBuffer bb=databufferpool_40.borrow(); + ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40); bb.limit(1); while(bb.hasRemaining()){ if(in.read(bb)==-1) { return null; } } - int type=bb.get(0); + int type=bb.get(0)&0xff; bb.limit(bb.capacity()); KLALBPacket klp; @@ -196,8 +193,8 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { klp=new NACKTPacket(bb); klp.readFromChannel(in); return klp; - case TEST: - klp=new TESTPacket(bb); + case TESTN: + klp=new TESTNPacket(bb); klp.readFromChannel(in); return klp; case VADDRACK: @@ -220,9 +217,13 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { klp=new ADDRREQPacket(bb); klp.readFromChannel(in); return klp; + case TEST1: + klp=new TEST1Packet(bb); + klp.readFromChannel(in); + return klp; } - //throw new StreamCorruptedException("unknown package type:"+type); - System.err.println("ignore unknown KLALBPacket type:"+type); + throw new StreamCorruptedException("unknown package type:"+type); + //System.err.println("ignore unknown KLALBPacket type:"+type); } } @@ -237,10 +238,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload { return null; } - public void doDisposeAfterSend() { - if(isDisposeAfterSend()) - dispose(); - } + private boolean ce=false; public void setCE(boolean ce) { this.ce=ce; diff --git a/src/org/kne/cloud/network/klalb/KLALBPacketLink.java b/src/org/kne/cloud/network/klalb/KLALBPacketLink.java index 4c64269..a069db6 100644 --- a/src/org/kne/cloud/network/klalb/KLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/KLALBPacketLink.java @@ -2,13 +2,26 @@ package org.kne.cloud.network.klalb; import java.io.IOException; import java.net.SocketException; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicLong; import org.kne.cloud.network.MultipurposeSocketAddress; public interface KLALBPacketLink { - public void writePacket(KLALBPacket kp) throws IOException; + public void setOutputTrafficCounters(AtomicLong[] al); + public void setOutputPacketsCounters(AtomicLong[] al); + public void setInputTrafficCounters(AtomicLong[] al); + public void setInputPacketsCounters(AtomicLong[] al); + public void writePacket(ByteBuffer kp) throws IOException; + public default void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException { + for (int i = 0; i < len; i++) { + writePacket(kpp[off+i]); + } + } + public void writeKLALBPacket(KLALBPacket kp) throws IOException; public void flush() throws IOException; - public KLALBPacket readPacket()throws IOException; + public KLALBPacket readKLALBPacket()throws IOException; + public ByteBuffer readPacket()throws IOException; public void close() throws IOException; public boolean isClosed(); public void setSoTimeout(int val) throws SocketException; diff --git a/src/org/kne/cloud/network/klalb/KLALBProxySystem.java b/src/org/kne/cloud/network/klalb/KLALBProxySystem.java index cdeda37..0db0fe4 100644 --- a/src/org/kne/cloud/network/klalb/KLALBProxySystem.java +++ b/src/org/kne/cloud/network/klalb/KLALBProxySystem.java @@ -11,11 +11,13 @@ import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -112,15 +114,43 @@ public class KLALBProxySystem { case "KLALBController": JsonElement vase= entry.get("VirtualAddress"); //System.out.println(vase); + Listdaddr=new ArrayList(); + JsonElement vdns= entry.get("DNS"); + if(vdns!=null) { + if(vdns instanceof JsonArray) { + JsonArray arr=(JsonArray) vdns; + for(JsonElement str:arr) { + try { + daddr.add((Inet6Address) InetAddress.getByName(str.getAsString())); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + }else { + try { + daddr.add((Inet6Address) InetAddress.getByName(vdns.getAsString())); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + } if(vase!=null) { try { - klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString())); + klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString()),daddr); } catch (UnknownHostException e) { e.printStackTrace(); } }else { - klalbController=new KLALBController(); + klalbController=new KLALBController(daddr); } + + + JsonElement vasn= entry.get("VirtualASN"); + if(vasn!=null) { + klalbController.getIpv6Router().setASN (Long.parseLong( vasn.getAsString())); + } + + JsonElement vsne=entry.get("VirtualSocketName"); //if(vsne!=null) { MultipurposeSocketAddress.getSocketTypeRegister().put(vsne.getAsString(), klalbController.getSocketType()); @@ -280,7 +310,7 @@ public class KLALBProxySystem { if(string.startsWith("SocketBridge")) { return new DefaultSocketBridgeFactory(); }else if(string.startsWith("MinecraftSocketBridge")) { - return new DefaultMinecraftSocketBridgeFactory(klalbController.getSelf(), Integer.parseInt(string.substring(21))); + return new DefaultMinecraftSocketBridgeFactory(klalbController.getSelf().getAddress(), Integer.parseInt(string.substring(21))); } throw new IllegalArgumentException("unknown SocketBridge type:"+string); } diff --git a/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java b/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java index 8561b68..954f83b 100644 --- a/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java +++ b/src/org/kne/cloud/network/klalb/KLALBRemoteLine.java @@ -5,42 +5,69 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.io.StreamCorruptedException; +import java.lang.foreign.MemorySegment; import java.net.Inet6Address; import java.net.InetAddress; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; import java.nio.channels.UnresolvedAddressException; import java.security.SecureRandom; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; import java.util.function.Supplier; - import org.kne.cloud.clock.AdjustedNanoClock; import org.kne.cloud.clock.ReliabilityBackoffTimeClock; +import org.kne.cloud.network.ByteBufferAllocator; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.SpeedLimiter; import org.kne.cloud.network.ThreadTool; import org.kne.cloud.network.ipv6.IPv6NetworkLink; import org.kne.cloud.network.ipv6.IPv6Packet; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6EmptyPayload; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader; import org.kne.cloud.network.ipv6.Inet6AddressGroup; import org.kne.cloud.network.ipv6.Neighbor; +import org.kne.cloud.network.ipv6.RouteItem; import org.kne.cloud.network.monitor.MonitorData; +import org.kne.cloud.network.monitor.NanoTimeSeries; import org.kne.cloud.network.monitor.QueueingMonitorDataImpl; import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl; +import org.kne.cloud.network.perf.TESTNPacket; +import org.kne.cloud.network.srv6.ACKSEQSSegmentRoutingTLV; +import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV; +import org.kne.cloud.network.srv6.SEQSSegmentRoutingTLV; +import org.kne.cloud.network.te.BandwidthDistributer; import org.kne.cloud.network.te.LoadingBalanceEntry; +import org.kne.concurrent.DisruptorExecutor; +import org.kne.concurrent.HighPerformanceExecutor; +import org.kne.io.KNEChannels; -public class KLALBRemoteLine implements IPv6NetworkLink,Comparable ,LoadingBalanceEntry{ +public class KLALBRemoteLine implements IPv6NetworkLink,Comparable { + + private static final int HEADER_CALIBRATE = 40; + private static final boolean debug = false; private static final boolean showpacket = false; @@ -221,10 +248,19 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable { //Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1); @@ -251,87 +287,153 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable { + Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1); + while((!kplink.isClosed()) && (!closed)) { + + Collectionvals= sendMap.values(); + for (Iterator iterator = vals.iterator(); iterator.hasNext();) { + SendItem sitm = (SendItem) iterator.next(); + if(System.nanoTime() -sitm.getSendtime()>RTO) { + iterator.remove(); + sendmapWindowUsed.addAndGet((int) -(sitm.getPacket().getPayload().getLength()+HEADER_CALIBRATE)); + //if(!kplink.isStream()) + if(sitm.getPacket().isPromise()) { + IPv6Packet pktr=sitm.getPacket(); + pktr.setPriority(pktr.getPriority()-1); + rerouteConsumer.accept(pktr); + } + //System.out.println("reroute"); + } + } + for (Iterator> iterator = recvedUIDMap.entrySet().iterator(); iterator.hasNext();) { + Entry sendItem = (Entry) iterator.next(); + if(System.nanoTime()-sendItem.getValue()>10000000000L) { + iterator.remove(); + } + + } + if(checkACKTime()) { + sendALLIPv6ACK(); + //System.out.println("ACK发送"); + } + try { + Thread.sleep(4); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }); + timer.start(); + Thread t = ThreadTool.makeVDaemonThreadIfSupport("远程发送线程", () -> { tlock = Thread.currentThread(); //tlock.setPriority(Thread.NORM_PRIORITY+1); try { - writePacketToKPL(new ADDRREQPacket()); - writePacketToKPL(new ADDRREQPacket()); + writeKLALBPacketToKPL(new ADDRREQPacket()); + writeKLALBPacketToKPL(new ADDRREQPacket()); if(addressGroup!=null) { - writePacketToKPL(new ADDRPacket(addressGroup)); - writePacketToKPL(new ADDRPacket(addressGroup)); + writeKLALBPacketToKPL(new ADDRPacket(addressGroup)); + writeKLALBPacketToKPL(new ADDRPacket(addressGroup)); } - writePacketToKPL(new VADDRREQPacket()); - writePacketToKPL(new VADDRREQPacket()); - writePacketToKPL(new VADDRPacket(localVaddrSupplier.get())); - writePacketToKPL(new VADDRPacket(localVaddrSupplier.get())); + writeKLALBPacketToKPL(new VADDRREQPacket()); + writeKLALBPacketToKPL(new VADDRREQPacket()); + writeKLALBPacketToKPL(new VADDRPacket(localVaddrSupplier.get())); + writeKLALBPacketToKPL(new VADDRPacket(localVaddrSupplier.get())); flushKPL(); - KLALBPacket kpp = null; + ByteBuffer[] kpp = null; + int kppslen=0; while ((!kplink.isClosed()) && (!closed)) { // TimeDebugger tdb=new TimeDebugger(); // tdb.putTime("start"); if(checkBandwidthReportTime()) { - sendIPacket(new BWINFPacket(monitor.getOutSpeedAvg2(), monitor.getInSpeedAvg2())); + sendIPacket(new BWINFPacket(monitor.getOutSpeedAvg(), monitor.getInSpeedAvg())); } if (checkPingTimeSleep()) { - writePacketToKPL(new PINGPacket(System.nanoTime())); + writeKLALBPacketToKPL(new PINGPacket(System.nanoTime())); if (remoteVaddr == null) - writePacketToKPL(new VADDRREQPacket()); + writeKLALBPacketToKPL(new VADDRREQPacket()); if(peerAddress==null) - writePacketToKPL(new ADDRREQPacket()); + writeKLALBPacketToKPL(new ADDRREQPacket()); }else { KLALBPacket kpip = IsendDequeList.poll(); if (kpip != null) { - writePacketToKPL(kpip); + writeKLALBPacketToKPL(kpip); }else { // tdb.putTime("Isend"); if (kpp == null) { - do { - kpp = sendDequeList.poll(); - } while (kpp != null && kpp.isDisposed()); - if(kpp==null) { + ByteBuffer tkpp = sendDequeList.poll(); + if(tkpp==null) { monitor.setQueueingDelay(0); + }else { + kpp=new ByteBuffer[10]; + kpp[0]=tkpp; + int i=1; + for(;i stime) { - stime = readTime; - } else { - stime = (stime * 999 + readTime) / 1000; - } - if (stime < 2000000000L) { - stime = 2000000000L; - }*/ - - // System.out.println(readTime); + ByteBuffer kppb = kplink.readPacket(); + kplink.setSoTimeout(3000); - kplink.setSoTimeout((int) (stime / 1000000)); - if (kpp == null) { + if (kppb == null) { break; } + + HighPerformanceExecutor.defaultExecutor.execute(()->{ + KLALBPacket kpp=null; + try { + kpp = KLALBPacket.readKLALBPacketFromChannel(KNEChannels.newReadableChannel(kppb)); + } catch (IOException e) { + e.printStackTrace(); + } + if(kpp==null) + return; + debugShowPacket("RX",kpp); switch (kpp.getType()) { case KLALBPacket.PING: sendIPacket(new PONGPacket(((PINGPacket) kpp).getTime() ,kpp.getRcvtime(), System.nanoTime())); @@ -404,29 +506,30 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable= 0 && DrcvDelayFactor >= 0) { @@ -436,7 +539,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable= congressSpeed) { congressSpeed = bwi.getDownSpeed(); } else { - congressSpeed = (congressSpeed * 999 + bwi.getDownSpeed()) / 1000; + congressSpeed = (congressSpeed * 199 + bwi.getDownSpeed()) / 200; } - congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * loadPercent)) ); + bandwidthDistributer.setTotalBandwidth (congressSpeed ); + congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * burstPercent)) ); + //reallimit=(int) (congress.getLimitspeed()*monitor.getLatencyMin()/1000000000L); + reallimit=(int) (Math.max(MIN_SPEED,(long) (congressSpeed*windowPercent ))*Math.max(2000000L,RTTMin)/1000000000L); // System.out.println(congressSpeed); break; case KLALBPacket.ADDRREQ: @@ -460,7 +566,13 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable l=srh.getTlvs(); + + for (int i = 0; i < l.size(); i++) { + IPv6SegmentRoutingTLV tlv=l.get(i); + if(tlv instanceof SEQSSegmentRoutingTLV) { + SEQSSegmentRoutingTLV seqs=(SEQSSegmentRoutingTLV) tlv; + // if(seqs.isPromise()) { + val=new IPSequence(seqs.getUUID(),seqs.isPromise()); + //} + + }else if(tlv instanceof ACKSEQSSegmentRoutingTLV) { + ACKSEQSSegmentRoutingTLV aseq=(ACKSEQSSegmentRoutingTLV) tlv; + l.remove(i); + i--; + + SendItem ipv6; + if((ipv6=sendMap.remove(aseq.getIPSequence()))!=null) { + sendmapWindowUsed.addAndGet((int) -(ipv6.getPacket().getPayload().getLength()+HEADER_CALIBRATE)); + long RTTC=System.nanoTime()-ipv6.getSendtime(); + if(RTTC<=RTTMin) { + RTTMin=RTTC; + }else { + RTTMin= (RTTMin*99999+RTTC)/100000; + } + if(firstUpdate.compareAndSet(true, false)) { + RTTAvg=RTTC; + RTTVar=RTTC/2; + + }else { + RTTVar=(RTTVar*3+Math.abs(RTTAvg-RTTC))/4; + RTTAvg= (RTTAvg*7+RTTC)/8; + } + RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4 + //System.out.println("remove:"+aseq.getSequence()+" "+sendMap.size()); + }else { + // System.out.println("miss:"+aseq.getSequence()+" "+sendMap.size()); + } + } + } + } + if(val!=null) + ackIDs.add(val); + /*if(val!=null&&peerAddress!=null) { + UUID val2=val; + HighPerformanceExecutor.defaultExecutor.execute(()->{ + IPv6Packet ipv=new IPv6Packet(); + ipv.setVersion(6); + ipv.setTrafficClass(0); + ipv.setFlowLabel(0); + ipv.setHopLimit(255); + ipv.setSourceAddress(addressGroup.getAddress()); + ipv.setDestinationAddress(peerAddress.getAddress()); + ipv.setPriority(0); + ipv.enableECN(); + IPv6SegmentRoutingHeader srh2=new IPv6SegmentRoutingHeader(); + srh2.getAddresses().add(peerAddress.getAddress()); + + srh2.getTlvs().add(new ACKSEQSSegmentRoutingTLV(val2,true)); + + ipv.getHeaders().add(srh2); + ipv.setPayload(new IPv6EmptyPayload()); + + sendIPacket(new IPv6OverKLALBPacket( ipv)); + //System.out.println("ack:"+val); + }); + }*/ + + if(ipv6con!=null) { + if(iv6.getPayload()instanceof IPv6EmptyPayload) { + //iv6.dispose(); + }else { + if(val!=null) { + Long l=recvedUIDMap.putIfAbsent(val.getUuid(), System.nanoTime()); + if(l==null) { + ipv6con.accept(iv6); + }else { + //System.out.println("虚假重传:"+val.getUuid()); + } + }else { ipv6con.accept(iv6); + } + } } break; default: - while (rec == null) { - Thread.sleep(1); - } + if(rec!=null) rec.accept( kpp); break; } + }); Thread.yield(); } + }catch(StreamCorruptedException sce) { + sce.printStackTrace(); } catch (IOException | UnresolvedAddressException e) { if (debug) e.printStackTrace(); - } catch (InterruptedException e) { + }catch(Exception e) { e.printStackTrace(); } finally { monitor.setState(MonitorData.OFFLINE); @@ -518,17 +715,14 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparablevals= sendMap.values(); + SendItem[]packs= vals.toArray(new SendItem[0]); + for (SendItem iPv6Packet : packs) { + rerouteConsumer.accept(iPv6Packet.getPacket()); + //System.out.println("重路由:"+iPv6Packet); } - }*/ + sendMap.clear(); + sendmapWindowUsed.set(0); } if (closed) { @@ -544,63 +738,98 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable ackIDs=new ConcurrentLinkedQueue<>(); + private volatile long prevAckTime=System.nanoTime(); + private volatile long ackInterval=1000000L; + private boolean checkACKTime() { + long cu = System.nanoTime(); + if (cu - prevAckTime > ackInterval) { + prevAckTime = cu; + return true; + } else { + return false; + } + } + private void sendALLIPv6ACK() { + if(peerAddress!=null) { + while(true) { + int rez=sendIPv6ACK(); + if(rez<=0) + break; + } + } + } + private int sendIPv6ACK() { + IPv6SegmentRoutingHeader srh2=new IPv6SegmentRoutingHeader(); + int adds=addACKSEQToSRH(srh2,40); + if(adds<=0) + return adds; + + //System.out.println(adds+"ACKS"); + + IPv6Packet ipv=new IPv6Packet(); + ipv.setVersion(6); + ipv.setTrafficClass(0); + ipv.setFlowLabel(0); + ipv.setHopLimit(255); + ipv.setSourceAddress(addressGroup.getAddress()); + ipv.setDestinationAddress(peerAddress.getAddress()); + ipv.setPriority(0); + ipv.enableECN(); + srh2.getAddresses().add(peerAddress.getAddress()); + + + ipv.getHeaders().add(srh2); + ipv.setPayload(new IPv6EmptyPayload()); + + sendIPacket(new IPv6OverKLALBPacket( ipv)); + //System.out.println("ack:"+val); + return adds; + } + private int addACKSEQToSRH(IPv6SegmentRoutingHeader srh,int maxAckCount){ + int i = 0; + for (; i < maxAckCount; i++) { + + IPSequence ackid= ackIDs.poll(); + if(ackid!=null) { + srh.getTlvs().add(new ACKSEQSSegmentRoutingTLV(ackid, ackid.isPromise())); + }else { + prevAckTime=System.nanoTime(); + return i; + } + } + return i; + } + private void flushKPL() throws IOException { kplink.flush(); } - private KLALBPacket readPacketFromKPL() throws IOException { - KLALBPacket packet = kplink.readPacket(); - if (showpacket) { - if (!(packet instanceof PINGPacket)) - if (!(packet instanceof PONGPacket)) - if (!(packet instanceof BWINFPacket)) - System.out.println("RX:" + packet); - } + private KLALBPacket readKLALBPacketFromKPL() throws IOException { + KLALBPacket packet = kplink.readKLALBPacket(); + debugShowPacket("RX",packet); if (packet != null) { packet.putTimePassport("received"); - long length=packet.getLength(); - monitor.getInTrafficAL().addAndGet(length); - monitor.getInPacketCounterAL().incrementAndGet(); - if (klalbController != null) - klalbController.getLinkMonitor().getInTrafficAL().addAndGet(length); - klalbController.getLinkMonitor().getInPacketCounterAL().incrementAndGet(); + } return packet; } - private void writePacketToKPL(KLALBPacket packet) throws IOException { - long length=packet.getLength(); - monitor.getOutTrafficAL().addAndGet(length); - monitor.getOutPacketCounterAL().incrementAndGet(); - if (klalbController != null) - klalbController.getLinkMonitor().getOutTrafficAL().addAndGet(length); - klalbController.getLinkMonitor().getOutPacketCounterAL().incrementAndGet(); - kplink.writePacket(packet); + private void writeKLALBPacketToKPL(KLALBPacket packet) throws IOException { + kplink.writeKLALBPacket(packet); packet.putTimePassport("sended"); packet.printPassport(); - if (showpacket) { - if (!(packet instanceof PINGPacket)) - if (!(packet instanceof PONGPacket)) - if (!(packet instanceof BWINFPacket)) - System.err.println("TX:" + packet); - } + debugShowPacket("TX",packet); } - private void writePacketToKPL(KLALBPacket packet,long length) throws IOException { - monitor.getOutTrafficAL().addAndGet(length); - monitor.getOutPacketCounterAL().incrementAndGet(); - if (klalbController != null) - klalbController.getLinkMonitor().getOutTrafficAL().addAndGet(length); - klalbController.getLinkMonitor().getOutPacketCounterAL().incrementAndGet(); - kplink.writePacket(packet); - + private void debugShowPacket(String label, KLALBPacket packet) { if (showpacket) { if (!(packet instanceof PINGPacket)) if (!(packet instanceof PONGPacket)) if (!(packet instanceof BWINFPacket)) - System.err.println("TX:" + packet); + System.err.println(label+":" + packet); } } @@ -622,7 +851,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable bwpingIntervalSleep) { @@ -667,16 +896,25 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable IsendDequeList = new ConcurrentLinkedQueue(); - private PriorityBlockingQueue sendDequeList = new PriorityBlockingQueue(); + private PriorityBlockingQueue sendDequeList = new PriorityBlockingQueue(); - public PriorityBlockingQueue getQueue() { + public PriorityBlockingQueue getQueue() { return sendDequeList; } protected void sendPacket(KLALBPacket blk) { + debugShowPacket("TX",blk); blk.markJoinqueuetime(); - sendDequeList.add(blk); + ByteBuffer buf=NetworkPacket.bufferAllocator.allocate((int) blk.getLength()); + try { + KLALBPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel(buf), blk); + buf.flip(); + sendDequeList.add(buf); LockSupport.unpark(tlock); + } catch (IOException e) { + // TODO 自动生成的 catch 块 + e.printStackTrace(); + } } private void sendIPacket(KLALBPacket blk) { @@ -688,21 +926,8 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable iterator = sendDequeList.iterator(); iterator.hasNext();) { - KLALBPacket queue = iterator.next(); - if (queue.getPriority() <= l) { - al.addAndGet(queue.getLength()); - } - - } - return al.get(); - } + + private volatile long predictTime; @@ -744,7 +969,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparableranks=new ArrayList(); private Consumer ipv6con; - @Override - public void noticeRank(int rank) { - while(rank>=ranks.size()) { - ranks.add(0.5); - } - for (int i = 0; i < ranks.size(); i++) { - if(i==rank) { - ranks.set(i, (ranks.get(i)*99.0+1.0D)/100.0); - }else { - ranks.set(i, ranks.get(i)*99.0/100.0); - } - } - } - - @Override - public double getWeightAtRank(int rank) { - while(rank>=ranks.size()) { - ranks.add(0.5); - } - return ranks.get(rank); - } - - public List getRanks() { - - return ranks; - } @Override public boolean isLoopBack() { return false; } + private BandwidthDistributer bandwidthDistributer=new BandwidthDistributer(); + @Override public List getNeighborsInfo() { Lisths=new ArrayList<>(); if(peerAddress!=null) { - hs.add(new Neighbor(peerAddress, remoteVaddr, monitor)); + hs.add(new Neighbor(peerAddress, remoteVaddr, monitor,bandwidthDistributer)); //System.out.println(peerAddress+" "+addressGroup); } return hs; @@ -821,26 +1021,77 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable sendMap= new ConcurrentHashMap<>(); + private AtomicInteger sendmapWindowUsed=new AtomicInteger(0); + private MaprecvedUIDMap=new ConcurrentHashMap(); + + private volatile int inputchachesize = 8192 * 4000; + private volatile int outputchachesize = 8192 * 240;//500 + private volatile int reallimit = 65536 ; + private Consumer rerouteConsumer; @Override public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException { - pack.lockAll(); - try { - if(pack.isSomeDisposed()) { - return; + //只有已连接的链路才能传输数据 + if(monitor.getState()==MonitorData.ONLINE) { + + //if(inet6Address.equals(remoteVaddr.getAddress())||inet6Address.equals(peerAddress.getAddress())) { + + //获得数据包的SRv6扩展头部 + IPv6SegmentRoutingHeader srh= pack.getSRHHeader(); + + IPSequence val=null; + if(srh!=null) { + List l=srh.getTlvs(); + for (int i = 0; i < l.size(); i++) { + IPv6SegmentRoutingTLV tlv=l.get(i); + if(tlv instanceof SEQSSegmentRoutingTLV) { + SEQSSegmentRoutingTLV seqs=(SEQSSegmentRoutingTLV) tlv; + //if(seqs.isPromise()) + //获得数据包的序号 + val=new IPSequence(seqs.getUUID(),seqs.isPromise()); + + break; + } + } + + if(val!=null) { + //放入滑动窗口中并记录缓冲区大小占用 + SendItem old= sendMap.put(val,new SendItem( pack)); + if(old!=null) { + sendmapWindowUsed.addAndGet((int) -(old.getPacket().getPayload().getLength()+HEADER_CALIBRATE)); + } + sendmapWindowUsed.addAndGet((int) (pack.getPayload().getLength()+HEADER_CALIBRATE)); + //System.out.println("add: "+ val+" "+sendMap.size()); + } + } + //捎带发送反方向的ACK给对方发送过来的数据包,减小设备性能开销 + if(srh!=null) { + addACKSEQToSRH(srh,10); + } + //发送数据包 + sendIPv6PacketToLink(pack); + //} + + }else { + if(rerouteConsumer!=null) { + rerouteConsumer.accept(pack); + } } - if(inet6Address.equals(remoteVaddr.getAddress())||inet6Address.equals(peerAddress.getAddress())) { + } + + @Override + public void setRerouteConsumer(Consumer rerouteConsumer) { + this.rerouteConsumer=rerouteConsumer; + } + + private void sendIPv6PacketToLink(IPv6Packet pack) { IPv6OverKLALBPacket kipv6=new IPv6OverKLALBPacket(pack); kipv6.setPriority(pack.getPriority()); - kipv6.setDisposeAfterSend(true); pack.putTimePassport("packdInLink"); pack.printPassport(); sendPacketToLink(kipv6); - } - }finally { - pack.unlockAll(); - } } private void sendPacketToLink(KLALBPacket packet) { @@ -850,13 +1101,18 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable30) { + public boolean isCongress(IPv6Packet iPv6Packet,double scale) { + if(monitor.getInDelay()>3000000000L||monitor.getOutDelay()>3000000000L||monitor.getInSpeedAvg()<=0||monitor.getOutSpeedAvg()<=0) return true; - }else { - return !congress.checkTransmit(iPv6Packet.getLength()); - } + boolean congress=sendmapWindowUsed.get()>reallimit*scale; + return congress; + + } + + @Override + public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) { + boolean xcongress=!congress.checkTransmit(iPv6Packet.getLength()); + return xcongress; } @Override @@ -879,6 +1135,30 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable getRouteItems() { + List rlist=new ArrayList<>(); + + Inet6AddressGroup adg=addressGroup; + if(adg!=null) + rlist.add(new RouteItem(new Inet6AddressGroup(adg.getAddress(), 128), + adg.getAddress(), this, "Direct", 0, 0, null, "D",true)); + + for (Iterator iteratorx = getNeighborsInfo() + .iterator(); iteratorx.hasNext();) { + Neighbor addresses = (Neighbor) iteratorx.next(); + RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(), + this, "Direct", 0, 128, addresses.getMonitor(), "D",false); + rlist.add(ri); + + RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(), + this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false); + rlist.add(ris); + + } + return rlist; + } + } diff --git a/src/org/kne/cloud/network/klalb/KLALBUtils.java b/src/org/kne/cloud/network/klalb/KLALBUtils.java index 1ff7c8d..467ca84 100644 --- a/src/org/kne/cloud/network/klalb/KLALBUtils.java +++ b/src/org/kne/cloud/network/klalb/KLALBUtils.java @@ -10,6 +10,8 @@ import java.net.UnknownHostException; import java.util.List; import java.util.UUID; import java.util.concurrent.LinkedBlockingQueue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.kne.cloud.network.MultipurposeSocketAddress; @@ -135,8 +137,28 @@ public class KLALBUtils { Color col=new Color( r,g,0); return col; } + public static Color getColorByLoadPercentagex(float f) { + int r=0; + int g=200; + if(f<50f) { + r+=f/50f*200f; + }else { + r=200; + g-=(f-50f)/50f*200f; + } + if(r>200) + r=200; + if(r<0) + r=0; + if(g>200) + g=200; + if(g<0) + g=0; + Color col=new Color( r,g,0); + return col; + } - public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress, MultipurposeSocketAddress targetAddress) + public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress, MultipurposeSocketAddress targetAddress,boolean buffered) throws IOException { if (targetAddress.isStream()) { if (targetAddress.supportNIO()) { @@ -164,14 +186,23 @@ public class KLALBUtils { } } public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress, - MultipurposeSocketAddress targetAddress, int timeout) throws UnknownHostException, IOException { + MultipurposeSocketAddress targetAddress,boolean buffered, int timeout) throws UnknownHostException, IOException { if (targetAddress.isStream()) { if (targetAddress.supportNIO()) { if (bindAddress != null) { + if(buffered) { + return new StreamChannelKLALBPacketLink(targetAddress + .connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout)); + }else { return new StreamChannelKLALBPacketLink(targetAddress .connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout)); + } } else { + if(buffered) { + return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel(timeout)); + }else { return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel(timeout)); + } } } else { if (bindAddress != null) { @@ -190,7 +221,116 @@ public class KLALBUtils { } } } - + public static final String IPv6Reg = "([\\da-fA-F]{1,4}:){7}[\\da-fA-F]{1,4}$" + + "|^:((:[\\da-fA-F]{1,4}){1,6}|:)$" + + "|^[\\da-fA-F]{1,4}:((:[\\da-fA-F]{1,4}){1,5}|:)$" + + "|^([\\da-fA-F]{1,4}:){2}((:[\\da-fA-F]{1,4}){1,4}|:)$" + + "|^([\\da-fA-F]{1,4}:){3}((:[\\da-fA-F]{1,4}){1,3}|:)$" + + "|^([\\da-fA-F]{1,4}:){4}((:[\\da-fA-F]{1,4}){1,2}|:)$" + + "|^([\\da-fA-F]{1,4}:){5}:([\\da-fA-F]{1,4})?$" + + "|^([\\da-fA-F]{1,4}:){6}:"; // IPv6地址的格式 + +/** + * 将一个IPv6地址转为全写格式,全写中的前导0省略 + * 例:将1ade:03da:0::转为1ade:3da:0:0:0:0:0:0 + * + * @param IPv6Str + * @return fullIPv6 + */ +public static String parseFullIPv6(String IPv6Str) { + // 判断IPv6地址的格式是否正确 + if (!IPv6Str.matches(IPv6Reg)) { + return ""; + } + + String[] arr = new String[]{"0", "0", "0", "0", "0", "0", "0", "0"}; + + // 将IPv6地址用::分开 + // 如果IPv6地址为::,tempArr.length==0 + // 如果不包含::或以::结尾,tempArr.length==1 + // 如果以::开头或::在中间,tempArr.length==2 + String[] tempArr = IPv6Str.split("::"); + + // tempArr[0]用:分开,填充到arr前半部分 + if (tempArr.length > 0) { + // new String[0]为空数组,因为"".split(":")为{""},如果tempArr[0]=="",此时数组包含一个元素 + String[] tempArr0 = tempArr[0].isEmpty() ? new String[0] : tempArr[0].split(":"); + for (int i = 0; i < tempArr0.length; i++) { + // 如果是纯数字,用parseInt去除前导0,如果包含字母,用正则去除前导0 + arr[i] = tempArr0[i].matches("\\d+") + ? (Integer.parseInt(tempArr0[i]) + "") + : tempArr0[i].replaceAll("^(0+)", ""); + } + } + + // tempArr[1]用:分开,填充到arr后半部分 + if (tempArr.length > 1) { + String[] tempArr1 = tempArr[1].isEmpty() ? new String[0] : tempArr[1].split(":"); + for (int i = 0; i < tempArr1.length; i++) { + arr[i + arr.length - tempArr1.length] = tempArr1[i].matches("\\d+") + ? (Integer.parseInt(tempArr1[i]) + "") + : tempArr1[i].replaceAll("^(0+)", ""); + } + } + + return join(arr, ":"); +} + +private static String join(String[] arr, String string) { + StringBuilder sb=new StringBuilder(); + for (int i = 0; i < arr.length; i++) { + sb.append(arr[i]); + if(i+1 0) { + for (int i = start; i < end; i++) { + arr[i] = ":"; + } + } + return join(arr, ":").replaceAll(":{2,}", "::"); +} } diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocket.java b/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocket.java new file mode 100644 index 0000000..d389ccd --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocket.java @@ -0,0 +1,24 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.Inet6Address; +import java.net.SocketException; + +import org.kne.cloud.network.RawSocket; +import org.kne.cloud.network.RawSocketImpl; +import org.kne.cloud.network.VirtualRawSocket; +import org.kne.cloud.network.srv6.SRv6Router; + +public class KLALBVirtualRawSocket extends VirtualRawSocket { + + public KLALBVirtualRawSocket(SRv6Router controller) { + super(new KLALBVirtualRawSocketImpl(controller)); + } + + public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress) throws SocketException { + super(new KLALBVirtualRawSocketImpl(controller),bindAddress); + } + public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress,int bindProtocol) throws SocketException { + super(new KLALBVirtualRawSocketImpl(controller),bindAddress,bindProtocol); + } +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocketImpl.java b/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocketImpl.java new file mode 100644 index 0000000..647a555 --- /dev/null +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualRawSocketImpl.java @@ -0,0 +1,272 @@ +package org.kne.cloud.network.klalb; + +import java.io.IOException; +import java.net.BindException; +import java.net.DatagramPacket; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.LockSupport; + +import org.kne.cloud.network.ByteBufferAllocator; +import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.RawSocketImpl; +import org.kne.cloud.network.ThreadTool; +import org.kne.cloud.network.VirtualRawSocketImpl; +import org.kne.cloud.network.ipv6.IPv6Packet; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload; +import org.kne.cloud.network.srv6.PacketConsumer; +import org.kne.cloud.network.srv6.SRv6Router; +import org.kne.concurrent.HighPerformanceExecutor; +import org.kne.io.KNEChannels; + +public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements PacketConsumer{ + + private boolean ipHeaderInclude=false; + + private SRv6Router router; + + + protected volatile Inet6Address remoteaddr; + protected volatile Inet6Address localaddr; + + private int bindProtocolNumber; + + private volatile int inputchachesize = 1024*1024; + + protected SRv6Router getRouter() { + return router; + } + + public KLALBVirtualRawSocketImpl(SRv6Router router) { + super(); + this.router = router; + } + + @Override + public void setOption(int optID, Object value) throws SocketException { + // TODO 自动生成的方法存根 + + } + + @Override + public Object getOption(int optID) throws SocketException { + // TODO 自动生成的方法存根 + return null; + } + + @Override + protected void create() throws IOException { + + } + + @Override + protected void setIPHeaderInclude(boolean ipHeaderInclude) throws IOException { + this.ipHeaderInclude=ipHeaderInclude; + } + + @Override + protected boolean getIPHeaderInclude() throws IOException { + return ipHeaderInclude; + } + + @Override + protected void setUseSelectTimeout(boolean useSelect) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected boolean getUseSelectTimeout() throws IOException { + // TODO 自动生成的方法存根 + return false; + } + + @Override + protected void setSendTimeout(int timeout) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected int getSendTimeout() throws IOException { + // TODO 自动生成的方法存根 + return 0; + } + + @Override + protected void setReceiveTimeout(int timeout) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected int getReceiveTimeout() throws IOException { + // TODO 自动生成的方法存根 + return 0; + } + + @Override + protected void close() { + router.getProtocolNumberRegister().remove(bindProtocolNumber); + } + + @Override + protected void bind(InetAddress address,int protocolNumber) throws SocketException{ + if(protocolNumber<0) { + throw new UnsupportedOperationException("unsupprted bind all protocols"); + } + try { + if (address.equals(Inet4Address.getByName("0.0.0.0"))) { + address = Inet6Address.getByName("::0"); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } + if (!(address instanceof Inet6Address)) { + throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address"); + } + if ((!address.isAnyLocalAddress()) && (!address.equals(router.getLocator().getAddress()))) { + throw new BindException("must bind to self"); + } + + localaddr=(Inet6Address) address; + this.bindProtocolNumber=protocolNumber; + if(router.getProtocolNumberRegister().putIfAbsent(protocolNumber, this)!=null) { + throw new BindException("protocol number already bind"); + } + } + + @Override + protected void join(InetAddress inetaddr) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected void leave(InetAddress inetaddr) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected void joinGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected void leaveGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException { + // TODO 自动生成的方法存根 + + } + + @Override + protected void send(DatagramPacket p) throws IOException { + ByteBuffer buf= ByteBuffer.wrap(p.getData(), p.getOffset(), p.getLength()); + if(ipHeaderInclude) { + + }else { + HighPerformanceExecutor.defaultExecutor.execute(() -> { + IPv6Packet ipv=new IPv6Packet(); + ipv.setVersion(6); + ipv.setTrafficClass(0); + ipv.setFlowLabel(0); + ipv.setHopLimit(255); + ipv.setSourceAddress(router.getLocator().getAddress()); + InetAddress address= p.getAddress(); + if (!(address instanceof Inet6Address)) { + throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address"); + } + ipv.setDestinationAddress((Inet6Address)address); + ipv.setPriority(3); + //ipv.enableECN(); + IPv6Payload pl=new IPv6Payload(bindProtocolNumber); + pl.getData().put(buf); + pl.getData().flip(); + ipv.setPayload(pl); + router.insertSRHandRoutePacket(ipv); + }); + } + } + + @Override + protected InetAddress peek() throws IOException { + return peekNextPacket().getSourceAddress(); + } + + @Override + protected void peekData(DatagramPacket p) throws IOException { + IPv6Packet pack=peekNextPacket(); + copyTo(pack, p); + } + + private void copyTo(IPv6Packet pack, DatagramPacket p) throws IOException { + p.setAddress(pack.getSourceAddress()); + ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength()); + if(ipHeaderInclude) { + + }else { + try { + pack.getPayload().writeToChannel(KNEChannels.newWritableChannel(buffer)); + }catch(BufferOverflowException e) { + + } + } + buffer.flip(); + p.setLength(buffer.limit()); + } + + @Override + protected void receive(DatagramPacket p) throws IOException { + IPv6Packet pack=pollNextPacket(); + copyTo(pack, p); + } + private volatile Thread parkThread; + private IPv6Packet peekNextPacket() { + IPv6Packet pol=null; + while(true) { + pol=recvQueue.peek(); + if(pol!=null) { + recvQueueUsed.addAndGet((int) -pol.getPayload().getLength()); + return pol; + } + parkThread=Thread.currentThread(); + LockSupport.parkNanos(1000000L); + } + } + private IPv6Packet pollNextPacket() { + IPv6Packet pol=null; + while(true) { + pol=recvQueue.poll(); + if(pol!=null) { + recvQueueUsed.addAndGet((int) -pol.getPayload().getLength()); + return pol; + } + parkThread=Thread.currentThread(); + LockSupport.parkNanos(1000000L); + } + } + private Queue recvQueue = new ConcurrentLinkedQueue(); + private AtomicInteger recvQueueUsed=new AtomicInteger(0); + + @Override + public void accept(IPv6Packet packx) throws IOException { + if(recvQueueUsed.get()<=inputchachesize) { + if(recvQueue.offer(packx)) { + recvQueueUsed.addAndGet((int) packx.getPayload().getLength()); + LockSupport.unpark(parkThread); + } + } + + } + +} diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java index ca6604b..e9a7f60 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocket.java @@ -14,16 +14,16 @@ public class KLALBVirtualSocket extends VirtualSocket { return (KLALBVirtualSocketImpl) super.getVirtualImpl(); } - private KLALBController controler; + private KLALBController controller; protected SocketChannel channel; public KLALBVirtualSocket(KLALBController controler) throws SocketException { super(controler.createVirtualImpl()); - this.controler = controler; + this.controller = controler; } - protected KLALBController getControler() { - return controler; + protected KLALBController getController() { + return controller; } public KLALBVirtualSocket(KLALBController controler,String host, int port) throws UnknownHostException, IOException { diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java index 3c52e10..f8fcd06 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketChannel.java @@ -115,8 +115,7 @@ public class KLALBVirtualSocketChannel extends SocketChannel{ @Override public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { - // TODO 自动生成的方法存根 - return 0; + return ((KVSIInputStream)socket.getInputStream()).read(dsts,offset,length); } @Override @@ -126,8 +125,7 @@ public class KLALBVirtualSocketChannel extends SocketChannel{ @Override public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { - // TODO 自动生成的方法存根 - return 0; + return ((KVSIOutputStream)socket.getOutputStream()).write(srcs,offset,length); } @Override @@ -151,4 +149,10 @@ public class KLALBVirtualSocketChannel extends SocketChannel{ socket.associateSocketChannel(b); } + public boolean isAutoFlush() throws IOException { + return ((KVSIOutputStream)socket.getOutputStream()).isAutoFlush(); + } + public void setAutoFlush(boolean b) throws IOException { + ((KVSIOutputStream)socket.getOutputStream()).setAutoFlush(b); + } } diff --git a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java index 9a87a07..84965a7 100644 --- a/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java +++ b/src/org/kne/cloud/network/klalb/KLALBVirtualSocketImpl.java @@ -35,6 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -55,13 +56,13 @@ import java.util.zip.GZIPInputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; -import org.kne.acclerate.FastLib; import org.kne.cloud.network.PortPair; import org.kne.cloud.network.SpeedLimiter; import org.kne.cloud.network.ThreadTool; import org.kne.cloud.network.VirtualSocketImpl; import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl; import org.kne.concurrent.SpinLock; +import org.kne.concurrent.ThreadParker; import org.kne.debug.TimeDebugger; import org.kne.io.Data; @@ -70,7 +71,8 @@ import com.google.gson.internal.Pair; import java.util.*; public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements BindableKLALBPacketConsumer{ - + + private static final int HEADER_CALIBRATE = 40; /* private PrintStream dbg; { @@ -90,6 +92,112 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl private KLALBController controller; + + //60000 30 30 + private final int MTU=10000; + private final long MIN_RTTVAR=100000000L; + private final long MIN_LIMIT_SPEED=128*1024L; + private final long REACK_INTERVAL = 100000000L; + + + private SpeedLimiter spdlmt=new SpeedLimiter(MIN_LIMIT_SPEED,2000000L); + + protected Inet6Address remoteaddr; + protected Inet6Address localaddr;{ + try { + localaddr=(Inet6Address) Inet6Address.getByName("::0"); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + } + //private CountDownLatch reseted=new CountDownLatch(1); + private BlockingQueue backlogQueue; + private ReentrantLock backlogQueuelock=new ReentrantLock(); + + private ThreadParker sendDequeLock=new ThreadParker(); + private Map recvMap = new ConcurrentHashMap(100000); + private AtomicInteger recvWindowUsed=new AtomicInteger(0); + //private AtomicInteger recvCounter=new AtomicInteger(0); + + + private Map sendmap=new ConcurrentHashMap(100000); + private AtomicInteger sendmapWindowUsed=new AtomicInteger(0); + //private ReentrantReadWriteLock sendmaplock=new ReentrantReadWriteLock(); + + private ThreadParker sendthread=new ThreadParker(); + //private List sendlist=new ArrayList<>(); + private TimerTask sendCheckTask=new SendCheckTask(); + + //private List inputchache = new RangeArrayList<>(); + //private Map inputchache=new ConcurrentHashMap(); + //private Lock inputchachelock=new ReentrantLock(); + + private AtomicBoolean firstUpdate=new AtomicBoolean(true); + + private boolean ignoreBindCheck; + private boolean connected; + + private boolean connectionPending; + private TimerTask flowControlTask=new FlowControlTask(); + + private PortPair portp; + + private InputStream vin; + private OutputStream vout; + + + private boolean closed; + + private KVSIInputStream kvsii; + private KVSIOutputStream kvsio; + + private boolean nodelay=true; + private long delaytime=2; + private int inputchachesize =128* 1024*1024; + private int outputchachesize = 128* 1024*1024; + + //long pad0,pad1,pad2,pad3,pad4,pad5,pad6,pad7; + //4000 100 100 + //10000 500 500//500 + private volatile long congressWindowSize = MTU * 40; + private volatile long sendWindowSize = MTU * 40; + + private volatile long rcvSpeed=MIN_LIMIT_SPEED; + private volatile long requestSpeed=MIN_LIMIT_SPEED; + private volatile long requestSpeedOld=MIN_LIMIT_SPEED; + //private volatile long congressSpeed=0; + private volatile double congressFactor=2; + + //private double[] congressFactors=new double[] {0.95,0.95,0.95,1.2,0.8}; + //private int congressFactorsState=0; + //private volatile double maxutilization=0.8; + + + + + + + private long inputcount = 0; + private volatile long peerAvaliableRcvWindow = MTU*40; + private long outputcount = 0; + + + private volatile long RTTMin=1000000000L; + private volatile long RTTVar=1000000000L; + private volatile long RTTAvg=1000000000L; + private volatile long RTO=1000000000L; + + private volatile long QueueingAvg=1000000000L; + + //private volatile long RunningSpeed=spdlmt.getLimitspeed(); + + + + + + + + protected int getInputchachesize() { return inputchachesize; } @@ -106,29 +214,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl this.outputchachesize = outputchachesize; } - //60000 30 30 - private static final int MTU=8192; - //4000 100 100 - //10000 500 500 - private volatile int inputchachesize = MTU * 4000; - private volatile int outputchachesize = MTU * 240;//500 - private volatile int reallimit = MTU * 240; - - private final long MIN_RTTVAR=50000000L; - private final long MIN_LIMIT_SPEED=64*1024L; - private volatile long rcvSpeed=MIN_LIMIT_SPEED; - private volatile long requestSpeed=MIN_LIMIT_SPEED; - private SpeedLimiter spdlmt=new SpeedLimiter(MIN_LIMIT_SPEED,1000000L); - private volatile long congressSpeed=0; - private volatile double congressFactor=2; - - //private double[] congressFactors=new double[] {0.95,0.95,0.95,1.2,0.8}; - //private int congressFactorsState=0; - //private volatile double maxutilization=0.8; - - private volatile boolean nodelay=true; - private volatile long delaytime=2; public long getDelaytime() { return delaytime; @@ -137,31 +223,8 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl public void setDelaytime(long delaytime) { this.delaytime = delaytime; } - protected volatile Inet6Address remoteaddr; - protected volatile Inet6Address localaddr;{ - try { - localaddr=(Inet6Address) Inet6Address.getByName("::0"); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - } - //private CountDownLatch reseted=new CountDownLatch(1); - private volatile BlockingQueue backlogQueue; - private ReentrantLock backlogQueuelock=new ReentrantLock(); - - private volatile Thread sendDequeLock; - private Queue recvQueue = new ConcurrentLinkedQueue(); - private AtomicInteger recvQueueUsed=new AtomicInteger(0); - //private AtomicInteger recvCounter=new AtomicInteger(0); - private Map sendmap=new ConcurrentHashMap(); - private AtomicInteger sendmapWindowUsed=new AtomicInteger(0); - //private ReentrantReadWriteLock sendmaplock=new ReentrantReadWriteLock(); - - private volatile Thread sendthread; - //private List sendlist=new ArrayList<>(); - private TimerTask sendCheckTask=new SendCheckTask(); private class SendCheckTask extends TimerTask{ public void run() { @@ -170,27 +233,32 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl try { Collection cdp=sendmap.values(); - for (Iterator iterator = cdp.iterator(); iterator.hasNext();) { + for (Iterator iterator = cdp.iterator(); iterator.hasNext();) { DATATPacket dtp = (DATATPacket) iterator.next(); try { long x=System.nanoTime(); long dt=x-dtp.resendtimer; - long limit= (long) (Math.pow(2, dtp.getSendCounter()-1)*(RTO)); + long limit= (long) (Math.pow(2, dtp.getSendCounter()-1)*(RTO*2)); if(dt>limit) { if(dtp.getSendCounter()>=10) { throw new IOException("send error!"); } - if(dtp.isDisposed()) - continue; + dtp.setPriority(4); long length= dtp.getLength(); socketRawMonitor.getOutTrafficAL().addAndGet(length); spdlmt.forceTransmit(length); controller.sendPacketToAddress((Inet6Address) remoteaddr,0,dtp,1); - //System.out.println("第"+(dtp.getSendRecord().size()-1)+"次重传:"+dtp+" "+dt+">"+limit); + //System.out.println("第"+(dtp.getSendCounter()-1)+"次重传:"+dtp+" "+dt+">"+limit); dtp.resendtimer=x; + + /*if(congressWindowSize>65535) { + congressWindowSize-=(dtp.getSize()+HEADER_CALIBRATE); + updateWindowSize(); + //System.out.println(reallimit+" -8192"); + }*/ } } catch (IOException e) { e.printStackTrace(); @@ -206,23 +274,20 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl }catch(Exception e) { e.printStackTrace(); } - if(portp!=null) - updateBandwidthReq(requestSpeed); } } - private TimerTask flowControlTask=new FlowControlTask(); + private class FlowControlTask extends TimerTask{ @Override public void run() { - if(recvQueue.isEmpty()) { try { if(getLocalPort()!=0&&getPort()!=0) if(remoteaddr instanceof Inet6Address&&(!remoteaddr.isAnyLocalAddress())) controller.sendPacketToAddress((Inet6Address) remoteaddr,0, new ACKTPacket(getLocalPort(),getPort(), -1, - true,false,socketMonitor.getInSpeedMax(),0)); + getAvaliableRcvWindow(),false,socketMonitor.getInSpeedMax(),0)); } catch (IOException e) { try { close0(true); @@ -232,37 +297,20 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl e.printStackTrace(); } - } } + + } - + private long getAvaliableRcvWindow() { + return Math.max(0, inputchachesize-recvWindowUsed.get()); + } protected boolean isListening() { return backlogQueue != null; } - //private List inputchache = new RangeArrayList<>(); - private Map inputchache=new ConcurrentHashMap(); - private Lock inputchachelock=new SpinLock(); - private long inputcount = 0; - private volatile boolean avaliable = true; - - private AtomicBoolean firstUpdate=new AtomicBoolean(true); - private volatile long RTTMin=1000000000L; - private volatile long RTTVar=1000000000L; - private volatile long RTTAvg=1000000000L; - private volatile long RTO=1000000000L; - - private volatile long QueueingAvg=1000000000L; - - private volatile long RunningSpeed=spdlmt.getLimitspeed(); - - private volatile boolean ignoreBindCheck; - private boolean connected; - - private volatile boolean connectionPending; @@ -343,7 +391,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl connect(new InetSocketAddress(address, port), 10000); } - private PortPair portp; + @Override protected void connect(SocketAddress address, int timeout) throws IOException { @@ -485,10 +533,10 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } - private InputStream vin; - private OutputStream vout; + protected class KVSIInputStream extends InputStream implements ReadableByteChannel{ + private DATATPacket dataPack = null; //private int count = 0; @@ -503,22 +551,30 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } else { int ret= dataPack.getDataBuffer().get() & 0xff; if(!dataPack.getDataBuffer().hasRemaining()) { - dataPack.dispose(); + //dataPack.dispose(); dataPack=null; } //System.out.println("read:"+1); return ret; } } - + private long reAckTime=System.nanoTime(); private DATATPacket nextPacket() throws IOException { //count = 0; while (true) { if (isClosed()) throw new SocketException("Socket is closed"); - DATATPacket dtp2 = recvQueue.poll(); + + DATATPacket dtp2 = recvMap.get(inputcount); if (dtp2 != null) { - recvQueueUsed.addAndGet(-dtp2.getSize()); + long oldcount= inputcount++; + recvMap.remove(oldcount); + int g=recvWindowUsed.addAndGet(-dtp2.getSize()); + long curt=System.nanoTime(); + if(g<=0&(curt-reAckTime)>REACK_INTERVAL) { + reAckTime=curt; + flowControlTask.run(); + } //System.out.println("PULL:"+dtp2); dataPack = dtp2; socketMonitor.getInTrafficAL().addAndGet(dtp2.getSize()); @@ -527,9 +583,9 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl controller.getDatatMonitor().getInPacketCounterAL().incrementAndGet(); //checkFlowControl(dtp2); break; + } - sendDequeLock=Thread.currentThread(); - LockSupport.parkNanos(1000000); + sendDequeLock.parkNanos(1000000); } //System.out.println("sorted:"+dataPack); return dataPack; @@ -560,7 +616,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if(!dataPack.getDataBuffer().hasRemaining()) { dataPack.putTimePassport("unpacked"); dataPack.printPassport(); - dataPack.dispose(); + //dataPack.dispose(); dataPack=null; } } @@ -584,7 +640,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if(!dataPack.getDataBuffer().hasRemaining()) { dataPack.putTimePassport("unpacked"); dataPack.printPassport(); - dataPack.dispose(); + //dataPack.dispose(); dataPack=null; } @@ -621,7 +677,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if(!dataPack.getDataBuffer().hasRemaining()) { dataPack.putTimePassport("unpacked"); dataPack.printPassport(); - dataPack.dispose(); + //dataPack.dispose(); dataPack=null; } } @@ -643,7 +699,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if(!dataPack.getDataBuffer().hasRemaining()) { dataPack.putTimePassport("unpacked"); dataPack.printPassport(); - dataPack.dispose(); + //dataPack.dispose(); dataPack=null; } @@ -666,7 +722,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } @Override public int available() throws IOException { - int i = recvQueueUsed.get(); + int i = recvWindowUsed.get(); /*for(DATATPacket V:recvQueue) { i+=(V.getSize()); }*/ @@ -681,9 +737,21 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + long lth=0; + for(int i=offset;i0) { + createDataPackIfNull(len); int remainD=dataPack.getDataBuffer().remaining(); int min=Math.min(len, remainD); dataPack.getDataBuffer().put(b, off, min); @@ -749,23 +824,26 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } - if(dataPack.getDataBuffer().position()>0) + if(dataPack!=null&& dataPack.getDataBuffer().position()>0) { + if(autoFlush) flush(); + } }finally { + if(olock!=null) olock.unlock(); } } - - - @Override - public int write(ByteBuffer src) throws IOException { + private int writeWithoutFlush(ByteBuffer src)throws IOException { if (isClosed()) throw new SocketException("Socket is closed"); int counter=0; + if(olock!=null) olock.lock(); try { + while(src.hasRemaining()) { + createDataPackIfNull(src.remaining()); int min=Math.min(src.remaining(), dataPack.getDataBuffer().remaining()); int olm=src.limit(); src.limit(src.position()+min); @@ -778,15 +856,62 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } - if(dataPack.getDataBuffer().position()>0) - flush(); + }finally { + if(olock!=null) + olock.unlock(); + } + return counter; + } + + @Override + public int write(ByteBuffer src) throws IOException { + if (isClosed()) + throw new SocketException("Socket is closed"); + int counter=0; + if(olock!=null) + olock.lock(); + try { + + while(src.hasRemaining()) { + createDataPackIfNull(src.remaining()); + int min=Math.min(src.remaining(), dataPack.getDataBuffer().remaining()); + int olm=src.limit(); + src.limit(src.position()+min); + dataPack.getDataBuffer().put(src); + counter+=min; + src.limit(olm); + + if (!dataPack.getDataBuffer().hasRemaining()) {//1429?5773?8669 + flush0(); + } + } + + if(dataPack!=null&& dataPack.getDataBuffer().position()>0) { + if(autoFlush) + flush(); + } + }finally { + if(olock!=null) olock.unlock(); } return counter; } + private void createDataPackIfNull(int remaining) { + if(dataPack==null) { + int blth; + if(autoFlush) { + blth=Math.min( remaining,MTU); + }else { + blth=MTU; + } + + dataPack=new DATATPacket(localport, port, outputcount++, blth); + dataPack.putTimePassport("buildHeader"); + } + } public void waitForAllAcknowledged(int timeout) throws IOException { long start=System.nanoTime(); while(true){ @@ -796,19 +921,21 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl break; if(timeout!=0&&(System.nanoTime()-start>timeout*1000000L)) throw new SocketTimeoutException("wait for acknowledged timout"); - sendthread=Thread.currentThread(); - LockSupport.parkNanos(1000000L); + sendthread.parkNanos(1000000L); } } AtomicReference ioe=new AtomicReference<>(); private volatile TimerTask tt; + @Override public void flush() throws IOException { if(nodelay||locked) { + if(olock!=null) olock.lock(); try { flush0(); }finally { + if(olock!=null) olock.unlock(); } }else { @@ -820,10 +947,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl if(isClosed()) cancel(); try { + if(olock!=null) olock.lock(); try { flush0(); }finally { + if(olock!=null) olock.unlock(); } } catch (IOException e) { @@ -842,16 +971,18 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } public void forceFlush() throws IOException{ + if(olock!=null) olock.lock(); try { flush0(); }finally { + if(olock!=null) olock.unlock(); } } private void flush0() throws IOException { - if (dataPack.getDataBuffer().position() > 0) { + if (dataPack!=null&&dataPack.getDataBuffer().position() > 0) { if(tt!=null) { tt.cancel(); tt=null; @@ -859,35 +990,29 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl //TimeDebugger td=new TimeDebugger(); //td.putTime("start"); dataPack.putTimePassport("packed"); - while (!avaliable) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + /*while (!avaliable) { + sendthread.parkNanos(1000000L); + }*/ dataPack.putTimePassport("waitForAvaliable"); //td.putTime("waitForAvaliable"); while(true){ if (isClosed()) throw new SocketException("Socket is closed"); //System.out.println(sendmap.size()); - boolean b=sendmapWindowUsed.get()<=reallimit; + boolean b=sendmapWindowUsed.get()<=sendWindowSize; //boolean b=sendmap.size()<=reallimit/MTU; if(b) - break; - sendthread=Thread.currentThread(); - LockSupport.parkNanos(1000000L); + break; + sendthread.parkNanos(1000000L); } dataPack.putTimePassport("waitForWindow"); //td.putTime("waitForCache"); DATATPacket pack=dataPack; - dataPack=new DATATPacket(localport, port, outputcount++,MTU); - dataPack.putTimePassport("buildHeader"); + dataPack=null; pack.getDataBuffer().flip(); //System.out.println(pack.getDataBuffer()); //cacheCreateTime=System.nanoTime(); - //td.putTime("flushBuffer"); + //td.putTime("flipBuffer"); spdlmt.transmit(pack.getDataBuffer().limit()); socketMonitor.getOutTrafficAL().addAndGet(pack.getDataBuffer().limit()); socketMonitor.getOutPacketCounterAL().incrementAndGet(); @@ -901,18 +1026,20 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl //td.putTime("doSend"); /* sendmaplock.readLock().lock(); try{*/ - pack.resendtimer=System.nanoTime(); DATATPacket prv= sendmap.put(pack.getNumber(),pack); - sendmapWindowUsed.addAndGet(pack.getSize()); + sendmapWindowUsed.addAndGet((int) (pack.getLength()+HEADER_CALIBRATE)); if(prv!=null) - sendmapWindowUsed.addAndGet(-prv.getSize()); + sendmapWindowUsed.addAndGet((int) (-(prv.getLength()+HEADER_CALIBRATE))); //System.out.println("PUSH:"+pack); /*}finally { sendmaplock.readLock().unlock(); }*/ //td.putTime("addToList"); + + + //td.putTime("newPacket"); //td.print(); - + } } @Override @@ -927,10 +1054,12 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl //outputclosed=true; if(isClosed()) return; + if(olock!=null) olock.lock(); try { flush0(); }finally { + if(olock!=null) olock.unlock(); } @@ -942,7 +1071,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl try{*/ pack.resendtimer=System.nanoTime(); sendmap.put(pack.getNumber(),pack); - sendmapWindowUsed.addAndGet(pack.getSize()); + sendmapWindowUsed.addAndGet((int) (pack.getLength()+HEADER_CALIBRATE)); /*}finally { sendmaplock.readLock().unlock(); }*/ @@ -953,8 +1082,7 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl //System.out.println(sendmap.size()); if(sendmap.isEmpty()) break; - sendthread=Thread.currentThread(); - LockSupport.parkNanos(1000000L); + sendthread.parkNanos(1000000L); } }finally { @@ -966,10 +1094,26 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl public boolean isOpen() { return !closed; } + public boolean isAutoFlush() { + return autoFlush; + } + public void setAutoFlush(boolean b) { + autoFlush=b; + } + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + long lth=0; + for(int i=offset;i0) { + if(autoFlush) + flush(); + } + return lth; + } } - private KVSIInputStream kvsii; private KVSIInputStream getKVSIInputStream() { if(kvsii==null) kvsii=new KVSIInputStream(); @@ -986,7 +1130,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl }*/ return vin; } - private KVSIOutputStream kvsio; private KVSIOutputStream getKVSIOutputStream() { if(kvsio==null) kvsio=new KVSIOutputStream(); @@ -1024,7 +1167,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl @Override protected void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { - // TODO 自动生成的方法存根 super.setPerformancePreferences(connectionTime, latency, bandwidth); } @@ -1066,8 +1208,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl } } - private volatile boolean closed; - private boolean isClosed() { return closed; } @@ -1080,7 +1220,6 @@ public class KLALBVirtualSocketImpl extends VirtualSocketImpl implements Bindabl @Override public int getLocalPort() { - // TODO 自动生成的方法存根 return super.getLocalPort(); } @@ -1100,7 +1239,7 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ b.write(dp.getDataBuffer()); dp.putTimePassport("unpacked"); dp.printPassport(); - dp.dispose(); + //dp.dispose(); } }catch(IOException e) { onError=true; @@ -1138,6 +1277,7 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ ByteBuffer tst=ByteBuffer.allocateDirect(MTU); while(true) { if(nodelay) { + kos.createDataPackIfNull(MTU); if(b.read(kos.dataPack.getDataBuffer())==-1) { break; } @@ -1194,13 +1334,11 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ try { b.close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } try { close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } } @@ -1240,7 +1378,7 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ orc.write(dp.getDataBuffer()); dp.putTimePassport("unpacked"); dp.printPassport(); - dp.dispose(); + //dp.dispose(); } }catch(IOException e) { onError=true; @@ -1260,13 +1398,11 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ try { associateSocket.close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } try { close(); } catch (IOException e) { - // TODO 自动生成的 catch 块 e.printStackTrace(); } } @@ -1278,6 +1414,7 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ ByteBuffer tst=ByteBuffer.allocateDirect(MTU); while(true) { if(nodelay) { + kos.createDataPackIfNull(MTU); if(irc.read(kos.dataPack.getDataBuffer())==-1) { break; } @@ -1371,224 +1508,11 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ case KLALBPacket.DATAT: DATATPacket dtp = (DATATPacket) u; - socketRawMonitor.getInTrafficAL().addAndGet(dtp.getLength()); - if(isListening()) { - if(dtp.getNumber()==0) { - backlogQueuelock.lock(); - try{ - - //controller.getStreamPortBinder().checkIsConnected(new Pair); - InetSocketAddress is=new InetSocketAddress(from, dtp.getSport()); - AtomicBoolean ab=new AtomicBoolean(true); - for (Iterator iterator = backlogQueue.iterator(); iterator.hasNext();) { - Object[] objects = (Object[]) iterator.next(); - if(is.equals(objects[0])) { - ab.set(false); - break; - } - } - if(ab.get()) { - if(controller.getStreamPortBinder().checkIsConnect(this,new InetSocketAddress(from, dtp.getSport()))) { - ab.set(false); - } - } - - - if(ab.get()) - if(backlogQueue.offer(new Object[] { is,from,dtp})) { - /* controller.sendPacketToAddress(from.getRemoteVaddr(), new ACKTPacket(dtp.getDport(), dtp.getSport(),dtp.getNumber(),true,0), - 0,2);*/ - }else { - controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()), - 2); - } - - - }finally { - backlogQueuelock.unlock(); - } - }else { - controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()), - 2); - } - }else { - //System.out.println(dtp.isCE()); - controller.sendPacketToAddress(from,0, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(), - recvQueueUsed.get() < inputchachesize,dtp.isCE(),socketMonitor.getInSpeedMax(),dtp.getSendcount()), 1); - - boolean added=false; - - long number=dtp.getNumber(); - if (number >= inputcount) { - - inputchache.putIfAbsent(number, dtp); - - /*inputchachelock.lock(); - try{ - int currindex=(int) (number-inputcount); - int reqsize=1+currindex; - - while(reqsize>inputchache.size()) { - inputchache.add(null); - } - - - - if(currindex>=0) { - DATATPacket old=(DATATPacket) inputchache.get(currindex); - if(old==null) { - inputchache.set(currindex, dtp); - }else { - dtp.dispose(); - } - } - - - int spos=inputchache.size(); - for (int i = 0; i < inputchache.size(); i++) { - DATATPacket datatPacket=(DATATPacket) inputchache.get(i); - if(datatPacket==null) { - spos=i; - break; - } - } - for (int i = 0; i < spos; i++) { - DATATPacket datatPacket = (DATATPacket)inputchache.get(i); - recvQueueUsed.addAndGet(datatPacket.getSize()); - recvQueue.add(datatPacket); - added=true; - inputcount++; - } - ((RangeArrayList)inputchache).removeRange(0,spos); - - }finally{ - inputchachelock.unlock(); - }*/ - - - - - - }else { - dtp.dispose(); - } - - inputchachelock.lock(); - try { - DATATPacket datatPacket = inputchache.remove(inputcount); - if(datatPacket!=null) { - inputcount++; - recvQueueUsed.addAndGet(datatPacket.getSize()); - recvQueue.add(datatPacket); - added=true; - } - }finally { - inputchachelock.unlock(); - } - if(added) { - LockSupport.unpark(sendDequeLock); - } - - //dbg.println(from.getMonitor()+","+dtp.getNumber()); - } + acceptDATA(from, dtp); break; case KLALBPacket.ACKT: ACKTPacket ackt = (ACKTPacket) u; - if(isListening()) { - controller.sendPacketToAddress(from,0, new RSTPacket(ackt.getDport(), ackt.getSport()), - 2); - }else { - avaliable = ackt.isAvaliable(); - - - rcvSpeed=ackt.getRcvSpeed(); - - /*if(rcvSpeed>=congressSpeed) { - congressSpeed=rcvSpeed; - }else { - congressSpeed=(congressSpeed*99+rcvSpeed)/100; - }*/ - - - if(ackt.isCongress()) { - congressFactor=1.2; - if(reallimit>MTU*2) { - reallimit-=8192; - //System.out.println(reallimit+" -2048"); - } - }else { - if(sendmapWindowUsed.get()*2L>=reallimit) { - reallimit+=1024; - //System.out.println(reallimit+" +1024"); - } - } - requestSpeed=(long) (Math.max(MIN_LIMIT_SPEED, rcvSpeed)*congressFactor); - - //System.out.println(spdlmt.getLimitspeed()/1024+"K "+ackt.getRcvSpeed()/1024+"K"); - DATATPacket kl=null; - - - kl=sendmap.remove(ackt.getNumber()); - if(kl!=null) { - sendmapWindowUsed.addAndGet(-kl.getSize()); - } - - if(kl!=null) { - if(sendthread!=null) - LockSupport.unpark(sendthread); - //controller.removeFromSend(from.getRemoteVaddr(),kl); - if(kl.getSendCounter()==1) { - long RTTC=ackt.getRcvtime()- kl.getSndtime(); - if(RTTC<=RTTMin) { - RTTMin=RTTC; - }else { - RTTMin= (RTTMin*99999+RTTC)/100000; - } - - long queueing=RTTC-RTTMin; - QueueingAvg=(QueueingAvg*99999+queueing)/100000; - - if(firstUpdate.compareAndSet(true, false)) { - RTTAvg=RTTC; - RTTVar=RTTC/2; - - }else { - RTTVar=(RTTVar*3+Math.abs(RTTAvg-RTTC))/4; - RTTAvg= (RTTAvg*7+RTTC)/8; - } - RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4 - - - - /*if(RTTC>RTO) { - congressFactor=Math.min( 0.9,congressFactor); - }else { - if(congressFactor<1.1) - congressFactor+=0.001; - } */ - - - //System.out.println(congressFactor); - //spdlmt.setLimitspeed(1024*1024); - //reallimit=Math.max(MTU*2,(int) (congressSpeed*RTTMin*4/1000000000L)); - //System.out.println(reallimit/MTU); - /*long nspd=(long) (congressSpeed*congressFactor); - spdlmt.setLimitspeed(Math.max(nspd,MIN_LIMIT_SPEED));*/ - - - // System.out.println("RwqSpeed:"+(requestSpeed/1024)+"K MaxSpeed:"+(congressSpeed/1024)+"K LimitSpeed:"+(spdlmt.getLimitspeed()/1024)+"K"); - //System.out.println("RTTMin:"+RTTMin/1000000L+"ms RTTAvg:"+RTTAvg/1000000L+"ms"); - - - } - kl.dispose(); - - } - - - - } - ackt.dispose(); + acceptACK(from, ackt); break; case KLALBPacket.NACKT: NACKTPacket nackt=(NACKTPacket) u; @@ -1619,6 +1543,228 @@ public void associateSocketChannel(SocketChannel b) throws IOException{ } } + private void acceptDATA(Inet6Address from, DATATPacket dtp) throws BindException, IOException { + socketRawMonitor.getInTrafficAL().addAndGet(dtp.getLength()); + if(isListening()) { + if(dtp.getNumber()==0) { + backlogQueuelock.lock(); + try{ + + //controller.getStreamPortBinder().checkIsConnected(new Pair); + InetSocketAddress is=new InetSocketAddress(from, dtp.getSport()); + AtomicBoolean ab=new AtomicBoolean(true); + for (Iterator iterator = backlogQueue.iterator(); iterator.hasNext();) { + Object[] objects = (Object[]) iterator.next(); + if(is.equals(objects[0])) { + ab.set(false); + break; + } + } + if(ab.get()) { + if(controller.getStreamPortBinder().checkIsConnect(this,new InetSocketAddress(from, dtp.getSport()))) { + ab.set(false); + } + } + + + if(ab.get()) + if(backlogQueue.offer(new Object[] { is,from,dtp})) { + /* controller.sendPacketToAddress(from.getRemoteVaddr(), new ACKTPacket(dtp.getDport(), dtp.getSport(),dtp.getNumber(),true,0), + 0,2);*/ + }else { + controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()), + 2); + } + + + }finally { + backlogQueuelock.unlock(); + } + }else { + controller.sendPacketToAddress(from,0, new RSTPacket(dtp.getDport(), dtp.getSport()), + 2); + } + }else { + //System.out.println(dtp.isCE()); + controller.sendPacketToAddress(from,0, new ACKTPacket(dtp.getDport(), dtp.getSport(), dtp.getNumber(), + getAvaliableRcvWindow(),dtp.isCE(),socketMonitor.getInSpeedMax(),dtp.getSendcount()), 1); + + boolean added=false; + + long number=dtp.getNumber(); + + /*inputchachelock.lock(); + try {*/ + if (number >= inputcount) { + + recvWindowUsed.addAndGet(dtp.getSize()); + if(recvMap.putIfAbsent (dtp.getNumber(), dtp)!=null) { + recvWindowUsed.addAndGet(-dtp.getSize()); + } + added=true; + + + + + + + }else { + //dtp.dispose(); + } + + + + if(added) { + sendDequeLock.unpark(); + } + + //dbg.println(from.getMonitor()+","+dtp.getNumber()); + } + } + + private void acceptACK(Inet6Address from, ACKTPacket ackt) throws IOException { + if(isListening()) { + controller.sendPacketToAddress(from,0, new RSTPacket(ackt.getDport(), ackt.getSport()), + 2); + }else { + peerAvaliableRcvWindow = ackt.getAvaliableRcvWindow(); + updateWindowSize(); + + rcvSpeed=ackt.getRcvSpeed(); + + /*if(rcvSpeed>=congressSpeed) { + congressSpeed=rcvSpeed; + }else { + congressSpeed=(congressSpeed*99+rcvSpeed)/100; + }*/ + + + + requestSpeed=(long) (Math.max(MIN_LIMIT_SPEED, rcvSpeed)*congressFactor); + + + if(portp!=null) { + if(requestSpeed>requestSpeedOld*1.01||requestSpeedswu) { + cachesizenew=(int) swu; + } + + }while(congresscachesize.compareAndSet(cachesizeold, cachesizenew)); + + //System.out.println(reallimit+" +1024"); + + }*/ + if(ackt.isCongress()) { + congressFactor=1.5; + if(congressWindowSize>65535) { + congressWindowSize-=(kl.getSize()+HEADER_CALIBRATE)/8; + updateWindowSize(); + //System.out.println(reallimit+" -8192"); + } + }else { + if(sendmapWindowUsed.get()*2L>=congressWindowSize&&congressWindowSize<=outputchachesize) { + congressWindowSize+=(kl.getSize()+HEADER_CALIBRATE)/32; + updateWindowSize(); + //System.out.println(reallimit+" +1024"); + } + } + //controller.removeFromSend(from.getRemoteVaddr(),kl); + if(kl.getSendCounter()==1) { + long RTTC=ackt.getRcvtime()- kl.getSndtime(); + if(RTTC<=RTTMin) { + RTTMin=RTTC; + }else { + RTTMin= (RTTMin*99999+RTTC)/100000; + } + + long queueing=RTTC-RTTMin; + QueueingAvg=(QueueingAvg*99999+queueing)/100000; + + if(firstUpdate.compareAndSet(true, false)) { + RTTAvg=RTTC; + RTTVar=RTTC/2; + + }else { + RTTVar=(RTTVar*3+Math.abs(RTTAvg-RTTC))/4; + RTTAvg= (RTTAvg*7+RTTC)/8; + } + RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4 + + + + /*if(RTTC>RTO) { + congressFactor=Math.min( 0.9,congressFactor); + }else { + if(congressFactor<1.1) + congressFactor+=0.001; + } */ + + + //System.out.println(congressFactor); + //spdlmt.setLimitspeed(1024*1024); + //reallimit=Math.max(MTU*2,(int) (congressSpeed*RTTMin*4/1000000000L)); + //System.out.println(reallimit/MTU); + /*long nspd=(long) (congressSpeed*congressFactor); + spdlmt.setLimitspeed(Math.max(nspd,MIN_LIMIT_SPEED));*/ + + + // System.out.println("RwqSpeed:"+(requestSpeed/1024)+"K MaxSpeed:"+(congressSpeed/1024)+"K LimitSpeed:"+(spdlmt.getLimitspeed()/1024)+"K"); + //System.out.println("RTTMin:"+RTTMin/1000000L+"ms RTTAvg:"+RTTAvg/1000000L+"ms"); + + + } + //kl.dispose(); + + } + + + + } + //ackt.dispose(); + } + + private void updateWindowSize() { + sendWindowSize=Math.min(peerAvaliableRcvWindow, congressWindowSize); + + if(sendthread!=null) + sendthread.unpark(); + } + @Override public InetAddress getRemoteInetAddress() { return remoteaddr; diff --git a/src/org/kne/cloud/network/klalb/PortBinder.java b/src/org/kne/cloud/network/klalb/PortBinder.java index ff42196..8f85c1e 100644 --- a/src/org/kne/cloud/network/klalb/PortBinder.java +++ b/src/org/kne/cloud/network/klalb/PortBinder.java @@ -34,11 +34,11 @@ public class PortBinder { this.controller = controller; } private ReentrantReadWriteLock bindMaplock=new ReentrantReadWriteLock(); - private MapbindMap=new ConcurrentHashMap<>(); + private MapbindMap=new ConcurrentHashMap<>(65536*16); private ReentrantReadWriteLock listenMaplock=new ReentrantReadWriteLock(); - private MaplistenMap=new ConcurrentHashMap<>(); + private MaplistenMap=new ConcurrentHashMap<>(65536*16); private ReentrantReadWriteLock connectMaplock=new ReentrantReadWriteLock(); - private Map,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>(); + private Map,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>(65536*16); private volatile int portn=65535; public void bind(BindableKLALBPacketConsumer ks) throws BindException { bindMaplock.writeLock().lock(); @@ -205,7 +205,7 @@ public class PortBinder { return b; }*/ public boolean distributePacketToConsumer(Inet6Address srcAddr,PortPacket packet) { - InetSocketAddress local=new InetSocketAddress(controller.getSelf(), packet.getDport()); + InetSocketAddress local=new InetSocketAddress(controller.getSelf().getAddress(), packet.getDport()); InetSocketAddress remote=new InetSocketAddress(srcAddr, packet.getSport()); BindableKLALBPacketConsumer bkc=connectMap.get(new Pair(local, remote)); if(bkc!=null) { diff --git a/src/org/kne/cloud/network/klalb/SendItem.java b/src/org/kne/cloud/network/klalb/SendItem.java new file mode 100644 index 0000000..7bea99c --- /dev/null +++ b/src/org/kne/cloud/network/klalb/SendItem.java @@ -0,0 +1,22 @@ +package org.kne.cloud.network.klalb; + +import org.kne.cloud.network.ipv6.IPv6Packet; + +public class SendItem { + + private IPv6Packet packet; + private long sendtime=System.nanoTime(); + + public SendItem(IPv6Packet packet) { + this.packet=packet; + } + + public IPv6Packet getPacket() { + return packet; + } + + public long getSendtime() { + return sendtime; + } + +} diff --git a/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java index 9d6bf50..406eda6 100644 --- a/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/SplitedDatagramKLALBPacketLink.java @@ -129,18 +129,20 @@ import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; +import java.util.concurrent.atomic.AtomicLong; import org.kne.cloud.network.DatagramServerSocket; import org.kne.cloud.network.DatagramServerSocket.SubDatagramSocket; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.PacketRebuilder; import org.kne.cloud.network.PacketSpliter; import org.kne.cloud.network.SpeedLimiter; import org.kne.debug.TimeDebugger; -public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { - private PacketSpliter pslr=new PacketSpliter(65535); - private PacketRebuilder pbdr=new PacketRebuilder(1000000000); +public class SplitedDatagramKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink { + private PacketSpliter pslr; + private PacketRebuilder pbdr; @Override public String toString() { @@ -151,13 +153,60 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { public SplitedDatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException { this.ds=connectDatagramSocket; - bibf.limit(0); + pslr=new PacketSpliter(new WritableByteChannel() { + + @Override + public boolean isOpen() { + return !ds.isClosed(); + } + + @Override + public void close() throws IOException { + } + + @Override + public int write(ByteBuffer src) throws IOException { + int rem=src.remaining(); + byte[]bt=src.array(); + DatagramPacket dp=new DatagramPacket(bt,src.position(),src.limit()); + //System.out.println("SendDatagram:"+src.remaining()); + ds.send(dp); + return rem; + } + },1350); + pbdr=new PacketRebuilder(new ReadableByteChannel() { + + @Override + public boolean isOpen() { + return !ds.isClosed(); + } + + @Override + public void close() throws IOException { + } + + @Override + public int read(ByteBuffer dst) throws IOException {DatagramPacket dp; + if(ds instanceof SubDatagramSocket) { + dp=((SubDatagramSocket) ds).receive(); + dst.put(dp.getData(), 0, dp.getLength()); + + }else { + dp=new DatagramPacket(bc, bc.length); + ds.receive(dp); + dst.put(dp.getData(), 0, dp.getLength()); + } + //System.out.println("RecvDatagram:"+dp.getLength()); + return dp.getLength(); + } + },1000000000); + } - private ByteBuffer bbf=ByteBuffer.allocate(65535); + //private ByteBuffer bbf=ByteBuffer.allocate(65535); - @Override - public void writePacket(KLALBPacket kp) throws IOException { + /*@Override + public void writeKLALBPacket(KLALBPacket kp) throws IOException { //System.out.println(" TX:"+kp); //KLALBPacket.writeKLALBPacketToStream(dos, kp); KLALBPacket.writeKLALBPacketToChannel(new WritableByteChannel() { @@ -184,47 +233,21 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { } }, kp); - } + }*/ private byte[]bc=new byte[65535]; - private ByteBuffer bibf=ByteBuffer.allocate(65535); + //private ByteBuffer bibf=ByteBuffer.allocate(65535); - @Override - public KLALBPacket readPacket() throws IOException { + /*@Override + public KLALBPacket readKLALBPacket() throws IOException { KLALBPacket kp=null; do { if(bibf.remaining()<=0) { bibf.clear(); - /*DatagramPacket dp=new DatagramPacket(bc, bc.length); - ds.receive(dp); - bibf.put(dp.getData(), 0, dp.getLength());*/ - pbdr.read(bibf,new ReadableByteChannel() { - - @Override - public boolean isOpen() { - return true; - } - - @Override - public void close() throws IOException { - } - - @Override - public int read(ByteBuffer dst) throws IOException {DatagramPacket dp; - if(ds instanceof SubDatagramSocket) { - dp=((SubDatagramSocket) ds).receive(); - dst.put(dp.getData(), 0, dp.getLength()); - - }else { - dp=new DatagramPacket(bc, bc.length); - ds.receive(dp); - dst.put(dp.getData(), 0, dp.getLength()); - } - return dp.getLength(); - } - } ); + + pbdr.read(bibf ); bibf.flip(); } @@ -259,7 +282,7 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { }while(true); return kp; } - +*/ @Override public void close() throws IOException { ds.close(); @@ -280,7 +303,7 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { return ds.getSoTimeout(); } - @Override + /*@Override public void flush() throws IOException { bbf.flip(); //TimeDebugger tdb=new TimeDebugger(); @@ -307,16 +330,34 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink { }); //tdb.putTime("flushEnd"); //tdb.print(); - /*byte[]bt=bbf.array(); - DatagramPacket dp=new DatagramPacket(bt,bbf.limit()); - ds.send(dp);*/ bbf.clear(); - } + }*/ @Override public boolean isStream() { return false; } + + @Override + public void writePacket(ByteBuffer kp) throws IOException { + incOutput(kp.remaining()); + pslr.write(kp); + } + + @Override + public ByteBuffer readPacket() throws IOException { + ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(65535); + pbdr.read(bbf ); + bbf.flip(); + incInput(bbf.remaining()); + return bbf; + } + + @Override + public void flush() throws IOException { + // TODO 自动生成的方法存根 + + } } diff --git a/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java b/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java index 330ae45..8cdde11 100644 --- a/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java +++ b/src/org/kne/cloud/network/klalb/StreamChannelKLALBPacketLink.java @@ -1,6 +1,7 @@ package org.kne.cloud.network.klalb; import java.io.BufferedOutputStream; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; @@ -19,14 +20,19 @@ import java.nio.channels.Channels; import java.nio.channels.SocketChannel; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicLong; +import org.kne.cloud.network.ByteBufferAllocator; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.ThreadTool; import org.kne.cloud.network.TimeoutTimer; +import org.kne.io.KNEChannels; -public class StreamChannelKLALBPacketLink implements KLALBPacketLink { +public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink { private volatile long timeoutTimer; private volatile boolean timerenabled=false; - private Thread timeouter=new Thread() { + private Runnable timeouter=new Runnable() { public void run() { timeoutTimer=System.nanoTime(); while(connectSocket.isOpen()) { @@ -38,7 +44,7 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink { } } try { - Thread.sleep(1); + Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } @@ -59,29 +65,13 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink { public StreamChannelKLALBPacketLink(SocketChannel connectSocket) throws IOException { this.connectSocket=connectSocket; connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true); - timeouter.start(); + ThreadTool.makeVDaemonThread("连接超时计时线程", timeouter); new KLALBOutputStream(Channels.newOutputStream(connectSocket)); new KLALBInputStream(Channels.newInputStream(connectSocket)); } - @Override - public void writePacket(KLALBPacket kp) throws IOException { - KLALBPacket.writeKLALBPacketToChannel(connectSocket, kp); - } - @Override - public KLALBPacket readPacket() throws IOException { - timeoutTimer=System.nanoTime(); - timerenabled=true; - KLALBPacket res; - try { - res=KLALBPacket.readKLALBPacketFromChannel(connectSocket); - }finally { - timerenabled=false; - } - return res; - } @Override public void close() throws IOException { @@ -113,5 +103,136 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink { public boolean isStream() { return true; } + + + + @Override + public void writePacket(ByteBuffer kp) throws IOException { + ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4); + szeWrite.limit(4); + //szeWrite.clear(); + incOutput(kp.limit()); + szeWrite.putInt(kp.limit()); + szeWrite.flip(); + KLALBVirtualSocketChannel obj = null; + connectSocket.write(new ByteBuffer[] {szeWrite,kp}); + /* + if(connectSocket instanceof KLALBVirtualSocketChannel) { + obj=(KLALBVirtualSocketChannel) connectSocket; + } + boolean isaflush=false; + if(obj!=null) { + isaflush=obj.isAutoFlush(); + obj.setAutoFlush(false); + } + + //connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,false); + connectSocket.write(szeWrite); + + //connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true); + if(obj!=null) { + obj.setAutoFlush(true); + } + connectSocket.write(kp); + if(obj!=null) { + obj.setAutoFlush(isaflush); + }*/ + + } + + + + @Override + public void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException { + ByteBuffer[] bbfw=new ByteBuffer[len<<1]; + for(int i=0;i nodes=new ConcurrentHashMap(); + private List edgeGroups=new ArrayList(); + + public Map getNodes() { + return nodes; + } + + public List getEdgeGroups() { + return edgeGroups; + } + + + + + + + + + private double borderGap=250; + + private double translateX,translateY; + + private double scale=1; + + public double getTranslateX() { + return translateX; + } + + public double getTranslateY() { + return translateY; + } + + + + public double getScale() { + return scale; + } + + public void setScale(double scale) { + this.scale = scale; + } + + + + @Override + public void paint(Graphics g) { + super.paint(g); + + Graphics2D g2d=(Graphics2D)g; + + recalcTranslate(); + g2d.scale(scale, scale); + g2d.translate(translateX,translateY); + double w=xmax-xmin; + double h=ymax-ymin; + if(w>=0&&h>=0) { + g2d.drawRect((int)(xmin-borderGap), (int)(ymin-borderGap), (int)(w+borderGap*2), (int)(h+borderGap*2)); + } + synchronized (edgeGroups) { + + for( GraphEdgeGroup graphNode :edgeGroups) { + graphNode.paint(g2d); + } + + } + for(GraphNode graphNode :nodes.values()) { + graphNode.paint(g2d); + } + + + } + public class GraphNode{ + private String text; + private Color color; + private double nodesize=40; + private double x; + private double y; + private boolean ismarked; + private Vector2 delta=new Vector2(0, 0); + public GraphNode(String text, Color color, double x, double y,boolean ismarked) { + super(); + this.text = text; + this.color = color; + this.x = x; + this.y = y; + this.ismarked=ismarked; + } + + public double getNodesize() { + return nodesize; + } + + public void setNodesize(double nodesize) { + this.nodesize = nodesize; + } + + public boolean isIsmarked() { + return ismarked; + } + + public void setIsmarked(boolean ismarked) { + this.ismarked = ismarked; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public Color getColor() { + return color; + } + + public void setColor(Color color) { + this.color = color; + } + + public double getX() { + return x; + } + + public void setX(int x) { + this.x = x; + } + + public GraphNode() { + super(); + } + + public double getY() { + return y; + } + + public void setY(int y) { + this.y = y; + } + + public void paint(Graphics2D g) { + g.setColor(Color.BLACK); + g.setStroke(new BasicStroke(2.0f)); + g.drawOval((int)(x-nodesize/2), (int)(y-nodesize/2), (int)(nodesize), (int)(nodesize)); + g.setFont(UIEnv.getFont().deriveFont(10.0f)); + + g.drawString(text, (int)(x+nodesize/2), (int)(y-nodesize/3)); + if(ismarked) { + Vector2 pos=new Vector2(x, y); + Vector2 v2a=new Vector2(0, -1).multi(nodesize/4); + Vector2 v2b=new Vector2(Math.sqrt(3)/2.0, 0.5).multi(nodesize/4); + Vector2 v2c=new Vector2(-Math.sqrt(3)/2.0, 0.5).multi(nodesize/4); + v2a=v2a.add(pos); + v2b=v2b.add(pos); + v2c=v2c.add(pos); + g.drawPolygon(new int[] {(int) v2a.x,(int) v2b.x,(int) v2c.x}, new int[] {(int) v2a.y,(int) v2b.y,(int) v2c.y}, 3); + } + } + + public Vector2 getPositionVec2() { + return new Vector2(x, y); + } + + public void commitDelta() { + x+=delta.x; + y+=delta.y; + delta=new Vector2(0, 0); + } + + public void clearDelta() { + delta=new Vector2(0, 0); + + } + } + public class GraphEdge{ + private GraphNode from; + private GraphNode to; + LinkDirection linkPath; + + public GraphEdge(GraphNode nfrom, GraphNode nto,LinkDirection lp) { + this.from=nfrom; + this.to=nto; + this.linkPath=lp; + } + + } + public class GraphEdgeGroup{ + private double length=100; + private double gap=12; + private boolean isShortest=false; + private GraphNode nodeA,nodeB; + private List edges=new ArrayList<>(); + + + + public double getLength() { + return length; + } + + public void setLength(double length) { + this.length = length; + } + + public double getGap() { + return gap; + } + + public void setGap(double gap) { + this.gap = gap; + } + + public boolean match(GraphNode a,GraphNode b) { + if(a.equals( nodeA)&&b.equals( nodeB)) + return true; + if(b.equals( nodeA)&&a.equals( nodeB)) + return true; + return false; + } + + public GraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) { + super(); + this.nodeA = nodeA; + this.nodeB = nodeB; + } + + public boolean isShortest() { + return isShortest; + } + + public void setShortest(boolean isShortest) { + this.isShortest = isShortest; + } + + public List getPaths() { + return getEdges(); + } + public void paint(Graphics2D g) { + + Vector2 nodeAv=new Vector2(nodeA.getX(), nodeA.getY()); + Vector2 nodeBv=new Vector2(nodeB.getX(), nodeB.getY()); + Vector2 vecDir=nodeBv.subtract(nodeAv); + Vector2 vecDirnor=vecDir.normalize(); + Vector2 vecRA=vecDirnor.multi(nodeA.getNodesize()/2); + Vector2 vecRB=vecDirnor.multi(nodeB.getNodesize()/2); + + Vector2 vec90nor=new Vector2( -vecDir.y, vecDir.x).normalize(); + + //所有线路完整显示 + /* + double width=gap*(edges.size()-1); + //System.out.println(width); + + Vector2 startPoint=nodeAv.add(vecR).add(vec90nor.multi(width/2)); + Vector2 endPoint=nodeBv.subtract(vecR).add(vec90nor.multi(width/2)); + + for (Iterator iterator = edges.iterator(); iterator.hasNext();) { + GraphEdge graphEdge = (GraphEdge) iterator.next(); + + //System.out.println(vec90nor); + + g.setColor(KLALBUtils.getColorByLoadPercentage(graphEdge.linkPath.getSpeed()*100f/graphEdge.linkPath.getBandwidth())); + + if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) ) + drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g); + + + if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) ) + drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g); + + startPoint=startPoint.subtract(vec90nor.multi(gap)); + endPoint=endPoint.subtract(vec90nor.multi(gap)); + } + */ + long totalupspeed=0; + long usedupspeed=0; + long totaldownspeed=0; + long useddownspeed=0; + for(GraphEdge graphEdge :getEdges()) { + if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) ) { + totalupspeed+=graphEdge.linkPath.getBandwidth(); + usedupspeed+=graphEdge.linkPath.getSpeed(); + } + + if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) ) { + totaldownspeed+=graphEdge.linkPath.getBandwidth(); + useddownspeed+=graphEdge.linkPath.getSpeed(); + } + } + + + + g.setStroke(new BasicStroke((float) Math.max(2.0, Math.log10(totalupspeed/10.0/1024.0)))); + + double width=gap*1; + Vector2 startPoint=nodeAv.add(vecRA).add(vec90nor.multi(width/2)); + Vector2 endPoint=nodeBv.subtract(vecRB).add(vec90nor.multi(width/2)); + + g.setColor(KLALBUtils.getColorByLoadPercentagex(usedupspeed*100f/totalupspeed)); + + drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g); + + + + startPoint=startPoint.subtract(vec90nor.multi(gap)); + endPoint=endPoint.subtract(vec90nor.multi(gap)); + + + + g.setStroke(new BasicStroke((float) Math.max(2.0, Math.log10(totaldownspeed/10.0/1024.0)))); + + g.setColor(KLALBUtils.getColorByLoadPercentagex(useddownspeed*100f/totaldownspeed)); + + + + drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g); + + startPoint=startPoint.subtract(vec90nor.multi(gap)); + endPoint=endPoint.subtract(vec90nor.multi(gap)); + + if(isShortest) { + BasicStroke dotted = new BasicStroke(2, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 0, new float[]{0,3,0,3}, 0); + g.setStroke(dotted); + g.setColor(Color.BLUE); + g.drawLine((int)nodeA.getX(), (int)nodeA.getY(), (int)nodeB.getX(), (int)nodeB.getY()); + } + + + } + + public List getEdges() { + return edges; + } + + + } + // 计算 + public static double[] rotateVec(int px, int py, double ang, + boolean isChLen, double newLen) { + + double mathstr[] = new double[2]; + // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度 + double vx = px * Math.cos(ang) - py * Math.sin(ang); + double vy = px * Math.sin(ang) + py * Math.cos(ang); + if (isChLen) { + double d = Math.sqrt(vx * vx + vy * vy); + vx = vx / d * newLen; + vy = vy / d * newLen; + mathstr[0] = vx; + mathstr[1] = vy; + } + return mathstr; + } + public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2) + { + + double H = 13; // 箭头高度 + double L = 8; // 底边的一半 + int x3 = 0; + int y3 = 0; + int x4 = 0; + int y4 = 0; + double awrad = Math.atan(L / H); // 箭头角度 + double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度 + double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len); + double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len); + double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点 + double y_3 = ey - arrXY_1[1]; + double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点 + double y_4 = ey - arrXY_2[1]; + + Double X3 = new Double(x_3); + x3 = X3.intValue(); + Double Y3 = new Double(y_3); + y3 = Y3.intValue(); + Double X4 = new Double(x_4); + x4 = X4.intValue(); + Double Y4 = new Double(y_4); + y4 = Y4.intValue(); + // 画线 + g2.drawLine(sx, sy, ex, ey); + // + GeneralPath triangle = new GeneralPath(); + triangle.moveTo(ex, ey); + triangle.lineTo(x3, y3); + triangle.lineTo(x4, y4); + triangle.closePath(); + //实心箭头 + g2.fill(triangle); + //非实心箭头 + //g2.draw(triangle); + + } + + protected void loadNodes() { + updateBounds(); + } + + private void recalcTranslate() { + double xmin=Double.MAX_VALUE,xmax=Double.MIN_VALUE; + double ymin=Double.MAX_VALUE,ymax=Double.MIN_VALUE; + for(GraphNode graphNode:nodes.values()) { + xmin=Math.min(xmin, graphNode.x); + xmax=Math.max(xmax, graphNode.x); + ymin=Math.min(ymin, graphNode.y); + ymax=Math.max(ymax, graphNode.y); + } + this.xmin=xmin; + this.xmax=xmax; + this.ymin=ymin; + this.ymax=ymax; + if(xmin!=Double.MAX_VALUE) { + translateX=-xmin+borderGap; + translateY= -ymin+borderGap; + } + } + + private double xmin=Double.MAX_VALUE,xmax=Double.MIN_VALUE; + private double ymin=Double.MAX_VALUE,ymax=Double.MIN_VALUE; + public void updateBounds() { + recalcTranslate(); + + if(xmin!=Double.MAX_VALUE) { + Dimension d=new Dimension((int)(((xmax-xmin)+borderGap*2)*scale),(int)(((ymax-ymin)+borderGap*2)*scale) ); + setPreferredSize(d); + setSize(d); + } + } + + public void runPhy() { + for( GraphNode graphEdgeGroup :nodes.values()) { + Vector2 vecpos=graphEdgeGroup.getPositionVec2(); + Vector2 vec=new Vector2(0, 0); + for (Iterator iteratorx =nodes.values().iterator(); iteratorx.hasNext();) { + GraphNode graphEdgeGroup2 = (GraphNode) iteratorx.next(); + if(graphEdgeGroup2!=graphEdgeGroup) { + Vector2 vecpos2=graphEdgeGroup2.getPositionVec2(); + Vector2 sub=vecpos.subtract(vecpos2); + double distance=sub.Length(); + Vector2 dic=sub.normalize(); + vec=vec.add(dic.multi(Math.min(10.0/distance,10.0))); + } + } + graphEdgeGroup.delta=graphEdgeGroup.delta.add(vec); + } + synchronized (edgeGroups) { + + for(GraphEdgeGroup graphEdgeGroup :edgeGroups) { + GraphNode na=graphEdgeGroup.nodeA; + GraphNode nb=graphEdgeGroup.nodeB; + Vector2 veca=na.getPositionVec2(); + Vector2 vecb=nb.getPositionVec2(); + Vector2 sub=veca.subtract(vecb); + double distance=sub.Length(); + double length=graphEdgeGroup.getLength()+na.getNodesize()/2+nb.getNodesize()/2; + + //System.out.println(length); + if(distance>length) { + Vector2 dicb=sub.normalize().multi((distance-length)/3); + Vector2 dica=dicb.opposite(); + na.delta=na.delta.add(dica); + nb.delta=nb.delta.add(dicb); + } + } + + } + + for( GraphNode graphEdgeGroup:nodes.values()) { + + graphEdgeGroup.commitDelta(); + } + + } + + private Random r=new Random(); + public Vector2 getRandomPos() { + double x,y; + if(xmin>=xmax) { + x=r.nextDouble(); + }else { + x=r.nextDouble(xmin, xmax); + } + if(ymin>=ymax) { + y=r.nextDouble(); + }else { + y=r.nextDouble(ymin, ymax); + } + return new Vector2(x, y); + } +} diff --git a/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI2.java b/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI2.java index fa282a6..daf1137 100644 --- a/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI2.java +++ b/src/org/kne/cloud/network/klalb/ui/KLALBStateGUI2.java @@ -5,9 +5,12 @@ import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; +import java.awt.Font; import java.awt.GridLayout; import java.awt.MenuItem; +import java.awt.Point; import java.awt.PopupMenu; +import java.awt.Rectangle; import java.awt.SystemTray; import java.awt.Toolkit; import java.awt.TrayIcon; @@ -18,7 +21,14 @@ import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; import java.io.IOException; +import java.net.Inet6Address; +import java.net.UnknownHostException; import java.util.Timer; import java.util.TimerTask; @@ -32,7 +42,9 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.JTextField; +import javax.swing.JViewport; import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; import javax.swing.border.LineBorder; import org.jfree.chart.ChartPanel; @@ -45,11 +57,14 @@ import org.jfree.chart.plot.dial.StandardDialRange; import org.jfree.chart.plot.dial.StandardDialScale; import org.jfree.chart.ui.RectangleEdge; import org.jfree.data.general.DefaultValueDataset; +import org.kne.cloud.klalb.uitool.SettingItem; +import org.kne.cloud.klalb.uitool.TextSettingItem; import org.kne.cloud.network.MultipurposeSocketAddress; import org.kne.cloud.network.klalb.CONST; import org.kne.cloud.network.klalb.KLALBController; import org.kne.cloud.network.klalb.KLALBRemoteLine; import org.kne.cloud.network.klalb.KLALBUtils; +import org.kne.cloud.network.klalb.ui.GraphPanel.GraphNode; import org.kne.cloud.network.monitor.MonitorData; import org.kne.ui.XFrame; import org.kne.ui.YScrollPane; @@ -63,8 +78,6 @@ public class KLALBStateGUI2 extends XFrame { private TrayIcon ti; - private long rate=200; - private Timer t,t2,t3; private JCheckBoxMenuItem showoffline; @@ -103,13 +116,16 @@ public class KLALBStateGUI2 extends XFrame { private DefaultValueDataset downEfficiency;*/ - private YScrollPane ysp; + private YScrollPane ysp,yspc; private JTextField devicesOnline; private JTextField textField; private JTextField addressField; + private JTextField addressField2; + private JTextField asnField; private NetworkGraphPanel graph; + private JTextField textFieldLocate; /** @@ -771,11 +787,135 @@ public class KLALBStateGUI2 extends XFrame { JPanel panel_4 = new JPanel(); panel_3.add(panel_4, BorderLayout.NORTH); + panel_4.setLayout(new BorderLayout(0, 0)); + + + + textFieldLocate = new JTextField(); + panel_4.add(textFieldLocate, BorderLayout.CENTER); + textFieldLocate.setColumns(10); graph = new NetworkGraphPanel(kc.getIpv6Router().getKlalbRouteProtol()); graph.setOpaque(false); - JScrollPane jsp=new JScrollPane(graph); + JScrollPane jsp=new JScrollPane();jsp.setWheelScrollingEnabled(false); + jsp.setViewportView(graph); + MouseAdapter ma = new MouseAdapter() { + + private Point origin; + + @Override + public void mousePressed(MouseEvent e) { + origin = new Point(e.getPoint()); + //System.out.println(e); + } + + @Override + public void mouseReleased(MouseEvent e) { + } + + @Override + public void mouseDragged(MouseEvent e) { + if (origin != null) { + //System.out.println(e); + //JViewport viewPort = (JViewport) SwingUtilities.getAncestorOfClass(JViewport.class, jsp); + //if (viewPort != null) { + int deltaX = origin.x - e.getX(); + int deltaY = origin.y - e.getY(); + + Rectangle view = jsp.getViewport().getVisibleRect(); + view.x += deltaX; + view.y += deltaY; + + jsp.getViewport().scrollRectToVisible(view); + // } + } + } + + }; + + + graph.addMouseWheelListener(new MouseWheelListener() { + private double scaleidx=1; + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + int val= e.getWheelRotation(); + double scaleidxold=scaleidx; + scaleidx*=Math.pow(1.1, val); + if(scaleidx>5) { + scaleidx=5; + } + if(scaleidx<0.1) { + scaleidx=0.1; + } + double pow=scaleidx/scaleidxold; + Point pos = jsp.getViewport().getViewPosition(); + double canvasX=e.getX(); + double canvasY=e.getY(); + double w=graph.getWidth(); + double h=graph.getHeight(); + double percentX=canvasX/w; + double percentY=canvasY/h; + graph.setScale(scaleidx); + graph.updateBounds(); + double newcanvasX=percentX*w*pow; + double newcanvasY=percentY*h*pow; + double dx= newcanvasX-canvasX; + double dy=newcanvasY-canvasY; + //System.out.println(dx+" "+dy); + pos.x+=dx; + pos.y+=dy ; + jsp.getViewport().setViewPosition(pos); + } + }); + + + JButton btnLocate = new JButton("Locate"); + btnLocate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String text= textFieldLocate.getText(); + try { + Inet6Address addr=(Inet6Address) Inet6Address.getByName(text); + GraphNode node= graph.getNodes().get(addr); + if(node==null) { + JOptionPane.showMessageDialog(KLALBStateGUI2.this, "Address not found", "Warning", JOptionPane.WARNING_MESSAGE); + }else { + Point pos = new Point(); + graph.updateBounds(); + Dimension dim= jsp.getViewport().getExtentSize(); + // System.out.println(dim); + pos.x =(int) ((node.getX()+graph.getTranslateX())*graph.getScale()-dim.width/2); + pos.y =(int) ((node.getY()+graph.getTranslateY())*graph.getScale()-dim.height/2); + jsp.getViewport().setViewPosition(pos); + } + } catch (UnknownHostException e1) { + JOptionPane.showMessageDialog(KLALBStateGUI2.this, "Input format error", "Error", JOptionPane.ERROR_MESSAGE); + e1.printStackTrace(); + } + } + }); + panel_4.add(btnLocate, BorderLayout.EAST); + + JButton btnHome = new JButton("Home"); + btnHome.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textFieldLocate.setText(addressField.getText()); + btnLocate.doClick(); + } + }); + panel_4.add(btnHome, BorderLayout.WEST); + graph.addMouseListener(ma); + graph.addMouseMotionListener(ma); panel_3.add(jsp, BorderLayout.CENTER); + yspc = new YScrollPane(730); + yspc.setOpaque(false); + JPanel configsPanel = new JPanel(); + configsPanel.setLayout(new BorderLayout(0, 0)); + configsPanel.add(yspc); + addSettingItems(yspc); + JButton btnSave = new JButton("Save settings"); + yspc.add(btnSave, BorderLayout.NORTH); + tabbedPane.addTab("Settings", null, configsPanel, null); + configsPanel.setOpaque(false); textField.addKeyListener(new KeyListener() { @Override @@ -795,7 +935,43 @@ public class KLALBStateGUI2 extends XFrame { } } }); +textFieldLocate.addKeyListener(new KeyListener() { + + @Override + public void keyTyped(KeyEvent e) { + } + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + // TODO 自动生成的方法存根 + + if(e.getKeyCode()==KeyEvent.VK_ENTER) { + btnLocate.doClick(); + } + } + }); } + private void addSettingItems(YScrollPane settings) { + SettingItem si=new SettingItem("Basic settings",UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),CONST.itemwidth,CONST.settingheight); + settings.getView().add(si); + + TextSettingItem addr6=new TextSettingItem("IPv6 address",CONST.itemwidth,CONST.settingheight); + addressField2=addr6.getTextField(); + settings.getView().add(addr6); + + TextSettingItem asn=new TextSettingItem("AS number",CONST.itemwidth,CONST.settingheight); + asnField=asn.getTextField(); + settings.getView().add(asn); + + settings.updateScrool(); + + } + + private void createRefreshTask(KLALBController kc, YScrollPane ysp) { if(tsk!=null) { tsk.cancel(); @@ -920,13 +1096,22 @@ public class KLALBStateGUI2 extends XFrame { if(!contt.equals(devicesOnline.getText())) { devicesOnline.setText(contt); } - String address=kc.getSelf().getHostAddress(); + String address=kc.getSelf().getAddress().getHostAddress(); if(!address.equals(addressField.getText())) { addressField.setText(address); } + if(!address.equals(addressField2.getText())) { + addressField2.setText(address); + } + + String asnstr=Long.toString( kc.getIpv6Router().getASN()); + if(!asnstr.equals(asnField.getText())) { + asnField.setText(asnstr); + } + } }; - t2.scheduleAtFixedRate(tsk2, 200, 50); + t2.scheduleAtFixedRate(tsk2, 200, 100); if(tsk3!=null) { tsk3.cancel(); @@ -970,7 +1155,7 @@ public class KLALBStateGUI2 extends XFrame { } } }; - t3.scheduleAtFixedRate(tsk4, 200, 10); + t3.scheduleAtFixedRate(tsk4, 200, 20); if(tsk5!=null) { tsk5.cancel(); } @@ -978,11 +1163,15 @@ public class KLALBStateGUI2 extends XFrame { @Override public void run() { - if(graph.isVisible()) + graph.loadNodes(); + graph.runPhy(); + if(graph.isVisible()) { graph.repaint(); + graph.revalidate(); + } } }; - t.scheduleAtFixedRate(tsk5, 200, 2000); + t.scheduleAtFixedRate(tsk5, 200, 100); //setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } diff --git a/src/org/kne/cloud/network/klalb/ui/NetworkGraphPanel.java b/src/org/kne/cloud/network/klalb/ui/NetworkGraphPanel.java index 2dbc0ff..b6dbbcf 100644 --- a/src/org/kne/cloud/network/klalb/ui/NetworkGraphPanel.java +++ b/src/org/kne/cloud/network/klalb/ui/NetworkGraphPanel.java @@ -2,6 +2,7 @@ package org.kne.cloud.network.klalb.ui; import java.awt.BasicStroke; import java.awt.Color; +import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; @@ -14,6 +15,7 @@ import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.awt.image.ImageObserver; import java.net.Inet6Address; +import java.net.InetAddress; import java.text.AttributedCharacterIterator; import java.util.ArrayList; import java.util.HashMap; @@ -26,240 +28,80 @@ import java.util.Set; import javax.swing.JButton; import javax.swing.JPanel; +import javax.swing.border.LineBorder; import org.kne.cloud.network.klalb.KLALBUtils; import org.kne.cloud.network.srv6.KLALBRoutingProtocol; import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection; -public class NetworkGraphPanel extends JPanel { +public class NetworkGraphPanel extends GraphPanel { private KLALBRoutingProtocol routingProtocol; - private Map nodes=new HashMap(); - private List edgeGroups=new ArrayList(); - private static final int nodesize=80; - private class GraphNode{ - private String text; - private Color color; - private int x; - private int y; - - public GraphNode(String text, Color color, int x, int y) { - super(); - this.text = text; - this.color = color; - this.x = x; - this.y = y; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public Color getColor() { - return color; - } - - public void setColor(Color color) { - this.color = color; - } - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public GraphNode() { - super(); - } - - public int getY() { - return y; - } - - public void setY(int y) { - this.y = y; - } - - public void paint(Graphics2D g) { - g.setColor(Color.BLACK); - g.setStroke(new BasicStroke(2.0f)); - g.drawOval(x-nodesize/2, y-nodesize/2, nodesize, nodesize); - g.setFont(UIEnv.getFont().deriveFont(10.0f)); - g.drawString(text, x+nodesize/2, y-nodesize/3); - } - } - private class GraphEdge{ - private GraphNode from; - private GraphNode to; - private LinkDirection linkPath; - - public GraphEdge(GraphNode nfrom, GraphNode nto,LinkDirection lp) { - this.from=nfrom; - this.to=nto; - this.linkPath=lp; - } - - } - private class GraphEdgeGroup{ - private static final double gap=3; - private GraphNode nodeA,nodeB; - private List edges=new ArrayList<>(); - private boolean match(GraphNode a,GraphNode b) { - if(a.equals( nodeA)&&b.equals( nodeB)) - return true; - if(b.equals( nodeA)&&a.equals( nodeB)) - return true; - return false; - } - - public GraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) { - super(); - this.nodeA = nodeA; - this.nodeB = nodeB; - } - public List getPaths() { - return edges; - } - public void paint(Graphics2D g) { - g.setStroke(new BasicStroke(1.0f)); - - Vector2 nodeAv=new Vector2(nodeA.getX(), nodeA.getY()); - Vector2 nodeBv=new Vector2(nodeB.getX(), nodeB.getY()); - Vector2 vecDir=nodeBv.subtract(nodeAv); - Vector2 vecDirnor=vecDir.normalize(); - Vector2 vecR=vecDirnor.multi(nodesize/2); - - Vector2 vec90nor=new Vector2( -vecDir.y, vecDir.x).normalize(); - - double width=gap*(edges.size()-1); - - Vector2 startPoint=nodeAv.add(vecR).add(vec90nor.multi(width/2)); - Vector2 endPoint=nodeBv.subtract(vecR).add(vec90nor.multi(width/2)); - //System.out.println(width); - for (Iterator iterator = edges.iterator(); iterator.hasNext();) { - GraphEdge graphEdge = (GraphEdge) iterator.next(); - - //System.out.println(vec90nor); - - g.setColor(KLALBUtils.getColorByLoadPercentage(graphEdge.linkPath.getSpeed()*100f/graphEdge.linkPath.getBandwidth())); - - if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) ) - drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g); - - - if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) ) - drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g); - - startPoint=startPoint.subtract(vec90nor.multi(gap)); - endPoint=endPoint.subtract(vec90nor.multi(gap)); - } - - //g.drawLine(nodeA.getX(), nodeA.getY(), nodeB.getX(), nodeB.getY()); - - } - - public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2) - { - - double H = 5; // 箭头高度 - double L = 2; // 底边的一半 - int x3 = 0; - int y3 = 0; - int x4 = 0; - int y4 = 0; - double awrad = Math.atan(L / H); // 箭头角度 - double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度 - double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len); - double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len); - double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点 - double y_3 = ey - arrXY_1[1]; - double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点 - double y_4 = ey - arrXY_2[1]; - - Double X3 = new Double(x_3); - x3 = X3.intValue(); - Double Y3 = new Double(y_3); - y3 = Y3.intValue(); - Double X4 = new Double(x_4); - x4 = X4.intValue(); - Double Y4 = new Double(y_4); - y4 = Y4.intValue(); - // 画线 - g2.drawLine(sx, sy, ex, ey); - // - GeneralPath triangle = new GeneralPath(); - triangle.moveTo(ex, ey); - triangle.lineTo(x3, y3); - triangle.lineTo(x4, y4); - triangle.closePath(); - //实心箭头 - g2.fill(triangle); - //非实心箭头 - //g2.draw(triangle); - - } - - // 计算 - public static double[] rotateVec(int px, int py, double ang, - boolean isChLen, double newLen) { - - double mathstr[] = new double[2]; - // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度 - double vx = px * Math.cos(ang) - py * Math.sin(ang); - double vy = px * Math.sin(ang) + py * Math.cos(ang); - if (isChLen) { - double d = Math.sqrt(vx * vx + vy * vy); - vx = vx / d * newLen; - vy = vy / d * newLen; - mathstr[0] = vx; - mathstr[1] = vy; - } - return mathstr; - } - - } public NetworkGraphPanel(KLALBRoutingProtocol routingProtocol) { super(); this.routingProtocol = routingProtocol; - //setSize(10000, 10000); - //setPreferredSize(getSize()); } - @Override - public void paint(Graphics g) { - super.paint(g); - loadNodes(); - - Graphics2D g2d=(Graphics2D)g; - - for (Iterator iterator = edgeGroups.iterator(); iterator.hasNext();) { - GraphEdgeGroup graphNode = (GraphEdgeGroup) iterator.next(); - graphNode.paint(g2d); + + private class InetGraphNode extends GraphNode{ + + private InetAddress address; + + public InetGraphNode() { + super(); + } + + public InetGraphNode(InetAddress address, Color color, double x, double y, boolean ismarked) { + super(getText(address), color, x, y, ismarked); + this.address=address; + } + + private static String getText(InetAddress address2) { + String text; + if(address2 instanceof Inet6Address) { + text=KLALBUtils.parseAbbrIPv6(address2.getHostAddress()); + }else { + text=address2.getHostAddress(); + } + return text; + } + + public InetAddress getAddress() { + return address; + } + + public void setAddress(InetAddress address) { + this.address = address; + super.setText(getText(address)); } - for (Iterator iterator = nodes.values().iterator(); iterator.hasNext();) { - GraphNode graphNode = (GraphNode) iterator.next(); - graphNode.paint(g2d); - } - - } - Random r=new Random(); - private void loadNodes() { + + private double nsPerPixel=1000L; + private class InetGraphEdgeGroup extends GraphEdgeGroup{ + public InetGraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) { + super(nodeA, nodeB); + } + + public void updateLength() { + long mindelay=Long.MAX_VALUE>>2; + for (Iterator iterator = getEdges().iterator(); iterator.hasNext();) { + GraphEdge graphEdge = (GraphEdge) iterator.next(); + mindelay=Math.min(mindelay, graphEdge.linkPath.getDelay()); + } + setLength(mindelay/nsPerPixel); + } + } + protected void loadNodes() { Map addr= routingProtocol.getAddresses(); Set ks=addr.keySet(); for (Iterator iterator = ks.iterator(); iterator.hasNext();) { Inet6Address inet6Address = (Inet6Address) iterator.next(); - if(!nodes.containsKey(inet6Address)) - nodes.put(inet6Address,new GraphNode(inet6Address.getHostAddress(),Color.BLACK,r.nextInt(50,getWidth()-100),r.nextInt(50,getHeight()-50))); - } - Set kns=nodes.keySet(); + if(!getNodes().containsKey(inet6Address)) { + Vector2 v2pos=super.getRandomPos(); + getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(routingProtocol.getRouter().getLocator().getAddress()))); + } + } + Set kns=getNodes().keySet(); for (Iterator iterator = kns.iterator(); iterator.hasNext();) { Inet6Address inet6Address = (Inet6Address) iterator.next(); if(!addr.containsKey(inet6Address)) { @@ -267,32 +109,53 @@ public class NetworkGraphPanel extends JPanel { } } //System.out.println("------------------------------------"); - edgeGroups.clear(); - Map> addr1= routingProtocol.getPaths(); - Set>> salink=addr1.entrySet(); - for (Iterator>> iterator = salink.iterator(); iterator.hasNext();) { - Entry> entry = (Entry>) iterator.next(); - Setlps=entry.getValue(); + synchronized (getEdgeGroups()) { + + getEdgeGroups().clear(); + Map> addr1= routingProtocol.getPaths(); + Set>> salink=addr1.entrySet(); + for (Iterator>> iterator = salink.iterator(); iterator.hasNext();) { + Entry> entry = (Entry>) iterator.next(); + Listlps=entry.getValue(); for (Iterator iterator2 = lps.iterator(); iterator2.hasNext();) { LinkDirection linkPath = (LinkDirection) iterator2.next(); //System.out.println(linkPath); - GraphNode nfrom=nodes.get(linkPath.getFromLocator()); - GraphNode nto=nodes.get(linkPath.getToLocator()); + InetGraphNode nfrom=(InetGraphNode) getNodes().get(linkPath.getFromLocator()); + InetGraphNode nto=(InetGraphNode) getNodes().get(linkPath.getToLocator()); + if(nfrom!=null&&nto!=null) { GraphEdgeGroup group=getGroup(nfrom, nto); - group.getPaths().add(new GraphEdge(nfrom,nto,linkPath)); + + + GraphEdge ge=new GraphEdge(nfrom,nto,linkPath); + group.getPaths().add(ge); + } } } + for (Iterator iterator = getEdgeGroups().iterator(); iterator.hasNext();) { + GraphEdgeGroup graphEdgeGroup = (GraphEdgeGroup) iterator.next(); + ((InetGraphEdgeGroup) graphEdgeGroup).updateLength(); + } + } + super.loadNodes(); } - private GraphEdgeGroup getGroup(GraphNode a,GraphNode b) { - for (Iterator iterator = edgeGroups.iterator(); iterator.hasNext();) { + private GraphEdgeGroup getGroup(InetGraphNode a,InetGraphNode b) { + for (Iterator iterator = getEdgeGroups().iterator(); iterator.hasNext();) { GraphEdgeGroup graphEdgeGroup = (GraphEdgeGroup) iterator.next(); if(graphEdgeGroup.match(a,b)) { return graphEdgeGroup; } } - GraphEdgeGroup ng=new GraphEdgeGroup(a, b); - edgeGroups.add(ng); + GraphEdgeGroup ng=new InetGraphEdgeGroup(a, b); + Inet6Address aprev= routingProtocol.getDijkstraPrevNode((Inet6Address) a.getAddress()); + Inet6Address bprev= routingProtocol.getDijkstraPrevNode((Inet6Address) b.getAddress()); + + if( b.getAddress().equals(aprev)||a.getAddress().equals(bprev)) { + ng.setShortest(true); + } + getEdgeGroups().add(ng); return ng; } + + } diff --git a/src/org/kne/cloud/network/klalb/ui/TPanel2.java b/src/org/kne/cloud/network/klalb/ui/TPanel2.java index 8df7561..3371571 100644 --- a/src/org/kne/cloud/network/klalb/ui/TPanel2.java +++ b/src/org/kne/cloud/network/klalb/ui/TPanel2.java @@ -10,6 +10,7 @@ import javax.swing.SwingConstants; import javax.swing.border.LineBorder; import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.klalb.CONST; import org.kne.cloud.network.klalb.KLALBController; import org.kne.cloud.network.klalb.KLALBRemoteLine; import org.kne.cloud.network.klalb.KLALBUtils; @@ -93,7 +94,7 @@ public class TPanel2 extends JPanel { targup.setHorizontalTextPosition(SwingConstants.LEFT); setBorder(new LineBorder(Color.LIGHT_GRAY)); - setSize(720, 45); + setSize(CONST.itemwidth, CONST.linepanelheight); setPreferredSize(getSize()); JPanel panel = new JPanel(); diff --git a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java index 8b2aedd..46faebe 100644 --- a/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java +++ b/src/org/kne/cloud/network/minecraft/SimpleKLALBMinecraftServer.java @@ -90,7 +90,7 @@ public class SimpleKLALBMinecraftServer { try { s=mpsa2.connectSocket(); MinecraftSocketBridge dsb=new MinecraftSocketBridge(pds, s); - dsb.getBridgeBA().getTransformers().add(new KLALBJsonMotdInserter(()->{return kc.getSelf();},()->{return 23333;})); + dsb.getBridgeBA().getTransformers().add(new KLALBJsonMotdInserter(()->{return kc.getSelf().getAddress();},()->{return 23333;})); dsb.run(); } catch (UnknownHostException e) { // TODO 自动生成的 catch 块 @@ -129,7 +129,7 @@ public class SimpleKLALBMinecraftServer { //soc.setTcpNoDelay(true); //((KLALBVirtualSocket) soc).setCompress(1); MinecraftSocketBridge dsb=new MinecraftSocketBridge(soc, s); - dsb.getBridgeBA().getTransformers().add(new KLALBJsonMotdInserter(()->{return kc.getSelf();},()->{return 23333;})); + dsb.getBridgeBA().getTransformers().add(new KLALBJsonMotdInserter(()->{return kc.getSelf().getAddress();},()->{return 23333;})); //dsb.getSab().setDelay(1); dsb.run(); /*CompressedSocketBridge csb=new CompressedSocketBridge(s, soc); diff --git a/src/org/kne/cloud/network/monitor/MonitorData.java b/src/org/kne/cloud/network/monitor/MonitorData.java index 8b230eb..699192a 100644 --- a/src/org/kne/cloud/network/monitor/MonitorData.java +++ b/src/org/kne/cloud/network/monitor/MonitorData.java @@ -2,7 +2,7 @@ package org.kne.cloud.network.monitor; import java.util.function.Consumer; -public interface MonitorData { +public interface MonitorData extends Cloneable { public static final int OFFLINE=0; public static final int CONNECTING=1; public static final int ONLINE=2; @@ -30,4 +30,6 @@ public double getReliability(); throw new IllegalArgumentException("Unknown state:"+state); } } + public Object clone() throws CloneNotSupportedException; + } diff --git a/src/org/kne/cloud/network/monitor/MonitorDataImpl.java b/src/org/kne/cloud/network/monitor/MonitorDataImpl.java index e74ab72..53331f7 100644 --- a/src/org/kne/cloud/network/monitor/MonitorDataImpl.java +++ b/src/org/kne/cloud/network/monitor/MonitorDataImpl.java @@ -86,4 +86,9 @@ private TimerTask ptt=new TimerTask() { public double getReliability() { return reliability; } +@Override +public Object clone() throws CloneNotSupportedException { + return super.clone(); +} + } diff --git a/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java index 11214df..8cda996 100644 --- a/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java +++ b/src/org/kne/cloud/network/monitor/SpeedAndTrafficMonitorDataImpl.java @@ -47,7 +47,7 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S } protected void createTask1() { - getTimer().scheduleAtFixedRate(tmt1, 0, 1000); + getTimer().scheduleAtFixedRate(tmt1, 0, 500); } protected void createTask2() { getTimer().scheduleAtFixedRate(tmt2, 0, 5000); @@ -123,24 +123,24 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S if(inTraffic!=null) { long i=inTraffic.get()-inTrafficOld; inTrafficOld =inTraffic.get(); - inSpeed= i*1000000000/d; + inSpeed= (long) (i*1000000000.0/d); } if(outTraffic!=null) { long o=outTraffic.get()-outTrafficOld; outTrafficOld =outTraffic.get(); - outSpeed= o*1000000000/d; + outSpeed= (long) (o*1000000000.0/d); } if(inCounter!=null) { long i=inCounter.get()-inCounterOld; inCounterOld =inCounter.get(); - inPPS= i*1000000000/d; + inPPS= (long) (i*1000000000.0/d); } if(outCounter!=null) { long i=outCounter.get()-outCounterOld; outCounterOld =outCounter.get(); - outPPS= i*1000000000/d; + outPPS= (long) (i*1000000000.0/d); } } if(outSpeed>=outSpeedMax) { @@ -182,25 +182,25 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S if(inTraffic!=null) { long i=inTraffic.get()-inTrafficOld1; inTrafficOld1 =inTraffic.get(); - inSpeedAvg= i*1000000000/d; + inSpeedAvg= (long) (i*1000000000.0/d); } if(outTraffic!=null) { long o=outTraffic.get()-outTrafficOld1; outTrafficOld1 =outTraffic.get(); - outSpeedAvg= o*1000000000/d; + outSpeedAvg= (long) (o*1000000000.0/d); } if(inCounter!=null) { long i=inCounter.get()-inCounterOld1; inCounterOld1 =inCounter.get(); - inPPSAvg= i*1000000000/d; + inPPSAvg= (long) (i*1000000000.0/d); } if(outCounter!=null) { long o=outCounter.get()-outCounterOld1; outCounterOld1 =outCounter.get(); - outPPSAvg= o*1000000000/d; + outPPSAvg= (long) (o*1000000000.0/d); } } @@ -218,13 +218,13 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S if(inTraffic!=null) { long i=inTraffic.get()-inTrafficOld2; inTrafficOld2 =inTraffic.get(); - inSpeedAvg2= i*1000000000/d; + inSpeedAvg2= (long) (i*1000000000.0/d); } if(outTraffic!=null) { long o=outTraffic.get()-outTrafficOld2; outTrafficOld2 =outTraffic.get(); - outSpeedAvg2= o*1000000000/d; + outSpeedAvg2= (long) (o*1000000000.0/d); } @@ -232,13 +232,13 @@ public class SpeedAndTrafficMonitorDataImpl extends MonitorDataImpl implements S if(inCounter!=null) { long i=inCounter.get()-inCounterOld2; inCounterOld2 =inCounter.get(); - inPPSAvg2= i*1000000000/d; + inPPSAvg2= (long) (i*1000000000.0/d); } if(outCounter!=null) { long o=outCounter.get()-outCounterOld2; outCounterOld2 =outCounter.get(); - outPPSAvg2= o*1000000000/d; + outPPSAvg2= (long) (o*1000000000.0/d); } } diff --git a/src/org/kne/cloud/network/perf/Kperf.java b/src/org/kne/cloud/network/perf/Kperf.java index bafaef6..c241053 100644 --- a/src/org/kne/cloud/network/perf/Kperf.java +++ b/src/org/kne/cloud/network/perf/Kperf.java @@ -24,7 +24,6 @@ import org.kne.cloud.network.klalb.KLALBPacketLink; import org.kne.cloud.network.klalb.KLALBUtils; import org.kne.cloud.network.klalb.PINGPacket; import org.kne.cloud.network.klalb.PONGPacket; -import org.kne.cloud.network.klalb.TESTPacket; import org.kne.cloud.network.klalb.VADDRACKPacket; import org.kne.cloud.network.klalb.VADDRPacket; import org.kne.cloud.network.klalb.VADDRREQPacket; @@ -74,12 +73,13 @@ public class Kperf implements Runnable{ private SpeedLimiter test = new SpeedLimiter(MIN_SPEED,10000000L); private static long MIN_SPEED=64*1024L; - private SpeedLimiter congress = new SpeedLimiter(0,10000000L); + private SpeedLimiter congress = new SpeedLimiter(10000000L); private long congressSpeed = 0; private double loadPercent = 1.01; - - private volatile int testSize=0; - //kperf {KLALB_Stream}[2486:1:34de:4abd:98c1:abd1:fc7a:401]:4564 + + KLALBPacket testPacket=null; + //kperf {KLALB_Stream}[2486:1:f189:7589:f1f7:6f5e:b2eb:1]:4564 + //kperf {KLALB_Stream}[2486:1::8888]:4564 @Override public void run() { Thread tc = ThreadTool.makeVDaemonThreadIfSupport("测速控制线程", () -> { @@ -100,14 +100,14 @@ public class Kperf implements Runnable{ System.out.printf("下载延迟 最小:%.3fms 平均:%.3fms 抖动:%.3fms\n",monitor.getInDelayMin()/1000000.0,monitor.getInDelayAvg()/1000000.0,monitor.getInJitter()/1000000.0); System.out.println("等待时间"+wtimes+"s"); - Thread.sleep(wtimes*1000);*/ + Thread.sleep(wtimes*1000); - +*/ startTime=System.nanoTime(); if(targetAddress!=null) { System.out.println("测试2/4:下载带宽测试"); test.setLimitspeed(0); - testSize=60000; + testPacket=new TESTNPacket(60000); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg())); @@ -118,7 +118,7 @@ public class Kperf implements Runnable{ }else { System.out.println("测试2/4:上传带宽测试"); test.setLimitspeed(1000L*1024L*1024L*1024L); - testSize=60000; + testPacket=new TESTNPacket(60000); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg())); @@ -135,7 +135,7 @@ public class Kperf implements Runnable{ if(targetAddress!=null) { System.out.println("测试3/4:上传带宽测试"); test.setLimitspeed(1000L*1024L*1024L*1024L); - testSize=60000; + testPacket=new TESTNPacket(60000); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg())); @@ -146,7 +146,7 @@ public class Kperf implements Runnable{ }else { System.out.println("测试3/4:下载带宽测试"); test.setLimitspeed(0); - testSize=60000; + testPacket=new TESTNPacket(60000); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg())); @@ -162,7 +162,7 @@ public class Kperf implements Runnable{ if(targetAddress!=null) { System.out.println("测试2/4:下载包转发率测试"); test.setLimitspeed(0); - testSize=0; + testPacket=new TEST1Packet(); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS())); @@ -171,7 +171,7 @@ public class Kperf implements Runnable{ }else { System.out.println("测试2/4:上传包转发率测试"); test.setLimitspeed(1000L*1024L*1024L*1024L); - testSize=0; + testPacket=new TEST1Packet(); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS())); @@ -186,7 +186,7 @@ public class Kperf implements Runnable{ if(targetAddress!=null) { System.out.println("测试3/4:上传包转发率测试"); test.setLimitspeed(1000L*1024L*1024L*1024L); - testSize=0; + testPacket=new TEST1Packet(); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS())); @@ -196,7 +196,7 @@ public class Kperf implements Runnable{ }else { System.out.println("测试3/4:下载包转发率测试"); test.setLimitspeed(0); - testSize=0; + testPacket=new TEST1Packet(); for (int i = 0; i < 30; i++) { System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0); System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS())); @@ -206,17 +206,19 @@ public class Kperf implements Runnable{ } System.out.println("等待时间"+wtimes+"s"); Thread.sleep(wtimes*1000); - + + System.out.println("测速结束!"); + } catch (InterruptedException e) { - e.printStackTrace(); - } - System.out.println("测速结束!"); + System.out.println("测速被中断!"); + }finally { close(); + } }); try { monitor.setState(MonitorData.CONNECTING); if(link==null) - link=KLALBUtils.createKLALBPacketLink(bindAddress, targetAddress,20000); + link=KLALBUtils.createKLALBPacketLink(bindAddress, targetAddress,false,20000); link.setSoTimeout(20000); @@ -243,10 +245,9 @@ public class Kperf implements Runnable{ }else { - - if (test.checkTransmit(testSize+3)) { - TESTPacket tp=new TESTPacket(testSize); - writePacketToKPL(tp); + KLALBPacket testp=testPacket; + if (testp!=null&&test.checkTransmit(testp.getLength())) { + writePacketToKPL(testp); @@ -351,7 +352,7 @@ public class Kperf implements Runnable{ congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * loadPercent)) ); // System.out.println(congressSpeed); break; - case KLALBPacket.TEST: + case KLALBPacket.TESTN: break; } Thread.yield(); @@ -371,6 +372,7 @@ public class Kperf implements Runnable{ e.printStackTrace(); } } + tc.interrupt(); } } private volatile long time = System.nanoTime(); @@ -441,7 +443,7 @@ public class Kperf implements Runnable{ private KLALBPacket readPacketFromKPL() throws IOException { - KLALBPacket packet = link.readPacket(); + KLALBPacket packet = link.readKLALBPacket(); if (showpacket) { System.out.println("RX:" + packet); @@ -459,7 +461,7 @@ public class Kperf implements Runnable{ long length=packet.getLength(); monitor.getOutTrafficAL().addAndGet(length); monitor.getOutPacketCounterAL().incrementAndGet(); - link.writePacket(packet); + link.writeKLALBPacket(packet); link.flush(); packet.putTimePassport("sended"); packet.printPassport(); diff --git a/src/org/kne/cloud/network/perf/MemcpyBenchmark.java b/src/org/kne/cloud/network/perf/MemcpyBenchmark.java new file mode 100644 index 0000000..42e640f --- /dev/null +++ b/src/org/kne/cloud/network/perf/MemcpyBenchmark.java @@ -0,0 +1,57 @@ +package org.kne.cloud.network.perf; + +import java.nio.ByteBuffer; + +import org.kne.cloud.network.NetworkPacket; + +public class MemcpyBenchmark { + public static void testArrayCopySpeed(int i) { + byte[]a=new byte[i]; + byte[]b=new byte[i]; + long start=System.nanoTime(); + System.arraycopy(a, 0, b, 0, i); + long time=System.nanoTime()-start; + long speed=i*1000000000L/time; + System.out.println(speed/1024L/1024L+" MB/s"); + } + public static void testByteBufferCopySpeed(int i) { + ByteBuffer a=ByteBuffer.allocateDirect(i); + ByteBuffer b=ByteBuffer.allocateDirect(i); + long start=System.nanoTime(); + a.put(b); + long time=System.nanoTime()-start; + long speed=i*1000000000L/time; + System.out.println(speed/1024L/1024L+" MB/s"); + } + public static Object un; + public static void testDirectByteBufferAllocateSpeed(int i) { + long start=System.nanoTime(); + for(int ix=0;ix<10000;ix++) { + ByteBuffer a=ByteBuffer.allocateDirect(i); + un=a; + } + long time=System.nanoTime()-start; + long speed=i*1000000000L/time*10000L; + System.out.println(speed/1024L/1024L+" MB/s"); + } + public static void testByteBufferAllocateSpeed(int i) { + long start=System.nanoTime(); + for(int ix=0;ix<10000;ix++) { + ByteBuffer a=ByteBuffer.allocate(i); + un=a; + } + long time=System.nanoTime()-start; + long speed=i*1000000000L/time*10000L; + System.out.println(speed/1024L/1024L+" MB/s"); + } + public static void testByteBufferAllocatorSpeed(int i) { + long start=System.nanoTime(); + for(int ix=0;ix<10000;ix++) { + ByteBuffer a=NetworkPacket.bufferAllocator.allocate(i); + un=a; + } + long time=System.nanoTime()-start; + long speed=i*1000000000L/time*10000L; + System.out.println(speed/1024L/1024L+" MB/s"); + } +} diff --git a/src/org/kne/cloud/network/perf/NodeBenchmark.java b/src/org/kne/cloud/network/perf/NodeBenchmark.java new file mode 100644 index 0000000..4b38b6e --- /dev/null +++ b/src/org/kne/cloud/network/perf/NodeBenchmark.java @@ -0,0 +1,91 @@ +package org.kne.cloud.network.perf; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.channels.ServerSocketChannel; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.kne.cloud.network.MultipurposeSocketAddress; +import org.kne.cloud.network.SocketChannelListener; +import org.kne.cloud.network.ThreadTool; +import org.kne.cloud.network.klalb.KLALBController; +import org.kne.cloud.network.klalb.KLALBRemoteLine; +import org.kne.cloud.network.klalb.StreamChannelKLALBPacketLink; + +public class NodeBenchmark implements Runnable{ + private List nodeList=new ArrayList<>(); + private class NodeEntry{ + private SocketChannelListener scl; + private KLALBController kc; + public SocketChannelListener getScl() { + return scl; + } + public KLALBController getKc() { + return kc; + } + public NodeEntry(SocketChannelListener scl, KLALBController kc) { + super(); + this.scl = scl; + this.kc = kc; + } + + } + private KLALBController klalbController; + private int nodes; + public NodeBenchmark(KLALBController klalbController,int nodes) { + this.klalbController=klalbController; + this.nodes=nodes; + } + + public void run() { +Random r=new Random(); +for (int i = 0; i < nodes; i++) { + KLALBController kct=new KLALBController(false); + try { + SocketChannelListener scl=new SocketChannelListener(ServerSocketChannel.open().bind(new InetSocketAddress("127.0.0.8",0))); + scl.setCon((c)->{ + try { + kct.addRemoteLine(new KLALBRemoteLine(new StreamChannelKLALBPacketLink(c))); + } catch (IOException e) { + e.printStackTrace(); + } + }); + System.out.println("KLALBController "+i+" created,locator:"+kct.getSelf()); + int size=nodeList.size(); + if(size>0) { + for (int j = 0; j < 1; j++) { + int ind=r.nextInt(size); + NodeEntry ne=nodeList.get(ind); + MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress((InetSocketAddress) ne.getScl().getServerSocketChannel().getLocalAddress()); + kct.addRemoteLines(mpsa); + System.out.println("connect:" +ne.getKc().getSelf().getAddress()); + + + } + } + nodeList.add(new NodeEntry( scl, kct)); + Thread.sleep(100); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +try { +NodeEntry ne=nodeList.get(0); +MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress((InetSocketAddress) ne.getScl().getServerSocketChannel().getLocalAddress()); +klalbController.addRemoteLines(mpsa); +} catch (IOException e) { + e.printStackTrace(); +} + } + + public void startPerfing() { + ThreadTool.makeVThreadIfSupport("节点数量测试线程" ,this).start(); + } + +} diff --git a/src/org/kne/cloud/network/perf/TEST1Packet.java b/src/org/kne/cloud/network/perf/TEST1Packet.java new file mode 100644 index 0000000..0315b13 --- /dev/null +++ b/src/org/kne/cloud/network/perf/TEST1Packet.java @@ -0,0 +1,34 @@ +package org.kne.cloud.network.perf; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +import org.kne.cloud.network.klalb.KLALBPacket; + +public class TEST1Packet extends KLALBPacket { +private static final int HEADER_LENGTH=1; + + @Override + public long getLength() { + return HEADER_LENGTH; + } + + + public TEST1Packet() { + super(TEST1,HEADER_LENGTH); + } + + + public TEST1Packet(ByteBuffer bb) { + super(bb,HEADER_LENGTH); + } + + + @Override + public String toString() { + return "TEST1"; + } +} diff --git a/src/org/kne/cloud/network/klalb/TESTPacket.java b/src/org/kne/cloud/network/perf/TESTNPacket.java similarity index 71% rename from src/org/kne/cloud/network/klalb/TESTPacket.java rename to src/org/kne/cloud/network/perf/TESTNPacket.java index 15fee88..252dd8c 100644 --- a/src/org/kne/cloud/network/klalb/TESTPacket.java +++ b/src/org/kne/cloud/network/perf/TESTNPacket.java @@ -1,4 +1,4 @@ -package org.kne.cloud.network.klalb; +package org.kne.cloud.network.perf; import java.io.DataInput; import java.io.DataInputStream; @@ -11,8 +11,9 @@ import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.klalb.KLALBPacket; -public class TESTPacket extends KLALBPacket { +public class TESTNPacket extends KLALBPacket { private static final int HEADER_LENGTH=3; @@ -23,8 +24,8 @@ public class TESTPacket extends KLALBPacket { } - public TESTPacket(int limit) { - super(TEST,HEADER_LENGTH); + public TESTNPacket(int limit) { + super(TESTN,HEADER_LENGTH); //dataBuffer.limit(limit); dataBuffer=ByteBuffer.allocate(limit); } @@ -37,7 +38,7 @@ public class TESTPacket extends KLALBPacket { @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { klalbHeader.putChar(1, (char) dataBuffer.limit()); super.writeToChannel(dto); //System.out.println(dataBuffer); @@ -45,7 +46,7 @@ public class TESTPacket extends KLALBPacket { } @Override - protected void readFromChannel(ReadableByteChannel din) throws IOException { + public void readFromChannel(ReadableByteChannel din) throws IOException { super.readFromChannel(din); int limit=klalbHeader.getChar(1); //dataBuffer.clear(); @@ -59,14 +60,14 @@ public class TESTPacket extends KLALBPacket { dataBuffer.flip(); } - public TESTPacket(ByteBuffer bb) { + public TESTNPacket(ByteBuffer bb) { super(bb,HEADER_LENGTH); } @Override public String toString() { - return "TEST["+dataBuffer.limit()+"]"; + return "TESTN["+dataBuffer.limit()+"]"; } diff --git a/src/org/kne/cloud/network/srv6/ACKSEQSSegmentRoutingTLV.java b/src/org/kne/cloud/network/srv6/ACKSEQSSegmentRoutingTLV.java new file mode 100644 index 0000000..b0079e3 --- /dev/null +++ b/src/org/kne/cloud/network/srv6/ACKSEQSSegmentRoutingTLV.java @@ -0,0 +1,101 @@ +package org.kne.cloud.network.srv6; + +import java.io.EOFException; +import java.io.IOException; +import java.net.Inet6Address; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.UUID; + +import org.kne.cloud.network.klalb.IPSequence; + +public class ACKSEQSSegmentRoutingTLV extends IPv6SegmentRoutingTLV { + public ACKSEQSSegmentRoutingTLV(ByteBuffer klalbHeader) { + super(klalbHeader); + } + + @Override + public String toString() { + return "ACKSEQSSegmentRoutingTLV [getSequence()=" + getSequence() + "]"; + } + + public ACKSEQSSegmentRoutingTLV(UUID ackid, boolean promise) { + super(IPv6SegmentRoutingTLV.ACKSEQS); + setUUID(ackid); + setPromise(promise); + getData().limit(22); + } + public ACKSEQSSegmentRoutingTLV(IPSequence ackid, boolean promise) { + super(IPv6SegmentRoutingTLV.ACKSEQS); + setIPSequence(ackid); + setPromise(promise); + getData().limit(22); + } + public void setUUID(UUID uuid) { + getData().putLong(6,uuid.getMostSignificantBits()); + getData().putLong(14,uuid.getLeastSignificantBits()); + } + + public UUID getUUID() { + return new UUID(getData().getLong(6),getData().getLong(14)); + } + public void setIPSequence(IPSequence ackid) { + setUUID(ackid.getUuid()); + } + + public IPSequence getIPSequence() { + return new IPSequence(getUUID(),isPromise()); + } + + @Override + public void writeToChannel(WritableByteChannel dto) throws IOException { + + super.writeToChannel(dto); + + } + + @Override + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { + super.readFromChannel(din, length); + + } + + public long getSequence() { + return getData().getLong(6); + } + public void setSequence(long sequence) { + getData().putLong(6,sequence); + } + public int getFlowNumber() { + return getData().getInt(2); + } + public void setFlowNumber(int flowsequence) { + getData().putInt(2,flowsequence); + } + public void setACKIP(Inet6Address ip) { + getData().put(14, ip.getAddress()); + } + public Inet6Address getACKIP() { + byte[]arr=new byte[16]; + getData().get(14,arr); + try { + return (Inet6Address) Inet6Address.getByAddress(arr); + } catch (UnknownHostException e) { + e.printStackTrace(); + return null; + } + } + public boolean isPromise() { + return getData().get(0)!=0?true:false; + } + + public void setPromise(boolean promise) { + if(promise) { + getData().put(0, (byte) 1); + }else { + getData().put(0, (byte) 0); + } + } +} diff --git a/src/org/kne/cloud/network/srv6/DijkstraAlgorithm.java b/src/org/kne/cloud/network/srv6/DijkstraAlgorithm.java index b1990cc..6322e66 100644 --- a/src/org/kne/cloud/network/srv6/DijkstraAlgorithm.java +++ b/src/org/kne/cloud/network/srv6/DijkstraAlgorithm.java @@ -1,6 +1,7 @@ package org.kne.cloud.network.srv6; public interface DijkstraAlgorithm extends Runnable{ + public static final long MAX_WEIGHT=Long.MAX_VALUE/256L; public void setGraph(long[][]pointers,long[][]heap,long startPoint) ; public void run(); public long[] getDirection(); diff --git a/src/org/kne/cloud/network/srv6/IPv6SegmentRoutingTLV.java b/src/org/kne/cloud/network/srv6/IPv6SegmentRoutingTLV.java index 1c7264e..42a8f30 100644 --- a/src/org/kne/cloud/network/srv6/IPv6SegmentRoutingTLV.java +++ b/src/org/kne/cloud/network/srv6/IPv6SegmentRoutingTLV.java @@ -14,14 +14,21 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { public static final int PADN=4; public static final int HMAC=5; public static final int SEQS=7; + public static final int ACKSEQS=8; + private int headerLength=2; + + public int getHeaderLength() { + return headerLength; + } + private boolean isDefault; protected volatile ByteBuffer header; private ByteBuffer data; - public IPv6SegmentRoutingTLV(ByteBuffer header ) { + public IPv6SegmentRoutingTLV(ByteBuffer header ) { this(header,true); } @@ -32,7 +39,10 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { public IPv6SegmentRoutingTLV(ByteBuffer header ,boolean isDefault ) { super(); this.header = header; - if(isDefault&&(getType()!=PAD1)) { + this.isDefault=isDefault; + if(getType()==PAD1) + headerLength=1; + if(isDefault&&(headerLength>1)) { data=ByteBuffer.allocate(512); } } @@ -42,17 +52,19 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { public IPv6SegmentRoutingTLV(int type,boolean isDefault) { super(); this.header=ByteBuffer.allocate(2); + this.isDefault=isDefault; header.put((byte) type); - if(isDefault&&(type!=PAD1)) { + if(type==PAD1) { + headerLength=1; + } + if(isDefault&&(headerLength>1)) { data=ByteBuffer.allocate(512); } } @Override public long getLength() { - if(getType()==PAD1) - return 1; - return header.limit()+(isDefault?data.limit():0); + return headerLength+(isDefault?data.limit():0); } public static IPv6SegmentRoutingTLV readIPv6SegmentRoutingTLVFromChannel(ReadableByteChannel din) throws IOException { @@ -74,6 +86,14 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { rtlv=new PADNSegmentRoutingTLV(bbf); rtlv.readFromChannel(din); return rtlv; + case SEQS: + rtlv=new SEQSSegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; + case ACKSEQS: + rtlv=new ACKSEQSSegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; default: rtlv=new IPv6SegmentRoutingTLV(bbf); rtlv.readFromChannel(din); @@ -84,26 +104,26 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { tlv.writeToChannel(dto); } @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { - if(isDefault&&(getType()!=PAD1)) { + public void writeToChannel(WritableByteChannel dto) throws IOException { + if(isDefault&&(headerLength>1)) { setDataLength(data.limit()); } + header.limit(headerLength); dto.write(header.slice(0,header.limit())); - if(isDefault&&(getType()!=PAD1)) { + if(isDefault&&(headerLength>1)) { dto.write(data.slice(0, data.limit())); } } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { header.limit(1); while (header.hasRemaining()) { if (din.read(header) == -1) { throw new EOFException(); } } - int type=getType(); - if(type!=PAD1) { + if(headerLength>1) { header.limit(2); while (header.hasRemaining()) { if (din.read(header) == -1) { @@ -113,7 +133,7 @@ public class IPv6SegmentRoutingTLV extends NetworkPacket { } header.flip(); - if(isDefault&&(getType()!=PAD1)) { + if(isDefault&&(headerLength>1)) { data.clear(); data.limit(getDataLength()); while(data.hasRemaining()){ diff --git a/src/org/kne/cloud/network/srv6/KLALBRoutingProtocol.java b/src/org/kne/cloud/network/srv6/KLALBRoutingProtocol.java index 925a0b9..7328c6f 100644 --- a/src/org/kne/cloud/network/srv6/KLALBRoutingProtocol.java +++ b/src/org/kne/cloud/network/srv6/KLALBRoutingProtocol.java @@ -32,26 +32,41 @@ import java.util.concurrent.locks.ReentrantLock; import org.kne.cloud.network.ipv6.IPv6NetworkLink; import org.kne.cloud.network.ipv6.Inet6AddressGroup; import org.kne.cloud.network.ipv6.Neighbor; +import org.kne.cloud.network.klalb.KLALBVirtualRawSocket; import org.kne.cloud.network.monitor.DelayMonitorData; import org.kne.cloud.network.monitor.MonitorData; import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl; import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorData; import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl; import org.kne.cloud.network.scanner.InetAddressRange; +import org.kne.cloud.network.te.BandwidthDistributer; + +import com.google.gson.internal.Pair; public class KLALBRoutingProtocol extends Thread{ private static final boolean debug = false; - + + private RouterInfo selfRouterInfo; private Map netmap=new ConcurrentHashMap<>(); private volatile Mapaddresses; - private volatile Map> paths; + private volatile Map> paths; + + + + + + + + public static final int DEFAULT_PORT=1001; + public static final int DEFAULT_PROTOCOL_NUMBER=252; + public static final long HOTSOPT_TIMEOUT = 1000000000; public static final int HOTSOPT_REPORT_INTERVAL = 100000000; @@ -63,60 +78,59 @@ public class KLALBRoutingProtocol extends Thread{ this.router=router; } - private ReentrantLock sendlock=new ReentrantLock(); + //private ReentrantLock sendlock=new ReentrantLock(); private long floodTimer=System.nanoTime(); private long floodTimer2=System.nanoTime(); + private long requestTimer=System.nanoTime(); @Override public void run() { Thread.currentThread().setName("KLALB路由协议接收线程"); getSelfRouterInfo(); - DatagramSocket ds = null; + KLALBVirtualRawSocket ds = null; try{ - ds=new DatagramSocket(new InetSocketAddress(router.getLocator().getAddress(), DEFAULT_PORT) ); - DatagramSocket ds2=ds; + ds=new KLALBVirtualRawSocket(router,router.getLocator().getAddress(), DEFAULT_PROTOCOL_NUMBER); + KLALBVirtualRawSocket ds2=ds; new Thread(()->{ Thread.currentThread().setName("KLALB路由协议接收线程"); while(true) { try { - /*Listlinks=router.getLinkTabel(); - Object[] nls=links.toArray(); - byte[]to=createLinkStatePacket(nls); - DatagramPacket dgp=new DatagramPacket(to,to.length); - - for(int i=0;ineis=nl.discoverNeighbors(); - for (Iterator iteratorx = neis.iterator(); iteratorx.hasNext();) { - Inet6Address addresses = (Inet6Address) iteratorx.next(); - dgp.setAddress(addresses); - dgp.setPort(DEFAULT_PORT); - ds2.send(dgp); - } - } - }*/ - RouterInfo slf= getSelfRouterInfo(); - RouterInfo oslf=netmap.put(slf.getLocator().getAddress(), slf); + selfRouterInfo = getSelfRouterInfo(); + RouterInfo oslf=netmap.put(selfRouterInfo.getLocator().getAddress(), selfRouterInfo); noticeUpdate(); - if(oslf==null||(!slf.equals(oslf))) { - //System.out.println("change:"+oslf+"\n"+slf); + /*if(oslf==null||(!selfRouterInfo.equals(oslf))) { long cur=System.nanoTime(); if(cur-floodTimer2>5000000000L) { //System.out.println("update10"); floodTimer2=cur; - floodPacket(ds2, null, new RouterInfoPacket(slf,true)); + floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true)); } }else { long cur=System.nanoTime(); if(cur-floodTimer>60000000000L) { //System.out.println("update60"); floodTimer=cur; - floodPacket(ds2, null, new RouterInfoPacket(slf,true)); + floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true)); } + }*/ + + long cur=System.nanoTime(); + if(cur-floodTimer>60000000000L) { + if(debug) + System.out.println("update60"); + floodTimer=cur; + floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true,-1)); } - Set requestSet=new HashSet<>(); + + if(cur-floodTimer2>1000000000L) { + if(debug) + System.out.println("update1"); + floodTimer2=cur; + floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true,router.getASN())); + } + + //Set requestSet=new HashSet<>(); for (Iterator> iterator = netmap.entrySet().iterator(); iterator.hasNext();) { Entry type = (Entry) iterator.next(); RouterInfo val=type.getValue(); @@ -124,7 +138,7 @@ public class KLALBRoutingProtocol extends Thread{ iterator.remove(); noticeUpdate(); } - Set ads=val.getNeighborAddresses(); + /*List ads=val.getNeighborAddresses(); for (Iterator iterator2 = ads.iterator(); iterator2.hasNext();) { Inet6Address address=iterator2.next().getLocator().getAddress(); //System.out.println(address); @@ -132,35 +146,37 @@ public class KLALBRoutingProtocol extends Thread{ requestSet.add(address); } - } + }*/ } + + + computeShortestPathIfUpdated(); + + + /*long cur2=System.nanoTime(); + if(cur2-requestTimer>1000000000L) { + requestTimer=cur2; + for (Iterator iterator = requestSet.iterator(); iterator.hasNext();) { Inet6Address inet6Address = (Inet6Address) iterator.next(); - byte[]to=new byte[] {0}; - DatagramPacket dgp=new DatagramPacket(to,to.length); - dgp.setAddress(inet6Address); - dgp.setPort(DEFAULT_PORT); + + writePacket(ds2, new RouterInfoRequestPacket( ), new InetSocketAddress(inet6Address, DEFAULT_PORT)); + if(debug) System.out.println("Request:"+inet6Address); - sendlock.lock(); - try { - ds2.send(dgp); - }catch(SocketException e) { - System.out.println("Send failed:"+dgp.getAddress()); - }finally { - sendlock.unlock(); - } + } - + + }*/ for (Iterator> iterator = hotspots.entrySet().iterator(); iterator.hasNext();) { Entry type = (Entry) iterator.next(); if(type.getValue().checkReportTime()) { //System.out.println("hotspot address:"+type.getKey()); - writePacket(ds2, new RouterInfoPacket( netmap.get(router.getLocator().getAddress()),false), new InetSocketAddress(type.getKey(), DEFAULT_PORT)); + writePacket(ds2, new RouterInfoPacket( netmap.get(router.getLocator().getAddress()),false,-1), new InetSocketAddress(type.getKey(), DEFAULT_PORT)); } if(type.getValue().checkTimeOut()) { iterator.remove(); @@ -193,8 +209,16 @@ public class KLALBRoutingProtocol extends Thread{ switch(kp.getType()) { case KLALBRoutingProtocolPacket.RINFO_REQ: RouterInfo rifr=netmap.get(router.getLocator().getAddress()); - if(rifr!=null) - writePacket(ds, new RouterInfoPacket( rifr,false), dgp.getSocketAddress()); + if(debug) + System.out.println("get Request from:"+dgp.getSocketAddress()); + if(rifr!=null) { + writePacket(ds, new RouterInfoPacket( rifr,false,-1), dgp.getSocketAddress()); + if(debug) + System.out.println("response router info:"+rifr); + }else { + if(debug) + System.out.println("router info is null!"); + } break; case KLALBRoutingProtocolPacket.RINFO: @@ -237,7 +261,8 @@ public class KLALBRoutingProtocol extends Thread{ } } - private void floodPacket(DatagramSocket ds,SocketAddress except,KLALBRoutingProtocolPacket rifp) throws IOException { + private void floodPacket(KLALBVirtualRawSocket ds2,SocketAddress except,RouterInfoPacket rifp) throws IOException { + long asn=rifp.getASN(); Listlinks=router.getLinkTabel(); Object[] nls=links.toArray(); for(int i=0;i> s=netmap.entrySet(); - Mapairs=new HashMap<>(); + Mapairs=new HashMap<>(netmap.size()+1); - Listrias=new ArrayList<>(); + Listrias=new ArrayList<>(netmap.size()+1); - Map>paths=new HashMap<>(); + Map>paths=new HashMap<>(); long number=0; - for (Iterator> iterator = s.iterator(); iterator.hasNext();) { - Entry entry = (Entry) iterator.next(); + for(Entry entry:s) { if(!airs.containsKey(entry.getKey())) { airs.put(entry.getKey(),number); rias.add( entry.getKey()); number++; } - Set ni= entry.getValue().getNeighborAddresses(); - for (Iterator iterator2 = ni.iterator(); iterator2.hasNext();) { - NeighborInfo neighborInfo = (NeighborInfo) iterator2.next(); + List ni= entry.getValue().getNeighborAddresses(); + for(NeighborInfo neighborInfo :ni) { Inet6Address ias2=neighborInfo.getLocator().getAddress(); if(!airs.containsKey(ias2)) { airs.put(ias2,number); rias.add( ias2); number++; } - Setlp1=paths.get(entry.getKey()); + Listlp1=paths.get(entry.getKey()); if(lp1==null) { - paths.put(entry.getKey(), lp1=new HashSet<>()); + paths.put(entry.getKey(), lp1=new ArrayList<>()); } - lp1.add(new LinkDirection(neighborInfo.getLocal(),neighborInfo.getNeighbor(),entry.getKey(), ias2, neighborInfo.getUploadDelay(),neighborInfo.getUploadSpeed(),neighborInfo.getUploadSpeedMax())); + lp1.add(new LinkDirection(neighborInfo.getLocal(),neighborInfo.getNeighbor(),entry.getKey(), ias2, neighborInfo.getUploadDelay(),neighborInfo.getUploadDelayMin(),neighborInfo.getUploadSpeed(),neighborInfo.getUploadSpeedMax())); - Setlp2=paths.get(ias2); + /*Setlp2=paths.get(ias2); if(lp2==null) { paths.put(ias2, lp2=new HashSet<>()); } - lp2.add( new LinkDirection(neighborInfo.getNeighbor(),neighborInfo.getLocal(),ias2,entry.getKey() , neighborInfo.getDownloadDelay(),neighborInfo.getDownloadSpeed(),neighborInfo.getDownloadSpeedMax())); + lp2.add( new LinkDirection(neighborInfo.getNeighbor(),neighborInfo.getLocal(),ias2,entry.getKey() , neighborInfo.getDownloadDelay(),neighborInfo.getDownloadDelayMin(),neighborInfo.getDownloadSpeed(),neighborInfo.getDownloadSpeedMax())); + */ } } + + + + long[][]pointers=new long[(int) airs.size()][2]; long heappos=0; long linknumber=0; - for (Iterator>> iterator = paths.entrySet().iterator(); iterator.hasNext();) { - Entry> entry = (Entry>) iterator.next(); + for(Entry> entry:paths.entrySet()) { + /*for (Iterator>> iterator = paths.entrySet().iterator(); iterator.hasNext();) { + Entry> entry = (Entry>) iterator.next();*/ linknumber+=entry.getValue().size(); } long[][]heap=new long[(int) (linknumber)][2]; @@ -377,12 +410,16 @@ public class KLALBRoutingProtocol extends Thread{ long heapindex=0; pointers[(int) i][0]=heappos; InetAddress ia=rias.get((int) i); - Setlks=paths.get(ia); + Listlks=paths.get(ia); if(lks!=null) + for(LinkDirection linkPath:lks) { + /* for (Iterator iterator = lks.iterator(); iterator.hasNext();) { - LinkDirection linkPath=iterator.next(); + LinkDirection linkPath=iterator.next();*/ heap[(int)(heappos+ heapindex)][0]=airs.get(linkPath.getToLocator()); heap[(int) (heappos+heapindex)][1]=linkPath.getWeight(); + //heap[(int) (heappos+heapindex)][2]=linkPath.get + // heap[(int) (heappos+heapindex)][3]=0; heapindex++; } @@ -391,6 +428,8 @@ public class KLALBRoutingProtocol extends Thread{ pointers[(int) i][1]=heapindex; } + + algorithm.setGraph(pointers,heap,airs.get(router.getLocator().getAddress())); algorithm.run(); directions=new NetmapDirections(algorithm.getDirection(), rias, airs); @@ -407,12 +446,12 @@ public class KLALBRoutingProtocol extends Thread{ private Inet6Address fromLocator; private Inet6Address toLocator; private long delay; + private long delayMin; private long speed; public long getSpeed() { return speed; } private long bandwidth; - private long usedBandwidth=0; public Inet6AddressGroup getFromAddress() { return fromAddress; } @@ -425,22 +464,28 @@ public class KLALBRoutingProtocol extends Thread{ public long getBandwidth() { return bandwidth; } + + public long getDelayMin() { + return delayMin; + } + public LinkDirection(Inet6AddressGroup fromAddress, Inet6AddressGroup toAddress, Inet6Address fromLocator, - Inet6Address toLocator,long delay,long speed, long bandwidth) { + Inet6Address toLocator, long delay, long delayMin, long speed, long bandwidth) { super(); this.fromAddress = fromAddress; this.toAddress = toAddress; this.fromLocator = fromLocator; this.toLocator = toLocator; this.delay = delay; - this.speed=speed; + this.delayMin = delayMin; + this.speed = speed; this.bandwidth = bandwidth; } @Override public String toString() { return "LinkDirection [fromAddress=" + fromAddress + ", toAddress=" + toAddress + ", fromLocator=" - + fromLocator + ", toLocator=" + toLocator + ", delay=" + delay + ", speed=" + speed - + ", bandwidth=" + bandwidth + ", usedBandwidth=" + usedBandwidth + "]"; + + fromLocator + ", toLocator=" + toLocator + ", delay=" + delay + ", delayMin=" + delayMin + + ", speed=" + speed + ", bandwidth=" + bandwidth + "]"; } public Inet6Address getFromLocator() { return fromLocator; @@ -470,8 +515,7 @@ public class KLALBRoutingProtocol extends Thread{ private RouterInfo getSelfRouterInfo() { Listlinks=router.getLinkTabel(); Object[] nls=links.toArray(); - RouterInfo ri=new RouterInfo(System.currentTimeMillis()); - ri.setLocator(router.getLocator()); + RouterInfo ri=new RouterInfo(System.currentTimeMillis(),router.getLocator(),router.getASN()); for(int i=0;i getAddresses() { return addresses; } - public Map> getPaths() { + public Map> getPaths() { return paths; } public List createSegmentList(Inet6Address dest) { @@ -564,12 +617,41 @@ public class KLALBRoutingProtocol extends Thread{ private Map hotspots=new ConcurrentHashMap<>(); public void putHotspotAddress(Inet6Address sourceAddress) { + if(true) { HotspotAddressTimer hat=hotspots.get(sourceAddress); if(hat==null) { hotspots.put(sourceAddress, new HotspotAddressTimer()); }else { hat.refreshTimeout(); } + } + } + private Map toIpBandwidth=new ConcurrentHashMap(); + + public void updateTotalRequestBandwidth(Inet6Address targetaAddress, Long treq) { + Objects.requireNonNull(targetaAddress); + //System.out.println("到"+targetaAddress.getHostAddress()+"请求带宽更新:"+treq); + if(treq<=0) { + if(toIpBandwidth.remove(targetaAddress)!=null) { + noticeUpdate(); + } + }else { + Long old=toIpBandwidth.put(targetaAddress, treq); + if(old==null||old.longValue()!=treq.longValue()) { + noticeUpdate(); + } + } + } + public Inet6Address getDijkstraPrevNode(Inet6Address text) { + NetmapDirections directionsx=directions; + if(directionsx==null) + return null; + long number= directionsx.getDirection_airs().get(text); + long prev= directionsx.getDirection()[(int)number]; + if(prev==-1) { + return null; + } + return directionsx.getDirection_rias().get((int) prev); } } diff --git a/src/org/kne/cloud/network/srv6/KLALBRoutingProtocolPacket.java b/src/org/kne/cloud/network/srv6/KLALBRoutingProtocolPacket.java index 505f4af..6b24daa 100644 --- a/src/org/kne/cloud/network/srv6/KLALBRoutingProtocolPacket.java +++ b/src/org/kne/cloud/network/srv6/KLALBRoutingProtocolPacket.java @@ -34,7 +34,7 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket { public KLALBRoutingProtocolPacket(int type) { super(); - header=NetworkPacket.databufferpool_40.borrow(); + header=NetworkPacket.bufferAllocator.allocate(40); header.put((byte) type); } @Override @@ -49,7 +49,7 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket { - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { sndtime=System.nanoTime(); dto.write(header.slice(0, (int) getHeaderSize())); } @@ -59,7 +59,7 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket { return false; } - protected void readFromChannel(ReadableByteChannel din,long length) throws IOException { + public void readFromChannel(ReadableByteChannel din,long length) throws IOException { rcvtime=System.nanoTime(); //System.out.println(this+" "+getHeaderSize()); header.limit((int) getHeaderSize()); @@ -89,12 +89,6 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket { return header; } - public void dispose() { - super.dispose(); - /* ByteBuffer headerx=header; - header=null; - KLALBRoutingProtocolPacket.databufferpool_40.back(headerx);*/ - } public static KLALBRoutingProtocolPacket readKLALBPacketFromStream(DataInputStream in) throws IOException { return readKLALBPacketFromChannel(Channels.newChannel(in)); @@ -102,7 +96,7 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket { public static KLALBRoutingProtocolPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException { while(true) { - ByteBuffer bb=databufferpool_40.borrow(); + ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40); bb.limit(1); while(bb.hasRemaining()){ if(in.read(bb)==-1) { diff --git a/src/org/kne/cloud/network/srv6/NeighborInfo.java b/src/org/kne/cloud/network/srv6/NeighborInfo.java index 54a0563..0eb8dd8 100644 --- a/src/org/kne/cloud/network/srv6/NeighborInfo.java +++ b/src/org/kne/cloud/network/srv6/NeighborInfo.java @@ -11,6 +11,7 @@ import java.net.Inet6Address; import java.util.Objects; import org.kne.cloud.network.ipv6.Inet6AddressGroup; +import org.kne.cloud.network.ipv6.Neighbor; public class NeighborInfo implements Serializable { @Override @@ -26,13 +27,16 @@ public class NeighborInfo implements Serializable { private Inet6AddressGroup local; private Inet6AddressGroup neighbor; private Inet6AddressGroup locator; - public NeighborInfo(Inet6AddressGroup local,Inet6AddressGroup neighbor,Inet6AddressGroup locator, long uploadDelay, long downloadDelay, long uploadSpeed, long downloadSpeed, long uploadspeedmax, long downloadspeedmax) { + private transient Neighbor context; + public NeighborInfo(Inet6AddressGroup local,Inet6AddressGroup neighbor,Inet6AddressGroup locator, long uploadDelay, long downloadDelay,long uploadDelayMin, long downloadDelayMin, long uploadSpeed, long downloadSpeed, long uploadspeedmax, long downloadspeedmax) { super(); this.local=local; this.neighbor = neighbor; this.locator=locator; this.uploadDelay = uploadDelay; this.downloadDelay = downloadDelay; + this.uploadDelayMin = uploadDelayMin; + this.downloadDelayMin= downloadDelayMin; this.uploadSpeed = uploadSpeed; this.downloadSpeed = downloadSpeed; this.uploadSpeedMax=uploadspeedmax; @@ -40,12 +44,24 @@ public class NeighborInfo implements Serializable { } public NeighborInfo() { } + private long uploadDelay; private long downloadDelay; + private long uploadDelayMin; + private long downloadDelayMin; private long uploadSpeed; private long downloadSpeed; private long uploadSpeedMax; private long downloadSpeedMax; + + + + public void setContext(Neighbor context) { + this.context = context; + } + public Neighbor getContext() { + return context; + } public Inet6AddressGroup getNeighbor() { return neighbor; } @@ -100,6 +116,7 @@ public class NeighborInfo implements Serializable { public void setLocator(Inet6AddressGroup locator) { this.locator = locator; } + @Override public int hashCode() { return Objects.hash(local, locator, neighbor); @@ -122,6 +139,8 @@ public class NeighborInfo implements Serializable { locator.writeToStream(out); out.writeLong(uploadDelay); out.writeLong(downloadDelay); + out.writeLong(uploadDelayMin); + out.writeLong(downloadDelayMin); out.writeLong(uploadSpeed); out.writeLong(downloadSpeed); out.writeLong(uploadSpeedMax); @@ -134,9 +153,17 @@ public class NeighborInfo implements Serializable { locator=new Inet6AddressGroup(in); uploadDelay=in.readLong(); downloadDelay=in.readLong(); + uploadDelayMin=in.readLong(); + downloadDelayMin=in.readLong(); uploadSpeed=in.readLong(); downloadSpeed=in.readLong(); uploadSpeedMax=in.readLong(); downloadSpeedMax=in.readLong(); } + public long getUploadDelayMin() { + return uploadDelayMin; + } + public long getDownloadDelayMin() { + return downloadDelayMin; + } } diff --git a/src/org/kne/cloud/network/srv6/PAD1SegmentRoutingTLV.java b/src/org/kne/cloud/network/srv6/PAD1SegmentRoutingTLV.java index bd968cb..57cb530 100644 --- a/src/org/kne/cloud/network/srv6/PAD1SegmentRoutingTLV.java +++ b/src/org/kne/cloud/network/srv6/PAD1SegmentRoutingTLV.java @@ -4,8 +4,8 @@ import java.nio.ByteBuffer; public class PAD1SegmentRoutingTLV extends IPv6SegmentRoutingTLV { - public PAD1SegmentRoutingTLV(int type) { - super(type); + public PAD1SegmentRoutingTLV() { + super(IPv6SegmentRoutingTLV.PAD1); } public PAD1SegmentRoutingTLV(ByteBuffer klalbHeader) { diff --git a/src/org/kne/cloud/network/srv6/PADNSegmentRoutingTLV.java b/src/org/kne/cloud/network/srv6/PADNSegmentRoutingTLV.java index 792d51f..22fcd83 100644 --- a/src/org/kne/cloud/network/srv6/PADNSegmentRoutingTLV.java +++ b/src/org/kne/cloud/network/srv6/PADNSegmentRoutingTLV.java @@ -11,19 +11,20 @@ public class PADNSegmentRoutingTLV extends IPv6SegmentRoutingTLV { super(klalbHeader); } - public PADNSegmentRoutingTLV(int type) { - super(type); + public PADNSegmentRoutingTLV(int dataLength) { + super(IPv6SegmentRoutingTLV.PADN); + getData().limit(dataLength); } - + @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { super.writeToChannel(dto); } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { super.readFromChannel(din, length); } diff --git a/src/org/kne/cloud/network/srv6/RouterInfo.java b/src/org/kne/cloud/network/srv6/RouterInfo.java index e921327..fc1a9a7 100644 --- a/src/org/kne/cloud/network/srv6/RouterInfo.java +++ b/src/org/kne/cloud/network/srv6/RouterInfo.java @@ -30,12 +30,20 @@ public class RouterInfo implements Serializable{ */ private static final long serialVersionUID = 1L; private Inet6AddressGroup locator; + private long asn; public Inet6AddressGroup getLocator() { return locator; } public void setLocator(Inet6AddressGroup locator) { this.locator = locator; } + + public long getAsn() { + return asn; + } + public void setAsn(long asn) { + this.asn = asn; + } @Override public int hashCode() { return Objects.hash(locator, neighborAddresses); @@ -51,7 +59,7 @@ public class RouterInfo implements Serializable{ RouterInfo other = (RouterInfo) obj; return Objects.equals(locator, other.locator) && Objects.equals(neighborAddresses, other.neighborAddresses); } - private Set neighborAddresses=new HashSet<>(); + private List neighborAddresses=new ArrayList<>(); private long createTime; @@ -59,7 +67,7 @@ public class RouterInfo implements Serializable{ return createTime; } private static final long INFO_UPDATETIME=10000000000L; - private static final long INFO_TIMEOUT=20000000000L; + private static final long INFO_TIMEOUT=120000000000L; private long putTime=System.nanoTime(); public boolean checkUpdateTime() { return System.nanoTime()-putTime>INFO_UPDATETIME; @@ -74,21 +82,24 @@ public class RouterInfo implements Serializable{ return "RINFO [locator=" + locator + ", neighborAddresses=" + neighborAddresses + ", putTime=" + putTime + "]"; } - public Set getNeighborAddresses() { + public List getNeighborAddresses() { return neighborAddresses; } - public RouterInfo( long createTime) { + public RouterInfo( long createTime,Inet6AddressGroup locator,long asn) { this.createTime = createTime; + this.locator=locator; + this.asn=asn; } + public RouterInfo() { } public void writeToStream(DataOutputStream out) throws IOException { locator.writeToStream(out); + out.writeLong(asn); out.writeLong(createTime); out.writeInt(neighborAddresses.size()); - for (Iterator iterator = neighborAddresses.iterator(); iterator.hasNext();) { - NeighborInfo neighborInfo = (NeighborInfo) iterator.next(); + for( NeighborInfo neighborInfo :neighborAddresses) { neighborInfo.writeToStream(out); } } @@ -101,9 +112,10 @@ public class RouterInfo implements Serializable{ } public void readFromStream(DataInputStream in) throws IOException { locator=new Inet6AddressGroup(in); + asn=in.readLong(); createTime=in.readLong(); int size=in.readInt(); - neighborAddresses=new HashSet<>(size); + neighborAddresses=new ArrayList<>(size); for (int i = 0; i < size; i++) { NeighborInfo nif=new NeighborInfo(); nif.readFromStream(in); diff --git a/src/org/kne/cloud/network/srv6/RouterInfoPacket.java b/src/org/kne/cloud/network/srv6/RouterInfoPacket.java index 928e70c..719df6a 100644 --- a/src/org/kne/cloud/network/srv6/RouterInfoPacket.java +++ b/src/org/kne/cloud/network/srv6/RouterInfoPacket.java @@ -24,9 +24,10 @@ import org.kne.cloud.network.ipv6.Inet6AddressGroup; public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Serializable{ - public RouterInfoPacket(RouterInfo routerInfo, boolean flood) { + public RouterInfoPacket(RouterInfo routerInfo, boolean flood,long asn) { super(RINFO); getHeader().put(1,(byte) (flood?1:0)); + getHeader().putLong(2,asn); this.rinfo=routerInfo; } protected RouterInfoPacket(ByteBuffer bb) { @@ -39,12 +40,16 @@ public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Seri return (getHeader().get(1)&1)==1; } + public long getASN() { + return getHeader().getLong(2); + } + public RouterInfo getRinfo() { return rinfo; } @Override protected long getHeaderSize() { - return super.getHeaderSize()+1; + return super.getHeaderSize()+9; } @Override public long getLength() { @@ -60,12 +65,12 @@ public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Seri @Override - protected void writeToChannel(WritableByteChannel dto) throws IOException { + public void writeToChannel(WritableByteChannel dto) throws IOException { super.writeToChannel(dto); rinfo.writeToChannel(dto); } @Override - protected void readFromChannel(ReadableByteChannel din, long length) throws IOException { + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { super.readFromChannel(din, length); rinfo=new RouterInfo(); rinfo.readFromChannel(din, length); diff --git a/src/org/kne/cloud/network/srv6/SEQSSegmentRoutingTLV.java b/src/org/kne/cloud/network/srv6/SEQSSegmentRoutingTLV.java new file mode 100644 index 0000000..eb3c89f --- /dev/null +++ b/src/org/kne/cloud/network/srv6/SEQSSegmentRoutingTLV.java @@ -0,0 +1,98 @@ +package org.kne.cloud.network.srv6; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.util.UUID; + +public class SEQSSegmentRoutingTLV extends IPv6SegmentRoutingTLV { + public SEQSSegmentRoutingTLV(ByteBuffer klalbHeader) { + super(klalbHeader); + } + + @Override + public String toString() { + return "SEQSSegmentRoutingTLV [getSequence()=" + getSequence() + "]"; + } + + public SEQSSegmentRoutingTLV(long sequence,UUID uuid, boolean promise,boolean keeporder/*,int flownumber,long flowsequence*/) { + super(IPv6SegmentRoutingTLV.SEQS); + setSequence(sequence); + setUUID(uuid); + setPromise(promise); + setKeepOrder(keeporder); + //setFlowNumber(flownumber); + //setFlowSequence(flowsequence); + //getData().limit(14); + //getData().limit(22); + getData().limit(30); + } + + public void setUUID(UUID uuid) { + getData().putLong(14,uuid.getMostSignificantBits()); + getData().putLong(22,uuid.getLeastSignificantBits()); + } + + public UUID getUUID() { + return new UUID(getData().getLong(14),getData().getLong(22)); + } + + @Override + public void writeToChannel(WritableByteChannel dto) throws IOException { + + super.writeToChannel(dto); + + } + + @Override + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { + super.readFromChannel(din, length); + + } + + public long getSequence() { + return getData().getLong(6); + } + public void setSequence(long sequence) { + getData().putLong(6,sequence); + } + + public int getFlowNumber() { + return getData().getInt(2); + } + public void setFlowNumber(int flowsequence) { + getData().putInt(2,flowsequence); + } + + /*public long getFlowSequence() { + return getData().getLong(14); + } + public void setFlowSequence(long flowsequence) { + getData().putLong(14,flowsequence); + }*/ + + public boolean isPromise() { + return getData().get(0)!=0?true:false; + } + + public void setPromise(boolean promise) { + if(promise) { + getData().put(0, (byte) 1); + }else { + getData().put(0, (byte) 0); + } + } + public boolean isKeepOrder() { + return getData().get(1)!=0?true:false; + } + + public void setKeepOrder(boolean keeporder) { + if(keeporder) { + getData().put(1, (byte) 1); + }else { + getData().put(1, (byte) 0); + } + } +} diff --git a/src/org/kne/cloud/network/srv6/SRv6PacketReorder.java b/src/org/kne/cloud/network/srv6/SRv6PacketReorder.java new file mode 100644 index 0000000..b40d9e4 --- /dev/null +++ b/src/org/kne/cloud/network/srv6/SRv6PacketReorder.java @@ -0,0 +1,74 @@ +package org.kne.cloud.network.srv6; + +import java.io.IOException; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; + +import org.kne.cloud.network.ipv6.IPv6Packet; + +public class SRv6PacketReorder { + + private PacketConsumer packetConsumer; + + public SRv6PacketReorder(PacketConsumer packetConsumer) { + this.packetConsumer=packetConsumer; + } + + private long jumpTime=500000000L; + + private Mapmap=new ConcurrentHashMap<>(); + + + private long orderTime=System.nanoTime(); + private AtomicLong seqptr=new AtomicLong(); + + public void put(IPv6Packet pack, long sequence) throws IOException { + //System.out.println(pack.getFlowLabel()+" "+sequence); + map.put(sequence,pack); + runOrdering(); + } + private ReentrantLock orderLock=new ReentrantLock(); + public void runOrdering() throws IOException { + orderLock.lock(); + try { + boolean whi=false; + do { + whi=false; + + while(true) { + IPv6Packet i6p=map.remove(seqptr.get()); + if(i6p!=null) { + //System.out.println("Ord:"+i6p.getFlowLabel()+" "+seqptr.get()); + seqptr.getAndIncrement(); + orderTime=System.nanoTime(); + if(packetConsumer!=null) { + packetConsumer.accept(i6p); + } + }else { + break; + } + } + long ct=System.nanoTime(); + if(ct-orderTime>jumpTime) { + orderTime=ct; + long l=Long.MAX_VALUE; + for(Long ent:map.keySet()) { + if(ent flowseqMap=new ConcurrentHashMap(); + public void mark(IPv6Packet ipp) { + AtomicLong nal=new AtomicLong(); + AtomicLong rez=flowseqMap.putIfAbsent(ipp.getFlowSession(), nal); + if(rez==null) { + rez=nal; + } + ipp.setFlowSeqMark(rez.getAndIncrement()); + } +} diff --git a/src/org/kne/cloud/network/srv6/SRv6Router.java b/src/org/kne/cloud/network/srv6/SRv6Router.java index 514d45b..a85f083 100644 --- a/src/org/kne/cloud/network/srv6/SRv6Router.java +++ b/src/org/kne/cloud/network/srv6/SRv6Router.java @@ -6,6 +6,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.nio.ByteBuffer; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -15,18 +16,19 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Consumer; -import org.kne.acclerate.FastLib; import org.kne.cloud.network.NetworkPacket; import org.kne.cloud.network.ipv6.FlowSession; import org.kne.cloud.network.ipv6.IPv6NetworkLink; @@ -74,8 +76,10 @@ import com.google.gson.internal.Pair; public class SRv6Router { private static final boolean debug = false; - public static final int MTU = 9000; + public static final int MTU = 8192; + public static final int MAX_REROUTE_COUNT=2;//1 + public static final IpV6RoutingType SRH_HEADER = new IpV6RoutingType((byte) 4, "SRH Header"); // private Listlinks=new ArrayList<>(); @@ -140,7 +144,7 @@ public class SRv6Router { } @Override - public boolean isCongress(IPv6Packet iPv6Packet) { + public boolean isCongress(IPv6Packet iPv6Packet,double scale) { return false; } @@ -170,6 +174,40 @@ public class SRv6Router { return loopbackAddress; } + @Override + public void setRerouteConsumer(Consumer rerouteConsumer) { + // TODO 自动生成的方法存根 + + } + + @Override + public List getRouteItems() { + List rlist=new ArrayList<>(); + + rlist.add(new RouteItem(new Inet6AddressGroup(this.getAddressGroup().getAddress(), 128), + this.getAddressGroup().getAddress(), this, "Direct", 0, 0, null, "D",true)); + + for (Iterator iteratorx = getNeighborsInfo() + .iterator(); iteratorx.hasNext();) { + Neighbor addresses = (Neighbor) iteratorx.next(); + RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(), + this, "Direct", 0, 128, addresses.getMonitor(), "D",false); + rlist.add(ri); + + RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(), + this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false); + rlist.add(ris); + + } + return rlist; + } + + @Override + public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) { + return false; + } + + }; public List getRouteTabel() { @@ -180,32 +218,44 @@ public class SRv6Router { return routeTabel0; } + + private Consumer defaultReroute = new Consumer() { + + @Override + public void accept(IPv6Packet t) { + //HighPerformanceExecutor.defaultExecutor.execute(() -> { + routePacket(t,true); + t.putTimePassport("rerouted"); + //}); + } + }; private Consumer defaultReceive = new Consumer() { @Override public void accept(IPv6Packet t) { - HighPerformanceExecutor.defaultExecutor.execute(() -> { + //HighPerformanceExecutor.defaultExecutor.execute(() -> { routePacket(t); t.putTimePassport("routed"); - }); + //}); } }; private Consumer srhReceive = new Consumer() { @Override public void accept(IPv6Packet t) { - HighPerformanceExecutor.defaultExecutor.execute(() -> { + //HighPerformanceExecutor.defaultExecutor.execute(() -> { insertSRHandRoutePacket(t); - }); + //}); } }; - + + private volatile UUID suid=UUID.randomUUID(); public void updateRouteTabel() { List routeTabel0x = new ArrayList<>(); for (Iterator iterator = linkTabel.iterator(); iterator.hasNext();) { IPv6NetworkLink nlink = (IPv6NetworkLink) iterator.next(); - if (nlink.isLoopBack()) { + /*if (nlink.isLoopBack()) { if (nlink instanceof IPv6TUNLoopbackNetworkLink) { routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128), nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 1, null, "D")); @@ -215,10 +265,7 @@ public class SRv6Router { nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 0, null, "D")); } - }/*else { - routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128), - nlink.getAddressGroup().getAddress(), inLoopBack, "Direct", 0, 0, null, "D")); - }*/ + } for (Iterator iteratorx = nlink.getNeighborsInfo() .iterator(); iteratorx.hasNext();) { Neighbor addresses = (Neighbor) iteratorx.next(); @@ -230,9 +277,11 @@ public class SRv6Router { nlink, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D"); routeTabel0x.add(ris); - } - + }*/ + Listroutes=nlink.getRouteItems(); + + routeTabel0x.addAll(routes); if (nlink instanceof IPv6TUNLoopbackNetworkLink) { @@ -240,14 +289,28 @@ public class SRv6Router { } else { nlink.setReceiveConsumer(defaultReceive); } + nlink.setRerouteConsumer(defaultReroute); } + /*List routeTabel1x=new ArrayList<>(routeTabel0x.size()); + routeTabel0x.addAll(routeTabel); + for (Iterator iterator = routeTabel0x.iterator(); iterator.hasNext();) { + RouteItem routeItem = (RouteItem) iterator.next(); + routeTabel1x.add((RouteItem) routeItem.clone()); + }*/ + for (Iterator iterator = routeTabel0x.iterator(); iterator.hasNext();) { + RouteItem routeItem = (RouteItem) iterator.next(); + routeItem.preSort(); + + } Collections.sort(routeTabel0x); routeTabel0 = routeTabel0x; + suid=UUID.randomUUID(); } private Inet6AddressGroup locator; + private long asn=new SecureRandom().nextLong(1,Long.MAX_VALUE); /* * public List getLinks() { return links; } */ @@ -259,42 +322,50 @@ public class SRv6Router { return locator; } + public long getASN() { + return asn; + } + + public void setASN(long asn) { + this.asn = asn; + } + public void setLocator(Inet6AddressGroup locator) { this.locator = locator; updateRouteTabel(); } - private ConcurrentHashMap swist = new ConcurrentHashMap<>(); + //private ConcurrentHashMap swist = new ConcurrentHashMap<>(); - // private AtomicLong qsn=new AtomicLong(); public void insertSRHandRoutePacket(IPv6Packet ipp) { insertSRH(ipp); ipp.putTimePassport("SRH inserted"); routePacket(ipp); ipp.putTimePassport("routed"); } - + + public void insertSRH(IPv6Packet ipp) { + if(ipp.getSRHHeader()!=null) { + throw new IllegalStateException("packet already has SRH!"); + } if (klalbRouteProtol != null) { List segs = klalbRouteProtol.createSegmentList(ipp.getDestinationAddress()); // System.out.println(segs); if (segs != null && (!segs.isEmpty())) { - /* - * Listtlvs=new ArrayList<>(1); if(ipp.getPayload().getType()==6) { - * SRv6StreamSequenceTLV sers= new SRv6StreamSequenceTLV(); - * sers.setSequence(qsn.getAndIncrement()); tlvs.add(sers); } - */ - - //IpV6RoutingSRHData srh = new IpV6RoutingSRHData(segs); - + IPv6SegmentRoutingHeader irh = new IPv6SegmentRoutingHeader(segs); + + //System.out.println(ipp.getFlowLabel()); + ThreadLocalRandom tlr=ThreadLocalRandom.current(); + //System.out.println(ipp.getFlowSeqMark()); + irh.getTlvs().add(new SEQSSegmentRoutingTLV(ipp.getFlowSeqMark(),new UUID(suid.getMostSignificantBits()^tlr.nextLong(),suid.getMostSignificantBits()^tlr.nextLong()),ipp.isPromise(),ipp.getFlowSeqMark()!=-1)); + ipp.getHeaders().add(irh); - + ipp.setDestinationAddress(segs.get(segs.size() - 1)); - /* - * if(ipp.getPayload().getType()==6) System.out.println(ipp); - */ + } } } @@ -303,7 +374,14 @@ public class SRv6Router { private volatile List routeTabel0 = new ArrayList<>(); // private ReentrantReadWriteLock routelock=new ReentrantReadWriteLock(); + + + //路由数据包 public void routePacket(IPv6Packet iPv6Packet) { + routePacket(iPv6Packet ,false); + } + //路由数据包 + public void routePacket(IPv6Packet iPv6Packet, boolean reroute) { // routelock.readLock().lock(); // try { // System.out.println("路由表:"+routeTabel0); @@ -311,96 +389,55 @@ public class SRv6Router { if (debug) { dbg=new StringBuilder(); } - iPv6Packet.lockAll(); try { - if(iPv6Packet.isSomeDisposed()) - return; - int hop = iPv6Packet.getHopLimit(); + int hop = iPv6Packet.getHopLimit();//检查TTL值,只有大于0才会被转发,否则丢弃 if (hop > 0) { // List mached=new ArrayList<>(); // RouteItem pri=null; - Inet6Address ia = iPv6Packet.getDestinationAddress(); - if (debug) { - dbg.append("----------------------------------------\n"); - dbg.append("packet:" + iPv6Packet.getSourceAddress().getHostAddress() + "->" - + iPv6Packet.getDestinationAddress().getHostAddress()+"\n"); - } - for (int i = 0; i < routeTabel0.size(); i++) { - RouteItem tri = routeTabel0.get(i); - if (!tri.checkMatch(ia)) { - if (debug) { - dbg.append(tri+"\n"); - dbg.append("unmatched.\n"); - } - continue; - } - if (!tri.getDestlink().isUp()) { - if (debug) { - dbg.append(tri+"\n"); - dbg.append("linkdown.\n"); - } - continue; - } - if (tri.getDestlink().isCongress(iPv6Packet)) { - if (debug) { - dbg.append(tri+"\n"); - dbg.append("congress.\n"); - } - continue; - } - if (!tri.getDestlink().canSend(iPv6Packet)) { - if (debug) { - dbg.append(tri+"\n"); - dbg.append("linkrefused.\n"); - } - continue; - } - if (debug) { - dbg.append(tri+"\n"); - dbg.append("matched.\n"); - } - processPacket(iPv6Packet, tri); - return; - /* - * if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; } - */ - } - if (debug) { - dbg.append("miss.\n"); - } - if (iPv6Packet.isEnableECN()) { - iPv6Packet.markCE(); - for (int i = 0; i < routeTabel0.size(); i++) { - RouteItem tri = routeTabel0.get(i); - if (tri.checkMatch(ia)) { - if (!tri.getDestlink().isUp()) { - continue; - } - processPacket(iPv6Packet, tri); - return; - /* - * if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; } - */ - } - } + + //按延迟顺序从小到大匹配路由表 + if(searchTableAndFoward(iPv6Packet, reroute, dbg)) { + //匹配到路由表,返回 + return ; } + + if (debug) - dbg.append("congress\n"); - // System.out.println(ia.getAddress()+" match "+ri); - /* - * for (Iterator iterator = mached.iterator(); iterator.hasNext();) { RouteItem - * routeItem = (RouteItem) iterator.next(); - * if(routeItem.getDestlink().isCongress()) { - * - * }else { processPacket(iPv6Packet,pri); break; } } - */ - // else - // System.out.println("路由失败:"+iPv6Packet); - + dbg.append("noroute\n"); + //System.out.println("找不到路由表:"+iPv6Packet.getSourceAddress().getHostAddress()+" -> "+iPv6Packet.getDestinationAddress().getHostAddress()); + + //未找到合适的路由表或路由表对应的链路down,使用FRR保护创建备用路由表 + IPv6SegmentRoutingHeader srh=iPv6Packet.getSRHHeader(); + if(srh!=null) { + System.out.println("原SRH:"+srh); + int segmentsLeft=srh.getSegmentsLeft(); + if(segmentsLeft>0) { + srh.getAddresses().remove(segmentsLeft); + segmentsLeft--; + } + List repairSegments= klalbRouteProtol.createSegmentList(srh.getAddresses().get(segmentsLeft)); + if(repairSegments ==null) { + System.out.println("FRR保护失败"); + return; + } + repairSegments.remove(0); + srh.getAddresses().addAll(segmentsLeft+1, repairSegments); + segmentsLeft+=repairSegments.size(); + srh.setSegmentsLeft(segmentsLeft); + iPv6Packet.setDestinationAddress(srh.getAddresses().get(segmentsLeft)); + }else { + return; + } + System.out.println("FRR修复SRH:"+srh); + if(searchTableAndFoward(iPv6Packet, reroute, dbg)) { + return ; + } + + } else { IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder(); - ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow(); + ByteBuffer IPv6data = NetworkPacket.bufferAllocator.allocate(65535); iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data)); byte[] raw = new byte[IPv6data.remaining()]; IPv6data.get(0, raw); @@ -433,34 +470,206 @@ public class SRv6Router { if(debug) { System.out.println(dbg.toString()); } - iPv6Packet.unlockAll(); } // }finally { // routelock.readLock().unlock(); // } } - private void processPacket(IPv6Packet iPv6Packet, RouteItem ri) throws IllegalRawDataException, IOException { - int hop = iPv6Packet.getHopLimit(); + private boolean searchTableAndFoward(IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg) + throws IllegalRawDataException, IOException { + byte[] ia = new byte[16]; + iPv6Packet.getRawDestinationAddress(ia); + if (debug) { + dbg.append("----------------------------------------\n"); + dbg.append("packet:" + iPv6Packet.getSourceAddress().getHostAddress() + " -> " + + iPv6Packet.getDestinationAddress().getHostAddress()+"\n"); + } + + boolean routeFound=false; + + RouteItem prevr=null; + List routes=new ArrayList<>(); + //遍历路由表 + for (RouteItem tri: routeTabel0) { + if(!tri.checkMatch(ia)) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("unmatched.\n"); + } + //跳过前缀与掩码不符合要求的路由表条目 + continue; + } + if (!tri.getDestlink().canSend(iPv6Packet)) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("linkrefused.\n"); + } + //跳过不能转发这种数据包的链路 + continue; + } + if (!tri.getDestlink().isUp()) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("linkdown.\n"); + } + //跳过断开连接的链路 + continue; + } + routeFound=true; + if(prevr!=null) { + if(!tri.ECMPequals(prevr)) { + //执行流量整形负载均衡调度算法 + if(routingLoadBalance(iPv6Packet, reroute, dbg, routes)) { + return routeFound; + } + routes.clear(); + } + } + //将等价路由加入负载均衡列表 + routes.add(tri); + + prevr=tri; + + + + } + routingLoadBalance(iPv6Packet, reroute, dbg, routes); + return routeFound; + } + private boolean routingLoadBalance(IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg, List routes) + throws IllegalRawDataException, IOException { + + double cscale=1.0; + if(iPv6Packet.getPayload().getProtocolNumber()==6) { + cscale=15.0; + } + + boolean retry=false; + long start=System.nanoTime(); + do { + retry=false; + //遍历可用于负载均衡调度的路由表 + for (RouteItem tri: routes) { + if (!tri.getDestlink().isUp()) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("linkdown.\n"); + } + //跳过断开的链路 + continue; + } + if (tri.getDestlink().isCongress(iPv6Packet,cscale)) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("congress.\n"); + } + //跳过缓冲区拥塞的链路 + continue; + } + + if (tri.getDestlink().isReachSpeedLimit(iPv6Packet)) { + retry=true; + if (debug) { + dbg.append(tri+"\n"); + dbg.append("reachspeedlimit.\n"); + } + //跳过达到流量整形速度限制的链路(若仅超过流量整形速度限制,可多次重试) + continue; + } + + if (debug) { + dbg.append(tri+"\n"); + dbg.append("matched.\n"); + } + //链路可用,处理并转发数据包 + processPacket(iPv6Packet, tri,reroute); + return true; + + } + if(retry) { + if(System.nanoTime()-start>200000000L) { + break; + } + try { + Thread.sleep(1); + } catch (InterruptedException e) { + e.printStackTrace(); + } + //Thread.yield(); + //短暂挂起当前线程,待链路速度未超限时重试发送数据包 + } + }while((!routes.isEmpty())&&retry); + if (debug) { + dbg.append("miss.\n"); + } + //负载均衡未匹配成功,若数据包支持ECN,打上拥塞标记位 + if(iPv6Packet.isEnableECN()) { + iPv6Packet.markCE(); + if (debug) { + dbg.append("ECN enabled.\n"); + } + } + + for (RouteItem tri: routes) { + + if (!tri.getDestlink().isUp()) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("linkdown.\n"); + } + continue; + } + if (tri.getDestlink().isCongress(iPv6Packet,25.0)) { + if (debug) { + dbg.append(tri+"\n"); + dbg.append("congress.\n"); + } + //缓冲区留部分余量避免丢包 + continue; + } + processPacket(iPv6Packet, tri,reroute); + return true; + } + //仍未成功发送,丢弃数据包 + return false; + } + + private void processPacket(IPv6Packet iPv6Packet, RouteItem ri, boolean reroute) throws IllegalRawDataException, IOException { + int hop = iPv6Packet.getHopLimit(); + if (ri.getDestlink().isLoopBack()) { - IPv6SegmentRoutingHeader srhh = getSRHHeaderFromPacket(iPv6Packet); + IPv6SegmentRoutingHeader srhh =iPv6Packet. getSRHHeader(); if (srhh != null) { - processSRv6Packet(iPv6Packet, ri, srhh); + processSRv6Packet(iPv6Packet, ri, srhh,reroute); } else { ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop()); } } else { + if(iPv6Packet.getRerouteCounter().getAndIncrement()>=MAX_REROUTE_COUNT) { + + //System.out.println("reroute count >=2"); + return; + } + + if(!reroute) { + // if(!iPv6Packet.isTTLdecreased()) { hop--; + /* iPv6Packet.setTTLdecreased(true); + }else { + System.out.print("ttl err"); + }*/ + } // System.out.println(ipp.getHeader().getSrcAddr()+"->"+ipp.getHeader().getDstAddr()+" // "+(hop+1)+"->"+hop); if (hop > 0) { - + iPv6Packet.setHopLimit(hop); ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop()); } else { IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder(); - ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow(); + ByteBuffer IPv6data = NetworkPacket.bufferAllocator.allocate(65535); iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data)); byte[] raw = new byte[IPv6data.remaining()]; IPv6data.get(0, raw); @@ -491,37 +700,25 @@ public class SRv6Router { } - private void processSRv6Packet(IPv6Packet iPv6Packet, RouteItem ri, IPv6SegmentRoutingHeader srhh) + private void processSRv6Packet(IPv6Packet iPv6Packet, RouteItem ri, IPv6SegmentRoutingHeader srhh, boolean reroute) throws IllegalRawDataException, IOException { - /*byte[] srd = new byte[(int) (srhh.getLength() - 4)]; - srhh.getData().get(4, srd); - IpV6RoutingSRHData srh = IpV6RoutingSRHData.newInstance(srd, 0, srd.length);*/ + if (srhh.getSegmentsLeft() <= 0) { ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop()); } else { - + if(reroute) { + + }else { int newSL = srhh.getSegmentsLeft() - 1; srhh.setSegmentsLeft(newSL); iPv6Packet.setDestinationAddress(srhh.getAddresses().get(newSL)); + } klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress()); - routePacket(iPv6Packet); + routePacket(iPv6Packet,reroute); } } - private IPv6SegmentRoutingHeader getSRHHeaderFromPacket(IPv6Packet iPv6Packet) { - IPv6SegmentRoutingHeader srhh = null; - List exhs = iPv6Packet.getHeaders(); - for (int j = 0; j < exhs.size(); j++) { - IPv6ExtHeader exh = exhs.get(j); - if (exh instanceof IPv6SegmentRoutingHeader) { - if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == 4) { - srhh = (IPv6SegmentRoutingHeader) exh; - break; - } - } - } - return srhh; - } + public SRv6Router(Inet6AddressGroup hostAddress) { super(); @@ -551,19 +748,20 @@ public class SRv6Router { return klalbRouteProtol; } - private Map protocolNumberRegister = new ConcurrentHashMap<>(); + private Map protocolNumberRegister = new ConcurrentHashMap<>(256*2); public Map getProtocolNumberRegister() { return protocolNumberRegister; } - public void putProtocolNumberPacketAndInsertSRH(IPv6Packet pkt) { + + /*public void putProtocolNumberPacketAndInsertSRHAsync(IPv6Packet pkt) { // inLoopBack.getReceiveConsumer().accept(pkt); srhReceive.accept(pkt); } - public void putProtocolNumberPacket(IPv6Packet pkt) { + public void putProtocolNumberPacketAsync(IPv6Packet pkt) { // inLoopBack.getReceiveConsumer().accept(pkt); defaultReceive.accept(pkt); - } + }*/ } diff --git a/src/org/kne/cloud/network/srv6/SingleDijkstraAlgorithm.java b/src/org/kne/cloud/network/srv6/SingleDijkstraAlgorithm.java index f41fa58..aa9f4f3 100644 --- a/src/org/kne/cloud/network/srv6/SingleDijkstraAlgorithm.java +++ b/src/org/kne/cloud/network/srv6/SingleDijkstraAlgorithm.java @@ -13,7 +13,6 @@ public class SingleDijkstraAlgorithm implements DijkstraAlgorithm { private long startPoint; - private static final long MAX_WEIGHT=Long.MAX_VALUE/256L; @Override public void setGraph(long[][] pointers,long[][] heap,long startPoint) { this.heap=heap; diff --git a/src/org/kne/cloud/network/tcp/TCPOptionTLV.java b/src/org/kne/cloud/network/tcp/TCPOptionTLV.java new file mode 100644 index 0000000..a57e5a9 --- /dev/null +++ b/src/org/kne/cloud/network/tcp/TCPOptionTLV.java @@ -0,0 +1,167 @@ +package org.kne.cloud.network.tcp; + +import java.io.EOFException; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; + +import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.klalb.KLALBPacket; + +public class TCPOptionTLV extends NetworkPacket { + public static final int PAD1=0; + public static final int PADN=4; + public static final int HMAC=5; + public static final int SEQS=7; + public static final int ACKSEQS=8; + + private int headerLength=2; + + public int getHeaderLength() { + return headerLength; + } + + private boolean isDefault; + + protected volatile ByteBuffer header; + + private ByteBuffer data; + + public TCPOptionTLV(ByteBuffer header ) { + this(header,true); + } + + public ByteBuffer getData() { + return data; + } + + public TCPOptionTLV(ByteBuffer header ,boolean isDefault ) { + super(); + this.header = header; + this.isDefault=isDefault; + if(getType()==PAD1) + headerLength=1; + if(isDefault&&(headerLength>1)) { + data=ByteBuffer.allocate(512); + } + } + public TCPOptionTLV(int type) { + this(type,true); + } + public TCPOptionTLV(int type,boolean isDefault) { + super(); + this.header=ByteBuffer.allocate(2); + this.isDefault=isDefault; + header.put((byte) type); + if(type==PAD1) { + headerLength=1; + } + if(isDefault&&(headerLength>1)) { + data=ByteBuffer.allocate(512); + } + } + + @Override + public long getLength() { + return headerLength+(isDefault?data.limit():0); + } + + public static TCPOptionTLV readIPv6SegmentRoutingTLVFromChannel(ReadableByteChannel din) throws IOException { + ByteBuffer bbf= ByteBuffer.allocate(2); + bbf.limit(1); + while (bbf.hasRemaining()) { + if (din.read(bbf) == -1) { + return null; + } + } + int type=bbf.get(0)&0xff; + TCPOptionTLV rtlv; + switch(type) { + /*case PAD1: + rtlv=new PAD1SegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; + case PADN: + rtlv=new PADNSegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; + case SEQS: + rtlv=new SEQSSegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; + case ACKSEQS: + rtlv=new ACKSEQSSegmentRoutingTLV(bbf); + rtlv.readFromChannel(din); + return rtlv;*/ + default: + rtlv=new TCPOptionTLV(bbf); + rtlv.readFromChannel(din); + return rtlv; + } + } + public static void writeIPv6SegmentRoutingTLVToChannel(WritableByteChannel dto,TCPOptionTLV tlv) throws IOException { + tlv.writeToChannel(dto); + } + @Override + public void writeToChannel(WritableByteChannel dto) throws IOException { + if(isDefault&&(headerLength>1)) { + setDataLength(data.limit()); + } + header.limit(headerLength); + dto.write(header.slice(0,header.limit())); + if(isDefault&&(headerLength>1)) { + dto.write(data.slice(0, data.limit())); + } + } + + @Override + public void readFromChannel(ReadableByteChannel din, long length) throws IOException { + header.limit(1); + while (header.hasRemaining()) { + if (din.read(header) == -1) { + throw new EOFException(); + } + } + if(headerLength>1) { + header.limit(2); + while (header.hasRemaining()) { + if (din.read(header) == -1) { + throw new EOFException(); + } + } + } + header.flip(); + + if(isDefault&&(headerLength>1)) { + data.clear(); + data.limit(getDataLength()); + while(data.hasRemaining()){ + if(din.read(data)==-1) { + throw new EOFException(); + } + } + data.flip(); + } + } + + @Override + protected boolean needEndPosition() { + return false; + } + + public int getType() { + return header.get(0)&0xff; + } + public void setType(int type) { + header.put(0,(byte) type); + } + + public int getDataLength() { + return header.get(1)&0xff; + } + + public void setDataLength(int dataLength) { + header.put(1,(byte) dataLength); + } +} diff --git a/src/org/kne/cloud/network/tcp/TCPPacket.java b/src/org/kne/cloud/network/tcp/TCPPacket.java new file mode 100644 index 0000000..81967b4 --- /dev/null +++ b/src/org/kne/cloud/network/tcp/TCPPacket.java @@ -0,0 +1,191 @@ +package org.kne.cloud.network.tcp; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import org.kne.cloud.network.NetworkPacket; +import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload; + +public class TCPPacket extends IPv6Payload{ + private ByteBuffer header=NetworkPacket.bufferAllocator.allocate(20); + + private Listoptions=new ArrayList(); + + public TCPPacket() { + super(6,false); + } + + public int getSrcPort() { + return header.getChar(0); + } + + public void setSrcPort(int srcPort) { + header.putChar(0, (char) srcPort); + } + + public int getDstPort() { + return header.getChar(2); + } + + public void setDstPort(int dstPort) { + header.putChar(2, (char) dstPort); + } + + public long getSeqNumber() { + return header.getInt(4)&0xffffffff; + } + + public void setSeqNumber(long seqNumber) { + header.putInt(4,(int) seqNumber); + } + + public long getAckNumber() { + return header.getInt(8)&0xffffffff; + } + + public void setAckNumber(long ackNumber) { + header.putInt(8,(int) ackNumber); + } + + public int getHeaderLength() { + return (header.get(12)>>>4)&0b1111; + } + + public void setHeaderLength(int headerLength) { + header.put(12, (byte) ((header.get(12)&0b00001111)|((headerLength&0b1111)<<4))); + } + + + public boolean isNS() { + return (header.get(12)&1)!=0; + } + + public void setNS(boolean ns) { + if(ns) { + header.put(12,(byte) (header.get(12)|0b00000001)); + }else { + header.put(12,(byte) (header.get(12)&0b11111110)); + } + } + + public boolean isCWR() { + return (header.get(13)&0b10000000)!=0; + } + + public void setCWR(boolean cwr) { + if(cwr) { + header.put(13,(byte) (header.get(13)|0b10000000)); + }else { + header.put(13,(byte) (header.get(13)&0b01111111)); + } + } + + public boolean isECE() { + return (header.get(13)&0b01000000)!=0; + } + + public void setECE(boolean ece) { + if(ece) { + header.put(13,(byte) (header.get(13)|0b01000000)); + }else { + header.put(13,(byte) (header.get(13)&0b10111111)); + } + } + + public boolean isURG() { + return (header.get(13)&0b00100000)!=0; + } + + public void setURG(boolean urg) { + if(urg) { + header.put(13,(byte) (header.get(13)|0b00100000)); + }else { + header.put(13,(byte) (header.get(13)&0b11011111)); + } + } + + public boolean isACK() { + return (header.get(13)&0b00010000)!=0; + } + + public void setACK(boolean ack) { + if(ack) { + header.put(13,(byte) (header.get(13)|0b00010000)); + }else { + header.put(13,(byte) (header.get(13)&0b11101111)); + } + } + + public boolean isPSH() { + return (header.get(13)&0b00001000)!=0; + } + + public void setPSH(boolean psh) { + if(psh) { + header.put(13,(byte) (header.get(13)|0b00001000)); + }else { + header.put(13,(byte) (header.get(13)&0b11110111)); + } + } + + public boolean isRST() { + return (header.get(13)&0b00000100)!=0; + } + + public void setRST(boolean psh) { + if(psh) { + header.put(13,(byte) (header.get(13)|0b00000100)); + }else { + header.put(13,(byte) (header.get(13)&0b11111011)); + } + } + + public boolean isSYN() { + return (header.get(13)&0b00000010)!=0; + } + + public void setSYN(boolean syn) { + if(syn) { + header.put(13,(byte) (header.get(13)|0b00000010)); + }else { + header.put(13,(byte) (header.get(13)&0b11111101)); + } + } + + public boolean isFIN() { + return (header.get(13)&0b00000001)!=0; + } + + public void setFIN(boolean fin) { + if(fin) { + header.put(13,(byte) (header.get(13)|0b00000001)); + }else { + header.put(13,(byte) (header.get(13)&0b11111110)); + } + } + + public int getWindowSize() { + return header.getChar(14); + } + + public void setWindowSize(int windowSize) { + header.putChar(14,(char) windowSize); + } + + public int getCheckSum() { + return header.getChar(16); + } + + public void setCheckSum(int checkSum) { + header.putChar(16,(char) checkSum); + } + + public int getUrgentPointer() { + return header.getChar(18); + } + + public void setUrgentPointer(int urgentPointer) { + header.putChar(18,(char) urgentPointer); + } +} diff --git a/src/org/kne/cloud/network/te/BandwidthDistributer.java b/src/org/kne/cloud/network/te/BandwidthDistributer.java index 7475a02..752ced7 100644 --- a/src/org/kne/cloud/network/te/BandwidthDistributer.java +++ b/src/org/kne/cloud/network/te/BandwidthDistributer.java @@ -17,6 +17,8 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.BiConsumer; import java.util.function.Consumer; +import org.kne.cloud.network.srv6.DijkstraAlgorithm; + public class BandwidthDistributer { private long totalBandwidth; private AtomicLong totalBandwidthRequest=new AtomicLong(); @@ -105,7 +107,7 @@ public class BandwidthDistributer { try { if(totalBandwidth!=this.totalBandwidth) { this.totalBandwidth = totalBandwidth; - redistribute(); + applyNewDistribute(redistribute(reqmap)); } }finally { rlock.unlock(); @@ -139,7 +141,7 @@ public class BandwidthDistributer { totalBandwidthRequestOld=totalBandwidthRequest.get(); if(totalRequestUpdateConsumer!=null) totalRequestUpdateConsumer.accept(totalBandwidthRequest.get()); - redistribute(); + applyNewDistribute(redistribute(reqmap)); } //if(changed) }finally { @@ -147,8 +149,20 @@ public class BandwidthDistributer { } } + public long getMaxRequestableBandwidth(T addr) { + rlock.lock(); + try { + Map reqmapclo=new HashMap<>( reqmap); + reqmapclo.put(addr, DijkstraAlgorithm.MAX_WEIGHT); + Map result=redistribute(reqmapclo); + return result.get(addr); + }finally { + rlock.unlock(); + } + } - private void redistribute() { + + private Map redistribute(Map reqmap) { Listndistrlist=new ArrayList(reqmap.size()); for (Entry entry : reqmap.entrySet()) { @@ -176,7 +190,7 @@ public class BandwidthDistributer { BandwidthDistributeInfo bwi=ndistrlist.get(i); newdistrmap.put(bwi.address, bwi.distBandwidth); } - applyNewDistribute(newdistrmap); + return newdistrmap; } @@ -246,6 +260,7 @@ public class BandwidthDistributer { bwd.setTotalRequestUpdateConsumer((l)->{System.out.println(l);}); bwd.setBandwidthRequest((Inet6Address) InetAddress.getByName("::2"),1*1000000L ); bwd.setBandwidthRequest((Inet6Address) InetAddress.getByName("::4"),10*1000000L ); + System.out.println("max:"+bwd.getMaxRequestableBandwidth((Inet6Address) InetAddress.getByName("::5"))); bwd.setBandwidthRequest((Inet6Address) InetAddress.getByName("::5"),100*1000000L ); bwd.setTotalBandwidth(110*1000000L); bwd.setBandwidthRequest((Inet6Address) InetAddress.getByName("::2"),0L ); diff --git a/src/org/kne/concurrent/DisruptorExecutor.java b/src/org/kne/concurrent/DisruptorExecutor.java new file mode 100644 index 0000000..36449cd --- /dev/null +++ b/src/org/kne/concurrent/DisruptorExecutor.java @@ -0,0 +1,114 @@ +package org.kne.concurrent; + +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +import com.lmax.disruptor.BlockingWaitStrategy; +import com.lmax.disruptor.EventFactory; +import com.lmax.disruptor.EventHandler; +import com.lmax.disruptor.EventTranslator; +import com.lmax.disruptor.LiteBlockingWaitStrategy; +import com.lmax.disruptor.RingBuffer; +import com.lmax.disruptor.Sequence; +import com.lmax.disruptor.SequenceBarrier; +import com.lmax.disruptor.SleepingWaitStrategy; +import com.lmax.disruptor.YieldingWaitStrategy; +import com.lmax.disruptor.dsl.Disruptor; +import com.lmax.disruptor.dsl.ProducerType; + + +public class DisruptorExecutor implements Executor{ + + public static final DisruptorExecutor defaultExecutor=new DisruptorExecutor(); + private RunnableHandler[]rh; + + public DisruptorExecutor() { + this(Runtime.getRuntime().availableProcessors(),1024); + } + public DisruptorExecutor(int threadcount,int bufferSize) { + this(threadcount,bufferSize,Executors.defaultThreadFactory()); + //this(threadcount,bufferSize,Thread.ofVirtual().factory()); + } + public DisruptorExecutor(int threadcount,int bufferSize,ThreadFactory th) { + + + + rh=new RunnableHandler[threadcount]; + + for (int i = 0; i < rh.length; i++) { + rh[i]=new RunnableHandler(bufferSize,th); + } + + + } + + private class RunnableHandler implements EventHandler>{ + + private Disruptor>ring; + public RunnableHandler(int bufferSize,ThreadFactory tf) + {ring=new Disruptor>(new EventFactory>() { + + @Override + public AtomicReference newInstance() { + return new AtomicReference(); + } + }, bufferSize,tf,ProducerType.MULTI, new SleepingWaitStrategy()); + ring.handleEventsWith(this); + ring.start(); + } + + @Override + public void onEvent(AtomicReference arg0, long sequence, boolean onEndOfBatch) throws Exception { + //System.out.println(sequence); + Runnable r =arg0.get(); + if(r!=null) + try { + r.run(); + }catch(Throwable th) { + th.printStackTrace(); + } + + } + + } + /* + * public final class MyHandler implements EventHandler +{ + + public void onEvent(final ValueEvent entry, final long sequence, final boolean onEndOfBatch) + { + if ((sequence % numberOfConsumers) == ordinal) + { + // Process the event + } + } +} + */ + private AtomicLong al=new AtomicLong(); + @Override + public void execute(Runnable command) { + int v=(int) (al.getAndIncrement()%rh.length); + rh[v].ring.publishEvent(new EventTranslator>() { + + @Override + public void translateTo(AtomicReference arg0, long arg1) { + arg0.set(command); + //arg0.compareAndSet(null, command); + } + }); + } + public static void main(String[] args) throws InterruptedException { + DisruptorExecutor dre=new DisruptorExecutor(); + for (int i = 0; i < 20; i++) { + dre.execute(()->{ + System.out.println("run"); + }); + System.out.println("exc"); + } + Thread.sleep(1000); + } +} diff --git a/src/org/kne/io/KNEChannels.java b/src/org/kne/io/KNEChannels.java index 417ee9c..2256589 100644 --- a/src/org/kne/io/KNEChannels.java +++ b/src/org/kne/io/KNEChannels.java @@ -1,12 +1,15 @@ package org.kne.io; +import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; +import java.nio.channels.SocketChannel; import java.nio.channels.WritableByteChannel; + public class KNEChannels { - private static class ByteBufferWritableByteChannel implements WritableByteChannel{ + public static class ByteBufferWritableByteChannel implements WritableByteChannel{ private ByteBuffer bbf; public ByteBuffer getBbf() { @@ -29,6 +32,7 @@ public class KNEChannels { public int write(ByteBuffer src) throws IOException { int opos=src.position(); //System.out.println(bbf+" "+src); + //FastLib .bufferPut(bbf,src); bbf.put(src); return src.position()-opos; } @@ -36,7 +40,7 @@ public class KNEChannels { public static WritableByteChannel newWritableChannel(ByteBuffer bbf) { return new ByteBufferWritableByteChannel(bbf); } - private static class ByteBufferReadableByteChannel implements ReadableByteChannel { + public static class ByteBufferReadableByteChannel implements ReadableByteChannel { private ByteBuffer bbf; public ByteBuffer getBbf() { @@ -70,4 +74,11 @@ public class KNEChannels { public static ReadableByteChannel newReadableChannel(ByteBuffer bbf) { return new ByteBufferReadableByteChannel(bbf); } + public static void readFully(ReadableByteChannel connectSocket, ByteBuffer szeRead) throws EOFException, IOException { + while (szeRead.hasRemaining()) { + if (connectSocket.read(szeRead) == -1) { + throw new EOFException(); + } + } + } }