is it possible access OS socket handler from Socket instance

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

is it possible access OS socket handler from Socket instance

Denis Kudriashov
 
Hi.

I play a bit of idea to make binding to libssh2 library.

And the main problem is function 
int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t socket)
where socket parameter is raw OS socket handle as I understand.

So question: is it possible to access this handle from image side from Socket instance?
There is socketHandle instance variable which is bytearray. What is it? 

Best regards,
Denis
Reply | Threaded
Open this post in threaded view
|

Re: is it possible access OS socket handler from Socket instance

Eliot Miranda-2
 
Hi Denis,

On Tue, Aug 8, 2017 at 2:11 AM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

I play a bit of idea to make binding to libssh2 library.

And the main problem is function 
int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t socket)
where socket parameter is raw OS socket handle as I understand.

So question: is it possible to access this handle from image side from Socket instance?

Yes, but non-trivially.
 
There is socketHandle instance variable which is bytearray. What is it? 

It is an instance of this struct:

typedef struct
{
  int   sessionID;
  int   socketType;  /* 0 = TCP, 1 = UDP */
  void  *privateSocketPtr;
}  SQSocket, *SocketPtr;

The two most common definitions are:
linux/mac
typedef struct privateSocketStruct
{
  int s;            /* Unix socket */
  int connSema;         /* connection io notification semaphore */
  int readSema;         /* read io notification semaphore */
  int writeSema;        /* write io notification semaphore */
  int sockState;        /* connection + data state */
  int sockError;        /* errno after socket error */
  union sockaddr_any peer;  /* default send/recv address for UDP */
  socklen_t peerSize;       /* dynamic sizeof(peer) */
  union sockaddr_any sender;    /* sender address for last UDP receive */
  socklen_t senderSize;     /* dynamic sizeof(sender) */
  int multiListen;      /* whether to listen for multiple connections */
  int acceptedSock;     /* a connection that has been accepted */
} privateSocketStruct;

win32:
typedef struct privateSocketStruct {
  struct privateSocketStruct *next;
  SOCKET s;

  int sockType;
  int sockState;
  int sockError;

  int readSema;
  int writeSema;
  int connSema;

  union sockaddr_any peer;  /* socket address in connect() or send/rcv address for UDP */
  socklen_t peerSize;       /* dynamic sizeof(peer) */

  HANDLE mutex;             /* The mutex used for synchronized access to this socket */
  acceptedSocketStruct *accepted; /* Accepted connections on a socket */


  DWORD  readWatcherOp;      /* read operation to watch */
  HANDLE hReadWatcherEvent;  /* event for waking up read watcher */
  HANDLE hReadThread;

  DWORD  writeWatcherOp;     /* write operation to watch */
  HANDLE hWriteWatcherEvent; /* event for waking up write watcher */
  HANDLE hWriteThread;

  volatile DWORD closePending; /* Cleanup counter */

  int readSelect;
  int writeSelect;
} privateSocketStruct;

So you *could* create an Alien on the 4 bytes at 9 in the handle on 32-bits, or the 8 bytes at 9 on 64-bits, and then decode the resulting pointer to a privateSocketStruct.  On linux & mac os it is the 4 bytes at 1.  On Win32 it's the 4 bytes at 5, and on Win64 it's the 4 bytes at 9.

But I would instead add a new primitive to the socket plugin, something like primitiveSocketGetNativeHandle, and use that :-)

To do this:
a) modify VMMaker.oscog's SocketPlugin to add the primitive
b) in platforms/Cross/plugins/SocketPlugin./SocketPlugin.h add something like
    sqInt sqSocketNativeHandle(SocketPtr s, int type);
where type is, say, 0 for the normal file descriptor and other values for future use (one platform has both data and control sockets in its privateSocketStruct
c) implement sqSocketNativeHandle appropriately in platforms/unix/plugins/SocketPlugin/sqUnixSocket.c, platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c et al. There are 5 in all; Mac OS Carbon, RiscOS & Plan9 are the other three.)

Best regards,
Denis

_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: is it possible access OS socket handler from Socket instance

Denis Kudriashov
 
Thank's Eliot for such detailed response.

First case should be really fun. I like hacking :). Then I will look at primitive.

Best regards,
Denis

2017-08-08 20:34 GMT+02:00 Eliot Miranda <[hidden email]>:
 
Hi Denis,

On Tue, Aug 8, 2017 at 2:11 AM, Denis Kudriashov <[hidden email]> wrote:
 
