问题描述
我实现了一个抽象抽象流的流类。 此类称为sniStream,我想将Sni工具添加到c#。
sniStream的来源是这样的,它使用了我已经实现的本地c ++库:
public class SniStream : Stream
{
[DllImport(@"SniReceiver.dll",CallingConvention = CallingConvention.StdCall)]
private static extern int write_ssl(string data);
[DllImport(@"SniReceiver.dll",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]
private static extern int read_ssl_sni(byte[] data,int offset,int count);
[DllImport(@"SniReceiver.dll",CallingConvention = CallingConvention.StdCall)]
private static extern void cleanup_openssl();
[DllImport(@"SniReceiver.dll",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr get_domainname(IntPtr sock);
[DllImport(@"SniReceiver.dll",CallingConvention = CallingConvention.StdCall)]
private static extern int get_ssl_pending();
[DllImport(@"SniReceiver.dll",CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr load_all_ssl_certificates(string path);
public SniStream(Stream innerStream,bool leaveInnerStreamOpen)
{
innerStream = this;
CanWrite = CanRead = true;
Position = 0;
CanSeek = false;
}
}
public override long Position { get; set; }
public override long Length { get; }
public override bool CanWrite { get; }
public override bool CanSeek { get; }
public override bool CanRead { get; }
public override long Seek(long offset,SeekOrigin origin) => throw new NotImplementedException();
public override void SetLength(long value) => throw new NotImplementedException();
public override void Write(byte[] buffer,int count)
{
int writed = write_ssl(Encoding.UTF8.GetString(buffer));
Position += writed;
//Array.Clear(buffer,buffer.Length);
}
public override int Read(byte[] buffer,int count)
{
int received = 0;
string s = "";
Array.Clear(buffer,buffer.Length);
received = read_ssl_sni(buffer,offset,count);
Position += received;
return received;
}
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer,CancellationToken cancellationToken = default)
{
return new ValueTask(new Task(() => {
int read= write_ssl(Encoding.UTF8.GetString(buffer.ToArray()));
Position += read;
})
);
}
public override ValueTask<int> ReadAsync(Memory<byte> buffer,CancellationToken cancellationToken = default)
{
int revieved = 0;
string s = "";
Array.Clear(buffer.ToArray(),buffer.Length);
revieved=read_ssl_sni(buffer.ToArray(),0);
Position += revieved;
return new ValueTask<int>(revieved);
}
public override Task<int> ReadAsync(byte[] buffer,int count,CancellationToken cancellationToken)
{
int revieved = 0;
string s = "";
Array.Clear(buffer,buffer.Length);
revieved = read_ssl_sni(buffer,count);
Position += revieved;
return Task.Fromresult(revieved);
}
public string GetDomainName(Socket sClient)
{
return Marshal.PtrToStringAnsi(get_domainname(sClient.Handle));
}
public static string LoadAllCertificates(string path)
{
string res = Marshal.PtrToStringAnsi(load_all_ssl_certificates(path));
return "";
}
public override void Flush()
{
//cleanup_openssl();
Position = 0;
}
C ++ SniReader是这样的:
#include "stdafx.h"
#include "SniReceiver.h"
#include <algorithm>
#include <cctype>
#include <string>
SSL *ssl;
SSL_CTX *create_context(SSL_CTX *ctx)
{
const SSL_METHOD *method;
method = TLSv1_2_server_method();
ctx = SSL_CTX_new(method);
if (!ctx) {
perror("Unable to create SSL context");
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
const char * load_all_ssl_certificates(char* certicatesPath)
{
//load certificates from a folder
}
void init_openssl()
{
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
}
void cleanup_openssl()
{
EVP_cleanup();
SSL_free(ssl);
}
static int ssl_servername_cb(SSL *s,int *ad,void *arg)
{
const char *servername = SSL_get_servername(s,TLSEXT_NAMETYPE_host_name);
domainname = servername;
if (servername != NULL) {
SSL_CTX * cc = certificates.at(servername);
SSL_set_SSL_CTX(s,cc);
}
return SSL_TLSEXT_ERR_OK;
}
extern "C" __declspec(dllexport) const char * __cdecl get_domainname(DWORD socket)
{
SSL_CTX *ctx = NULL;
init_openssl();
ctx = create_context(ctx);
SSL_CTX_set_tlsext_servername_callback(ctx,ssl_servername_cb);
ssl = SSL_new(ctx);
int x = SSL_set_fd(ssl,socket);
int hand = SSL_do_handshake(ssl);
int acc = SSL_accept(ssl);
return domainname;
}
extern "C" __declspec(dllexport) int __stdcall write_ssl(char data[])
{
int writed=SSL_write(ssl,data,strlen(data));
return writed;
}
extern "C" __declspec(dllexport) int __stdcall read_ssl_sni(char recvb[],int count)
{
const int recvbuflen = 4096;
char recvbuf[recvbuflen];
return(SSL_read(ssl,recvb,count));
}
头文件是这个
#include <WinSock2.h>
#include "minwindef.h"
#include <iostream>
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <map>
#include <tuple>
#include <filesystem> //New in C++ 17 //old one include <dirent.h> for windows
namespace fs = std::filesystem; // work with vs 2019
std::map<std::string,SSL_CTX *> certificates;
const char *domainname;
char *readResult;
extern "C" __declspec(dllexport) char * __cdecl receive_socket(DWORD socket);
extern "C" __declspec(dllexport) const char * __cdecl load_all_ssl_certificates(char* path);
extern "C" __declspec(dllexport) int __stdcall add_num(int a,int b);
extern "C" __declspec(dllexport) int __stdcall write_ssl(char* data);
extern "C" __declspec(dllexport) int __stdcall read_ssl_sni(char recvbuf[],int count);
extern "C" __declspec(dllexport) const char * __cdecl get_domainname(DWORD socket);
extern "C" __declspec(dllexport) int __stdcall get_ssl_pending();
extern "C" __declspec(dllexport) void __cdecl cleanup_openssl();
问题是c#程序在异步模式下使用sniStream。我有2页,一个叫做fulsh, 其他同花顺2。 (冲洗只是名称,而不是冲洗流)。
flush返回flush,而flush2返回flush2。
当我先调用每个,在加载第一个之前,在浏览器的新标签页中调用第二个时,第二页的内容先于前。我认为缓冲区中的某些部分重叠。 我在msdn上了解到,异步方法的流类的实现者应在其中调用Read和Write方法。
有什么想法吗?我应该创建一个在sniStream中共享为缓冲区的字节数组吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)