From: Toni Wilen Date: Sat, 1 Apr 2017 17:09:03 +0000 (+0300) Subject: Implement sendmsg() and recvmsg() X-Git-Tag: 3500~71 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=47c767959a4a382baf857ba6db8b86406b747a19;p=francis%2Fwinuae.git Implement sendmsg() and recvmsg() --- diff --git a/bsdsocket.cpp b/bsdsocket.cpp index 10345a53..74161bb9 100644 --- a/bsdsocket.cpp +++ b/bsdsocket.cpp @@ -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) diff --git a/include/bsdsocket.h b/include/bsdsocket.h index 7c9bf32a..2de460ee 100644 --- a/include/bsdsocket.h +++ b/include/bsdsocket.h @@ -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); diff --git a/od-win32/bsdsock.cpp b/od-win32/bsdsock.cpp index 3fa3e295..388d7a6c 100644 --- a/od-win32/bsdsock.cpp +++ b/od-win32/bsdsock.cpp @@ -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))