Hi.

I play a bit of idea to make binding to libssh2 library.

And the main problem is function 
int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t socket)
where socket parameter is raw OS socket handle as I understand.

So question: is it possible to access this handle from image side from Socket instance?

Yes, but non-trivially.
 
There is socketHandle instance variable which is bytearray. What is it? 

It is an instance of this struct:

typedef struct
{
  int   sessionID;
  int   socketType;  /* 0 = TCP, 1 = UDP */
  void  *privateSocketPtr;
}  SQSocket, *SocketPtr;

The two most common definitions are:
linux/mac
typedef struct privateSocketStruct
{
  int s;            /* Unix socket */
  int connSema;         /* connection io notification semaphore */
  int readSema;         /* read io notification semaphore */
  int writeSema;        /* write io notification semaphore */
  int sockState;        /* connection + data state */
  int sockError;        /* errno after socket error */
  union sockaddr_any peer;  /* default send/recv address for UDP */
  socklen_t peerSize;       /* dynamic sizeof(peer) */
  union sockaddr_any sender;    /* sender address for last UDP receive */
  socklen_t senderSize;     /* dynamic sizeof(sender) */
  int multiListen;      /* whether to listen for multiple connections */
  int acceptedSock;     /* a connection that has been accepted */
} privateSocketStruct;

win32:
typedef struct privateSocketStruct {
  struct privateSocketStruct *next;
  SOCKET s;

  int sockType;
  int sockState;
  int sockError;

  int readSema;
  int writeSema;
  int connSema;

  union sockaddr_any peer;  /* socket address in connect() or send/rcv address for UDP */
  socklen_t peerSize;       /* dynamic sizeof(peer) */

  HANDLE mutex;             /* The mutex used for synchronized access to this socket */
  acceptedSocketStruct *accepted; /* Accepted connections on a socket */


  DWORD  readWatcherOp;      /* read operation to watch */
  HANDLE hReadWatcherEvent;  /* event for waking up read watcher */
  HANDLE hReadThread;

  DWORD  writeWatcherOp;     /* write operation to watch */
  HANDLE hWriteWatcherEvent; /* event for waking up write watcher */
  HANDLE hWriteThread;

  volatile DWORD closePending; /* Cleanup counter */

  int readSelect;
  int writeSelect;
} privateSocketStruct;

So you *could* create an Alien on the 4 bytes at 9 in the handle on 32-bits, or the 8 bytes at 9 on 64-bits, and then decode the resulting pointer to a privateSocketStruct.  On linux & mac os it is the 4 bytes at 1.  On Win32 it's the 4 bytes at 5, and on Win64 it's the 4 bytes at 9.

But I would instead add a new primitive to the socket plugin, something like primitiveSocketGetNativeHandle, and use that :-)

To do this:
a) modify VMMaker.oscog's SocketPlugin to add the primitive
b) in platforms/Cross/plugins/SocketPlugin./SocketPlugin.h add something like
    sqInt sqSocketNativeHandle(SocketPtr s, int type);
where type is, say, 0 for the normal file descriptor and other values for future use (one platform has both data and control sockets in its privateSocketStruct
c) implement sqSocketNativeHandle appropriately in platforms/unix/plugins/SocketPlugin/sqUnixSocket.c, platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c et al. There are 5 in all; Mac OS Carbon, RiscOS & Plan9 are the other three.)

Best regards,
Denis

_,,,^..^,,,_
best, Eliot


Reply | Threaded
Open this post in threaded view
|

Re: is it possible access OS socket handler from Socket instance

David T. Lewis
In reply to this post by Eliot Miranda-2
 
Good guidance on how to do it with a plugin (and please do give it a try!).
Also, if you have the AIO plugin in your VM, check and see if this works
for you:

primOSSocketHandle: sqSocket
        "Answer the low level socket descriptor for a socket IO handle."

        <primitive: 'primitiveOSSocketHandle' module: 'AioPlugin'>
        ^ nil

See class AioEventHandler in the OSProcess package for example usage.

Dave


On Tue, Aug 08, 2017 at 11:34:16AM -0700, Eliot Miranda wrote:

