Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-utils / wait_obj.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * Virtual Channel Manager
4  *
5  * Copyright 2009-2011 Jay Sorg
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <freerdp/utils/memory.h>
25 #include <freerdp/utils/wait_obj.h>
26
27 #ifndef _WIN32
28 #include <sys/time.h>
29 #else
30 #include <winsock2.h>
31 #endif
32
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 struct wait_obj
38 {
39 #ifdef _WIN32
40         HANDLE event;
41 #else
42         int pipe_fd[2];
43 #endif
44         int attached;
45 };
46
47 struct wait_obj*
48 wait_obj_new(void)
49 {
50         struct wait_obj* obj;
51
52         obj = xnew(struct wait_obj);
53
54         obj->attached = 0;
55 #ifdef _WIN32
56         obj->event = CreateEvent(NULL, TRUE, FALSE, NULL);
57 #else
58         obj->pipe_fd[0] = -1;
59         obj->pipe_fd[1] = -1;
60         if (pipe(obj->pipe_fd) < 0)
61         {
62                 printf("wait_obj_new: pipe failed\n");
63                 xfree(obj);
64                 return NULL;
65         }
66 #endif
67
68         return obj;
69 }
70
71 struct wait_obj* wait_obj_new_with_fd(void* fd)
72 {
73         struct wait_obj* obj;
74
75         obj = xnew(struct wait_obj);
76
77         obj->attached = 1;
78 #ifdef _WIN32
79         obj->event = fd;
80 #else
81         obj->pipe_fd[0] = (int)(long)fd;
82         obj->pipe_fd[1] = -1;
83 #endif
84
85         return obj;
86 }
87
88 void
89 wait_obj_free(struct wait_obj* obj)
90 {
91         if (obj)
92         {
93
94                 if (obj->attached == 0)
95                 {
96 #ifdef _WIN32
97                         if (obj->event)
98                         {
99                                 CloseHandle(obj->event);
100                                 obj->event = NULL;
101                         }
102 #else
103                         if (obj->pipe_fd[0] != -1)
104                         {
105                                 close(obj->pipe_fd[0]);
106                                 obj->pipe_fd[0] = -1;
107                         }
108                         if (obj->pipe_fd[1] != -1)
109                         {
110                                 close(obj->pipe_fd[1]);
111                                 obj->pipe_fd[1] = -1;
112                         }
113 #endif
114                 }
115
116                 xfree(obj);
117         }
118 }
119
120 int
121 wait_obj_is_set(struct wait_obj* obj)
122 {
123 #ifdef _WIN32
124         return (WaitForSingleObject(obj->event, 0) == WAIT_OBJECT_0);
125 #else
126         fd_set rfds;
127         int num_set;
128         struct timeval time;
129
130         FD_ZERO(&rfds);
131         FD_SET(obj->pipe_fd[0], &rfds);
132         memset(&time, 0, sizeof(time));
133         num_set = select(obj->pipe_fd[0] + 1, &rfds, 0, 0, &time);
134         return (num_set == 1);
135 #endif
136 }
137
138 void
139 wait_obj_set(struct wait_obj* obj)
140 {
141 #ifdef _WIN32
142         SetEvent(obj->event);
143 #else
144         int len;
145
146         if (wait_obj_is_set(obj))
147                 return;
148         len = write(obj->pipe_fd[1], "sig", 4);
149         if (len != 4)
150                 printf("wait_obj_set: error\n");
151 #endif
152 }
153
154 void
155 wait_obj_clear(struct wait_obj* obj)
156 {
157 #ifdef _WIN32
158         ResetEvent(obj->event);
159 #else
160         int len;
161
162         while (wait_obj_is_set(obj))
163         {
164                 len = read(obj->pipe_fd[0], &len, 4);
165                 if (len != 4)
166                         printf("wait_obj_clear: error\n");
167         }
168 #endif
169 }
170
171 int
172 wait_obj_select(struct wait_obj** listobj, int numobj, int timeout)
173 {
174 #ifndef _WIN32
175         int max;
176         int sock;
177         int index;
178 #endif
179         fd_set fds;
180         int status;
181         struct timeval time;
182         struct timeval* ptime;
183
184         ptime = 0;
185         if (timeout >= 0)
186         {
187                 time.tv_sec = timeout / 1000;
188                 time.tv_usec = (timeout * 1000) % 1000000;
189                 ptime = &time;
190         }
191
192 #ifndef _WIN32
193         max = 0;
194         FD_ZERO(&fds);
195         if (listobj)
196         {
197                 for (index = 0; index < numobj; index++)
198                 {
199                         sock = listobj[index]->pipe_fd[0];
200                         FD_SET(sock, &fds);
201
202                         if (sock > max)
203                                 max = sock;
204                 }
205         }
206         status = select(max + 1, &fds, 0, 0, ptime);
207 #else
208         status = select(0, &fds, 0, 0, ptime);
209 #endif
210
211         return status;
212 }
213
214 void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count)
215 {
216 #ifdef _WIN32
217         fds[*count] = (void*) obj->event;
218 #else
219         if (obj->pipe_fd[0] == -1)
220                 return;
221
222         fds[*count] = (void*)(long) obj->pipe_fd[0];
223 #endif
224         (*count)++;
225 }