©2004 by Marc J. Rochkind. All rights reserved. Portions marked "Open Source" may be copied under license.

 

Main Page   Modules   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

c7/smi_mq.c

Go to the documentation of this file.
00001 /*
00002     SMI - POSIX messages
00003     AUP2, Sec. 7.07.2
00004 
00005     Copyright 2003 by Marc J. Rochkind. All rights reserved.
00006     May be copied only for purposes and under conditions described
00007     on the Web page www.basepath.com/aup/copyright.htm.
00008 
00009     The Example Files are provided "as is," without any warranty;
00010     without even the implied warranty of merchantability or fitness
00011     for a particular purpose. The author and his publisher are not
00012     responsible for any damages, direct or incidental, resulting
00013     from the use or non-use of these Example Files.
00014 
00015     The Example Files may contain defects, and some contain deliberate
00016     coding mistakes that were included for educational reasons.
00017     You are responsible for determining if and how the Example Files
00018     are to be used.
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 /*[top]*/
00051 #define MAX_CLIENTS 20
00052 
00053 typedef struct {
00054     SMIENTITY sq_entity;            /* entity */
00055     mqd_t sq_mqd_server;            /* server message-queue descriptor */
00056     char sq_name[SERVER_NAME_MAX];  /* server name */
00057     struct client_info { /* Client uses only sq_clients[0] */
00058         mqd_t cl_mqd;               /* client message-queue descriptor */
00059         pid_t cl_pid;               /* client process ID */
00060     } sq_clients[MAX_CLIENTS];
00061     struct client_id sq_client;     /* client ID */
00062     size_t sq_msgsize; /* msg size */
00063     struct smi_msg *sq_msg; /* msg buffer */
00064 } SMIQ_MQ;
00065 /*[make_mq_name]*/
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 /*[get_client_mqd]*/
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 /*[smi_open_mq]*/
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 /*[smi_close_mq]*/
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 /*[smi_send_getaddr_mq]*/
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 /*[smi_receive_getaddr_mq]*/
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 

Generated on Fri Apr 23 10:56:59 2004 for AUP2 Example Source by doxygen 1.3.1