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 "smi_mq.h"
00023 #ifdef COMPILES_POSIX_MESSAGE_PASSING
00024 #include <mqueue.h>
00025 #endif
00026
00027 #ifndef COMPILES_POSIX_MESSAGE_PASSING
00028
00029 typedef int mqd_t;
00030 struct mq_attr {
00031 long mq_flags;
00032 long mq_maxmsg;
00033 long mq_msgsize;
00034 long mq_curmsgs;
00035 };
00036
00037 static int missing_function(const char *s, ...)
00038 {
00039 errno = ENOSYS;
00040 return -1;
00041 }
00042
00043 #define mq_open (mqd_t)missing_function
00044 #define mq_close(a) missing_function(NULL)
00045 #define mq_unlink missing_function
00046 #define mq_send(a, b, c, d) missing_function(NULL)
00047 #define mq_receive(a, b, c, d) missing_function(NULL)
00048
00049 #endif
00050
00051 #define MAX_CLIENTS 20
00052
00053 typedef struct {
00054 SMIENTITY sq_entity;
00055 mqd_t sq_mqd_server;
00056 char sq_name[SERVER_NAME_MAX];
00057 struct client_info {
00058 mqd_t cl_mqd;
00059 pid_t cl_pid;
00060 } sq_clients[MAX_CLIENTS];
00061 struct client_id sq_client;
00062 size_t sq_msgsize;
00063 struct smi_msg *sq_msg;
00064 } SMIQ_MQ;
00065
00066 static void make_mq_name_server(const SMIQ_MQ *p, char *mqname,
00067 size_t mqname_max)
00068 {
00069 snprintf(mqname, mqname_max, "/smimq-s%s", p->sq_name);
00070 }
00071
00072 static void make_mq_name_client(pid_t pid, char *mqname,
00073 size_t mqname_max)
00074 {
00075 snprintf(mqname, mqname_max, "/smimq-c%d", pid);
00076 }
00077
00078 static mqd_t get_client_mqd(SMIQ_MQ *p, pid_t pid)
00079 {
00080 int i, avail = -1;
00081 char mqname[SERVER_NAME_MAX + 100];
00082
00083 for (i = 0; i < MAX_CLIENTS; i++) {
00084 if (p->sq_clients[i].cl_pid == pid)
00085 return p->sq_clients[i].cl_mqd;
00086 if (avail == -1 && p->sq_clients[i].cl_pid == 0)
00087 avail = i;
00088 }
00089 errno = ECONNREFUSED;
00090 ec_neg1( avail )
00091 p->sq_clients[avail].cl_pid = pid;
00092 make_mq_name_client(pid, mqname, sizeof(mqname));
00093 ec_neg1( p->sq_clients[avail].cl_mqd = mq_open(mqname, O_WRONLY) )
00094 return p->sq_clients[avail].cl_mqd;
00095
00096 EC_CLEANUP_BGN
00097 return (mqd_t)-1;
00098 EC_CLEANUP_END
00099 }
00100
00101 static pid_t my_pid;
00102
00103 SMIQ *smi_open_mq(const char *name, SMIENTITY entity, size_t msgsize)
00104 {
00105 SMIQ_MQ *p = NULL;
00106 char mqname[SERVER_NAME_MAX + 100];
00107 struct mq_attr attr = {0};
00108
00109 my_pid = getpid();
00110 ec_null( p = calloc(1, sizeof(SMIQ_MQ)) )
00111 p->sq_msgsize = msgsize + offsetof(struct smi_msg, smi_data);
00112 ec_null( p->sq_msg = calloc(1, p->sq_msgsize) )
00113 p->sq_entity = entity;
00114 p->sq_mqd_server = p->sq_clients[0].cl_mqd = (mqd_t)-1;
00115 if (strlen(name) >= SERVER_NAME_MAX) {
00116 errno = ENAMETOOLONG;
00117 EC_FAIL
00118 }
00119 strcpy(p->sq_name, name);
00120 make_mq_name_server(p, mqname, sizeof(mqname));
00121 attr.mq_maxmsg = 100;
00122 attr.mq_msgsize = p->sq_msgsize;
00123 if (p->sq_entity == SMI_SERVER) {
00124 (void)mq_unlink(mqname);
00125 ec_cmp( errno, ENOSYS )
00126 ec_neg1( p->sq_mqd_server = mq_open(mqname, O_RDONLY | O_CREAT,
00127 PERM_FILE, &attr) )
00128 }
00129 else {
00130 ec_neg1( p->sq_mqd_server = mq_open(mqname, O_WRONLY) )
00131 make_mq_name_client(my_pid, mqname, sizeof(mqname));
00132 ec_neg1( p->sq_clients[0].cl_mqd = mq_open(mqname,
00133 O_RDONLY | O_CREAT, PERM_FILE, &attr) )
00134 }
00135 return (SMIQ *)p;
00136
00137 EC_CLEANUP_BGN
00138 if (p != NULL)
00139 (void)smi_close_mq((SMIQ *)p);
00140 return NULL;
00141 EC_CLEANUP_END
00142 }
00143
00144 bool smi_close_mq(SMIQ *sqp)
00145 {
00146 SMIQ_MQ *p = (SMIQ_MQ *)sqp;
00147 char msgname[SERVER_NAME_MAX + 100];
00148
00149 if (p->sq_entity == SMI_SERVER) {
00150 make_mq_name_server(p, msgname, sizeof(msgname));
00151 (void)mq_close(p->sq_mqd_server);
00152 (void)mq_unlink(msgname);
00153 }
00154 else {
00155 make_mq_name_client(my_pid, msgname, sizeof(msgname));
00156 (void)mq_close(p->sq_mqd_server);
00157 (void)mq_unlink(msgname);
00158 }
00159 free(p->sq_msg);
00160 free(p);
00161 return true;
00162 }
00163
00164 bool smi_send_getaddr_mq(SMIQ *sqp, struct client_id *client,
00165 void **addr)
00166 {
00167 SMIQ_MQ *p = (SMIQ_MQ *)sqp;
00168
00169 if (p->sq_entity == SMI_SERVER)
00170 p->sq_client = *client;
00171 *addr = p->sq_msg;
00172 return true;
00173 }
00174
00175 bool smi_send_release_mq(SMIQ *sqp)
00176 {
00177 SMIQ_MQ *p = (SMIQ_MQ *)sqp;
00178 mqd_t mqd_receiver;
00179
00180 if (p->sq_entity == SMI_SERVER)
00181 ec_neg1( mqd_receiver = get_client_mqd(p, p->sq_client.c_id1) )
00182 else {
00183 mqd_receiver = p->sq_mqd_server;
00184 p->sq_msg->smi_client.c_id1 = my_pid;
00185 }
00186 ec_neg1( mq_send(mqd_receiver, (const char *)p->sq_msg,
00187 p->sq_msgsize, 0) )
00188 return true;
00189
00190 EC_CLEANUP_BGN
00191 return false;
00192 EC_CLEANUP_END
00193 }
00194
00195 bool smi_receive_getaddr_mq(SMIQ *sqp, void **addr)
00196 {
00197 SMIQ_MQ *p = (SMIQ_MQ *)sqp;
00198 mqd_t mqd_receiver;
00199 ssize_t nrcv;
00200
00201 if (p->sq_entity == SMI_SERVER)
00202 mqd_receiver = p->sq_mqd_server;
00203 else
00204 mqd_receiver = p->sq_clients[0].cl_mqd;
00205 ec_neg1( nrcv = mq_receive(mqd_receiver, (char *)p->sq_msg,
00206 p->sq_msgsize, NULL) )
00207 *addr = p->sq_msg;
00208 return true;
00209
00210 EC_CLEANUP_BGN
00211 return false;
00212 EC_CLEANUP_END
00213 }
00214
00215 bool smi_receive_release_mq(SMIQ *sqp)
00216 {
00217 return true;
00218 }
00219
00220