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 + -
显示快捷键?