blob: 805271ef70d193f08d762f60258bffb40560f1e8 [file] [log] [blame]
/* wrapsock.c provides access to socket related system calls.
Copyright (C) 2008-2022 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 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 3, or (at your option)
any later version.
GNU Modula-2 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.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#include "config.h"
#include <stdbool.h>
#define EXPORT(FUNC) m2iso ## _wrapsock_ ## FUNC
#define IMPORT(MODULE,FUNC) m2iso ## _ ## MODULE ## _ ## FUNC
#define M2EXPORT(FUNC) m2iso ## _M2_wrapsock_ ## FUNC
#define M2LIBNAME "m2iso"
/* This module should be rewritten to use C++. */
typedef void (*proc_con) (int, char **, char **);
typedef void (*proc_dep) (void);
extern void m2iso_M2RTS_RequestDependant (const char *modulename, const char *libname, const char *dependancy);
extern void m2iso_M2RTS_RegisterModule (const char *modulename, const char *libname,
proc_con init, proc_con fini, proc_dep dependencies);
#if defined(HAVE_SYS_TYPES_H)
#include "sys/types.h"
#endif
#if defined(HAVE_SYS_SOCKET_H)
#include "sys/socket.h"
#endif
#if defined(HAVE_NETINET_IN_H)
#include "netinet/in.h"
#endif
#if defined(HAVE_NETDB_H)
#include "netdb.h"
#endif
#if defined(HAVE_UNISTD_H)
#include "unistd.h"
#endif
#if defined(HAVE_SIGNAL_H)
#include "signal.h"
#endif
#if defined(HAVE_SYS_ERRNO_H)
#include "sys/errno.h"
#endif
#if defined(HAVE_ERRNO_H)
#include "errno.h"
#endif
#if defined(HAVE_MALLOC_H)
#include "malloc.h"
#endif
#if defined(HAVE_MALLOC_H)
#include "signal.h"
#endif
#if defined(HAVE_STRING_H)
#include "string.h"
#endif
#if defined(HAVE_STDLIB_H)
#include "stdlib.h"
#endif
#include "ChanConsts.h"
#define MAXHOSTNAME 1024
#define MAXPBBUF 1024
#if defined(HAVE_NETINET_IN_H)
typedef struct
{
char hostname[MAXHOSTNAME];
struct hostent *hp;
struct sockaddr_in sa;
int sockFd;
int portNo;
int hasChar;
char pbChar[MAXPBBUF];
} clientInfo;
static openResults clientConnect (clientInfo *c);
/* clientOpen - returns an ISO Modula-2 OpenResult. It attempts to
connect to: hostname:portNo. If successful then the data
structure, c, will have its fields initialized. */
openResults
EXPORT(clientOpen) (clientInfo *c, char *hostname, unsigned int length,
int portNo)
{
/* remove SIGPIPE which is raised on the server if the client is killed. */
signal (SIGPIPE, SIG_IGN);
c->hp = gethostbyname (hostname);
if (c->hp == NULL)
return noSuchFile;
memset ((void *)&c->sa, 0, sizeof (c->sa));
c->sa.sin_family = AF_INET;
memcpy ((void *)&c->sa.sin_addr, (void *)c->hp->h_addr, c->hp->h_length);
c->portNo = portNo;
c->sa.sin_port = htons (portNo);
c->hasChar = 0;
/* Open a TCP socket (an Internet stream socket) */
c->sockFd = socket (c->hp->h_addrtype, SOCK_STREAM, 0);
return clientConnect (c);
}
/* clientOpenIP - returns an ISO Modula-2 OpenResult. It attempts to
connect to: ipaddress:portNo. If successful then the data
structure, c, will have its fields initialized. */
openResults
EXPORT(clientOpenIP) (clientInfo *c, unsigned int ip, int portNo)
{
/* remove SIGPIPE which is raised on the server if the client is killed. */
signal (SIGPIPE, SIG_IGN);
memset ((void *)&c->sa, 0, sizeof (c->sa));
c->sa.sin_family = AF_INET;
memcpy ((void *)&c->sa.sin_addr, (void *)&ip, sizeof (ip));
c->portNo = portNo;
c->sa.sin_port = htons (portNo);
/* Open a TCP socket (an Internet stream socket) */
c->sockFd = socket (PF_INET, SOCK_STREAM, 0);
return clientConnect (c);
}
/* clientConnect - returns an ISO Modula-2 OpenResult once a connect
has been performed. If successful the clientInfo will include the
file descriptor ready for read/write operations. */
static openResults
clientConnect (clientInfo *c)
{
if (connect (c->sockFd, (struct sockaddr *)&c->sa, sizeof (c->sa)) < 0)
return noSuchFile;
return opened;
}
/* getClientPortNo - returns the portNo from structure, c. */
int
EXPORT(getClientPortNo) (clientInfo *c)
{
return c->portNo;
}
/* getClientHostname - fills in the hostname of the server the to
which the client is connecting. */
void
EXPORT(getClientHostname) (clientInfo *c, char *hostname, unsigned int high)
{
strncpy (hostname, c->hostname, high + 1);
}
/* getClientSocketFd - returns the sockFd from structure, c. */
int
EXPORT(getClientSocketFd) (clientInfo *c)
{
return c->sockFd;
}
/* getClientIP - returns the sockFd from structure, s. */
unsigned int
EXPORT(getClientIP) (clientInfo *c)
{
#if 0
printf("client ip = %s\n", inet_ntoa (c->sa.sin_addr.s_addr));
#endif
return c->sa.sin_addr.s_addr;
}
/* getPushBackChar returns true if a pushed back character is
available. */
bool
EXPORT(getPushBackChar) (clientInfo *c, char *ch)
{
if (c->hasChar > 0)
{
c->hasChar--;
*ch = c->pbChar[c->hasChar];
return true;
}
return false;
}
/* setPushBackChar returns true if it is able to push back a
character. */
bool
EXPORT(setPushBackChar) (clientInfo *c, char ch)
{
if (c->hasChar == MAXPBBUF)
return false;
c->pbChar[c->hasChar] = ch;
c->hasChar++;
return true;
}
/* getSizeOfClientInfo - returns the sizeof (opaque data type). */
unsigned int
EXPORT(getSizeOfClientInfo) (void)
{
return sizeof (clientInfo);
}
#endif
/* GNU Modula-2 linking hooks. */
void
M2EXPORT(init) (int, char **, char **)
{
}
void
M2EXPORT(fini) (int, char **, char **)
{
}
void
M2EXPORT(dep) (void)
{
}
void __attribute__((__constructor__))
M2EXPORT(ctor) (void)
{
m2iso_M2RTS_RegisterModule ("wrapsock", M2LIBNAME,
M2EXPORT(init), M2EXPORT(fini),
M2EXPORT(dep));
}