>  
> Hi Denis,
>
> On Tue, Aug 8, 2017 at 2:11 AM, Denis Kudriashov <[hidden email]>
> wrote:
>
> >
> > Hi.
> >
> > I play a bit of idea to make binding to libssh2 library.
> >
> > And the main problem is function
> >
> > int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t
> > socket)
> >
> > where socket parameter is raw OS socket handle as I understand.
> >
> > So question: is it possible to access this handle from image side from
> > Socket instance?
> >
>
> Yes, but non-trivially.
>
>
> > There is socketHandle instance variable which is bytearray. What is it?
> >
>
> It is an instance of this struct:
>
> typedef struct
> {
>   int   sessionID;
>   int   socketType;  /* 0 = TCP, 1 = UDP */
>   void  *privateSocketPtr;
> }  SQSocket, *SocketPtr;
>
> The two most common definitions are:
> linux/mac
> typedef struct privateSocketStruct
> {
>   int s;            /* Unix socket */
>   int connSema;         /* connection io notification semaphore */
>   int readSema;         /* read io notification semaphore */
>   int writeSema;        /* write io notification semaphore */
>   int sockState;        /* connection + data state */
>   int sockError;        /* errno after socket error */
>   union sockaddr_any peer;  /* default send/recv address for UDP */
>   socklen_t peerSize;       /* dynamic sizeof(peer) */
>   union sockaddr_any sender;    /* sender address for last UDP receive */
>   socklen_t senderSize;     /* dynamic sizeof(sender) */
>   int multiListen;      /* whether to listen for multiple connections */
>   int acceptedSock;     /* a connection that has been accepted */
> } privateSocketStruct;
>
> win32:
> typedef struct privateSocketStruct {
>   struct privateSocketStruct *next;
>   SOCKET s;
>
>   int sockType;
>   int sockState;
>   int sockError;
>
>   int readSema;
>   int writeSema;
>   int connSema;
>
>   union sockaddr_any peer;  /* socket address in connect() or send/rcv
> address for UDP */
>   socklen_t peerSize;       /* dynamic sizeof(peer) */
>
>   HANDLE mutex;             /* The mutex used for synchronized access to
> this socket */
>   acceptedSocketStruct *accepted; /* Accepted connections on a socket */
>
>
>   DWORD  readWatcherOp;      /* read operation to watch */
>   HANDLE hReadWatcherEvent;  /* event for waking up read watcher */
>   HANDLE hReadThread;
>
>   DWORD  writeWatcherOp;     /* write operation to watch */
>   HANDLE hWriteWatcherEvent; /* event for waking up write watcher */
>   HANDLE hWriteThread;
>
>   volatile DWORD closePending; /* Cleanup counter */
>
>   int readSelect;
>   int writeSelect;
> } privateSocketStruct;
>
> So you *could* create an Alien on the 4 bytes at 9 in the handle on
> 32-bits, or the 8 bytes at 9 on 64-bits, and then decode the resulting
> pointer to a privateSocketStruct.  On linux & mac os it is the 4 bytes at
> 1.  On Win32 it's the 4 bytes at 5, and on Win64 it's the 4 bytes at 9.
>
> But I would instead add a new primitive to the socket plugin, something
> like primitiveSocketGetNativeHandle, and use that :-)
>
> To do this:
> a) modify VMMaker.oscog's SocketPlugin to add the primitive
> b) in platforms/Cross/plugins/SocketPlugin./SocketPlugin.h add something
> like
>     sqInt sqSocketNativeHandle(SocketPtr s, int type);
> where type is, say, 0 for the normal file descriptor and other values for
> future use (one platform has both data and control sockets in its
> privateSocketStruct
> c) implement sqSocketNativeHandle appropriately in
> platforms/unix/plugins/SocketPlugin/sqUnixSocket.c,
> platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c et al. There are 5 in
> all; Mac OS Carbon, RiscOS & Plan9 are the other three.)
>
> Best regards,
> > Denis
> >
>
> _,,,^..^,,,_
> best, Eliot

Reply | Threaded
Open this post in threaded view
|

Re: is it possible access OS socket handler from Socket instance

Denis Kudriashov
 
Thank's David.
I followed your advice (this plugin is included in Pharo).

So I succeed with libssh2. There are a couple of strange issues but they are not critical for now.
Project is on github https://github.com/dionisiydk/libssh2-pharo-bindings. It uses UFFI. So it is only for Pharo

2017-08-08 21:43 GMT+02:00 David T. Lewis <[hidden email]>:

Good guidance on how to do it with a plugin (and please do give it a try!).
Also, if you have the AIO plugin in your VM, check and see if this works
for you:

primOSSocketHandle: sqSocket
        "Answer the low level socket descriptor for a socket IO handle."

        <primitive: 'primitiveOSSocketHandle' module: 'AioPlugin'>
        ^ nil

See class AioEventHandler in the OSProcess package for example usage.

Dave


On Tue, Aug 08, 2017 at 11:34:16AM -0700, Eliot Miranda wrote:
>
> Hi Denis,
>
> On Tue, Aug 8, 2017 at 2:11 AM, Denis Kudriashov <[hidden email]>
> wrote:
>
> >
> > Hi.
> >
> > I play a bit of idea to make binding to libssh2 library.
> >
> > And the main problem is function
> >
> > int libssh2_session_handshake(LIBSSH2_SESSION *session, libssh2_socket_t
> > socket)
> >
> > where socket parameter is raw OS socket handle as I understand.
> >
> > So question: is it possible to access this handle from image side from
> > Socket instance?
> >
>
> Yes, but non-trivially.
>
>
> > There is socketHandle instance variable which is bytearray. What is it?
> >
>
> It is an instance of this struct:
>
> typedef struct
> {
>   int   sessionID;
>   int   socketType;  /* 0 = TCP, 1 = UDP */
>   void  *privateSocketPtr;
> }  SQSocket, *SocketPtr;
>
> The two most common definitions are:
> linux/mac
> typedef struct privateSocketStruct
> {
>   int s;            /* Unix socket */
>   int connSema;         /* connection io notification semaphore */
>   int readSema;         /* read io notification semaphore */
>   int writeSema;        /* write io notification semaphore */
>   int sockState;        /* connection + data state */
>   int sockError;        /* errno after socket error */
>   union sockaddr_any peer;  /* default send/recv address for UDP */
>   socklen_t peerSize;       /* dynamic sizeof(peer) */
>   union sockaddr_any sender;    /* sender address for last UDP receive */
>   socklen_t senderSize;     /* dynamic sizeof(sender) */
>   int multiListen;      /* whether to listen for multiple connections */
>   int acceptedSock;     /* a connection that has been accepted */
> } privateSocketStruct;
>
> win32:
> typedef struct privateSocketStruct {
>   struct privateSocketStruct *next;
>   SOCKET s;
>
>   int sockType;
>   int sockState;
>   int sockError;
>
>   int readSema;
>   int writeSema;
>   int connSema;
>
>   union sockaddr_any peer;  /* socket address in connect() or send/rcv
> address for UDP */
>   socklen_t peerSize;       /* dynamic sizeof(peer) */
>
>   HANDLE mutex;             /* The mutex used for synchronized access to
> this socket */
>   acceptedSocketStruct *accepted; /* Accepted connections on a socket */
>
>
>   DWORD  readWatcherOp;      /* read operation to watch */
>   HANDLE hReadWatcherEvent;  /* event for waking up read watcher */
>   HANDLE hReadThread;
>
>   DWORD  writeWatcherOp;     /* write operation to watch */
>   HANDLE hWriteWatcherEvent; /* event for waking up write watcher */
>   HANDLE hWriteThread;
>
>   volatile DWORD closePending; /* Cleanup counter */
>
>   int readSelect;
>   int writeSelect;
> } privateSocketStruct;
>
> So you *could* create an Alien on the 4 bytes at 9 in the handle on
> 32-bits, or the 8 bytes at 9 on 64-bits, and then decode the resulting
> pointer to a privateSocketStruct.  On linux & mac os it is the 4 bytes at
> 1.  On Win32 it's the 4 bytes at 5, and on Win64 it's the 4 bytes at 9.
>
> But I would instead add a new primitive to the socket plugin, something
> like primitiveSocketGetNativeHandle, and use that :-)
>
> To do this:
> a) modify VMMaker.oscog's SocketPlugin to add the primitive
> b) in platforms/Cross/plugins/SocketPlugin./SocketPlugin.h add something
> like
>     sqInt sqSocketNativeHandle(SocketPtr s, int type);
> where type is, say, 0 for the normal file descriptor and other values for
> future use (one platform has both data and control sockets in its
> privateSocketStruct
> c) implement sqSocketNativeHandle appropriately in
> platforms/unix/plugins/SocketPlugin/sqUnixSocket.c,
> platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c et al. There are 5 in
> all; Mac OS Carbon, RiscOS & Plan9 are the other three.)
>
> Best regards,
> > Denis
> >
>
> _,,,^..^,,,_
> best, Eliot