]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Implement sendmsg() and recvmsg()
authorToni Wilen <twilen@winuae.net>
Sat, 1 Apr 2017 17:09:03 +0000 (20:09 +0300)
committerToni Wilen <twilen@winuae.net>
Sat, 1 Apr 2017 17:09:03 +0000 (20:09 +0300)
bsdsocket.cpp
include/bsdsocket.h
od-win32/bsdsock.cpp

index 10345a53006c5ba3fa4a39af319cd9831d1ec60f..74161bb9e45dffc7798c872e23803821259d6c8d 100644 (file)
@@ -23,6 +23,7 @@
 #include "bsdsocket.h"
 #include "threaddep/thread.h"
 #include "native2amiga.h"
+#include "debug.h"
 
 #ifdef BSDSOCKET
 
@@ -604,7 +605,7 @@ static uae_u32 REGPARAM2 bsdsocklib_connect (TrapContext *ctx)
 static uae_u32 REGPARAM2 bsdsocklib_sendto (TrapContext *ctx)
 {
        struct socketbase *sb = get_socketbase (ctx);
-       host_sendto(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), trap_get_dreg(ctx, 1),
+       host_sendto(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), NULL, trap_get_dreg(ctx, 1),
                trap_get_dreg(ctx, 2), trap_get_areg(ctx, 1), trap_get_dreg(ctx, 3));
        return sb->resultval;
 }
@@ -613,7 +614,7 @@ static uae_u32 REGPARAM2 bsdsocklib_sendto (TrapContext *ctx)
 static uae_u32 REGPARAM2 bsdsocklib_send (TrapContext *ctx)
 {
        struct socketbase *sb = get_socketbase (ctx);
-       host_sendto(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), trap_get_dreg(ctx, 1),
+       host_sendto(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), NULL, trap_get_dreg(ctx, 1),
                trap_get_dreg(ctx, 2), 0, 0);
        return sb->resultval;
 }
@@ -622,7 +623,7 @@ static uae_u32 REGPARAM2 bsdsocklib_send (TrapContext *ctx)
 static uae_u32 REGPARAM2 bsdsocklib_recvfrom (TrapContext *ctx)
 {
        struct socketbase *sb = get_socketbase (ctx);
-       host_recvfrom(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), trap_get_dreg(ctx, 1),
+       host_recvfrom(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), NULL, trap_get_dreg(ctx, 1),
                trap_get_dreg(ctx, 2), trap_get_areg(ctx, 1), trap_get_areg(ctx, 2));
        return sb->resultval;
 }
@@ -631,7 +632,7 @@ static uae_u32 REGPARAM2 bsdsocklib_recvfrom (TrapContext *ctx)
 static uae_u32 REGPARAM2 bsdsocklib_recv (TrapContext *ctx)
 {
        struct socketbase *sb = get_socketbase (ctx);
-       host_recvfrom(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), trap_get_dreg(ctx, 1),
+       host_recvfrom(ctx, sb, trap_get_dreg(ctx, 0), trap_get_areg(ctx, 0), NULL, trap_get_dreg(ctx, 1),
                trap_get_dreg(ctx, 2), 0, 0);
        return sb->resultval;
 }
@@ -1066,16 +1067,131 @@ static uae_u32 REGPARAM2 bsdsocklib_Dup2Socket (TrapContext *ctx)
        return host_dup2socket(ctx, sb, trap_get_dreg(ctx, 0), trap_get_dreg(ctx, 1));
 }
 
