static void *msg_flush_thread(void *arg) { while (1) { msg_flush(); if (cancel) break; sleep_ms(XK_MSG_FLUSHINTERVAL); } return (void *) 0; }
/* * Print the queued messages. */ void message_flush(void) { /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Flush when needed */ if (message_column) { /* Print pending messages */ msg_flush(message_column); /* Forget it */ msg_flag = FALSE; /* Reset */ message_column = 0; } }
/** * Print the queued messages. */ void message_flush(game_event_type unused, game_event_data *data, void *user) { /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Flush when needed */ if (message_column) { /* Print pending messages */ if (Term) msg_flush(message_column); /* Forget it */ msg_flag = false; /* Reset */ message_column = 0; } }
/* * Output a message to the top line of the screen. * * Break long messages into multiple pieces (40-72 chars). * * Allow multiple short messages to "share" the top line. * * Prompt the user to make sure he has a chance to read them. * * These messages are memorized for later reference (see above). * * We could do a "Term_fresh()" to provide "flicker" if needed. * * The global "msg_flag" variable can be cleared to tell us to "erase" any * "pending" messages still on the screen, instead of using "msg_flush()". * This should only be done when the user is known to have read the message. * * We must be very careful about using the "msg("%s", )" functions without * explicitly calling the special "msg("%s", NULL)" function, since this may * result in the loss of information if the screen is cleared, or if anything * is displayed on the top line. * * Hack -- Note that "msg("%s", NULL)" will clear the top line even if no * messages are pending. */ static void msg_print_aux(u16b type, const char *msg) { int n; char *t; char buf[1024]; byte color; int w, h; if (!Term) return; /* Obtain the size */ (void)Term_get_size(&w, &h); /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Message Length */ n = (msg ? strlen(msg) : 0); /* Hack -- flush when requested or needed */ if (message_column && (!msg || ((message_column + n) > (w - 8)))) { /* Flush */ msg_flush(message_column); /* Forget it */ msg_flag = FALSE; /* Reset */ message_column = 0; } /* No message */ if (!msg) return; /* Paranoia */ if (n > 1000) return; /* Memorize the message (if legal) */ if (character_generated && !(p_ptr->is_dead)) message_add(msg, type); /* Window stuff */ p_ptr->redraw |= (PR_MESSAGE); /* Copy it */ my_strcpy(buf, msg, sizeof(buf)); /* Analyze the buffer */ t = buf; /* Get the color of the message */ color = message_type_color(type); /* Split message */ while (n > w - 1) { char oops; int check, split; /* Default split */ split = w - 8; /* Find the rightmost split point */ for (check = (w / 2); check < w - 8; check++) if (t[check] == ' ') split = check; /* Save the split character */ oops = t[split]; /* Split the message */ t[split] = '\0'; /* Display part of the message */ Term_putstr(0, 0, split, color, t); /* Flush it */ msg_flush(split + 1); /* Restore the split character */ t[split] = oops; /* Insert a space */ t[--split] = ' '; /* Prepare to recurse on the rest of "buf" */ t += split; n -= split; } /* Display the tail of the message */ Term_putstr(message_column, 0, n, color, t); /* Remember the message */ msg_flag = TRUE; /* Remember the position */ message_column += n + 1; /* Send refresh event */ event_signal(EVENT_MESSAGE); }
void exread( int sockfd ) { void* ptr; conn_data_t* conn_data = connections[ sockfd ]; if ( !conn_data->buffer ) { conn_data->buffer = malloc(PACK_DATA_SIZE); conn_data->bufferlen = 0; memset( conn_data->buffer, 0, PACK_DATA_SIZE ); } website_t* website; ssize_t len = zs_read( sockfd, conn_data->buffer + conn_data->bufferlen, PACK_DATA_SIZE - conn_data->bufferlen ); // TODO: wait for entire header before looking up website if ( len <= 0 ) { cleanup: // cleanup cleanup_connection( sockfd ); return; } if ( conn_data->postlen == -1 ) /* if we have received all the data already, ignore */ return; conn_data->bufferlen += len; //printf( "%d: read %zu\n", sockfd, len ); ptr = conn_data->buffer; if ( conn_data->website_sockfd == -1 ) { /* If req_info is NULL this is the start of a request and the HTTP request headers need to be parsed. */ struct hostent* hp; hp = NULL;//gethostbyaddr( (char*) &conn_data->addr, sizeof( conn_data->addr ), AF_INET ); char* endofhdrs; if ( !( endofhdrs = strnstr( conn_data->buffer, HTTP_HDR_ENDL HTTP_HDR_ENDL, PACK_DATA_SIZE ) ) ) { if ( conn_data->bufferlen == PACK_DATA_SIZE ) { /* If the end of the headers was not found the request was either malformatted or too long, DO NOT send to website. */ zs_write( sockfd, html_error_414, sizeof( html_error_414 ) ); syslog( LOG_WARNING, "exread: headers to long" ); goto cleanup; } // Have not received the full header yet, wait zs_set_read( sockfd ); return; } endofhdrs += sizeof( HTTP_HDR_ENDL HTTP_HDR_ENDL ) - 1; /* Get HTTP request type */ if ( startswith( conn_data->buffer, HTTP_GET ) ) conn_data->request_type = HTTP_GET_TYPE; else if ( startswith( conn_data->buffer, HTTP_POST ) ) conn_data->request_type = HTTP_POST_TYPE; else { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } /* Find website for request from HTTP header */ char urlbuf[ PACK_DATA_SIZE ]; if ( !get_url_from_http_header( conn_data->buffer, urlbuf, sizeof( urlbuf ) ) ) { //syslog( LOG_WARNING, "exread: no url found in http request headers: %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "" ); zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } if ( !( website = website_find( urlbuf, conn_data->is_https ? "https://" : "http://", inet_ntoa( zs_get_addr( conn_data->exlisnfd )->sin_addr ) ) ) ) { //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf ); zs_write( sockfd, html_error_404, sizeof( html_error_404 ) ); goto cleanup; } /* Set the website id so that furthur sections of this request can check if the website is still alive. */ conn_data->website_sockfd = website->sockfd; /* Check the websites socket to make sure the request came in on the right socket. */ website_data_t* website_data = website->udata; if ( website_data->exlisnfd != conn_data->exlisnfd ) { //syslog( LOG_WARNING, "exread: no website to service request: %s %s %s", // inet_ntoa( conn_data->addr.sin_addr ), hp ? hp->h_name : "", urlbuf ); zs_write( sockfd, html_error_404, sizeof( html_error_404 ) ); goto cleanup; } //printf( "%s\n", buffer ); /* Create a new message to send the request to the corresponding website. The msgid should be set to the external file descriptor to send the response back to. */ conn_data->msgid = msg_open( website->sockfd, sockfd ); zs_set_write( sockfd ); // If request_type is POST check if there is content after the HTTP header char postlenbuf[ 32 ]; memset( postlenbuf, 0, sizeof( postlenbuf ) ); if ( conn_data->request_type == HTTP_POST_TYPE && ( ptr = strnstr( conn_data->buffer, "Content-Length: ", PACK_DATA_SIZE ) ) ) { char* tmp = strnstr( ptr + 16, HTTP_HDR_ENDL, PACK_DATA_SIZE - ( (long)ptr + 16 - (long)conn_data->buffer ) ); if ( !tmp ) { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } memcpy( postlenbuf, ptr + 16, (long) tmp - (long) ( ptr + 16 ) ); conn_data->postlen = strtoumax( postlenbuf, NULL, 0 ); if ( conn_data->postlen < 0 ) { zs_write( sockfd, html_error_400, sizeof( html_error_400 ) ); goto cleanup; } } // Write the message length size_t msglen = ( endofhdrs - conn_data->buffer ) + conn_data->postlen + sizeof( conn_data->addr.sin_addr ) + 1; if ( hp ) msglen += strlen( hp->h_name ); if ( msg_write( website->sockfd, conn_data->msgid, (void*) &msglen, sizeof( size_t ) ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } // Write the ip address and hostname of the request if ( msg_write( website->sockfd, conn_data->msgid, (void*) &conn_data->addr.sin_addr, sizeof( conn_data->addr.sin_addr ) ) == -1 || ( hp && msg_write( website->sockfd, conn_data->msgid, (void*) hp->h_name, strlen( hp->h_name ) ) == -1 ) || msg_write( website->sockfd, conn_data->msgid, (void*) "\0", 1 ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } // Send the whole header to the website if ( msg_write( website->sockfd, conn_data->msgid, (void*) conn_data->buffer, ( endofhdrs - conn_data->buffer ) ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } ptr = endofhdrs; } else { if ( !( website = website_get_by_sockfd( conn_data->website_sockfd ) ) ) { // syslog( LOG_WARNING, "exread: no website to service request" ); zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } } if ( conn_data->request_type == HTTP_POST_TYPE && conn_data->postlen ) { int left = conn_data->bufferlen - ( ptr - (void*)conn_data->buffer ); if ( left > conn_data->postlen ) conn_data->postlen = left; if ( msg_write( website->sockfd, conn_data->msgid, (void*) ptr, left ) == -1 ) { zs_write( sockfd, html_error_502, sizeof( html_error_502 ) ); goto cleanup; } conn_data->postlen -= left; } if ( !conn_data->postlen ) { /* If there isn't more data coming, */ msg_flush( website->sockfd, conn_data->msgid ); /* must make sure to keep sockfd in read mode to detect a connection close from the other end */ conn_data->postlen = -1; zs_set_read( sockfd ); } else msg_set_write( website->sockfd, conn_data->msgid ); free( conn_data->buffer ); conn_data->buffer = NULL; //printf( "%d: still needs %d post data\n", sockfd, conn_data->postlen ); }
/** * Output a message to the top line of the screen. * * Break long messages into multiple pieces (40-72 chars). * * Allow multiple short messages to "share" the top line. * * Prompt the user to make sure he has a chance to read them. * * These messages are memorized for later reference (see above). * * We could do a "Term_fresh()" to provide "flicker" if needed. * * The global "msg_flag" variable can be cleared to tell us to "erase" any * "pending" messages still on the screen, instead of using "msg_flush()". * This should only be done when the user is known to have read the message. * * We must be very careful about using the "msg("%s", )" functions without * explicitly calling the special "msg("%s", NULL)" function, since this may * result in the loss of information if the screen is cleared, or if anything * is displayed on the top line. * * Hack -- Note that "msg("%s", NULL)" will clear the top line even if no * messages are pending. */ void display_message(game_event_type unused, game_event_data *data, void *user) { int n; char *t; char buf[1024]; byte color; int w, h; int type; const char *msg; if (!data) return; type = data->message.type; msg = data->message.msg; if (type == MSG_BELL || !msg || !Term || !character_generated) return; /* Obtain the size */ (void)Term_get_size(&w, &h); /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Message Length */ n = (msg ? strlen(msg) : 0); /* Hack -- flush when requested or needed */ if (message_column && (!msg || ((message_column + n) > (w - 8)))) { /* Flush */ msg_flush(message_column); /* Forget it */ msg_flag = false; /* Reset */ message_column = 0; } /* No message */ if (!msg) return; /* Paranoia */ if (n > 1000) return; /* Copy it */ my_strcpy(buf, msg, sizeof(buf)); /* Analyze the buffer */ t = buf; /* Get the color of the message */ color = message_type_color(type); /* Split message */ while (n > w - 1) { char oops; int check, split; /* Default split */ split = w - 8; /* Find the rightmost split point */ for (check = (w / 2); check < w - 8; check++) if (t[check] == ' ') split = check; /* Save the split character */ oops = t[split]; /* Split the message */ t[split] = '\0'; /* Display part of the message */ Term_putstr(0, 0, split, color, t); /* Flush it */ msg_flush(split + 1); /* Restore the split character */ t[split] = oops; /* Insert a space */ t[--split] = ' '; /* Prepare to recurse on the rest of "buf" */ t += split; n -= split; } /* Display the tail of the message */ Term_putstr(message_column, 0, n, color, t); /* Remember the message */ msg_flag = true; /* Remember the position */ message_column += n + 1; }