1 /*
2  * Copyright (C) 2002-2009, Edmundo Albuquerque de Souza e Silva.
3  *
4  * This file may be distributed under the terms of the Q Public License
5  * as defined by Trolltech AS of Norway and appearing in the file
6  * LICENSE.QPL included in the packaging of this file.
7  *
8  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
9  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
10  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
11  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
12  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
13  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
14  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  */
17 
18 /***************************************************************************
19                              rmmsg.c
20                              -------------------
21     begin                : May 2001
22     Authors              : Jorge Allyson Azevedo
23                            Milena Scanferla
24                            Daniel Sadoc
25     email                : {allyson,milena,sadoc}@land.ufrj.br
26  ***************************************************************************/
27 
28 #ifndef MSG_C
29 #define MSG_C
30 
31 #include <pthread.h>
32 #include "rmmsg.h"
33 
34 int s_qid = -1; /* message queue identifier
35                  * -1: queue not initialized
36                  * -2: queue removed
37                  * otherwise: queue identifier
38                  */
39 #ifdef SOLARIS
40 pthread_mutex_t remove_queues_lock;
41 #else
42 pthread_mutex_t remove_queues_lock = PTHREAD_MUTEX_INITIALIZER;
43 #endif
44 
45 /*****************************************************************************************************
46  *
47  * int init_queue()
48  *
49  * Initializes the message queue.
50  *
51  * Side effects: updates s_qid.
52  * Returns > 0 id if OK
53  *         -1 if error
54  *
55  ******************************************************************************************************/
init_queue()56 int init_queue()
57 {
58     int queue_id;
59     int QKEY;
60 
61 #ifdef SOLARIS
62     pthread_mutex_init(&remove_queues_lock,NULL);
63 #endif
64     QKEY = QKEY_BASE;
65     while( ( queue_id = msgget( QKEY, IPC_CREAT | QPERM | IPC_EXCL ) ) == -1 )
66     {
67         if( errno == EEXIST )
68         {
69 #ifdef DEBUG_NET_MSGS
70             fprintf( stderr,"DEBUG_NET_MSGS init_queue: Message queue key %d already used. Trying %d. \n",
71                 QKEY,
72                 QKEY + 1 );
73 #endif
74             QKEY++;
75         }
76         else
77         {
78             perror( "init_queue: msgget failed" );
79             return -1;
80         }
81     }
82     s_qid = queue_id;
83 
84     return( queue_id );
85 }
86 
87 /*****************************************************************************************************
88  *
89  * void remove_queues(int i)
90  *
91  * Removes the message queue.
92  *
93  * Side effects: sets s_qid to -2 on success.
94  *
95  ******************************************************************************************************/
remove_queues(int i)96 void remove_queues( int i )
97 {
98 
99     pthread_mutex_lock( &remove_queues_lock );
100     if( s_qid != -2 )
101     {
102         if( msgctl( s_qid, IPC_RMID, NULL ) == -1 )
103             fprintf( stderr, "remove_queues ERROR: Failed to remove message queue %d.\n", s_qid );
104     }
105 
106     s_qid = -2;
107     pthread_mutex_unlock( &remove_queues_lock );
108 }
109 
110 /*****************************************************************************************************
111  *
112  * int messageQueueEnter(char *objname, int len)
113  *
114  * Puts a message of size len in the message queue.
115  *
116  * Arguments:    objname,    the message to be enqueued;
117  *                len,        the size of the message.
118  *
119  * Return value: 0 on success;
120  *              -1 on error.
121  *
122  ******************************************************************************************************/
messageQueueEnter(char * objname,int len)123 int messageQueueEnter( char *objname, int len )
124 {
125     struct q_entry s_entry;
126     int aux, ind;
127 
128     pthread_mutex_lock( &remove_queues_lock );
129 
130     if (len > MAXOBN)
131     {
132         fprintf( stderr, "messageQueueEnter ERROR: Name too long!\n" );
133         return -1;
134     }
135 
136     if( s_qid == -1 )
137         s_qid = init_queue();
138 
139     if ( s_qid == -1 || s_qid == -2 )
140     {
141         fprintf( stderr,"messageQueueEnter ERROR: init_queue() failed!\n" );
142         return -1;
143     }
144 
145 #ifdef DEBUG_NET_MSGS
146     fprintf( stderr,"DEBUG_NET_MSGS messageQueueEnter: preparing to send data to app.\n" );
147 #endif
148 
149     s_entry.mtype = ( long )1;
150 
151     /* converts len from base 10 to base 256 - least signif. digit is stored in mtext[0] */
152 
153     for( aux = len, ind = 0; aux != 0; aux = aux/256, ind++ )
154         s_entry.mtext[ ind ] = aux % 256;
155 
156     /* FIXME: the following test is really necessary? */
157     if( ind > MSG_QUEUE_HEADER_SIZE )
158     {
159         fprintf( stderr, "messageQueueEnter ERROR: You must increment the MSG_QUEUE_HEADER_SIZE. ind=%d\n", ind );
160         return -1;
161     }
162 
163     memcpy( &(s_entry.mtext[MSG_QUEUE_HEADER_SIZE]), objname, len );
164 
165 #ifdef DEBUG_NET_MSGS
166     fprintf( stderr, "DEBUG_NET_MSGS messageQueueEnter: data ready!\n" );
167 #endif
168 
169     if( msgsnd( s_qid, &s_entry, len + MSG_QUEUE_HEADER_SIZE, 0 ) == -1 )
170     {
171         perror( "messageQueueEnter: Couldn't send message to app - msgsnd failed!" );
172         pthread_mutex_unlock( &remove_queues_lock );
173         return -1;
174     }
175 #ifdef DEBUG_NET_MSGS
176     fprintf( stderr, "DEBUG_NET_MSGS messageQueueEnter: data sent to app.\n" );
177 #endif
178 
179     pthread_mutex_unlock( &remove_queues_lock );
180 
181     return 0;
182 }
183 #endif
184