diff --git a/src/main/java/logicface/LinkService.java b/src/main/java/logicface/LinkService.java new file mode 100644 index 0000000..7845583 --- /dev/null +++ b/src/main/java/logicface/LinkService.java @@ -0,0 +1,160 @@ +package logicface; + +import component.LpPacketFragmentId; +import component.LpPacketFragmentNum; +import component.LpPacketFragmentSeq; +import encoding.*; +import packet.Interest; +import packet.LpPacket; +import packet.MINPacket; +import packet.PacketException; +import util.ByteHelper; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 20:31 2021/4/13 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class LinkService { + public ITransport transport; // 传输通道 + public LogicFace logicFace=new LogicFace();// LinkService关联的logicFace + public int mtu; // MTU大小 + public int lpPacketHeadSize; // lpPacket 编码成数组时的头部大小 + public long lpPacketId; // 发送的lpPacket 编码 + + /** + * 计算lpPacket头部大小 + */ + private void calculateLpPacketHeadSize() throws LogicFaceException { + try { + LpPacket lpPacket=new LpPacket(); + lpPacket.lpPacketHeader.setLpPacketFragmentId(new LpPacketFragmentId(Long.MAX_VALUE)); + lpPacket.lpPacketHeader.setLpPacketFragmentSeq(new LpPacketFragmentSeq(Long.MAX_VALUE)); + lpPacket.lpPacketHeader.setLpPacketFragmentNum(new LpPacketFragmentNum(Long.MAX_VALUE)); + + byte[] buf=new byte[Encoder.MaxPacketSize]; + Encoder encoder=new Encoder(); + if(!encoder.encoderReset(new SizeT(Encoder.MaxPacketSize+1000),new SizeT(0))){ + throw new LogicFaceException("LinkService.calculateLpPacketHeadSize: encoderReset error"); + } + this.lpPacketHeadSize = lpPacket.wireEncode(encoder); + this.lpPacketHeadSize -= Encoder.MaxPacketSize; + } catch (EncoderException | PacketException e) { + throw new LogicFaceException("LinkService.calculateLpPacketHeadSize: "+e.getMessage()); + } + } + + /** + * 初始化linkService + * @param mtu + * @throws LogicFaceException + */ + public void init(int mtu) throws LogicFaceException { + this.mtu=mtu; + this.calculateLpPacketHeadSize(); + this.lpPacketId=0; + } + + /** + * 从lpPacket中提取出MINPacket对象 + * @param lpPacket + * @return + */ + private MINPacket getMINPacketFromLpPacket(LpPacket lpPacket) throws LogicFaceException { + try { + byte[] payload=lpPacket.payload.getValue(); + Block block=new Block(payload,true); + + MINPacket minPacket=new MINPacket(); + if(!minPacket.wireDecode(block)){ + return null; + } + + return minPacket; + } catch (BlockException | PacketException e) { + throw new LogicFaceException("LinkService.getMINPacketFromLpPacket: "+e.getMessage()); + } + } + + /** + * 收到lpPacket包的处理函数,该函数被相关联的 transport 的 receive 函数调用 + * @return + */ + public MINPacket receivePacket() throws LogicFaceException { + LpPacket lpPacket=this.transport.receive(); + // 未分包,只有一个包 + MINPacket minPacket=this.getMINPacketFromLpPacket(lpPacket); + return minPacket; + } + + /** + * 发送一个lp包分片 + * @param buf 分片的数据 + * @param bufLen 数据长度 + * @param fragmentId 分片号 + * @param fragmentNum 分片数 + * @param fragmentSeq 第几块分片,从0开始 + * @return + */ + private boolean sendFragment(byte[] buf,int bufLen,long fragmentId,long fragmentNum, long fragmentSeq){ + LpPacket lpPacket=new LpPacket(); + lpPacket.setId(fragmentId); + lpPacket.setFragmentNum(fragmentNum); + lpPacket.setFragmentSeq(fragmentSeq); + byte[] nbuf=ByteHelper.getLenBytes(buf,0,bufLen); + lpPacket.setValue(nbuf); + return this.transport.send(lpPacket); + } + + /** + * 发送指定长度的一段数据,如果数据过长,会调用sendFragment发送多个分片 + * @param buf + * @param bufLen + * @return + */ + private boolean sendByteBuffer(byte[] buf,int bufLen){ + int fragmentLen=this.mtu-this.lpPacketHeadSize-10; + int startIndex=0; + int fragmentSeq=0; + int fragmentNum=bufLen/fragmentLen; + if(bufLen%fragmentLen!=0){ + fragmentNum++; + } + while (startIndex(bufLen-startIndex)){ + fragmentLen=bufLen-startIndex; + } + byte[] nbuf= ByteHelper.getLenBytes(buf,startIndex,fragmentLen); + if(!this.sendFragment(nbuf,fragmentLen,this.lpPacketId,fragmentNum,fragmentSeq)){ + return false; + } + startIndex+=fragmentLen; + fragmentSeq++; + } + this.lpPacketId++; + return true; + } + + /** + * 发送一个兴趣包 + * @param interest + * @return + */ + public boolean sendInterest(Interest interest) throws LogicFaceException { + try { + Encoder encoder=new Encoder(); + if(!encoder.encoderReset(new SizeT(Encoder.MaxPacketSize),new SizeT(0))){ + return false; + } + int bufLen=interest.wireEncode(encoder); + byte[] buf=encoder.getBuffer(); + return this.sendByteBuffer(buf,bufLen); + } catch (EncoderException | PacketException e) { + throw new LogicFaceException("LinkService.sendInterest: "+e.getMessage()); + } + } + + +} diff --git a/src/main/java/logicface/LogicFace.java b/src/main/java/logicface/LogicFace.java new file mode 100644 index 0000000..911e4b9 --- /dev/null +++ b/src/main/java/logicface/LogicFace.java @@ -0,0 +1,78 @@ +package logicface; + +import component.Identifier; +import packet.MINPacket; + +/* + * @Author: Wang Feng + * @Description: 逻辑接口类 + * @Version: 1.0.0 + * @Date: 20:27 2021/4/13 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class LogicFace { + // LogicFaceType区:LogicFace的类型 + public static final int LogicFaceTypeTCP = 0; + public static final int LogicFaceTypeUDP = 1; + public static final int LogicFaceTypeEther = 2; + public static final int LogicFaceTypeUnix = 3; + public static final int LogicFaceTypeInner = 4; + + // 成员变量区 + public int logicFaceType; + public ITransport transport; // 与logicFace绑定的transport + public LinkService linkService; // 与logicFace绑定的linkService + public LogicFaceCounters logicFaceCounters=new LogicFaceCounters(); // logicFace 流量统计对象 + public long expireTime; // 超时时间 ms + public boolean state; // true 为 up , false 为down + + /** + * 通过TCP连接MIR + * @param ip MIR的IP地址,如"1.1.12.2" + * @param port MIR的TCP端口号,如 13899 + * @return + */ + public boolean initWithTcp(String ip,String port){ + return true; + } + + /** + * 通过UDP连接MIR + * @param ip MIR的IP地址,如"1.1.12.2" + * @param port MIR的TCP端口号,如 13899 + * @return + */ + public boolean initWithUdp(String ip,String port){ + return true; + } + + /** + * 通过unixSocket连接MIR + * @param path MIR的unix socket地址,默认是 "/tmp/mir-sock" + * @return + */ + public boolean initWithUnixSocket(String path){ + return true; + } + + /** + * 在MIR中注册一个标识,路由指向本客户端 + * // (1) 构造一个命令兴趣包, 通过l.SendInterest(interest) 把兴趣包发出去; + * // (2) 等待一个数据包, 如果等待超时,则报错,如果接收到的包不是数据包则报错; + * // (3) 解析收到的数据包,根据数据包中的应答信息判断标识是否注册成功 + * @param identifier 要添加的路由标识 + * @param timeout 超时时间,以 毫秒 为单位 + * @return + */ + public boolean registerIdentifier(Identifier identifier,long timeout){ + return true; + } + + /** + * 从 LogicFace 中接收一个网络包 + * @return 多标识网络包 + */ +// public MINPacket ReceivePacket(){ +// return this.linkService +// } +} diff --git a/src/main/java/logicface/LogicFaceCounters.java b/src/main/java/logicface/LogicFaceCounters.java new file mode 100644 index 0000000..63d5bfc --- /dev/null +++ b/src/main/java/logicface/LogicFaceCounters.java @@ -0,0 +1,11 @@ +package logicface; + +/* + * @Author: Wang Feng + * @Description: + * @Version: 1.0.0 + * @Date: 20:35 2021/4/13 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class LogicFaceCounters { +} diff --git a/src/main/java/logicface/LogicFaceException.java b/src/main/java/logicface/LogicFaceException.java new file mode 100644 index 0000000..1ea3474 --- /dev/null +++ b/src/main/java/logicface/LogicFaceException.java @@ -0,0 +1,14 @@ +package logicface; + +/* + * @Author: hongyu guo + * @Description: + * @Version: 1.0.0 + * @Date: 19:38 2021/03/15 + * @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室 + */ +public class LogicFaceException extends Exception{ + public LogicFaceException(String msg){ + super("LogicFace."+msg); + } +} diff --git a/src/main/java/packet/LpPacket.java b/src/main/java/packet/LpPacket.java index 206d330..46afd7e 100644 --- a/src/main/java/packet/LpPacket.java +++ b/src/main/java/packet/LpPacket.java @@ -1,8 +1,6 @@ package packet; -import component.ComponentException; -import component.LpPacketHeader; -import component.Payload; +import component.*; import encoding.*; /* @@ -24,6 +22,38 @@ public class LpPacket implements IEncodingAble { this.payload=payload; } + public void setId(long fragmentId){ + this.lpPacketHeader.setLpPacketFragmentId(new LpPacketFragmentId(fragmentId)); + } + + public long getId(){ + return this.lpPacketHeader.getLpPacketFragmentId().getId(); + } + + public void setFragmentNum(long fragmentNum){ + this.lpPacketHeader.setLpPacketFragmentNum(new LpPacketFragmentNum(fragmentNum)); + } + + public long getFragmentNum(){ + return this.lpPacketHeader.getLpPacketFragmentNum().getFragmentNum(); + } + + public void setFragmentSeq(long fragmentSeq){ + this.lpPacketHeader.setLpPacketFragmentSeq(new LpPacketFragmentSeq(fragmentSeq)); + } + + public long getFragmentSeq(){ + return this.lpPacketHeader.getLpPacketFragmentSeq().getFragmentSeq(); + } + + public void setValue(byte[] value){ + this.payload.setValue(value); + } + + public byte[] getValue(){ + return this.payload.getValue(); + } + /** * 将 LpPacket 线速编码为一个 TLV * @param encoder