00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "toolkits/net/jed_tcp.h"
00026 #if (PLATAFORMA == i386_LINUX_GCC) || (PLATAFORMA == ALPHA) || (PLATAFORMA == SPARC64_LINUX_GCC)
00027 #include "toolkits/media/_unix_io.h"
00028 #endif
00029
00030 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00031 #include <sys/poll.h>
00032 #endif
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include "lista.cc"
00039
00040 #ifdef UNIX_ENABLED
00041 #include <strings.h>
00042 #endif
00043
00044 #ifdef UNIX_ENABLED
00045 #define REPORTAR_ERROR_CONNECT() \
00046 fprintf(stderr, \
00047 "<CONEXION_TCP> - ERROR: El cliente no puede conectarse.\n" \
00048 " Motivo: "); \
00049 switch ( errno ) { \
00050 case EBADF: \
00051 fprintf(stderr, "descriptor de socket invalido.\n"); \
00052 break; \
00053 case EFAULT: \
00054 fprintf(stderr, "segmentation fault.\n"); \
00055 break; \
00056 case ENOTSOCK: \
00057 fprintf(stderr, "el descriptor de archivo no es un socket.\n"); \
00058 break; \
00059 case EISCONN: \
00060 fprintf(stderr, \
00061 "el socket ya habia sido conectado a otro servidor!\n"); \
00062 break; \
00063 case ECONNREFUSED: \
00064 fprintf(stderr, "acceso denegado por el servidor!\n"); \
00065 break; \
00066 case ETIMEDOUT: \
00067 fprintf(stderr, "TIMEOUT - no se encuentra el servidor!\n"); \
00068 break; \
00069 case ENETUNREACH: \
00070 fprintf(stderr, "NETWORK UNREACHABLE - la red esta caida!\n"); \
00071 break; \
00072 case EADDRINUSE: \
00073 fprintf(stderr, \
00074 "el puerto TCP esta siendo usado por otro proceso.\n"); \
00075 break; \
00076 case EINPROGRESS: \
00077 fprintf(stderr, "conexion en progreso fallida (?).\n"); \
00078 break; \
00079 case EALREADY: \
00080 fprintf(stderr, "conexion en progreso anterior (?).\n"); \
00081 break; \
00082 default: \
00083 fprintf(stderr, "desconocido (%d).\n", errno); \
00084 break; \
00085 } \
00086 fflush(stderr); \
00087 return FALSE;
00088
00089 #define REPORTAR_ERROR_LISTEN() \
00090 fprintf(stderr, \
00091 "<CONEXION_TCP> - ERROR: El servidor no puede recibir conexiones.\n"\
00092 " Motivo: "); \
00093 switch ( errno ) { \
00094 case EBADF: \
00095 fprintf(stderr, "descriptor de socket invalido.\n"); \
00096 break; \
00097 case ENOTSOCK: \
00098 fprintf(stderr, "el descriptor de archivo no es un socket.\n"); \
00099 break; \
00100 case EOPNOTSUPP: \
00101 fprintf(stderr, "el socket no es orientado a conexion.\n"); \
00102 break; \
00103 default: \
00104 fprintf(stderr, "desconocido (%d).\n", errno); \
00105 break; \
00106 } \
00107 fflush(stderr); \
00108 return FALSE;
00109
00110 #define REPORTAR_ERROR_SOCKET() \
00111 fprintf(stderr, \
00112 "<CONEXION_TCP> - ERROR: no puedo abrir un sockete datagrama.\n" \
00113 " Motivo: "); \
00114 switch ( errno ) { \
00115 case EPROTONOSUPPORT: \
00116 fprintf(stderr, "Protocolo TCP/IP no soportado!\n"); \
00117 break; \
00118 case EMFILE: \
00119 fprintf(stderr, \
00120 "Este proceso tiene demasiados archivos abiertos.\n"); \
00121 break; \
00122 case ENFILE: \
00123 fprintf(stderr, \
00124 "Existen demasiados archivos abiertos en el sistema!\n"); \
00125 break; \
00126 case EACCES: \
00127 fprintf(stderr, "Acceso denegado para abrir sockets en TCP/IP.\n"); \
00128 break; \
00129 case ENOBUFS: \
00130 fprintf(stderr, "Memoria insuficiente para abrir el socket!\n"); \
00131 break; \
00132 default: \
00133 fprintf(stderr, "desconocido (%d).\n", errno); \
00134 break; \
00135 } \
00136 fflush(stderr); \
00137 return FALSE;
00138
00139 #define REPORTAR_ERROR_BIND() \
00140 fprintf(stderr, \
00141 "<CONEXION_TCP> - ERROR: no puedo agarrar un puerto local\n" \
00142 " Motivo: "); \
00143 switch ( errno ) { \
00144 case EBADF: \
00145 fprintf(stderr, "descriptor de socket invalido.\n"); \
00146 break; \
00147 case EINVAL: case EADDRINUSE: \
00148 fprintf(stderr, "el puerto %d esta ocupado por otro proceso.\n", \
00149 puerto_servidor); \
00150 break; \
00151 case EACCES: \
00152 fprintf(stderr,"acceso denegado para este usuario tratando\n" \
00153 " de abrir el puerto %d.\n", \
00154 puerto_servidor); \
00155 break; \
00156 case ENOTSOCK: \
00157 fprintf(stderr, "el descriptor de archivo no es un socket.\n"); \
00158 break; \
00159 default: \
00160 fprintf(stderr, "desconocido (%d).\n", errno); \
00161 break; \
00162 } \
00163 fflush(stderr); \
00164 return FALSE;
00165
00166 #endif
00167
00168 #if PLATAFORMA == i386_WIN32_VC
00169
00170 int WINSOCK_counter = 0;
00171
00172
00173 #define REPORTAR_ERROR_CONNECT() \
00174 fprintf(stderr, \
00175 "<CONEXION_TCP> - ERROR: El cliente no puede conectarse.\n"); \
00176 fflush(stderr); \
00177 return FALSE;
00178
00179 #define REPORTAR_ERROR_LISTEN() \
00180 fprintf(stderr, \
00181 "<CONEXION_TCP> - ERROR: El servidor no puede recibir conexiones.\n");\
00182 fflush(stderr); \
00183 return FALSE;
00184
00185 #define REPORTAR_ERROR_SOCKET() \
00186 fprintf(stderr, \
00187 "<CONEXION_TCP> - ERROR: no puedo abrir un sockete datagrama.\n"); \
00188 fflush(stderr); \
00189 return FALSE;
00190
00191 #define REPORTAR_ERROR_BIND() \
00192 fprintf(stderr, \
00193 "<CONEXION_TCP> - ERROR: no puedo agarrar un puerto local\n"); \
00194 fflush(stderr); \
00195 return FALSE;
00196
00197 #endif
00198
00199
00200
00201
00202
00203 CONEXION_TCP::CONEXION_TCP(char *nombre, int puerto)
00204 {
00205 _id = -666;
00206
00207 Nombre_servidor = new char[strlen(nombre) + 1];
00208
00209 if ( !Nombre_servidor ) {
00210 fprintf(stderr, "<CONEXION_TCP> - ERROR: Memoria insuficiente!\n");
00211 fflush(stderr);
00212 exit(1);
00213 }
00214
00215 strcpy(Nombre_servidor, nombre);
00216 puerto_servidor = puerto;
00217 }
00218
00219 CONEXION_TCP::CONEXION_TCP()
00220 {
00221 _id = -666;
00222 Nombre_servidor = new char[strlen("<dummy>") + 1];
00223
00224 if ( !Nombre_servidor ) {
00225 fprintf(stderr, "<CONEXION_TCP> - ERROR: Memoria insuficiente!\n");
00226 fflush(stderr);
00227 exit(1);
00228 }
00229
00230 strcpy(Nombre_servidor, "<dummy>");
00231 puerto_servidor = 0;
00232 }
00233
00234 CONEXION_TCP::~CONEXION_TCP()
00235 {
00236 cerrar();
00237 }
00238
00239 int
00240 CONEXION_TCP::id(void)
00241 {
00242 return _id;
00243 }
00244
00245 void
00246 CONEXION_TCP::set_id(int i)
00247 {
00248 _id = i;
00249 }
00250
00251 void
00252 CONEXION_TCP::cerrar(void)
00253 {
00254 #ifdef SOCKETS_ENABLED
00255 #ifdef UNIX_ENABLED
00256 close(sockfd);
00257 #endif
00258 #if PLATAFORMA == i386_WIN32_VC
00259 closesocket(sockfd);
00260 WINSOCK_counter--;
00261 if ( !WINSOCK_counter ) WSACleanup();
00262 #endif
00263 #endif
00264 }
00265
00266 BOOLEAN
00267 CONEXION_TCP::crear_como_servidor(void)
00273 {
00274 #ifndef SOCKETS_ENABLED
00275 fprintf(stderr,"<CONEXION_TCP> - ERROR: "
00276 "No se ha compilado soporte para sockets TCP.\n");
00277 fflush(stderr);
00278 return FALSE;
00279 #endif
00280
00281 #ifdef SOCKETS_ENABLED
00282 #if PLATAFORMA == i386_WIN32_VC
00283 int wcode;
00284 WORD wVersionRequested = MAKEWORD(1,1);
00285 WSADATA wsaData;
00286
00287
00288 if ( !WINSOCK_counter ) {
00289 wcode = WSAStartup(wVersionRequested, &wsaData);
00290 if ( wsaData.wVersion != wVersionRequested ) {
00291 fprintf(stderr,
00292 "<JED_TCP> - ERROR: Version incorrecta de Winsock!\n");
00293 fflush(stderr);
00294 WSACleanup();
00295 return FALSE;
00296 }
00297 if ( wcode == SOCKET_ERROR ) {
00298 fprintf(stderr,
00299 "<JED_TCP> - ERROR: Error de Winsock %d\n", WSAGetLastError());
00300 fflush(stderr);
00301 WSACleanup();
00302 return FALSE;
00303 }
00304 }
00305 WINSOCK_counter++;
00306 #endif
00307
00308
00309 sockfd = socket(AF_INET, SOCK_STREAM, 0);
00310 #ifdef UNIX_ENABLED
00311 if ( sockfd < 0 ) {
00312 REPORTAR_ERROR_SOCKET();
00313 }
00314 #endif
00315 #if PLATAFORMA == i386_WIN32_VC
00316 if( sockfd == INVALID_SOCKET ) {
00317 REPORTAR_ERROR_SOCKET();
00318 }
00319 #endif
00320
00321
00322 int code;
00323
00324
00325
00326 memset((char*)&direccion_servidor, 0, sizeof(direccion_servidor));
00327 direccion_servidor.sin_family = AF_INET;
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 direccion_servidor.sin_addr.s_addr = htonl(INADDR_ANY);
00338
00339
00340 direccion_servidor.sin_port = htons(puerto_servidor);
00341
00342
00343 code = bind(sockfd,
00344 (LPSOCKADDR)&direccion_servidor,
00345 sizeof(direccion_servidor));
00346 #ifdef UNIX_ENABLED
00347 if ( code < 0 ) {
00348 #endif
00349 #if PLATAFORMA == i386_WIN32_VC
00350 if( code == SOCKET_ERROR ) {
00351 #endif
00352 REPORTAR_ERROR_BIND();
00353 }
00354
00355
00356
00357 code = listen(sockfd, 5);
00358 #ifdef UNIX_ENABLED
00359 if ( code < 0 ) {
00360 #endif
00361 #if PLATAFORMA == i386_WIN32_VC
00362 if( code == SOCKET_ERROR ) {
00363 #endif
00364 REPORTAR_ERROR_LISTEN();
00365 }
00366
00367 return TRUE;
00368 #endif // SOCKETS_ENABLED
00369 }
00370
00371 CONEXION_TCP *
00372 CONEXION_TCP::aceptar_conexion(void)
00379 {
00380 #ifndef SOCKETS_ENABLED
00381 return NULL;
00382 #endif
00383
00384 #ifdef SOCKETS_ENABLED
00385 #ifdef UNIX_ENABLED
00386 int nuevo_sockfd;
00387 #endif
00388 #if PLATAFORMA == i386_WIN32_VC
00389 SOCKET nuevo_sockfd;
00390 #endif
00391 int long_data = sizeof(direccion_cliente);
00392 CONEXION_TCP *Nueva_conexion;
00393
00394 #ifdef DEBUG_TCP
00395 printf("<CONEXION_TCP> Estoy listo para aceptar clientes...\n");
00396 fflush(stdout);
00397 #endif
00398
00399 #if PLATAFORMA == i386_WIN32_VC
00400 int wcode;
00401 WORD wVersionRequested = MAKEWORD(1,1);
00402 WSADATA wsaData;
00403
00404 if ( !WINSOCK_counter ) {
00405 wcode = WSAStartup(wVersionRequested, &wsaData);
00406 if ( wsaData.wVersion != wVersionRequested ) {
00407 fprintf(stderr,
00408 "<JED_TCP> - ERROR: Version incorrecta de Winsock!\n");
00409 fflush(stderr);
00410 return FALSE;
00411 }
00412 }
00413 WINSOCK_counter++;
00414 #endif
00415
00416 nuevo_sockfd = accept(sockfd,
00417 (struct sockaddr *)&direccion_cliente,
00418 (SOCK_INT *)&long_data);
00419 #ifdef UNIX_ENABLED
00420 if ( nuevo_sockfd < 0 ) {
00421 #endif
00422 #if PLATAFORMA == i386_WIN32_VC
00423 if( nuevo_sockfd == INVALID_SOCKET ) {
00424 #endif
00425 return NULL;
00426 }
00427
00428 #ifdef DEBUG_TCP
00429 printf("Acepto una conexion del host con IP \"%s\", puerto %d\n",
00430 inet_ntoa(direccion_cliente.sin_addr),
00431 htons(direccion_cliente.sin_port)) ;
00432 #endif
00433 Nueva_conexion = new CONEXION_TCP();
00434
00435 if ( !Nueva_conexion ) {
00436 return NULL;
00437 }
00438
00439 Nueva_conexion->sockfd = nuevo_sockfd;
00440
00441 #ifdef DEBUG_TCP
00442 printf("<CONEXION_TCP> Creo una CONEXION_TCP para el nuevo cliente!\n");
00443 fflush(stdout);
00444 #endif
00445
00446 return Nueva_conexion;
00447 #endif
00448 }
00449
00450
00451 BOOLEAN
00452 CONEXION_TCP::crear_como_cliente(void)
00456 {
00457 #ifndef SOCKETS_ENABLED
00458 fprintf(stderr,"<CONEXION_TCP> - ERROR: "
00459 "No se ha compilado soporte para sockets TCP.\n");
00460 fflush(stderr);
00461 return FALSE;
00462 #endif
00463
00464 #ifdef SOCKETS_ENABLED
00465 #if PLATAFORMA == i386_WIN32_VC
00466 int wcode;
00467 WORD wVersionRequested = MAKEWORD(1,1);
00468 WSADATA wsaData;
00469
00470
00471 if ( !WINSOCK_counter ) {
00472 wcode = WSAStartup(wVersionRequested, &wsaData);
00473 if ( wsaData.wVersion != wVersionRequested ) {
00474 fprintf(stderr,
00475 "<JED_TCP> - ERROR: Version incorrecta de Winsock!\n");
00476 fflush(stderr);
00477 WSACleanup();
00478 return FALSE;
00479 }
00480 if ( wcode == SOCKET_ERROR ) {
00481 fprintf(stderr,
00482 "<JED_TCP> - ERROR: Error de Winsock %d\n", WSAGetLastError());
00483 fflush(stderr);
00484 WSACleanup();
00485 return FALSE;
00486 }
00487 }
00488 WINSOCK_counter++;
00489 #endif
00490
00491
00492 sockfd = socket(AF_INET, SOCK_STREAM, 0);
00493 if ( sockfd < 0 ) {
00494 REPORTAR_ERROR_SOCKET();
00495 }
00496
00497
00498
00499
00500 memset((void *)&direccion_servidor, 0, (int)sizeof(direccion_servidor));
00501 direccion_servidor.sin_family = AF_INET;
00502 direccion_servidor.sin_addr.s_addr = inet_addr(Nombre_servidor);
00503 direccion_servidor.sin_port = htons(puerto_servidor);
00504
00505
00506 int code;
00507
00508 code = connect( sockfd,
00509 (struct sockaddr *)&direccion_servidor,
00510 sizeof(direccion_servidor) );
00511 if ( code < 0 ) {
00512 REPORTAR_ERROR_CONNECT();
00513 }
00514
00515 return TRUE;
00516 #endif // SOCKETS_ENABLED
00517 }
00518
00519 int
00520 CONEXION_TCP::enviar(char *buffer, int tam_buffer)
00521 {
00522 #ifndef SOCKETS_ENABLED
00523 return -1;
00524 #endif // SOCKETS_ENABLED
00525
00526 #ifdef SOCKETS_ENABLED
00527
00528 #ifdef UNIX_ENABLED
00529
00530
00531
00532
00533
00534
00535 int n = write(sockfd, buffer, tam_buffer);
00536
00537
00538
00539
00540 return n;
00541 #endif
00542 #if PLATAFORMA == i386_WIN32_VC
00543 int n = send(sockfd, buffer, tam_buffer, 0);
00544
00545
00546
00547
00548
00549
00550
00551 return n;
00552 #endif
00553
00554 #endif // SOCKETS_ENABLED
00555 }
00556
00557 BOOLEAN
00558 CONEXION_TCP::pendiente(void)
00567 {
00568 #ifdef UNIX_ENABLED
00569 return _pendiente;
00570 #endif
00571 #ifndef UNIX_ENABLED
00572 return FALSE;
00573 #endif
00574 }
00575
00576 int
00577 CONEXION_TCP::recibir(char *buffer, int tam_buffer)
00578
00579
00580
00581 {
00582 #ifndef SOCKETS_ENABLED
00583 return -1;
00584 #endif // SOCKETS_ENABLED
00585
00586 #ifdef SOCKETS_ENABLED
00587 #ifdef UNIX_ENABLED
00588 int n;
00589
00590 n = recv(sockfd, buffer, tam_buffer, 0);
00591
00592 #if PLATAFORMA == i386_LINUX_GCC || PLATAFORMA == SPARC64_LINUX_GCC
00593 struct pollfd p = {sockfd, 0x03, 0x00};
00594
00595 if ( poll(&p, 1, 10) && p.revents & 0x01 ) {
00596 _pendiente = TRUE;
00597 }
00598 else {
00599 _pendiente = FALSE;
00600 }
00601 #endif
00602
00603 return n;
00604 #endif
00605 #if PLATAFORMA == i386_WIN32_VC
00606 int n = recv(sockfd, buffer, tam_buffer, 0);
00607
00608
00609
00610
00611
00612
00613
00614
00615 return n;
00616 #endif
00617 #endif // SOCKETS_ENABLED
00618 }
00619
00620 #if PLATAFORMA == i386_WIN32_VC
00621
00622 static void (*F)(void *, int);
00623 static void *Data;
00624
00625 #endif
00626
00627 void
00628 CONEXION_TCP::registro_asincronico(void (*f)(void *, int), void *User_data)
00629 {
00630 #ifdef SOCKETS_ENABLED
00631
00632
00633 #ifdef UNIX_ENABLED
00634 instalar_sistema_asincronico();
00635 registrar_entrada(sockfd, f, User_data);
00636 #endif
00637
00638
00639 #ifndef CBUILDER
00640 #if PLATAFORMA == i386_WIN32_VC
00641 int code;
00642 HWND ventana_virtual;
00643
00644 ventana_virtual = instalar_sistema_asincronico_sockets();
00645 registrar_entrada_sockets(sockfd, f, User_data);
00646
00647 code = WSAAsyncSelect(sockfd, ventana_virtual,
00648 666 ,
00649 FD_READ | FD_ACCEPT | FD_CLOSE
00650
00651 );
00652
00653 if ( code != 0 ) {
00654 fprintf(stderr, "<CONEXION_TCP> - ERROR: Fallo en WSAAsyncSelect.\n");
00655 fprintf(stderr, "WSAGetLastError = %d.\n", WSAGetLastError());
00656 fflush(stderr);
00657 exit(1);
00658 }
00659
00660
00661
00662
00663 F = f;
00664 Data = User_data;
00665 #endif // i386_WIN32_VC
00666 #endif // CBUILDER
00667
00668
00669 #ifdef DEBUG_TCP
00670 printf("<CONEXION_TCP> Registro funcion asincronica en fd %d\n", sockfd);
00671 fflush(stdout);
00672 #endif
00673 #endif // SOCKETS_ENABLED
00674 }
00675
00676
00677
00678
00679