1001 lines
21 KiB
C
1001 lines
21 KiB
C
/*
|
|
Copyright (C) 1996-1997 Id Software, Inc.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
#include <go32.h>
|
|
#include "mpdosock.h"
|
|
|
|
//#include "types.h"
|
|
typedef unsigned char BYTE;
|
|
typedef unsigned short WORD;
|
|
typedef unsigned long DWORD;
|
|
|
|
//#include "lpc.h"
|
|
typedef struct {
|
|
short version; // version of LPC requested
|
|
short sizeOfArgs; // size of arguments
|
|
short service; // service # requested
|
|
char Data[1]; // data
|
|
} LPCData;
|
|
|
|
typedef struct {
|
|
short version; // LPC version
|
|
short sizeOfReturn; // return data size
|
|
short error; // any error codes
|
|
short noRet; // number of returns
|
|
char Data[1]; // data
|
|
} LPCReturn;
|
|
|
|
//#include "services.h"
|
|
#define MAXSOCKETS 20
|
|
|
|
// services
|
|
#define LPC_SOCKBIND 4
|
|
#define LPC_SOCKGETHOSTBYNAME 5
|
|
#define LPC_SOCKGETHOSTNAME 6
|
|
#define LPC_SOCKGETHOSTBYADDR 7
|
|
#define LPC_SOCKCLOSE 8
|
|
#define LPC_SOCKSOCKET 9
|
|
#define LPC_SOCKRECVFROM 10
|
|
#define LPC_SOCKSENDTO 11
|
|
#define LPC_SOCKIOCTL 12
|
|
#define LPC_SOCKGETSOCKNAME 13
|
|
#define LPC_SOCKFLUSH 14
|
|
#define LPC_SOCKSETOPT 15
|
|
#define LPC_SOCKGETLASTERROR 16
|
|
#define LPC_SOCKINETADDR 17
|
|
|
|
// htons, ntohs, htonl, ntohl implemented locally
|
|
|
|
// errors
|
|
#define LPC_UNRECOGNIZED_SERVICE -1
|
|
#define LPC_NOERROR 0
|
|
|
|
// structures for support
|
|
typedef struct {
|
|
SOCKET s;
|
|
int namelen;
|
|
char name[1];
|
|
} BindArgs;
|
|
|
|
typedef struct {
|
|
SOCKET s;
|
|
long cmd;
|
|
char data[1];
|
|
} IoctlArgs;
|
|
|
|
typedef struct {
|
|
int retVal;
|
|
int namelen;
|
|
char name[1];
|
|
} GetSockNameRet;
|
|
|
|
typedef GetSockNameRet GetHostNameRet;
|
|
|
|
typedef struct {
|
|
int retVal;
|
|
int h_addr_0; // that's the only important value
|
|
} GetHostByNameRet;
|
|
|
|
typedef struct {
|
|
int len;
|
|
int type;
|
|
char addr[1];
|
|
} GetHostByAddrArgs;
|
|
|
|
typedef struct {
|
|
int retVal;
|
|
char h_name[1]; // h_name is the only important value
|
|
} GetHostByAddrRet;
|
|
|
|
typedef struct {
|
|
SOCKET s;
|
|
int flags;
|
|
} RecvFromArgs;
|
|
|
|
typedef struct {
|
|
int retVal;
|
|
int errCode;
|
|
int len; // message len
|
|
struct sockaddr sockaddr;
|
|
int sockaddrlen;
|
|
char Data[1];
|
|
} RecvFromRet;
|
|
|
|
typedef struct {
|
|
SOCKET s;
|
|
int flags;
|
|
int len;
|
|
struct sockaddr sockaddr;
|
|
int sockaddrlen;
|
|
char Data[1];
|
|
} SendToArgs;
|
|
|
|
typedef struct {
|
|
int retVal;
|
|
int errCode;
|
|
} SendToRet;
|
|
|
|
typedef struct {
|
|
int bufflen;
|
|
SOCKET s;
|
|
int len;
|
|
int sockaddrlen;
|
|
struct sockaddr address;
|
|
char data[1];
|
|
} SocketChannelData;
|
|
|
|
typedef struct {
|
|
int af;
|
|
int type;
|
|
int protocol;
|
|
} SocketArgs;
|
|
|
|
typedef struct {
|
|
SOCKET s;
|
|
int len;
|
|
int flags;
|
|
int addrlen;
|
|
struct sockaddr addr;
|
|
char data[1];
|
|
} WinSockData;
|
|
|
|
typedef struct {
|
|
SOCKET s;
|
|
int level;
|
|
int optname;
|
|
int optlen;
|
|
char optval[1];
|
|
} SetSockOptArgs;
|
|
|
|
typedef struct {
|
|
SOCKET sock[MAXSOCKETS];
|
|
} SocketMap;
|
|
|
|
//#include "rtq.h"
|
|
#define RTQ_NODE struct rtq_node
|
|
|
|
RTQ_NODE
|
|
{
|
|
RTQ_NODE *self; // Ring zero address of this node
|
|
RTQ_NODE *left; // Ring zero address of preceding node
|
|
RTQ_NODE *right; // Ring zero address of succeding node
|
|
BYTE * rtqDatum; // Ring 3 Datum of Buffer (start of preface)
|
|
BYTE * rtqInsert; // Ring 3 insertion position
|
|
WORD rtqLen; // Length of buffer, excluding preface
|
|
WORD rtqUpCtr; // Up Counter of bytes used so far
|
|
WORD rtqQCtr; // number of nodes attached
|
|
WORD padding; // DWORD alignment
|
|
};
|
|
|
|
#define RTQ_PARAM_MOVENODE struct rtq_param_movenode
|
|
RTQ_PARAM_MOVENODE
|
|
{
|
|
WORD rtqFromDQ;
|
|
WORD rtqToDQ;
|
|
};
|
|
|
|
RTQ_NODE* rtq_fetch(RTQ_NODE*, RTQ_NODE*); // To, From
|
|
|
|
//#include "mplib.h"
|
|
// give up time slice
|
|
void Yield(void);
|
|
void MGenWakeupDll(void);
|
|
|
|
// post a message to win32 side
|
|
void PostWindowsMessage(void);
|
|
|
|
// get # of items on qNo
|
|
int MGenGetQueueCtr(int qNo);
|
|
|
|
// move first node from qFrom to qTo
|
|
RTQ_NODE *MGenMoveTo(int qFrom, int qTo);
|
|
|
|
// get first node from q
|
|
RTQ_NODE *MGenGetNode(int q);
|
|
|
|
// get master node, returning size of RTQ_NODE for size verification
|
|
RTQ_NODE *MGenGetMasterNode(unsigned *size);
|
|
|
|
// move all nodes from qFrom to qTo
|
|
RTQ_NODE *MGenFlushNodes(int qFrom, int qTo);
|
|
|
|
// count number of nodes in queues designated by bitmask
|
|
// lowerOrderBits == 0..31, upperOrderBits == 32-63
|
|
int MGenMCount(unsigned lowerOrderBits, unsigned upperOrderBits);
|
|
|
|
// perform consistency check on chunnel address space
|
|
int MGenSanityCheck(void);
|
|
|
|
#include <stdio.h>
|
|
#include <sys/farptr.h>
|
|
|
|
extern short flat_selector;
|
|
|
|
#define SOCKET_MAP_QUEUE 41
|
|
|
|
#define IDLE_QUEUE 44
|
|
#define REC_QUEUE 45
|
|
#define SEND_QUEUE 46
|
|
|
|
// queue sizes
|
|
#define FREEQBASE 58
|
|
#define FREEQ64 58
|
|
#define FREEQ128 59
|
|
#define FREEQ256 60
|
|
#define FREEQ512 61
|
|
#define FREEQ1024 62
|
|
#define FREEQ2048 63
|
|
|
|
#define NFREEQ 6
|
|
|
|
#define QLIMIT 10
|
|
|
|
#define PRIVATEQ 50
|
|
|
|
#define FARPKL(x) (_farnspeekl((unsigned long) x))
|
|
#define FARPKB(x) (_farnspeekb((unsigned long) x))
|
|
#define FARPKS(x) (_farnspeekw((unsigned long) x))
|
|
|
|
#define FARPOKL(x, y) (_farnspokel((unsigned long) x, (unsigned long) y))
|
|
#define FARPOKB(x, y) (_farnspokeb((unsigned long) x, (unsigned char) y))
|
|
|
|
int Qsizes[] = { 64, 128, 256, 512, 1024, 2048 };
|
|
|
|
int SocketError = 0;
|
|
|
|
SocketMap *SockMap;
|
|
|
|
#define HOSTENT_ALIAS_LIMIT 5
|
|
#define HOSTENT_STRLEN_LIMIT 50
|
|
#define HOSTENT_ADDR_LIST_LIMIT 5
|
|
|
|
struct hostent HostEnt;
|
|
|
|
char HostEnt_hname[HOSTENT_STRLEN_LIMIT];
|
|
char *HostEnt_h_aliases[HOSTENT_ALIAS_LIMIT];
|
|
char HostEnt_names[HOSTENT_ALIAS_LIMIT][HOSTENT_STRLEN_LIMIT];
|
|
struct in_addr* HostEnt_addr_list[HOSTENT_ADDR_LIST_LIMIT];
|
|
struct in_addr HostEnt_addrs[HOSTENT_ADDR_LIST_LIMIT];
|
|
|
|
void
|
|
fmemcpyto(void *to, const void *from, int length)
|
|
{
|
|
movedata(_my_ds(), (unsigned)from, flat_selector, (unsigned)to, length);
|
|
}
|
|
|
|
void
|
|
fmemcpyfrom(void *to, const void *from, int length)
|
|
{
|
|
movedata(flat_selector, (unsigned)from, _my_ds(), (unsigned)to, length);
|
|
}
|
|
|
|
void
|
|
fstrcpyto(char *to, const char *from)
|
|
{
|
|
while (*from) {
|
|
FARPOKB(to, *from);
|
|
to++; from++;
|
|
}
|
|
FARPOKB(to, 0);
|
|
}
|
|
|
|
void
|
|
fstrncpyto(char *to, const char *from, int len)
|
|
{
|
|
while (*from && len) {
|
|
FARPOKB(to, *from);
|
|
to++; from++; len--;
|
|
}
|
|
FARPOKB(to, 0);
|
|
}
|
|
|
|
void
|
|
fstrcpyfrom(char *to, const char *from)
|
|
{
|
|
while (FARPKB(from)) {
|
|
*to = FARPKB(from);
|
|
from++; to++;
|
|
}
|
|
*to = 0;
|
|
}
|
|
|
|
void
|
|
fstrncpyfrom(char *to, const char *from, int len)
|
|
{
|
|
while (FARPKB(from) && len) {
|
|
*to = FARPKB(from);
|
|
from++; to++; len--;
|
|
}
|
|
*to = 0;
|
|
}
|
|
|
|
void
|
|
GetSocketMap(void)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(SOCKET_MAP_QUEUE);
|
|
|
|
SockMap = (SocketMap *) FARPKL(&n->rtqDatum);
|
|
}
|
|
|
|
void *
|
|
GetFreeBufferToQueue(int q, int bufSize)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < NFREEQ; i++) {
|
|
if (Qsizes[i] >= bufSize && MGenGetQueueCtr(i+FREEQBASE)) {
|
|
RTQ_NODE *n = MGenMoveTo(i+FREEQBASE, q);
|
|
if (!n)
|
|
continue;
|
|
FARPOKL(&n->rtqUpCtr, bufSize);
|
|
return (void *) FARPKL(&n->rtqDatum);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
FreeBufferFromQueue(int q)
|
|
{
|
|
int i;
|
|
RTQ_NODE *n = MGenGetNode(q);
|
|
|
|
for (i = 0; i < NFREEQ; i++) {
|
|
if (Qsizes[i] == FARPKS(&n->rtqLen)) {
|
|
MGenMoveTo(q, i+FREEQBASE);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
SetLPCData(LPCData *lpc)
|
|
{
|
|
|
|
FARPOKL(&(lpc->version), 1);
|
|
FARPOKL(&(lpc->sizeOfArgs), 0);
|
|
FARPOKL(&(lpc->service), 0);
|
|
}
|
|
|
|
int
|
|
bind(SOCKET s, const struct sockaddr *name, int namelen)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
BindArgs *bargs;
|
|
int retVal;
|
|
|
|
_farsetsel(flat_selector);
|
|
SocketError = 0;
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKBIND);
|
|
bargs = (BindArgs *) p->Data;
|
|
FARPOKL(&bargs->s, s);
|
|
FARPOKL(&bargs->namelen, namelen);
|
|
fmemcpyto(bargs->name, name, namelen);
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
int
|
|
closesocket(SOCKET s)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
int retVal;
|
|
|
|
_farsetsel(flat_selector);
|
|
SocketError = 0;
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKCLOSE);
|
|
FARPOKL(p->Data, s);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void
|
|
ZapHostEnt()
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
void
|
|
ReconstructHostEnt(struct hostent *s, void *flattened)
|
|
{
|
|
struct hostent *old = (struct hostent *) flattened;
|
|
int i;
|
|
char **ptr;
|
|
|
|
|
|
s->h_name = HostEnt_hname;
|
|
fstrncpyfrom(s->h_name, (char *) FARPKL(&old->h_name), HOSTENT_STRLEN_LIMIT-1);
|
|
s->h_name[HOSTENT_STRLEN_LIMIT-1] = 0;
|
|
|
|
s->h_aliases = HostEnt_h_aliases;
|
|
ptr = (char **) FARPKL(&old->h_aliases);
|
|
for (i = 0; i < (HOSTENT_ALIAS_LIMIT-1) && FARPKL(ptr); i++, ptr++) {
|
|
s->h_aliases[i] = HostEnt_names[i];
|
|
// fstrncpyfrom(s->h_aliases[i], (void *) FARPKL(ptr), HOSTENT_STRLEN_LIMIT-1);
|
|
s->h_aliases[i][HOSTENT_STRLEN_LIMIT-1] = 0;
|
|
}
|
|
s->h_aliases[i] = 0;
|
|
|
|
s->h_addrtype = FARPKS(&old->h_addrtype);
|
|
s->h_length = FARPKS(&old->h_length);
|
|
|
|
if (FARPKS(&old->h_length) != sizeof(struct in_addr)) {
|
|
printf("Error!\n");
|
|
exit(0);
|
|
}
|
|
|
|
s->h_addr_list = (char **) HostEnt_addr_list;
|
|
ptr = (char **) FARPKL(&old->h_addr_list);
|
|
for (i = 0; i < (HOSTENT_ADDR_LIST_LIMIT - 1) && FARPKL(ptr); i++, ptr++) {
|
|
s->h_addr_list[i] = (char *) &(HostEnt_addrs[i]);
|
|
fmemcpyfrom(s->h_addr_list[i], (void *) FARPKL(ptr), s->h_length);
|
|
}
|
|
s->h_addr_list[i] = 0;
|
|
}
|
|
|
|
|
|
int
|
|
getsockname(SOCKET s, struct sockaddr *name, int *namelen)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
GetSockNameRet *ret;
|
|
int retVal;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKGETSOCKNAME);
|
|
FARPOKL(p->Data, s);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
ret = (GetSockNameRet *) r->Data;
|
|
retVal = FARPKL(&ret->retVal);
|
|
fmemcpyfrom(name, ret->name, FARPKL(&ret->namelen));
|
|
*namelen = FARPKL(&ret->namelen);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
int
|
|
gethostname(char *name, int namelen)
|
|
{
|
|
RTQ_NODE *n;
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
GetHostNameRet *ret;
|
|
int retVal;
|
|
char *s;
|
|
|
|
_farsetsel(flat_selector);
|
|
SocketError = 0;
|
|
n = (RTQ_NODE *) MGenGetNode(IDLE_QUEUE);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service,LPC_SOCKGETHOSTNAME);
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = (RTQ_NODE *) (MGenGetNode(REC_QUEUE))) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
ret = (GetHostNameRet *) r->Data;
|
|
|
|
retVal = FARPKL(&ret->retVal);
|
|
|
|
s = ret->name;
|
|
|
|
fstrncpyfrom(name, s, namelen);
|
|
|
|
#if 0
|
|
len = strlen(ret->name);
|
|
|
|
if (len > namelen)
|
|
memcpy(name, ret->name, ret->namelen);
|
|
else
|
|
strcpy(name, ret->name);
|
|
#endif
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
struct hostent *
|
|
gethostbyname(const char *name)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
struct hostent *retVal;
|
|
|
|
_farsetsel(flat_selector);
|
|
SocketError = 0;
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKGETHOSTBYNAME);
|
|
fstrcpyto(p->Data, name);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
retVal = (struct hostent *) r->Data;
|
|
|
|
if (FARPKL(&retVal->h_name) == 0) {
|
|
retVal = 0;
|
|
} else {
|
|
ZapHostEnt();
|
|
ReconstructHostEnt(&HostEnt, (void *) retVal);
|
|
retVal = &HostEnt;
|
|
}
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
struct hostent *
|
|
gethostbyaddr(const char *addr, int len, int type)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
GetHostByAddrArgs *args;
|
|
struct hostent *retVal;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKGETHOSTBYADDR);
|
|
args = (GetHostByAddrArgs *) p->Data;
|
|
FARPOKL(&args->len, len);
|
|
FARPOKL(&args->type, type);
|
|
fmemcpyto(args->addr, addr, len);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
retVal = (struct hostent *) r->Data;
|
|
|
|
if (FARPKL(&retVal->h_name) == 0) {
|
|
retVal = 0;
|
|
} else {
|
|
ZapHostEnt();
|
|
|
|
ReconstructHostEnt(&HostEnt, (void *) retVal);
|
|
retVal = &HostEnt;
|
|
}
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
SOCKET
|
|
socket(int af, int type, int protocol)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
SocketArgs *args;
|
|
int retVal;
|
|
|
|
_farsetsel(flat_selector);
|
|
SocketError = 0;
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKSOCKET);
|
|
args = (SocketArgs *) p->Data;
|
|
FARPOKL(&args->af, af);
|
|
FARPOKL(&args->type, type);
|
|
FARPOKL(&args->protocol, protocol);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void
|
|
sockets_flush(void)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
|
|
SocketError = 0;
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKFLUSH);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
}
|
|
|
|
int
|
|
recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from,
|
|
int *fromlen)
|
|
{
|
|
int i;
|
|
RTQ_NODE *n;
|
|
WinSockData *data;
|
|
int bytesRead;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
if (!SockMap)
|
|
GetSocketMap();
|
|
|
|
for (i = 0; i < MAXSOCKETS; i++) {
|
|
if (FARPKL(&(SockMap->sock[i])) == s)
|
|
break;
|
|
}
|
|
|
|
if (i == MAXSOCKETS)
|
|
return SOCKET_ERROR;
|
|
|
|
// pick up node
|
|
n = MGenGetNode(i);
|
|
if (n == 0) {
|
|
SocketError = WSAEWOULDBLOCK;
|
|
return -1;
|
|
}
|
|
|
|
data = (WinSockData *) FARPKL(&n->rtqDatum);
|
|
bytesRead = FARPKL(&data->len);
|
|
|
|
if (from) {
|
|
fmemcpyfrom(from, &data->addr, sizeof(struct sockaddr));
|
|
}
|
|
|
|
if (fromlen) {
|
|
*fromlen = FARPKL(&data->addrlen);
|
|
}
|
|
|
|
fmemcpyfrom(buf, data->data, len > bytesRead ? bytesRead : len);
|
|
|
|
if ((flags & MSG_PEEK) == 0) {
|
|
FreeBufferFromQueue(i);
|
|
}
|
|
|
|
return bytesRead;
|
|
}
|
|
|
|
int
|
|
sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)
|
|
{
|
|
int i;
|
|
int outQ;
|
|
WinSockData *data;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
if (!SockMap)
|
|
GetSocketMap();
|
|
|
|
for (i = 0; i < MAXSOCKETS; i++) {
|
|
if (FARPKL(&SockMap->sock[i]) == s) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == MAXSOCKETS) {
|
|
SocketError = WSAENOTSOCK;
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
outQ = i + MAXSOCKETS;
|
|
|
|
if (MGenGetQueueCtr(outQ) >= QLIMIT) {
|
|
SocketError = WSAEWOULDBLOCK;
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
data = GetFreeBufferToQueue(PRIVATEQ, len + sizeof(WinSockData));
|
|
|
|
if (!data) {
|
|
SocketError = WSAEWOULDBLOCK;
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
FARPOKL(&data->s, s);
|
|
FARPOKL(&data->len, len);
|
|
if (to) {
|
|
fmemcpyto(&data->addr, to, tolen);
|
|
FARPOKL(&data->addrlen, tolen);
|
|
} else {
|
|
FARPOKL(&data->addrlen, 0);
|
|
}
|
|
|
|
FARPOKL(&data->flags, flags);
|
|
|
|
fmemcpyto(data->data, buf, len);
|
|
|
|
MGenMoveTo(PRIVATEQ, outQ);
|
|
|
|
return len;
|
|
}
|
|
|
|
int
|
|
ioctlsocket(SOCKET s, long cmd, unsigned long *argp)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
IoctlArgs *args;
|
|
int retVal;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKIOCTL);
|
|
args = (IoctlArgs *) p->Data;
|
|
FARPOKL(&args->s, s);
|
|
FARPOKL(&args->cmd, cmd);
|
|
|
|
switch(cmd) {
|
|
case FIONBIO:
|
|
FARPOKL(args->data, *argp);
|
|
break;
|
|
default:
|
|
return SOCKET_ERROR;
|
|
}
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
int
|
|
setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
SetSockOptArgs *args;
|
|
int retVal;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKSETOPT);
|
|
args = (SetSockOptArgs *) p->Data;
|
|
FARPOKL(&args->s, s);
|
|
FARPOKL(&args->level, level);
|
|
FARPOKL(&args->optname, optname);
|
|
FARPOKL(&args->optlen, optlen);
|
|
fmemcpyto(args->optval, optval, optlen);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
int
|
|
WSAGetLastError(void)
|
|
{
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
int retVal;
|
|
|
|
|
|
_farsetsel(flat_selector);
|
|
if (SocketError) {
|
|
int err = SocketError;
|
|
|
|
SocketError = 0;
|
|
return err;
|
|
}
|
|
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKGETLASTERROR);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
unsigned long inet_addr(const char *cp)
|
|
{
|
|
int ret;
|
|
unsigned int ha1, ha2, ha3, ha4;
|
|
unsigned long ipaddr;
|
|
|
|
ret = sscanf(cp, "%d.%d.%d.%d", &ha1, &ha2, &ha3, &ha4);
|
|
if (ret != 4)
|
|
return -1;
|
|
ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
|
|
return ipaddr;
|
|
#if 0
|
|
RTQ_NODE *n = MGenGetNode(IDLE_QUEUE);
|
|
LPCData *p;
|
|
LPCReturn *r;
|
|
int retVal;
|
|
|
|
SocketError = 0;
|
|
_farsetsel(flat_selector);
|
|
p = (LPCData *) FARPKL(&n->rtqDatum);
|
|
SetLPCData(p);
|
|
FARPOKL(&p->service, LPC_SOCKINETADDR);
|
|
|
|
fstrcpyto(p->Data, cp);
|
|
|
|
MGenMoveTo(IDLE_QUEUE, SEND_QUEUE);
|
|
PostWindowsMessage();
|
|
|
|
while ((n = MGenGetNode(REC_QUEUE)) == 0)
|
|
Yield();
|
|
|
|
r = (LPCReturn *) FARPKL(&n->rtqDatum);
|
|
|
|
if (FARPKS(&r->error) != LPC_NOERROR) {
|
|
return -1;
|
|
}
|
|
|
|
retVal = FARPKL(r->Data);
|
|
|
|
// get ready for next call
|
|
MGenMoveTo(REC_QUEUE, IDLE_QUEUE);
|
|
|
|
return retVal;
|
|
#endif
|
|
}
|
|
|
|
char *inet_ntoa (struct in_addr in)
|
|
{
|
|
static char buf [32];
|
|
|
|
sprintf(buf, "%u.%u.%u.%u", in.S_un.S_un_b.s_b1, in.S_un.S_un_b.s_b2, in.S_un.S_un_b.s_b3, in.S_un.S_un_b.s_b4);
|
|
return buf;
|
|
}
|