Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/target
bin
obj
11 changes: 11 additions & 0 deletions csharp/DirectIpNet.Native/DirectIpNet.Native.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<OutputType>Library</OutputType>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="../DirectIpNet/SBDDirectIP.csproj" />
</ItemGroup>
</Project>
56 changes: 56 additions & 0 deletions csharp/DirectIpNet.Native/Exports.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SBDDirectIP;

namespace SBDDirectIP.Native;

public static unsafe class Exports
{
[StructLayout(LayoutKind.Sequential)]
public struct ConfirmationInfo
{
public uint ClientMsgId;
public uint IdReference;
public MessageStatus Status;
}

[UnmanagedCallersOnly(EntryPoint = "directip_send_mt")]
public static int SendMt(byte* host, int port, uint clientMsgId, byte* imei, byte* payload, int payloadLen, ConfirmationInfo* confirmation)
{
try
{
var hostStr = Marshal.PtrToStringUTF8((IntPtr)host)!;
var imeiStr = Marshal.PtrToStringUTF8((IntPtr)imei)!;
var data = new byte[payloadLen];
if (payload != null && payloadLen > 0)
{
Marshal.Copy((IntPtr)payload, data, 0, payloadLen);
}

var client = new DirectIpClient(hostStr, port);
var msg = MTMessage.Builder()
.ClientMsgId(clientMsgId)
.Imei(imeiStr)
.Payload(data)
.Build();

Task<Confirmation> task = client.SendAsync(msg);
task.Wait();
Confirmation conf = task.Result;

if (confirmation != null)
{
confirmation->ClientMsgId = conf.ClientMsgId;
confirmation->IdReference = conf.IdReference;
confirmation->Status = conf.Status;
}

return 0;
}
catch
{
return -1;
}
}
}
35 changes: 35 additions & 0 deletions csharp/DirectIpNet.Native/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# DirectIpNet.Native

This project exposes the `SBDDirectIP` API as a native C library. It uses
`UnmanagedCallersOnly` so the resulting binary can be consumed from any language
that can call C functions.

## Building

Use `dotnet publish` with NativeAOT enabled to produce a shared library:

```shell
cd csharp/DirectIpNet.Native
dotnet publish -c Release -r linux-x64
```

The compiled library will be placed under `bin/Release/net8.0/linux-x64/native`.

## Usage

Include `directip.h` in your C or C++ project and link against the produced
library. Example:

```c
#include "directip.h"

int main() {
ConfirmationInfo conf;
const char payload[] = "Hello";
int rc = directip_send_mt("127.0.0.1", 10800, 1,
"012345678901234",
(const uint8_t*)payload, sizeof(payload)-1,
&conf);
return rc;
}
```
28 changes: 28 additions & 0 deletions csharp/DirectIpNet.Native/directip.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef DIRECTIP_H
#define DIRECTIP_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
uint32_t ClientMsgId;
uint32_t IdReference;
int32_t Status;
} ConfirmationInfo;

int directip_send_mt(const char* host,
int port,
uint32_t client_msg_id,
const char* imei,
const uint8_t* payload,
int payload_len,
ConfirmationInfo* confirmation);

#ifdef __cplusplus
}
#endif

#endif // DIRECTIP_H
29 changes: 29 additions & 0 deletions csharp/DirectIpNet/DirectIpClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace SBDDirectIP;

public class DirectIpClient
{
private readonly string _host;
private readonly int _port;

public DirectIpClient(string host, int port)
{
_host = host;
_port = port;
}

public async Task<Confirmation> SendAsync(MTMessage message)
{
using var client = new TcpClient();
await client.ConnectAsync(_host, _port);
using var stream = client.GetStream();
var data = message.ToArray();
await stream.WriteAsync(data, 0, data.Length);
var buffer = new byte[56];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
return Confirmation.FromArray(buffer.AsSpan(3));
}
}
Loading