commit package to go along with the last commit, thanks fofware
[openwrt/svn-archive/archive.git] / net / remotectrl / src / Socket.c
1 /*
2 * Javier Abellan, 20 Jun 2000
3 *
4 * Funciones de lectura y escritura en sockets
5 *
6 * MODIFICACIONES:
7 * 4 Septiembre 2003: Añadidas funciones para sockets UDP.
8 */
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <sys/un.h>
13 #include <netdb.h>
14 #include <unistd.h>
15 #include <errno.h>
16 #include <stdio.h>
17
18 #include "Socket.h"
19
20 #define BUFFER_SIZE 13
21
22 int ReadTcpSocket (int fd, char **Datos)
23 {
24 int Leido = 0;
25 struct head_t *head;
26 int Aux=0;
27 char buffer[BUFFER_SIZE];
28 char *message;
29 message = malloc(BUFFER_SIZE);
30 while (1){
31 bzero(buffer, BUFFER_SIZE);
32 Aux = read(fd, buffer, BUFFER_SIZE-1);
33 if (Leido==0){
34 message = memcpy(message, buffer, Aux);
35 head = malloc(sizeof(struct head_t));
36 head = memcpy(head,buffer,Aux);
37 } else {
38 message = realloc(message,(strlen(message)+Aux));
39 if (Aux == BUFFER_SIZE-1)
40 message = strcat(message,buffer);
41 else
42 message = strncat(message,buffer,Aux);
43 }
44 Leido += Aux;
45
46 printf("msg=%s Leido=%d\n", message, Leido);
47 if (Aux < BUFFER_SIZE-1 || Leido == head->len )
48 break;
49 }
50 *Datos=realloc(*Datos,Leido+1);
51 memcpy(*Datos,head,sizeof(struct head_t));
52 memcpy(*Datos+12, message, Leido);
53 return Leido;
54 }
55
56 int WriteTcpSocket(int fd, int type, int command, char *data){
57 int Escrito = 0;
58 int Aux = 0;
59
60 int Longitud = (sizeof(int)*3)+strlen((char *)data);
61 struct s_msg *Datos;
62 Datos = malloc(Longitud);
63 Datos->type = type;
64 Datos->command = command;
65 Datos->len = Longitud;
66 strcpy(Datos->data, data);
67 printf("Longitud=%d convertido Type=%d Command=%d Len=%d Data=%s\n",Longitud, Datos->type, Datos->command, Datos->len, Datos->data);
68 printf("Longitud=%d int=%d\n", Longitud,sizeof(int));
69 /*
70 if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
71 return -1;
72
73 */
74 //printf("Data:%s", *Datos);
75 while (Escrito < Longitud)
76 {
77 Aux = write (fd, Datos + Escrito, Longitud - Escrito);
78 if (Aux > 0)
79 {
80 Escrito = Escrito + Aux;
81 }
82 else
83 {
84 if (Aux == 0)
85 return Escrito;
86 else
87 return -1;
88 }
89 }
90 free(Datos);
91 return Escrito;
92 }
93
94 /*
95 * Lee datos del socket. Supone que se le pasa un buffer con hueco
96 * suficiente para los datos. Devuelve el numero de bytes leidos o
97 * 0 si se cierra fichero o -1 si hay error.
98 */
99 int Lee_Socket1 (int fd, char *Datos, int Longitud)
100 {
101 int Leido = 0;
102 int Aux = 0;
103
104
105 /*
106 * Comprobacion de que los parametros de entrada son correctos
107 */
108 if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
109 return -1;
110
111 /*
112 * Mientras no hayamos leido todos los datos solicitados
113 */
114
115 while (Leido < Longitud)
116 {
117 Aux = read (fd, Datos + Leido, Longitud - Leido);
118 if (Aux > 0)
119 {
120 /*
121 * Si hemos conseguido leer datos, incrementamos la variable
122 * que contiene los datos leidos hasta el momento
123 */
124 Leido = Leido + Aux;
125 }
126 else
127 {
128 /*
129 * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
130 * los caracteres leidos hasta ese momento
131 */
132 if (Aux == 0)
133 return Leido;
134 if (Aux == -1)
135 {
136 /*
137 * En caso de error, la variable errno nos indica el tipo
138 * de error.
139 * El error EINTR se produce si ha habido alguna
140 * interrupcion del sistema antes de leer ningun dato. No
141 * es un error realmente.
142 * El error EGAIN significa que el socket no esta disponible
143 * de momento, que lo intentemos dentro de un rato.
144 * Ambos errores se tratan con una espera de 100 microsegundos
145 * y se vuelve a intentar.
146 * El resto de los posibles errores provocan que salgamos de
147 * la funcion con error.
148 */
149 switch (errno)
150 {
151 case EINTR:
152 case EAGAIN:
153 usleep (100);
154 break;
155 default:
156 return -1;
157 }
158 }
159 }
160 }
161
162 /*
163 * Se devuelve el total de los caracteres leidos
164 */
165 return Leido;
166 }
167
168 /*
169 * Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
170 * o -1 si hay error.
171 */
172 int Escribe_Socket (int fd, char *Datos, int Longitud)
173 {
174 int Escrito = 0;
175 int Aux = 0;
176
177 /*
178 * Comprobacion de los parametros de entrada
179 */
180 if ((fd == -1) || (Datos == NULL) || (Longitud < 1))
181 return -1;
182
183 /*
184 * Bucle hasta que hayamos escrito todos los caracteres que nos han
185 * indicado.
186 */
187 while (Escrito < Longitud)
188 {
189 Aux = write (fd, Datos + Escrito, Longitud - Escrito);
190 if (Aux > 0)
191 {
192 /*
193 * Si hemos conseguido escribir caracteres, se actualiza la
194 * variable Escrito
195 */
196 Escrito = Escrito + Aux;
197 }
198 else
199 {
200 /*
201 * Si se ha cerrado el socket, devolvemos el numero de caracteres
202 * leidos.
203 * Si ha habido error, devolvemos -1
204 */
205 if (Aux == 0)
206 return Escrito;
207 else
208 return -1;
209 }
210 }
211
212 /*
213 * Devolvemos el total de caracteres leidos
214 */
215 return Escrito;
216 }
217
218 /**
219 * Lee un mensaje de un socket udp. Los parámetros que se pasan son:
220 * - Descriptor fd del socket del que se quiere leer.
221 * - Estructura Remoto, en la que se devolverá los datos del que ha enviado el
222 * mensaje que acabamos de leer.
223 * - Longitud_Remoto de la estructura anterior. Debe pasarse relleno con el tamaño
224 * de Remoto y se devolverá rellena con el tamaño de los datos en Remoto.
225 * - Buffer de Datos donde se quiere que aparezca el mensaje.
226 * - Longitud_Datos del buffer anterior.
227 *
228 * Devuelve el número de bytes leidos o -1 en caso de error.
229 */
230 int Lee_Socket_Udp (
231 int fd, struct sockaddr *Remoto, socklen_t *Longitud_Remoto,
232 char *Datos, int Longitud_Datos)
233 {
234 int Leido = 0;
235 int Aux = 0;
236
237 /*
238 * Comprobacion de que los parametros de entrada son correctos
239 */
240 if ((fd == -1) || (Datos == NULL) || (Longitud_Datos < 1)
241 || (Remoto == NULL) || (Longitud_Remoto == NULL))
242 {
243 return -1;
244 }
245
246 /*
247 * Mientras no hayamos leido todos los datos solicitados
248 */
249 while (Leido < Longitud_Datos)
250 {
251 Aux = recvfrom (fd, Datos + Leido, Longitud_Datos - Leido, 0,
252 Remoto, Longitud_Remoto);
253
254 if (Aux > 0)
255 {
256 /*
257 * Si hemos conseguido leer datos, incrementamos la variable
258 * que contiene los datos leidos hasta el momento
259 */
260 Leido = Leido + Aux;
261 }
262 else
263 {
264 /*
265 * Si read devuelve 0, es que se ha cerrado el socket. Devolvemos
266 * los caracteres leidos hasta ese momento
267 */
268 if (Aux == 0)
269 return Leido;
270 if (Aux == -1)
271 {
272 /*
273 * En caso de error, la variable errno nos indica el tipo
274 * de error.
275 * El error EINTR se produce si ha habido alguna
276 * interrupcion del sistema antes de leer ningun dato. No
277 * es un error realmente.
278 * El error EGAIN significa que el socket no esta disponible
279 * de momento, que lo intentemos dentro de un rato.
280 * Ambos errores se tratan con una espera de 100 microsegundos
281 * y se vuelve a intentar.
282 * El resto de los posibles errores provocan que salgamos de
283 * la funcion con error.
284 */
285 switch (errno)
286 {
287 case EINTR:
288 case EAGAIN:
289 usleep (100);
290 break;
291 default:
292 return -1;
293 }
294 }
295 }
296 }
297
298 /*
299 * Se devuelve el total de los caracteres leidos
300 */
301 return Leido;
302 }
303
304 /**
305 * Escribe dato en el socket cliente. Devuelve numero de bytes escritos,
306 * o -1 si hay error.
307 * - fd es el descriptor del socket.
308 * - Remoto es el destinatario del mensaje, a quién se lo queremos enviar.
309 * - Longitud_Remoto es el tamaño de Remoto en bytes.
310 * - Datos es el mensaje que queremos enviar.
311 * - Longitud_Datos es el tamaño del mensaje en bytes.
312 */
313 int Escribe_Socket_Udp (int fd, struct sockaddr *Remoto,
314 socklen_t Longitud_Remoto, char *Datos, int Longitud_Datos)
315 {
316 int Escrito = 0;
317 int Aux = 0;
318
319 /*
320 * Comprobacion de los parametros de entrada
321 */
322 if ((fd == -1) || (Datos == NULL) || (Longitud_Datos < 1)
323 || (Remoto == NULL) )
324 {
325 return -1;
326 }
327
328 /*
329 * Bucle hasta que hayamos escrito todos los caracteres que nos han
330 * indicado.
331 */
332 while (Escrito < Longitud_Datos)
333 {
334 Aux = sendto (fd, Datos + Escrito, Longitud_Datos - Escrito, 0,
335 Remoto, Longitud_Remoto);
336
337 if (Aux > 0)
338 {
339 /*
340 * Si hemos conseguido escribir caracteres, se actualiza la
341 * variable Escrito
342 */
343 Escrito = Escrito + Aux;
344 }
345 else
346 {
347 /*
348 * Si se ha cerrado el socket, devolvemos el numero de caracteres
349 * leidos.
350 * Si ha habido error, devolvemos -1
351 */
352 if (Aux == 0)
353 return Escrito;
354 else
355 {
356 return -1;
357 }
358 }
359 }
360
361 /*
362 * Devolvemos el total de caracteres leidos
363 */
364 return Escrito;
365 }
366
367
368 /**
369 * Rellena una estructura sockaddr_in con los datos que se le pasan. Esta estrutura es
370 * útil para el envio o recepción de mensajes por sockets Udp o para abrir conexiones.
371 * Se le pasa el host. Puede ser NULL (para abrir socket servidor Udp o para recepción de
372 * mensajes de cualquier host).
373 * Se le pasa el servicio. Puede ser NULL (para abrir socket cliente Udp).
374 * Se le pasa una estructura sockaddr_in que devolverá rellena.
375 * Se le pasa una Longitud. Debe contener el tamaño de la estructura sockaddr_in y
376 * devolverá el tamaño de la estructura una vez rellena.
377 * Devuelve -1 en caso de error.
378 */
379 int Dame_Direccion_Udp (char *Host, char *Servicio, struct sockaddr_in *Servidor,
380 int *Longitud_Servidor)
381 {
382 struct servent *Puerto;
383 struct hostent *Maquina;
384
385 /* Comprobación de parámetros */
386 if (Servidor == NULL) return -1;
387
388 /* Relleno del primer campo de la estructura */
389 Servidor->sin_family = AF_INET;
390
391 /* Si nos han pasado un host ... */
392 if (Host != NULL)
393 {
394 /* ... obtenemos la dirección del host y la ponemos en la estructura */
395 Maquina = gethostbyname (Host);
396 if (Maquina == NULL)
397 return -1;
398
399 Servidor->sin_addr.s_addr = ((struct in_addr *)(Maquina->h_addr))->s_addr;
400 }
401 else
402 /* Si no nos han pasado un host, ponemos cualquier host. */
403 Servidor->sin_addr.s_addr = INADDR_ANY;
404
405 /* Si servicio en NULL, hacemos que el puerto lo eliga el sistema operativo
406 libremente.*/
407 if (Servicio == NULL)
408 Servidor->sin_port = 0;
409 else
410 {
411 /* Si el servicio no es NULL, lo obtenemos. */
412 Puerto = getservbyname (Servicio, "udp");
413 if (Puerto == NULL)
414 return -1;
415 Servidor->sin_port = Puerto->s_port;
416 }
417 }