//----< get message content>----------------------------------------- /////////////////////////////////////////////////////////////////////////////////////////////// ////readMsg's function is very similar with readline std::string Socket::readMsg() { std::string temp1; char block[1]; size_t pos=0; size_t count=0; size_t record[2]; record[0] = 0; int contentsize=0; while (true) { if (!recvAll(block, 1)) return ""; if (block[0] != '\n' && block[0] != '\r') { temp1 += block[0]; if (block[0] == ',') { if (count == 2) record[0] = pos; if (count == 3) { record[1] = pos; std::string test; test = temp1.substr(record[0] + 1, pos - record[0] - 1); contentsize = atoi(test.c_str()); } if (count == 4) { for (int i = 0; i < contentsize; i++) { bool temp2 = recvAll(block, 1); temp1 += block[0]; } } count++; } pos++; } else { temp1 += '\n'; if (bytesLeft() > 0) { char last = block[0]; ::recv(s_, block, 1, MSG_PEEK);// remove remaining newline or carriage return if next in buffer if (last == '\n' && block[0] == '\r') recv(block, 1); else if (last == '\r' && block[0] == '\n') recv(block, 1); } return temp1; } } return temp1; }
/* * - removes ending newline if present, else reads to end of buffer * - returns empty string if not successful * */ std::string Socket::readLine() { std::string temp; char block[1]; //while(bytesLeft() > 0) // don't block while(true) { if(!recvAll(block,1)) return ""; // save all chars that are not newlines or carriage returns if(block[0] != '\n' && block[0] != '\r') temp += block[0]; else { temp += '\n'; if(bytesLeft() > 0) { char last = block[0]; // remove remaining newline or carriage return if next in buffer ::recv(s_,block,1,MSG_PEEK); if(last == '\n' && block[0] == '\r') recv(block,1); else if(last == '\r' && block[0] == '\n') recv(block, 1); } return temp; } } return temp; }
void *solicitar_solicitar_bytes(int socket_umv, uint32_t base, uint32_t offset, int tamanio, uint32_t id_programa, char origen, t_log *logger) { uint32_t bEnv = 0; char *orden = codificar_solicitar_bytes(base,offset,tamanio,id_programa); void *valorRetorno = NULL; t_paquete_programa paq_saliente; paq_saliente.id = origen; paq_saliente.mensaje = orden; log_info(logger, "[INTERFAZ_UMV] [ORDEN] [%c] - %s", origen, orden); paq_saliente.sizeMensaje = strlen(orden); char *paqueteSaliente = serializar_paquete(&paq_saliente, logger); bEnv = paq_saliente.tamanio_total; if(sendAll(socket_umv, paqueteSaliente, &bEnv)){ log_error(logger, "[INTERFAZ_UMV] Error en la solicitud de solicitar_bytes. Motivo: %s", strerror(errno)); free(paqueteSaliente); free(orden); return 0; } free(paqueteSaliente); free(orden); uint32_t bRec = 0; t_paquete_programa respuesta; log_info(logger, "[INTERFAZ_UMV] Esperando la respuesta de la UMV al comando solicitar_bytes."); bRec = recvAll(&respuesta, socket_umv); log_info(logger, "[INTERFAZ_UMV] La UMV respondió %s", respuesta.mensaje); valorRetorno = (void *) respuesta.mensaje; return valorRetorno; }
Message Next(int sock){ char buf[8]; recvAll(sock,buf,8); Message result; result.type=*(Type*)buf; result.size=*(uint8_t*)(buf+4); //DBG("Just recved type=%d size=%u\n",result.type,result.size); if(result.size>MAX_BODY_SIZE){ throw std::runtime_error("Received message body too large"); } result.body.resize(result.size); recvAll(sock,&result.body[0],result.size); //DBG("Finished a msg"); return result; }
void *atencionConexiones(void *config) { t_log *logger = (t_log *) (((t_config_conexion *) config)->logger); int *sock = (int *) (((t_config_conexion *) config)->socket); t_param_memoria *parametros_memoria = (t_param_memoria *) (((t_config_conexion *) config)->parametros_memoria); pthread_t *punteroAEsteHilo = (pthread_t *) (((t_config_conexion *) config)->hilo); t_paquete_programa paq; int bytesRecibidos = 0; int atendiendoSolicitud = 1; pthread_mutex_init(&op_atomica, NULL); while(atendiendoSolicitud){ bytesRecibidos = recvAll(&paq, *sock); log_info(logger, "[ATENCION_CONN] Recibí una solicitud de %d bytes.", bytesRecibidos); if(bytesRecibidos == 0){ //independientemente que haya sido una cpu o el plp, este hilo ya no tiene nada que hacer. log_info(logger, "[ATENCION_CONN] Se desconectó una CPU (lo más probable). Este hilo de atención finalizará ahora."); goto liberarRecursos; } switch(paq.id){ case 'P': ; int resp = 0; handler_plp(*sock, &resp, paq.mensaje, parametros_memoria, logger); break; case 'C': ; void *resp_buf = NULL; handler_cpu(*sock, resp_buf, paq.mensaje, parametros_memoria, logger); break; case 'H': log_info(logger, "[ATENCION_CONN] Recibí un handshake del Kernel"); log_info(logger, "[ATENCION_CONN] El mensaje del handshake es: %s\n", paq.mensaje); break; case 'F': default: log_info(logger, "[ATENCION_CONN] No puedo identificar el tipo de conexión"); //close(*sock); atendiendoSolicitud = 0; } free(paq.mensaje); bytesRecibidos = 0; } liberarRecursos: free(sock); free(parametros_memoria); free(punteroAEsteHilo); free(config); pthread_exit(NULL); }
char *solicitarInstruccion(t_intructions instruccion) { int mensaje[5]; mensaje[0] = LEER; mensaje[1] = instruccion.start / tamanio_pagina;//Pagina en la que esta el codigo mensaje[2] = instruccion.start % tamanio_pagina;//Offset de la pagina mensaje[3] = instruccion.offset; //Size de la instruccion mensaje[4] = pcb_actual.pid; //pid printf("Start instruccion: %d, offset: %d.\n",instruccion.start,instruccion.offset); printf("msj %d, pag %d, offset %d, size %d, pid %d.\n", mensaje[0],mensaje[1],mensaje[2],mensaje[3],mensaje[4]); send(socket_umc, &mensaje, 5*sizeof(int), 0); //Recibo la respuesta si hay stack_overflow recv(socket_umc,&mensaje[0],sizeof(int),0); if(mensaje[0] == OVERFLOW) { printf("Error al solicitar instruccion: STACK_OVERFLOW\n"); return NULL; } char *resultado = malloc(instruccion.offset + 1); printf("Espero el resultado...\n"); if( recvAll(socket_umc,resultado,instruccion.offset,MSG_WAITALL) <= 0) { perror("Error al recibir instruccion"); } //Le agrego un \0 al resultado resultado[instruccion.offset] = '\0'; printf("Pude recibir la instruccion:\n\n"); fwrite(resultado,sizeof(char),instruccion.offset,stdout); printf("\n\n"); return resultado; }
uint32_t solicitar_enviar_bytes(int socket_umv, uint32_t base, uint32_t offset, int tamanio, void *buffer, uint32_t id_programa, char origen, t_log *logger) { uint32_t bEnv = 0; uint32_t tamanio_de_la_orden_completa = 0; char *orden = codificar_enviar_bytes(base,offset,tamanio,buffer,id_programa,&tamanio_de_la_orden_completa); uint32_t valorRetorno = 0; t_paquete_programa paq_saliente; paq_saliente.id = origen; paq_saliente.mensaje = orden; log_info(logger, "[INTERFAZ_UMV] [ORDEN] [%c] - %s", origen, orden); paq_saliente.sizeMensaje = tamanio_de_la_orden_completa; char *paqueteSaliente = serializar_paquete(&paq_saliente, logger); bEnv = paq_saliente.tamanio_total; if(sendAll(socket_umv, paqueteSaliente, &bEnv)){ log_error(logger, "[INTERFAZ_UMV] Error en la solicitud de enviar bytes para el segmento de código. Motivo: %s", strerror(errno)); free(paqueteSaliente); free(orden); return 0; } free(paqueteSaliente); free(orden); uint32_t bRec = 0; t_paquete_programa respuesta; log_info(logger, "[INTERFAZ_UMV] Esperando la respuesta de la UMV al comando enviar_bytes."); bRec = recvAll(&respuesta, socket_umv); log_info(logger, "[INTERFAZ_UMV] La UMV respondió %s", respuesta.mensaje); valorRetorno = atoi(respuesta.mensaje); free(respuesta.mensaje); return valorRetorno; }
/** Receive a raw string (not encoded by msgpack). * This IO call blocks. * We pass the lua_State to avoid mixing thread contexts. */ LuaStackSize lk::Socket::recv(lua_State *L) { if (lua_isnumber(L, 3)) { setRecvTimeout(lua_tonumber(L, 3)); } if (lua_isnumber(L, 2)) { // <self> <num_bytes> [<timeout>] return recvBytes(L, lua_tonumber(L, 2)); } else if (lua_isstring(L, 2)) { // <self> <mode> [<timeout>] const char *mode = lua_tostring(L, 2); if (mode[0] == '*' && mode[1] == 'a') { return recvAll(L); } else if (mode[0] == '*' && mode[1] == 'l') { return recvLine(L); } else { throw dub::Exception("Bad mode to recv (should be '*a' or '*l' but found '%s')", mode); } } // receive a single line (not returning \r or \n). return recvLine(L); return 1; }
uint32_t solicitar_crear_segmento(int socket_umv, uint32_t id_programa, uint32_t tamanio_segmento, char origen, t_log *logger) { uint32_t bEnv = 0; char *orden = codificar_crear_segmento(id_programa, tamanio_segmento); uint32_t valorRetorno = 0; t_paquete_programa paq_saliente; paq_saliente.id = origen; paq_saliente.mensaje = orden; log_info(logger, "[INTERFAZ_UMV] [ORDEN] [%c] - %s", origen, orden); paq_saliente.sizeMensaje = strlen(orden); char *paqueteSaliente = serializar_paquete(&paq_saliente, logger); bEnv = paq_saliente.tamanio_total; if(sendAll(socket_umv, paqueteSaliente, &bEnv)){ log_error(logger, "[INTERFAZ_UMV] Error en la solicitud de creación de segmento. Motivo: %s", strerror(errno)); free(paqueteSaliente); free(orden); return 0; } free(paqueteSaliente); free(orden); uint32_t bRec = 0; t_paquete_programa respuesta; log_info(logger, "[INTERFAZ_UMV] Esperando la respuesta de la UMV al comando crear_segmento."); bRec = recvAll(&respuesta, socket_umv); log_info(logger, "[INTERFAZ_UMV] La UMV respondió %s", respuesta.mensaje); valorRetorno = atoi(respuesta.mensaje); free(respuesta.mensaje); return valorRetorno; }
int ClientSocket::recvNr() { int ret = 0; recvAll(&ret, 4); return ret; }
float ClientSocket::recvFloat32() { float ret = 0; recvAll(&ret, sizeof(float)); return ret; }
int32_t ClientSocket::recvInt32() { int32_t ret = -1; recvAll(&ret, sizeof(int32_t)); return ret; }
//check for the incoming file after waiting for a connection int receiveFile(int port, char** inputFile, long* fileLength){ int receiveSocket, acceptedSocket; int err, portStrlen; char *portStr; struct addrinfo *res, *curr; struct addrinfo hints; struct sockaddr incomingAddr; socklen_t incomingAddrSize = sizeof(incomingAddr); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; portStrlen = ceil(log10((float)(port))) + 1; portStr = (char *)(malloc(portStrlen * sizeof(char))); sprintf(portStr, "%d", port); err = getaddrinfo(NULL,portStr, &hints, &res); if(err){return GETADDR_ERROR;} err = -1; curr = res; while(NULL != curr){ receiveSocket = socket((*curr).ai_family, (*curr).ai_socktype, (*curr).ai_protocol); if(-1 != receiveSocket){ err = bind(receiveSocket, (*curr).ai_addr, (*curr).ai_addrlen); } if(-1 != err){ break; } close(receiveSocket); curr = (*curr).ai_next; } if(NULL == curr){ return SOCKET_ABSENT_ERROR; } freeaddrinfo(res); //start off the connection listening interface and wait for connections long amtReceived = 0; printf("Waiting for connections.\n"); err = listen(receiveSocket, 1); if(err) {return ERROR;} acceptedSocket = accept(receiveSocket, &incomingAddr, &incomingAddrSize); if(-1 == acceptedSocket){return ERROR;} printf("Inbound file.\n"); char * buff = (char*)(malloc(1 * sizeof(uint32_t))); recvAll(acceptedSocket, buff, 1*sizeof(uint32_t)); *fileLength = ntohl( *((long*)(buff))); *inputFile = (char*)(malloc( *fileLength *sizeof(char))); recvAll(acceptedSocket, *inputFile, *fileLength); return NONE; }
int main(int argc, char *argv[]) { int errorArgumentos = 0; int errorLogger = 0; int errorConfig = 0; int errorConexion = 0; int errorEnvio = 0; int statusRecepcion = 0; //Variables para el script FILE *script = NULL; //Variables para el logger t_log *logger = NULL; //Variables para el socket int unSocket = -1; struct sockaddr_in socketInfo; //Variables para la carga de la configuración t_config *config = NULL; errorArgumentos = checkArgs(argc); errorLogger = crearLogger(&logger); errorConfig = cargarConfig(&config); if(errorArgumentos || errorLogger || errorConfig) { goto liberarRecursos; return EXIT_FAILURE; } int puerto = config_get_int_value(config, "Puerto"); char *ip_kernel = config_get_string_value(config, "IP"); if ((script = fopen(argv[1],"r")) != NULL) { //Pudimos abrir el archivo correctamente //Entonces creamos la conexión log_info(logger, "Conectando a %s:%d ...", ip_kernel, puerto); errorConexion = crear_conexion_saliente(&unSocket, &socketInfo, ip_kernel, puerto, logger, "PROGRAMA"); if (errorConexion) { log_error(logger, "Error al conectar con el Kernel."); goto liberarRecursos; return EXIT_FAILURE; } log_info(logger, "Conexión establecida."); log_info(logger, "Comenzando a enviar el script AnSISOP."); errorEnvio = enviarDatos(script, unSocket, logger); if (errorEnvio) { goto liberarRecursos; return EXIT_FAILURE; } else { finalizarEnvio(&unSocket); log_info(logger, "Transmisión finalizada."); } //acá se abre la guarda para el modo debug t_paquete_programa paq; while(1){ statusRecepcion = recvAll(&paq, unSocket); if(statusRecepcion == 0){ log_error(logger, "Hubo un error al recibir un mensaje del Kernel."); } else { if(ejecutarMensajeKernel(paq.mensaje)){ //Si es 0 era porque era un imprimir/imprimirTexto. Si es 1, hay que terminar. log_info(logger, "Finalizó la ejecución del programa."); free(paq.mensaje); goto liberarRecursos; break; } } } //acá se cierra la guarda para el modo debug } else { log_error(logger,"No se pudo abrir el script AnSISOP. Motivo: %s", strerror(errno)); goto liberarRecursos; return EXIT_FAILURE; } goto liberarRecursos; return EXIT_SUCCESS; liberarRecursos: if(unSocket != -1) close(unSocket); if(script) fclose(script); if(logger) log_destroy(logger); if(config) config_destroy(config); }
static void* x11connThreadWriteProc(void* dataPtr) { X11ConnData* data = (X11ConnData*)dataPtr; unsigned char *buf = NULL; size_t bufLen = 0; { xConnSetupPrefix header; if (!recvAll(data->server, &header, sz_xConnSetupPrefix)) goto done; if (!sendAll(data->client, &header, sz_xConnSetupPrefix)) goto done; log_debug("Server connection setup reply: %d\n", header.success); size_t dataLength = header.length * 4; bufSize(&buf, &bufLen, dataLength); if (!recvAll(data->server, buf, dataLength)) goto done; if (!sendAll(data->client, buf, dataLength)) goto done; } bufSize(&buf, &bufLen, sz_xReply); while (!data->exiting) { if (!recvAll(data->server, buf, sz_xReply)) goto done; size_t ofs = sz_xReply; const xReply* reply = (xReply*)buf; if (reply->generic.type == X_Reply || reply->generic.type == GenericEvent) { size_t dataLength = reply->generic.length * 4; bufSize(&buf, &bufLen, ofs + dataLength); reply = (xReply*)buf; // in case bufSize moved buf if (!recvAll(data->server, buf+ofs, dataLength)) goto done; ofs += dataLength; } log_debug2(" [%d]Response: %d sequenceNumber=%d length=%d\n", data->index, reply->generic.type, reply->generic.sequenceNumber, ofs); if (reply->generic.type == X_Reply) { switch (data->notes[reply->generic.sequenceNumber]) { case Note_X_GetGeometry: { xGetGeometryReply* reply = (xGetGeometryReply*)buf; log_debug2(" XGetGeometry(%d,%d,%d,%d)\n", reply->x, reply->y, reply->width, reply->height); fixCoords(&reply->x, &reply->y, &reply->width, &reply->height); log_debug2(" -> (%d,%d,%d,%d)\n", reply->x, reply->y, reply->width, reply->height); break; } case Note_X_InternAtom_Other: { xInternAtomReply* reply = (xInternAtomReply*)buf; log_debug2(" X_InternAtom: atom=%d\n", reply->atom); break; } case Note_X_QueryExtension_XFree86_VidModeExtension: { xQueryExtensionReply* reply = (xQueryExtensionReply*)buf; log_debug2(" X_QueryExtension (XFree86-VidModeExtension): present=%d major_opcode=%d first_event=%d first_error=%d\n", reply->present, reply->major_opcode, reply->first_event, reply->first_error); if (reply->present) data->opcode_XFree86_VidModeExtension = reply->major_opcode; break; } case Note_X_QueryExtension_RANDR: { xQueryExtensionReply* reply = (xQueryExtensionReply*)buf; log_debug2(" X_QueryExtension (RANDR): present=%d major_opcode=%d first_event=%d first_error=%d\n", reply->present, reply->major_opcode, reply->first_event, reply->first_error); if (reply->present) data->opcode_RANDR = reply->major_opcode; break; } case Note_X_QueryExtension_Xinerama: { xQueryExtensionReply* reply = (xQueryExtensionReply*)buf; log_debug2(" X_QueryExtension (XINERAMA): present=%d major_opcode=%d first_event=%d first_error=%d\n", reply->present, reply->major_opcode, reply->first_event, reply->first_error); if (reply->present) data->opcode_Xinerama = reply->major_opcode; break; } case Note_X_QueryExtension_NV_GLX: { xQueryExtensionReply* reply = (xQueryExtensionReply*)buf; log_debug2(" X_QueryExtension (NV-GLX): present=%d major_opcode=%d first_event=%d first_error=%d\n", reply->present, reply->major_opcode, reply->first_event, reply->first_error); if (reply->present) data->opcode_NV_GLX = reply->major_opcode; break; } case Note_X_QueryExtension_Other: { xQueryExtensionReply* reply = (xQueryExtensionReply*)buf; log_debug2(" X_QueryExtension: present=%d major_opcode=%d first_event=%d first_error=%d\n", reply->present, reply->major_opcode, reply->first_event, reply->first_error); break; } case Note_X_XF86VidModeGetModeLine: { xXF86VidModeGetModeLineReply* reply = (xXF86VidModeGetModeLineReply*)buf; log_debug2(" X_XF86VidModeGetModeLine(%d x %d)\n", reply->hdisplay, reply->vdisplay); fixSize(&reply->hdisplay, &reply->vdisplay); log_debug2(" -> (%d x %d)\n", reply->hdisplay, reply->vdisplay); break; } case Note_X_XF86VidModeGetAllModeLines: { xXF86VidModeGetAllModeLinesReply* reply = (xXF86VidModeGetAllModeLinesReply*)buf; xXF86VidModeModeInfo* modeInfos = (xXF86VidModeModeInfo*)(buf + sz_xXF86VidModeGetAllModeLinesReply); for (size_t i=0; i<reply->modecount; i++) { xXF86VidModeModeInfo* modeInfo = modeInfos + i; log_debug2(" X_XF86VidModeGetAllModeLines[%d] = %d x %d\n", i, modeInfo->hdisplay, modeInfo->vdisplay); fixSize(&modeInfo->hdisplay, &modeInfo->vdisplay); log_debug2(" -> %d x %d\n", modeInfo->hdisplay, modeInfo->vdisplay); } break; } case Note_X_RRGetScreenInfo: { xRRGetScreenInfoReply* reply = (xRRGetScreenInfoReply*)buf; xScreenSizes* sizes = (xScreenSizes*)(buf+sz_xRRGetScreenInfoReply); for (size_t i=0; i<reply->nSizes; i++) { xScreenSizes* size = sizes+i; log_debug2(" X_RRGetScreenInfo[%d] = %d x %d\n", i, size->widthInPixels, size->heightInPixels); fixSize(&size->widthInPixels, &size->heightInPixels); log_debug2(" -> %d x %d\n", size->widthInPixels, size->heightInPixels); } break; } case Note_X_RRGetScreenResources: { xRRGetScreenResourcesReply* reply = (xRRGetScreenResourcesReply*)buf; void* ptr = buf+sz_xRRGetScreenResourcesReply; ptr += reply->nCrtcs * sizeof(CARD32); ptr += reply->nOutputs * sizeof(CARD32); for (size_t i=0; i<reply->nModes; i++) { xRRModeInfo* modeInfo = (xRRModeInfo*)ptr; log_debug2(" X_RRGetScreenResources[%d] = %d x %d\n", i, modeInfo->width, modeInfo->height); fixSize(&modeInfo->width, &modeInfo->height); log_debug2(" -> %d x %d\n", modeInfo->width, modeInfo->height); ptr += sz_xRRModeInfo; } break; } case Note_X_RRGetCrtcInfo: { xRRGetCrtcInfoReply* reply = (xRRGetCrtcInfoReply*)buf; log_debug2(" X_RRGetCrtcInfo = %dx%d @ %dx%d\n", reply->width, reply->height, reply->x, reply->y); if (reply->mode != None) { fixMonitor(&reply->x, &reply->y, &reply->width, &reply->height); if (!reply->width || !reply->height) { reply->x = reply->y = reply->width = reply->height = 0; reply->mode = None; reply->rotation = reply->rotations = RR_Rotate_0; reply->nOutput = reply->nPossibleOutput = 0; } } log_debug2(" -> %dx%d @ %dx%d\n", reply->width, reply->height, reply->x, reply->y); break; } case Note_X_XineramaQueryScreens: { xXineramaQueryScreensReply* reply = (xXineramaQueryScreensReply*)buf; xXineramaScreenInfo* screens = (xXineramaScreenInfo*)(buf+sz_XineramaQueryScreensReply); for (size_t i=0; i<reply->number; i++) { xXineramaScreenInfo* screen = screens+i; log_debug2(" X_XineramaQueryScreens[%d] = %dx%d @ %dx%d\n", i, screen->width, screen->height, screen->x_org, screen->y_org); fixCoords(&screen->x_org, &screen->y_org, &screen->width, &screen->height); log_debug2(" -> %dx%d @ %dx%d\n", screen->width, screen->height, screen->x_org, screen->y_org); } break; } case Note_NV_GLX: { #if 0 char fn[256]; static int counter = 0; sprintf(fn, "/tmp/hax11-NV-%d-rsp-%d", reply->generic.sequenceNumber, counter++); FILE* f = fopen(fn, "wb"); fwrite(buf, 1, ofs, f); fclose(f); #endif break; } } } if (config.debug >= 2 && config.actualX && config.actualY && memmem(buf, ofs, &config.actualX, 2) && memmem(buf, ofs, &config.actualY, 2)) log_debug2(" Found actualW/H in output! ----------------------------------------------------------------------------------------------\n"); if (!sendAll(data->client, buf, ofs)) goto done; } done: log_debug("Exiting write thread.\n"); data->exiting = 1; close(data->client); close(data->server); return NULL; }
static void* x11connThreadReadProc(void* dataPtr) { X11ConnData* data = (X11ConnData*)dataPtr; unsigned char *buf = NULL; size_t bufLen = 0; bufSize(&buf, &bufLen, 1<<16); xConnClientPrefix header; if (!recvAll(data->client, &header, sizeof(header))) goto done; if (header.byteOrder != 'l') { log_debug("Unsupported byte order %c!\n", header.byteOrder); goto done; } if (!sendAll(data->server, &header, sz_xConnClientPrefix)) goto done; if (!recvAll(data->client, buf, pad(header.nbytesAuthProto))) goto done; if (!sendAll(data->server, buf, pad(header.nbytesAuthProto))) goto done; if (!recvAll(data->client, buf, pad(header.nbytesAuthString))) goto done; if (!sendAll(data->server, buf, pad(header.nbytesAuthString))) goto done; unsigned short sequenceNumber = 0; while (!data->exiting) { sequenceNumber++; size_t ofs = 0; if (!recvAll(data->client, buf+ofs, sz_xReq)) goto done; ofs += sz_xReq; const xReq* req = (xReq*)buf; uint requestLength = req->length * 4; if (requestLength == 0) // Big Requests Extension { recvAll(data->client, buf+ofs, 4); requestLength = *(uint*)(buf+ofs) * 4; ofs += 4; } log_debug2("[%d][%d] Request %d (%s) with data %d, length %d\n", data->index, sequenceNumber, req->reqType, requestNames[req->reqType], req->data, requestLength); bufSize(&buf, &bufLen, requestLength); req = (xReq*)buf; // in case bufSize moved buf if (!recvAll(data->client, buf+ofs, requestLength - ofs)) goto done; data->notes[sequenceNumber] = Note_None; switch (req->reqType) { // Fix for games that create the window of the wrong size or on the wrong monitor. case X_CreateWindow: { xCreateWindowReq* req = (xCreateWindowReq*)buf; log_debug2(" XCreateWindow(%dx%d @ %dx%d)\n", req->width, req->height, req->x, req->y); fixCoords(&req->x, &req->y, &req->width, &req->height); log_debug2(" -> (%dx%d @ %dx%d)\n", req->width, req->height, req->x, req->y); break; } case X_ConfigureWindow: { xConfigureWindowReq* req = (xConfigureWindowReq*)buf; INT16 dummyXY = 0; CARD16 dummyW = config.mainW; CARD16 dummyH = config.mainH; INT16 *x = &dummyXY, *y = &dummyXY; CARD16 *w = &dummyW, *h = &dummyH; int* ptr = (int*)(buf + sz_xConfigureWindowReq); if (req->mask & 0x0001) // x { x = (INT16*)ptr; ptr++; } if (req->mask & 0x0002) // y { y = (INT16*)ptr; ptr++; } if (req->mask & 0x0004) // width { w = (CARD16*)ptr; ptr++; } if (req->mask & 0x0008) // height { h = (CARD16*)ptr; ptr++; } log_debug2(" XConfigureWindow(%dx%d @ %dx%d)\n", *w, *h, *x, *y); fixCoords(x, y, w, h); log_debug2(" -> (%dx%d @ %dx%d)\n", *w, *h, *x, *y); break; } // Fix for games setting their window size based on the X root window size // (which can encompass multiple physical monitors). case X_GetGeometry: { data->notes[sequenceNumber] = Note_X_GetGeometry; break; } case X_InternAtom: { xInternAtomReq* req = (xInternAtomReq*)buf; const char* name = (const char*)(buf + sz_xInternAtomReq); log_debug2(" XInternAtom: %.*s\n", req->nbytes, name); data->notes[sequenceNumber] = Note_X_InternAtom_Other; break; } case X_ChangeProperty: { xChangePropertyReq* req = (xChangePropertyReq*)buf; log_debug2(" XChangeProperty: property=%d type=%d format=%d)\n", req->property, req->type, req->format); if (req->type == XA_WM_SIZE_HINTS) { XSizeHints* data = (XSizeHints*)(buf + sz_xChangePropertyReq); fixCoords((INT16*)&data->x, (INT16*)&data->y, (CARD16*)&data->width, (CARD16*)&data->height); fixSize((CARD16*)&data->max_width, (CARD16*)&data->max_height); fixSize((CARD16*)&data->base_width, (CARD16*)&data->base_height); } break; } case X_QueryExtension: { xQueryExtensionReq* req = (xQueryExtensionReq*)buf; const char* name = (const char*)(buf + sz_xQueryExtensionReq); log_debug2(" XQueryExtension(%.*s)\n", req->nbytes, name); if (!strmemcmp("XFree86-VidModeExtension", name, req->nbytes)) data->notes[sequenceNumber] = Note_X_QueryExtension_XFree86_VidModeExtension; else if (!strmemcmp("RANDR", name, req->nbytes)) data->notes[sequenceNumber] = Note_X_QueryExtension_RANDR; else if (!strmemcmp("XINERAMA", name, req->nbytes)) data->notes[sequenceNumber] = Note_X_QueryExtension_Xinerama; else if (!strmemcmp("NV-GLX", name, req->nbytes)) data->notes[sequenceNumber] = Note_X_QueryExtension_NV_GLX; else data->notes[sequenceNumber] = Note_X_QueryExtension_Other; } case 0: break; default: { if (req->reqType == data->opcode_XFree86_VidModeExtension) { xXF86VidModeGetModeLineReq* req = (xXF86VidModeGetModeLineReq*)buf; log_debug2(" XFree86_VidModeExtension - %d\n", req->xf86vidmodeReqType); switch (req->xf86vidmodeReqType) { case X_XF86VidModeGetModeLine: data->notes[sequenceNumber] = Note_X_XF86VidModeGetModeLine; break; case X_XF86VidModeGetAllModeLines: data->notes[sequenceNumber] = Note_X_XF86VidModeGetAllModeLines; break; } } else if (req->reqType == data->opcode_RANDR) { log_debug2(" RANDR - %d\n", req->data); switch (req->data) { case X_RRGetScreenInfo: data->notes[sequenceNumber] = Note_X_RRGetScreenInfo; break; case X_RRGetScreenResources: data->notes[sequenceNumber] = Note_X_RRGetScreenResources; break; case X_RRGetCrtcInfo: data->notes[sequenceNumber] = Note_X_RRGetCrtcInfo; break; } } else if (req->reqType == data->opcode_Xinerama) { log_debug2(" Xinerama - %d\n", req->data); switch (req->data) { case X_XineramaQueryScreens: data->notes[sequenceNumber] = Note_X_XineramaQueryScreens; break; } } else if (req->reqType == data->opcode_NV_GLX) { #if 0 char fn[256]; sprintf(fn, "/tmp/hax11-NV-%d-req", sequenceNumber); FILE* f = fopen(fn, "wb"); fwrite(buf, 1, requestLength, f); fclose(f); #endif data->notes[sequenceNumber] = Note_NV_GLX; } break; } } if (config.debug >= 2 && config.actualX && config.actualY && memmem(buf, requestLength, &config.actualX, 2) && memmem(buf, requestLength, &config.actualY, 2)) log_debug2(" Found actualW/H in input! ----------------------------------------------------------------------------------------------\n"); if (!sendAll(data->server, buf, requestLength)) goto done; } done: log_debug("Exiting read thread.\n"); data->exiting = 1; close(data->client); close(data->server); return NULL; }