/************************************************************************** write wrapper function -vasc **************************************************************************/ static int write_socket_data(struct connection *pc, struct socket_packet_buffer *buf, int limit) { int start, nput, nblock; if (is_server() && pc->server.is_closing) { return 0; } for (start=0; buf->ndata-start>limit;) { fd_set writefs, exceptfs; struct timeval tv; FC_FD_ZERO(&writefs); FC_FD_ZERO(&exceptfs); FD_SET(pc->sock, &writefs); FD_SET(pc->sock, &exceptfs); tv.tv_sec = 0; tv.tv_usec = 0; if (fc_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { if (errno != EINTR) { break; } else { /* EINTR can happen sometimes, especially when compiling with -pg. * Generally we just want to run select again. */ continue; } } if (FD_ISSET(pc->sock, &exceptfs)) { connection_close(pc, _("network exception")); return -1; } if (FD_ISSET(pc->sock, &writefs)) { nblock=MIN(buf->ndata-start, MAX_LEN_PACKET); log_debug("trying to write %d limit=%d", nblock, limit); if((nput=fc_writesocket(pc->sock, (const char *)buf->data+start, nblock)) == -1) { #ifdef NONBLOCKING_SOCKETS if (errno == EWOULDBLOCK || errno == EAGAIN) { break; } #endif connection_close(pc, _("lagging connection")); return -1; } start += nput; } } if (start > 0) { buf->ndata -= start; memmove(buf->data, buf->data+start, buf->ndata); pc->last_write = timer_renew(pc->last_write, TIMER_USER, TIMER_ACTIVE); timer_start(pc->last_write); } return 0; }
/**************************************************************************** Send the request string to the metaserver. ****************************************************************************/ static void meta_send_request(struct server_scan *scan) { const char *capstr; char str[MAX_LEN_PACKET]; char machine_string[128]; my_uname(machine_string, sizeof(machine_string)); capstr = fc_url_encode(our_capability); my_snprintf(str, sizeof(str), "POST %s HTTP/1.1\r\n" "Host: %s:%d\r\n" "User-Agent: Freeciv/%s %s %s\r\n" "Connection: close\r\n" "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n" "Content-Length: %lu\r\n" "\r\n" "client_cap=%s\r\n", scan->meta.urlpath, scan->meta.name, scan->meta.port, VERSION_STRING, client_string, machine_string, (unsigned long) (strlen("client_cap=") + strlen(capstr)), capstr); if (fc_writesocket(scan->sock, str, strlen(str)) != strlen(str)) { /* Even with non-blocking this shouldn't fail. */ scan->error_func(scan, fc_strerror(fc_get_errno())); return; } scan->meta.state = META_WAITING; }
/************************************************************************* Writes buf to socket and returns the response in an fz_FILE. Use only on blocking sockets. *************************************************************************/ fz_FILE *fc_querysocket(int sock, void *buf, size_t size) { FILE *fp; #ifdef HAVE_FDOPEN fp = fdopen(sock, "r+b"); if (fwrite(buf, 1, size, fp) != size) { log_error("socket %d: write error", sock); } fflush(fp); /* we don't use fc_closesocket on sock here since when fp is closed * sock will also be closed. fdopen doesn't dup the socket descriptor. */ #else /* HAVE_FDOPEN */ { char tmp[4096]; int n; #ifdef WIN32_NATIVE /* tmpfile() in mingw attempts to make a temp file in the root directory * of the current drive, which we may not have write access to. */ { char filename[MAX_PATH]; GetTempPath(sizeof(filename), filename); sz_strlcat(filename, "fctmp"); fp = fc_fopen(filename, "w+b"); } #else /* WIN32_NATIVE */ fp = tmpfile(); #endif /* WIN32_NATIVE */ if (fp == NULL) { return NULL; } fc_writesocket(sock, buf, size); while ((n = fc_readsocket(sock, tmp, sizeof(tmp))) > 0) { if (fwrite(tmp, 1, n, fp) != n) { log_error("socket %d: write error", sock); } } fflush(fp); fc_closesocket(sock); rewind(fp); } #endif /* HAVE_FDOPEN */ return fz_from_stream(fp); }
/************************************************************************** write wrapper function -vasc **************************************************************************/ static int write_socket_data(struct connection *pc, struct socket_packet_buffer *buf, int limit) { int start, nput, nblock; if (pc->delayed_disconnect) { if (delayed_disconnect > 0) { return 0; } else { if (close_callback) { (*close_callback)(pc); } return -1; } } for (start=0; buf->ndata-start>limit;) { fd_set writefs, exceptfs; struct timeval tv; MY_FD_ZERO(&writefs); MY_FD_ZERO(&exceptfs); FD_SET(pc->sock, &writefs); FD_SET(pc->sock, &exceptfs); tv.tv_sec = 0; tv.tv_usec = 0; if (fc_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { if (errno != EINTR) { break; } else { /* EINTR can happen sometimes, especially when compiling with -pg. * Generally we just want to run select again. */ continue; } } if (FD_ISSET(pc->sock, &exceptfs)) { if (delayed_disconnect > 0) { pc->delayed_disconnect = TRUE; return 0; } else { if (close_callback) { (*close_callback)(pc); } return -1; } } if (FD_ISSET(pc->sock, &writefs)) { nblock=MIN(buf->ndata-start, MAX_LEN_PACKET); freelog(LOG_DEBUG,"trying to write %d limit=%d",nblock,limit); if((nput=fc_writesocket(pc->sock, (const char *)buf->data+start, nblock)) == -1) { #ifdef NONBLOCKING_SOCKETS if (errno == EWOULDBLOCK || errno == EAGAIN) { break; } #endif if (delayed_disconnect > 0) { pc->delayed_disconnect = TRUE; return 0; } else { if (close_callback) { (*close_callback)(pc); } return -1; } } start += nput; } } if (start > 0) { buf->ndata -= start; memmove(buf->data, buf->data+start, buf->ndata); pc->last_write = renew_timer_start(pc->last_write, TIMER_USER, TIMER_ACTIVE); } return 0; }