psptcpux.c

来自「db.* (pronounced dee-be star) is an adva」· C语言 代码 · 共 1,005 行 · 第 1/2 页

C
1,005
字号
/*************************************************************************** *                                                                         * * db.linux                                                                * * open source platform support package for Linux (tm)                     * *                                                                         * * Copyright (c) 2000 Centura Software Corporation. All rights reseved.    * *                                                                         * * Use of this software, whether in source code format, or in executable,  * * binary object code form, is governed by the CENTURA OPEN SOURCE LICENSE * * which is fully described in the LICENSE.TXT file, included within this  * * distribution of source code files.                                      * *                                                                         * **************************************************************************//* psptcpux.c - Contains the TCP/IP and Unix Domain sockets functions for                UNIX */#if defined(QNX) || defined(SCO3)#define NO_UNIX_DOMAIN#endif#include <unistd.h>#include <netdb.h>#include <sys/time.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#if defined(QNX)#include <sys/select.h>#endif#if !defined(NO_UNIX_DOMAIN)#include <sys/un.h>#endif#if !defined(INADDR_NONE)#define INADDR_NONE ((unsigned long) -1)#endif#include "psp.h"#include "pspint.h"typedef union {    struct sockaddr_in in;    struct sockaddr_un un;} saddr;typedef struct {    int    sock;           /* connection socket *//*    void (*pipefcn)(int);*/  /* location to hold current SIGPIPE function */    char  *tokfile;        /* token file for local connect through IP */    saddr  addrinfo;} LMC_CLIENT_DATA;typedef struct {    fd_set            FDS;    fd_set            holdFDS;    int               count;    int               sock1;    int               sock2;    char             *tokfile;    int               numclients;    int               maxclients;    LMC_CLIENT_DATA **clients;} LMC_SERVER_DATA;static int   psp_socket_checkid(const char *);static void  psp_socket_disconnect(void *);static void *psp_socket_waitmsg(void *, long);static void  psp_socket_stoplisten(void *);static void  psp_socket_disconclient(void *, void *);static void  psp_socket_info(const void *, char *, char *, char *);static int   psp_tcp_connect(const char *, const char *, const char *, void **);static int   psp_tcp_listen(const char *, const char *, int, void **);static int   psp_tcp_send(const void *, size_t, const void *);static int   psp_tcp_receive(void **, size_t *, const void *);LOCKCOMM_FCNS tcp_lockcomm = {    "TCP/IP sockets",    psp_tcp_send,    psp_tcp_receive,    psp_socket_checkid,    psp_tcp_connect,    psp_socket_disconnect,    psp_tcp_listen,    psp_socket_waitmsg,    psp_socket_stoplisten,    psp_socket_disconclient,    psp_socket_info};static int tcp_connect(const char *, const char *, int);static int tcp_listen(const char *);#if !defined(NO_UNIX_DOMAIN)static int   psp_ip_connect(const char *, const char *, const char *, void **);static int   psp_ip_listen(const char *, const char *, int, void **);static int   psp_ip_send(const void *, size_t, const void *);static int   psp_ip_receive(void **, size_t *, const void *);LOCKCOMM_FCNS ip_lockcomm = {    "Unix Domain sockets",    psp_ip_send,    psp_ip_receive,    psp_socket_checkid,    psp_ip_connect,    psp_socket_disconnect,    psp_ip_listen,    psp_socket_waitmsg,    psp_socket_stoplisten,    psp_socket_disconclient,    psp_socket_info};static int ip_connect(const char *, const char *, char *, int);static int ip_listen(const char *, const char *, char *);#endifstatic int socket_send(const MSG_HDR *, const void *, int, int);static int socket_receive(void *, int, int);/* ==========================================================================   Check to see if TCP/IP is available*/int psp_tcp_avail(    int            *flags,    LOCKCOMM_FCNS **fcns){    *flags = PSP_FLAG_NETWORK_ORDER /* | PSP_FLAG_TAF_CLOSE */;    *fcns = &tcp_lockcomm;    return PSP_OKAY;}/* ==========================================================================   Verify that the id is valid for this transport*/static int psp_socket_checkid(    const char *id){    return PSP_OKAY;}/* ==========================================================================   TCP/IP specific connection*/static int tcp_connect(    const char *name,    const char *port,    int         timeout){    int                ii;    int                sock;    int                addr_len;    unsigned long      addr;    struct hostent    *host;    struct servent    *service;    struct protoent   *protocol;    struct sockaddr   *sockaddr = NULL;    struct sockaddr_in sockaddr_in;    sockaddr = (struct sockaddr *) &sockaddr_in;    addr_len = sizeof(struct sockaddr_in);    host = gethostbyname(name);    endhostent();    if (host!= NULL) {        sockaddr_in.sin_family = host->h_addrtype;        memcpy(&sockaddr_in.sin_addr, host->h_addr, host->h_length);    }    else if ((addr = inet_addr(name)) != INADDR_NONE) {        sockaddr_in.sin_family = AF_INET;        sockaddr_in.sin_addr.s_addr = addr;    }    else {        /* TBD: Log out error *//*        printf("cannot create valid sockaddr: check lock manager name\n"); */        return -1;    }    /* We have found the TCP/IP host that the lock manager is on, now       figure out the port number. */    protocol = getprotobyname("tcp");    endprotoent();    sockaddr_in.sin_port = 0;    if (port)        sockaddr_in.sin_port = htons(atoi(port));    if (sockaddr_in.sin_port == 0) {        if (port && (service = getservbyname(port, "tcp")) != NULL)            sockaddr_in.sin_port = service->s_port;        else if ((service = getservbyname("db.star", "tcp")) != NULL)            sockaddr_in.sin_port = service->s_port;        endservent();        /* If no port was found, try the default */        if (sockaddr_in.sin_port == 0)            sockaddr_in.sin_port = htons(1523);    }    sock = socket(sockaddr->sa_family, SOCK_STREAM, protocol->p_proto);    if (sock == -1)        return -1;    for (ii = 0; ii < timeout; ii++) {        if (connect(sock, sockaddr, addr_len) != -1)            break;        /* TBD: Log out error *//*        printf("ip connect fail: %s (%d)\n", strerror(errno), errno); */        psp_sleep(1);    }    if (ii == timeout) {        close(sock);        return -1;    }    return sock;}/* ==========================================================================   Open a TCP/IP connection to the lock manager*/static int psp_tcp_connect(    const char *lockmgr,    const char *tmp,    const char *id,    void      **data){    int              sock = -1;    char            *name;    char            *portpos;    char             tokfile[80] = "";    LMC_CLIENT_DATA *lmcdata;    /* TBD: Need to get timeout value (net_timeout) from db.star.ini. */    int                timeout = 5;#if defined(QNX)    name = psp_strdup(lockmgr + ((lockmgr[0] == '/') ? 1 : 0), 0);#else    name = psp_strdup(lockmgr, 0);#endif    if ((portpos = strchr(name, ':')) != NULL)        *portpos++ = '\0';#if !defined(NO_UNIX_DOMAIN)    /* If there is no ':' in the lock manager name then it is probably       running locally.  Try to connect to it using a UNIX domain socket,       as this is faster than TCP/IP. */    if (!portpos)        sock = ip_connect(name, tmp, tokfile, timeout);#endif    /* If the attempt to connect to a local lock manager failed, or if the       lock manager name contains a ':' then it must be running on a       remote machine - use a TCP/IP socket. */    if (sock == -1)        sock = tcp_connect(name, portpos, timeout);    psp_freeMemory(name, 0);    if (sock == -1)        return PSP_FAILED;    /* Allocate control data buffer */    lmcdata = (LMC_CLIENT_DATA *) psp_getMemory(sizeof(LMC_CLIENT_DATA), 0);    if (lmcdata == NULL) {        shutdown(sock, 2);        close(sock);        return PSP_NOMEMORY;    }    lmcdata->sock = sock;/*    lmcdata->pipefcn = signal(SIGPIPE, SIG_IGN); */    if (tokfile[0])        lmcdata->tokfile = psp_strdup(tokfile, 0);    else        lmcdata->tokfile = NULL;    *data = lmcdata;    return PSP_OKAY;}/* ==========================================================================   TCP/IP specific listen*/static int tcp_listen(    const char *name){    int                sock;    int                opt;    char               hostname[128];    struct hostent    *host;    struct servent    *service;    struct sockaddr_in sockaddr_in;    sockaddr_in.sin_port = 0;    if ((name = strchr(name, ':')) != NULL)        sockaddr_in.sin_port = htons(atoi(name + 1));    if (sockaddr_in.sin_port == 0 && name &&             (service = getservbyname(name + 1, "tcp")) != NULL)        sockaddr_in.sin_port = service->s_port; /* Port from /etc/services */    if (sockaddr_in.sin_port == 0 &&            (service = getservbyname("db.star", "tcp")) != NULL)        sockaddr_in.sin_port = service->s_port; /* Port from /etc/services */    endservent();    if (sockaddr_in.sin_port == 0)        sockaddr_in.sin_port = htons(1523);  /* Default port number */    if (gethostname(hostname, sizeof(hostname)) != -1 &&            (host = gethostbyname(hostname)) != NULL) {        sockaddr_in.sin_family = host->h_addrtype;        memcpy(&sockaddr_in.sin_addr, host->h_addr, host->h_length);    }    else {        sockaddr_in.sin_family = AF_INET;        sockaddr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);    }    endhostent();    if (sockaddr_in.sin_addr.s_addr != 0) {        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)            return -1;        if (connect(sock, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) != -1) {            close(sock);            return -2;        }        close(sock);    }    sockaddr_in.sin_addr.s_addr = 0;    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)        return -1;    opt = 1;    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt));    if (bind(sock, (struct sockaddr *) &sockaddr_in, sizeof(sockaddr_in)) == -1) {        close(sock);        return -1;    }    if (listen(sock, 5) == -1) {        close(sock);        return -1;    }    return sock;}#if !defined(NO_UNIX_DOMAIN)/* ==========================================================================   Unix Domain sockets specific listen*/static int ip_listen(    const char *name,    const char *tmp,    char *tokfile){    int                sock;    char              *p;    struct sockaddr_un sockaddr_un;    sprintf(tokfile, "%s%s", tmp, name);    if ((p = strchr(tokfile, ':')) != NULL)        *p = '\0';    sockaddr_un.sun_family = AF_UNIX;     strcpy(sockaddr_un.sun_path, tokfile);    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)        return -1;    if (connect(sock, (struct sockaddr *) &sockaddr_un, sizeof(sockaddr_un)) != -1) {        close(sock);        return -2;    }    if (bind(sock, (struct sockaddr *) &sockaddr_un, sizeof(sockaddr_un)) == -1) {       /* Since we could not connect, but the bind failed, there may be an          old socket file left over - shut it down, delete the file, and          start again. */       close(sock);       unlink(tokfile);       if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)           return -1;       if (bind(sock, (struct sockaddr *) &sockaddr_un, sizeof(sockaddr_un)) == -1) {           close(sock);           return -1;       }    }    if (listen(sock, 5) == -1) {        close(sock);        return -1;    }    return sock;}#endif/* ==========================================================================   Listen for TCP/IP connections*/static int psp_tcp_listen(    const char *name,    const char *tmp,    int         maxclients,    void      **data){    int              sock1;    int              sock2;    char            *p;    char             tokfile[80] = "";    LMC_SERVER_DATA *lmcdata;    if ((sock1 = tcp_listen(name)) == -2)        return PSP_DUPLICATE;    if (sock1 == -1)        return PSP_FAILED;    sock2 = ip_listen(name, tmp, tokfile);    if ((lmcdata = psp_getMemory(sizeof(LMC_SERVER_DATA), 0)) == NULL) {        close(sock1);        if (sock2 >= 0) {           close(sock2);           unlink(tokfile);        }        return PSP_NOMEMORY;    }    lmcdata->clients = psp_cGetMemory(maxclients * sizeof(LMC_CLIENT_DATA), 0);    if (lmcdata->clients == NULL) {        psp_freeMemory(lmcdata, 0);        close(sock1);        if (sock2 >= 0) {            close(sock2);            unlink(tokfile);        }        return PSP_NOMEMORY;    }    lmcdata->count = 0;    FD_ZERO(&lmcdata->holdFDS);    FD_SET(sock1, &lmcdata->holdFDS);    if (sock2 >= 0)        FD_SET(sock2, &lmcdata->holdFDS);    lmcdata->sock1 = sock1;    lmcdata->sock2 = sock2;    if (tokfile[0])        lmcdata->tokfile = psp_strdup(tokfile, 0);    else        lmcdata->tokfile = NULL;    lmcdata->numclients = 0;    lmcdata->maxclients = maxclients;    *data = lmcdata;    return PSP_OKAY;}#if !defined(NO_UNIX_DOMAIN)/* ==========================================================================   Listen for Unix Domain socket connections*/static int psp_ip_listen(    const char *name,    const char *tmp,    int         maxclients,    void      **data){    int              sock;    char            *p;    char             tokfile[80] = "";    LMC_SERVER_DATA *lmcdata;    if ((sock = ip_listen(name, tmp, tokfile)) == -2)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?