Skip to content

Commit

Permalink
Network card initial
Browse files Browse the repository at this point in the history
  • Loading branch information
Ktlo committed Aug 17, 2021
1 parent 72a4e61 commit e7767ec
Show file tree
Hide file tree
Showing 53 changed files with 2,885 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/DatagramSession.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package li.cil.oc2.api.inet;

public interface DatagramSession extends Session {
}
7 changes: 7 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/EchoSession.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package li.cil.oc2.api.inet;

public interface EchoSession extends Session {
int getSequenceNumber();

int getTtl();
}
35 changes: 35 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/InternetProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package li.cil.oc2.api.inet;

/**
* Internet access provider for oc2:internet-card item.
* At initialization phase one implementation of this interface will be loaded via {@link java.util.ServiceLoader}.
* If no implementation is found, then the default one will be used instead.
* <p>
* It is recommended to not implement this interface directly.
* There are several abstract classes for several levels of TCP/IP stack:
*
* <ul>
* <li>{@link LinkLocalLayerInternetProvider}</li>
* <li>{@link NetworkLayerInternetProvider}</li>
* <li>{@link TransportLayerInternetProvider}</li>
* <li>{@link SessionLayerInternetProvider}</li>
* </ul>
* <p>
* Each of these classes implements {@link InternetProvider} and
* asks you to provide an implementation of corresponding TCP/IP layer.
*
* @see LinkLocalLayerInternetProvider
* @see NetworkLayerInternetProvider
* @see TransportLayerInternetProvider
* @see SessionLayerInternetProvider
*/
public interface InternetProvider {

/**
* This method should provide and implementation of {@link LinkLocalLayer} interface and not fail.
* It will be called once for each loaded internet card.
*
* @return an implementation of {@link LinkLocalLayer} interface
*/
LinkLocalLayer provideInternet();
}
49 changes: 49 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/LinkLocalLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package li.cil.oc2.api.inet;

import java.nio.ByteBuffer;