+#if 0
+struct iovec {
+       caddr_t iov_base;
+       int     iov_len;
+};
+
+struct msghdr {
+       caddr_t msg_name;               /* optional address */
+       u_int   msg_namelen;            /* size of address */
+       struct  iovec *msg_iov;         /* scatter/gather array */
+       u_int   msg_iovlen;             /* # elements in msg_iov */
+       caddr_t msg_control;            /* ancillary data, see below */
+       u_int   msg_controllen;         /* ancillary data buffer len */
+       int     msg_flags;              /* flags on received message */
+};
+#endif
+
+#define MSG_EOR                0x08    /* data completes record */
+#define        MSG_TRUNC       0x10    /* data discarded before delivery */
+
 static uae_u32 REGPARAM2 bsdsocklib_sendmsg (TrapContext *ctx)
 {
-       write_log (_T("bsdsocket: UNSUPPORTED: sendmsg()\n"));
-       return 0;
+       struct socketbase *sb = get_socketbase (ctx);
+       uaecptr sd = trap_get_dreg(ctx, 0);
+       uaecptr msg = trap_get_areg(ctx, 0);
+       uae_u32 flags = trap_get_dreg(ctx, 1);
+
+       SOCKET s = getsock (ctx, sb, sd + 1);
+       if (s == INVALID_SOCKET)
+               return -1;
+
+       int iovlen = trap_get_long(ctx, msg + 12);
+       int total = 0;
+       uaecptr iovec = trap_get_long(ctx, msg + 8);
+       for (int i = 0; i < iovlen; i++) {
+               uaecptr iovecp = iovec + i * 8;
+               int cnt = trap_get_long(ctx, iovecp + 4);
+               if (total + cnt < total)
+                       return -1;
+               total += cnt;
+       }
+       if (total < 0) {
+               bsdsocklib_seterrno(ctx, sb, 22); // EINVAL
+               return -1;
+       }
+       if (trap_get_long(ctx, msg + 16)) { // msg_control
+               if (trap_get_long(ctx, msg + 20) < 10) { // msg_controllen
+                       bsdsocklib_seterrno(ctx, sb, 22); // EINVAL
+                       return -1;
+               }
+               // control is not supported
+       }
+       uae_u8 *data = xmalloc(uae_u8, total);
+       if (!data) {
+               bsdsocklib_seterrno(ctx, sb, 55); // ENOBUFS
+               return -1;
+       }
+       uae_u8 *p = data;
+       for (int i = 0; i < iovlen; i++) {
+               uaecptr iovecp = iovec + i * 8;
+               int cnt = trap_get_long(ctx, iovecp + 4);
+               trap_get_bytes(ctx, p, trap_get_long(ctx, iovecp), cnt);
+               p += cnt;
+       }
+       uaecptr to = trap_get_long(ctx, msg + 0);
+       host_sendto(ctx, sb, sd, 0, data, total, flags, to, msg + 4);
+       xfree(data);
+       return sb->resultval;
 }
 
 static uae_u32 REGPARAM2 bsdsocklib_recvmsg (TrapContext *ctx)
 {
-       write_log (_T("bsdsocket: UNSUPPORTED: recvmsg()\n"));
-       return 0;
+       struct socketbase *sb = get_socketbase (ctx);
+       uaecptr sd = trap_get_dreg(ctx, 0);
+       uaecptr msg = trap_get_areg(ctx, 0);
+       uae_u32 flags = trap_get_dreg(ctx, 1);
+
+       SOCKET s = getsock (ctx, sb, sd + 1);
+       if (s == INVALID_SOCKET)
+               return -1;
+
+       uae_u32 msg_flags = trap_get_long(ctx, msg + 24);
+       int iovlen = trap_get_long(ctx, msg + 12);
+       int total = 0;
+       uaecptr iovec = trap_get_long(ctx, msg + 8);
+       for (int i = 0; i < iovlen; i++) {
+               uaecptr iovecp = iovec + i * 8;
+               int cnt = trap_get_long(ctx, iovecp + 4);
+               if (total + cnt < total)
+                       return -1;
+               total += cnt;
+       }
+       if (total < 0) {
+               bsdsocklib_seterrno(ctx, sb, 22); // EINVAL
+               return -1;
+       }
+       uae_u8 *data = xmalloc(uae_u8, total);
+       if (!data) {
+               bsdsocklib_seterrno(ctx, sb, 55); // ENOBUFS
+               return -1;
+       }
+       uaecptr from = trap_get_long(ctx, msg + 0);
+       host_recvfrom(ctx, sb, sd, 0, data, total, flags, from, msg + 4);
+       if (sb->resultval > 0) {
+               uae_u8 *p = data;
+               int total2 = 0;
+               total = sb->resultval;
+               for (int i = 0; i < iovlen && total > 0; i++) {
+                       uaecptr iovecp = iovec + i * 8;
+                       int cnt = trap_get_long(ctx, iovecp + 4);
+                       if (cnt > total)
+                               cnt = total;
+                       trap_put_bytes(ctx, p, trap_get_long(ctx, iovecp), cnt);
+                       p += cnt;
+                       total -= cnt;
+                       total2 += cnt;
+               }
+               if (total2 == sb->resultval)
+                       msg_flags |= MSG_EOR;
+               if (total > 0 && (sb->ftable[sd - 1] & SF_DGRAM))
+                       msg_flags |= MSG_TRUNC;
+               trap_put_long(ctx, msg + 24, msg_flags);
+       }
+       xfree(data);
+       return sb->resultval;
 }
 
 static uae_u32 REGPARAM2 bsdsocklib_gethostname (TrapContext *ctx)
