00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "defs.h"
00022 #include "../c4/setblock.h"
00023 #include "smi_fifo.h"
00024
00025
00026
00027
00028
00029
00030
00031 #define MAX_CLIENTS 20
00032
00033 typedef struct {
00034 SMIENTITY sq_entity;
00035 int sq_fd_server;
00036 int sq_fd_server_w;
00037 char sq_name[SERVER_NAME_MAX];
00038 struct {
00039 int cl_fd;
00040 pid_t cl_pid;
00041 } sq_clients[MAX_CLIENTS];
00042 struct client_id sq_client;
00043 size_t sq_msgsize;
00044 struct smi_msg *sq_msg;
00045 } SMIQ_FIFO;
00046
00047 static void clients_bgn(SMIQ_FIFO *p)
00048 {
00049 int i;
00050
00051 for (i = 0; i < MAX_CLIENTS; i++)
00052 p->sq_clients[i].cl_fd = -1;
00053 }
00054
00055 static int clients_find(SMIQ_FIFO *p, pid_t pid)
00056 {
00057 int i, avail = -1;
00058
00059 for (i = 0; i < MAX_CLIENTS; i++) {
00060 if (p->sq_clients[i].cl_pid == pid)
00061 return i;
00062 if (p->sq_clients[i].cl_fd == -1 && avail == -1)
00063 avail = i;
00064 }
00065 if (avail != -1)
00066 p->sq_clients[avail].cl_pid = pid;
00067 return avail;
00068 }
00069
00070 static void clients_close_all(SMIQ_FIFO *p)
00071 {
00072 int i;
00073
00074 for (i = 0; i < MAX_CLIENTS; i++)
00075 if (p->sq_clients[i].cl_fd != -1) {
00076 (void)close(p->sq_clients[i].cl_fd);
00077 p->sq_clients[i].cl_fd = -1;
00078 }
00079 }
00080
00081 static void clients_end(SMIQ_FIFO *p)
00082 {
00083 clients_close_all(p);
00084 }
00085
00086 static void make_fifo_name_server(const SMIQ_FIFO *p, char *fifoname,
00087 size_t fifoname_max)
00088 {
00089 snprintf(fifoname, fifoname_max, "/tmp/smififo-%s", p->sq_name);
00090 }
00091
00092 static void make_fifo_name_client(pid_t pid, char *fifoname,
00093 size_t fifoname_max)
00094 {
00095 snprintf(fifoname, fifoname_max, "/tmp/smififo%ld", (long)pid);
00096 }
00097
00098
00099
00100
00101
00102 SMIQ *smi_open_fifo(const char *name, SMIENTITY entity, size_t msgsize)
00103 {
00104 SMIQ_FIFO *p = NULL;
00105 char fifoname[SERVER_NAME_MAX + 50];
00106
00107 ec_null( p = calloc(1, sizeof(SMIQ_FIFO)) )
00108 p->sq_msgsize = msgsize + offsetof(struct smi_msg, smi_data);
00109 ec_null( p->sq_msg = calloc(1, p->sq_msgsize) )
00110 p->sq_entity = entity;
00111 if (strlen(name) >= SERVER_NAME_MAX) {
00112 errno = ENAMETOOLONG;
00113 EC_FAIL
00114 }
00115 strcpy(p->sq_name, name);
00116 make_fifo_name_server(p, fifoname, sizeof(fifoname));
00117 if (p->sq_entity == SMI_SERVER) {
00118 clients_bgn(p);
00119 if (mkfifo(fifoname, PERM_FILE) == -1 && errno != EEXIST)
00120 EC_FAIL
00121 ec_neg1( p->sq_fd_server = open(fifoname, O_RDONLY) )
00122 ec_neg1( p->sq_fd_server_w = open(fifoname, O_WRONLY) )
00123 }
00124 else {
00125 ec_neg1( p->sq_fd_server = open(fifoname, O_WRONLY) )
00126 make_fifo_name_client(getpid(), fifoname, sizeof(fifoname));
00127 (void)unlink(fifoname);
00128 ec_neg1( mkfifo(fifoname, PERM_FILE) )
00129 ec_neg1( p->sq_clients[0].cl_fd =
00130 open(fifoname, O_RDONLY | O_NONBLOCK) )
00131 ec_false( setblock(p->sq_clients[0].cl_fd, true) )
00132 ec_neg1( p->sq_clients[1].cl_fd = open(fifoname, O_WRONLY) )
00133 }
00134 return (SMIQ *)p;
00135
00136 EC_CLEANUP_BGN
00137 if (p != NULL) {
00138 free(p->sq_msg);
00139 free(p);
00140 }
00141 return NULL;
00142 EC_CLEANUP_END
00143 }
00144
00145 bool smi_close_fifo(SMIQ *sqp)
00146 {
00147 SMIQ_FIFO *p = (SMIQ_FIFO *)sqp;
00148
00149 clients_end(p);
00150 (void)close(p->sq_fd_server);
00151
00152
00153
00154 if (p->sq_entity == SMI_CLIENT) {
00155 char fifoname[SERVER_NAME_MAX + 50];
00156
00157 make_fifo_name_client(getpid(), fifoname, sizeof(fifoname));
00158 (void)unlink(fifoname);
00159 }
00160 else
00161 (void)close(p->sq_fd_server_w);
00162 free(p->sq_msg);
00163 free(p);
00164 return true;
00165 }
00166
00167
00168
00169 bool smi_send_getaddr_fifo(SMIQ *sqp, struct client_id *client,
00170 void **addr)
00171 {
00172 SMIQ_FIFO *p = (SMIQ_FIFO *)sqp;
00173
00174 if (p->sq_entity == SMI_SERVER)
00175 p->sq_client = *client;
00176 *addr = p->sq_msg;
00177 return true;
00178 }
00179
00180 bool smi_send_release_fifo(SMIQ *sqp)
00181 {
00182 SMIQ_FIFO *p = (SMIQ_FIFO *)sqp;
00183 ssize_t nwrite;
00184
00185 if (p->sq_entity == SMI_SERVER) {
00186 int nclient = clients_find(p, p->sq_client.c_id1);
00187 if (nclient == -1 || p->sq_clients[nclient].cl_fd == -1) {
00188 errno = EADDRNOTAVAIL;
00189 EC_FAIL
00190 }
00191 ec_neg1( nwrite = write(p->sq_clients[nclient].cl_fd, p->sq_msg,
00192 p->sq_msgsize) )
00193 }
00194 else {
00195 p->sq_msg->smi_client.c_id1 = (long)getpid();
00196 ec_neg1( nwrite = write(p->sq_fd_server, p->sq_msg,
00197 p->sq_msgsize) )
00198 }
00199 return true;
00200
00201 EC_CLEANUP_BGN
00202 return false;
00203 EC_CLEANUP_END
00204 }
00205
00206 bool smi_receive_getaddr_fifo(SMIQ *sqp, void **addr)
00207 {
00208 SMIQ_FIFO *p = (SMIQ_FIFO *)sqp;
00209 ssize_t nread;
00210
00211 if (p->sq_entity == SMI_SERVER) {
00212 int nclient;
00213 char fifoname[SERVER_NAME_MAX + 50];
00214
00215 while (true) {
00216 ec_neg1( nread = read(p->sq_fd_server, p->sq_msg,
00217 p->sq_msgsize) )
00218 if (nread == 0) {
00219 errno = ENETDOWN;
00220 EC_FAIL
00221 }
00222 if (nread < offsetof(struct smi_msg, smi_data)) {
00223 errno = E2BIG;
00224 EC_FAIL
00225 }
00226 if ((nclient = clients_find(p,
00227 (pid_t)p->sq_msg->smi_client.c_id1)) == -1) {
00228 continue;
00229 }
00230 if (p->sq_clients[nclient].cl_fd == -1) {
00231 make_fifo_name_client((pid_t)p->sq_msg->smi_client.c_id1,
00232 fifoname, sizeof(fifoname));
00233 ec_neg1( p->sq_clients[nclient].cl_fd =
00234 open(fifoname, O_WRONLY) )
00235 }
00236 break;
00237 }
00238 }
00239 else
00240 ec_neg1( nread = read(p->sq_clients[0].cl_fd, p->sq_msg,
00241 p->sq_msgsize) )
00242 *addr = p->sq_msg;
00243 return true;
00244
00245 EC_CLEANUP_BGN
00246 return false;
00247 EC_CLEANUP_END
00248 }
00249
00250 bool smi_receive_release_fifo(SMIQ *sqp)
00251 {
00252 return true;
00253 }
00254