/**
* Link local or channel TCP/IP layer interface.
* <p>
* There is a default link local layer implementation that uses provided {@link NetworkLayer} implementation
* (see {@link NetworkLayerInternetProvider} for more information).
*/
public interface LinkLocalLayer {
/**
* Ethernet frame header size. Consists of two ethernet (MAC) addresses and protocol number.
*/
int FRAME_HEADER_SIZE = 14;

/**
* Default ethernet frame body size that is used in Linux.
*/
int DEFAULT_MTU = 1500;

/**
* Default ethernet frame size.
*/
int FRAME_SIZE = FRAME_HEADER_SIZE + DEFAULT_MTU;

////////////////////////////////////////////////////////////////////

/**
* Tries to get the next ethernet frame to send it to virtual computer later.
* <p>
* Normally, this method is invoked every game tick in the Internet thread.
*
* @param frame byte buffer where frame body should be put
* @return should return false, if no ethernet frame were gathered, and true otherwise
*/
default boolean receiveEthernetFrame(final ByteBuffer frame) {
return false;
}

/**
* Sends an ethernet frame from virtual computer.
*
* @param frame byte buffer filled with ethernet frame data
*/
default void sendEthernetFrame(final ByteBuffer frame) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package li.cil.oc2.api.inet;

import li.cil.oc2.common.inet.NullLinkLocalLayer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* An {@link InternetProvider} partial implementation that expects an {@link LinkLocalLayer} implementation from
* protected method {@link LinkLocalLayerInternetProvider#provideLinkLocalLayer()}.
*
* @see InternetProvider
* @see LinkLocalLayer
*/
public abstract class LinkLocalLayerInternetProvider implements InternetProvider {
private static final Logger LOGGER = LogManager.getLogger();

/**
* This method is called from {@link LinkLocalLayerInternetProvider#provideInternet()} in order to get an
* {@link LinkLocalLayer} implementation.
* If it fails, then a dummy {@link LinkLocalLayer} implementation will be used.
* Dummy implementation will do nothing.
*
* @return an implementation of link local TCP/IP layer for internet cards
* @throws Exception this method is allowed to fail with an exception
*/
protected abstract LinkLocalLayer provideLinkLocalLayer() throws Exception;

@Override
public final LinkLocalLayer provideInternet() {
try {
return provideLinkLocalLayer();
} catch (Exception e) {
LOGGER.error("Failed to instantiate the implementation " +
"of Internet provider for internet card (provider {})", this.getClass(), e);
return NullLinkLocalLayer.INSTANCE;
}
}
}
65 changes: 65 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/NetworkLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package li.cil.oc2.api.inet;

import java.nio.ByteBuffer;

/**
* Network TCP/IP layer interface.
* <p>
* There is a default network layer implementation that uses provided {@link TransportLayer} implementation
* (see {@link TransportLayerInternetProvider} for more information).
*/
public interface NetworkLayer {

/**
* The value of this constant should be returned by {@link NetworkLayer#receivePacket(ByteBuffer)} method if no
* data is arrived.
*/
short PROTOCOL_NONE = 0;

/**
* The value of this constant should be returned by {@link NetworkLayer#receivePacket(ByteBuffer)} method if IPv4
* packet is arrived.
*/
short PROTOCOL_IPv4 = 0x0800;

/**
* The value of this constant should be returned by {@link NetworkLayer#receivePacket(ByteBuffer)} method if any IP
* packet is arrived (can be either IPv4 packet or IPv6 packet).
* <p>
* Normally, this value should be returned if any data is arrived.
*/
short PROTOCOL_IP = PROTOCOL_IPv4;

/**
* The value of this constant should be returned by {@link NetworkLayer#receivePacket(ByteBuffer)} method if IPv6
* packet is arrived.
*/
short PROTOCOL_IPv6 = (short) 0x86dd;

////////////////////////////////////////////////////////////////////////////////////

/**
* Tries to get the next IP paket to wrap it into an ethernet frame and send it to virtual computer later.
* <p>
* Normally, this method is invoked every game tick in the Internet thread.
*
* @param packet byte buffer where IP packet body should be put
* @return protocol number of received data (either {@link NetworkLayer#PROTOCOL_IP},
* {@link NetworkLayer#PROTOCOL_IPv4} or {@link NetworkLayer#PROTOCOL_IPv6}) or
* {@link NetworkLayer#PROTOCOL_NONE}, if no new data has arrived
*/
default short receivePacket(final ByteBuffer packet) {
return PROTOCOL_NONE;
}

/**
* Sends an IP packet extracted from an ethernet frame that sent virtual computer.
*
* @param protocol protocol number of arrived message; normally, should be either
* {@link NetworkLayer::PROTOCOL_IPv4} or {@link NetworkLayer::PROTOCOL_IPv6}
* @param packet arrived data
*/
default void sendPacket(final short protocol, final ByteBuffer packet) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package li.cil.oc2.api.inet;

import li.cil.oc2.common.inet.DefaultLinkLocalLayer;

/**
* An {@link InternetProvider} partial implementation that expects an {@link NetworkLayer} implementation from
* protected method {@link NetworkLayerInternetProvider#provideNetworkLayer()}.
*
* @see InternetProvider
* @see NetworkLayer
*/
public abstract class NetworkLayerInternetProvider extends LinkLocalLayerInternetProvider {

/**
* This method is called from {@link NetworkLayerInternetProvider#provideLinkLocalLayer()} in order to get a
* {@link NetworkLayer} implementation.
* Retrieved {@link NetworkLayer} implementation will be wrapped with internal {@link LinkLocalLayer}
* implementation.
*
* @return an implementation of network TCP/IP layer for internet cards
* @throws Exception this method is allowed to fail with an exception
*/
protected abstract NetworkLayer provideNetworkLayer() throws Exception;

@Override
protected final LinkLocalLayer provideLinkLocalLayer() throws Exception {
return new DefaultLinkLocalLayer(provideNetworkLayer());
}
}
23 changes: 23 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/Session.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package li.cil.oc2.api.inet;

import javax.annotation.Nullable;
import java.net.InetSocketAddress;

public interface Session {
long getId();

void close();

States getState();

@Nullable
Object getUserdata();

void setUserdata(final Object userdata);

InetSocketAddress getDestination();

enum States {
NEW, ESTABLISHED, FINISH, REJECT, EXPIRED
}
}
22 changes: 22 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/SessionLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package li.cil.oc2.api.inet;

import javax.annotation.Nullable;
import java.nio.ByteBuffer;

/**
* A session layer interface of TCP/IP stack.
*/
public interface SessionLayer {
default void receiveSession(final Receiver receiver) {

}

default void sendSession(final Session session, @Nullable final ByteBuffer data) {
session.close();
}

interface Receiver {
@Nullable
ByteBuffer receive(Session session);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package li.cil.oc2.api.inet;

import li.cil.oc2.common.inet.DefaultTransportLayer;

/**
* An {@link InternetProvider} partial implementation that expects an {@link SessionLayer} implementation from
* protected method {@link SessionLayerInternetProvider#provideSessionLayer()}.
*
* @see InternetProvider
* @see SessionLayer
*/
public abstract class SessionLayerInternetProvider extends TransportLayerInternetProvider {

/**
* This method is called from {@link SessionLayerInternetProvider#provideTransportLayer()} in order to get a
* {@link SessionLayer} implementation.
* Retrieved {@link SessionLayer} implementation will be wrapped with internal {@link TransportLayer}
* implementation.
*
* @return an implementation of session TCP/IP layer for internet cards
* @throws Exception this method is allowed to fail with an exception
*/
protected abstract SessionLayer provideSessionLayer() throws Exception;

@Override
protected final TransportLayer provideTransportLayer() throws Exception {
return new DefaultTransportLayer(provideSessionLayer());
}
}
4 changes: 4 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/StreamSession.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package li.cil.oc2.api.inet;

public interface StreamSession extends Session {
}
60 changes: 60 additions & 0 deletions src/main/java/li/cil/oc2/api/inet/TransportLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package li.cil.oc2.api.inet;

/**
* Transport TCP/IP layer interface.
* <p>
* There is a default transport layer implementation that uses provided {@link SessionLayer} implementation
* (see {@link SessionLayerInternetProvider} for more information).
*/
public interface TransportLayer {

/**
* The value of this constant should be returned by {@link TransportLayer#receiveTransportMessage(TransportMessage)}
* method if no data is arrived.
*/
byte PROTOCOL_NONE = 0;

/**
* The value of this constant should be returned by {@link TransportLayer#receiveTransportMessage(TransportMessage)}
* method if an ICMP message is arrived.
*/
byte PROTOCOL_ICMP = 1;

/**
* The value of this constant should be returned by {@link TransportLayer#receiveTransportMessage(TransportMessage)}
* method if a TCP packet is arrived.
*/
byte PROTOCOL_TCP = 6;

/**
* The value of this constant should be returned by {@link TransportLayer#receiveTransportMessage(TransportMessage)}
* method if a UDP message is arrived.
*/
byte PROTOCOL_UDP = 17;

////////////////////////////////////////////////////////////////////////////////////

/**
* Tries to get the next transport message to wrap it into an IP packet and send it to virtual computer later.
* <p>
* Normally, this method is invoked every game tick in the Internet thread.
*
* @param message transport message object that should be filled with arrived data
* @return protocol number of received data (can be, for example, {@link TransportLayer#PROTOCOL_ICMP},
* {@link TransportLayer#PROTOCOL_TCP} or {@link TransportLayer#PROTOCOL_UDP}) or
* {@link TransportLayer#PROTOCOL_NONE}, if no new data has arrived
*/
default byte receiveTransportMessage(final TransportMessage message) {
return 0;
}

/**
* Sends a transport message extracted from an IP packet that sent virtual computer.
*
* @param protocol protocol number of arrived message
* @param message arrived transport message
*/
default void sendTransportMessage(byte protocol, final TransportMessage message) {

}
}
Loading

0 comments on commit e7767ec

Please sign in to comment.