index 7c9bf32aa1d56c413061791fc61e97d7c555e888..2de460ee0cfe63cfe78f0ef7abe6766f861dc5a5 100644 (file)
@@ -128,6 +128,7 @@ struct UAEBSDBase {
 /* socket properties */
 #define SF_BLOCKING 0x80000000
 #define SF_BLOCKINGINPROGRESS 0x40000000
+#define SF_DGRAM 0x20000000
 /* STBC_FDCALLBACK */
 #define FDCB_FREE  0
 #define FDCB_ALLOC 1
@@ -170,8 +171,8 @@ extern int host_socket (TrapContext *, SB, int, int, int);
 extern uae_u32 host_bind (TrapContext *, SB, uae_u32, uae_u32, uae_u32);
 extern uae_u32 host_listen (TrapContext *, SB, uae_u32, uae_u32);
 extern void host_accept (TrapContext *, SB, uae_u32, uae_u32, uae_u32);
-extern void host_sendto (TrapContext *, SB, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32);
-extern void host_recvfrom (TrapContext *, SB, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32);
+extern void host_sendto (TrapContext *, SB, uae_u32, uae_u32, uae_u8*, uae_u32, uae_u32, uae_u32, uae_u32);
+extern void host_recvfrom (TrapContext *, SB, uae_u32, uae_u32, uae_u8*, uae_u32, uae_u32, uae_u32, uae_u32);
 extern uae_u32 host_shutdown (SB, uae_u32, uae_u32);
 extern void host_setsockopt (SB, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32);
 extern uae_u32 host_getsockopt (TrapContext *, SB, uae_u32, uae_u32, uae_u32, uae_u32, uae_u32);
index 3fa3e29556c7a92a655834c018a8319f08fe8734..388d7a6c6b2ec6f5f5fbc884e7ba828f41746740 100644 (file)
@@ -124,11 +124,11 @@ static LRESULT CALLBACK SocketWindowProc(HWND hwnd, UINT message, WPARAM wParam,
 #define SOCKVER_MAJOR 2
 #define SOCKVER_MINOR 2
 
-#define SF_RAW_RAW             0x20000000
-#define SF_RAW_UDP             0x10000000
-#define SF_RAW_RUDP            0x08000000
-#define SF_RAW_RICMP   0x04000000
-#define SF_RAW_HDR             0x02000000
+#define SF_RAW_RAW             0x10000000
+#define SF_RAW_UDP             0x08000000
+#define SF_RAW_RUDP            0x04000000
+#define SF_RAW_RICMP   0x02000000
+#define SF_RAW_HDR             0x01000000
 
 typedef        struct ip_option_information {
        u_char Ttl;             /* Time To Live (used for traceroute) */
@@ -628,6 +628,9 @@ int host_socket(TrapContext *ctx, SB, int af, int type, int protocol)
        }
 
        sb->ftable[sd-1] = SF_BLOCKING;
+       if (faketype == SOCK_DGRAM || protocol != IPPROTO_TCP)
+               sb->ftable[sd-1] |= SF_DGRAM;
+
        ioctlsocket(s,FIONBIO,&nonblocking);
        BSDTRACE((_T(" -> Socket=%d %x\n"),sd,s));
 
@@ -818,7 +821,6 @@ struct threadsock_packet
                        uae_char *buf;
                        uae_char *realpt;
                        uae_u32 sd;
-                       uae_u32 msg;
                        uae_u32 len;
                        uae_u32 flags;
                        uae_u32 to;
@@ -1071,7 +1073,7 @@ struct udphdr {
 
 #endif
 
-void host_sendto (TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 to, uae_u32 tolen)
+void host_sendto (TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u8 *hmsg, uae_u32 len, uae_u32 flags, uae_u32 to, uae_u32 tolen)
 {
        SOCKET s;
        char *realpt;
@@ -1086,17 +1088,21 @@ void host_sendto (TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, ua
 
 
        if (to)
-               BSDTRACE((_T("sendto(%d,0x%x,%d,0x%x,0x%x,%d):%d-> "),sd,msg,len,flags,to,tolen,wscnt));
+               BSDTRACE((_T("sendto(%d,0x%x,%p,%d,0x%x,0x%x,%d):%d-> "),sd,msg,hmsg,len,flags,to,tolen,wscnt));
        else
-               BSDTRACE((_T("send(%d,0x%x,%d,%d):%d -> "),sd,msg,len,flags,wscnt));
+               BSDTRACE((_T("send(%d,0x%x,%p,%d,%d):%d -> "),sd,msg,hmsg,len,flags,wscnt));
 
        sd++;
        s = getsock(ctx, sb, sd);
 
        if (s != INVALID_SOCKET) {
-               if (!addr_valid (_T("host_sendto1"), msg, 4))
-                       return;
-               realpt = (char*)get_real_address (msg);
+               if (hmsg == NULL) {
+                       if (!addr_valid (_T("host_sendto1"), msg, 4))
+                               return;
+                       realpt = (char*)get_real_address (msg);
+               } else {
+                       realpt = (char*)hmsg;
+               }
 
                if (ISBSDTRACE) {
                        write_log(_T("FT %08x "), sb->ftable[sd - 1]);
@@ -1191,7 +1197,6 @@ void host_sendto (TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, ua
                        sockreq.sb = sb;
                        sockreq.params.sendto_s.buf = buf;
                        sockreq.params.sendto_s.sd = sd;
-                       sockreq.params.sendto_s.msg = msg;
                        sockreq.params.sendto_s.flags = flags;
                        sockreq.params.sendto_s.to = to;
                        sockreq.params.sendto_s.tolen = tolen;
@@ -1248,7 +1253,7 @@ error:
                BSDTRACE((_T("sendto %d:%d\n"),sb->resultval,wscnt));
 }
 
-void host_recvfrom(TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, uae_u32 flags, uae_u32 addr, uae_u32 addrlen)
+void host_recvfrom(TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u8 *hmsg, uae_u32 len, uae_u32 flags, uae_u32 addr, uae_u32 addrlen)
 {
        SOCKET s;
        uae_char *realpt;
@@ -1262,17 +1267,21 @@ void host_recvfrom(TrapContext *ctx, SB, uae_u32 sd, uae_u32 msg, uae_u32 len, u
        wscnt = ++wscounter;
 
        if (addr)
-               BSDTRACE((_T("recvfrom(%d,0x%x,%d,0x%x,0x%x,%d):%d -> "),sd,msg,len,flags,addr,get_long (addrlen),wscnt));
+               BSDTRACE((_T("recvfrom(%d,0x%x,%p,%d,0x%x,0x%x,%d):%d -> "),sd,msg,hmsg,len,flags,addr,get_long (addrlen),wscnt));
        else
-               BSDTRACE((_T("recv(%d,0x%x,%d,0x%x):%d -> "),sd,msg,len,flags,wscnt));
+               BSDTRACE((_T("recv(%d,0x%x,%p,%d,0x%x):%d -> "),sd,msg,hmsg,len,flags,wscnt));
 
        sd++;
        s = getsock(ctx, sb,sd);
 
        if (s != INVALID_SOCKET) {
-               if (!addr_valid (_T("host_recvfrom1"), msg, 4))
-                       return;
-               realpt = (char*)get_real_address (msg);
+               if (hmsg == NULL) {
+                       if (!addr_valid (_T("host_recvfrom1"), msg, 4))
+                               return;
+                       realpt = (char*)get_real_address (msg);
+               } else {
+                       realpt = (char*)hmsg;
+               }
 
                if (addr) {
                        if (!addr_valid (_T("host_recvfrom1"), addrlen, 4))