简体   繁体   中英

How to encapsulate a SCTP packet in UDP and send it over UDP channel in java

I have to transfer a file using SCTP protocol. I have written the code in java but the code is not working when I am using 4G hotspot.network. So I came across this RFC which talks about UDP encapsulation of SCTP. I want to know if there is an implementation which I can use to encapsulate SCTP packet in UDP and send it over UDP channel so that it can traverse heavily NATted.network. My current code for sending the data packet is as follows:

import java.io.*;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.*;

import com.sun.nio.sctp.MessageInfo;
import com.sun.nio.sctp.SctpChannel;
import com.sun.nio.sctp.SctpServerChannel;

public class Main {
    SctpChannel connectionChannelPrimary;
    SctpChannel connectionChannelSecondary;
    InetSocketAddress serverSocketAddressPrimary;
    InetSocketAddress serverSocketAddressSecondary;

    String directoryPath;

    public Main() {
        serverSocketAddressPrimary = new InetSocketAddress(6002);
        serverSocketAddressSecondary = new InetSocketAddress(6003);
    }

    public void setDirectoryPath(String directoryPath) {
        this.directoryPath = directoryPath;
    }

    public String getDirectoryPath() {
        return directoryPath;
    }

    public void establishConnection(int connId) throws IOException {
        SctpServerChannel sctpServerChannel = SctpServerChannel.open();
        if (connId == 0) {
            sctpServerChannel.bind(serverSocketAddressPrimary);
            connectionChannelPrimary = sctpServerChannel.accept();
            System.out.println("connection established for primary");
        } else {
            sctpServerChannel.bind(serverSocketAddressSecondary);
            connectionChannelSecondary = sctpServerChannel.accept();
            System.out.println("connection established for helper");
        }

    }

    ArrayList<String> getAllFiles() {
        File directory = new File(this.directoryPath);
        ArrayList<String> fileNames = new ArrayList<>();
        for (File fileEntry : Objects.requireNonNull(directory.listFiles())) {
            if (fileEntry.isFile()) {
                fileNames.add(fileEntry.getName());
            }
        }
        Collections.sort(fileNames);
        return fileNames;
    }

    public byte[] readFile(String filename) throws IOException {
        String extraString = "\n\n\n\nNRL\n\n\n";
        File file = new File(filename);
        FileInputStream fl = new FileInputStream(file);
        ByteBuffer finalBuffer = ByteBuffer.allocate((int) (file.length() + extraString.length()));
        byte[] arr = new byte[(int) file.length()];
        int res = fl.read(arr);
        if (res < 0) {
            System.out.println("Error in reading file");
            fl.close();
            return null;
        }
        fl.close();
        finalBuffer.put(arr);
        finalBuffer.put(extraString.getBytes());
        byte[] tmp = new byte[extraString.length()];
        finalBuffer.position((int) (file.length() - 1));
        finalBuffer.get(tmp, 0, tmp.length);
        return finalBuffer.array();
    }

    public void sendBytes(String filename, int connId) throws IOException {
        byte[] message = readFile(filename);
        assert message != null;
        System.out.println(message.length);
        int tmp = 0;
        int cntIndex = 60000;
        int prevIndex = 0;
        boolean isBreak = false;
        while (!isBreak) {
            byte[] slice;
            if (prevIndex + 60000 >= message.length) {
                slice = Arrays.copyOfRange(message, prevIndex, message.length);
                isBreak = true;
            } else {
                slice = Arrays.copyOfRange(message, prevIndex, cntIndex);
                prevIndex = cntIndex;
                cntIndex = cntIndex + 60000;
            }
            final ByteBuffer byteBuffer = ByteBuffer.allocate(64000);
            final MessageInfo messageInfo = MessageInfo.createOutgoing(null, 0);
            byteBuffer.put(slice);
            byteBuffer.flip();
            tmp += slice.length;
            try {
                if (connId == 0) connectionChannelPrimary.send(byteBuffer, messageInfo);
                else connectionChannelSecondary.send(byteBuffer, messageInfo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(tmp);
    }

    public static void main(String[] args) throws IOException {
        String bgFilePath = "/home/iiitd/Desktop/background/";
        String fgFilePath = "/home/iiitd/Desktop/foreground/";
        Main myObj = new Main();
        myObj.setDirectoryPath("/home/iiitd/Desktop/tmp/");
        myObj.establishConnection(1);
        myObj.establishConnection(0);
        ArrayList<String> files = myObj.getAllFiles();

        for (String tmpFile : files) {
            String cntFilePath = myObj.getDirectoryPath() + tmpFile;
            
            myObj.sendBytes(cntFilePath,0);
        }
    }
}

RFC Link: https://datatracker.ietf.org/doc/html/draft-ietf-tsvwg-sctp-udp-encaps-09

In C, I think that usrsctp is a popular implementation of SCTP over UDP. If I understand correctly, it was used by Google Chrome at some point (though I see they mentioned moving to "dcsctp" at some point). Also I have seen it in a mirror of the Firefox sources in 2016 , not sure what's the state today.

So one solution would be to wrap usrsctp with JNI. And it appears that this is exactly what jitsi-sctp is doing. I haven't used it, but I would have a look.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM