Bueno estoy trabajando con un servidor proxy HTTP y parece que hay problemas con los sockets al hacer accept(), antes de nada decir que uso el navegador para conectar al servidor, decir que es un proxy recibe petición del navegador carga la peticion y la manda al servidor con CURL, y mando la respuesta al socket.
WSAEINTR 10004 Interrupted function call: A blocking operation was interrupted by a call to WSACancelBlockingCall.
Esto quiere decir que alguien ha llamado llamado a WSACancelBlockingCall y las funciones de espera asociadas a sockets no funcionan como recv o accept ya que son funciones que se bloquean hasta obtener una respuesta a no ser que se las ponga un temporizador máximo de espera, si se llama a esta función esa espera desaparece haciéndolas inútiles.
El código:
Código
void Run(std::string serverIP, UINT serverPort) { WSADATA wsa; SOCKET serverSocket; sockaddr_in serverAddr; WSAStartup(MAKEWORD(2, 0), &wsa); if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR) { serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(serverPort); serverAddr.sin_addr.s_addr = inet_addr(serverIP.c_str()); if (::bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) != SOCKET_ERROR) { if (listen(serverSocket, MAXIMUM_VICTIMS) != SOCKET_ERROR) { SOCKET victimSocket; sockaddr_in victimAddr; victimAddr.sin_family = AF_INET; INT len = sizeof(victimAddr); while (status != DISABLE) { victimSocket = accept(serverSocket, (sockaddr*)&victimAddr, &len); if (victimSocket != INVALID_SOCKET) { std::thread t(HTTPSession, victimSocket, inet_ntoa(victimAddr.sin_addr), status); t.detach(); } } } } closesocket(serverSocket); } WSACleanup(); }
Las 2 primeras requests del cliente las recibe y responde con éxito pero a partir de la segunda request tras enviar la respuesta llama a WSACancelBlockingCall, ¿porque? ¿cómo evitarlo?.
Una vez que sale el error 10004 el bucle itera produciendo errores 10093 (WSANOTINITIALISED).
Puede que sea llamada en HTTPSession:
Código
void HTTPSession(SOCKET victimSocket, std::string victimIP, STATUS& controller) { CHAR headerBuffer[8192]; memset(headerBuffer, '\0', 8192); INT rlen = recv(victimSocket, headerBuffer, 8192, NULL); ... }
Reading: http://www.sockets.com/winsock.htm#CancelBlockingCall
Estoy probando a ponerlo en blocking mode de nuevo con:
Código
Pero falla de nuevo por el error 10004.
ULONG iMode = 0;//blocking mode ioctlsocket(victimSocket, FIONBIO, &iMode);
Saludos.
Edito: Bueno, decir que esta parcialmente arreglado con una chapuza que trataré de mejorar, lo que vengo a hacer es reestablecer el modo block despues de cada accept para el socket "victimSocket", así si al llamar al thread y hacer el recv() se llama a cancelblocking rapidamente se reestablecera tras obtener la respuesta de recv. Hay que llamar a WSAStartup pues la llamada a cancelblocking llama a WSACleanup().
Código
ULONG iMode = 0;//block mode while (status != DISABLE) { victimSocket = accept(serverSocket, (sockaddr*)&victimAddr, &len); if (victimSocket != INVALID_SOCKET) { std::thread t(HTTPSession, victimSocket, inet_ntoa(victimAddr.sin_addr), status); t.detach(); } WSAStartup(MAKEWORD(2, 0), &wsa); INT iResult = ioctlsocket(victimSocket, FIONBIO, &iMode); if (iResult != NO_ERROR) printf("ioctlsocket failed with error: %ld %d\n", iResult, GetLastError()); }
PD: He probado a hacerlo solo cuando de error y no funciona, sería curar con esto prevenimos siempre pero evidentemente no me convence tener que llamar a WSAStartup en un bucle, buscaré mejores alternativas..
Edito otra vez: NO hace falta usar ioctlsocket para ponerlo en modo block, solo con llamar a WSAStartup ya funciona y no da error :""""(, la cosa es que parece que para cada socket hay que llamar a WSAStartup así que meteré la llamada en HTTPSession.