00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef DARWIN
00022
00023 #define _BSD_SOCKLEN_T_ int
00024 #endif
00025 #include "defs.h"
00026 #include "ssi.h"
00027 #ifdef SOLARIS
00028 #define __EXTENSIONS__
00029 #endif
00030 #include <netdb.h>
00031 #undef __EXTENSIONS__
00032 #include <sys/un.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035
00036 static void set_fd_hwm(SSI *ssip, int fd)
00037 {
00038 if (fd > ssip->ssi_fd_hwm)
00039 ssip->ssi_fd_hwm = fd;
00040 }
00041
00042 static void reset_fd_hwm(SSI *ssip, int fd)
00043 {
00044 if (fd == ssip->ssi_fd_hwm)
00045 ssip->ssi_fd_hwm--;
00046 }
00047
00048 bool make_sockaddr(struct sockaddr *sa, socklen_t *len, const char *name,
00049 int domain, bool will_bind)
00050 {
00051 struct addrinfo *infop = NULL;
00052
00053 if (domain == AF_UNIX) {
00054 struct sockaddr_un *sunp = (struct sockaddr_un *)sa;
00055
00056 if (strlen(name) >= sizeof(sunp->sun_path)) {
00057 errno = ENAMETOOLONG;
00058 EC_FAIL
00059 }
00060 strcpy(sunp->sun_path, name);
00061 sunp->sun_family = AF_UNIX;
00062 *len = sizeof(*sunp);
00063 }
00064 else {
00065 struct addrinfo hint;
00066 char nodename[SSI_NAME_SIZE], *servicename;
00067
00068 memset(&hint, 0, sizeof(hint));
00069 hint.ai_family = domain;
00070 hint.ai_socktype = SOCK_STREAM;
00071 if (will_bind)
00072 hint.ai_flags = AI_PASSIVE;
00073 strcpy(nodename, name);
00074 servicename = strchr(nodename, ':');
00075 if (servicename == NULL) {
00076 errno = EINVAL;
00077 EC_FAIL
00078 }
00079 *servicename = '\0';
00080 servicename++;
00081 ec_ai( getaddrinfo(nodename, servicename, &hint, &infop) )
00082 memcpy(sa, infop->ai_addr, infop->ai_addrlen);
00083 *len = infop->ai_addrlen;
00084 freeaddrinfo(infop);
00085 }
00086 return true;
00087
00088 EC_CLEANUP_BGN
00089 if (infop != NULL)
00090 freeaddrinfo(infop);
00091 return false;
00092 EC_CLEANUP_END
00093 }
00094
00095
00096
00097
00098
00099 SSI *ssi_open(const char *name_server, bool server)
00100 {
00101 SSI *ssip = NULL;
00102 struct sockaddr_storage sa;
00103 socklen_t sa_len;
00104
00105 ec_null( ssip = (SSI *)calloc(1, sizeof(SSI)) )
00106 ssip->ssi_server = server;
00107 if (strncmp(name_server, "//", 2) == 0) {
00108 ssip->ssi_domain = AF_INET;
00109 name_server += 2;
00110 }
00111 else {
00112 ssip->ssi_domain = AF_UNIX;
00113 if (ssip->ssi_server)
00114 (void)unlink(name_server);
00115 }
00116 if (strlen(name_server) >= sizeof(ssip->ssi_name_server)) {
00117 errno = ENAMETOOLONG;
00118 EC_FAIL
00119 }
00120 strcpy(ssip->ssi_name_server, name_server);
00121 ec_false( make_sockaddr((struct sockaddr *)&sa, &sa_len,
00122 ssip->ssi_name_server, ssip->ssi_domain, ssip->ssi_server) )
00123 ec_neg1( ssip->ssi_fd = socket(ssip->ssi_domain, SOCK_STREAM, 0) )
00124 set_fd_hwm(ssip, ssip->ssi_fd);
00125 if (ssip->ssi_domain == AF_INET) {
00126
00127
00128
00129
00130 int socket_option_value = 1;
00131
00132 ec_neg1( setsockopt(ssip->ssi_fd, SOL_SOCKET, SO_REUSEADDR,
00133 &socket_option_value, sizeof(socket_option_value)) )
00134 }
00135 if (ssip->ssi_server) {
00136 FD_ZERO(&ssip->ssi_fd_set);
00137 ec_neg1( bind(ssip->ssi_fd, (struct sockaddr *)&sa, sa_len) )
00138 ec_neg1( listen(ssip->ssi_fd, SOMAXCONN) )
00139 FD_SET(ssip->ssi_fd, &ssip->ssi_fd_set);
00140 }
00141 else
00142 ec_neg1( connect(ssip->ssi_fd, (struct sockaddr *)&sa, sa_len) )
00143 return ssip;
00144
00145 EC_CLEANUP_BGN
00146 free(ssip);
00147 return NULL;
00148 EC_CLEANUP_END
00149 }
00150
00151 bool ssi_close(SSI *ssip)
00152 {
00153 if (ssip->ssi_server) {
00154 int fd;
00155
00156 for (fd = 0; fd <= ssip->ssi_fd_hwm; fd++)
00157 if (FD_ISSET(fd, &ssip->ssi_fd_set))
00158 (void)close(fd);
00159 if (ssip->ssi_domain == AF_UNIX)
00160 (void)unlink(ssip->ssi_name_server);
00161 }
00162 else
00163 (void)close(ssip->ssi_fd);
00164 free(ssip);
00165 return true;
00166 }
00167
00168 bool ssi_close_fd(SSI *ssip, int fd)
00169 {
00170 ec_neg1( close(fd) );
00171 FD_CLR(fd, &ssip->ssi_fd_set);
00172 reset_fd_hwm(ssip, fd);
00173 return true;
00174
00175 EC_CLEANUP_BGN
00176 return false;
00177 EC_CLEANUP_END
00178 }
00179
00180 int ssi_wait_server(SSI *ssip)
00181 {
00182 if (ssip->ssi_server) {
00183 fd_set fd_set_read;
00184 int fd, clientfd;
00185 struct sockaddr_un from;
00186 socklen_t from_len = sizeof(from);
00187
00188 while (true) {
00189 fd_set_read = ssip->ssi_fd_set;
00190 ec_neg1( select(ssip->ssi_fd_hwm + 1, &fd_set_read, NULL, NULL,
00191 NULL) )
00192 for (fd = 0; fd <= ssip->ssi_fd_hwm; fd++)
00193 if (FD_ISSET(fd, &fd_set_read)) {
00194 if (fd == ssip->ssi_fd) {
00195 ec_neg1( clientfd = accept(ssip->ssi_fd,
00196 (struct sockaddr *)&from, &from_len) );
00197 FD_SET(clientfd, &ssip->ssi_fd_set);
00198 set_fd_hwm(ssip, clientfd);
00199 continue;
00200 }
00201 else
00202 return fd;
00203 }
00204 }
00205 }
00206 else {
00207 errno = ENOTSUP;
00208 EC_FAIL
00209 }
00210
00211 EC_CLEANUP_BGN
00212 return -1;
00213 EC_CLEANUP_END
00214 }
00215
00216 int ssi_get_server_fd(SSI *ssip)
00217 {
00218 return ssip->ssi_fd;
00219 }
00220
00221 #if 0
00222 bool ssi_send(SSI *ssip, void *buf, size_t bufsize)
00223 {
00224 if (ssip->ssi_server) {
00225 ec_neg1( sendto(ssip->ssi_fd_client, buf, bufsize, 0,
00226 (struct sockaddr *)&ssip->ssi_sa, ssip->ssi_sa_len) )
00227 }
00228 else
00229 ec_neg1( send(ssip->ssi_fd, buf, bufsize, 0) )
00230 return true;
00231
00232 EC_CLEANUP_BGN
00233 return false;
00234 EC_CLEANUP_END
00235 }
00236
00237 bool ssi_receive(SSI *ssip, void *buf, size_t bufsize)
00238 {
00239 if (ssip->ssi_server) {
00240 ec_neg1( ssip->ssi_fd_client = ssi_wait_server(ssip) )
00241 ssip->ssi_sa_len = sizeof(ssip->ssi_sa);
00242
00243 ec_neg1( recvfrom(ssip->ssi_fd_client, buf, bufsize,
00244 0, (struct sockaddr *)&ssip->ssi_sa, &ssip->ssi_sa_len) )
00245 }
00246 else
00247 ec_neg1( recv(ssip->ssi_fd, buf, bufsize, 0) )
00248 return true;
00249
00250 EC_CLEANUP_BGN
00251 return false;
00252 EC_CLEANUP_END
00253 }
00254 #endif