#include "bsdsocket.h"
#include "threaddep/thread.h"
#include "native2amiga.h"
+#include "debug.h"
#ifdef BSDSOCKET
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;
}
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;
}
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;
}
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;
}
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)
/* socket properties */
#define SF_BLOCKING 0x80000000
#define SF_BLOCKINGINPROGRESS 0x40000000
+#define SF_DGRAM 0x20000000
/* STBC_FDCALLBACK */
#define FDCB_FREE 0
#define FDCB_ALLOC 1
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);
#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) */
}
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));
uae_char *buf;
uae_char *realpt;
uae_u32 sd;
- uae_u32 msg;
uae_u32 len;
uae_u32 flags;
uae_u32 to;
#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;
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]);
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;
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;
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))