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